Commit graph

7453 commits

Author SHA1 Message Date
ayazhafiz
ae104c3791 Elide unnecessary lifetimes 2022-01-19 23:16:48 -05:00
ayazhafiz
a5de224626 Specialize polymorphic non-function expressions
This commit fixes a long-standing bug wherein bindings to polymorphic,
non-function expressions would be lowered at binding site, rather than
being specialized at the call site.

Concretely, consider the program

```
main =
    n = 1

    idU8 : U8 -> U8
    idU8 = \m -> m

    idU8 n
```

Prior to this commit, we would lower `n = 1` as part of the IR, and the
`n` at the call site `idU8 n` would reference the lowered definition.
However, at the definition site, `1` has the polymorphic type `Num *` -
it is not until the the call site that we are able to refine the type
bound by `n`, but at that point it's too late. Since the default layout
for `Num *` is a signed 64-bit int, we would generate IR like

```
procedure main():
    let App.n : Builtin(Int(I64)) = 1i64;
    ...
    let App.5 : Builtin(Int(U8)) = CallByName Add.idU8 App.n;
    ret App.5;
```

But we know `idU8` expects a `u8`; giving it an `i64` is nonsense.
Indeed this would trigger LLVM miscompilations later on.

To remedy this, we now keep a sidecar table that maps symbols to the
polymorphic expression they reference, when they do so. We then
specialize references to symbols on the fly at usage sites, similar to
how we specialize function usages.

Looking at our example, the definition `n = 1` is now never lowered to
the IR directly. We only generate code for `1` at each place `n` is
referenced. As a larger example, you can imagine that

```
main =
    n = 1

    asU8 : U8 -> U8
    asU32 : U32 -> U8

    asU8 n + asU32 n
```

is lowered to the moral equivalent of

```
main =
    asU8 : U8 -> U8
    asU32 : U32 -> U8

    asU8 1 + asU32 1
```

Moreover, transient usages of polymorphic expressions are lowered
successfully with this approach. See for example the
`monomorphized_tag_with_polymorphic_arg_and_monomorphic_arg` test in
this commit, which checks that

```
main =
    mono : U8
    mono = 15
    poly = A
    wrap = Wrapped poly mono

    useWrap1 : [Wrapped [A] U8, Other] -> U8
    useWrap1 =
        \w -> when w is
            Wrapped A n -> n
            Other -> 0

    useWrap2 : [Wrapped [A, B] U8] -> U8
    useWrap2 =
        \w -> when w is
            Wrapped A n -> n
            Wrapped B _ -> 0

    useWrap1 wrap * useWrap2 wrap
```

has proper code generated for it, in the presence of the polymorphic
`wrap` which references the polymorphic `poly`.

https://github.com/rtfeldman/roc/pull/2347 had a different approach to
this - polymorphic expressions would be converted to (possibly capturing) thunks.
This has the benefit of reducing code size if there are many polymorphic
usages, but may make the generated code slower and makes integration
with the existing IR implementation harder. In practice I think the
average number of polymorphic usages of an expression will be very
small.

