mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
Add StrCat support and update hello-zig to support dev backend
This commit is contained in:
parent
2f24067267
commit
d1021d652d
6 changed files with 186 additions and 94 deletions
|
@ -226,6 +226,7 @@ impl CallConv<AArch64GeneralReg, AArch64FloatReg> for AArch64Call {
|
|||
|
||||
#[inline(always)]
|
||||
fn load_args<'a>(
|
||||
_buf: &mut Vec<'a, u8>,
|
||||
_symbol_map: &mut MutMap<Symbol, SymbolStorage<AArch64GeneralReg, AArch64FloatReg>>,
|
||||
_args: &'a [(Layout<'a>, Symbol)],
|
||||
_ret_layout: &Layout<'a>,
|
||||
|
|
|
@ -48,6 +48,7 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait> {
|
|||
|
||||
// load_args updates the symbol map to know where every arg is stored.
|
||||
fn load_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
symbol_map: &mut MutMap<Symbol, SymbolStorage<GeneralReg, FloatReg>>,
|
||||
args: &'a [(Layout<'a>, Symbol)],
|
||||
// ret_layout is needed because if it is a complex type, we pass a pointer as the first arg.
|
||||
|
@ -422,7 +423,12 @@ impl<
|
|||
args: &'a [(Layout<'a>, Symbol)],
|
||||
ret_layout: &Layout<'a>,
|
||||
) -> Result<(), String> {
|
||||
CC::load_args(&mut self.symbol_storage_map, args, ret_layout)?;
|
||||
CC::load_args(
|
||||
&mut self.buf,
|
||||
&mut self.symbol_storage_map,
|
||||
args,
|
||||
ret_layout,
|
||||
)?;
|
||||
// Update used and free regs.
|
||||
for (sym, storage) in &self.symbol_storage_map {
|
||||
match storage {
|
||||
|
@ -1063,7 +1069,7 @@ impl<
|
|||
Layout::Builtin(Builtin::Str) => {
|
||||
if self.symbol_storage_map.contains_key(&Symbol::RET_POINTER) {
|
||||
// This will happen on windows, return via pointer here.
|
||||
Err("Returning strings via pointer not yet implemented".to_string())
|
||||
return Err("Returning strings via pointer not yet implemented".to_string());
|
||||
} else {
|
||||
ASM::mov_reg64_base32(&mut self.buf, CC::GENERAL_RETURN_REGS[0], *offset);
|
||||
ASM::mov_reg64_base32(
|
||||
|
@ -1071,7 +1077,6 @@ impl<
|
|||
CC::GENERAL_RETURN_REGS[1],
|
||||
*offset + 8,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Layout::Struct(field_layouts) => {
|
||||
|
|
|
@ -177,6 +177,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
|||
|
||||
#[inline(always)]
|
||||
fn load_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
symbol_map: &mut MutMap<Symbol, SymbolStorage<X86_64GeneralReg, X86_64FloatReg>>,
|
||||
args: &'a [(Layout<'a>, Symbol)],
|
||||
ret_layout: &Layout<'a>,
|
||||
|
@ -231,6 +232,29 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
|||
);
|
||||
}
|
||||
}
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
if general_i + 1 < Self::GENERAL_PARAM_REGS.len() {
|
||||
// Load the value to the param reg.
|
||||
let dst1 = Self::GENERAL_PARAM_REGS[general_i];
|
||||
let dst2 = Self::GENERAL_PARAM_REGS[general_i + 1];
|
||||
base_offset += 16;
|
||||
X86_64Assembler::mov_reg64_base32(buf, dst1, base_offset - 8);
|
||||
X86_64Assembler::mov_reg64_base32(buf, dst2, base_offset);
|
||||
symbol_map.insert(
|
||||
*sym,
|
||||
SymbolStorage::Base {
|
||||
offset: base_offset,
|
||||
size: 16,
|
||||
owned: true,
|
||||
},
|
||||
);
|
||||
general_i += 2;
|
||||
} else {
|
||||
return Err(
|
||||
"loading strings args on the stack is not yet implemented".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
Layout::Struct(&[]) => {}
|
||||
x => {
|
||||
return Err(format!(
|
||||
|
@ -257,7 +281,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!()) => {}
|
||||
Layout::Builtin(single_register_builtins!() | Builtin::Str) => {}
|
||||
x => {
|
||||
return Err(format!(
|
||||
"receiving return type, {:?}, is not yet implemented",
|
||||
|
@ -373,6 +397,32 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
|
|||
stack_offset += 8;
|
||||
}
|
||||
}
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
if general_i + 1 < Self::GENERAL_PARAM_REGS.len() {
|
||||
// Load the value to the param reg.
|
||||
let dst1 = Self::GENERAL_PARAM_REGS[general_i];
|
||||
let dst2 = Self::GENERAL_PARAM_REGS[general_i + 1];
|
||||
match symbol_map
|
||||
.get(&args[i])
|
||||
.ok_or("function argument does not reference any symbol")?
|
||||
{
|
||||
SymbolStorage::Base { offset, .. } => {
|
||||
X86_64Assembler::mov_reg64_base32(buf, dst1, *offset);
|
||||
X86_64Assembler::mov_reg64_base32(buf, dst2, *offset + 8);
|
||||
}
|
||||
_ => {
|
||||
return Err("Strings only support being loaded from base offsets"
|
||||
.to_string());
|
||||
}
|
||||
}
|
||||
general_i += 2;
|
||||
} else {
|
||||
return Err(
|
||||
"calling functions with strings on the stack is not yet implemented"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Layout::Struct(&[]) => {}
|
||||
x => {
|
||||
return Err(format!(
|
||||
|
@ -516,6 +566,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
|
||||
#[inline(always)]
|
||||
fn load_args<'a>(
|
||||
_buf: &mut Vec<'a, u8>,
|
||||
symbol_map: &mut MutMap<Symbol, SymbolStorage<X86_64GeneralReg, X86_64FloatReg>>,
|
||||
args: &'a [(Layout<'a>, Symbol)],
|
||||
ret_layout: &Layout<'a>,
|
||||
|
@ -535,9 +586,18 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
Layout::Builtin(single_register_integers!()) => {
|
||||
symbol_map
|
||||
.insert(*sym, SymbolStorage::GeneralReg(Self::GENERAL_PARAM_REGS[i]));
|
||||
i += 1;
|
||||
}
|
||||
Layout::Builtin(single_register_floats!()) => {
|
||||
symbol_map.insert(*sym, SymbolStorage::FloatReg(Self::FLOAT_PARAM_REGS[i]));
|
||||
i += 1;
|
||||
}
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
// I think this just needs to be passed on the stack, so not a huge deal.
|
||||
return Err(
|
||||
"Passing str args with Windows fast call not yet implemented."
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
Layout::Struct(&[]) => {}
|
||||
x => {
|
||||
|
@ -547,7 +607,6 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
));
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
} else {
|
||||
base_offset += match layout {
|
||||
Layout::Builtin(single_register_builtins!()) => 8,
|
||||
|
@ -580,7 +639,6 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
ret_layout: &Layout<'a>,
|
||||
) -> Result<u32, String> {
|
||||
let mut stack_offset = Self::SHADOW_SPACE_SIZE as i32;
|
||||
let mut reg_i = 0;
|
||||
// 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 {
|
||||
|
@ -597,7 +655,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
Layout::Builtin(single_register_integers!()) => {
|
||||
if i < Self::GENERAL_PARAM_REGS.len() {
|
||||
// Load the value to the param reg.
|
||||
let dst = Self::GENERAL_PARAM_REGS[reg_i];
|
||||
let dst = Self::GENERAL_PARAM_REGS[i];
|
||||
match symbol_map
|
||||
.get(&args[i])
|
||||
.ok_or("function argument does not reference any symbol")?
|
||||
|
@ -615,7 +673,6 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
)
|
||||
}
|
||||
}
|
||||
reg_i += 1;
|
||||
} else {
|
||||
// Load the value to the stack.
|
||||
match symbol_map
|
||||
|
@ -651,7 +708,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
Layout::Builtin(single_register_floats!()) => {
|
||||
if i < Self::FLOAT_PARAM_REGS.len() {
|
||||
// Load the value to the param reg.
|
||||
let dst = Self::FLOAT_PARAM_REGS[reg_i];
|
||||
let dst = Self::FLOAT_PARAM_REGS[i];
|
||||
match symbol_map
|
||||
.get(&args[i])
|
||||
.ok_or("function argument does not reference any symbol")?
|
||||
|
@ -668,7 +725,6 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
return Err("Cannot load general symbol into FloatReg".to_string())
|
||||
}
|
||||
}
|
||||
reg_i += 1;
|
||||
} else {
|
||||
// Load the value to the stack.
|
||||
match symbol_map
|
||||
|
@ -700,6 +756,12 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
|
|||
stack_offset += 8;
|
||||
}
|
||||
}
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
// I think this just needs to be passed on the stack, so not a huge deal.
|
||||
return Err(
|
||||
"Passing str args with Windows fast call not yet implemented.".to_string(),
|
||||
);
|
||||
}
|
||||
Layout::Struct(&[]) => {}
|
||||
x => {
|
||||
return Err(format!(
|
||||
|
|
|
@ -93,12 +93,8 @@ where
|
|||
for (layout, sym) in proc.args {
|
||||
self.set_layout_map(*sym, layout)?;
|
||||
}
|
||||
// let start = std::time::Instant::now();
|
||||
self.scan_ast(&proc.body);
|
||||
self.create_free_map();
|
||||
// let duration = start.elapsed();
|
||||
// println!("Time to calculate lifetimes: {:?}", duration);
|
||||
// println!("{:?}", self.last_seen_map());
|
||||
self.build_stmt(&proc.body, &proc.ret_layout)?;
|
||||
self.finalize()
|
||||
}
|
||||
|
@ -119,6 +115,11 @@ where
|
|||
self.free_symbols(stmt)?;
|
||||
Ok(())
|
||||
}
|
||||
Stmt::Refcounting(_modify, following) => {
|
||||
// TODO: actually deal with refcounting. For hello world, we just skipped it.
|
||||
self.build_stmt(following, ret_layout)?;
|
||||
Ok(())
|
||||
}
|
||||
Stmt::Switch {
|
||||
cond_symbol,
|
||||
cond_layout,
|
||||
|
@ -298,6 +299,13 @@ where
|
|||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
Symbol::STR_CONCAT => self.build_run_low_level(
|
||||
sym,
|
||||
&LowLevel::StrConcat,
|
||||
arguments,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
x if x
|
||||
.module_string(&self.env().interns)
|
||||
.starts_with(ModuleName::APP) =>
|
||||
|
@ -470,6 +478,13 @@ where
|
|||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrConcat => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_CONCAT.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
x => Err(format!("low level, {:?}. is not yet implemented", x)),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue