slices (offsets now real in backend)

This commit is contained in:
2024-12-07 23:56:00 -05:00
parent 0e0dbd647d
commit 606cb30c6b
14 changed files with 305 additions and 215 deletions

View File

@@ -1,23 +1,30 @@
fn start() { fn start() {
print("Hello World!\n", 13); print("Helld!\n");
print("Hello World!\n", 13); print("Hello World!!!!!\n");
exit(0); thinger();
print("what\n");
exit(39);
}
fn thinger() {
print("estamos jugando\n");
} }
fn unused() { fn unused() {
print("Hello World!\n", 13); print("el unused\n");
} }
fn print(msg, len) { fn print(msg: slice<8>) {
asm (a1 = msg, a2 = len) { asm (a1 = msg) {
ld a2, 0, a2 ld a2, 8, a1
ld a1, 0, a1
li a0, 1 li a0, 1
li a7, 64 li a7, 64
ecall ecall
} }
} }
fn exit(status: 32) { fn exit(status: 64) {
asm (a0 = status) { asm (a0 = status) {
ld a0, 0, a0 ld a0, 0, a0
li a7, 93 li a7, 93

View File

@@ -4,12 +4,44 @@ use crate::{
compiler::{arch::riscv64::Reg, create_program, Addr}, compiler::{arch::riscv64::Reg, create_program, Addr},
ir::{ ir::{
arch::riscv64::{RV64Instruction as AI, RegRef}, arch::riscv64::{RV64Instruction as AI, RegRef},
IRLInstruction as IRI, IRLProgram, IRLInstruction as IRI, IRLProgram, Len, Size, Symbol, VarID,
}, },
}; };
use super::{LinkerInstruction as LI, *}; use super::{LinkerInstruction as LI, *};
fn align(s: &Size) -> i32 {
(*s as i32 - 1).div_euclid(8) + 1
}
fn mov_mem(
v: &mut Vec<LI>,
src: Reg,
src_offset: i32,
dest: Reg,
dest_offset: i32,
temp: Reg,
mut len: Len,
) {
let mut off = 0;
while len >= 8 {
v.extend([
LI::Ld {
dest: temp,
offset: src_offset + off,
base: src,
},
LI::Sd {
src: temp,
offset: dest_offset + off,
base: dest,
},
]);
len -= 8;
off += 8;
}
}
pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) { pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
let mut fns = Vec::new(); let mut fns = Vec::new();
let mut data = Vec::new(); let mut data = Vec::new();
@@ -20,26 +52,36 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
let mut v = Vec::new(); let mut v = Vec::new();
let mut stack = HashMap::new(); let mut stack = HashMap::new();
let mut stack_len = 0; let mut stack_len = 0;
if !f.stack.is_empty() || !f.args.is_empty() { let has_stack = !f.stack.is_empty() || !f.args.is_empty() || f.makes_call;
let mut stack_ra = None;
if has_stack {
if f.makes_call {
// return addr
stack_ra = Some(stack_len);
stack_len += 8;
}
for (id, s) in &f.stack { for (id, s) in &f.stack {
stack.insert(id, stack_len); stack.insert(id, stack_len);
stack_len += *s as i32; stack_len += align(s);
} }
for (id, s) in f.args.iter().rev() { for (id, s) in f.args.iter().rev() {
stack.insert(id, stack_len); stack.insert(id, stack_len);
stack_len += *s as i32; stack_len += align(s);
} }
v.push(LI::Addi { v.push(LI::Addi {
dest: sp, dest: sp,
src: sp, src: sp,
imm: -stack_len, imm: -stack_len,
}); });
if let Some(stack_ra) = stack_ra {
v.push(LI::Sd { src: ra, offset: stack_ra, base: sp });
}
} }
for i in &f.instructions { for i in &f.instructions {
match i { match i {
IRI::Mv { dest, src } => todo!(), IRI::Mv { dest, src } => todo!(),
IRI::Ref { dest, src } => todo!(), IRI::Ref { dest, src } => todo!(),
IRI::LoadAddr { dest, src } => { IRI::LoadAddr { dest, offset, src } => {
v.extend([ v.extend([
LI::La { LI::La {
dest: t0, dest: t0,
@@ -47,36 +89,38 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
}, },
LI::Sd { LI::Sd {
src: t0, src: t0,
offset: stack[dest], offset: stack[dest] + *offset as i32,
base: sp, base: sp,
}, },
]); ]);
} }
IRI::LoadData {
dest,
offset,
src,
len,
} => {
v.push(LI::La {
dest: t0,
src: *src,
});
mov_mem(&mut v, t0, 0, sp, stack[dest] + *offset as i32, t1, *len);
}
IRI::Call { dest, f, args } => { IRI::Call { dest, f, args } => {
let mut offset = 0; let mut offset = 0;
for (arg, s) in args { for (arg, s) in args {
offset -= *s as i32; let bs = align(s);
v.extend([ offset -= bs;
LI::Ld { mov_mem(&mut v, sp, stack[arg], sp, offset, t0, bs as Len);
dest: t0,
offset: stack[arg],
base: sp,
},
LI::Sd {
src: t0,
offset,
base: sp,
},
]);
} }
v.push(LI::Call(*f)); v.push(LI::Call(*f));
} }
IRI::AsmBlock { args, instructions } => { IRI::AsmBlock { args, instructions } => {
for (reg, var) in args { for (reg, var) in args {
v.push(LI::Ld { v.push(LI::Addi {
dest: *reg, dest: *reg,
offset: stack[var], imm: stack[var],
base: sp, src: sp,
}); });
} }
fn r(rr: RegRef) -> Reg { fn r(rr: RegRef) -> Reg {
@@ -105,9 +149,17 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
IRI::Ret { src } => todo!(), IRI::Ret { src } => todo!(),
} }
} }
if *sym != program.entry() { if has_stack {
v.push(LI::Ret); if let Some(stack_ra) = stack_ra {
v.push(LI::Ld { dest: ra, offset: stack_ra, base: sp });
} }
v.push(LI::Addi {
dest: sp,
src: sp,
imm: stack_len,
});
}
v.push(LI::Ret);
fns.push((v, *sym)); fns.push((v, *sym));
} }
create_program(fns, data, Some(program.entry())) create_program(fns, data, Some(program.entry()))

View File

@@ -9,6 +9,9 @@ pub struct FnID(pub usize);
#[derive(Clone, Copy, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub struct DataID(pub usize); pub struct DataID(pub usize);
pub type Size = u32;
pub type Len = u32;
impl Debug for VarID { impl Debug for VarID {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "var{}", self.0) write!(f, "var{}", self.0)

View File

@@ -7,8 +7,9 @@ use std::collections::HashMap;
pub struct IRLFunction { pub struct IRLFunction {
pub name: String, pub name: String,
pub instructions: Vec<IRLInstruction>, pub instructions: Vec<IRLInstruction>,
pub stack: HashMap<VarID, usize>, pub stack: HashMap<VarID, Size>,
pub args: Vec<(VarID, usize)>, pub args: Vec<(VarID, Size)>,
pub makes_call: bool,
} }
#[derive(Debug)] #[derive(Debug)]
@@ -23,12 +24,19 @@ pub enum IRLInstruction {
}, },
LoadAddr { LoadAddr {
dest: VarID, dest: VarID,
offset: Size,
src: Symbol, src: Symbol,
}, },
LoadData {
dest: VarID,
offset: Size,
src: Symbol,
len: Len,
},
Call { Call {
dest: VarID, dest: VarID,
f: Symbol, f: Symbol,
args: Vec<(VarID, usize)>, args: Vec<(VarID, Size)>,
}, },
AsmBlock { AsmBlock {
instructions: Vec<RV64Instruction>, instructions: Vec<RV64Instruction>,

View File

@@ -2,7 +2,7 @@ use std::collections::HashMap;
use crate::ir::{FnID, SymbolSpace}; use crate::ir::{FnID, SymbolSpace};
use super::{IRLFunction, IRLInstruction, IRUInstruction, Namespace, Symbol, VarID}; use super::{IRLFunction, IRLInstruction, IRUInstruction, Len, Namespace, Symbol, VarID};
pub struct IRLProgram { pub struct IRLProgram {
sym_space: SymbolSpace, sym_space: SymbolSpace,
@@ -14,10 +14,9 @@ pub struct IRLProgram {
impl IRLProgram { impl IRLProgram {
pub fn create(ns: &Namespace) -> Option<Self> { pub fn create(ns: &Namespace) -> Option<Self> {
let mut start = None; let mut start = None;
for (i, f) in ns.fns.iter().enumerate() { for (i, f) in ns.iter_fns() {
let f = f.as_ref()?; if f?.name == "start" {
if f.name == "start" { start = Some(i);
start = Some(FnID(i));
} }
} }
let start = start?; let start = start?;
@@ -25,78 +24,121 @@ impl IRLProgram {
let entry = builder.func(&start); let entry = builder.func(&start);
while let Some((sym, i)) = builder.pop_fn() { while let Some((sym, i)) = builder.pop_fn() {
let f = ns.fns[i.0].as_ref().unwrap(); let f = ns.fns[i.0].as_ref().unwrap();
let mut instructions = Vec::new(); let mut instrs = Vec::new();
let mut stack = HashMap::new(); let mut stack = HashMap::new();
let mut alloc_stack = |i: &VarID| { let mut makes_call = false;
if !stack.contains_key(i) { let mut alloc_stack = |i: &VarID| -> bool {
stack.insert(*i, 8); let size = *stack
} .entry(*i)
.or_insert(ns.size_of_var(i).expect("unsized type"));
size == 0
}; };
for i in &f.instructions { for i in &f.instructions {
instructions.push(match i { match i {
IRUInstruction::Mv { dest, src } => { IRUInstruction::Mv { dest, src } => {
alloc_stack(dest); if alloc_stack(dest) {
IRLInstruction::Mv { continue;
}
instrs.push(IRLInstruction::Mv {
dest: *dest, dest: *dest,
src: *src, src: *src,
} });
} }
IRUInstruction::Ref { dest, src } => { IRUInstruction::Ref { dest, src } => {
alloc_stack(dest); if alloc_stack(dest) {
IRLInstruction::Ref { continue;
}
instrs.push(IRLInstruction::Ref {
dest: *dest, dest: *dest,
src: *src, src: *src,
} });
} }
IRUInstruction::LoadData { dest, src } => { IRUInstruction::LoadData { dest, src } => {
alloc_stack(dest); if alloc_stack(dest) {
let addr = builder.ro_data(src, &ns.data[src.0]); continue;
IRLInstruction::LoadAddr {
dest: *dest,
src: addr,
} }
let data = &ns.data[src.0];
let sym = builder.ro_data(src, data);
instrs.push(IRLInstruction::LoadData {
dest: *dest,
offset: 0,
len: data.len() as Len,
src: sym,
});
}
IRUInstruction::LoadSlice { dest, src, len } => {
if alloc_stack(dest) {
continue;
}
let sym = builder.ro_data(src, &ns.data[src.0]);
instrs.push(IRLInstruction::LoadAddr {
dest: *dest,
offset: 0,
src: sym,
});
let sym = builder.anon_ro_data(&(*len as u64).to_le_bytes());
instrs.push(IRLInstruction::LoadData {
dest: *dest,
offset: 8,
len: 8,
src: sym,
});
} }
IRUInstruction::LoadFn { dest, src } => { IRUInstruction::LoadFn { dest, src } => {
alloc_stack(dest); if alloc_stack(dest) {
let sym = builder.func(src); continue;
IRLInstruction::LoadAddr {
dest: *dest,
src: sym,
} }
let sym = builder.func(src);
instrs.push(IRLInstruction::LoadAddr {
dest: *dest,
offset: 0,
src: sym,
});
} }
IRUInstruction::Call { dest, f, args } => { IRUInstruction::Call { dest, f, args } => {
alloc_stack(dest); alloc_stack(dest);
makes_call = true;
let fid = &ns.fn_map[f]; let fid = &ns.fn_map[f];
let sym = builder.func(fid); let sym = builder.func(fid);
IRLInstruction::Call { instrs.push(IRLInstruction::Call {
dest: *dest, dest: *dest,
f: sym, f: sym,
args: args.iter().map(|a| (*a, 8)).collect(), args: args
.iter()
.map(|a| (*a, ns.size_of_var(a).expect("unsized type")))
.collect(),
});
} }
} IRUInstruction::AsmBlock { instructions, args } => {
IRUInstruction::AsmBlock { instructions, args } => IRLInstruction::AsmBlock { instrs.push(IRLInstruction::AsmBlock {
instructions: instructions.clone(), instructions: instructions.clone(),
args: args.clone(), args: args.clone(),
}, })
IRUInstruction::Ret { src } => IRLInstruction::Ret { src: *src }, }
}); IRUInstruction::Ret { src } => instrs.push(IRLInstruction::Ret { src: *src }),
};
} }
builder.write_fn( builder.write_fn(
sym, sym,
IRLFunction { IRLFunction {
name: f.name.clone(), name: f.name.clone(),
instructions, instructions: instrs,
args: f.args.iter().map(|a| (*a, 8)).collect(), makes_call,
args: f
.args
.iter()
.map(|a| (*a, ns.size_of_var(a).expect("unsized type")))
.collect(),
stack, stack,
}, },
); );
} }
let sym_space = builder.finish().expect("we failed the mission"); let sym_space = builder.finish().expect("we failed the mission");
println!("fns:"); // println!("fns:");
for (a, f) in sym_space.fns() { // for (a, f) in sym_space.fns() {
println!(" {:?}: {}", a, f.name); // println!(" {:?}: {}", a, f.name);
} // }
println!("datas: {}", sym_space.ro_data().len()); // println!("datas: {}", sym_space.ro_data().len());
Some(Self { sym_space, entry }) Some(Self { sym_space, entry })
} }

View File

@@ -56,13 +56,17 @@ impl SymbolSpaceBuilder {
pub fn pop_fn(&mut self) -> Option<(WritableSymbol, FnID)> { pub fn pop_fn(&mut self) -> Option<(WritableSymbol, FnID)> {
self.unwritten_fns.pop() self.unwritten_fns.pop()
} }
pub fn ro_data(&mut self, id: &DataID, data: &Vec<u8>) -> Symbol { pub fn anon_ro_data(&mut self, data: &[u8]) -> Symbol {
let sym = self.reserve();
self.write_ro_data(sym, data.to_vec())
}
pub fn ro_data(&mut self, id: &DataID, data: &[u8]) -> Symbol {
match self.data_map.get(id) { match self.data_map.get(id) {
Some(s) => *s, Some(s) => *s,
None => { None => {
let sym = self.reserve(); let sym = self.reserve();
self.data_map.insert(*id, *sym); self.data_map.insert(*id, *sym);
self.write_ro_data(sym, data.clone()) self.write_ro_data(sym, data.to_vec())
} }
} }
} }

View File

@@ -1,8 +1,8 @@
use crate::compiler::arch::riscv64::Reg; use std::fmt::Write;
use super::{arch::riscv64::RV64Instruction, DataID, FnID, VarID}; use super::{arch::riscv64::RV64Instruction, DataID, FnID, Len, VarID};
use crate::{compiler::arch::riscv64::Reg, util::Padder};
#[derive(Debug)]
pub struct IRUFunction { pub struct IRUFunction {
pub name: String, pub name: String,
pub args: Vec<VarID>, pub args: Vec<VarID>,
@@ -22,6 +22,11 @@ pub enum IRUInstruction {
dest: VarID, dest: VarID,
src: DataID, src: DataID,
}, },
LoadSlice {
dest: VarID,
src: DataID,
len: Len,
},
LoadFn { LoadFn {
dest: VarID, dest: VarID,
src: FnID, src: FnID,
@@ -70,6 +75,7 @@ impl std::fmt::Debug for IRUInstruction {
Self::Ref { dest, src } => write!(f, "{dest:?} <- &{src:?}"), Self::Ref { dest, src } => write!(f, "{dest:?} <- &{src:?}"),
Self::LoadData { dest, src } => write!(f, "{dest:?} <- {src:?}"), Self::LoadData { dest, src } => write!(f, "{dest:?} <- {src:?}"),
Self::LoadFn { dest, src } => write!(f, "{dest:?} <- {src:?}"), Self::LoadFn { dest, src } => write!(f, "{dest:?} <- {src:?}"),
Self::LoadSlice { dest, src, len } => write!(f, "{dest:?} <- &[{src:?}; {len}]"),
Self::Call { Self::Call {
dest, dest,
f: func, f: func,
@@ -80,3 +86,21 @@ impl std::fmt::Debug for IRUInstruction {
} }
} }
} }
impl std::fmt::Debug for IRUFunction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}{:?}", &self.name, self.args)?;
if !self.instructions.is_empty() {
f.write_str("{\n ")?;
let mut padder = Padder::new(f);
for i in &self.instructions {
// they don't expose wrap_buf :grief:
padder.write_str(&format!("{i:?};\n"))?;
}
f.write_char('}')?;
} else {
f.write_str("{}")?;
}
Ok(())
}
}

View File

@@ -19,7 +19,7 @@ pub struct Namespace {
impl Namespace { impl Namespace {
pub fn new() -> Self { pub fn new() -> Self {
let mut s = Self { Self {
fn_defs: Vec::new(), fn_defs: Vec::new(),
var_defs: Vec::new(), var_defs: Vec::new(),
type_defs: Vec::new(), type_defs: Vec::new(),
@@ -28,11 +28,7 @@ impl Namespace {
fns: Vec::new(), fns: Vec::new(),
temp: 0, temp: 0,
stack: vec![HashMap::new()], stack: vec![HashMap::new()],
};
for b in BuiltinType::enumerate() {
s.def_type(b.def());
} }
s
} }
pub fn push(&mut self) -> NamespaceGuard { pub fn push(&mut self) -> NamespaceGuard {
self.stack.push(HashMap::new()); self.stack.push(HashMap::new());
@@ -76,6 +72,27 @@ impl Namespace {
self.var_defs.push(var); self.var_defs.push(var);
VarID(i) VarID(i)
} }
pub fn size_of_type(&self, ty: &Type) -> Option<Size> {
// TODO: target matters
Some(match ty {
Type::Concrete(id) => {
let def = &self.type_defs[id.0];
todo!()
}
Type::Bits(b) => *b,
Type::Generic { base, args } => todo!(),
Type::Fn { args, ret } => todo!(),
Type::Ref(_) => 64,
Type::Array(ty, len) => self.size_of_type(ty)? * len,
Type::Slice(_) => 128,
Type::Infer => return None,
Type::Error => return None,
Type::Unit => 0,
})
}
pub fn size_of_var(&self, var: &VarID) -> Option<Size> {
self.size_of_type(&self.var_defs[var.0].ty)
}
pub fn temp_var(&mut self, origin: FileSpan, ty: Type) -> VarID { pub fn temp_var(&mut self, origin: FileSpan, ty: Type) -> VarID {
let v = self.def_var(VarDef { let v = self.def_var(VarDef {
name: format!("temp{}", self.temp), name: format!("temp{}", self.temp),
@@ -151,7 +168,9 @@ impl Namespace {
Type::Error => str += "{error}", Type::Error => str += "{error}",
Type::Infer => str += "{inferred}", Type::Infer => str += "{inferred}",
Type::Bits(size) => str += &format!("b{}", size), Type::Bits(size) => str += &format!("b{}", size),
Type::Array(t) => str += &format!("[{}]", self.type_name(t)), Type::Array(t, len) => str += &format!("[{}; {len}]", self.type_name(t)),
Type::Unit => str += "()",
Type::Slice(t) => str += &format!("&[{}]", self.type_name(t)),
} }
str str
} }
@@ -167,6 +186,16 @@ impl Namespace {
pub fn write_fn(&mut self, id: FnID, f: IRUFunction) { pub fn write_fn(&mut self, id: FnID, f: IRUFunction) {
self.fns[id.0] = Some(f); self.fns[id.0] = Some(f);
} }
pub fn iter_vars(&self) -> impl Iterator<Item = (VarID, &VarDef)> {
(0..self.var_defs.len())
.map(|i| VarID(i))
.zip(self.var_defs.iter())
}
pub fn iter_fns(&self) -> impl Iterator<Item = (FnID, Option<&IRUFunction>)> {
(0..self.fns.len())
.map(|i| FnID(i))
.zip(self.fns.iter().map(|f| f.as_ref()))
}
} }
pub struct NamespaceGuard<'a>(&'a mut Namespace); pub struct NamespaceGuard<'a>(&'a mut Namespace);

View File

@@ -1,4 +1,4 @@
use super::{Origin, TypeDef, TypeID}; use super::{Len, TypeID};
#[derive(Clone)] #[derive(Clone)]
pub enum Type { pub enum Type {
@@ -7,47 +7,21 @@ pub enum Type {
Generic { base: TypeID, args: Vec<Type> }, Generic { base: TypeID, args: Vec<Type> },
Fn { args: Vec<Type>, ret: Box<Type> }, Fn { args: Vec<Type>, ret: Box<Type> },
Ref(Box<Type>), Ref(Box<Type>),
Array(Box<Type>), Slice(Box<Type>),
Array(Box<Type>, Len),
Infer, Infer,
Error, Error,
Unit,
} }
impl Type { impl Type {
pub fn rf(self) -> Self { pub fn rf(self) -> Self {
Self::Ref(Box::new(self)) Self::Ref(Box::new(self))
} }
pub fn arr(self) -> Self { pub fn arr(self, len: Len) -> Self {
Self::Array(Box::new(self)) Self::Array(Box::new(self), len)
}
pub fn slice(self) -> Self {
Self::Slice(Box::new(self))
} }
} }
#[repr(usize)]
#[derive(Debug, Clone, Copy)]
pub enum BuiltinType {
Unit,
}
impl BuiltinType {
pub fn enumerate() -> &'static [Self; 1] {
&[Self::Unit]
}
pub fn def(&self) -> TypeDef {
match self {
BuiltinType::Unit => TypeDef {
name: "()".to_string(),
args: 0,
origin: Origin::Builtin,
},
}
}
pub fn id(&self) -> TypeID {
TypeID::builtin(self)
}
}
impl TypeID {
pub fn builtin(ty: &BuiltinType) -> Self {
Self(*ty as usize)
}
}

View File

@@ -37,10 +37,13 @@ fn run_file(file: &str, gdb: bool) {
let mut namespace = Namespace::new(); let mut namespace = Namespace::new();
module.lower(&mut namespace.push(), &mut ctx.output); module.lower(&mut namespace.push(), &mut ctx.output);
if ctx.output.errs.is_empty() { if ctx.output.errs.is_empty() {
println!("vars:"); // println!("vars:");
for def in &namespace.var_defs { // for (id, def) in namespace.iter_vars() {
println!(" {}: {}", def.name, namespace.type_name(&def.ty)); // println!(" {id:?} = {}: {}", def.name, namespace.type_name(&def.ty));
} // }
// for (id, f) in namespace.iter_fns() {
// println!("{id:?} = {:#?}", f.unwrap());
// }
let program = IRLProgram::create(&namespace); let program = IRLProgram::create(&namespace);
let bin = compiler::compile(program.expect("morir")); let bin = compiler::compile(program.expect("morir"));
println!("compiled"); println!("compiled");

View File

@@ -1,6 +1,6 @@
use crate::ir::{FileSpan, NamespaceGuard, Origin, Type, VarDef}; use crate::ir::{FileSpan, NamespaceGuard, Origin, Type, VarDef};
use super::{Node, ParserMsg, ParserOutput, PType, PVarDef}; use super::{Node, PType, PVarDef, ParserMsg, ParserOutput};
impl Node<PVarDef> { impl Node<PVarDef> {
pub fn lower( pub fn lower(
@@ -54,10 +54,18 @@ impl PType {
if let Ok(num) = self.name.parse::<u32>() { if let Ok(num) = self.name.parse::<u32>() {
Type::Bits(num) Type::Bits(num)
} else { } else {
match self.name.as_str() {
"slice" => {
let inner = self.args[0].lower(namespace, output);
Type::Slice(Box::new(inner))
}
_ => {
output.err(ParserMsg::from_span(span, "Type not found".to_string())); output.err(ParserMsg::from_span(span, "Type not found".to_string()));
Type::Error Type::Error
} }
} }
} }
} }
}
}
} }

View File

@@ -1,5 +1,5 @@
use super::{func::FnLowerCtx, FnLowerable, PExpr, UnaryOp}; use super::{func::FnLowerCtx, FnLowerable, PExpr, UnaryOp};
use crate::ir::{IRUInstruction, Type, VarID}; use crate::ir::{IRUInstruction, Size, Type, VarID};
impl FnLowerable for PExpr { impl FnLowerable for PExpr {
type Output = VarID; type Output = VarID;
@@ -7,13 +7,15 @@ impl FnLowerable for PExpr {
Some(match self { Some(match self {
PExpr::Lit(l) => match l.as_ref()? { PExpr::Lit(l) => match l.as_ref()? {
super::PLiteral::String(s) => { super::PLiteral::String(s) => {
let dest = ctx.map.temp_var(l.span, Type::Bits(64).arr().rf()); let dest = ctx.map.temp_var(l.span, Type::Bits(8).slice());
let src = ctx.map.def_data(s.as_bytes().to_vec()); let data = s.as_bytes().to_vec();
ctx.push(IRUInstruction::LoadData { dest, src }); let len = data.len() as Size;
let src = ctx.map.def_data(data);
ctx.push(IRUInstruction::LoadSlice { dest, src, len });
dest dest
} }
super::PLiteral::Char(c) => { super::PLiteral::Char(c) => {
let dest = ctx.map.temp_var(l.span, Type::Bits(64).arr().rf()); let dest = ctx.map.temp_var(l.span, Type::Bits(8).slice());
let src = ctx.map.def_data(c.to_string().as_bytes().to_vec()); let src = ctx.map.def_data(c.to_string().as_bytes().to_vec());
ctx.push(IRUInstruction::LoadData { dest, src }); ctx.push(IRUInstruction::LoadData { dest, src });
dest dest
@@ -79,9 +81,15 @@ impl FnLowerable for PExpr {
let ty = match def { let ty = match def {
Some(def) => def.ret.clone(), Some(def) => def.ret.clone(),
None => { None => {
ctx.err_at(e.span, format!("Expected function, found {}", ctx.map.type_name(&ctx.map.get_var(fe).ty))); ctx.err_at(
e.span,
format!(
"Expected function, found {}",
ctx.map.type_name(&ctx.map.get_var(fe).ty)
),
);
Type::Error Type::Error
}, }
}; };
let temp = ctx.temp(ty); let temp = ctx.temp(ty);
ctx.push(IRUInstruction::Call { ctx.push(IRUInstruction::Call {

View File

@@ -1,8 +1,8 @@
use super::{FnLowerable, PFunction, Node, ParserMsg, ParserOutput}; use super::{FnLowerable, Node, PFunction, ParserMsg, ParserOutput};
use crate::{ use crate::{
ir::{ ir::{
BuiltinType, FileSpan, FnDef, FnID, IRUFunction, Idents, IRUInstruction, IRInstructions, FileSpan, FnDef, FnID, IRInstructions, IRUFunction, IRUInstruction, Idents, NamespaceGuard,
NamespaceGuard, Origin, Type, VarDef, VarID, Origin, Type, VarDef, VarID,
}, },
parser, parser,
}; };
@@ -46,7 +46,7 @@ impl PFunction {
.collect(); .collect();
let ret = match &header.ret { let ret = match &header.ret {
Some(ty) => ty.lower(map, output), Some(ty) => ty.lower(map, output),
None => Type::Concrete(BuiltinType::Unit.id()), None => Type::Unit,
}; };
Some(map.def_fn(FnDef { Some(map.def_fn(FnDef {
name: name.to_string(), name: name.to_string(),
@@ -63,9 +63,7 @@ impl PFunction {
) -> IRUFunction { ) -> IRUFunction {
let mut instructions = IRInstructions::new(); let mut instructions = IRInstructions::new();
let def = map.get_fn(id).clone(); let def = map.get_fn(id).clone();
let args = def.args.iter().map(|a| { let args = def.args.iter().map(|a| map.named_var(a.clone())).collect();
map.named_var(a.clone())
}).collect();
let mut ctx = FnLowerCtx { let mut ctx = FnLowerCtx {
instructions: &mut instructions, instructions: &mut instructions,
map, map,
@@ -79,67 +77,6 @@ impl PFunction {
} }
} }
// impl Node<AsmFunction> {
// pub fn lower_header(
// &self,
// map: &mut NamespaceGuard,
// output: &mut ParserOutput,
// ) -> Option<FnIdent> {
// self.as_ref()?.lower_header(map, output)
// }
// pub fn lower_body(
// &self,
// map: &mut NamespaceGuard,
// output: &mut ParserOutput,
// ) -> Option<Function> {
// Some(self.as_ref()?.lower_body(map, output))
// }
// }
//
// impl AsmFunction {
// pub fn lower_header(
// &self,
// map: &mut NamespaceGuard,
// output: &mut ParserOutput,
// ) -> Option<FnIdent> {
// let header = self.header.as_ref()?;
// let name = header.name.as_ref()?;
// let args = header
// .args
// .iter()
// .map(|a| {
// // a.lower(map, output).unwrap_or(VarDef {
// // name: "{error}".to_string(),
// // origin: Origin::File(a.span),
// // ty: Type::Error,
// // })
// })
// .collect();
// // let ret = match &header.ret {
// // Some(ty) => ty.lower(map, output),
// // None => Type::Concrete(BuiltinType::Unit.id()),
// // };
// let ret = Type::Concrete(BuiltinType::Unit.id());
// Some(map.def_fn(FnDef {
// name: name.to_string(),
// origin: Origin::File(self.header.span),
// args,
// ret,
// }))
// }
// pub fn lower_body(&self, map: &mut NamespaceGuard, output: &mut ParserOutput) -> Function {
// let mut instructions = Instructions::new();
// let mut ctx = FnLowerCtx {
// instructions: &mut instructions,
// map,
// output,
// span: self.body.span,
// };
// self.body.lower(&mut ctx);
// Function::new(instructions)
// }
// }
pub struct FnLowerCtx<'a, 'n> { pub struct FnLowerCtx<'a, 'n> {
pub map: &'a mut NamespaceGuard<'n>, pub map: &'a mut NamespaceGuard<'n>,
pub instructions: &'a mut IRInstructions, pub instructions: &'a mut IRInstructions,

View File

@@ -7,15 +7,6 @@ pub struct PType {
pub args: Vec<Node<PType>>, pub args: Vec<Node<PType>>,
} }
impl PType {
pub fn unit() -> Self {
Self {
name: "()".to_string(),
args: Vec::new(),
}
}
}
impl Parsable for PType { impl Parsable for PType {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> { fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let next = ctx.expect_peek()?; let next = ctx.expect_peek()?;