roc-lang / roc

A fast, friendly, functional language.
https://roc-lang.org
Universal Permissive License v1.0
4.4k stars 309 forks source link

Unnecessary padding between tag union payload and discriminant #7171

Open svcxc opened 1 week ago

svcxc commented 1 week ago

In a non-recursive tag union layout, the discriminant deliberately comes after the payload in memory. This is to allow it to be placed in what might otherwise become padding. According to roc glue, this optimization is not currently taking place. Given the following glue platform:

platform "test-platform"
    requires {} { main : _ }
    exposes []
    packages {}
    imports []
    provides [mainForHost]

mainForHost : [A U16 U8, B]
mainForHost = main

The following shape is emitted by the glue platform for mainForHost:

(TagUnion (NonRecursive {discriminantOffset: 4, discriminantSize: 1, ...))

Ideally discriminantOffset should equal 3, as that byte is now unnecessarily used as padding. This bug does not break anything, but it is a missed optimization.

bhansconnect commented 1 week ago

My guess for this issue is that we are representing the union as {payload: {u16, u8}, tag: u8}. This leads to extra padding and is not what we want. We want {u16, u8, u8} where the last u8 in the struct is the tag.