Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use __IR__ in defintrinsic #49

Merged
merged 1 commit into from
Nov 30, 2024

Conversation

jackalcooper
Copy link
Contributor

@jackalcooper jackalcooper commented Nov 28, 2024

Summary by CodeRabbit

  • New Features

    • Improved macro expansion handling with enhanced error messages and type validation.
    • Streamlined intrinsic function definitions by simplifying parameter handling.
    • Introduced a new dump function for outputting MLIR entities at compile time.
  • Bug Fixes

    • Enhanced error reporting for unsupported types and failed expansions.
  • Refactor

    • Removed pattern matching for options in function signatures, improving readability and maintainability.
    • Centralized context extraction for intrinsic functions.

These changes enhance the clarity, robustness, and usability of the module, ensuring a smoother experience for end-users.

Copy link
Contributor

coderabbitai bot commented Nov 28, 2024

Walkthrough

The pull request introduces significant modifications across multiple modules in the Charms library, primarily focusing on the defintrinsic function and related macro functionalities. Key changes include the removal of the uniq_mlir_params/2 function in Charms.Defm.Expander, updates to function signatures to extract context from __IR__ instead of directly using the Opts struct, and enhancements in error handling during macro expansion. These changes streamline function definitions and improve the clarity of the code while maintaining the core functionalities of the modules involved.

Changes

File Change Summary
lib/charms/defm/expander.ex Removed uniq_mlir_params/2; updated expand_macro/5 to check for intrinsic implementation; modified expand_if_clause_body/2 and expand_call_as_op/5 for clarity and validation; enhanced error handling for empty blocks.
lib/charms/env.ex Updated defintrinsic to extract context from __IR__ instead of function parameters; altered function signature accordingly.
lib/charms/intrinsic.ex Simplified defintrinsic macro by removing opts parameter; updated internal logic for handling options and transformations; modified Opts struct.
lib/charms/kernel.ex Modified defintrinsic definitions to streamline option handling by extracting from __IR__; refined function signatures for clarity.
lib/charms/pointer.ex Removed pattern matching on Opts in multiple intrinsic functions; replaced with direct extraction from __IR__ for cleaner function signatures.
lib/charms/prelude.ex Updated defintrinsic signatures for result_at and type_of to remove explicit argument pattern matching; streamlined argument handling using __IR__.
lib/charms/simd.ex Simplified new and t function signatures by removing %Opts{}; extracted options from __IR__ within function bodies.
lib/charms/term.ex Changed defintrinsic t() to extract context from __IR__, simplifying the function signature and maintaining existing functionality.
test/defm_test.exs Added new test case "dump" to DefmTest using capture_io to assert output from DumpTerm; included definition of DumpTerm module.

Possibly related PRs

🐇 In the land of charms where macros play,
A new function sprouted, brightening the day.
With clearer paths and types in sight,
Errors now vanish, all feels just right.
So hop along, dear friends, let's cheer,
For the magic of code brings us near! 🎉


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (9)
lib/charms/env.ex (1)

8-9: LGTM! Good refactoring of context handling.

The change improves code organization by moving the pattern matching from the function signature to the function body. This is consistent with similar changes across other modules and makes the function signature cleaner while maintaining the same functionality.

This pattern of using __IR__ for context access provides better separation of concerns and makes the module's interface simpler and more maintainable.

lib/charms/term.ex (1)

11-12: LGTM! Clean refactoring of context handling.

The change simplifies the function signature while maintaining functionality by extracting the context from __IR__. This aligns with the standardization of context handling across other modules in the codebase.

This refactoring improves the module's design by:

  • Reducing function signature complexity
  • Standardizing how context is accessed across intrinsic functions
  • Maintaining a clear separation between the public API and internal implementation details
lib/charms/simd.ex (2)

13-19: LGTM! Consider using more descriptive parameter names.

The switch to __IR__ extraction is well-implemented and maintains all necessary context. However, since the parameters are unused (prefixed with _), consider naming them to match their extracted counterparts for better code readability.

-  defintrinsic new(_type, _literal_values) do
+  defintrinsic new(type_param, literal_values_param) do

