Current section

Files

Jump to
charms lib charms prelude.ex
Raw

lib/charms/prelude.ex

defmodule Charms.Prelude do
@moduledoc """
Intrinsic module to define essential functions provided by Charms.
"""
use Charms.Intrinsic
alias Charms.Intrinsic.Opts
alias Beaver.MLIR.Dialect.{Arith, Func}
@enif_functions Beaver.ENIF.functions()
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
i when is_integer(i) ->
if MLIR.CAPI.mlirTypeIsAInteger(t) |> Beaver.Native.to_term() do
Arith.constant(value: Attribute.integer(t, i)) >>> t
else
raise ArgumentError, "Not an integer type, #{to_string(t)}"
end
end
end
end
defp wrap_arg({v, _}, _) do
v
end
defintrinsic result_at(%MLIR.Operation{} = op, index) do
num_results = MLIR.CAPI.mlirOperationGetNumResults(op)
if index < num_results do
MLIR.CAPI.mlirOperationGetResult(op, index)
else
raise ArgumentError,
"Index #{index} is out of bounds for operation results, num results: #{num_results}"
end
end
@doc """
Get the MLIR type of the given value.
"""
defintrinsic type_of(value) do
MLIR.Value.type(value)
end
@doc """
Dump the MLIR entity at compile time with `IO.puts/1`
"""
defintrinsic dump(entity) do
entity |> tap(&IO.puts(MLIR.to_string(&1)))
end
signature_ctx = MLIR.Context.create()
for name <- @enif_functions do
{arg_types, _} = Beaver.ENIF.signature(signature_ctx, name)
args = Macro.generate_arguments(length(arg_types), __MODULE__)
defintrinsic unquote(name)(unquote_splicing(args)) do
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, blk: blk do
Func.call(args, callee: Attribute.flat_symbol_ref("#{unquote(name)}"), loc: loc) >>>
case ret_types do
[ret] ->
ret
[] ->
[]
end
end
end
end
MLIR.Context.destroy(signature_ctx)
@doc false
def intrinsics() do
@enif_functions ++ [:result_at]
end
end