diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 7b4cab0..914dc89 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -24,7 +24,7 @@ jobs: - name: Set up Elixir uses: erlef/setup-beam@v1 with: - elixir-version: "1.17-dev" # [Required] Define the Elixir version + elixir-version: "1.17" # [Required] Define the Elixir version otp-version: "26.0" # [Required] Define the Erlang/OTP version - name: Restore dependencies cache uses: actions/cache@v3 diff --git a/guides/programming-with-charms.livemd b/guides/programming-with-charms.livemd index dfbcda6..6e7e4a7 100644 --- a/guides/programming-with-charms.livemd +++ b/guides/programming-with-charms.livemd @@ -2,7 +2,7 @@ ```elixir Mix.install([ - {:charms, "~> 0.1.1"} + {:charms, "~> 0.1.2"} ]) ``` diff --git a/lib/charms/debug.ex b/lib/charms/debug.ex index e686385..7348ff3 100644 --- a/lib/charms/debug.ex +++ b/lib/charms/debug.ex @@ -9,7 +9,7 @@ defmodule Charms.Debug do MLIR.dump!(op) _ -> - MLIR.Transforms.print_ir(op) + MLIR.Transform.print_ir(op) end else op diff --git a/lib/charms/defm/definition.ex b/lib/charms/defm/definition.ex index ec8634d..97d2d81 100644 --- a/lib/charms/defm/definition.ex +++ b/lib/charms/defm/definition.ex @@ -153,8 +153,7 @@ defmodule Charms.Defm.Definition do end if msg = Beaver.Walker.attributes(op)["msg"] do - MLIR.Attribute.unwrap(msg) - |> MLIR.StringRef.to_string() + MLIR.Attribute.unwrap(msg) |> MLIR.to_string() else "Poison operation detected in the IR. #{to_string(op)}" end @@ -180,12 +179,12 @@ defmodule Charms.Defm.Definition do |> MLIR.CAPI.mlirFunctionTypeGetNumResults() |> Beaver.Native.to_term() do 0 -> - mlir ctx: MLIR.CAPI.mlirOperationGetContext(func), block: b do + mlir ctx: MLIR.CAPI.mlirOperationGetContext(func), blk: b do Func.return(loc: MLIR.Operation.location(func)) >>> [] end 1 -> - mlir ctx: MLIR.CAPI.mlirOperationGetContext(last_op), block: b do + mlir ctx: MLIR.CAPI.mlirOperationGetContext(last_op), blk: b do results = Beaver.Walker.results(last_op) |> Enum.to_list() Func.return(results, loc: MLIR.Operation.location(last_op)) >>> [] end @@ -225,10 +224,13 @@ defmodule Charms.Defm.Definition do |> then(fn {_, acc} -> MapSet.to_list(acc) end) end - def do_compile(ctx, definitions, diagnostic_server) do - m = MLIR.Module.create(ctx, "") + def do_compile(ctx, definitions) do + # this function might be called at compile time, so we need to ensure the application is started + :ok = Application.ensure_started(:kinda) + :ok = Application.ensure_started(:beaver) + m = MLIR.Module.create("", ctx: ctx) - mlir ctx: ctx, block: MLIR.Module.body(m) do + mlir ctx: ctx, blk: MLIR.Module.body(m) do mlir_expander = %Charms.Defm.Expander{ ctx: ctx, blk: Beaver.Env.block(), @@ -266,20 +268,20 @@ defmodule Charms.Defm.Definition do m |> Charms.Debug.print_ir_pass() - |> MLIR.Pass.Composer.nested( + |> Beaver.Composer.nested( "func.func", {"append_missing_return", "func.func", &append_missing_return/1} ) - |> MLIR.Pass.Composer.nested("func.func", Charms.Defm.Pass.CreateAbsentFunc) - |> MLIR.Pass.Composer.append({"check-poison", "builtin.module", &check_poison!/1}) - |> MLIR.Transforms.canonicalize() + |> Beaver.Composer.nested("func.func", Charms.Defm.Pass.CreateAbsentFunc) + |> Beaver.Composer.append({"check-poison", "builtin.module", &check_poison!/1}) + |> MLIR.Transform.canonicalize() |> then(fn op -> - case MLIR.Pass.Composer.run(op, print: Charms.Debug.step_print?()) do + case Beaver.Composer.run(op, print: Charms.Debug.step_print?()) do {:ok, op} -> op {:error, msg} -> - raise_compile_error(__ENV__, diagnostic_server, msg) + raise_compile_error(__ENV__, msg) end end) |> then(&{MLIR.to_string(&1, bytecode: true), referenced_modules(&1)}) @@ -296,15 +298,28 @@ defmodule Charms.Defm.Definition do """ def compile(definitions) when is_list(definitions) do ctx = MLIR.Context.create() - {:ok, diagnostic_server} = GenServer.start(Beaver.Diagnostic.Server, []) - diagnostic_handler_id = Beaver.Diagnostic.attach(ctx, diagnostic_server) - - try do - do_compile(ctx, definitions, diagnostic_server) - after - Beaver.Diagnostic.detach(ctx, diagnostic_handler_id) - MLIR.Context.destroy(ctx) - :ok = GenServer.stop(diagnostic_server) + {res, msg} = MLIR.Context.with_diagnostics( + ctx, + fn -> + try do + {:ok, do_compile(ctx, definitions)} + rescue + err -> + {:error, err} + end + end, + fn d, _acc -> Charms.Diagnostic.compile_error_message(d) end + ) + case {res, msg} do + {{:ok, {mlir, mods}}, nil} -> + MLIR.Context.destroy(ctx) + {mlir, mods} + + {_, {:ok, d_msg}} -> + raise CompileError, d_msg + + {{:error, err}, _} -> + raise err end end diff --git a/lib/charms/defm/expander.ex b/lib/charms/defm/expander.ex index d11baf9..a2e19c2 100644 --- a/lib/charms/defm/expander.ex +++ b/lib/charms/defm/expander.ex @@ -19,7 +19,7 @@ defmodule Charms.Defm.Expander do """ use Beaver alias MLIR.Attribute - alias MLIR.Dialect.{Func, CF, SCF, MemRef, Index, Arith, Ub, LLVM} + alias MLIR.Dialect.{Func, CF, SCF, MemRef, Index, Arith, UB, LLVM} require Func import Charms.Diagnostic, only: :macros # Define the environment we will use for expansion. @@ -67,7 +67,6 @@ defmodule Charms.Defm.Expander do """ def expand(ast, file) do ctx = MLIR.Context.create() - Beaver.Diagnostic.attach(ctx) available_ops = MapSet.new(MLIR.Dialect.Registry.ops(:all, ctx: ctx)) mlir = %__MODULE__{ @@ -102,12 +101,12 @@ defmodule Charms.Defm.Expander do defp create_call(mod, name, args, types, state, env) do op = - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do %Beaver.SSA{ op: "func.call", arguments: args ++ [callee: Attribute.flat_symbol_ref(mangling(mod, name))], ctx: Beaver.Env.context(), - block: Beaver.Env.block(), + blk: Beaver.Env.block(), loc: MLIR.Location.from_env(env) } |> Beaver.SSA.put_results(types) @@ -118,8 +117,8 @@ defmodule Charms.Defm.Expander do end defp create_poison(msg, state, env) do - mlir ctx: state.mlir.ctx, block: state.mlir.blk do - Ub.poison(msg: MLIR.Attribute.string(msg), loc: MLIR.Location.from_env(env)) >>> + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do + UB.poison(msg: MLIR.Attribute.string(msg), loc: MLIR.Location.from_env(env)) >>> ~t{none} end |> then(&{&1, state, env}) @@ -130,7 +129,7 @@ defmodule Charms.Defm.Expander do update_in( state.mlir.dependence_modules, &Map.put_new_lazy(&1, module, fn -> - MLIR.Module.create(state.mlir.ctx, module.__ir__()) |> MLIR.Operation.from_module() + MLIR.Module.create(module.__ir__(), ctx: state.mlir.ctx) |> MLIR.Operation.from_module() end) ) |> then(&{&1.mlir.dependence_modules[module], &1}) @@ -175,7 +174,7 @@ defmodule Charms.Defm.Expander do MLIR.StringRef.create(mangling(mod, name)) ) - if MLIR.is_null(sym) do + if MLIR.null?(sym) do raise_compile_error( env, "function #{name} not found in module #{inspect(mod)}" @@ -274,7 +273,7 @@ defmodule Charms.Defm.Expander do defp expand_std(Enum, :reduce, args, state, env) do while = - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do [l, init, f] = args {l, state, env} = expand(l, state, env) {init, state, env} = expand(init, state, env) @@ -343,7 +342,7 @@ defmodule Charms.Defm.Expander do defp expand_std(String, :length, args, state, env) do {string, state, env} = expand(args, state, env) - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do zero = Index.constant(value: Attribute.index(0)) >>> Type.index() len = MemRef.dim(string, zero) >>> :infer end @@ -371,7 +370,7 @@ defmodule Charms.Defm.Expander do state = with [head_arg_type | _] <- arg_types, - MLIR.Type.equal?(head_arg_type, Beaver.ENIF.Type.env(ctx: state.mlir.ctx)), + MLIR.equal?(head_arg_type, Beaver.ENIF.Type.env(ctx: state.mlir.ctx)), [{:env, _, nil} | _] <- args do a = MLIR.Block.get_arg!(Beaver.Env.block(), 0) put_in(state.mlir.enif_env, a) @@ -430,7 +429,7 @@ defmodule Charms.Defm.Expander do op: op, arguments: args, ctx: state.mlir.ctx, - block: state.mlir.blk, + blk: state.mlir.blk, loc: MLIR.Location.from_env(env), results: if(has_implemented_inference(op, state.mlir.ctx), do: [:infer], else: []) } @@ -473,7 +472,7 @@ defmodule Charms.Defm.Expander do args, %Charms.Intrinsic.Opts{ ctx: state.mlir.ctx, - block: state.mlir.blk, + blk: state.mlir.blk, loc: loc } ]) @@ -754,10 +753,10 @@ defmodule Charms.Defm.Expander do defp expand({:^, _meta, [arg]}, state, %{context: context} = env) do {b, state, env} = expand(arg, state, %{env | context: nil}) - match?(%MLIR.Block{}, b) || raise Beaver.EnvNotFoundError, MLIR.Block + match?(%MLIR.Block{}, b) || raise_compile_error(env, "Expected a block, got: #{inspect(b)}") br = - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do CF.br({b, []}) >>> [] end @@ -845,14 +844,14 @@ defmodule Charms.Defm.Expander do found = MLIR.CAPI.mlirSymbolTableLookup(s_table, MLIR.StringRef.create(sym_name)) loc = MLIR.Location.from_env(env) - mlir ctx: state.mlir.ctx, block: MLIR.Module.body(state.mlir.mod) do - if MLIR.is_null(found) do + mlir ctx: state.mlir.ctx, blk: MLIR.Module.body(state.mlir.mod) do + if MLIR.null?(found) do MemRef.global(ast, sym_name: Attribute.string(sym_name), loc: loc) >>> :infer else found end |> then( - &mlir block: state.mlir.blk do + &mlir blk: state.mlir.blk do name = Attribute.flat_symbol_ref(Attribute.unwrap(&1[:sym_name])) MemRef.get_global(name: name, loc: loc) >>> Attribute.unwrap(&1[:type]) end @@ -880,7 +879,7 @@ defmodule Charms.Defm.Expander do # Expands a nil clause body in an if statement, yielding no value. defp expand_if_clause_body(nil, state, _env) do - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do SCF.yield() >>> [] [] end @@ -888,7 +887,7 @@ defmodule Charms.Defm.Expander do # Expands a non-nil clause body in an if statement, yielding the last evaluated value. defp expand_if_clause_body(clause_body, state, env) do - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do {ret, _, _} = expand(clause_body, state, env) case ret do @@ -961,7 +960,7 @@ defmodule Charms.Defm.Expander do parent_block = state.mlir.blk f = - mlir ctx: state.mlir.ctx, block: parent_block do + mlir ctx: state.mlir.ctx, blk: parent_block do {ret_types, state, env} = ret_types |> expand(state, env) {arg_types, state, env} = arg_types |> expand(state, env) @@ -1012,7 +1011,7 @@ defmodule Charms.Defm.Expander do {condition, state, env} = expand(condition, state, env) v = - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do true_body = block do expand(true_body, put_in(state.mlir.blk, Beaver.Env.block()), env) @@ -1044,7 +1043,7 @@ defmodule Charms.Defm.Expander do loc = MLIR.Location.from_env(env) v = - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do cond_type = MLIR.Value.type(condition) bool_type = Type.i1(ctx: state.mlir.ctx) # Ensure the condition is a i1, if not compare it to 0 @@ -1085,7 +1084,7 @@ defmodule Charms.Defm.Expander do loc = MLIR.Location.from_env(env) v = - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do SCF.while loc: loc do region do block _() do @@ -1119,7 +1118,7 @@ defmodule Charms.Defm.Expander do {ptr, state, env} = expand(ptr, state, env) v = - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do zero = Index.constant(value: Attribute.index(0)) >>> Type.index() lower_bound = zero upper_bound = Index.casts(len) >>> Type.index() @@ -1170,7 +1169,7 @@ defmodule Charms.Defm.Expander do op: op, arguments: args, ctx: state.mlir.ctx, - block: state.mlir.blk, + blk: state.mlir.blk, loc: MLIR.Location.from_env(env) } |> Beaver.SSA.put_results(return_types) @@ -1209,7 +1208,7 @@ defmodule Charms.Defm.Expander do {type, state, env} = expand(type, state, env) value = - mlir ctx: state.mlir.ctx, block: state.mlir.blk do + mlir ctx: state.mlir.ctx, blk: state.mlir.blk do loc = MLIR.Location.from_env(env) cond do diff --git a/lib/charms/defm/pass/create_absent_func.ex b/lib/charms/defm/pass/create_absent_func.ex index b2f7ae7..0590d59 100644 --- a/lib/charms/defm/pass/create_absent_func.ex +++ b/lib/charms/defm/pass/create_absent_func.ex @@ -27,14 +27,14 @@ defmodule Charms.Defm.Pass.CreateAbsentFunc do @default_visibility "private" # create absent if it is a function not found in the symbol table - defp create_func(ctx, block, symbol_table, ir, created) do + defp create_func(ctx, blk, symbol_table, ir, created) do with op = %MLIR.Operation{} <- ir, "func.call" <- MLIR.Operation.name(op), {name, arg_types, ret_types} <- decompose(op), - true <- MLIR.is_null(mlirSymbolTableLookup(symbol_table, name)), - name_str <- MLIR.StringRef.to_string(name), + true <- MLIR.null?(mlirSymbolTableLookup(symbol_table, name)), + name_str <- MLIR.to_string(name), false <- MapSet.member?(created, name_str) do - mlir ctx: ctx, block: block do + mlir ctx: ctx, blk: blk do {arg_types, ret_types} = if s = Beaver.ENIF.signature(ctx, String.to_atom(name_str)) do s diff --git a/lib/charms/diagnostic.ex b/lib/charms/diagnostic.ex index ae57a3b..ba4bea1 100644 --- a/lib/charms/diagnostic.ex +++ b/lib/charms/diagnostic.ex @@ -1,42 +1,29 @@ defmodule Charms.Diagnostic do @moduledoc false @doc false - def compile_error_message(diagnostic_server) when is_pid(diagnostic_server) do - case txt = Beaver.Diagnostic.Server.flush(diagnostic_server) do - "[Beaver] [Diagnostic] [" <> _suffix -> + alias Beaver.MLIR + def compile_error_message(%Beaver.MLIR.Diagnostic{} = d) do + loc = to_string(MLIR.location(d)) + txt = to_string(d) + case txt do + "" -> + {:error, "No diagnostic message"} + + note -> c = Regex.named_captures( - ~r/\[Beaver\] \[Diagnostic\] \[(?.+):(?\d+):(?\d+)\] (?.*)/, - txt + ~r/(?.+):(?\d+):(?\d+)/, + loc ) - {:ok, [file: c["file"], line: c["line"] || 0, description: c["note"] || txt]} - - "" -> - {:error, "No diagnostic message"} + {:ok, [file: c["file"], line: c["line"] || 0, description: note]} end end - defmacro raise_compile_error(env, description) do + defmacro raise_compile_error(env, diagnostic) do quote do raise CompileError, - Charms.Diagnostic.compile_error_message_from_env(unquote(env), unquote(description)) - end - end - - defmacro raise_compile_error(env, diagnostic_server, fallback_description) do - quote do - case Charms.Diagnostic.compile_error_message(unquote(diagnostic_server)) do - {:ok, dm} -> - dm - - {:error, _} -> - Charms.Diagnostic.compile_error_message_from_env( - unquote(env), - unquote(fallback_description) - ) - end - |> then(&raise(CompileError, &1)) + Charms.Diagnostic.compile_error_message_from_env(unquote(env), unquote(diagnostic)) end end diff --git a/lib/charms/intrinsic.ex b/lib/charms/intrinsic.ex index 5986ad4..183dc6e 100644 --- a/lib/charms/intrinsic.ex +++ b/lib/charms/intrinsic.ex @@ -3,7 +3,7 @@ defmodule Charms.Intrinsic do @moduledoc """ Options for intrinsic functions. """ - defstruct [:ctx, :block, :loc] + defstruct [:ctx, :blk, :loc] end @moduledoc """ diff --git a/lib/charms/jit.ex b/lib/charms/jit.ex index 1e33f8f..ef31ace 100644 --- a/lib/charms/jit.ex +++ b/lib/charms/jit.ex @@ -7,24 +7,24 @@ defmodule Charms.JIT do alias Beaver.MLIR alias __MODULE__.LockedCache - defstruct ctx: nil, engine: nil, owner: true, diagnostic_server: nil, diagnostic_handler_id: nil + defstruct ctx: nil, engine: nil, owner: true defp jit_of_mod(m) do - import Beaver.MLIR.{Conversion, Transforms} + import Beaver.MLIR.{Conversion, Transform} m - |> MLIR.Operation.verify!(debug: true) - |> MLIR.Pass.Composer.nested("func.func", "llvm-request-c-wrappers") - |> MLIR.Pass.Composer.nested("func.func", loop_invariant_code_motion()) + |> MLIR.verify!() + |> Beaver.Composer.nested("func.func", "llvm-request-c-wrappers") + |> Beaver.Composer.nested("func.func", loop_invariant_code_motion()) |> convert_scf_to_cf |> convert_arith_to_llvm() |> convert_index_to_llvm() |> convert_func_to_llvm() - |> MLIR.Pass.Composer.append("convert-vector-to-llvm{reassociate-fp-reductions}") - |> MLIR.Pass.Composer.append("finalize-memref-to-llvm") + |> Beaver.Composer.append("convert-vector-to-llvm{reassociate-fp-reductions}") + |> Beaver.Composer.append("finalize-memref-to-llvm") |> reconcile_unrealized_casts |> Charms.Debug.print_ir_pass() - |> MLIR.Pass.Composer.run!(print: Charms.Debug.step_print?()) + |> Beaver.Composer.run!(print: Charms.Debug.step_print?()) |> MLIR.ExecutionEngine.create!(opt_level: 3, object_dump: true) |> tap(&beaver_raw_jit_register_enif(&1.ref)) end @@ -38,10 +38,10 @@ defmodule Charms.JIT do found = mlirSymbolTableLookup(s_table, MLIR.Attribute.unwrap(sym)) body = MLIR.Module.body(to) - if MLIR.is_null(found) do + if MLIR.null?(found) do mlirBlockAppendOwnedOperation(body, mlirOperationClone(op)) else - unless Func.is_external(op) do + unless Func.external?(op) do mlirOperationDestroy(found) mlirBlockAppendOwnedOperation(body, mlirOperationClone(op)) end @@ -56,7 +56,7 @@ defmodule Charms.JIT do [head | tail] = modules for module <- tail do - if MLIR.is_null(module), do: raise("can't merge a null module") + if MLIR.null?(module), do: raise("can't merge a null module") clone_ops(head, module) if destroy, do: MLIR.Module.destroy(module) end @@ -66,16 +66,13 @@ defmodule Charms.JIT do defp do_init(modules) when is_list(modules) do ctx = MLIR.Context.create() - {:ok, diagnostic_server} = GenServer.start(Beaver.Diagnostic.Server, []) - diagnostic_handler_id = Beaver.Diagnostic.attach(ctx, diagnostic_server) - modules |> Enum.map(fn m when is_atom(m) -> - m.__ir__() |> then(&MLIR.Module.create(ctx, &1)) + m.__ir__() |> then(&MLIR.Module.create(&1, ctx: ctx)) s when is_binary(s) -> - s |> then(&MLIR.Module.create(ctx, &1)) + s |> then(&MLIR.Module.create(&1, ctx: ctx)) %MLIR.Module{} = m -> m @@ -84,27 +81,27 @@ defmodule Charms.JIT do raise ArgumentError, "Unexpected module type: #{inspect(other)}" end) |> then(fn op -> - try do - op - |> merge_modules() - |> jit_of_mod - rescue - e -> - case Charms.Diagnostic.compile_error_message(diagnostic_server) do - {:ok, dm} -> - reraise CompileError, dm, __STACKTRACE__ - - {:error, _} -> - reraise e, __STACKTRACE__ + {res, _} = MLIR.Context.with_diagnostics( + ctx, + fn -> + try do + {:ok, op |> merge_modules() |> jit_of_mod()} + rescue + err -> + {:error, err} end + end, + fn d, _acc -> Charms.Diagnostic.compile_error_message(d) end + ) + case res do + {:ok, jit} -> jit + {:error, err} -> raise err end end) |> then( &%__MODULE__{ ctx: ctx, - engine: &1, - diagnostic_server: diagnostic_server, - diagnostic_handler_id: diagnostic_handler_id + engine: &1 } ) |> then(&{:ok, &1}) @@ -173,14 +170,10 @@ defmodule Charms.JIT do %__MODULE__{ ctx: ctx, engine: engine, - owner: true, - diagnostic_server: diagnostic_server, - diagnostic_handler_id: diagnostic_handler_id + owner: true } -> - Beaver.Diagnostic.detach(ctx, diagnostic_handler_id) MLIR.ExecutionEngine.destroy(engine) MLIR.Context.destroy(ctx) - :ok = GenServer.stop(diagnostic_server) nil -> :not_found diff --git a/lib/charms/kernel.ex b/lib/charms/kernel.ex index 0386d65..85afa6e 100644 --- a/lib/charms/kernel.ex +++ b/lib/charms/kernel.ex @@ -9,8 +9,8 @@ defmodule Charms.Kernel do @unary_ops [:!] @binary_macro_ops [:&&, :||] - defp constant_of_same_type(i, v, %Opts{ctx: ctx, block: block, loc: loc}) do - mlir ctx: ctx, block: block do + defp constant_of_same_type(i, v, %Opts{ctx: ctx, blk: blk, loc: loc}) do + mlir ctx: ctx, blk: blk do t = MLIR.CAPI.mlirValueGetType(v) if MLIR.CAPI.mlirTypeIsAInteger(t) |> Beaver.Native.to_term() do @@ -29,8 +29,8 @@ defmodule Charms.Kernel do defp i_predicate(:<), do: :slt defp i_predicate(:<=), do: :sle - defp create_binary(op, operands, type, ctx, block, loc) do - mlir ctx: ctx, block: block do + defp create_binary(op, operands, type, ctx, blk, loc) do + mlir ctx: ctx, blk: blk do case op do op when op in @compare_ops -> Arith.cmpi(operands, predicate: Arith.cmp_i_predicate(i_predicate(op)), loc: loc) >>> @@ -59,7 +59,7 @@ defmodule Charms.Kernel do for name <- @binary_ops ++ @binary_macro_ops do defintrinsic unquote(name)(left, right) do - opts = %Opts{ctx: ctx, block: block, loc: loc} = __IR__ + opts = %Opts{ctx: ctx, blk: blk, loc: loc} = __IR__ {operands, type} = case {left, right} do @@ -82,7 +82,7 @@ defmodule Charms.Kernel do end |> then(fn [left, _] = operands -> {operands, MLIR.CAPI.mlirValueGetType(left)} end) - create_binary(unquote(name), operands, type, ctx, block, loc) + create_binary(unquote(name), operands, type, ctx, blk, loc) end end diff --git a/lib/charms/pointer.ex b/lib/charms/pointer.ex index e15ac21..4d6847d 100644 --- a/lib/charms/pointer.ex +++ b/lib/charms/pointer.ex @@ -67,9 +67,9 @@ defmodule Charms.Pointer do Gets the element pointer of `elem_type` for the given base pointer `ptr` and index `n`. """ defintrinsic element_ptr(elem_type, ptr, n) do - %Opts{ctx: ctx, block: block} = __IR__ + %Opts{ctx: ctx, blk: blk} = __IR__ - mlir ctx: ctx, block: block do + mlir ctx: ctx, blk: blk do LLVM.getelementptr(ptr, n, elem_type: elem_type, rawConstantIndices: ~a{array} diff --git a/lib/charms/prelude.ex b/lib/charms/prelude.ex index 15fa26d..4867adc 100644 --- a/lib/charms/prelude.ex +++ b/lib/charms/prelude.ex @@ -7,8 +7,8 @@ defmodule Charms.Prelude do alias Beaver.MLIR.Dialect.{Arith, Func} @enif_functions Beaver.ENIF.functions() - defp wrap_arg({i, t}, %Opts{ctx: ctx, block: block}) when is_integer(i) do - mlir ctx: ctx, block: block do + defp wrap_arg({i, t}, %Opts{ctx: ctx, blk: blk}) when is_integer(i) do + mlir ctx: ctx, blk: blk do case i do %MLIR.Value{} -> i @@ -59,11 +59,11 @@ defmodule Charms.Prelude do args = Macro.generate_arguments(length(arg_types), __MODULE__) defintrinsic unquote(name)(unquote_splicing(args)) do - opts = %Opts{ctx: ctx, block: block, loc: loc} = __IR__ + opts = %Opts{ctx: ctx, blk: blk, loc: loc} = __IR__ {arg_types, ret_types} = Beaver.ENIF.signature(ctx, unquote(name)) args = [unquote_splicing(args)] |> Enum.zip(arg_types) |> Enum.map(&wrap_arg(&1, opts)) - mlir ctx: ctx, block: block do + mlir ctx: ctx, blk: blk do Func.call(args, callee: Attribute.flat_symbol_ref("#{unquote(name)}"), loc: loc) >>> case ret_types do [ret] -> diff --git a/lib/charms/simd.ex b/lib/charms/simd.ex index 6e3cad5..2e671dc 100644 --- a/lib/charms/simd.ex +++ b/lib/charms/simd.ex @@ -11,12 +11,12 @@ defmodule Charms.SIMD do Return the constant value of the given `type` and `literal_values` """ defintrinsic new(type, literal_values) do - %Opts{ctx: ctx, block: block} = __IR__ + %Opts{ctx: ctx, blk: blk} = __IR__ - mlir ctx: ctx, block: block do + mlir ctx: ctx, blk: blk do element_type = MLIR.CAPI.mlirShapedTypeGetElementType(type) - if MLIR.is_null(element_type) do + if MLIR.null?(element_type) do raise "element type is null" end diff --git a/mix.exs b/mix.exs index ebb7290..2500f36 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule Charms.MixProject do def project do [ app: :charms, - version: "0.1.2-dev", + version: "0.1.3-dev", elixir: "~> 1.17", start_permanent: Mix.env() == :prod, elixirc_paths: elixirc_paths(Mix.env()), @@ -30,7 +30,7 @@ defmodule Charms.MixProject do def application do [ mod: {Charms.Application, []}, - extra_applications: [:logger] + extra_applications: [:logger, :beaver] ] end @@ -75,7 +75,7 @@ defmodule Charms.MixProject do defp deps do [ {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, - {:beaver, "~> 0.3.10"}, + {:beaver, "~> 0.4.0"}, {:benchee, "~> 1.0", only: :dev}, {:credo, "~> 1.7", only: [:dev, :test], runtime: false} ] diff --git a/mix.lock b/mix.lock index b2487f4..aeaface 100644 --- a/mix.lock +++ b/mix.lock @@ -1,18 +1,18 @@ %{ - "beaver": {:hex, :beaver, "0.3.10", "cc897feead5bfdd243dd84a8cea73829e2f8053ccc59b05396abf9682a7effeb", [:mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kinda, "~> 0.9.2", [hex: :kinda, repo: "hexpm", optional: false]}], "hexpm", "659d889d9e6244b0e35ea6481ea1ac5ad1ea2eef6496f111e6a1ab4a61b57901"}, + "beaver": {:hex, :beaver, "0.4.0", "82014114c6c54efd6583ec4dbd8df6b7c9559ee190fcd6a2658dd688c2e8da63", [:mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kinda, "~> 0.9.3", [hex: :kinda, repo: "hexpm", optional: false]}], "hexpm", "2e336f4ab2f7088562943bb153ee981baca5156c3e429066d563734193761a18"}, "benchee": {:hex, :benchee, "1.3.1", "c786e6a76321121a44229dde3988fc772bca73ea75170a73fd5f4ddf1af95ccf", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "76224c58ea1d0391c8309a8ecbfe27d71062878f59bd41a390266bf4ac1cc56d"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, - "credo": {:hex, :credo, "1.7.8", "9722ba1681e973025908d542ec3d95db5f9c549251ba5b028e251ad8c24ab8c5", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cb9e87cc64f152f3ed1c6e325e7b894dea8f5ef2e41123bd864e3cd5ceb44968"}, + "credo": {:hex, :credo, "1.7.10", "6e64fe59be8da5e30a1b96273b247b5cf1cc9e336b5fd66302a64b25749ad44d", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "71fbc9a6b8be21d993deca85bf151df023a3097b01e09a2809d460348561d8cd"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"}, - "elixir_make": {:hex, :elixir_make, "0.8.4", "4960a03ce79081dee8fe119d80ad372c4e7badb84c493cc75983f9d3bc8bde0f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "6e7f1d619b5f61dfabd0a20aa268e575572b542ac31723293a4c1a567d5ef040"}, - "ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"}, + "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, + "ex_doc": {:hex, :ex_doc, "0.35.1", "de804c590d3df2d9d5b8aec77d758b00c814b356119b3d4455e4b8a8687aecaf", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "2121c6402c8d44b05622677b761371a759143b958c6c19f6558ff64d0aed40df"}, "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, - "kinda": {:hex, :kinda, "0.9.2", "d75aaac76810f50b9db91347034f73e4a305a9a6ba405862f4db7342793e265b", [:mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "fd4a8484cd95d6e17de841079466e70ff8d96fe996fbd44bb3d7a6be95ce30ac"}, + "kinda": {:hex, :kinda, "0.9.3", "936e1e7a6e54943b078366319af4de4cce5f2ff2a9462e03187fcf762278f93c", [:mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "6661b01420625474ebe1cbb592e8ea450d6434943c6c04800183ccee62fbfbd7"}, "llvm_config": {:hex, :llvm_config, "0.1.1", "2c4a1e16c51d18528014c35783bc7779cb8b8b0d0ed2a5f3b4d35709a819e492", [:mix], [], "hexpm", "026376818206f1ff91f48946aa0272cac2bae2d00e81916d1275b3f9ca72a7ea"}, - "makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, + "makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"}, + "makeup_elixir": {:hex, :makeup_elixir, "1.0.0", "74bb8348c9b3a51d5c589bf5aebb0466a84b33274150e3b6ece1da45584afc82", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "49159b7d7d999e836bedaf09dcf35ca18b312230cf901b725a64f3f42e407983"}, "makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, "statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"}, diff --git a/test/call_test.exs b/test/call_test.exs index b0b6a05..2675c1f 100644 --- a/test/call_test.exs +++ b/test/call_test.exs @@ -1,29 +1,21 @@ defmodule CallTest do use ExUnit.Case, async: true - import ExUnit.CaptureLog + @tag capture_log: true test "if with value" do file = "test/call_test.exs" line = __ENV__.line + 10 - log = - capture_log(fn -> - assert_raise CompileError, fn -> - defmodule CallingAbsentFunc do - use Charms - alias Charms.{Pointer, Term} + assert_raise CompileError, fn -> + defmodule CallingAbsentFunc do + use Charms + alias Charms.{Pointer, Term} - defm get(env, i) :: Term.t() do - AbsentMod.absent_fun(env, i) - func.return(i) - end - end + defm get(env, i) :: Term.t() do + AbsentMod.absent_fun(env, i) + func.return(i) end - end) - - assert log =~ - "(CompileError) #{file}:#{line}: Unknown invocation: AbsentMod.absent_fun/2" - - assert log =~ "#{file}:#{line}" + end + end end end diff --git a/test/expander_test.exs b/test/expander_test.exs index 0575180..de36914 100644 --- a/test/expander_test.exs +++ b/test/expander_test.exs @@ -55,9 +55,9 @@ defmodule POCTest do test "vars" do assert vars("var = 123") == [var: nil] - assert catch_error(vars("^var = 123") == []) == %Beaver.EnvNotFoundError{ - message: "no valid Beaver.MLIR.Block in the environment" - } + assert_raise CompileError, + ~r"Expected a block, got: ", + fn -> vars("^var = 123") == [] end end test "remotes" do @@ -135,7 +135,7 @@ defmodule POCTest do end |> compile() |> tap(fn ir -> assert to_string(ir) =~ "@Elixir.ReturnPassedArg" end) - |> MLIR.Operation.verify!() + |> MLIR.verify!() |> tap(fn m -> {_key, %Charms.JIT{}} = Charms.JIT.init(m, name: :return_this) engine = Charms.JIT.engine(:return_this) @@ -161,7 +161,7 @@ defmodule POCTest do |> tap(fn m -> assert to_string(m) =~ "Unknown invocation: Foo.bar/1" end) - |> MLIR.Operation.verify!() + |> MLIR.verify!() end test "op not found" do