46-48: LGTM! Maintain consistent parameter naming style.

The __IR__ extraction is cleanly implemented. For consistency with the suggested changes in the new function, consider using meaningful parameter names here as well.

-  defintrinsic t(_type, _width) do
+  defintrinsic t(type_param, width_param) do
lib/charms/prelude.ex (1)

Line range hint 53-67: Consider more robust pattern matching for __IR__.

The current implementation combines extraction and destructuring of opts which could make debugging harder if __IR__ doesn't contain the expected fields. Consider splitting this into separate pattern matching steps:

- opts = %Opts{args: args, ctx: ctx, block: block, loc: loc} = __IR__
+ opts = __IR__
+ %Opts{args: args, ctx: ctx, block: block, loc: loc} = opts

This change would:

  1. Make it clearer where pattern matching failures occur
  2. Improve error messages in case of missing fields
  3. Make the code more maintainable
lib/charms/pointer.ex (2)

70-76: Fix indentation for consistency

While the extraction of values from __IR__ is correct, the indentation of the pattern match is inconsistent with the module's style.

 defintrinsic element_ptr(_elem_type, _ptr, _n) do
-    %Opts{
-      ctx: ctx,
-      block: block,
-      args: [elem_type, ptr, n]
-    } = __IR__
+  %Opts{
+    ctx: ctx,
+    block: block,
+    args: [elem_type, ptr, n]
+  } = __IR__

Line range hint 23-89: Consider documenting the __IR__ pattern

The transition to using __IR__ for context and argument extraction appears to be part of a larger refactoring effort. Consider adding documentation about this pattern in the module's documentation or in a central place, as it seems to be a fundamental change in how intrinsics are defined.

lib/charms/kernel.ex (1)

89-90: LGTM! Consider improving error handling.

The refactoring to use __IR__ is consistent with the binary operations. However, there are opportunities for improvement:

  1. Make the error message more descriptive by including the actual value:
-      raise ArgumentError, "Not an integer type to negate, unsupported type: #{to_string(t)}"
+      raise ArgumentError, "Cannot negate value of type: #{to_string(t)}. Expected an integer type."
  1. Consider extracting the integer type check into a helper function since it's used in both binary and unary operations:
defp ensure_integer_type!(value, operation) do
  t = MLIR.Value.type(value)
  unless MLIR.CAPI.mlirTypeIsAInteger(t) |> Beaver.Native.to_term() do
    raise ArgumentError, "Cannot perform #{operation} on type: #{to_string(t)}. Expected an integer type."
  end
  t
end
lib/charms/intrinsic.ex (1)

Line range hint 89-97: Enhance the error message for better debugging

The current error message could be more helpful by including information about where intrinsic functions should be used.

Consider this improvement:

-          raise "Intrinsic #{Exception.format_mfa(__MODULE__, unquote(name), arity)} cannot be called outside of a defm body"
+          raise "Intrinsic #{Exception.format_mfa(__MODULE__, unquote(name), arity)} cannot be called outside of a defm body. " <>
+                "Intrinsic functions must be used within Charms.defm blocks for proper IR generation."
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 2d2b2ad and 666634e.

📒 Files selected for processing (8)
  • lib/charms/defm/expander.ex (1 hunks)
  • lib/charms/env.ex (1 hunks)
  • lib/charms/intrinsic.ex (3 hunks)
  • lib/charms/kernel.ex (2 hunks)
  • lib/charms/pointer.ex (3 hunks)
  • lib/charms/prelude.ex (3 hunks)
  • lib/charms/simd.ex (2 hunks)
  • lib/charms/term.ex (1 hunks)
🔇 Additional comments (10)
lib/charms/simd.ex (1)

Line range hint 13-48: Verify consistent pattern usage across modules.

Let's ensure this __IR__ extraction pattern is consistently applied across related modules.

✅ Verification successful

Pattern is consistently applied across all modules

The verification shows that the __IR__ extraction pattern is consistently used across all modules in the codebase:

  • All defintrinsic functions follow the same pattern of extracting values from __IR__ using %Opts{...} = __IR__
  • The pattern is used in multiple modules including term.ex, simd.ex, kernel.ex, prelude.ex, env.ex, and pointer.ex
  • The implementation in the reviewed code follows this established pattern correctly
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent usage of __IR__ extraction pattern in defintrinsic functions

# Search for defintrinsic function definitions and their __IR__ usage
ast-grep --pattern 'defintrinsic $name($$$) do
  $$$
  %Opts{$$$} = __IR__
  $$$
end'

# Look for any remaining direct Opts pattern matching in function signatures
rg "defintrinsic.*%Opts.*do"

Length of output: 118


Script:

#!/bin/bash
# Let's try a different approach to find defintrinsic patterns

# Search for all defintrinsic definitions
rg "^\s*defintrinsic\s+\w+" -A 5

# Also search for __IR__ usage patterns
rg "__IR__" -A 2 -B 2

Length of output: 7045

lib/charms/prelude.ex (2)

Line range hint 30-41: LGTM! Safe implementation with proper bounds checking.

The refactoring to use __IR__ maintains the important bounds checking and detailed error messaging while simplifying the function signature.


42-44: LGTM! Clean and concise implementation.

The refactoring simplifies the function signature while maintaining the core functionality.

lib/charms/pointer.ex (2)

23-25: LGTM: Clean extraction of context and arguments from __IR__

The change aligns with the PR objective and maintains the function's logic while improving the code structure.


88-89: LGTM: Simple and correct context extraction

The change maintains the function's purpose while aligning with the new __IR__ pattern.

lib/charms/kernel.ex (1)

61-63: LGTM! Verify __IR__ availability.

The refactoring to use __IR__ improves the function signature while maintaining the same functionality. However, we should verify that __IR__ is consistently available in this macro context.

✅ Verification successful

__IR__ usage is consistent and verified

The search results confirm that __IR__ is consistently available and properly used across all defintrinsic macro contexts in the codebase:

  • It's used in similar pattern matching with %Opts{} across multiple modules (term.ex, prelude.ex, simd.ex, kernel.ex, pointer.ex, env.ex)
  • The macro infrastructure in intrinsic.ex explicitly handles __IR__ bindings
  • All usages follow the same pattern of extracting context, args, blocks, or location information
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if __IR__ is consistently used across similar contexts
# and verify its availability in macro expansions

# Search for other defintrinsic usages
rg -A 3 "defintrinsic.*do" --type elixir

# Search for __IR__ usage patterns
rg "__IR__" --type elixir

Length of output: 4272

lib/charms/intrinsic.ex (4)

98-108: LGTM! Clean implementation of IR transformation

The postwalk transformation elegantly handles the replacement of __IR__ nodes with the appropriate context reference.


113-113: LGTM! Good pattern matching for early validation

The pattern matching ensures that the required context is available early in the function execution.


83-85: Verify impact of the breaking change in function signature

The removal of the opts parameter from defintrinsic is a breaking change. Please ensure all existing usages have been updated.


38-46: Verify the availability of charms_intrinsic_internal_opts in all macro expansion contexts

The refactoring moves from explicit parameter passing to relying on a module variable. While this simplifies the interface, we should ensure that charms_intrinsic_internal_opts is always properly set before macro expansion.

Let's verify the usage:

lib/charms/defm/expander.ex Show resolved Hide resolved
@jackalcooper jackalcooper force-pushed the use-unhygienic-var-to-make-opts-accessible branch from 666634e to b382726 Compare November 28, 2024 11:42
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (4)
lib/charms/prelude.ex (2)

30-39: LGTM! Consider adding documentation.

The function implementation is correct and type-safe. The error handling is appropriate for out-of-bounds indices.

Consider adding @doc documentation to describe the function's purpose and parameters, similar to the type_of function.

+  @doc """
+  Get the result at the specified index from an MLIR operation.
+  Raises ArgumentError if the index is out of bounds.
+  """
   defintrinsic result_at(%MLIR.Operation{} = op, index) do

48-52: LGTM! Consider enhancing documentation.

The implementation is clean and maintains functional style using tap.

Consider enhancing the documentation to clarify the return value:

   @doc """
   Dump the MLIR entity at compile time with `IO.puts/1`
+  Returns the input entity unchanged, allowing for chaining.
   """
lib/charms/kernel.ex (1)

89-96: Consider enhancing error handling and documentation.

A few suggestions to improve the implementation:

  1. The error message could be more specific about supported integer types
  2. Consider adding documentation to explain that this implements boolean negation via xor

Here's a suggested improvement:

 defintrinsic !value do
   t = MLIR.Value.type(value)

   unless MLIR.CAPI.mlirTypeIsAInteger(t) |> Beaver.Native.to_term() do
-    raise ArgumentError, "Not an integer type to negate, unsupported type: #{to_string(t)}"
+    raise ArgumentError, "Boolean negation requires an integer type (i1, i8, etc), got: #{to_string(t)}"
   end

   quote bind_quoted: [v: value, t: t] do
     one = const 1 :: t
     value arith.xori(v, one) :: t  # Implements boolean negation: result = value XOR 1
   end
 end
test/defm_test.exs (1)

208-220: Consider strengthening the test assertions.

The test could be more robust with these improvements:

  1. Use a more specific regex pattern to avoid false positives
  2. Add assertions to verify the function's return value

Here's a suggested enhancement:

   test "dump" do
+    test_value = 42
     assert capture_io(fn ->
-             defmodule DumpTerm do
-               use Charms
-               alias Charms.Term
-
-               defm d(env, a) :: Term.t() do
-                 dump(a)
-                 func.return(a)
-               end
-             end
-           end) =~ ~r"block argument.+i64"
+             defmodule DumpTerm do
+               use Charms
+               alias Charms.Term
+
+               defm d(env, a) :: Term.t() do
+                 dump(a)
+                 func.return(a)
+               end
+             end
+           end) =~ ~r"block argument 'a' of type 'i64'"
+
+    assert DumpTerm.d(test_value) == test_value
   end
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 666634e and b382726.

📒 Files selected for processing (9)
  • lib/charms/defm/expander.ex (5 hunks)
  • lib/charms/env.ex (1 hunks)
  • lib/charms/intrinsic.ex (4 hunks)
  • lib/charms/kernel.ex (2 hunks)
  • lib/charms/pointer.ex (2 hunks)
  • lib/charms/prelude.ex (2 hunks)
  • lib/charms/simd.ex (2 hunks)
  • lib/charms/term.ex (1 hunks)
  • test/defm_test.exs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • lib/charms/defm/expander.ex
  • lib/charms/env.ex
  • lib/charms/intrinsic.ex
  • lib/charms/simd.ex
  • lib/charms/term.ex
🔇 Additional comments (12)
lib/charms/pointer.ex (6)

15-16: LGTM! Clean implementation using bind_quoted

The change improves code clarity by explicitly binding the elem_type variable in the quoted expression.


52-53: LGTM! Simplified implementation

The change maintains type safety while making the code more concise using bind_quoted.


61-62: LGTM! Consistent with the load implementation

The change follows the same clean pattern as the load function, maintaining consistency in the codebase.


83-86: LGTM! Clean type creation

The t/0 function correctly creates a deferred LLVM pointer type using the context from __IR__.


23-44: Verify type compatibility across MLIR operations

The implementation correctly handles size type conversion to i64, but we should verify that this type is consistently used across other MLIR operations in the codebase.

✅ Verification successful

Let me gather more information about type handling across MLIR operations.


Type handling for size operations is consistent across the codebase

The verification shows that:

  • All size-related operations consistently use i64 type casting through index.casts or arith.extsi
  • Type checking with MLIR.Value.type is properly implemented across the codebase
  • The allocate/2 function's type handling aligns with other size-related operations in lib/charms/defm/expander.ex and test files
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other MLIR operations that might need similar i64 type handling
ast-grep --pattern 'value arith.extsi($_) :: i64()'

Length of output: 125


Script:

#!/bin/bash
# Search for i64 type usage in MLIR operations
rg ":: i64\(\)" -A 2

# Search for other size-related operations
rg "size.*::" -A 2

# Look for MLIR.Value.type usage
ast-grep --pattern 'MLIR.Value.type($_)'

Length of output: 2362


Line range hint 69-77: Verify the hardcoded constant index value

While the MLIR DSL usage is correct, the hardcoded value -2147483648 in rawConstantIndices needs verification:

  1. Is this value intentional?
  2. Should it be parameterized or documented?
lib/charms/prelude.ex (2)

41-46: LGTM! Well-documented and clean implementation.

The function is well-documented and follows the single responsibility principle.


61-64: LGTM! Verify intrinsic function generation.

The changes correctly utilize __IR__ for context and maintain existing functionality while improving code clarity.

Let's verify that all intrinsic functions are properly generated:

✅ Verification successful

LGTM! Intrinsic function generation is correctly implemented.

The verification shows that:

  • The defintrinsic macro is properly used across multiple modules with consistent __IR__ pattern matching
  • In prelude.ex, the dynamic generation of intrinsic functions from @enif_functions correctly:
    • Uses __IR__ to extract context, block, and location
    • Maintains proper signature handling with Beaver.ENIF.signature
    • Wraps arguments consistently using the wrap_arg helper
    • Generates the appropriate MLIR function calls
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all functions in @enif_functions are properly defined
# and that their signatures match the expected pattern using __IR__.

# Search for all defintrinsic function definitions
ast-grep --pattern 'defintrinsic $name($$$) do
  opts = %Opts{$$$} = __IR__
  $$$
end'

Length of output: 88


Script:

#!/bin/bash
# Let's try a different approach to verify the intrinsic function definitions
# First, let's check the content of the prelude.ex file
cat lib/charms/prelude.ex

# As a backup, let's also search for any files containing 'defintrinsic'
rg "defintrinsic" -A 5

Length of output: 8225

lib/charms/kernel.ex (2)

89-90: LGTM! Clean signature refactoring.

The simplified function signature improves readability while maintaining the same functionality.


61-63: LGTM! Clean refactoring to use __IR__.

The change simplifies the function signature while maintaining the same functionality by extracting context from __IR__. This is a good improvement in code clarity.

Let's verify the macro expansion:

✅ Verification successful

Verified: __IR__ macro expansion is correctly implemented

The code changes are safe and correct. The defintrinsic macro properly handles __IR__ by transforming it into var!(charms_intrinsic_internal_opts) during macro expansion, which maintains the same functionality as the previous implementation but with cleaner syntax. The macro ensures that the opts struct with all necessary context (ctx, block, loc) is available to intrinsic implementations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that __IR__ is properly defined in the macro context
ast-grep --pattern 'defmacro defintrinsic($_, $_) do
  $$$
  __IR__
  $$$
end'

Length of output: 80


Script:

#!/bin/bash
# Let's try a broader search for defintrinsic macro definition
ast-grep --pattern 'defmacro defintrinsic'

# Also search for any __IR__ usage in the file
rg "__IR__" --type elixir -C 3

Length of output: 3304


Script:

#!/bin/bash
# Let's check the defintrinsic macro definition in intrinsic.ex
rg "defmacro defintrinsic" -A 10 lib/charms/intrinsic.ex

Length of output: 510


Script:

#!/bin/bash
# Let's see the complete defintrinsic macro implementation to understand how __IR__ is handled
rg "defmacro defintrinsic" -A 30 lib/charms/intrinsic.ex

# Also check for any opts variable setup
rg "var!\(charms_intrinsic_internal_opts\)" -A 5 lib/charms/intrinsic.ex

Length of output: 1641

test/defm_test.exs (2)

44-44: LGTM!

The import statement is correctly placed and necessary for the new test case.


208-220: LGTM! Test structure and implementation are sound.

The test case correctly verifies the output of the dump/1 macro while maintaining proper module structure and function implementation.

@jackalcooper jackalcooper merged commit 6752628 into main Nov 30, 2024
1 check passed
@jackalcooper jackalcooper deleted the use-unhygienic-var-to-make-opts-accessible branch November 30, 2024 12:56
@coderabbitai coderabbitai bot mentioned this pull request Dec 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant