mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
add loading tag for non-recursive union
This commit is contained in:
parent
05959b0622
commit
2307be8f0a
3 changed files with 74 additions and 15 deletions
|
@ -6,7 +6,7 @@ use roc_error_macros::internal_error;
|
||||||
use roc_module::symbol::{Interns, Symbol};
|
use roc_module::symbol::{Interns, Symbol};
|
||||||
use roc_mono::code_gen_help::CodeGenHelp;
|
use roc_mono::code_gen_help::CodeGenHelp;
|
||||||
use roc_mono::ir::{BranchInfo, JoinPointId, Literal, Param, ProcLayout, SelfRecursive, Stmt};
|
use roc_mono::ir::{BranchInfo, JoinPointId, Literal, Param, ProcLayout, SelfRecursive, Stmt};
|
||||||
use roc_mono::layout::{Builtin, Layout};
|
use roc_mono::layout::{Builtin, Layout, UnionLayout};
|
||||||
use roc_target::TargetInfo;
|
use roc_target::TargetInfo;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
@ -870,6 +870,11 @@ impl<
|
||||||
.load_field_at_index(sym, structure, index, field_layouts);
|
.load_field_at_index(sym, structure, index, field_layouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_tag_id(&mut self, sym: &Symbol, structure: &Symbol, union_layout: &UnionLayout<'a>) {
|
||||||
|
self.storage_manager
|
||||||
|
.load_union_tag_id(&mut self.buf, sym, structure, union_layout);
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
(
|
(
|
||||||
|
|
|
@ -9,7 +9,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},
|
layout::{Builtin, Layout, UnionLayout},
|
||||||
};
|
};
|
||||||
use roc_target::TargetInfo;
|
use roc_target::TargetInfo;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
|
@ -522,11 +522,7 @@ impl<
|
||||||
) {
|
) {
|
||||||
debug_assert!(index < field_layouts.len() as u64);
|
debug_assert!(index < field_layouts.len() as u64);
|
||||||
// This must be removed and reinserted for ownership and mutability reasons.
|
// This must be removed and reinserted for ownership and mutability reasons.
|
||||||
let owned_data = if let Some(owned_data) = self.allocation_map.remove(structure) {
|
let owned_data = self.remove_allocation_for_sym(structure);
|
||||||
owned_data
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {}", structure);
|
|
||||||
};
|
|
||||||
self.allocation_map
|
self.allocation_map
|
||||||
.insert(*structure, Rc::clone(&owned_data));
|
.insert(*structure, Rc::clone(&owned_data));
|
||||||
match self.get_storage_for_sym(structure) {
|
match self.get_storage_for_sym(structure) {
|
||||||
|
@ -538,9 +534,9 @@ impl<
|
||||||
data_offset += field_size as i32;
|
data_offset += field_size as i32;
|
||||||
}
|
}
|
||||||
debug_assert!(data_offset < base_offset + size as i32);
|
debug_assert!(data_offset < base_offset + size as i32);
|
||||||
self.allocation_map.insert(*sym, owned_data);
|
|
||||||
let layout = field_layouts[index as usize];
|
let layout = field_layouts[index as usize];
|
||||||
let size = layout.stack_size(self.target_info);
|
let size = layout.stack_size(self.target_info);
|
||||||
|
self.allocation_map.insert(*sym, owned_data);
|
||||||
self.symbol_storage_map.insert(
|
self.symbol_storage_map.insert(
|
||||||
*sym,
|
*sym,
|
||||||
Stack(if is_primitive(&layout) {
|
Stack(if is_primitive(&layout) {
|
||||||
|
@ -565,6 +561,40 @@ impl<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_union_tag_id(
|
||||||
|
&mut self,
|
||||||
|
_buf: &mut Vec<'a, u8>,
|
||||||
|
sym: &Symbol,
|
||||||
|
structure: &Symbol,
|
||||||
|
union_layout: &UnionLayout<'a>,
|
||||||
|
) {
|
||||||
|
// This must be removed and reinserted for ownership and mutability reasons.
|
||||||
|
let owned_data = self.remove_allocation_for_sym(structure);
|
||||||
|
self.allocation_map
|
||||||
|
.insert(*structure, Rc::clone(&owned_data));
|
||||||
|
match union_layout {
|
||||||
|
UnionLayout::NonRecursive(_) => {
|
||||||
|
let (union_offset, _) = self.stack_offset_and_size(structure);
|
||||||
|
|
||||||
|
let (data_size, data_alignment) =
|
||||||
|
union_layout.data_size_and_alignment(self.target_info);
|
||||||
|
let id_offset = data_size - data_alignment;
|
||||||
|
let id_builtin = union_layout.tag_id_builtin();
|
||||||
|
|
||||||
|
let size = id_builtin.stack_size(self.target_info);
|
||||||
|
self.allocation_map.insert(*sym, owned_data);
|
||||||
|
self.symbol_storage_map.insert(
|
||||||
|
*sym,
|
||||||
|
Stack(ReferencedPrimitive {
|
||||||
|
base_offset: union_offset + id_offset as i32,
|
||||||
|
size,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
x => todo!("getting tag id of union with layout ({:?})", x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a struct on the stack, moving the data in fields into the struct.
|
/// Creates a struct on the stack, moving the data in fields into the struct.
|
||||||
pub fn create_struct(
|
pub fn create_struct(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -973,11 +1003,7 @@ impl<
|
||||||
|
|
||||||
/// Frees an reference and release an allocation if it is no longer used.
|
/// Frees an reference and release an allocation if it is no longer used.
|
||||||
fn free_reference(&mut self, sym: &Symbol) {
|
fn free_reference(&mut self, sym: &Symbol) {
|
||||||
let owned_data = if let Some(owned_data) = self.allocation_map.remove(sym) {
|
let owned_data = self.remove_allocation_for_sym(sym);
|
||||||
owned_data
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {:?}", sym);
|
|
||||||
};
|
|
||||||
if Rc::strong_count(&owned_data) == 1 {
|
if Rc::strong_count(&owned_data) == 1 {
|
||||||
self.free_stack_chunk(owned_data.0, owned_data.1);
|
self.free_stack_chunk(owned_data.0, owned_data.1);
|
||||||
}
|
}
|
||||||
|
@ -1060,7 +1086,26 @@ impl<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a value from storage. They index symbol must be defined.
|
#[allow(dead_code)]
|
||||||
|
/// Gets the allocated area for a symbol. The index symbol must be defined.
|
||||||
|
fn get_allocation_for_sym(&self, sym: &Symbol) -> &Rc<(i32, u32)> {
|
||||||
|
if let Some(allocation) = self.allocation_map.get(sym) {
|
||||||
|
allocation
|
||||||
|
} else {
|
||||||
|
internal_error!("Unknown symbol: {:?}", sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes and returns the allocated area for a symbol. They index symbol must be defined.
|
||||||
|
fn remove_allocation_for_sym(&mut self, sym: &Symbol) -> Rc<(i32, u32)> {
|
||||||
|
if let Some(allocation) = self.allocation_map.remove(sym) {
|
||||||
|
allocation
|
||||||
|
} else {
|
||||||
|
internal_error!("Unknown symbol: {:?}", sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a value from storage. The index symbol must be defined.
|
||||||
fn get_storage_for_sym(&self, sym: &Symbol) -> &Storage<GeneralReg, FloatReg> {
|
fn get_storage_for_sym(&self, sym: &Symbol) -> &Storage<GeneralReg, FloatReg> {
|
||||||
if let Some(storage) = self.symbol_storage_map.get(sym) {
|
if let Some(storage) = self.symbol_storage_map.get(sym) {
|
||||||
storage
|
storage
|
||||||
|
|
|
@ -14,7 +14,7 @@ use roc_mono::ir::{
|
||||||
BranchInfo, CallType, Expr, JoinPointId, ListLiteralElement, Literal, Param, Proc, ProcLayout,
|
BranchInfo, CallType, Expr, JoinPointId, ListLiteralElement, Literal, Param, Proc, ProcLayout,
|
||||||
SelfRecursive, Stmt,
|
SelfRecursive, Stmt,
|
||||||
};
|
};
|
||||||
use roc_mono::layout::{Builtin, Layout, LayoutId, LayoutIds};
|
use roc_mono::layout::{Builtin, Layout, LayoutId, LayoutIds, UnionLayout};
|
||||||
|
|
||||||
mod generic64;
|
mod generic64;
|
||||||
mod object_builder;
|
mod object_builder;
|
||||||
|
@ -315,6 +315,12 @@ trait Backend<'a> {
|
||||||
} => {
|
} => {
|
||||||
self.load_struct_at_index(sym, structure, *index, field_layouts);
|
self.load_struct_at_index(sym, structure, *index, field_layouts);
|
||||||
}
|
}
|
||||||
|
Expr::GetTagId {
|
||||||
|
structure,
|
||||||
|
union_layout,
|
||||||
|
} => {
|
||||||
|
self.get_tag_id(sym, structure, union_layout);
|
||||||
|
}
|
||||||
x => todo!("the expression, {:?}", x),
|
x => todo!("the expression, {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -680,6 +686,9 @@ trait Backend<'a> {
|
||||||
field_layouts: &'a [Layout<'a>],
|
field_layouts: &'a [Layout<'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>);
|
||||||
|
|
||||||
/// 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