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

Translate types only as needed #71

Closed
jameysharp opened this issue Sep 23, 2016 · 1 comment
Closed

Translate types only as needed #71

jameysharp opened this issue Sep 23, 2016 · 1 comment

Comments

@jameysharp
Copy link
Owner

Standard C system headers have a bazillion declarations in them, most of which are not used by any given translation unit. So it's unfortunate when Corrode fails to translate a declaration and gives up, if just skipping that declaration would have led to correct output for a particular translation unit.

I'd like to solve this by making baseTypeOf defer most of the work it currently does. For each declared type, it should save just enough information that we can recognize whether the type is used later. We shouldn't check whether we know how to translate the type until its first use.

Doing this correctly means that when a type is first used, translating it may trigger the first use of other types. The translator must not go into an infinite loop if a type references itself, directly or indirectly.

extern declarations need to be similarly lazy. An extern declaration should only force the types it uses to be inspected if the declaration is used.

Would be nice: Distinguish between using a pointer to a type versus using the type itself. If all uses of a type are behind pointers, then we can translate the type as an unconstructable enum, like we currently do for union, because the pointer representation doesn't depend on the type it points to. In that case we should not report any error even if the type is one we can't translate. If, on the other hand, a struct or union ever has its fields accessed or is copied, or a C enum has its values used, then we need to translate the type. So this generalizes the special-case treatment we currently give union.

@jameysharp
Copy link
Owner Author

I almost have this working! Remaining issues:

  • Sometimes it's too lazy and doesn't output a struct declaration that it should have.
  • Anonymous types get emitted once for each use, with different names. (That's no good.)
  • Translation would probably infinite-loop right now if a type references itself. (That's bad.)
  • The code is a mess now, so I either need to figure out how to simplify it, or write documentation explaining it.
    • enum declarations and incomplete types are not yet emitted the new way, so there are two independent ways to emit types.
  • I haven't done the "would be nice" part yet.

jameysharp added a commit that referenced this issue Oct 15, 2016
This is somewhat more efficient since it avoids an extra list traversal
per symbol lookup, and some other redundant work per use of an extern
symbol...

But more importantly, it'll be easier to ensure that anonymous types are
translated consistently under the lazy translation plan of #71 if we can
be sure they're translated only once and memoized.

This also establishes the infrastructure for carefully managed mutable
state. Rust enthusiasts should appreciate that.
jameysharp added a commit that referenced this issue Oct 16, 2016
My previous commit, for issue #71, wasn't lazy enough. A declaration
like this would lead to infinite recursion:

```c
struct S {
    void (*f)(struct S *);
} v;
```
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

No branches or pull requests

1 participant