mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
(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
This commit is contained in:
parent
f314abfed9
commit
5e5eb6dca8
4 changed files with 54 additions and 40 deletions
|
@ -246,14 +246,18 @@ fn block_of_memory_help(context: &Context, union_size: u32) -> BasicTypeEnum<'_>
|
|||
let num_i64 = union_size / 8;
|
||||
let num_i8 = union_size % 8;
|
||||
|
||||
let i8_array_type = context.i8_type().array_type(num_i8).as_basic_type_enum();
|
||||
let i64_array_type = context.i64_type().array_type(num_i64).as_basic_type_enum();
|
||||
|
||||
if num_i8 == 0 {
|
||||
// the object fits perfectly in some number of i64's
|
||||
if num_i64 == 0 {
|
||||
// The object fits perfectly in some number of i8s
|
||||
context.struct_type(&[i8_array_type], false).into()
|
||||
} else if num_i8 == 0 {
|
||||
// The object fits perfectly in some number of i64s
|
||||
// (i.e. the size is a multiple of 8 bytes)
|
||||
context.struct_type(&[i64_array_type], false).into()
|
||||
} else {
|
||||
// there are some trailing bytes at the end
|
||||
// There are some trailing bytes at the end
|
||||
let i8_array_type = context.i8_type().array_type(num_i8).as_basic_type_enum();
|
||||
|
||||
context
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue