Skip to content

Conversation

@zerbina
Copy link
Collaborator

@zerbina zerbina commented May 14, 2025

Summary

Add the LPtr IL providing a dedicated pointer type and an Offset
operation for pointer arithmetic. Higher-level ILs as well as skully
and source2il are changed to use the new Ptr type.

Details

Idea

The idea behind a dedicated pointer type is to:

  1. allow for better static error detection, once type checking for ILs
    is implemented
  2. allow higher-level passes to defer decision making (i.e., regarding
    how a pointer is implemented)
  3. keep the type for code generators that need it

Implementation

  • add the LPtr providing the Ptr type and Nil and Offset
    expression. It extends the L0 IL and is the new basis for the
    L1 IL
  • integrate the new IL and the new ptrToInt pass (LPtr -> L0)
    into the main executable and the REPL
  • update the higher-level ILs to consider Ptr and Nil
  • change the stack allocation pass to emit Offset instead of integer
    arithmetic
  • change the aggregate-related passes, as well as the global-to-pointer
    pass, to use Ptr instead of lowering to UInt
  • update the expected output of the modified existing tests
  • add tests for the new ptrToInt pass

The IL uses a symbolic name (rather than a numeric one) so that the
existing ILs don't have to be renamed.

Usage of Offset is disallowed past the L2 IL for now, so that raw
pointer arithmetic is not exposed to higher-level ILs for now.

Source2IL

  • add an internal-only tkPointer type
  • replace the pointerType constant with using tkPointer directly
  • translate tkPointer and procedure pointers to the IL Ptr type
  • update the hand-written L30 code to not use pointer arithmetic

Skully

  • translate MIR pointer-like types to Ptr
  • use Nil for representing nil pointers
  • adjust the cast translation, which needs to handle pointers no longer
    being arithmetic types

Notes For Reviewers

zerbina added 15 commits May 14, 2025 00:13
It extends the `L0` language and is the basis for the `L1` language.

The `L3` is modified such that the new `Offset` is removed again. While
there's nothing preventing `Offset` from working in the `L3` and above,
it's better if higher-level ILs don't have access to pointer arithmetic
for now.
The pass has to use the `Ptr` type now, making the `ptrSize` parameter
obsolete.
Size and alignment computation for simple types was assuming `Int`,
`UInt`, and `Float` types, but now there's also the `Ptr` type, which
has a different shape.
Same as with the stack allocation pass, `Ptr` has to be used now.
Pointers are no longer arithmetic types in the `L3`, meaning that
`Add` and `Mul` are not applicable anymore.

The pointer size still has to be passed to the pass, as the former is
required for various type size computations.
The size computations need to consider the new `Ptr` type.
The need to manually do this does highlight an issue with the current
system. A better solution would be for there to be some set(s) to which
`Nil` and `Ptr` are added, with processing then looking for items of
that set instead of enumerating all node kinds manually.
It's not exposed to the source language and only meant for internal use
in `source2il`. `source2il` doesn't yet use it, however.
* `tkPointer` and procedure pointers now translate to `Ptr`. This
  requires some adjustments in the hand-written L30 code
* the `pointerType` constant is replaced with using `tkPointer` directly
Aggregate parameter lowering, global lowering, and stack allocation all
emit different code now.
This means:
* translating all MIR pointer-like types to `Ptr`
* adjusting the cast translation, which has to take into account
  pointer types not being numeric/arithmetic type anymore
* using `Nil` instead of zero for representing nil pointers
@zerbina zerbina added enhancement New feature or request refactor labels May 14, 2025
@zerbina zerbina mentioned this pull request May 14, 2025
7 tasks
Copy link
Contributor

@saem saem left a comment

Choose a reason for hiding this comment

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

A couple of minor comments, nothing major.

On the topic of adding pointer and null, I wonder if some of the necessary changes would have been easier to catch with a push towards exhaustive cases?

@zerbina
Copy link
Collaborator Author

zerbina commented May 15, 2025

On the topic of adding pointer and null, I wonder if some of the necessary changes would have been easier to catch with a push towards exhaustive cases?

It would have been, yea, but enumerating all syntax is would be a lot of work, currently.

What's missing is the non-terminals from the IL grammars (e.g., type, path, expr, etc.) being available as sets, which would make using exhaustive case statements a lot more comfortable, overall. This is tricky, however, as the non-terminals (and thus the sets) are different based on which language level one is at.


Relatedly, whatever the experiment with a new IR will yield, one thing it has made obvious to me already is that the hierarchical, inheritance/extension-based language level design should be replaced with a compositional design, where there are atomic language features + capabilities that have dependencies on one another.

@zerbina zerbina merged commit 4138bb6 into nim-works:main May 15, 2025
7 checks passed
@zerbina zerbina deleted the implement-il-ptr branch May 15, 2025 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants