forked from AbleOS/holey-bytes
structs work with optimizations
This commit is contained in:
parent
11f6537a09
commit
4336fec653
|
@ -174,7 +174,7 @@ main := fn(): int {
|
||||||
return 9001
|
return 9001
|
||||||
}
|
}
|
||||||
|
|
||||||
finst := Ty2.{ty: .{a: @bitcast(@sizeof(u32)), b: 1}, c: 3}
|
finst := Ty2.{ty: .{a: 4, b: 1}, c: 3}
|
||||||
inst := odher_pass(finst)
|
inst := odher_pass(finst)
|
||||||
if inst.c == 3 {
|
if inst.c == 3 {
|
||||||
return pass(&inst.ty)
|
return pass(&inst.ty)
|
||||||
|
@ -183,8 +183,7 @@ main := fn(): int {
|
||||||
}
|
}
|
||||||
|
|
||||||
pass := fn(t: ^Ty): int {
|
pass := fn(t: ^Ty): int {
|
||||||
.{a, b} := *t
|
return t.a - t.b
|
||||||
return a - b
|
|
||||||
}
|
}
|
||||||
|
|
||||||
odher_pass := fn(t: Ty2): Ty2 {
|
odher_pass := fn(t: Ty2): Ty2 {
|
||||||
|
|
|
@ -1214,7 +1214,6 @@ impl Types {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(not(feature = "opts"), expect(dead_code))]
|
#[cfg_attr(not(feature = "opts"), expect(dead_code))]
|
||||||
#[expect(dead_code)]
|
|
||||||
fn find_struct_field(&self, s: ty::Struct, name: &str) -> Option<usize> {
|
fn find_struct_field(&self, s: ty::Struct, name: &str) -> Option<usize> {
|
||||||
let name = self.names.project(name)?;
|
let name = self.names.project(name)?;
|
||||||
self.struct_fields(s).iter().position(|f| f.name == name)
|
self.struct_fields(s).iter().position(|f| f.name == name)
|
||||||
|
|
442
lang/src/son.rs
442
lang/src/son.rs
|
@ -12,7 +12,7 @@ use {
|
||||||
reg, task,
|
reg, task,
|
||||||
ty::{self},
|
ty::{self},
|
||||||
vc::{BitSet, Vc},
|
vc::{BitSet, Vc},
|
||||||
Func, HashMap, Offset, Reloc, Sig, Size, SymKey, TypedReloc, Types,
|
Func, HashMap, Offset, OffsetIter, Reloc, Sig, SymKey, TypedReloc, Types,
|
||||||
},
|
},
|
||||||
alloc::{borrow::ToOwned, string::String, vec::Vec},
|
alloc::{borrow::ToOwned, string::String, vec::Vec},
|
||||||
core::{
|
core::{
|
||||||
|
@ -567,30 +567,28 @@ impl Nodes {
|
||||||
target
|
target
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_loop_value(&mut self, index: usize, value: &mut Nid, loops: &mut [Loop]) {
|
fn load_loop_value(&mut self, index: usize, value: &mut Value, loops: &mut [Loop]) {
|
||||||
if *value != 0 {
|
if value.id != 0 {
|
||||||
|
debug_assert!(!value.var);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let [loob, loops @ ..] = loops else { unreachable!() };
|
let [loob, loops @ ..] = loops else { unreachable!() };
|
||||||
let lvalue = &mut loob.scope[index].value;
|
let lvalue = &mut loob.scope[index].value;
|
||||||
|
|
||||||
self.load_loop_value(index, &mut lvalue.id, loops);
|
self.load_loop_value(index, lvalue, loops);
|
||||||
|
|
||||||
if !self[lvalue.id].is_lazy_phi() {
|
if !self[lvalue.id].is_lazy_phi() {
|
||||||
self.unlock(*value);
|
self.unlock(value.id);
|
||||||
let inps = [loob.node, lvalue.id, VOID];
|
let inps = [loob.node, lvalue.id, VOID];
|
||||||
self.unlock(inps[1]);
|
self.unlock(lvalue.id);
|
||||||
let ty = self[inps[1]].ty;
|
lvalue.id = self.new_node_nop(lvalue.ty, Kind::Phi, inps);
|
||||||
let phi = self.new_node_nop(ty, Kind::Phi, inps);
|
self[lvalue.id].lock_rc += 2;
|
||||||
self[phi].lock_rc += 2;
|
|
||||||
*value = phi;
|
|
||||||
lvalue.id = phi;
|
|
||||||
} else {
|
} else {
|
||||||
self.lock(lvalue.id);
|
self.lock(lvalue.id);
|
||||||
self.unlock(*value);
|
self.unlock(value.id);
|
||||||
*value = lvalue.id;
|
|
||||||
}
|
}
|
||||||
|
*value = *lvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_dominance(&mut self, nd: Nid, min: Nid, check_outputs: bool) {
|
fn check_dominance(&mut self, nd: Nid, min: Nid, check_outputs: bool) {
|
||||||
|
@ -789,13 +787,6 @@ struct Variable {
|
||||||
value: Value,
|
value: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
|
||||||
struct MemKey {
|
|
||||||
region: Nid,
|
|
||||||
offset: u32,
|
|
||||||
node: Nid,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ItemCtx {
|
struct ItemCtx {
|
||||||
file: FileId,
|
file: FileId,
|
||||||
|
@ -813,7 +804,8 @@ struct ItemCtx {
|
||||||
|
|
||||||
loops: Vec<Loop>,
|
loops: Vec<Loop>,
|
||||||
vars: Vec<Variable>,
|
vars: Vec<Variable>,
|
||||||
memories: Vec<MemKey>,
|
store: Option<Nid>,
|
||||||
|
loads: Vec<Nid>,
|
||||||
clobbered: Vec<Nid>,
|
clobbered: Vec<Nid>,
|
||||||
ret_relocs: Vec<Reloc>,
|
ret_relocs: Vec<Reloc>,
|
||||||
relocs: Vec<TypedReloc>,
|
relocs: Vec<TypedReloc>,
|
||||||
|
@ -899,7 +891,11 @@ impl Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn var(id: usize) -> Self {
|
pub fn var(id: usize) -> Self {
|
||||||
Self { id: id as Nid, var: true, ..Default::default() }
|
Self { id: u16::MAX - (id as Nid), var: true, ..Default::default() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ptr(id: Nid) -> Self {
|
||||||
|
Self { id, ptr: true, ..Default::default() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -908,7 +904,6 @@ impl Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[expect(dead_code)]
|
|
||||||
pub fn off(self, off: Offset) -> Self {
|
pub fn off(self, off: Offset) -> Self {
|
||||||
Self { off, ..self }
|
Self { off, ..self }
|
||||||
}
|
}
|
||||||
|
@ -964,56 +959,36 @@ impl Codegen {
|
||||||
log::info!("{out}");
|
log::info!("{out}");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn region_range(&self, region: Nid, offset: Offset, size: Size) -> core::ops::Range<usize> {
|
|
||||||
let start = self
|
|
||||||
.ci
|
|
||||||
.memories
|
|
||||||
.binary_search_by_key(&(region, offset), |k| (k.region, k.offset))
|
|
||||||
.unwrap_or_else(core::convert::identity);
|
|
||||||
let end = self
|
|
||||||
.ci
|
|
||||||
.memories
|
|
||||||
.binary_search_by(|k| (k.region, k.offset).cmp(&(region, offset + size)))
|
|
||||||
.unwrap_or_else(core::convert::identity);
|
|
||||||
|
|
||||||
start..end
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mem_op(&mut self, region: Nid, offset: Offset, kind: Kind, ty: ty::Id, mut inps: Vc) -> Nid {
|
|
||||||
let size = self.tys.size_of(ty);
|
|
||||||
let range = self.region_range(region, offset, size);
|
|
||||||
|
|
||||||
for mk in &self.ci.memories[range.clone()] {
|
|
||||||
debug_assert_eq!(mk.region, region);
|
|
||||||
debug_assert!(mk.offset >= offset);
|
|
||||||
debug_assert!(mk.offset < offset + size);
|
|
||||||
inps.push(mk.node);
|
|
||||||
}
|
|
||||||
|
|
||||||
if range.is_empty() {
|
|
||||||
inps.push(region);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (new_op, peeped) = self.ci.nodes.new_node_low(ty, kind, inps);
|
|
||||||
if !peeped {
|
|
||||||
for mk in &self.ci.memories[range.clone()] {
|
|
||||||
self.ci.nodes.unlock(mk.node);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.ci
|
|
||||||
.memories
|
|
||||||
.splice(range, core::iter::once(MemKey { node: new_op, region, offset }));
|
|
||||||
self.ci.nodes.lock(new_op);
|
|
||||||
}
|
|
||||||
new_op
|
|
||||||
}
|
|
||||||
|
|
||||||
fn store_mem(&mut self, region: Nid, offset: Offset, value: Nid) -> Nid {
|
fn store_mem(&mut self, region: Nid, offset: Offset, value: Nid) -> Nid {
|
||||||
self.mem_op(region, offset, Kind::Stre { offset }, self.tof(value), [VOID, value].into())
|
let mut vc = Vc::from([VOID, value, region]);
|
||||||
|
if let Some(str) = self.ci.store {
|
||||||
|
self.ci.nodes.unlock(str);
|
||||||
|
vc.push(str);
|
||||||
|
}
|
||||||
|
for load in self.ci.loads.drain(..) {
|
||||||
|
if load == value {
|
||||||
|
self.ci.nodes.unlock(load);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if !self.ci.nodes.unlock_remove(load) {
|
||||||
|
vc.push(load);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let store = self.ci.nodes.new_node(self.tof(value), Kind::Stre { offset }, vc);
|
||||||
|
self.ci.nodes.lock(store);
|
||||||
|
self.ci.store = Some(store);
|
||||||
|
store
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_mem(&mut self, region: Nid, offset: Offset, ty: ty::Id) -> Nid {
|
fn load_mem(&mut self, region: Nid, offset: Offset, ty: ty::Id) -> Nid {
|
||||||
self.mem_op(region, offset, Kind::Load { offset }, ty, [VOID].into())
|
let mut vc = Vc::from([VOID, region]);
|
||||||
|
if let Some(str) = self.ci.store {
|
||||||
|
vc.push(str);
|
||||||
|
}
|
||||||
|
let load = self.ci.nodes.new_node(ty, Kind::Load { offset }, vc);
|
||||||
|
self.ci.nodes.lock(load);
|
||||||
|
self.ci.loads.push(load);
|
||||||
|
load
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate(&mut self) {
|
pub fn generate(&mut self) {
|
||||||
|
@ -1046,11 +1021,13 @@ impl Codegen {
|
||||||
return Value::NEVER;
|
return Value::NEVER;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log::info!("{}", self.ty_display(self.ci.nodes[self.ci.vars[index].value.id].ty));
|
||||||
self.ci.nodes.load_loop_value(
|
self.ci.nodes.load_loop_value(
|
||||||
index,
|
index,
|
||||||
&mut self.ci.vars[index].value.id,
|
&mut self.ci.vars[index].value,
|
||||||
&mut self.ci.loops,
|
&mut self.ci.loops,
|
||||||
);
|
);
|
||||||
|
debug_assert_ne!(self.ci.vars[index].value.ty, ty::Id::VOID);
|
||||||
|
|
||||||
Some(Value::var(index).ty(self.ci.vars[index].value.ty))
|
Some(Value::var(index).ty(self.ci.vars[index].value.ty))
|
||||||
}
|
}
|
||||||
|
@ -1067,8 +1044,8 @@ impl Codegen {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut inps = Vc::from([self.ci.ctrl, value.id]);
|
let mut inps = Vc::from([self.ci.ctrl, value.id]);
|
||||||
for m in self.ci.memories.iter() {
|
for &m in self.ci.store.iter() {
|
||||||
inps.push(m.node);
|
inps.push(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.ctrl = self.ci.nodes.new_node(ty::Id::VOID, Kind::Return, inps);
|
self.ci.ctrl = self.ci.nodes.new_node(ty::Id::VOID, Kind::Return, inps);
|
||||||
|
@ -1081,44 +1058,44 @@ impl Codegen {
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
//Expr::Field { target, name, pos } => {
|
Expr::Field { target, name, pos } => {
|
||||||
// let vtarget = self.raw_expr(target)?;
|
let mut vtarget = self.raw_expr(target)?;
|
||||||
// let tty = vtarget.ty;
|
self.strip_var(&mut vtarget);
|
||||||
|
let tty = vtarget.ty;
|
||||||
|
|
||||||
// let ty::Kind::Struct(s) = self.tys.base_of(tty).unwrap_or(tty).expand() else {
|
let ty::Kind::Struct(s) = self.tys.base_of(tty).unwrap_or(tty).expand() else {
|
||||||
// self.report(
|
self.report(
|
||||||
// pos,
|
pos,
|
||||||
// fa!(
|
fa!(
|
||||||
// "the '{}' is not a struct, or pointer to one, \
|
"the '{}' is not a struct, or pointer to one, \
|
||||||
// but accessing fields is only possible on structs",
|
but accessing fields is only possible on structs",
|
||||||
// self.ty_display(tty)
|
self.ty_display(tty)
|
||||||
// ),
|
),
|
||||||
// );
|
);
|
||||||
// return Value::NEVER;
|
return Value::NEVER;
|
||||||
// };
|
};
|
||||||
|
|
||||||
// let Some((offset, ty)) = OffsetIter::offset_of(&self.tys, s, name) else {
|
let Some((offset, ty)) = OffsetIter::offset_of(&self.tys, s, name) else {
|
||||||
// let field_list = self
|
let field_list = self
|
||||||
// .tys
|
.tys
|
||||||
// .struct_fields(s)
|
.struct_fields(s)
|
||||||
// .iter()
|
.iter()
|
||||||
// .map(|f| self.tys.names.ident_str(f.name))
|
.map(|f| self.tys.names.ident_str(f.name))
|
||||||
// .intersperse("', '")
|
.intersperse("', '")
|
||||||
// .collect::<String>();
|
.collect::<String>();
|
||||||
// self.report(
|
self.report(
|
||||||
// pos,
|
pos,
|
||||||
// fa!(
|
fa!(
|
||||||
// "the '{}' does not have this field, \
|
"the '{}' does not have this field, \
|
||||||
// but it does have '{field_list}'",
|
but it does have '{field_list}'",
|
||||||
// self.ty_display(tty)
|
self.ty_display(tty)
|
||||||
// ),
|
),
|
||||||
// );
|
);
|
||||||
// return Value::NEVER;
|
return Value::NEVER;
|
||||||
// };
|
};
|
||||||
|
|
||||||
// todo!()
|
Some(Value::ptr(vtarget.id).off(offset).ty(ty))
|
||||||
// //Some(self.ptr_mem(vtarget, offset, ty, true))
|
}
|
||||||
//}
|
|
||||||
Expr::UnOp { op: TokenKind::Band, val, .. } => {
|
Expr::UnOp { op: TokenKind::Band, val, .. } => {
|
||||||
let ctx = Ctx { ty: ctx.ty.and_then(|ty| self.tys.base_of(ty)) };
|
let ctx = Ctx { ty: ctx.ty.and_then(|ty| self.tys.base_of(ty)) };
|
||||||
|
|
||||||
|
@ -1177,12 +1154,12 @@ impl Codegen {
|
||||||
Expr::BinOp { left, op: TokenKind::Assign, right } => {
|
Expr::BinOp { left, op: TokenKind::Assign, right } => {
|
||||||
let dest = self.raw_expr(left)?;
|
let dest = self.raw_expr(left)?;
|
||||||
let value = self.expr(right)?;
|
let value = self.expr(right)?;
|
||||||
self.ci.nodes.lock(value.id);
|
|
||||||
|
|
||||||
_ = self.assert_ty(left.pos(), value.ty, dest.ty, true, "assignment dest");
|
_ = self.assert_ty(left.pos(), value.ty, dest.ty, true, "assignment dest");
|
||||||
|
|
||||||
if dest.var {
|
if dest.var {
|
||||||
let var = &mut self.ci.vars[dest.id as usize];
|
self.ci.nodes.lock(value.id);
|
||||||
|
let var = &mut self.ci.vars[(u16::MAX - dest.id) as usize];
|
||||||
let prev = core::mem::replace(&mut var.value, value);
|
let prev = core::mem::replace(&mut var.value, value);
|
||||||
self.ci.nodes.unlock_remove(prev.id);
|
self.ci.nodes.unlock_remove(prev.id);
|
||||||
} else if dest.ptr {
|
} else if dest.ptr {
|
||||||
|
@ -1282,6 +1259,22 @@ impl Codegen {
|
||||||
|
|
||||||
inps.push(value.id);
|
inps.push(value.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(str) = self.ci.store {
|
||||||
|
inps.push(str);
|
||||||
|
}
|
||||||
|
for load in self.ci.loads.drain(..) {
|
||||||
|
if !self.ci.nodes.unlock_remove(load) {
|
||||||
|
inps.push(load);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.store_mem(VOID, 0, VOID);
|
||||||
|
for load in self.ci.loads.drain(..) {
|
||||||
|
if !self.ci.nodes.unlock_remove(load) {
|
||||||
|
inps.push(load);
|
||||||
|
}
|
||||||
|
}
|
||||||
self.ci.ctrl = self.ci.nodes.new_node(sig.ret, Kind::Call { func }, inps);
|
self.ci.ctrl = self.ci.nodes.new_node(sig.ret, Kind::Call { func }, inps);
|
||||||
for c in self.ci.clobbered.drain(..) {
|
for c in self.ci.clobbered.drain(..) {
|
||||||
self.ci.nodes[self.ci.ctrl].inputs.push(c);
|
self.ci.nodes[self.ci.ctrl].inputs.push(c);
|
||||||
|
@ -1290,74 +1283,73 @@ impl Codegen {
|
||||||
|
|
||||||
Some(Value::new(self.ci.ctrl).ty(sig.ret))
|
Some(Value::new(self.ci.ctrl).ty(sig.ret))
|
||||||
}
|
}
|
||||||
//Expr::Ctor { pos, ty, fields, .. } => {
|
Expr::Ctor { pos, ty, fields, .. } => {
|
||||||
// //let Some(sty) = ty.map(|ty| self.ty(ty)).or(ctx.ty) else {
|
let Some(sty) = ty.map(|ty| self.ty(ty)).or(ctx.ty) else {
|
||||||
// // self.report(
|
self.report(
|
||||||
// // pos,
|
pos,
|
||||||
// // "the type of struct cannot be inferred from context, \
|
"the type of struct cannot be inferred from context, \
|
||||||
// // use an explicit type instead: <type>.{ ... }",
|
use an explicit type instead: <type>.{ ... }",
|
||||||
// // );
|
);
|
||||||
// // return Value::NEVER;
|
return Value::NEVER;
|
||||||
// //};
|
};
|
||||||
|
|
||||||
// //let ty::Kind::Struct(s) = sty.expand() else {
|
let ty::Kind::Struct(s) = sty.expand() else {
|
||||||
// // let inferred = if ty.is_some() { "" } else { "inferred " };
|
let inferred = if ty.is_some() { "" } else { "inferred " };
|
||||||
// // self.report(
|
self.report(
|
||||||
// // pos,
|
pos,
|
||||||
// // fa!(
|
fa!(
|
||||||
// // "the {inferred}type of the constructor is `{}`, \
|
"the {inferred}type of the constructor is `{}`, \
|
||||||
// // but thats not a struct",
|
but thats not a struct",
|
||||||
// // self.ty_display(sty)
|
self.ty_display(sty)
|
||||||
// // ),
|
),
|
||||||
// // );
|
);
|
||||||
// // return Value::NEVER;
|
return Value::NEVER;
|
||||||
// //};
|
};
|
||||||
|
|
||||||
// //// TODO: dont allocate
|
// TODO: dont allocate
|
||||||
// //let mut offs = OffsetIter::new(s, &self.tys)
|
let mut offs = OffsetIter::new(s, &self.tys)
|
||||||
// // .into_iter(&self.tys)
|
.into_iter(&self.tys)
|
||||||
// // .map(|(f, o)| (f.ty, o))
|
.map(|(f, o)| (f.ty, o))
|
||||||
// // .collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
// //let mem = self.ci.nodes.new_node(sty, Kind::Stck, [VOID, MEM]);
|
let mem = self.ci.nodes.new_node(sty, Kind::Stck, [VOID, MEM]);
|
||||||
// //for field in fields {
|
for field in fields {
|
||||||
// // let Some(index) = self.tys.find_struct_field(s, field.name) else {
|
let Some(index) = self.tys.find_struct_field(s, field.name) else {
|
||||||
// // self.report(
|
self.report(
|
||||||
// // field.pos,
|
field.pos,
|
||||||
// // fa!("struct '{}' does not have this field", self.ty_display(sty)),
|
fa!("struct '{}' does not have this field", self.ty_display(sty)),
|
||||||
// // );
|
);
|
||||||
// // continue;
|
continue;
|
||||||
// // };
|
};
|
||||||
|
|
||||||
// // let (ty, offset) =
|
let (ty, offset) =
|
||||||
// // core::mem::replace(&mut offs[index], (ty::Id::UNDECLARED, field.pos));
|
core::mem::replace(&mut offs[index], (ty::Id::UNDECLARED, field.pos));
|
||||||
|
|
||||||
// // if ty == ty::Id::UNDECLARED {
|
if ty == ty::Id::UNDECLARED {
|
||||||
// // self.report(field.pos, "the struct field is already initialized");
|
self.report(field.pos, "the struct field is already initialized");
|
||||||
// // self.report(offset, "previous initialization is here");
|
self.report(offset, "previous initialization is here");
|
||||||
// // continue;
|
continue;
|
||||||
// // }
|
}
|
||||||
|
|
||||||
// // let value = self.expr_ctx(&field.value, Ctx::default().with_ty(ty))?;
|
let value = self.expr_ctx(&field.value, Ctx::default().with_ty(ty))?;
|
||||||
// // self.store_mem(mem, offset, value);
|
self.store_mem(mem, offset, value.id);
|
||||||
// //}
|
}
|
||||||
|
|
||||||
// //let field_list = self
|
let field_list = self
|
||||||
// // .tys
|
.tys
|
||||||
// // .struct_fields(s)
|
.struct_fields(s)
|
||||||
// // .iter()
|
.iter()
|
||||||
// // .zip(offs)
|
.zip(offs)
|
||||||
// // .filter(|&(_, (ty, _))| ty != ty::Id::UNDECLARED)
|
.filter(|&(_, (ty, _))| ty != ty::Id::UNDECLARED)
|
||||||
// // .map(|(f, _)| self.tys.names.ident_str(f.name))
|
.map(|(f, _)| self.tys.names.ident_str(f.name))
|
||||||
// // .intersperse(", ")
|
.intersperse(", ")
|
||||||
// // .collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
// //if !field_list.is_empty() {
|
if !field_list.is_empty() {
|
||||||
// // self.report(pos, fa!("the struct initializer is missing {field_list}"));
|
self.report(pos, fa!("the struct initializer is missing {field_list}"));
|
||||||
// //}
|
}
|
||||||
|
|
||||||
// //Some(mem)
|
Some(Value::ptr(mem).ty(sty))
|
||||||
// todo!()
|
}
|
||||||
//}
|
|
||||||
Expr::Block { stmts, .. } => {
|
Expr::Block { stmts, .. } => {
|
||||||
let base = self.ci.vars.len();
|
let base = self.ci.vars.len();
|
||||||
|
|
||||||
|
@ -1453,6 +1445,7 @@ impl Codegen {
|
||||||
let phi = &self.ci.nodes[scope_var.value.id];
|
let phi = &self.ci.nodes[scope_var.value.id];
|
||||||
debug_assert_eq!(phi.kind, Kind::Phi);
|
debug_assert_eq!(phi.kind, Kind::Phi);
|
||||||
debug_assert_eq!(phi.inputs[2], VOID);
|
debug_assert_eq!(phi.inputs[2], VOID);
|
||||||
|
debug_assert_eq!(phi.ty, scope_var.value.ty);
|
||||||
let prev = phi.inputs[1];
|
let prev = phi.inputs[1];
|
||||||
self.ci.nodes.replace(scope_var.value.id, prev);
|
self.ci.nodes.replace(scope_var.value.id, prev);
|
||||||
scope_var.value.id = prev;
|
scope_var.value.id = prev;
|
||||||
|
@ -1462,7 +1455,7 @@ impl Codegen {
|
||||||
|
|
||||||
if dest_var.value.id == VOID {
|
if dest_var.value.id == VOID {
|
||||||
self.ci.nodes.unlock(dest_var.value.id);
|
self.ci.nodes.unlock(dest_var.value.id);
|
||||||
dest_var.value.id = scope_var.value.id;
|
dest_var.value = scope_var.value;
|
||||||
self.ci.nodes.lock(dest_var.value.id);
|
self.ci.nodes.lock(dest_var.value.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1574,9 +1567,9 @@ impl Codegen {
|
||||||
|
|
||||||
fn strip_var(&mut self, n: &mut Value) {
|
fn strip_var(&mut self, n: &mut Value) {
|
||||||
if core::mem::take(&mut n.var) {
|
if core::mem::take(&mut n.var) {
|
||||||
let mut id = self.ci.vars[n.id as usize].value.id;
|
let id = (u16::MAX - n.id) as usize;
|
||||||
self.ci.nodes.load_loop_value(n.id as usize, &mut id, &mut self.ci.loops);
|
self.ci.nodes.load_loop_value(id, &mut self.ci.vars[id].value, &mut self.ci.loops);
|
||||||
n.id = id;
|
*n = self.ci.vars[id].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1629,8 +1622,8 @@ impl Codegen {
|
||||||
) {
|
) {
|
||||||
for (i, (else_var, then_var)) in to.iter_mut().zip(from).enumerate() {
|
for (i, (else_var, then_var)) in to.iter_mut().zip(from).enumerate() {
|
||||||
if else_var.value.id != then_var.value.id {
|
if else_var.value.id != then_var.value.id {
|
||||||
nodes.load_loop_value(i, &mut then_var.value.id, loops);
|
nodes.load_loop_value(i, &mut then_var.value, loops);
|
||||||
nodes.load_loop_value(i, &mut else_var.value.id, loops);
|
nodes.load_loop_value(i, &mut else_var.value, loops);
|
||||||
if else_var.value.id != then_var.value.id {
|
if else_var.value.id != then_var.value.id {
|
||||||
let ty = nodes[else_var.value.id].ty;
|
let ty = nodes[else_var.value.id].ty;
|
||||||
debug_assert_eq!(ty, nodes[then_var.value.id].ty, "TODO: typecheck properly");
|
debug_assert_eq!(ty, nodes[then_var.value.id].ty, "TODO: typecheck properly");
|
||||||
|
@ -1716,21 +1709,11 @@ impl Codegen {
|
||||||
|
|
||||||
self.ci.nodes.unlock(end);
|
self.ci.nodes.unlock(end);
|
||||||
|
|
||||||
for mem in self.ci.memories.drain(..) {
|
if let Some(mem) = self.ci.store.take() {
|
||||||
if self.ci.nodes[mem.region].kind == Kind::Stck
|
self.ci.nodes.unlock_remove(mem);
|
||||||
&& self.ci.nodes[mem.node]
|
}
|
||||||
.outputs
|
for load in self.ci.loads.drain(..) {
|
||||||
.iter()
|
self.ci.nodes.unlock_remove(load);
|
||||||
.all(|&n| self.ci.nodes[n].kind == Kind::Return)
|
|
||||||
{
|
|
||||||
let outs = core::mem::take(&mut self.ci.nodes[mem.node].outputs);
|
|
||||||
for out in outs {
|
|
||||||
let index =
|
|
||||||
self.ci.nodes[out].inputs.iter().rposition(|&o| o == mem.node).unwrap();
|
|
||||||
self.ci.nodes[out].inputs.swap_remove(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.ci.nodes.unlock_remove(mem.node);
|
|
||||||
}
|
}
|
||||||
self.ci.nodes.unlock(mem);
|
self.ci.nodes.unlock(mem);
|
||||||
|
|
||||||
|
@ -1837,6 +1820,7 @@ impl Codegen {
|
||||||
let mut nodes = core::mem::take(&mut self.ci.nodes);
|
let mut nodes = core::mem::take(&mut self.ci.nodes);
|
||||||
|
|
||||||
let func = Function::new(&mut nodes, &self.tys, sig);
|
let func = Function::new(&mut nodes, &self.tys, sig);
|
||||||
|
log::info!("{:?}", func);
|
||||||
if self.ci.call_count != 0 {
|
if self.ci.call_count != 0 {
|
||||||
core::mem::swap(
|
core::mem::swap(
|
||||||
&mut self.ralloc.env.preferred_regs_by_class,
|
&mut self.ralloc.env.preferred_regs_by_class,
|
||||||
|
@ -1958,23 +1942,29 @@ impl Codegen {
|
||||||
Kind::Load { offset } => {
|
Kind::Load { offset } => {
|
||||||
let region = node.inputs[1];
|
let region = node.inputs[1];
|
||||||
let size = self.tys.size_of(node.ty);
|
let size = self.tys.size_of(node.ty);
|
||||||
debug_assert_eq!(size, 8, "TODO");
|
if size <= 8 {
|
||||||
let (base, offset) = match func.nodes[region].kind {
|
let (base, offset) = match func.nodes[region].kind {
|
||||||
Kind::Stck => (reg::STACK_PTR, func.nodes[region].offset + offset),
|
Kind::Stck => (reg::STACK_PTR, func.nodes[region].offset + offset),
|
||||||
_ => (atr(allocs[1]), func.nodes[region].offset + offset),
|
_ => (atr(allocs[1]), func.nodes[region].offset + offset),
|
||||||
};
|
};
|
||||||
self.ci.emit(instrs::ld(atr(allocs[0]), base, offset as _, size as _));
|
self.ci.emit(instrs::ld(atr(allocs[0]), base, offset as _, size as _));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Kind::Stre { offset } => {
|
Kind::Stre { offset } => {
|
||||||
let region = node.inputs[2];
|
let region = node.inputs[2];
|
||||||
let size = self.tys.size_of(node.ty);
|
if region != VOID {
|
||||||
debug_assert_eq!(size, 8, "TODO");
|
let size = u16::try_from(self.tys.size_of(node.ty)).expect("TODO");
|
||||||
let nd = &func.nodes[region];
|
let nd = &func.nodes[region];
|
||||||
let (base, offset, src) = match nd.kind {
|
let (base, offset, src) = match nd.kind {
|
||||||
Kind::Stck => (reg::STACK_PTR, nd.offset + offset, allocs[0]),
|
Kind::Stck => (reg::STACK_PTR, nd.offset + offset, allocs[0]),
|
||||||
_ => (atr(allocs[0]), offset, allocs[1]),
|
_ => (atr(allocs[0]), offset, allocs[1]),
|
||||||
};
|
};
|
||||||
self.ci.emit(instrs::st(atr(src), base, offset as _, size as _));
|
if size > 8 {
|
||||||
|
self.ci.emit(instrs::bmc(base, atr(src), size));
|
||||||
|
} else {
|
||||||
|
self.ci.emit(instrs::st(atr(src), base, offset as _, size));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -2393,7 +2383,14 @@ impl<'a> Function<'a> {
|
||||||
regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int),
|
regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int),
|
||||||
)]);
|
)]);
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
9..=16 => todo!(),
|
||||||
|
_ => {
|
||||||
|
self.def_nid(arg);
|
||||||
|
self.add_instr(NEVER, vec![regalloc2::Operand::reg_fixed_def(
|
||||||
|
self.rg(arg),
|
||||||
|
regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int),
|
||||||
|
)]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2459,7 +2456,13 @@ impl<'a> Function<'a> {
|
||||||
regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int),
|
regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
9..=16 => todo!("pass in two register"),
|
||||||
|
_ => {
|
||||||
|
ops.push(regalloc2::Operand::reg_fixed_use(
|
||||||
|
self.rg(i),
|
||||||
|
regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2478,19 +2481,26 @@ impl<'a> Function<'a> {
|
||||||
Kind::Phi | Kind::Arg { .. } | Kind::Mem => {}
|
Kind::Phi | Kind::Arg { .. } | Kind::Mem => {}
|
||||||
Kind::Load { .. } => {
|
Kind::Load { .. } => {
|
||||||
let region = node.inputs[1];
|
let region = node.inputs[1];
|
||||||
let ops = match self.nodes[region].kind {
|
if self.tys.size_of(node.ty) <= 8 {
|
||||||
Kind::Stck => vec![self.drg(nid)],
|
let ops = match self.nodes[region].kind {
|
||||||
_ => vec![self.drg(nid), self.urg(region)],
|
Kind::Stck => vec![self.drg(nid)],
|
||||||
};
|
_ => vec![self.drg(nid), self.urg(region)],
|
||||||
self.add_instr(nid, ops);
|
};
|
||||||
|
self.add_instr(nid, ops);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Kind::Stre { .. } => {
|
Kind::Stre { .. } => {
|
||||||
let region = node.inputs[2];
|
let region = node.inputs[2];
|
||||||
let ops = match self.nodes[region].kind {
|
if region != VOID {
|
||||||
Kind::Stck => vec![self.urg(node.inputs[1])],
|
let ops = match self.nodes[region].kind {
|
||||||
_ => vec![self.urg(region), self.urg(node.inputs[1])],
|
_ if self.tys.size_of(node.ty) > 8 => {
|
||||||
};
|
vec![self.urg(region), self.urg(self.nodes[node.inputs[1]].inputs[1])]
|
||||||
self.add_instr(nid, ops);
|
}
|
||||||
|
Kind::Stck => vec![self.urg(node.inputs[1])],
|
||||||
|
_ => vec![self.urg(region), self.urg(node.inputs[1])],
|
||||||
|
};
|
||||||
|
self.add_instr(nid, ops);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,23 @@ clobber:
|
||||||
ST r3, r2, 0a, 8h
|
ST r3, r2, 0a, 8h
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -32d
|
ADDI64 r254, r254, -64d
|
||||||
ST r31, r254, 8a, 24h
|
ST r31, r254, 8a, 56h
|
||||||
LI64 r32, 2d
|
LI64 r32, 2d
|
||||||
|
LI64 r33, 1d
|
||||||
|
LI64 r34, 0d
|
||||||
ADDI64 r2, r254, 0d
|
ADDI64 r2, r254, 0d
|
||||||
|
ST r34, r254, 0a, 8h
|
||||||
|
ST r33, r254, 0a, 8h
|
||||||
ST r32, r254, 0a, 8h
|
ST r32, r254, 0a, 8h
|
||||||
|
LD r35, r254, 0a, 8h
|
||||||
JAL r31, r0, :clobber
|
JAL r31, r0, :clobber
|
||||||
LD r33, r254, 0a, 8h
|
LD r36, r254, 0a, 8h
|
||||||
ADDI64 r1, r33, -4d
|
MULI64 r37, r35, 2d
|
||||||
LD r31, r254, 8a, 24h
|
SUB64 r1, r37, r36
|
||||||
ADDI64 r254, r254, 32d
|
LD r31, r254, 8a, 56h
|
||||||
|
ADDI64 r254, r254, 64d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 166
|
code size: 229
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,23 +1,26 @@
|
||||||
drop:
|
drop:
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -32d
|
ADDI64 r254, r254, -56d
|
||||||
ST r31, r254, 8a, 24h
|
ST r31, r254, 8a, 48h
|
||||||
LI64 r32, 1d
|
LI64 r32, 1d
|
||||||
ADDI64 r2, r254, 0d
|
ADDI64 r33, r254, 0d
|
||||||
|
ADDI64 r34, r33, 1000d
|
||||||
|
ADDI64 r35, r34, -1000d
|
||||||
ST r32, r254, 0a, 8h
|
ST r32, r254, 0a, 8h
|
||||||
|
CP r2, r35
|
||||||
JAL r31, r0, :modify
|
JAL r31, r0, :modify
|
||||||
CP r2, r32
|
CP r2, r32
|
||||||
JAL r31, r0, :drop
|
JAL r31, r0, :drop
|
||||||
LD r33, r254, 0a, 8h
|
LD r36, r35, 0a, 8h
|
||||||
ADDI64 r1, r33, -2d
|
ADDI64 r1, r36, -2d
|
||||||
LD r31, r254, 8a, 24h
|
LD r31, r254, 8a, 48h
|
||||||
ADDI64 r254, r254, 32d
|
ADDI64 r254, r254, 56d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
modify:
|
modify:
|
||||||
LI64 r3, 2d
|
LI64 r3, 2d
|
||||||
ST r3, r2, 0a, 8h
|
ST r3, r2, 0a, 8h
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 187
|
code size: 212
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
main:
|
||||||
|
ADDI64 r254, r254, -88d
|
||||||
|
ST r31, r254, 40a, 48h
|
||||||
|
LI64 r32, 3d
|
||||||
|
LI64 r33, 1d
|
||||||
|
LI64 r34, 4d
|
||||||
|
ADDI64 r35, r254, 0d
|
||||||
|
ST r34, r254, 0a, 8h
|
||||||
|
ST r33, r254, 8a, 8h
|
||||||
|
ADDI64 r2, r254, 16d
|
||||||
|
BMC r254, r2, 16h
|
||||||
|
ST r32, r254, 32a, 8h
|
||||||
|
JAL r31, r0, :odher_pass
|
||||||
|
LD r36, r1, 16a, 8h
|
||||||
|
JNE r36, r32, :0
|
||||||
|
CP r2, r1
|
||||||
|
JAL r31, r0, :pass
|
||||||
|
JMP :1
|
||||||
|
0: LI64 r1, 0d
|
||||||
|
1: LD r31, r254, 40a, 48h
|
||||||
|
ADDI64 r254, r254, 88d
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
odher_pass:
|
||||||
|
CP r1, r2
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
pass:
|
||||||
|
LD r4, r2, 8a, 8h
|
||||||
|
LD r5, r2, 0a, 8h
|
||||||
|
SUB64 r1, r5, r4
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
code size: 268
|
||||||
|
ret: 3
|
||||||
|
status: Ok(())
|
Loading…
Reference in a new issue