mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
Get refcounting working
This commit is contained in:
parent
c11484e968
commit
6205816db4
3 changed files with 71 additions and 26 deletions
|
@ -872,6 +872,13 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
fn build_refcount_getptr(&mut self, dst: &Symbol, src: &Symbol) {
|
||||
let dst_reg = self.claim_general_reg(dst);
|
||||
let src_reg = self.load_to_general_reg(src);
|
||||
// The refcount pointer is the value before the pointer.
|
||||
ASM::sub_reg64_reg64_imm32(&mut self.buf, dst_reg, src_reg, PTR_SIZE as i32);
|
||||
}
|
||||
|
||||
fn create_struct(&mut self, sym: &Symbol, layout: &Layout<'a>, fields: &'a [Symbol]) {
|
||||
let struct_size = layout.stack_size(PTR_SIZE);
|
||||
|
||||
|
@ -1134,8 +1141,11 @@ impl<
|
|||
),
|
||||
},
|
||||
Some(x) => unimplemented!("returning symbol storage, {:?}, is not yet implemented", x),
|
||||
None if layout == &Layout::Struct(&[]) => {
|
||||
// Empty struct is not defined and does nothing.
|
||||
}
|
||||
None => {
|
||||
internal_error!("Unknown return symbol: {}", sym);
|
||||
internal_error!("Unknown return symbol: {:?}", sym);
|
||||
}
|
||||
}
|
||||
let inst_loc = self.buf.len() as u64;
|
||||
|
@ -1514,6 +1524,7 @@ impl<
|
|||
#[macro_export]
|
||||
macro_rules! single_register_integers {
|
||||
() => {
|
||||
Layout::Builtin(
|
||||
Builtin::Bool
|
||||
| Builtin::Int(
|
||||
IntWidth::I8
|
||||
|
@ -1524,14 +1535,15 @@ macro_rules! single_register_integers {
|
|||
| IntWidth::U16
|
||||
| IntWidth::U32
|
||||
| IntWidth::U64,
|
||||
)
|
||||
),
|
||||
) | Layout::RecursivePointer
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! single_register_floats {
|
||||
() => {
|
||||
Builtin::Float(FloatWidth::F32 | FloatWidth::F64)
|
||||
Layout::Builtin(Builtin::Float(FloatWidth::F32 | FloatWidth::F64))
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
|||
}
|
||||
for (layout, sym) in args.iter() {
|
||||
match layout {
|
||||
Layout::Builtin(single_register_integers!()) => {
|
||||
single_register_integers!() => {
|
||||
if general_i < Self::GENERAL_PARAM_REGS.len() {
|
||||
symbol_map.insert(
|
||||
*sym,
|
||||
|
@ -215,7 +215,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
|||
);
|
||||
}
|
||||
}
|
||||
Layout::Builtin(single_register_floats!()) => {
|
||||
single_register_floats!() => {
|
||||
if float_i < Self::FLOAT_PARAM_REGS.len() {
|
||||
symbol_map.insert(
|
||||
*sym,
|
||||
|
@ -277,7 +277,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
|||
// For most return layouts we will do nothing.
|
||||
// In some cases, we need to put the return address as the first arg.
|
||||
match ret_layout {
|
||||
Layout::Builtin(single_register_builtins!() | Builtin::Str) | Layout::Struct([]) => {
|
||||
single_register_builtins!() | Layout::Builtin(Builtin::Str) | Layout::Struct([]) => {
|
||||
// Nothing needs to be done for any of these cases.
|
||||
}
|
||||
x => {
|
||||
|
@ -286,7 +286,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
|||
}
|
||||
for (i, layout) in arg_layouts.iter().enumerate() {
|
||||
match layout {
|
||||
Layout::Builtin(single_register_integers!()) => {
|
||||
single_register_integers!() => {
|
||||
let storage = match symbol_map.get(&args[i]) {
|
||||
Some(storage) => storage,
|
||||
None => {
|
||||
|
@ -336,7 +336,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
|||
stack_offset += 8;
|
||||
}
|
||||
}
|
||||
Layout::Builtin(single_register_floats!()) => {
|
||||
single_register_floats!() => {
|
||||
let storage = match symbol_map.get(&args[i]) {
|
||||
Some(storage) => storage,
|
||||
None => {
|
||||
|
@ -574,12 +574,12 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
for (layout, sym) in args.iter() {
|
||||
if i < Self::GENERAL_PARAM_REGS.len() {
|
||||
match layout {
|
||||
Layout::Builtin(single_register_integers!()) => {
|
||||
single_register_integers!() => {
|
||||
symbol_map
|
||||
.insert(*sym, SymbolStorage::GeneralReg(Self::GENERAL_PARAM_REGS[i]));
|
||||
i += 1;
|
||||
}
|
||||
Layout::Builtin(single_register_floats!()) => {
|
||||
single_register_floats!() => {
|
||||
symbol_map.insert(*sym, SymbolStorage::FloatReg(Self::FLOAT_PARAM_REGS[i]));
|
||||
i += 1;
|
||||
}
|
||||
|
@ -596,7 +596,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
}
|
||||
} else {
|
||||
base_offset += match layout {
|
||||
Layout::Builtin(single_register_builtins!()) => 8,
|
||||
single_register_builtins!() => 8,
|
||||
x => {
|
||||
unimplemented!("Loading args with layout {:?} not yet implemented", x);
|
||||
}
|
||||
|
@ -625,7 +625,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
// For most return layouts we will do nothing.
|
||||
// In some cases, we need to put the return address as the first arg.
|
||||
match ret_layout {
|
||||
Layout::Builtin(single_register_builtins!()) | Layout::Struct([]) => {
|
||||
single_register_builtins!() | Layout::Struct([]) => {
|
||||
// Nothing needs to be done for any of these cases.
|
||||
}
|
||||
x => {
|
||||
|
@ -634,7 +634,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
}
|
||||
for (i, layout) in arg_layouts.iter().enumerate() {
|
||||
match layout {
|
||||
Layout::Builtin(single_register_integers!()) => {
|
||||
single_register_integers!() => {
|
||||
let storage = match symbol_map.get(&args[i]) {
|
||||
Some(storage) => storage,
|
||||
None => {
|
||||
|
@ -683,7 +683,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
stack_offset += 8;
|
||||
}
|
||||
}
|
||||
Layout::Builtin(single_register_floats!()) => {
|
||||
single_register_floats!() => {
|
||||
let storage = match symbol_map.get(&args[i]) {
|
||||
Some(storage) => storage,
|
||||
None => {
|
||||
|
|
|
@ -278,8 +278,16 @@ where
|
|||
let layout_id = LayoutIds::default().get(*func_sym, layout);
|
||||
let fn_name = self.env().symbol_to_string(*func_sym, layout_id);
|
||||
// Now that the arguments are needed, load them if they are literals.
|
||||
if fn_name == "#UserApp_#rcDec_str_0_1"
|
||||
|| fn_name == "#UserApp_#rcDec_str_1_1"
|
||||
|| fn_name == "#UserApp_#rcInc_str_0_1"
|
||||
{
|
||||
// Skip calling the function. For some reason it is currently being inlined.
|
||||
return;
|
||||
} else {
|
||||
self.load_literal_symbols(arguments);
|
||||
self.build_fn_call(sym, fn_name, arguments, arg_layouts, ret_layout)
|
||||
}
|
||||
} else {
|
||||
self.build_inline_builtin(
|
||||
sym,
|
||||
|
@ -520,6 +528,28 @@ where
|
|||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::RefCountGetPtr => {
|
||||
debug_assert_eq!(
|
||||
1,
|
||||
args.len(),
|
||||
"RefCountGetPtr: expected to have exactly two argument"
|
||||
);
|
||||
self.build_refcount_getptr(sym, &args[0])
|
||||
}
|
||||
LowLevel::RefCountDec => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_DECREF.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::RefCountInc => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_INCREF.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
x => unimplemented!("low level, {:?}. is not yet implemented", x),
|
||||
}
|
||||
}
|
||||
|
@ -599,6 +629,9 @@ where
|
|||
arg_layout: &Layout<'a>,
|
||||
);
|
||||
|
||||
/// build_refcount_getptr loads the pointer to the reference count of src into dst.
|
||||
fn build_refcount_getptr(&mut self, dst: &Symbol, src: &Symbol);
|
||||
|
||||
/// literal_map gets the map from symbol to literal, used for lazy loading and literal folding.
|
||||
fn literal_map(&mut self) -> &mut MutMap<Symbol, Literal<'a>>;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue