mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
add new union creation
This commit is contained in:
parent
f8e12da809
commit
28ec18c564
3 changed files with 67 additions and 2 deletions
|
@ -982,6 +982,17 @@ impl<
|
|||
.load_union_tag_id(&mut self.buf, sym, structure, union_layout);
|
||||
}
|
||||
|
||||
fn tag(
|
||||
&mut self,
|
||||
sym: &Symbol,
|
||||
fields: &'a [Symbol],
|
||||
union_layout: &UnionLayout<'a>,
|
||||
tag_id: TagIdIntType,
|
||||
) {
|
||||
self.storage_manager
|
||||
.create_union(&mut self.buf, sym, union_layout, fields, tag_id)
|
||||
}
|
||||
|
||||
fn load_literal(&mut self, sym: &Symbol, layout: &Layout<'a>, lit: &Literal<'a>) {
|
||||
match (lit, layout) {
|
||||
(
|
||||
|
|
|
@ -10,7 +10,7 @@ use roc_error_macros::internal_error;
|
|||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::{
|
||||
ir::{JoinPointId, Param},
|
||||
layout::{Builtin, Layout, UnionLayout},
|
||||
layout::{Builtin, Layout, TagIdIntType, UnionLayout},
|
||||
};
|
||||
use roc_target::TargetInfo;
|
||||
use std::cmp::max;
|
||||
|
@ -655,6 +655,42 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a union on the stack, moving the data in fields into the union and tagging it.
|
||||
pub fn create_union(
|
||||
&mut self,
|
||||
buf: &mut Vec<'a, u8>,
|
||||
sym: &Symbol,
|
||||
union_layout: &UnionLayout<'a>,
|
||||
fields: &'a [Symbol],
|
||||
tag_id: TagIdIntType,
|
||||
) {
|
||||
match union_layout {
|
||||
UnionLayout::NonRecursive(field_layouts) => {
|
||||
let (data_size, data_alignment) =
|
||||
union_layout.data_size_and_alignment(self.target_info);
|
||||
let id_offset = data_size - data_alignment;
|
||||
if data_alignment < 8 || data_alignment % 8 != 0 {
|
||||
todo!("small/unaligned tagging");
|
||||
}
|
||||
let base_offset = self.claim_stack_area(sym, data_size);
|
||||
let mut current_offset = base_offset;
|
||||
for (field, field_layout) in
|
||||
fields.iter().zip(field_layouts[tag_id as usize].iter())
|
||||
{
|
||||
self.copy_symbol_to_stack_offset(buf, current_offset, field, field_layout);
|
||||
let field_size = field_layout.stack_size(self.target_info);
|
||||
current_offset += field_size as i32;
|
||||
}
|
||||
self.with_tmp_general_reg(buf, |_symbol_storage, buf, reg| {
|
||||
ASM::mov_reg64_imm64(buf, reg, tag_id as i64);
|
||||
debug_assert!((base_offset + id_offset as i32) % 8 == 0);
|
||||
ASM::mov_base32_reg64(buf, base_offset + id_offset as i32, reg);
|
||||
});
|
||||
}
|
||||
x => todo!("creating unions with layout: {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies a complex symbol ot the stack to the arg pointer.
|
||||
pub fn copy_symbol_to_arg_pionter(
|
||||
&mut self,
|
||||
|
@ -678,7 +714,7 @@ impl<
|
|||
/// The offset is not guarenteed to be perfectly aligned, it follows Roc's alignment plan.
|
||||
/// This means that, for example 2 I32s might be back to back on the stack.
|
||||
/// Always interact with the stack using aligned 64bit movement.
|
||||
fn copy_symbol_to_stack_offset(
|
||||
pub fn copy_symbol_to_stack_offset(
|
||||
&mut self,
|
||||
buf: &mut Vec<'a, u8>,
|
||||
to_offset: i32,
|
||||
|
@ -705,6 +741,7 @@ impl<
|
|||
ASM::mov_base32_reg64(buf, to_offset + 8, reg);
|
||||
});
|
||||
}
|
||||
_ if layout.stack_size(self.target_info) == 0 => {}
|
||||
_ if layout.safe_to_memcpy() => {
|
||||
let (from_offset, size) = self.stack_offset_and_size(sym);
|
||||
debug_assert!(from_offset % 8 == 0);
|
||||
|
|
|
@ -329,6 +329,14 @@ trait Backend<'a> {
|
|||
} => {
|
||||
self.get_tag_id(sym, structure, union_layout);
|
||||
}
|
||||
Expr::Tag {
|
||||
tag_layout,
|
||||
tag_id,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
self.tag(sym, &arguments, tag_layout, *tag_id);
|
||||
}
|
||||
x => todo!("the expression, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
@ -767,6 +775,15 @@ trait Backend<'a> {
|
|||
/// get_tag_id loads the tag id from a the union.
|
||||
fn get_tag_id(&mut self, sym: &Symbol, structure: &Symbol, union_layout: &UnionLayout<'a>);
|
||||
|
||||
/// tag sets the tag for a union.
|
||||
fn tag(
|
||||
&mut self,
|
||||
sym: &Symbol,
|
||||
args: &'a [Symbol],
|
||||
tag_layout: &UnionLayout<'a>,
|
||||
tag_id: TagIdIntType,
|
||||
);
|
||||
|
||||
/// return_symbol moves a symbol to the correct return location for the backend and adds a jump to the end of the function.
|
||||
fn return_symbol(&mut self, sym: &Symbol, layout: &Layout<'a>);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue