mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +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);
|
.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>) {
|
fn load_literal(&mut self, sym: &Symbol, layout: &Layout<'a>, lit: &Literal<'a>) {
|
||||||
match (lit, layout) {
|
match (lit, layout) {
|
||||||
(
|
(
|
||||||
|
|
|
@ -10,7 +10,7 @@ use roc_error_macros::internal_error;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::{
|
use roc_mono::{
|
||||||
ir::{JoinPointId, Param},
|
ir::{JoinPointId, Param},
|
||||||
layout::{Builtin, Layout, UnionLayout},
|
layout::{Builtin, Layout, TagIdIntType, UnionLayout},
|
||||||
};
|
};
|
||||||
use roc_target::TargetInfo;
|
use roc_target::TargetInfo;
|
||||||
use std::cmp::max;
|
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.
|
/// Copies a complex symbol ot the stack to the arg pointer.
|
||||||
pub fn copy_symbol_to_arg_pionter(
|
pub fn copy_symbol_to_arg_pionter(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -678,7 +714,7 @@ impl<
|
||||||
/// The offset is not guarenteed to be perfectly aligned, it follows Roc's alignment plan.
|
/// 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.
|
/// This means that, for example 2 I32s might be back to back on the stack.
|
||||||
/// Always interact with the stack using aligned 64bit movement.
|
/// Always interact with the stack using aligned 64bit movement.
|
||||||
fn copy_symbol_to_stack_offset(
|
pub fn copy_symbol_to_stack_offset(
|
||||||
&mut self,
|
&mut self,
|
||||||
buf: &mut Vec<'a, u8>,
|
buf: &mut Vec<'a, u8>,
|
||||||
to_offset: i32,
|
to_offset: i32,
|
||||||
|
@ -705,6 +741,7 @@ impl<
|
||||||
ASM::mov_base32_reg64(buf, to_offset + 8, reg);
|
ASM::mov_base32_reg64(buf, to_offset + 8, reg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
_ if layout.stack_size(self.target_info) == 0 => {}
|
||||||
_ if layout.safe_to_memcpy() => {
|
_ if layout.safe_to_memcpy() => {
|
||||||
let (from_offset, size) = self.stack_offset_and_size(sym);
|
let (from_offset, size) = self.stack_offset_and_size(sym);
|
||||||
debug_assert!(from_offset % 8 == 0);
|
debug_assert!(from_offset % 8 == 0);
|
||||||
|
|
|
@ -329,6 +329,14 @@ trait Backend<'a> {
|
||||||
} => {
|
} => {
|
||||||
self.get_tag_id(sym, structure, union_layout);
|
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),
|
x => todo!("the expression, {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -767,6 +775,15 @@ trait Backend<'a> {
|
||||||
/// get_tag_id loads the tag id from a the union.
|
/// 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>);
|
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.
|
/// 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>);
|
fn return_symbol(&mut self, sym: &Symbol, layout: &Layout<'a>);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue