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]) { 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,24 +1524,26 @@ impl<
#[macro_export] #[macro_export]
macro_rules! single_register_integers { macro_rules! single_register_integers {
() => { () => {
Builtin::Bool Layout::Builtin(
| Builtin::Int( Builtin::Bool
IntWidth::I8 | Builtin::Int(
| IntWidth::I16 IntWidth::I8
| IntWidth::I32 | IntWidth::I16
| IntWidth::I64 | IntWidth::I32
| IntWidth::U8 | IntWidth::I64
| IntWidth::U16 | IntWidth::U8
| IntWidth::U32 | IntWidth::U16
| IntWidth::U64, | IntWidth::U32
) | 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))
}; };
} }

View file

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

View file

@ -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.
self.load_literal_symbols(arguments); if fn_name == "#UserApp_#rcDec_str_0_1"
self.build_fn_call(sym, fn_name, arguments, arg_layouts, ret_layout) || 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 { } 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>>;