finishing structures
This commit is contained in:
parent
bc59886428
commit
d5a5c932e7
|
@ -3,7 +3,19 @@ Ty := struct {
|
||||||
b: int,
|
b: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
main := fn(): int {
|
Ty2 := struct {
|
||||||
inst := Ty.{ a: 1, b: 2 };
|
ty: Ty,
|
||||||
return inst.a + inst.b;
|
c: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
main := fn(): int {
|
||||||
|
inst := Ty2.{ ty: Ty.{ a: 4, b: 1 }, c: 3 };
|
||||||
|
if inst.c == 3 {
|
||||||
|
return pass(inst.ty);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pass := fn(t: Ty): int {
|
||||||
|
return t.a - t.b;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
use crate::ident::Ident;
|
use crate::ident::Ident;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
|
@ -134,6 +136,13 @@ impl Func {
|
||||||
);
|
);
|
||||||
self.code.extend_from_slice(&instr[..len]);
|
self.code.extend_from_slice(&instr[..len]);
|
||||||
}
|
}
|
||||||
|
// ---- 0 24 bottom
|
||||||
|
// | 3
|
||||||
|
// ---- 8 16
|
||||||
|
// | 2
|
||||||
|
// ---- 16 8
|
||||||
|
// | 1
|
||||||
|
// ---- 24 0 top
|
||||||
|
|
||||||
fn push(&mut self, value: Reg, size: usize) {
|
fn push(&mut self, value: Reg, size: usize) {
|
||||||
self.subi64(STACK_PTR, STACK_PTR, size as _);
|
self.subi64(STACK_PTR, STACK_PTR, size as _);
|
||||||
|
@ -225,6 +234,10 @@ impl RegAlloc {
|
||||||
self.free.push(reg.0);
|
self.free.push(reg.0);
|
||||||
std::mem::forget(reg);
|
std::mem::forget(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prepare_call(&mut self) {
|
||||||
|
self.free.extend((2..=11).rev());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FnLabel {
|
struct FnLabel {
|
||||||
|
@ -256,39 +269,37 @@ struct Struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Codegen<'a> {
|
pub struct Codegen<'a> {
|
||||||
path: &'a std::path::Path,
|
path: &'a std::path::Path,
|
||||||
ret: Type,
|
ret: Type,
|
||||||
gpa: RegAlloc,
|
gpa: RegAlloc,
|
||||||
code: Func,
|
code: Func,
|
||||||
temp: Func,
|
temp: Func,
|
||||||
labels: Vec<FnLabel>,
|
labels: Vec<FnLabel>,
|
||||||
stack_size: u64,
|
stack_size: u64,
|
||||||
vars: Vec<Variable>,
|
vars: Vec<Variable>,
|
||||||
stack_relocs: Vec<StackReloc>,
|
|
||||||
ret_relocs: Vec<RetReloc>,
|
ret_relocs: Vec<RetReloc>,
|
||||||
loops: Vec<Loop>,
|
loops: Vec<Loop>,
|
||||||
records: Vec<Struct>,
|
records: Vec<Struct>,
|
||||||
pointers: Vec<Type>,
|
pointers: Vec<Type>,
|
||||||
main: Option<LabelId>,
|
main: Option<LabelId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Codegen<'a> {
|
impl<'a> Codegen<'a> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
path: std::path::Path::new(""),
|
path: std::path::Path::new(""),
|
||||||
ret: bt::VOID,
|
ret: bt::VOID,
|
||||||
gpa: Default::default(),
|
gpa: Default::default(),
|
||||||
code: Default::default(),
|
code: Default::default(),
|
||||||
temp: Default::default(),
|
temp: Default::default(),
|
||||||
labels: Default::default(),
|
labels: Default::default(),
|
||||||
stack_size: 0,
|
stack_size: 0,
|
||||||
vars: Default::default(),
|
vars: Default::default(),
|
||||||
stack_relocs: Default::default(),
|
|
||||||
ret_relocs: Default::default(),
|
ret_relocs: Default::default(),
|
||||||
loops: Default::default(),
|
loops: Default::default(),
|
||||||
records: Default::default(),
|
records: Default::default(),
|
||||||
pointers: Default::default(),
|
pointers: Default::default(),
|
||||||
main: None,
|
main: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +345,11 @@ impl<'a> Codegen<'a> {
|
||||||
self.gpa.free(dreg);
|
self.gpa.free(dreg);
|
||||||
reg
|
reg
|
||||||
}
|
}
|
||||||
|
Loc::DerefRef(dreg) => {
|
||||||
|
let reg = self.gpa.allocate();
|
||||||
|
self.code.encode(instrs::ld(reg.0, dreg, 0, 8));
|
||||||
|
reg
|
||||||
|
}
|
||||||
Loc::Imm(imm) => {
|
Loc::Imm(imm) => {
|
||||||
let reg = self.gpa.allocate();
|
let reg = self.gpa.allocate();
|
||||||
self.code.encode(instrs::li64(reg.0, imm));
|
self.code.encode(instrs::li64(reg.0, imm));
|
||||||
|
@ -349,35 +365,19 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
fn alloc_stack(&mut self, size: u32) -> u64 {
|
fn alloc_stack(&mut self, size: u32) -> u64 {
|
||||||
let offset = self.stack_size;
|
let offset = self.stack_size;
|
||||||
|
log::dbg!("alloc_stack: {} {}", offset, size);
|
||||||
self.stack_size += size as u64;
|
self.stack_size += size as u64;
|
||||||
offset
|
offset
|
||||||
}
|
}
|
||||||
|
|
||||||
fn store_stack(&mut self, reg: Reg, offset: u64, size: u16) {
|
fn store_stack(&mut self, reg: Reg, offset: u64, size: u16) {
|
||||||
self.stack_relocs.push(StackReloc {
|
|
||||||
offset: self.code.code.len() as u32 + 3,
|
|
||||||
size,
|
|
||||||
});
|
|
||||||
self.code.encode(instrs::st(reg, STACK_PTR, offset, size));
|
self.code.encode(instrs::st(reg, STACK_PTR, offset, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_stack(&mut self, reg: Reg, offset: u64, size: u16) {
|
fn load_stack(&mut self, reg: Reg, offset: u64, size: u16) {
|
||||||
self.stack_relocs.push(StackReloc {
|
|
||||||
offset: self.code.code.len() as u32 + 3,
|
|
||||||
size,
|
|
||||||
});
|
|
||||||
self.code.encode(instrs::ld(reg, STACK_PTR, offset, size));
|
self.code.encode(instrs::ld(reg, STACK_PTR, offset, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reloc_stack(&mut self) {
|
|
||||||
for reloc in self.stack_relocs.drain(..) {
|
|
||||||
let dest = &mut self.code.code[reloc.offset as usize..][..reloc.size as usize];
|
|
||||||
let value = u64::from_ne_bytes(dest.try_into().unwrap());
|
|
||||||
let offset = self.stack_size - value;
|
|
||||||
dest.copy_from_slice(&offset.to_ne_bytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reloc_rets(&mut self) {
|
fn reloc_rets(&mut self) {
|
||||||
let len = self.code.code.len() as i32;
|
let len = self.code.code.len() as i32;
|
||||||
for reloc in self.ret_relocs.drain(..) {
|
for reloc in self.ret_relocs.drain(..) {
|
||||||
|
@ -411,18 +411,24 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
fn expr(&mut self, expr: &'a parser::Expr<'a>, expeted: Option<Type>) -> Option<Value> {
|
fn expr(&mut self, expr: &'a parser::Expr<'a>, expeted: Option<Type>) -> Option<Value> {
|
||||||
match *expr {
|
match *expr {
|
||||||
|
E::Bool { value, .. } => Some(Value {
|
||||||
|
ty: bt::BOOL,
|
||||||
|
loc: Loc::Imm(value as u64),
|
||||||
|
}),
|
||||||
E::Ctor { ty, fields } => {
|
E::Ctor { ty, fields } => {
|
||||||
let ty = self.ty(&ty);
|
let ty = self.ty(&ty);
|
||||||
let TypeKind::Struct(idx) = TypeKind::from_ty(ty) else {
|
let TypeKind::Struct(idx) = TypeKind::from_ty(ty) else {
|
||||||
panic!("expected struct, got {:?}", ty);
|
panic!("expected struct, got {:?}", ty);
|
||||||
};
|
};
|
||||||
let size = self.size_of(ty);
|
|
||||||
let stack = self.alloc_stack(size as u32);
|
|
||||||
let mut field_values = fields
|
let mut field_values = fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, field)| self.expr(field, None).map(|v| (*name, v)))
|
.map(|(name, field)| self.expr(field, None).map(|v| (*name, v)))
|
||||||
.collect::<Option<Vec<_>>>()?;
|
.collect::<Option<Vec<_>>>()?;
|
||||||
|
|
||||||
|
let size = self.size_of(ty);
|
||||||
|
let stack = self.alloc_stack(size as u32);
|
||||||
|
|
||||||
let decl_fields = self.records[idx as usize].fields.clone();
|
let decl_fields = self.records[idx as usize].fields.clone();
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for (name, ty) in decl_fields.as_ref() {
|
for (name, ty) in decl_fields.as_ref() {
|
||||||
|
@ -434,10 +440,15 @@ impl<'a> Codegen<'a> {
|
||||||
if value.ty != *ty {
|
if value.ty != *ty {
|
||||||
panic!("expected {:?}, got {:?}", ty, value.ty);
|
panic!("expected {:?}, got {:?}", ty, value.ty);
|
||||||
}
|
}
|
||||||
let reg = self.loc_to_reg(value.loc);
|
log::dbg!("ctor: {} {} {:?}", stack, offset, value.loc);
|
||||||
self.store_stack(reg.0, stack + offset, 8);
|
self.assign(
|
||||||
self.gpa.free(reg);
|
Value {
|
||||||
offset += 8;
|
ty: value.ty,
|
||||||
|
loc: Loc::Stack(stack + offset),
|
||||||
|
},
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
offset += self.size_of(*ty);
|
||||||
}
|
}
|
||||||
Some(Value {
|
Some(Value {
|
||||||
ty,
|
ty,
|
||||||
|
@ -454,18 +465,25 @@ impl<'a> Codegen<'a> {
|
||||||
.iter()
|
.iter()
|
||||||
.position(|(name, _)| name.as_ref() == field)
|
.position(|(name, _)| name.as_ref() == field)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let size = self.size_of(decl_fields[index].1);
|
let offset = decl_fields[..index]
|
||||||
assert_eq!(size, 8, "TODO: implement other sizes");
|
.iter()
|
||||||
|
.map(|(_, ty)| self.size_of(*ty))
|
||||||
|
.sum::<u64>();
|
||||||
let value = match target.loc {
|
let value = match target.loc {
|
||||||
Loc::Reg(_) => todo!(),
|
Loc::Reg(_) => todo!(),
|
||||||
Loc::RegRef(_) => todo!(),
|
Loc::RegRef(_) => todo!(),
|
||||||
Loc::Deref(r) => {
|
Loc::Deref(r) => {
|
||||||
self.code.encode(instrs::addi64(r.0, r.0, index as u64 * 8));
|
self.code.encode(instrs::addi64(r.0, r.0, offset));
|
||||||
Loc::Deref(r)
|
Loc::Deref(r)
|
||||||
}
|
}
|
||||||
|
Loc::DerefRef(r) => {
|
||||||
|
let reg = self.gpa.allocate();
|
||||||
|
self.code.encode(instrs::addi64(reg.0, r, offset));
|
||||||
|
Loc::Deref(reg)
|
||||||
|
}
|
||||||
Loc::Imm(_) => todo!(),
|
Loc::Imm(_) => todo!(),
|
||||||
Loc::Stack(stack) => Loc::Stack(stack + index as u64 * 8),
|
Loc::Stack(stack) => Loc::Stack(stack + offset),
|
||||||
Loc::StackRef(stack) => Loc::StackRef(stack + index as u64 * 8),
|
Loc::StackRef(stack) => Loc::StackRef(stack + offset),
|
||||||
};
|
};
|
||||||
Some(Value {
|
Some(Value {
|
||||||
ty: decl_fields[index].1,
|
ty: decl_fields[index].1,
|
||||||
|
@ -491,10 +509,6 @@ impl<'a> Codegen<'a> {
|
||||||
match val.loc {
|
match val.loc {
|
||||||
Loc::StackRef(off) => {
|
Loc::StackRef(off) => {
|
||||||
let reg = self.gpa.allocate();
|
let reg = self.gpa.allocate();
|
||||||
self.stack_relocs.push(StackReloc {
|
|
||||||
offset: self.code.code.len() as u32 + 3,
|
|
||||||
size: 8,
|
|
||||||
});
|
|
||||||
self.code.encode(instrs::addi64(reg.0, STACK_PTR, off));
|
self.code.encode(instrs::addi64(reg.0, STACK_PTR, off));
|
||||||
Some(Value {
|
Some(Value {
|
||||||
ty: self.alloc_pointer(val.ty),
|
ty: self.alloc_pointer(val.ty),
|
||||||
|
@ -529,35 +543,36 @@ impl<'a> Codegen<'a> {
|
||||||
if *name == "main" {
|
if *name == "main" {
|
||||||
self.main = Some(frame.label);
|
self.main = Some(frame.label);
|
||||||
}
|
}
|
||||||
|
|
||||||
log::dbg!("fn-args");
|
log::dbg!("fn-args");
|
||||||
for (i, arg) in args.iter().enumerate() {
|
let mut parama = 2..12;
|
||||||
let offset = self.alloc_stack(8);
|
for arg in args.iter() {
|
||||||
let ty = self.ty(&arg.ty);
|
let ty = self.ty(&arg.ty);
|
||||||
|
let loc = self.load_arg(ty, &mut parama);
|
||||||
self.vars.push(Variable {
|
self.vars.push(Variable {
|
||||||
id: arg.id,
|
id: arg.id,
|
||||||
value: Value {
|
value: Value { ty, loc },
|
||||||
ty,
|
|
||||||
loc: Loc::Stack(offset),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
self.store_stack(i as Reg + 2, offset, 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.gpa.init_callee();
|
self.gpa.init_callee();
|
||||||
self.ret = self.ty(ret);
|
self.ret = self.ty(ret);
|
||||||
|
|
||||||
log::dbg!("fn-body");
|
log::dbg!("fn-body");
|
||||||
if self.expr(body, None).is_some() {
|
if self.expr(body, None).is_some() {
|
||||||
panic!("expected all paths in the fucntion {name} to return");
|
panic!("expected all paths in the fucntion {name} to return");
|
||||||
}
|
}
|
||||||
self.vars.clear();
|
self.vars.clear();
|
||||||
|
|
||||||
|
log::dbg!("fn-prelude, stack: {:x}", self.stack_size);
|
||||||
|
|
||||||
log::dbg!("fn-relocs");
|
log::dbg!("fn-relocs");
|
||||||
self.reloc_stack();
|
|
||||||
log::dbg!("fn-prelude");
|
|
||||||
self.write_fn_prelude(frame);
|
self.write_fn_prelude(frame);
|
||||||
|
|
||||||
log::dbg!("fn-ret");
|
log::dbg!("fn-ret");
|
||||||
self.reloc_rets();
|
self.reloc_rets();
|
||||||
self.ret();
|
self.ret();
|
||||||
self.stack_size = 0;
|
self.stack_size = 0;
|
||||||
self.vars.clear();
|
|
||||||
Some(Value::VOID)
|
Some(Value::VOID)
|
||||||
}
|
}
|
||||||
E::BinOp {
|
E::BinOp {
|
||||||
|
@ -578,11 +593,10 @@ impl<'a> Codegen<'a> {
|
||||||
func: E::Ident { id, .. },
|
func: E::Ident { id, .. },
|
||||||
args,
|
args,
|
||||||
} => {
|
} => {
|
||||||
for (i, arg) in args.iter().enumerate() {
|
let mut parama = 2..12;
|
||||||
|
for arg in args.iter() {
|
||||||
let arg = self.expr(arg, None)?;
|
let arg = self.expr(arg, None)?;
|
||||||
let reg = self.loc_to_reg(arg.loc);
|
self.pass_arg(arg, &mut parama);
|
||||||
self.code.encode(instrs::cp(i as Reg + 2, reg.0));
|
|
||||||
self.gpa.free(reg);
|
|
||||||
}
|
}
|
||||||
let func = self.get_or_reserve_label(*id);
|
let func = self.get_or_reserve_label(*id);
|
||||||
self.code.call(func);
|
self.code.call(func);
|
||||||
|
@ -784,21 +798,60 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign(&mut self, left: Value, right: Value) -> Option<Value> {
|
fn assign(&mut self, right: Value, left: Value) -> Option<Value> {
|
||||||
let rhs = self.loc_to_reg(right.loc);
|
let size = self.size_of(left.ty);
|
||||||
match left.loc {
|
|
||||||
Loc::Deref(reg) => {
|
match size {
|
||||||
self.code.encode(instrs::st(rhs.0, reg.0, 0, 8));
|
8 => {
|
||||||
self.gpa.free(reg);
|
let lhs = self.loc_to_reg(left.loc);
|
||||||
|
match right.loc {
|
||||||
|
Loc::Deref(reg) => {
|
||||||
|
self.code.encode(instrs::st(lhs.0, reg.0, 0, 8));
|
||||||
|
self.gpa.free(reg);
|
||||||
|
}
|
||||||
|
Loc::RegRef(reg) => self.code.encode(instrs::cp(reg, lhs.0)),
|
||||||
|
Loc::StackRef(offset) | Loc::Stack(offset) => {
|
||||||
|
self.store_stack(lhs.0, offset, 8)
|
||||||
|
}
|
||||||
|
l => unimplemented!("{:?}", l),
|
||||||
|
}
|
||||||
|
self.gpa.free(lhs);
|
||||||
}
|
}
|
||||||
Loc::RegRef(reg) => self.code.encode(instrs::cp(reg, rhs.0)),
|
16..=u64::MAX => {
|
||||||
Loc::StackRef(offset) => self.store_stack(rhs.0, offset, 8),
|
let rhs = self.loc_to_ptr(right.loc);
|
||||||
_ => unimplemented!(),
|
let lhs = self.loc_to_ptr(left.loc);
|
||||||
|
let cp = self.gpa.allocate();
|
||||||
|
for offset in (0..size).step_by(8) {
|
||||||
|
self.code.encode(instrs::ld(cp.0, lhs.0, offset, 8));
|
||||||
|
self.code.encode(instrs::st(cp.0, rhs.0, offset, 8));
|
||||||
|
}
|
||||||
|
self.gpa.free(rhs);
|
||||||
|
self.gpa.free(lhs);
|
||||||
|
self.gpa.free(cp);
|
||||||
|
}
|
||||||
|
s => unimplemented!("size: {}", s),
|
||||||
}
|
}
|
||||||
self.gpa.free(rhs);
|
|
||||||
Some(Value::VOID)
|
Some(Value::VOID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn loc_to_ptr(&mut self, loc: Loc) -> LinReg {
|
||||||
|
match loc {
|
||||||
|
Loc::Deref(reg) => reg,
|
||||||
|
Loc::DerefRef(reg) => {
|
||||||
|
let dreg = self.gpa.allocate();
|
||||||
|
self.code.encode(instrs::cp(dreg.0, reg));
|
||||||
|
dreg
|
||||||
|
}
|
||||||
|
Loc::Stack(offset) | Loc::StackRef(offset) => {
|
||||||
|
let reg = self.gpa.allocate();
|
||||||
|
self.code.encode(instrs::addi64(reg.0, STACK_PTR, offset));
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
l => panic!("expected stack location, got {:?}", l),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_or_reserve_label(&mut self, name: Ident) -> LabelId {
|
fn get_or_reserve_label(&mut self, name: Ident) -> LabelId {
|
||||||
if let Some(label) = self.labels.iter().position(|l| l.name == name) {
|
if let Some(label) = self.labels.iter().position(|l| l.name == name) {
|
||||||
label as u32
|
label as u32
|
||||||
|
@ -897,23 +950,94 @@ impl<'a> Codegen<'a> {
|
||||||
self.code.encode(instrs::li64(reg.0, imm));
|
self.code.encode(instrs::li64(reg.0, imm));
|
||||||
Loc::Reg(reg)
|
Loc::Reg(reg)
|
||||||
}
|
}
|
||||||
Loc::StackRef(mut off) => {
|
Loc::StackRef(off) => {
|
||||||
let size = self.size_of(ty);
|
let size = self.size_of(ty);
|
||||||
assert!(size % 8 == 0, "TODO: implement other sizes");
|
|
||||||
let stack = self.alloc_stack(size as u32);
|
let stack = self.alloc_stack(size as u32);
|
||||||
let reg = self.gpa.allocate();
|
self.assign(
|
||||||
while size > 0 {
|
Value {
|
||||||
self.load_stack(reg.0, off, 8);
|
ty,
|
||||||
self.store_stack(reg.0, stack, 8);
|
loc: Loc::Stack(stack),
|
||||||
off += 8;
|
},
|
||||||
}
|
Value {
|
||||||
self.gpa.free(reg);
|
ty,
|
||||||
|
loc: Loc::StackRef(off),
|
||||||
|
},
|
||||||
|
);
|
||||||
Loc::Stack(stack)
|
Loc::Stack(stack)
|
||||||
}
|
}
|
||||||
l => l,
|
l => l,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pass_arg(&mut self, value: Value, parama: &mut Range<u8>) {
|
||||||
|
let size = self.size_of(value.ty);
|
||||||
|
let p = parama.next().unwrap() as Reg;
|
||||||
|
|
||||||
|
if size > 16 {
|
||||||
|
let (Loc::Stack(stack) | Loc::StackRef(stack)) = value.loc else {
|
||||||
|
panic!("expected stack location, got {:?}", value.loc);
|
||||||
|
};
|
||||||
|
self.code.encode(instrs::addi64(p, STACK_PTR, stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
match value.loc {
|
||||||
|
Loc::Reg(reg) => {
|
||||||
|
self.code.encode(instrs::cp(p, reg.0));
|
||||||
|
self.gpa.free(reg);
|
||||||
|
}
|
||||||
|
Loc::RegRef(reg) => {
|
||||||
|
self.code.encode(instrs::cp(p, reg));
|
||||||
|
}
|
||||||
|
Loc::Deref(reg) => {
|
||||||
|
self.code.encode(instrs::ld(p, reg.0, 0, size as _));
|
||||||
|
self.gpa.free(reg);
|
||||||
|
}
|
||||||
|
Loc::DerefRef(reg) => {
|
||||||
|
self.code.encode(instrs::ld(p, reg, 0, size as _));
|
||||||
|
}
|
||||||
|
Loc::Imm(imm) => {
|
||||||
|
self.code.encode(instrs::li64(p, imm));
|
||||||
|
}
|
||||||
|
Loc::Stack(stack) | Loc::StackRef(stack) => {
|
||||||
|
self.load_stack(p, stack, size as _);
|
||||||
|
self.load_stack(parama.next().unwrap(), stack + 8, size as _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_arg(&mut self, ty: Type, parama: &mut Range<u8>) -> Loc {
|
||||||
|
let size = self.size_of(ty);
|
||||||
|
match size {
|
||||||
|
8 => {
|
||||||
|
let stack = self.alloc_stack(8);
|
||||||
|
self.store_stack(parama.next().unwrap(), stack, 8);
|
||||||
|
Loc::Stack(stack)
|
||||||
|
}
|
||||||
|
16 => {
|
||||||
|
let stack = self.alloc_stack(16);
|
||||||
|
self.store_stack(parama.next().unwrap(), stack, 8);
|
||||||
|
self.store_stack(parama.next().unwrap(), stack + 8, 8);
|
||||||
|
Loc::Stack(stack)
|
||||||
|
}
|
||||||
|
24..=u64::MAX => {
|
||||||
|
let ptr = parama.next().unwrap();
|
||||||
|
let stack = self.alloc_stack(size as u32);
|
||||||
|
self.assign(
|
||||||
|
Value {
|
||||||
|
ty,
|
||||||
|
loc: Loc::StackRef(stack),
|
||||||
|
},
|
||||||
|
Value {
|
||||||
|
ty,
|
||||||
|
loc: Loc::DerefRef(ptr),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
Loc::Stack(stack)
|
||||||
|
}
|
||||||
|
blah => todo!("{blah:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ensure_spilled(&mut self, loc: Loc) -> Loc {
|
fn ensure_spilled(&mut self, loc: Loc) -> Loc {
|
||||||
match loc {
|
match loc {
|
||||||
Loc::Reg(reg) => {
|
Loc::Reg(reg) => {
|
||||||
|
@ -944,6 +1068,7 @@ enum Loc {
|
||||||
Reg(LinReg),
|
Reg(LinReg),
|
||||||
RegRef(Reg),
|
RegRef(Reg),
|
||||||
Deref(LinReg),
|
Deref(LinReg),
|
||||||
|
DerefRef(Reg),
|
||||||
Imm(u64),
|
Imm(u64),
|
||||||
Stack(u64),
|
Stack(u64),
|
||||||
StackRef(u64),
|
StackRef(u64),
|
||||||
|
@ -976,7 +1101,7 @@ mod tests {
|
||||||
"read: {:x} {} {:?}",
|
"read: {:x} {} {:?}",
|
||||||
addr.get(),
|
addr.get(),
|
||||||
count,
|
count,
|
||||||
core::slice::from_raw_parts(target, count)
|
core::slice::from_raw_parts(addr.get() as *const u8, count)
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.skip_while(|&&b| b == 0)
|
.skip_while(|&&b| b == 0)
|
||||||
|
@ -994,7 +1119,17 @@ mod tests {
|
||||||
source: *const u8,
|
source: *const u8,
|
||||||
count: usize,
|
count: usize,
|
||||||
) -> Result<(), hbvm::mem::StoreError> {
|
) -> Result<(), hbvm::mem::StoreError> {
|
||||||
log::dbg!("write: {:x} {}", addr.get(), count);
|
log::dbg!(
|
||||||
|
"write: {:x} {} {:?}",
|
||||||
|
addr.get(),
|
||||||
|
count,
|
||||||
|
core::slice::from_raw_parts(source, count)
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.skip_while(|&&b| b == 0)
|
||||||
|
.map(|&b| format!("{:02x}", b))
|
||||||
|
.collect::<String>()
|
||||||
|
);
|
||||||
unsafe { core::ptr::copy(source, addr.get() as *mut u8, count) }
|
unsafe { core::ptr::copy(source, addr.get() as *mut u8, count) }
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,7 @@ gen_token_kind! {
|
||||||
Continue = b"continue",
|
Continue = b"continue",
|
||||||
Fn = b"fn",
|
Fn = b"fn",
|
||||||
Struct = b"struct",
|
Struct = b"struct",
|
||||||
|
True = b"true",
|
||||||
#[punkt]
|
#[punkt]
|
||||||
LParen = "(",
|
LParen = "(",
|
||||||
RParen = ")",
|
RParen = ")",
|
||||||
|
|
|
@ -96,6 +96,8 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
Some(match name {
|
Some(match name {
|
||||||
"int" => bt::INT,
|
"int" => bt::INT,
|
||||||
"bool" => bt::BOOL,
|
"bool" => bt::BOOL,
|
||||||
|
"void" => bt::VOID,
|
||||||
|
"never" => bt::NEVER,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -139,6 +141,10 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
let frame = self.idents.len();
|
let frame = self.idents.len();
|
||||||
let token = self.next();
|
let token = self.next();
|
||||||
let mut expr = match token.kind {
|
let mut expr = match token.kind {
|
||||||
|
T::True => E::Bool {
|
||||||
|
pos: token.start,
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
T::Struct => E::Struct {
|
T::Struct => E::Struct {
|
||||||
pos: token.start,
|
pos: token.start,
|
||||||
fields: {
|
fields: {
|
||||||
|
@ -399,6 +405,10 @@ pub enum Expr<'a> {
|
||||||
target: &'a Self,
|
target: &'a Self,
|
||||||
field: &'a str,
|
field: &'a str,
|
||||||
},
|
},
|
||||||
|
Bool {
|
||||||
|
pos: u32,
|
||||||
|
value: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::fmt::Display for Expr<'a> {
|
impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
|
@ -488,6 +498,7 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
Self::Number { value, .. } => write!(f, "{}", value),
|
Self::Number { value, .. } => write!(f, "{}", value),
|
||||||
|
Self::Bool { value, .. } => write!(f, "{}", value),
|
||||||
Self::BinOp { left, right, op } => {
|
Self::BinOp { left, right, op } => {
|
||||||
let display_branch = |f: &mut std::fmt::Formatter, expr: &Self| {
|
let display_branch = |f: &mut std::fmt::Formatter, expr: &Self| {
|
||||||
if let Self::BinOp { op: lop, .. } = expr
|
if let Self::BinOp { op: lop, .. } = expr
|
||||||
|
|
Loading…
Reference in a new issue