Get refcounting working

This commit is contained in:
Brendan Hansknecht 2021-12-04 10:43:45 -08:00
parent c11484e968
commit 6205816db4
3 changed files with 71 additions and 26 deletions

View file

@ -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))
};
}

View file

@ -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 => {

View file

@ -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>>;