diff --git a/native/mlir-zig-proj/src/enif_support.zig b/native/mlir-zig-proj/src/enif_support.zig index 4b1be601..2adc069f 100644 --- a/native/mlir-zig-proj/src/enif_support.zig +++ b/native/mlir-zig-proj/src/enif_support.zig @@ -2,11 +2,13 @@ const beam = @import("beam"); const mlir_capi = @import("mlir_capi.zig"); pub const c = @import("prelude.zig"); const e = @import("runtime.zig"); +const result = @import("result.zig"); + const Invocation = struct { arg_terms: []beam.term = undefined, res_term: beam.term = undefined, packed_args: []?*anyopaque = undefined, // [arg0, arg1... result] - pub fn init(self: *@This(), environment: beam.env, list: beam.term) !void { + fn init(self: *@This(), environment: beam.env, list: beam.term) !void { const size = try beam.get_list_length(environment, list); var head: beam.term = undefined; self.arg_terms = try beam.allocator.alloc(beam.term, size); @@ -21,26 +23,25 @@ const Invocation = struct { errdefer beam.allocator.free(self.arg_terms); errdefer beam.allocator.free(self.packed_args); } - pub fn deinit(self: *@This()) void { + fn deinit(self: *@This()) void { beam.allocator.free(self.arg_terms); beam.allocator.free(self.packed_args); } - pub fn invoke(self: *@This(), environment: beam.env, jit: mlir_capi.ExecutionEngine.T, name: beam.binary) callconv(.C) mlir_capi.LogicalResult.T { + fn invoke(self: *@This(), environment: beam.env, jit: mlir_capi.ExecutionEngine.T, name: beam.binary) callconv(.C) mlir_capi.LogicalResult.T { self.packed_args[0] = @ptrCast(@constCast(&environment)); return c.mlirExecutionEngineInvokePacked(jit, c.mlirStringRefCreate(name.data, name.size), &self.packed_args[0]); } }; -pub fn beaver_raw_jit_invoke_with_terms(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - var jit: mlir_capi.ExecutionEngine.T = mlir_capi.ExecutionEngine.resource.fetch(env, args[0]) catch - return beam.make_error_binary(env, "fail to fetch resource for ExecutionEngine, expected: " ++ @typeName(mlir_capi.ExecutionEngine.T)); - var name: beam.binary = beam.get_binary(env, args[1]) catch - return beam.make_error_binary(env, "fail to get binary for jit func name"); +fn beaver_raw_jit_invoke_with_terms(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + const Error = error{JITFunctionCallFailure}; + var jit: mlir_capi.ExecutionEngine.T = try mlir_capi.ExecutionEngine.resource.fetch(env, args[0]); + var name: beam.binary = try beam.get_binary(env, args[1]); var invocation = Invocation{}; - invocation.init(env, args[2]) catch return beam.make_error_binary(env, "fail to init jit invocation"); + try invocation.init(env, args[2]); defer invocation.deinit(); if (c.beaverLogicalResultIsFailure(invocation.invoke(env, jit, name))) { - return beam.make_error_binary(env, "fail to call jit function"); + return Error.JITFunctionCallFailure; } return invocation.res_term; } @@ -56,9 +57,8 @@ fn register_jit_symbol(jit: mlir_capi.ExecutionEngine.T, comptime name: []const c.mlirExecutionEngineRegisterSymbol(jit, name_str_ref, @ptrCast(@constCast(&f))); } -pub fn beaver_raw_jit_register_enif(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - var jit: mlir_capi.ExecutionEngine.T = mlir_capi.ExecutionEngine.resource.fetch(env, args[0]) catch - return beam.make_error_binary(env, "fail to fetch resource for ExecutionEngine, expected: " ++ @typeName(mlir_capi.ExecutionEngine.T)); +fn beaver_raw_jit_register_enif(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + var jit = try mlir_capi.ExecutionEngine.resource.fetch(env, args[0]); inline for (enif_function_names) |name| { register_jit_symbol(jit, name, @field(e, name)); } @@ -122,26 +122,21 @@ fn dump_type_info(env: beam.env, ctx: mlir_capi.Context.T, comptime t: type) !be return beam.make_tuple(env, type_info_slice); } -pub fn beaver_raw_enif_signatures(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - const ctx = mlir_capi.Context.resource.fetch(env, args[0]) catch - return beam.make_error_binary(env, "fail to fetch resource for argument #0, expected: " ++ @typeName(mlir_capi.Context.T)); - var signatures: []beam.term = beam.allocator.alloc(beam.term, enif_function_names.len) catch - return beam.make_error_binary(env, "fail to allocate"); +fn beaver_raw_enif_signatures(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + const ctx = try mlir_capi.Context.resource.fetch(env, args[0]); + var signatures: []beam.term = try beam.allocator.alloc(beam.term, enif_function_names.len); inline for (enif_function_names, 0..) |name, i| { const f = @field(e, name); const FTI = @typeInfo(@TypeOf(f)).Fn; - var signature_slice: []beam.term = beam.allocator.alloc(beam.term, 3) catch - return beam.make_error_binary(env, "fail to allocate"); + var signature_slice: []beam.term = try beam.allocator.alloc(beam.term, 3); defer beam.allocator.free(signature_slice); - var arg_type_slice: []beam.term = beam.allocator.alloc(beam.term, FTI.params.len) catch - return beam.make_error_binary(env, "fail to allocate"); + var arg_type_slice: []beam.term = try beam.allocator.alloc(beam.term, FTI.params.len); defer beam.allocator.free(arg_type_slice); inline for (FTI.params, 0..) |p, arg_i| { if (p.type) |t| { - arg_type_slice[arg_i] = dump_type_info(env, ctx, t) catch - return beam.make_error_binary(env, "fail to allocate"); + arg_type_slice[arg_i] = try dump_type_info(env, ctx, t); } else if (@TypeOf(f) == @TypeOf(e.enif_compare_pids)) { - arg_type_slice[arg_i] = dump_type_info(env, ctx, [*c]u8) catch return beam.make_error_binary(env, "fail to dump type"); + arg_type_slice[arg_i] = try dump_type_info(env, ctx, [*c]u8); } else { @compileError("param type not found, function: " ++ name); } @@ -155,15 +150,14 @@ pub fn beaver_raw_enif_signatures(env: beam.env, _: c_int, args: [*c]const beam. ret_size = 0; } } - var ret_slice: []beam.term = beam.allocator.alloc(beam.term, ret_size) catch - return beam.make_error_binary(env, "fail to allocate"); + var ret_slice: []beam.term = try beam.allocator.alloc(beam.term, ret_size); defer beam.allocator.free(ret_slice); if (FTI.return_type) |t| { if (t != void) { - ret_slice[0] = dump_type_info(env, ctx, t) catch return beam.make_error_binary(env, "fail to dump type"); + ret_slice[0] = try dump_type_info(env, ctx, t); } } else if (f == e.enif_compare_pids) { - ret_slice[0] = dump_type_info(env, ctx, c_int) catch return beam.make_error_binary(env, "fail to dump type"); + ret_slice[0] = try dump_type_info(env, ctx, c_int); } else { @compileError("return type not found, function: " ++ name); } @@ -173,25 +167,31 @@ pub fn beaver_raw_enif_signatures(env: beam.env, _: c_int, args: [*c]const beam. return beam.make_term_list(env, signatures); } -pub fn beaver_raw_enif_functions(env: beam.env, _: c_int, _: [*c]const beam.term) callconv(.C) beam.term { - var names: []beam.term = beam.allocator.alloc(beam.term, enif_function_names.len) catch - return beam.make_error_binary(env, "fail to allocate"); +fn beaver_raw_enif_functions(env: beam.env, _: c_int, _: [*c]const beam.term) !beam.term { + var names: []beam.term = try beam.allocator.alloc(beam.term, enif_function_names.len); inline for (enif_function_names, 0..) |name, i| { names[i] = beam.make_atom(env, name); } return beam.make_term_list(env, names); } -pub fn beaver_raw_mlir_type_of_enif_obj(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - const ctx = mlir_capi.Context.resource.fetch(env, args[0]) catch - return beam.make_error_binary(env, "fail to fetch resource for argument #0, expected: " ++ @typeName(mlir_capi.Context.T)); - var name = beam.get_atom_slice(env, args[1]) catch - return beam.make_error_binary(env, "fail to get name"); +fn beaver_raw_mlir_type_of_enif_obj(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + const Error = error{MLIRTypeForEnifObjNotFound}; + const ctx = try mlir_capi.Context.resource.fetch(env, args[0]); + var name = try beam.get_atom_slice(env, args[1]); inline for (.{ "term", "env" }) |obj| { if (@import("std").mem.eql(u8, name, obj)) { const t = @field(beam, obj); - return enif_mlir_type(env, ctx, t) catch return beam.make_error_binary(env, "fail to get mlir type"); + return try enif_mlir_type(env, ctx, t); } } - return beam.make_error_binary(env, "mlir type not found for enif obj"); + return Error.MLIRTypeForEnifObjNotFound; } + +pub const nifs = .{ + result.nif("beaver_raw_jit_invoke_with_terms", 3, beaver_raw_jit_invoke_with_terms).entry, + result.nif("beaver_raw_jit_register_enif", 1, beaver_raw_jit_register_enif).entry, + result.nif("beaver_raw_enif_signatures", 1, beaver_raw_enif_signatures).entry, + result.nif("beaver_raw_enif_functions", 0, beaver_raw_enif_functions).entry, + result.nif("beaver_raw_mlir_type_of_enif_obj", 2, beaver_raw_mlir_type_of_enif_obj).entry, +}; diff --git a/native/mlir-zig-proj/src/main.zig b/native/mlir-zig-proj/src/main.zig index 7d1a6635..02a9fd22 100644 --- a/native/mlir-zig-proj/src/main.zig +++ b/native/mlir-zig-proj/src/main.zig @@ -13,354 +13,20 @@ const registry = @import("registry.zig"); const pointer = @import("pointer.zig"); const string_ref = @import("string_ref.zig"); const Printer = string_ref.Printer; +const memref = @import("memref.zig"); -fn MemRefDescriptorAccessor(comptime MemRefT: type) type { - return struct { - fn allocated_ptr(env: beam.env, term: beam.term) callconv(.C) beam.term { - var descriptor: MemRefT = beam.fetch_resource(MemRefT, env, MemRefT.resource_type, term) catch - return beam.make_error_binary(env, "fail to fetch resource for descriptor, expected: " ++ @typeName(MemRefT)); - var ret: mlir_capi.OpaquePtr.T = @ptrCast(descriptor.allocated); - return mlir_capi.OpaquePtr.resource.make(env, ret) catch return beam.make_error_binary(env, "fail to make allocated ptr"); - } - fn aligned_ptr(env: beam.env, term: beam.term) callconv(.C) beam.term { - var descriptor: MemRefT = beam.fetch_resource(MemRefT, env, MemRefT.resource_type, term) catch - return beam.make_error_binary(env, "fail to fetch resource for descriptor, expected: " ++ @typeName(MemRefT)); - var ret: mlir_capi.OpaquePtr.T = @ptrCast(descriptor.aligned); - return mlir_capi.OpaquePtr.resource.make(env, ret) catch return beam.make_error_binary(env, "fail to make aligned ptr"); - } - fn fetch_ptr_or_nil(env: beam.env, ptr_term: beam.term) !MemRefT.ElementResourceKind.Ptr.T { - if (MemRefT.ElementResourceKind.Ptr.resource.fetch(env, ptr_term)) |value| { - return value; - } else |err| { - if (try beam.is_nil(env, ptr_term)) { - return null; - } else { - return err; - } - } - } - fn offset(env: beam.env, term: beam.term) callconv(.C) beam.term { - var descriptor: MemRefT = beam.fetch_resource(MemRefT, env, MemRefT.resource_type, term) catch - return beam.make_error_binary(env, "fail to fetch resource for descriptor, expected: " ++ @typeName(MemRefT)); - return beam.make_i64(env, descriptor.offset); - } - }; -} - -fn memref_module_name(comptime resource_kind: type, comptime rank: i32) []const u8 { - return resource_kind.module_name ++ ".MemRef." ++ @tagName(@as(MemRefRankType, @enumFromInt(rank))); -} - -fn UnrankMemRefDescriptor(comptime ResourceKind: type) type { - return extern struct { - pub fn make(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - var allocated: ResourceKind.Ptr.T = MemRefDescriptorAccessor(@This()).fetch_ptr_or_nil(env, args[0]) catch - return beam.make_error_binary(env, "fail to fetch allocated. expected: " ++ @typeName(ResourceKind.Ptr.T)); - var aligned: ResourceKind.Ptr.T = MemRefDescriptorAccessor(@This()).fetch_ptr_or_nil(env, args[1]) catch - return beam.make_error_binary(env, "fail to fetch aligned. expected: " ++ @typeName(ResourceKind.Ptr.T)); - var offset: mlir_capi.I64.T = mlir_capi.I64.resource.fetch(env, args[2]) catch - return beam.make_error_binary(env, "fail to fetch offset"); - const kind: type = dataKindToMemrefKind(ResourceKind); - var descriptor: UnrankMemRefDescriptor(ResourceKind) = undefined; - if (allocated == null) { - descriptor = .{ - .offset = offset, - }; - } else { - descriptor = .{ - .allocated = allocated, - .aligned = aligned, - .offset = offset, - }; - } - return kind.per_rank_resource_kinds[0].resource.make(env, descriptor) catch return beam.make_error_binary(env, "fail to make unranked memref descriptor"); - } - pub const maker = .{ make, 5 }; - pub const module_name = memref_module_name(ResourceKind, 0); - const ElementResourceKind = ResourceKind; - const T = ResourceKind.T; - allocated: ?*T = null, - aligned: ?*T = null, - offset: i64 = undefined, - pub var resource_type: beam.resource_type = undefined; - fn allocated_ptr(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - return MemRefDescriptorAccessor(@This()).allocated_ptr(env, args[0]); - } - fn aligned_ptr(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - return MemRefDescriptorAccessor(@This()).aligned_ptr(env, args[0]); - } - fn get_offset(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - return MemRefDescriptorAccessor(@This()).offset(env, args[0]); - } - pub const nifs = .{ e.ErlNifFunc{ .name = module_name ++ ".allocated", .arity = 1, .fptr = allocated_ptr, .flags = 1 }, e.ErlNifFunc{ .name = module_name ++ ".aligned", .arity = 1, .fptr = aligned_ptr, .flags = 1 }, e.ErlNifFunc{ .name = module_name ++ ".offset", .arity = 1, .fptr = get_offset, .flags = 1 } }; - }; -} - -fn MemRefDescriptor(comptime ResourceKind: type, comptime N: usize) type { - return extern struct { - const T = ResourceKind.T; - allocated: ?*T = null, - aligned: ?*T = null, - offset: i64 = undefined, - sizes: [N]i64 = undefined, - strides: [N]i64 = undefined, - fn populate(self: *@This(), allocated: *T, aligned: *T, offset: i64, sizes: []i64, strides: []i64) void { - self.allocated = allocated; - self.aligned = aligned; - self.offset = offset; - const rank = sizes.len; - mem.copy(i64, self.sizes[0..rank], sizes[0..rank]); - mem.copy(i64, self.strides[0..rank], strides[0..rank]); - } - fn populate2(self: *@This(), offset: i64, sizes: []i64, strides: []i64) void { - self.offset = offset; - const rank = sizes.len; - mem.copy(i64, self.sizes[0..rank], sizes[0..rank]); - mem.copy(i64, self.strides[0..rank], strides[0..rank]); - } - pub fn make(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - var allocated: ResourceKind.Ptr.T = MemRefDescriptorAccessor(@This()).fetch_ptr_or_nil(env, args[0]) catch - return beam.make_error_binary(env, "fail to fetch allocated. expected: " ++ @typeName(ResourceKind.Ptr.T)); - var aligned: ResourceKind.Ptr.T = MemRefDescriptorAccessor(@This()).fetch_ptr_or_nil(env, args[1]) catch - return beam.make_error_binary(env, "fail to fetch aligned. expected: " ++ @typeName(ResourceKind.Ptr.T)); - var offset: mlir_capi.I64.T = mlir_capi.I64.resource.fetch(env, args[2]) catch - return beam.make_error_binary(env, "fail to fetch offset"); - const sizes = beam.get_slice_of(i64, env, args[3]) catch return beam.make_error_binary(env, "fail to get sizes as zig slice"); - defer beam.allocator.free(sizes); - const strides = beam.get_slice_of(i64, env, args[4]) catch return beam.make_error_binary(env, "fail to get sizes as zig slice"); - defer beam.allocator.free(strides); - if (sizes.len != strides.len) { - return beam.make_error_binary(env, "sizes and strides must have the same length"); - } - const kind: type = dataKindToMemrefKind(ResourceKind); - comptime var rank = N; - if (rank != sizes.len) { - return beam.make_error_binary(env, "wrong sizes for " ++ @typeName(@This())); - } - if (rank != strides.len) { - return beam.make_error_binary(env, "wrong strides for " ++ @typeName(@This())); - } - var descriptor: MemRefDescriptor(ResourceKind, rank) = .{}; - if (allocated == null) { - descriptor.populate2(offset, sizes, strides); - } else { - descriptor.populate(allocated, aligned, offset, sizes, strides); - } - return kind.per_rank_resource_kinds[rank].resource.make(env, descriptor) catch return beam.make_error_binary(env, "fail to make memref descriptor"); - } - pub const maker = .{ make, 5 }; - pub const ElementResourceKind = ResourceKind; - pub const module_name = memref_module_name(ResourceKind, N); - pub var resource_type: beam.resource_type = undefined; - fn allocated_ptr(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - return MemRefDescriptorAccessor(@This()).allocated_ptr(env, args[0]); - } - fn aligned_ptr(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - return MemRefDescriptorAccessor(@This()).aligned_ptr(env, args[0]); - } - fn get_offset(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - return MemRefDescriptorAccessor(@This()).offset(env, args[0]); - } - fn get_sizes(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - comptime var rank = N; - var descriptor: @This() = beam.fetch_resource(@This(), env, @This().resource_type, args[0]) catch - return beam.make_error_binary(env, "fail to fetch resource for descriptor, expected: " ++ @typeName(@This())); - var ret: []beam.term = beam.allocator.alloc(beam.term, @intCast(rank)) catch - return beam.make_error_binary(env, "fail to allocate"); - defer beam.allocator.free(ret); - var i: usize = 0; - while (i < rank) : ({ - i += 1; - }) { - ret[@intCast(i)] = beam.make_i64(env, descriptor.sizes[i]); - } - return beam.make_term_list(env, ret); - } - fn get_strides(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - comptime var rank = N; - var descriptor: @This() = beam.fetch_resource(@This(), env, @This().resource_type, args[0]) catch - return beam.make_error_binary(env, "fail to fetch resource for descriptor, expected: " ++ @typeName(@This())); - var ret: []beam.term = beam.allocator.alloc(beam.term, @intCast(rank)) catch - return beam.make_error_binary(env, "fail to allocate"); - defer beam.allocator.free(ret); - var i: usize = 0; - while (i < rank) : ({ - i += 1; - }) { - ret[@intCast(i)] = beam.make_i64(env, descriptor.strides[i]); - } - return beam.make_term_list(env, ret); - } - pub const nifs = .{ e.ErlNifFunc{ .name = module_name ++ ".allocated", .arity = 1, .fptr = allocated_ptr, .flags = 1 }, e.ErlNifFunc{ .name = module_name ++ ".aligned", .arity = 1, .fptr = aligned_ptr, .flags = 1 }, e.ErlNifFunc{ .name = module_name ++ ".offset", .arity = 1, .fptr = get_offset, .flags = 1 }, e.ErlNifFunc{ .name = module_name ++ ".sizes", .arity = 1, .fptr = get_sizes, .flags = 1 }, e.ErlNifFunc{ .name = module_name ++ ".strides", .arity = 1, .fptr = get_strides, .flags = 1 } }; - }; -} - -const Complex = struct { - fn of(comptime ElementKind: type) type { - return struct { - const T = extern struct { - i: ElementKind.T, - r: ElementKind.T, - }; - }; - } - const F32 = kinda.ResourceKind(Complex.of(mlir_capi.F32).T, "Elixir.Beaver.Native.Complex.F32"); -}; - -const MemRefDataType = enum { - @"Complex.F32", - U8, - U16, - U32, - F32, - F64, - I8, - I16, - I32, - I64, -}; - -fn dataTypeToResourceKind(comptime self: MemRefDataType) type { - return switch (self) { - .@"Complex.F32" => Complex.F32, - .U8 => mlir_capi.U8, - .U16 => mlir_capi.U16, - .U32 => mlir_capi.U32, - .F32 => mlir_capi.F32, - .F64 => mlir_capi.F64, - .I8 => mlir_capi.I8, - .I16 => mlir_capi.I16, - .I32 => mlir_capi.I32, - .I64 => mlir_capi.I64, - }; -} - -fn dataKindToDataType(comptime self: type) MemRefDataType { - return switch (self) { - Complex.F32 => MemRefDataType.@"Complex.F32", - mlir_capi.U8 => MemRefDataType.U8, - mlir_capi.U16 => MemRefDataType.U16, - mlir_capi.U32 => MemRefDataType.U32, - mlir_capi.F32 => MemRefDataType.F32, - mlir_capi.F64 => MemRefDataType.F64, - mlir_capi.I8 => MemRefDataType.I8, - mlir_capi.I16 => MemRefDataType.I16, - mlir_capi.I32 => MemRefDataType.I32, - mlir_capi.I64 => MemRefDataType.I64, - else => unreachable(), - }; -} - -const memref_kinds = .{ - BeaverMemRef(dataTypeToResourceKind(MemRefDataType.@"Complex.F32")), - BeaverMemRef(dataTypeToResourceKind(MemRefDataType.U8)), - BeaverMemRef(dataTypeToResourceKind(MemRefDataType.U16)), - BeaverMemRef(dataTypeToResourceKind(MemRefDataType.U32)), - BeaverMemRef(dataTypeToResourceKind(MemRefDataType.F32)), - BeaverMemRef(dataTypeToResourceKind(MemRefDataType.F64)), - BeaverMemRef(dataTypeToResourceKind(MemRefDataType.I8)), - BeaverMemRef(dataTypeToResourceKind(MemRefDataType.I16)), - BeaverMemRef(dataTypeToResourceKind(MemRefDataType.I32)), - BeaverMemRef(dataTypeToResourceKind(MemRefDataType.I64)), -}; - -fn dataKindToMemrefKind(comptime self: type) type { - const dt = dataKindToDataType(self); - const index = @intFromEnum(dt); - return memref_kinds[index]; -} - -const MemRefRankType = enum { - DescriptorUnranked, - Descriptor1D, - Descriptor2D, - Descriptor3D, - Descriptor4D, - Descriptor5D, - Descriptor6D, - Descriptor7D, - Descriptor8D, - Descriptor9D, -}; - -fn BeaverMemRef(comptime ResourceKind: type) type { - return struct { - const data_kind_name = ResourceKind.module_name; - pub const nifs = - per_rank_resource_kinds[0].nifs ++ - per_rank_resource_kinds[1].nifs ++ - per_rank_resource_kinds[2].nifs ++ - per_rank_resource_kinds[3].nifs ++ - per_rank_resource_kinds[4].nifs ++ - per_rank_resource_kinds[5].nifs; - fn MemRefOfRank(comptime rank: u8) type { - if (rank == 0) { - return kinda.ResourceKind2(UnrankMemRefDescriptor(ResourceKind)); - } else { - return kinda.ResourceKind2(MemRefDescriptor(ResourceKind, rank)); - } - } - const per_rank_resource_kinds = .{ - MemRefOfRank(0), - MemRefOfRank(1), - MemRefOfRank(2), - MemRefOfRank(3), - MemRefOfRank(4), - MemRefOfRank(5), - }; - fn open(env: beam.env) void { - comptime var i = 0; - inline while (i < per_rank_resource_kinds.len) : (i += 1) { - per_rank_resource_kinds[i].open_all(env); - } - } - }; -} - -const handwritten_nifs = @import("wrapper.zig").nif_entries ++ mlir_capi.EntriesOfKinds ++ pass.nifs ++ registry.nifs ++ string_ref.nifs ++ diagnostic.nifs ++ pointer.nifs ++ .{ - e.ErlNifFunc{ .name = "beaver_raw_to_string_attribute", .arity = 1, .fptr = Printer(mlir_capi.Attribute, c.mlirAttributePrint).to_string, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_to_string_type", .arity = 1, .fptr = Printer(mlir_capi.Type, c.mlirTypePrint).to_string, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_to_string_operation", .arity = 1, .fptr = Printer(mlir_capi.Operation, c.mlirOperationPrint).to_string, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_to_string_operation_specialized", .arity = 1, .fptr = Printer(mlir_capi.Operation, c.beaverOperationPrintSpecializedFrom).to_string, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_to_string_operation_generic", .arity = 1, .fptr = Printer(mlir_capi.Operation, c.beaverOperationPrintGenericOpForm).to_string, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_to_string_operation_bytecode", .arity = 1, .fptr = Printer(mlir_capi.Operation, c.mlirOperationWriteBytecode).to_string, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_to_string_value", .arity = 1, .fptr = Printer(mlir_capi.Value, c.mlirValuePrint).to_string, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_to_string_pm", .arity = 1, .fptr = Printer(mlir_capi.OpPassManager, c.mlirPrintPassPipeline).to_string, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_to_string_affine_map", .arity = 1, .fptr = Printer(mlir_capi.AffineMap, c.mlirAffineMapPrint).to_string, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_to_string_location", .arity = 1, .fptr = Printer(mlir_capi.Location, c.beaverLocationPrint).to_string, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_jit_invoke_with_terms", .arity = 3, .fptr = enif_support.beaver_raw_jit_invoke_with_terms, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_jit_register_enif", .arity = 1, .fptr = enif_support.beaver_raw_jit_register_enif, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_enif_signatures", .arity = 1, .fptr = enif_support.beaver_raw_enif_signatures, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_enif_functions", .arity = 0, .fptr = enif_support.beaver_raw_enif_functions, .flags = 0 }, - e.ErlNifFunc{ .name = "beaver_raw_mlir_type_of_enif_obj", .arity = 2, .fptr = enif_support.beaver_raw_mlir_type_of_enif_obj, .flags = 0 }, -} ++ - pointer.PtrOwner.Kind.nifs ++ - Complex.F32.nifs ++ - dataKindToMemrefKind(Complex.F32).nifs ++ - dataKindToMemrefKind(mlir_capi.U8).nifs ++ - dataKindToMemrefKind(mlir_capi.U16).nifs ++ - dataKindToMemrefKind(mlir_capi.U32).nifs ++ - dataKindToMemrefKind(mlir_capi.F32).nifs ++ - dataKindToMemrefKind(mlir_capi.F64).nifs ++ - dataKindToMemrefKind(mlir_capi.I8).nifs ++ - dataKindToMemrefKind(mlir_capi.I16).nifs ++ - dataKindToMemrefKind(mlir_capi.I32).nifs ++ - dataKindToMemrefKind(mlir_capi.I64).nifs; +const handwritten_nifs = @import("wrapper.zig").nif_entries ++ mlir_capi.EntriesOfKinds ++ pass.nifs ++ registry.nifs ++ string_ref.nifs ++ diagnostic.nifs ++ pointer.nifs ++ memref.nifs ++ enif_support.nifs; const num_nifs = handwritten_nifs.len; export var nifs: [num_nifs]e.ErlNifFunc = handwritten_nifs; export fn nif_load(env: beam.env, _: [*c]?*anyopaque, _: beam.term) c_int { kinda.open_internal_resource_types(env); - mlir_capi.open_generated_resource_types(env); - comptime var i = 0; - inline while (i < memref_kinds.len) : (i += 1) { - memref_kinds[i].open(env); - } - Complex.F32.open_all(env); - beam.open_resource_wrapped(env, pass.Token); kinda.Internal.OpaqueStruct.open_all(env); - pointer.PtrOwner.Kind.open(env); + mlir_capi.open_all(env); + memref.open_all(env); + pointer.open_all(env); + pass.open_all(env); return 0; } diff --git a/native/mlir-zig-proj/src/memref.zig b/native/mlir-zig-proj/src/memref.zig new file mode 100644 index 00000000..f0b7fa3b --- /dev/null +++ b/native/mlir-zig-proj/src/memref.zig @@ -0,0 +1,327 @@ +const beam = @import("beam"); +const std = @import("std"); +const mem = @import("std").mem; +const mlir_capi = @import("mlir_capi.zig"); +pub const c = @import("prelude.zig"); +const e = @import("erl_nif"); +const result = @import("result.zig"); +const kinda = @import("kinda"); + +fn MemRefDescriptorAccessor(comptime MemRefT: type) type { + return struct { + fn allocated_ptr(env: beam.env, term: beam.term) !beam.term { + var descriptor: MemRefT = try beam.fetch_resource(MemRefT, env, MemRefT.resource_type, term); + return try mlir_capi.OpaquePtr.resource.make(env, @ptrCast(descriptor.allocated)); + } + fn aligned_ptr(env: beam.env, term: beam.term) !beam.term { + var descriptor: MemRefT = try beam.fetch_resource(MemRefT, env, MemRefT.resource_type, term); + return try mlir_capi.OpaquePtr.resource.make(env, @ptrCast(descriptor.aligned)); + } + fn fetch_ptr_or_nil(env: beam.env, ptr_term: beam.term) !MemRefT.ElementResourceKind.Ptr.T { + if (MemRefT.ElementResourceKind.Ptr.resource.fetch(env, ptr_term)) |value| { + return value; + } else |err| { + if (try beam.is_nil(env, ptr_term)) { + return null; + } else { + return err; + } + } + } + fn offset(env: beam.env, term: beam.term) !beam.term { + var descriptor = try beam.fetch_resource(MemRefT, env, MemRefT.resource_type, term); + return beam.make_i64(env, descriptor.offset); + } + }; +} + +fn memref_module_name(comptime resource_kind: type, comptime rank: i32) []const u8 { + return resource_kind.module_name ++ ".MemRef." ++ @tagName(@as(MemRefRankType, @enumFromInt(rank))); +} + +fn UnrankMemRefDescriptor(comptime ResourceKind: type) type { + return extern struct { + pub fn make(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + var allocated: ResourceKind.Ptr.T = try MemRefDescriptorAccessor(@This()).fetch_ptr_or_nil(env, args[0]); + var aligned: ResourceKind.Ptr.T = try MemRefDescriptorAccessor(@This()).fetch_ptr_or_nil(env, args[1]); + var offset: mlir_capi.I64.T = try mlir_capi.I64.resource.fetch(env, args[2]); + const kind: type = dataKindToMemrefKind(ResourceKind); + var descriptor: UnrankMemRefDescriptor(ResourceKind) = undefined; + if (allocated == null) { + descriptor = .{ + .offset = offset, + }; + } else { + descriptor = .{ + .allocated = allocated, + .aligned = aligned, + .offset = offset, + }; + } + return try kind.per_rank_resource_kinds[0].resource.make(env, descriptor); + } + pub const maker = .{ result.wrap(make), 5 }; + pub const module_name = memref_module_name(ResourceKind, 0); + const ElementResourceKind = ResourceKind; + const T = ResourceKind.T; + allocated: ?*T = null, + aligned: ?*T = null, + offset: i64 = undefined, + pub var resource_type: beam.resource_type = undefined; + fn allocated_ptr(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + return try MemRefDescriptorAccessor(@This()).allocated_ptr(env, args[0]); + } + fn aligned_ptr(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + return try MemRefDescriptorAccessor(@This()).aligned_ptr(env, args[0]); + } + fn get_offset(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + return try MemRefDescriptorAccessor(@This()).offset(env, args[0]); + } + pub const nifs = .{ result.nif(module_name ++ ".allocated", 1, allocated_ptr).entry, result.nif(module_name ++ ".aligned", 1, aligned_ptr).entry, result.nif(module_name ++ ".offset", 1, get_offset).entry }; + }; +} + +fn MemRefDescriptor(comptime ResourceKind: type, comptime N: usize) type { + return extern struct { + const T = ResourceKind.T; + allocated: ?*T = null, + aligned: ?*T = null, + offset: i64 = undefined, + sizes: [N]i64 = undefined, + strides: [N]i64 = undefined, + fn populate(self: *@This(), allocated: *T, aligned: *T, offset: i64, sizes: []i64, strides: []i64) void { + self.allocated = allocated; + self.aligned = aligned; + self.offset = offset; + const rank = sizes.len; + mem.copy(i64, self.sizes[0..rank], sizes[0..rank]); + mem.copy(i64, self.strides[0..rank], strides[0..rank]); + } + fn populate2(self: *@This(), offset: i64, sizes: []i64, strides: []i64) void { + self.offset = offset; + const rank = sizes.len; + mem.copy(i64, self.sizes[0..rank], sizes[0..rank]); + mem.copy(i64, self.strides[0..rank], strides[0..rank]); + } + pub fn make(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + const Error = error{ + SizesAndStridesOfDifferentLength, + WrongSizesForRank, + WrongStridesForRank, + }; + var allocated: ResourceKind.Ptr.T = try MemRefDescriptorAccessor(@This()).fetch_ptr_or_nil(env, args[0]); + var aligned: ResourceKind.Ptr.T = try MemRefDescriptorAccessor(@This()).fetch_ptr_or_nil(env, args[1]); + var offset: mlir_capi.I64.T = try mlir_capi.I64.resource.fetch(env, args[2]); + const sizes = try beam.get_slice_of(i64, env, args[3]); + defer beam.allocator.free(sizes); + const strides = try beam.get_slice_of(i64, env, args[4]); + defer beam.allocator.free(strides); + if (sizes.len != strides.len) { + return Error.SizesAndStridesOfDifferentLength; + } + const kind: type = dataKindToMemrefKind(ResourceKind); + comptime var rank = N; + if (rank != sizes.len) { + return Error.WrongSizesForRank; + } + if (rank != strides.len) { + return Error.WrongStridesForRank; + } + var descriptor: MemRefDescriptor(ResourceKind, rank) = .{}; + if (allocated == null) { + descriptor.populate2(offset, sizes, strides); + } else { + descriptor.populate(allocated, aligned, offset, sizes, strides); + } + return try kind.per_rank_resource_kinds[rank].resource.make(env, descriptor); + } + pub const maker = .{ result.wrap(make), 5 }; + pub const ElementResourceKind = ResourceKind; + pub const module_name = memref_module_name(ResourceKind, N); + pub var resource_type: beam.resource_type = undefined; + fn allocated_ptr(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + return try MemRefDescriptorAccessor(@This()).allocated_ptr(env, args[0]); + } + fn aligned_ptr(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + return try MemRefDescriptorAccessor(@This()).aligned_ptr(env, args[0]); + } + fn get_offset(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + return try MemRefDescriptorAccessor(@This()).offset(env, args[0]); + } + fn get_sizes(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + comptime var rank = N; + var descriptor: @This() = try beam.fetch_resource(@This(), env, @This().resource_type, args[0]); + var ret: []beam.term = try beam.allocator.alloc(beam.term, @intCast(rank)); + defer beam.allocator.free(ret); + var i: usize = 0; + while (i < rank) : ({ + i += 1; + }) { + ret[@intCast(i)] = beam.make_i64(env, descriptor.sizes[i]); + } + return beam.make_term_list(env, ret); + } + fn get_strides(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + comptime var rank = N; + var descriptor: @This() = try beam.fetch_resource(@This(), env, @This().resource_type, args[0]); + var ret: []beam.term = try beam.allocator.alloc(beam.term, @intCast(rank)); + defer beam.allocator.free(ret); + var i: usize = 0; + while (i < rank) : ({ + i += 1; + }) { + ret[@intCast(i)] = beam.make_i64(env, descriptor.strides[i]); + } + return beam.make_term_list(env, ret); + } + pub const nifs = .{ + result.nif(module_name ++ ".allocated", 1, allocated_ptr).entry, + result.nif(module_name ++ ".aligned", 1, aligned_ptr).entry, + result.nif(module_name ++ ".offset", 1, get_offset).entry, + result.nif(module_name ++ ".sizes", 1, get_sizes).entry, + result.nif(module_name ++ ".strides", 1, get_strides).entry, + }; + }; +} + +const Complex = struct { + fn of(comptime ElementKind: type) type { + return struct { + const T = extern struct { + i: ElementKind.T, + r: ElementKind.T, + }; + }; + } + const F32 = kinda.ResourceKind(Complex.of(mlir_capi.F32).T, "Elixir.Beaver.Native.Complex.F32"); +}; + +const MemRefDataType = enum { + @"Complex.F32", + U8, + U16, + U32, + F32, + F64, + I8, + I16, + I32, + I64, +}; + +fn dataTypeToResourceKind(comptime self: MemRefDataType) type { + return switch (self) { + .@"Complex.F32" => Complex.F32, + .U8 => mlir_capi.U8, + .U16 => mlir_capi.U16, + .U32 => mlir_capi.U32, + .F32 => mlir_capi.F32, + .F64 => mlir_capi.F64, + .I8 => mlir_capi.I8, + .I16 => mlir_capi.I16, + .I32 => mlir_capi.I32, + .I64 => mlir_capi.I64, + }; +} + +fn dataKindToDataType(comptime self: type) MemRefDataType { + return switch (self) { + Complex.F32 => MemRefDataType.@"Complex.F32", + mlir_capi.U8 => MemRefDataType.U8, + mlir_capi.U16 => MemRefDataType.U16, + mlir_capi.U32 => MemRefDataType.U32, + mlir_capi.F32 => MemRefDataType.F32, + mlir_capi.F64 => MemRefDataType.F64, + mlir_capi.I8 => MemRefDataType.I8, + mlir_capi.I16 => MemRefDataType.I16, + mlir_capi.I32 => MemRefDataType.I32, + mlir_capi.I64 => MemRefDataType.I64, + else => unreachable(), + }; +} + +const memref_kinds = .{ + BeaverMemRef(dataTypeToResourceKind(MemRefDataType.@"Complex.F32")), + BeaverMemRef(dataTypeToResourceKind(MemRefDataType.U8)), + BeaverMemRef(dataTypeToResourceKind(MemRefDataType.U16)), + BeaverMemRef(dataTypeToResourceKind(MemRefDataType.U32)), + BeaverMemRef(dataTypeToResourceKind(MemRefDataType.F32)), + BeaverMemRef(dataTypeToResourceKind(MemRefDataType.F64)), + BeaverMemRef(dataTypeToResourceKind(MemRefDataType.I8)), + BeaverMemRef(dataTypeToResourceKind(MemRefDataType.I16)), + BeaverMemRef(dataTypeToResourceKind(MemRefDataType.I32)), + BeaverMemRef(dataTypeToResourceKind(MemRefDataType.I64)), +}; + +fn dataKindToMemrefKind(comptime self: type) type { + const dt = dataKindToDataType(self); + const index = @intFromEnum(dt); + return memref_kinds[index]; +} + +const MemRefRankType = enum { + DescriptorUnranked, + Descriptor1D, + Descriptor2D, + Descriptor3D, + Descriptor4D, + Descriptor5D, + Descriptor6D, + Descriptor7D, + Descriptor8D, + Descriptor9D, +}; + +fn BeaverMemRef(comptime ResourceKind: type) type { + return struct { + const data_kind_name = ResourceKind.module_name; + pub const nifs = + per_rank_resource_kinds[0].nifs ++ + per_rank_resource_kinds[1].nifs ++ + per_rank_resource_kinds[2].nifs ++ + per_rank_resource_kinds[3].nifs ++ + per_rank_resource_kinds[4].nifs ++ + per_rank_resource_kinds[5].nifs; + fn MemRefOfRank(comptime rank: u8) type { + if (rank == 0) { + return kinda.ResourceKind2(UnrankMemRefDescriptor(ResourceKind)); + } else { + return kinda.ResourceKind2(MemRefDescriptor(ResourceKind, rank)); + } + } + const per_rank_resource_kinds = .{ + MemRefOfRank(0), + MemRefOfRank(1), + MemRefOfRank(2), + MemRefOfRank(3), + MemRefOfRank(4), + MemRefOfRank(5), + }; + fn open(env: beam.env) void { + comptime var i = 0; + inline while (i < per_rank_resource_kinds.len) : (i += 1) { + per_rank_resource_kinds[i].open_all(env); + } + } + }; +} + +pub const nifs = Complex.F32.nifs ++ + dataKindToMemrefKind(Complex.F32).nifs ++ + dataKindToMemrefKind(mlir_capi.U8).nifs ++ + dataKindToMemrefKind(mlir_capi.U16).nifs ++ + dataKindToMemrefKind(mlir_capi.U32).nifs ++ + dataKindToMemrefKind(mlir_capi.F32).nifs ++ + dataKindToMemrefKind(mlir_capi.F64).nifs ++ + dataKindToMemrefKind(mlir_capi.I8).nifs ++ + dataKindToMemrefKind(mlir_capi.I16).nifs ++ + dataKindToMemrefKind(mlir_capi.I32).nifs ++ + dataKindToMemrefKind(mlir_capi.I64).nifs; + +pub fn open_all(env: beam.env) void { + comptime var i = 0; + inline while (i < memref_kinds.len) : (i += 1) { + memref_kinds[i].open(env); + } + Complex.F32.open_all(env); +} diff --git a/native/mlir-zig-proj/src/mlir_capi.zig b/native/mlir-zig-proj/src/mlir_capi.zig index 050208b2..6c4ce705 100644 --- a/native/mlir-zig-proj/src/mlir_capi.zig +++ b/native/mlir-zig-proj/src/mlir_capi.zig @@ -157,7 +157,7 @@ pub const allKinds = .{ LLVMThreadPool, TypeIDAllocator, }; -pub fn open_generated_resource_types(env: beam.env) void { +pub fn open_all(env: beam.env) void { inline for (allKinds) |k| { k.open_all(env); } diff --git a/native/mlir-zig-proj/src/pass.zig b/native/mlir-zig-proj/src/pass.zig index 32d6d011..0ae5f73b 100644 --- a/native/mlir-zig-proj/src/pass.zig +++ b/native/mlir-zig-proj/src/pass.zig @@ -7,7 +7,7 @@ const debug_print = @import("std").debug.print; const result = @import("result.zig"); const diagnostic = @import("diagnostic.zig"); -pub const Token = struct { +const Token = struct { mutex: std.Thread.Mutex = .{}, cond: std.Thread.Condition = .{}, done: bool = false, @@ -112,3 +112,6 @@ pub fn do_create(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term } pub const nifs = .{ result.nif("beaver_raw_create_mlir_pass", 5, do_create).entry, result.nif("beaver_raw_pass_token_signal", 1, Token.pass_token_signal).entry }; +pub fn open_all(env: beam.env) void { + beam.open_resource_wrapped(env, Token); +} diff --git a/native/mlir-zig-proj/src/pointer.zig b/native/mlir-zig-proj/src/pointer.zig index a89cd3f4..3d12c7ae 100644 --- a/native/mlir-zig-proj/src/pointer.zig +++ b/native/mlir-zig-proj/src/pointer.zig @@ -30,11 +30,15 @@ fn own_opaque_ptr(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term fn read_opaque_ptr(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { var ptr = try mlir_capi.OpaquePtr.resource.fetch(env, args[0]); var len = try mlir_capi.USize.resource.fetch(env, args[1]); + const Error = error{NullPointer}; if (ptr == null) { - return beam.make_error_binary(env, "ptr is null"); + return Error.NullPointer; } const slice = @as(mlir_capi.U8.Array.T, @ptrCast(ptr))[0..len]; return beam.make_slice(env, slice); } -pub const nifs = .{ result.nif("beaver_raw_get_null_ptr", 0, get_null).entry, result.nif("beaver_raw_own_opaque_ptr", 1, own_opaque_ptr).entry, result.nif("beaver_raw_read_opaque_ptr", 2, read_opaque_ptr).entry }; +pub const nifs = .{ result.nif("beaver_raw_get_null_ptr", 0, get_null).entry, result.nif("beaver_raw_own_opaque_ptr", 1, own_opaque_ptr).entry, result.nif("beaver_raw_read_opaque_ptr", 2, read_opaque_ptr).entry } ++ PtrOwner.Kind.nifs; +pub fn open_all(env: beam.env) void { + PtrOwner.Kind.open(env); +} diff --git a/native/mlir-zig-proj/src/result.zig b/native/mlir-zig-proj/src/result.zig index 876e5dd8..3eaa7d63 100644 --- a/native/mlir-zig-proj/src/result.zig +++ b/native/mlir-zig-proj/src/result.zig @@ -15,3 +15,7 @@ pub fn nif(comptime name: [*c]const u8, comptime arity: usize, comptime f: anyty pub const entry = e.ErlNifFunc{ .name = name, .arity = arity, .fptr = exported, .flags = 0 }; }; } + +pub fn wrap(comptime f: anytype) fn (env: beam.env, n: c_int, args: [*c]const beam.term) callconv(.C) beam.term { + return nif("", 0, f).exported; +} diff --git a/native/mlir-zig-proj/src/string_ref.zig b/native/mlir-zig-proj/src/string_ref.zig index 894a6c9a..d1daa067 100644 --- a/native/mlir-zig-proj/src/string_ref.zig +++ b/native/mlir-zig-proj/src/string_ref.zig @@ -6,25 +6,28 @@ const result = @import("result.zig"); pub const c = @import("prelude.zig"); const mem = @import("std").mem; -pub fn Printer(comptime ResourceKind: type, comptime print_fn: anytype) type { +pub fn Printer(comptime name: [*c]const u8, comptime ResourceKind: type, comptime print_fn: anytype) type { return struct { + const Error = error{ + NullPointerFound, + }; const Buffer = std.ArrayList(u8); buffer: Buffer, fn collect_string_ref(s: mlir_capi.StringRef.T, userData: ?*anyopaque) callconv(.C) void { var printer: *@This() = @ptrCast(@alignCast(userData)); printer.*.buffer.appendSlice(s.data[0..s.length]) catch unreachable; } - pub fn to_string(env: beam.env, _: c_int, args: [*c]const beam.term) callconv(.C) beam.term { - var entity: ResourceKind.T = ResourceKind.resource.fetch(env, args[0]) catch - return beam.make_error_binary(env, "fail to fetch resource for MLIR entity to print, expected: " ++ @typeName(ResourceKind.T)); + fn to_string(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + var entity: ResourceKind.T = try ResourceKind.resource.fetch(env, args[0]); if (entity.ptr == null) { - return beam.make_error_binary(env, "null pointer found: " ++ @typeName(@TypeOf(entity))); + return Error.NullPointerFound; } var printer = @This(){ .buffer = Buffer.init(beam.allocator) }; defer printer.buffer.deinit(); print_fn(entity, collect_string_ref, &printer); return beam.make_slice(env, printer.buffer.items); } + const entry = result.nif(name, 1, to_string).entry; }; } @@ -56,13 +59,12 @@ fn beaver_raw_string_ref_to_binary(env: beam.env, _: c_int, args: [*c]const beam return string_ref_to_binary(env, try mlir_capi.StringRef.resource.fetch(env, args[0])); } -const Error = error{ - ResAllocFailure, - NotBinary, -}; - // memory layout {StringRef, real_binary, null} fn beaver_raw_get_string_ref(env: beam.env, _: c_int, args: [*c]const beam.term) !beam.term { + const Error = error{ + ResAllocFailure, + NotBinary, + }; const StructT = mlir_capi.StringRef.T; const DataT = [*c]u8; var bin: beam.binary = undefined; @@ -82,4 +84,17 @@ fn beaver_raw_get_string_ref(env: beam.env, _: c_int, args: [*c]const beam.term) return e.enif_make_resource(env, ptr); } -pub const nifs = .{ result.nif("beaver_raw_get_string_ref", 1, beaver_raw_get_string_ref).entry, result.nif("beaver_raw_string_ref_to_binary", 1, beaver_raw_string_ref_to_binary).entry }; +pub const nifs = .{ + result.nif("beaver_raw_get_string_ref", 1, beaver_raw_get_string_ref).entry, + result.nif("beaver_raw_string_ref_to_binary", 1, beaver_raw_string_ref_to_binary).entry, + Printer("beaver_raw_to_string_attribute", mlir_capi.Attribute, c.mlirAttributePrint).entry, + Printer("beaver_raw_to_string_type", mlir_capi.Type, c.mlirTypePrint).entry, + Printer("beaver_raw_to_string_operation", mlir_capi.Operation, c.mlirOperationPrint).entry, + Printer("beaver_raw_to_string_operation_specialized", mlir_capi.Operation, c.beaverOperationPrintSpecializedFrom).entry, + Printer("beaver_raw_to_string_operation_generic", mlir_capi.Operation, c.beaverOperationPrintGenericOpForm).entry, + Printer("beaver_raw_to_string_operation_bytecode", mlir_capi.Operation, c.mlirOperationWriteBytecode).entry, + Printer("beaver_raw_to_string_value", mlir_capi.Value, c.mlirValuePrint).entry, + Printer("beaver_raw_to_string_pm", mlir_capi.OpPassManager, c.mlirPrintPassPipeline).entry, + Printer("beaver_raw_to_string_affine_map", mlir_capi.AffineMap, c.mlirAffineMapPrint).entry, + Printer("beaver_raw_to_string_location", mlir_capi.Location, c.beaverLocationPrint).entry, +};