Closes https://github.com/rtfeldman/roc/issues/2336
Closes https://github.com/rtfeldman/roc/issues/2254
Closes https://github.com/rtfeldman/roc/issues/2344
2022-01-19 22:52:15 -05:00
ayazhafiz
3342090e7b Add var_contains_content conditional function to Subs
This function checks for the existence of a content of a certain shape
on a content, or any its deep children.
2022-01-19 22:51:15 -05:00
Folkert
202a8438ce change UserApp -> Test in mono tests 2022-01-19 23:22:19 +01:00
Folkert
72e883a20b make symbol debug formatting consistent 2022-01-19 23:21:18 +01:00
Folkert
ee4c2177c0 add annotation for Effect.loop 2022-01-19 23:13:34 +01:00
Folkert
5230c6f6f3 implement Effect.loop 2022-01-19 23:06:32 +01:00
Folkert
2adcbecf8a update mono tests 2022-01-19 21:01:18 +01:00
Folkert
fbab19a937 custom debug instance for LambdaSet
so that symbols are printed as their numbers; makes mono tests reliable
2022-01-19 20:57:36 +01:00
Folkert
859bdf5212 Merge remote-tracking branch 'origin/trunk' into effect-forever 2022-01-19 20:14:24 +01:00
Folkert
4c445f9f24 recognize functions that become tail-recursive after closure conversion 2022-01-19 20:09:20 +01:00
Folkert
389681ee90 return forall b. Effect b 2022-01-19 19:19:43 +01:00
Folkert
359956220e working definition of Effect.forever 2022-01-19 19:11:37 +01:00
Jan Van Bruggen
8e4b6f0cab Remove Num.(min/max)Int
Replace all uses with `Num.(min/max)I64`,
since all uses expect an `I64`.
2022-01-19 09:55:06 -07:00
Jan Van Bruggen
fb66467343 Remove trailing spaces from test snapshots 2022-01-18 22:33:24 -07:00
Jan Van Bruggen
1e9d2d1239 Remove accidental trailing spaces 2022-01-18 22:25:46 -07:00
Jan Van Bruggen
93d65a1601 Remove leftover TODOs 2022-01-17 18:53:36 -07:00
Jan Van Bruggen
591477e77b Add most remaining Num.min/max* builtins
This skips `min/maxU128`, as they require a subtle change
to the `I128`-centric implementation of `Int`s.
2022-01-17 15:26:23 -07:00
Jan Van Bruggen
865dcd5507 Expose existing Num.min/max builtin docs 2022-01-17 13:17:03 -07:00
Jan Van Bruggen
cdf705941e Improve Num.min/max docstrings 2022-01-17 13:17:03 -07:00
Jan Van Bruggen
79241adf8e Reorder Num.min/max docs 2022-01-17 13:17:03 -07:00
Anton-4
a6537683a1
Merge pull request #2355 from rtfeldman/fix-lint-error
Fix a lint error by simplifying an if/else block
2022-01-17 12:49:57 +01:00
Brian Carroll
f354b4842b Wasm: Move Eq/NotEq into LowLevelCall 2022-01-17 09:35:08 +00:00
Brian Carroll
f635dd8776 Wasm: Refactor lowlevels to get more flexibility without increasing boilerplate. 2022-01-17 09:33:06 +00:00
Brian Carroll
88b779c3ff Wasm: Create CodeGenNumber 2022-01-17 09:33:06 +00:00
Brian Carroll
05a6a9c7ce Wasm: update comments on lowlevels 2022-01-17 09:33:06 +00:00
Chelsea Troy
085c02ffee Infrastructure to test and implement the replacement of an 'expect' failure with an error production
Last command run was 'cargo test expect_fail'
2022-01-16 22:01:22 -06:00
Richard Feldman
cff861ddd4
Merge pull request #2352 from rtfeldman/wasm-move-methods-around
Wasm: Reorganise Stmt and Expr methods
2022-01-16 22:38:52 -05:00
Richard Feldman
2ade76b373
Merge pull request #2354 from rtfeldman/add_builtin_Num.minI128
Add `Num.minI128` builtin
2022-01-16 22:38:27 -05:00
Folkert
be14dd4954 write big comment on why this _should_ work 2022-01-17 00:11:58 +01:00
Folkert
697a65e77c builtins can use builtins now 2022-01-16 22:28:36 +01:00
Jan Van Bruggen
c1dc0226f6 Fix a lint error by simplifying an if/else block
From `cargo clippy -- -D warnings`:
```
error: all if blocks contain the same code at the start
   --> compiler/gen_wasm/src/wasm_module/sections.rs:478:9
    |
478 | /         if bytes[*cursor] == 0 {
479 | |             u8::skip_bytes(bytes, cursor);
480 | |             u32::skip_bytes(bytes, cursor);
    | |___________________________________________^
    |
    = note: `-D clippy::branches-sharing-code` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code
help: consider moving the start statements out like this
    |
478 ~         u8::skip_bytes(bytes, cursor);
479 +         u32::skip_bytes(bytes, cursor);
480 +         if bytes[*cursor] == 0 {
    |

error: could not compile `roc_gen_wasm` due to previous error
warning: build failed, waiting for other jobs to finish...
error: build failed
```
2022-01-16 06:14:10 -07:00
Jan Van Bruggen
a61b8e402c
Fix directory name typo 2022-01-15 18:37:07 -07:00
Jan Van Bruggen
d7e2be306f WIP: Add Num.minI128 builtin (TODOs remain) 2022-01-15 17:49:15 -07:00
Jan Van Bruggen
d2c2064782 Add missing Num.maxI128 docs 2022-01-15 17:49:02 -07:00
Brian Carroll
5e68f298df Wasm: Reorganise Stmt and Expr methods 2022-01-15 15:53:41 +00:00
Brian Carroll
6bdc27a49e Wasm: Use Vec instead of MutSet for called preloads 2022-01-15 15:35:42 +00:00
Brian Carroll
f4650654ca Wasm: cosmetic changes to fake WASI functions 2022-01-15 15:35:42 +00:00
Brian Carroll
94ea50f56a Wasm: Clarify some more magic numbers 2022-01-15 15:35:42 +00:00
Brian Carroll
9290d3ad5c Wasm: Clarify where magic constant 5 comes from 2022-01-15 15:35:42 +00:00
Brian Carroll
e37ca971bd Wasm: Simplify CodeBuilder serialization, based on Richard's suggestion 2022-01-15 15:35:37 +00:00
Brian Carroll
54e820620a Wasm: Improve a todo in roc_build 2022-01-15 14:34:06 +00:00
Brian Carroll
8c4fd93b07 Wasm: Remove old debug code that's never used. We have the HTML debugger now. 2022-01-15 13:27:34 +00:00
Brian Carroll
8d5a1cb661 Wasm: Replace _ todo with RuntimeError todo 2022-01-15 13:27:34 +00:00
Brian Carroll
c38134bdc0 Wasm: remove legacy unused ret_layout 2022-01-15 13:27:34 +00:00
Brian Carroll
bafb6e54d0 Wasm: Change panic for literals todo -> internal_error 2022-01-15 13:27:34 +00:00
Brian Carroll
91a0b21e70 Wasm: Get rid of some Backend compatibility code 2022-01-15 13:27:34 +00:00
Brian Carroll
f4137013cb Wasm: tweaks from self-review 2022-01-14 18:50:52 +00:00
Brian Carroll
c5134fa015 Wasm: rename DeadCodeMetadata to PreloadsCallGraph 2022-01-14 18:37:52 +00:00
Brian Carroll
4311b5a410 Wasm: Make dead functions unreachable, and the same for all return types 2022-01-14 18:21:13 +00:00