Commit graph

1831 commits

Author SHA1 Message Date
Brian Carroll
040b8ce430 Reduce code size for Union refcount procedures 2022-01-06 10:49:34 +00:00
Brian Carroll
d9cc3c5692 Modify refcount of contents *before* structure to prevent use-after-free 2022-01-06 10:49:34 +00:00
Brian Carroll
456bda0895 Prevent confusion between separate instances of RecursivePointer 2022-01-06 10:49:34 +00:00
Brian Carroll
ad95ea4a3b Remove a debug assert 2022-01-06 10:49:34 +00:00
Brian Carroll
5e642c880c Mask out union tag ID from pointer when calculating refcount address 2022-01-06 10:49:34 +00:00
Brian Carroll
5d7b4018b7 Generate refcounting helper procedures for tag unions 2022-01-05 12:24:04 +00:00
Folkert
fc4cea9f75 don't throw away a jump 2022-01-03 16:50:43 +01:00
Folkert
7044e95df8 fix imported function thunk 2022-01-03 16:18:53 +01:00
Brian Carroll
1de26c084d Make Struct DecRef a no-op 2022-01-01 21:57:28 +00:00
Brian Carroll
98ab97083a For DecRef, remove assumption that the refcounted symbol is ARG_1 2022-01-01 21:57:28 +00:00
Brian Carroll
176bb6f6aa Use joinpoints for DecRef 2022-01-01 21:57:28 +00:00
Brian Carroll
e55806fe27 Update is_rc_implemented_yet 2022-01-01 12:33:36 +00:00
Brian Carroll
8078afc74f Delete a stray println from debug 2022-01-01 11:39:55 +00:00
Brian Carroll
953d82b341 Merge branch 'trunk' of github.com:rtfeldman/roc into wasm-refcount-struct 2022-01-01 11:33:27 +00:00
Brian Carroll
310de090a3 Wasm: Refcounting for struct fields 2022-01-01 11:32:53 +00:00
Brian Carroll
12a330dd76 Refactor to move all refcount IR gen to the same file 2021-12-31 23:09:11 +00:00
Folkert
ee9f0b2f04 force imported thunks when assigned to a variable 2021-12-31 21:44:07 +01:00
Brian Carroll
f767014f30
Merge pull request #2301 from rtfeldman/wasm-refcount-list
Wasm refcounting for lists
2021-12-31 13:25:38 +00:00
Brian Carroll
c5663e3538 Generate IR helper proc for list refcounting 2021-12-30 17:15:31 +00:00
Brian Carroll
59472d3310 Slightly improve pretty printing of inc statement 2021-12-30 09:01:22 +00:00
ayazhafiz
d966d8921f Support nullable wrapped tag union layouts in REPL 2021-12-29 17:55:21 -06:00
Brian Carroll
37de499248 Reorganise code gen helper in roc_mono 2021-12-28 11:03:33 +00:00
Folkert de Vries
249878cbd9
Merge pull request #2281 from rtfeldman/i/2149
(llvm) Generate code for tag unions less than 64 bits in size correctly
2021-12-27 22:38:08 +01:00
Brian Carroll
c67b9e7a6f clippy 2021-12-27 18:11:48 +00:00
Brian Carroll
0285cd88c5 Don't emit tail recursion loop for non-recursive unions 2021-12-27 18:08:43 +00:00
Brian Carroll
0d8a2c8a49 Use tail call elimination where possible in == for tag unions 2021-12-27 18:08:43 +00:00
Brian Carroll
65a9464d98 Replace RecursivePointer todo with unreachable 2021-12-27 18:08:43 +00:00
ayazhafiz
a03f7fa46c Update layout tests 2021-12-26 14:44:43 -06:00
ayazhafiz
c8ba554d8c Clippy warning 2021-12-26 11:58:50 -06:00
ayazhafiz
5e5eb6dca8 (llvm) Generate code for tag unions less than 64 bits in size correctly
Previously, we assumed that a union layout always lived on >= 1 64-bit
boundary when generating an LLVM type for it. For small tags unions,
like `[ Ok i8, Err ]` this need not be the case; indeed, a tag union
like that is actually only 2 bits - 1 bit for the "i8" data, and one bit
of the tag kind.

This led to a discrepancy between what the layout IR and generated LLVM
code would assume about the size of tag unions. In the case above, the
layout IR would assume the tag data is 2 bits wide, and the tag id is 1
bit into the data. But the LLVM code would generate a type that was 65
bits wide, the first 64 bits being for the "i8" data and the last 1 bit
being for the tag kind.

Usually, just running the LLVM-emitted code would not present a problem.
But it does present a problem when we use the layout IR to inspect the
result of LLVM-run code, in particular when we try to look up the tag
ID, as the repl does. This patch fixes that issue.

Note that this bug did not present itself in `test_gen` previously
because the data that most tests check against is stored in the front of
the representation.

Closes #2149
2021-12-26 11:45:02 -06:00
Brian Carroll
e54ce0c975 Ensure procs are in the same order as the Symbols 2021-12-26 10:45:23 +00:00
Brian Carroll
9fb7048de0 Rename rec_ptr_layout -> recursive_union
I kept thinking it was of type Layout but it's not
2021-12-26 10:45:23 +00:00
Brian Carroll
ab7867d233 Separate specializations from procs
This was causing issues with recursive procs.
We need to be able to look up the proc's symbol
before we have finished generating it.
2021-12-26 10:45:23 +00:00
Brian Carroll
d08b79295c Fix unique names 2021-12-26 10:40:45 +00:00
Brian Carroll
da4cf721cc Fix equality on empty structures 2021-12-26 10:40:45 +00:00
Brian Carroll
a0afb64cb0 Fix bug storing linker data for generated procs 2021-12-26 10:40:45 +00:00
Brian Carroll
0fbe49dce9 Shorten some variable names 2021-12-26 10:40:45 +00:00
Brian Carroll
ca501fdcf1 Restructure CodeGenHelp to generate IR immediately, in depth-first traversal 2021-12-26 10:40:45 +00:00
ayazhafiz
1f81a598f7 Presence constraint flag -> Enum 2021-12-23 19:40:18 -06:00
ayazhafiz
b97ff380e3 Presence constraints for tag union types
This work is related to restricting tag union sizes in input positions.
As an example, for something like

```
\x -> when x is
    A M -> X
    A N -> X
    A _ -> X
```

we'd like to infer `[A [M, N]* ]` rather than the `[A, [M, N]* ]*` we
infer today. Notice the difference is that the former type tells us we
only accepts `A`s, but the argument of the `A` can be `M`, `N` or
anything else (hence the `_`).

So what's the idea? It's an encoding of the "must have"/"might have"
design discussed in https://github.com/rtfeldman/roc/issues/1758. Let's
take our example above and walk through unification of each branch.

Suppose `x` starts off as a flex var `t`.

```
\x -> when x is
    A M -> X
```

Now we introduce a new kind of constraint called a "presence"
constraint. It says "t has at least [A [M]]". I'll notate this as `t +=
[A [M]]`. When `t` is free as it is here, this is equivalent to `t ~
[A [M]]`.

```
\x -> when x is
    ...
    A N -> X
```

At this branch we introduce the presence constraint `[A [M]] += [A [N]]`.
Notice that there's two tag unions we care about resolving here - one is
the toplevel one that says "I have an `A ...` inside of me", and the
other one is the tag union that's the tyarg to `A`. They are distinct
and at different depths.

For the toplevel one, we first figure out if the number of tags in the
union needs to expand. It does not - we're hoping to resolve the type
`[A [M, N]]`, which only has `A` in the toplevel union. So, we don't
need to do anything extra there, other than the merge the nested tag
unions.

We recurse on the shared tags, and now we have the presence constraint
`[M] += [N]`. At this point it's important to remember that the left and
right hand types are backed by type variables, so this is really
something like `t11 [M] += t12 [N]`, where `[M]` and `[N]` are just what
we know the variables `t11` and `t12` to be at this moment. So how do we
solve for `t11 [M, N]` from here? Well, we can encode this constraint as
a type variable definition and a unification constraint we already know
how to solve:

```
New definition: t11 [M]a    (a fresh)
New constraint: a ~ t12 [N]
```

That's it; upon unification, `t11 [M, N]` falls out.

Okay, last step.

```
\x -> when x is
    ...
    A _ -> X
```

We now have `[A [M, N]] += [A a]`, where `a` is a fresh unbound
variable. Again nothing has to happen on the toplevel. We walk down and
find `t11 [M, N] += t21 a`. This is actually called an "open constraint"; we
differentiate it at the time we generate constraints because it follows
syntactically from the presence of an `_`, but it's semantically
equivalent to the presence constraint `t11 [M, N] += t21 a`. It's just
called opening because literally the only way `t11 [M, N] += t21 a` can
be true is if we set `t11 a`. Well, actually, we assume `a` is a tag
union, so we just make `t11` the open tag union `[M, N]a`. Since `a` is
unbound, this eventually becomes a wildcard and hence falls out `[M, N]*`.
Also, once we open a tag union with an open constraint, we never close
it again.

That's it. The rest falls out recursively. This gives us a really easy
way to encode these ordering constraints in the unification-based system
we have today with minimal additional intervention. We do have to patch
variables in-place sometimes, and the additive nature of these
constraints feels about out-of-place relative to unification, but it
seems to work well.

Resolves #1758
2021-12-23 19:40:18 -06:00
ayazhafiz
a626214852 Fix use of undeclared symbol
090a8923c5 changed `Located -> Loc`, but
5d7aff373c introduced another instance of
`Located` and didn't have the commit history of 090a8923c5
2021-12-23 17:58:12 -06:00
Folkert de Vries
5f7476d54f
Merge pull request #2266 from rtfeldman/joshuawarner32/loc
Parser refactor: always group (Row, Col) into Position
2021-12-24 00:02:13 +01:00
Folkert de Vries
db44d03e66
Merge pull request #2259 from rtfeldman/i/2227-record-layout-hang
Turn invalid record field types into runtime errors
2021-12-23 20:17:34 +01:00
Joshua Warner
22e2545fd6 format 2021-12-22 20:46:42 -08:00
Joshua Warner
f19220473a Rename Located -> Loc 2021-12-22 19:18:22 -08:00
ayazhafiz
ac54a5e024 Remove nonsene panic 2021-12-22 19:38:10 -06:00
ayazhafiz
ed64ff912a Implement List.dropIf
This was referenced in the `List` documentation and in the
[tutorial](./TUTORIAL.md), but wasn't actually implemented prior to this
commit!

Part of #2227
2021-12-22 12:34:48 -06:00
Brian Carroll
d33c1b54fd Ensure unique names for helper procs 2021-12-22 09:28:20 +00:00
Brian Carroll
4a970f089a Eq for empty list 2021-12-22 09:22:31 +00:00
Brian Carroll
e9ae8452b0 Equality tests passing for List I64 2021-12-22 08:42:39 +00:00