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

sem/transf: don't collapse implict addr/deref nodes #498

Merged
merged 1 commit into from
Dec 25, 2022

Conversation

zerbina
Copy link
Collaborator

@zerbina zerbina commented Dec 17, 2022

Summary

The collapsing produces unsound AST in the case that the operand of the
nkHiddenDeref doesn't have the same type as the nkHiddenAddr node.
For example, if the nkHiddenDeref dereferences a ptr or ref value,
the collapsing would result in a ptr or ref value to be directly
passed to var parameter (because nkHiddenAddr nodes are generated
when passing something to a var parameter), which is incorrect.

The reason that this didn't cause many problems so far is that var,
ref, and ptr are all pointers underneath for the C target, and that
cgen doesn't inspect the type of nodes in many cases.

The collapsing done directly in semexpr is removed and the one done in
transf is adjusted:

  • only DerefExpr( Addr(x) ) and Addr( DerefExpr(x) ) (both are
    expressions explicitly provided by the user) are collapsed -- the
    latter one only when x is of ptr type.
  • since collapsing HiddenDeref( HiddenAddr(x) ) is always known to be
    safe, the behaviour is kept. Because of a cgen issue, it's currently
    also required.

Unconditional collapsing of all address-of + deref expression is now
performed inside the C code-generator, because it is known that the
operands to all dereference operations map to C pointers at that point.

Details

The compiler targets C89, where dereferencing a pointer requires a
pointer to complete type, even when the result is immediately passed to
an address-of operation (i.e. &(*x)). cgen now requests the complete
type whenever emitting a deref.

Copy link
Collaborator

@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.

Looks good to me. Plenty of comments to understand and improve things over time.

else:
result = c.config.newError(n, reportAst(rsemVarForOutParamNeeded, n))
## Wraps the expression `n` in an ``nkHiddenAddr`` or, if the expression is
## not a mutable lvalue, an ``nkError``
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for documenting it, as well.

let n = result
# collapse ``nkAddr( nkDerefExpr(x) )`` to ``x``, but only if ``x`` is of
# pointer type. Performing the collapsing when ``x`` is a ``ref`` would be
# incorrect, as there'd be a formal vs. actual type mismatch then
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yup

@saem
Copy link
Collaborator

saem commented Dec 18, 2022

Once tests pass let's merge.

@haxscramper haxscramper added refactor Implementation refactor compiler General compiler tag compiler/sem Related to semantic-analysis system of the compiler labels Dec 18, 2022
@haxscramper haxscramper added the compiler/backend Related to backend system of the compiler label Dec 18, 2022
@zerbina zerbina force-pushed the no-addr-collapsing branch 2 times, most recently from e7ae3e5 to 4742dad Compare December 18, 2022 20:44
@zerbina
Copy link
Collaborator Author

zerbina commented Dec 23, 2022

Another detour is needed, it seems. The PR that fixed the JS code-generator issue that was the previous blocker also added a test for arguments to var parameters, which now fails with the VM back-end. This uncovered a large amount of issues with vmgen, so I'm going to fix them first.

## Summary
The collapsing produces unsound AST in the case that the operand of the
`nkHiddenDeref` doesn't have the same type as the `nkHiddenAddr` node.
For example, if the `nkHiddenDeref` dereferences a `ptr` or `ref` value,
the collapsing would result in a `ptr` or `ref` value to be directly
passed to `var` parameter (because `nkHiddenAddr` nodes are generated
when passing something to a `var` parameter), which is incorrect.

The reason that this didn't cause many problems so far is that `var`,
`ref`, and `ptr` are all pointers underneath for the C target, and that
`cgen` doesn't inspect the type of nodes in many cases.

The collapsing done directly in `semexpr` is removed and the one done in
`transf` is adjusted:
- only `DerefExpr( Addr(x) )` and `Addr( DerefExpr(x) )`  (both are
  expressions explicitly provided by the user) are collapsed -- the
  latter one only when `x` is of `ptr` type.
- since collapsing `HiddenDeref( HiddenAddr(x) )` is always known to be
  safe, the behaviour is kept. Because of a `cgen` issue, it's currently
  also required.

Unconditional collapsing of all address-of + deref expression is now
performed inside the C code-generator, because it is known that the
operands to all dereference operations map to C pointers at that point.

## Details
The compiler targets C89, where dereferencing a pointer requires a
pointer to complete type, even when the result is immediately passed to
an address-of operation (i.e. `&(*x)`). `cgen` now requests the complete
type whenever emitting a deref.

`vmgen` depends on the removed collapsing and thus generates
incorrect code in some cases now -- until the code-generator is fixed,
the `tvar_arguments` test is disabled for the VM target.
@zerbina
Copy link
Collaborator Author

zerbina commented Dec 24, 2022

I'm in the process of fixing the mentioned vmgen issues, but the fixes there depend on the nkHiddenAddr/nkHiddenDeref nodes to not be collapsed (which this PR implements).

In order to break the cyclic dependency, I disabled the tvar_arguments test here and am going to merge the vmgen fixes as a follow up.

bors r+

@bors
Copy link
Contributor

bors bot commented Dec 25, 2022

Build succeeded:

@bors bors bot merged commit e6a61ed into nim-works:devel Dec 25, 2022
@zerbina zerbina deleted the no-addr-collapsing branch December 25, 2022 00:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/backend Related to backend system of the compiler compiler/sem Related to semantic-analysis system of the compiler compiler General compiler tag refactor Implementation refactor
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants