mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +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]) {
|
fn create_struct(&mut self, sym: &Symbol, layout: &Layout<'a>, fields: &'a [Symbol]) {
|
||||||
let struct_size = layout.stack_size(PTR_SIZE);
|
let struct_size = layout.stack_size(PTR_SIZE);
|
||||||
|
|
||||||
|
@ -1134,8 +1141,11 @@ impl<
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Some(x) => unimplemented!("returning symbol storage, {:?}, is not yet implemented", x),
|
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 => {
|
None => {
|
||||||
internal_error!("Unknown return symbol: {}", sym);
|
internal_error!("Unknown return symbol: {:?}", sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let inst_loc = self.buf.len() as u64;
|
let inst_loc = self.buf.len() as u64;
|
||||||
|
@ -1514,6 +1524,7 @@ impl<
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! single_register_integers {
|
macro_rules! single_register_integers {
|
||||||
() => {
|
() => {
|
||||||
|
Layout::Builtin(
|
||||||
Builtin::Bool
|
Builtin::Bool
|
||||||
| Builtin::Int(
|
| Builtin::Int(
|
||||||
IntWidth::I8
|
IntWidth::I8
|
||||||
|
@ -1524,14 +1535,15 @@ macro_rules! single_register_integers {
|
||||||
| IntWidth::U16
|
| IntWidth::U16
|
||||||
| IntWidth::U32
|
| IntWidth::U32
|
||||||
| IntWidth::U64,
|
| IntWidth::U64,
|
||||||
)
|
),
|
||||||
|
) | Layout::RecursivePointer
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! single_register_floats {
|
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() {
|
for (layout, sym) in args.iter() {
|
||||||
match layout {
|
match layout {
|
||||||
Layout::Builtin(single_register_integers!()) => {
|
single_register_integers!() => {
|
||||||
if general_i < Self::GENERAL_PARAM_REGS.len() {
|
if general_i < Self::GENERAL_PARAM_REGS.len() {
|
||||||
symbol_map.insert(
|
symbol_map.insert(
|
||||||
*sym,
|
*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() {
|
if float_i < Self::FLOAT_PARAM_REGS.len() {
|
||||||
symbol_map.insert(
|
symbol_map.insert(
|
||||||
*sym,
|
*sym,
|
||||||
|
@ -277,7 +277,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
||||||
// For most return layouts we will do nothing.
|
// For most return layouts we will do nothing.
|
||||||
// In some cases, we need to put the return address as the first arg.
|
// In some cases, we need to put the return address as the first arg.
|
||||||
match ret_layout {
|
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.
|
// Nothing needs to be done for any of these cases.
|
||||||
}
|
}
|
||||||
x => {
|
x => {
|
||||||
|
@ -286,7 +286,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
||||||
}
|
}
|
||||||
for (i, layout) in arg_layouts.iter().enumerate() {
|
for (i, layout) in arg_layouts.iter().enumerate() {
|
||||||
match layout {
|
match layout {
|
||||||
Layout::Builtin(single_register_integers!()) => {
|
single_register_integers!() => {
|
||||||
let storage = match symbol_map.get(&args[i]) {
|
let storage = match symbol_map.get(&args[i]) {
|
||||||
Some(storage) => storage,
|
Some(storage) => storage,
|
||||||
None => {
|
None => {
|
||||||
|
@ -336,7 +336,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
||||||
stack_offset += 8;
|
stack_offset += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Layout::Builtin(single_register_floats!()) => {
|
single_register_floats!() => {
|
||||||
let storage = match symbol_map.get(&args[i]) {
|
let storage = match symbol_map.get(&args[i]) {
|
||||||
Some(storage) => storage,
|
Some(storage) => storage,
|
||||||
None => {
|
None => {
|
||||||
|
@ -574,12 +574,12 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
||||||
for (layout, sym) in args.iter() {
|
for (layout, sym) in args.iter() {
|
||||||
if i < Self::GENERAL_PARAM_REGS.len() {
|
if i < Self::GENERAL_PARAM_REGS.len() {
|
||||||
match layout {
|
match layout {
|
||||||
Layout::Builtin(single_register_integers!()) => {
|
single_register_integers!() => {
|
||||||
symbol_map
|
symbol_map
|
||||||
.insert(*sym, SymbolStorage::GeneralReg(Self::GENERAL_PARAM_REGS[i]));
|
.insert(*sym, SymbolStorage::GeneralReg(Self::GENERAL_PARAM_REGS[i]));
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
Layout::Builtin(single_register_floats!()) => {
|
single_register_floats!() => {
|
||||||
symbol_map.insert(*sym, SymbolStorage::FloatReg(Self::FLOAT_PARAM_REGS[i]));
|
symbol_map.insert(*sym, SymbolStorage::FloatReg(Self::FLOAT_PARAM_REGS[i]));
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
@ -596,7 +596,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
base_offset += match layout {
|
base_offset += match layout {
|
||||||
Layout::Builtin(single_register_builtins!()) => 8,
|
single_register_builtins!() => 8,
|
||||||
x => {
|
x => {
|
||||||
unimplemented!("Loading args with layout {:?} not yet implemented", 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.
|
// For most return layouts we will do nothing.
|
||||||
// In some cases, we need to put the return address as the first arg.
|
// In some cases, we need to put the return address as the first arg.
|
||||||
match ret_layout {
|
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.
|
// Nothing needs to be done for any of these cases.
|
||||||
}
|
}
|
||||||
x => {
|
x => {
|
||||||
|
@ -634,7 +634,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
||||||
}
|
}
|
||||||
for (i, layout) in arg_layouts.iter().enumerate() {
|
for (i, layout) in arg_layouts.iter().enumerate() {
|
||||||
match layout {
|
match layout {
|
||||||
Layout::Builtin(single_register_integers!()) => {
|
single_register_integers!() => {
|
||||||
let storage = match symbol_map.get(&args[i]) {
|
let storage = match symbol_map.get(&args[i]) {
|
||||||
Some(storage) => storage,
|
Some(storage) => storage,
|
||||||
None => {
|
None => {
|
||||||
|
@ -683,7 +683,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
||||||
stack_offset += 8;
|
stack_offset += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Layout::Builtin(single_register_floats!()) => {
|
single_register_floats!() => {
|
||||||
let storage = match symbol_map.get(&args[i]) {
|
let storage = match symbol_map.get(&args[i]) {
|
||||||
Some(storage) => storage,
|
Some(storage) => storage,
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -278,8 +278,16 @@ where
|
||||||
let layout_id = LayoutIds::default().get(*func_sym, layout);
|
let layout_id = LayoutIds::default().get(*func_sym, layout);
|
||||||
let fn_name = self.env().symbol_to_string(*func_sym, layout_id);
|
let fn_name = self.env().symbol_to_string(*func_sym, layout_id);
|
||||||
// Now that the arguments are needed, load them if they are literals.
|
// 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.load_literal_symbols(arguments);
|
||||||
self.build_fn_call(sym, fn_name, arguments, arg_layouts, ret_layout)
|
self.build_fn_call(sym, fn_name, arguments, arg_layouts, ret_layout)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.build_inline_builtin(
|
self.build_inline_builtin(
|
||||||
sym,
|
sym,
|
||||||
|
@ -520,6 +528,28 @@ where
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
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),
|
x => unimplemented!("low level, {:?}. is not yet implemented", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -599,6 +629,9 @@ where
|
||||||
arg_layout: &Layout<'a>,
|
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.
|
/// 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>>;
|
fn literal_map(&mut self) -> &mut MutMap<Symbol, Literal<'a>>;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue