forked from AbleOS/holey-bytes
handling conditional stores
This commit is contained in:
parent
c900f4ef5c
commit
4a7b4e4ead
|
@ -999,3 +999,20 @@ clobber := fn(cb: ^int): void {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### conditional_stores
|
||||||
|
```hb
|
||||||
|
main := fn(): int {
|
||||||
|
mem := &1
|
||||||
|
|
||||||
|
if cond() == 0 {
|
||||||
|
*mem = 0
|
||||||
|
} else {
|
||||||
|
*mem = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
return *mem
|
||||||
|
}
|
||||||
|
|
||||||
|
cond := fn(): int return 0
|
||||||
|
```
|
||||||
|
|
450
lang/src/son.rs
450
lang/src/son.rs
|
@ -14,7 +14,7 @@ use {
|
||||||
vc::{BitSet, Vc},
|
vc::{BitSet, Vc},
|
||||||
Func, HashMap, Offset, OffsetIter, Reloc, Sig, SymKey, TypedReloc, Types,
|
Func, HashMap, Offset, OffsetIter, Reloc, Sig, SymKey, TypedReloc, Types,
|
||||||
},
|
},
|
||||||
alloc::{borrow::ToOwned, string::String, vec::Vec},
|
alloc::{string::String, vec::Vec},
|
||||||
core::{
|
core::{
|
||||||
assert_matches::debug_assert_matches,
|
assert_matches::debug_assert_matches,
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
@ -279,8 +279,53 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
K::Phi => {
|
K::Phi => {
|
||||||
if self[target].inputs[1] == self[target].inputs[2] {
|
let &[ctrl, lhs, rhs] = self[target].inputs.as_slice() else { unreachable!() };
|
||||||
return Some(self[target].inputs[1]);
|
|
||||||
|
if lhs == rhs {
|
||||||
|
return Some(lhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self[lhs].kind == Kind::Stre
|
||||||
|
&& self[rhs].kind == Kind::Stre
|
||||||
|
&& self[lhs].ty == self[rhs].ty
|
||||||
|
&& self[lhs].inputs[2] == self[rhs].inputs[2]
|
||||||
|
&& self[lhs].inputs.get(3) == self[rhs].inputs.get(3)
|
||||||
|
{
|
||||||
|
let pick_value = self.new_node(self[lhs].ty, Kind::Phi, [
|
||||||
|
ctrl,
|
||||||
|
self[lhs].inputs[1],
|
||||||
|
self[rhs].inputs[1],
|
||||||
|
]);
|
||||||
|
let mut vc = Vc::from([VOID, pick_value, self[lhs].inputs[2]]);
|
||||||
|
for &rest in &self[lhs].inputs[3..] {
|
||||||
|
vc.push(rest);
|
||||||
|
}
|
||||||
|
for &rest in &self[rhs].inputs[4..] {
|
||||||
|
vc.push(rest);
|
||||||
|
}
|
||||||
|
return Some(self.new_node(self[lhs].ty, Kind::Stre, vc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
K::Stre => {
|
||||||
|
if self[target].inputs[2] != VOID
|
||||||
|
&& self[target].inputs.len() == 4
|
||||||
|
&& self[self[target].inputs[3]].kind == Kind::Stre
|
||||||
|
&& self[self[target].inputs[3]].inputs[2] == self[target].inputs[2]
|
||||||
|
{
|
||||||
|
return Some(self.modify_input(
|
||||||
|
self[target].inputs[3],
|
||||||
|
1,
|
||||||
|
self[target].inputs[1],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
K::Load => {
|
||||||
|
if self[target].inputs.len() == 3
|
||||||
|
&& self[self[target].inputs[2]].kind == Kind::Stre
|
||||||
|
&& self[self[target].inputs[2]].inputs[2] == self[target].inputs[1]
|
||||||
|
&& self[self[target].inputs[2]].ty == self[target].ty
|
||||||
|
{
|
||||||
|
return Some(self[self[target].inputs[2]].inputs[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -574,7 +619,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
let [loob, loops @ ..] = loops else { unreachable!() };
|
let [loob, loops @ ..] = loops else { unreachable!() };
|
||||||
let lvalue = &mut loob.scope[index].value;
|
let lvalue = &mut loob.scope.vars[index].value;
|
||||||
|
|
||||||
self.load_loop_value(index, lvalue, loops);
|
self.load_loop_value(index, lvalue, loops);
|
||||||
|
|
||||||
|
@ -631,6 +676,30 @@ impl Nodes {
|
||||||
fn iter_mut(&mut self) -> impl Iterator<Item = &mut Node> {
|
fn iter_mut(&mut self) -> impl Iterator<Item = &mut Node> {
|
||||||
self.values.iter_mut().flat_map(Result::as_mut)
|
self.values.iter_mut().flat_map(Result::as_mut)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lock_scope(&mut self, scope: &Scope) {
|
||||||
|
if let Some(str) = scope.store {
|
||||||
|
self.lock(str);
|
||||||
|
}
|
||||||
|
for &load in &scope.loads {
|
||||||
|
self.lock(load);
|
||||||
|
}
|
||||||
|
for var in &scope.vars {
|
||||||
|
self.lock(var.value.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unlock_remove_scope(&mut self, scope: &Scope) {
|
||||||
|
if let Some(str) = scope.store {
|
||||||
|
self.unlock_remove(str);
|
||||||
|
}
|
||||||
|
for &load in &scope.loads {
|
||||||
|
self.unlock_remove(load);
|
||||||
|
}
|
||||||
|
for var in &scope.vars {
|
||||||
|
self.unlock_remove(var.value.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Index<Nid> for Nodes {
|
impl ops::Index<Nid> for Nodes {
|
||||||
|
@ -773,8 +842,8 @@ type IDomDepth = u16;
|
||||||
struct Loop {
|
struct Loop {
|
||||||
node: Nid,
|
node: Nid,
|
||||||
ctrl: [Nid; 2],
|
ctrl: [Nid; 2],
|
||||||
ctrl_scope: [Vec<Variable>; 2],
|
ctrl_scope: [Scope; 2],
|
||||||
scope: Vec<Variable>,
|
scope: Scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
@ -783,6 +852,13 @@ struct Variable {
|
||||||
value: Value,
|
value: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
struct Scope {
|
||||||
|
vars: Vec<Variable>,
|
||||||
|
loads: Vec<Nid>,
|
||||||
|
store: Option<Nid>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ItemCtx {
|
struct ItemCtx {
|
||||||
file: FileId,
|
file: FileId,
|
||||||
|
@ -799,9 +875,7 @@ struct ItemCtx {
|
||||||
filled: Vec<Nid>,
|
filled: Vec<Nid>,
|
||||||
|
|
||||||
loops: Vec<Loop>,
|
loops: Vec<Loop>,
|
||||||
vars: Vec<Variable>,
|
scope: Scope,
|
||||||
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>,
|
||||||
|
@ -871,7 +945,6 @@ impl Default for Regalloc {
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy)]
|
||||||
struct Value {
|
struct Value {
|
||||||
ty: ty::Id,
|
ty: ty::Id,
|
||||||
off: Offset,
|
|
||||||
var: bool,
|
var: bool,
|
||||||
ptr: bool,
|
ptr: bool,
|
||||||
id: Nid,
|
id: Nid,
|
||||||
|
@ -879,8 +952,8 @@ struct Value {
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
const NEVER: Option<Value> =
|
const NEVER: Option<Value> =
|
||||||
Some(Self { ty: ty::Id::NEVER, off: 0, var: false, ptr: false, id: NEVER });
|
Some(Self { ty: ty::Id::NEVER, var: false, ptr: false, id: NEVER });
|
||||||
const VOID: Value = Self { ty: ty::Id::VOID, off: 0, var: false, ptr: false, id: VOID };
|
const VOID: Value = Self { ty: ty::Id::VOID, var: false, ptr: false, id: VOID };
|
||||||
|
|
||||||
pub fn new(id: Nid) -> Self {
|
pub fn new(id: Nid) -> Self {
|
||||||
Self { id, ..Default::default() }
|
Self { id, ..Default::default() }
|
||||||
|
@ -898,11 +971,6 @@ impl Value {
|
||||||
pub fn ty(self, ty: impl Into<ty::Id>) -> Self {
|
pub fn ty(self, ty: impl Into<ty::Id>) -> Self {
|
||||||
Self { ty: ty.into(), ..self }
|
Self { ty: ty.into(), ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn off(self, off: Offset) -> Self {
|
|
||||||
Self { off, ..self }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -957,11 +1025,11 @@ impl Codegen {
|
||||||
|
|
||||||
fn store_mem(&mut self, region: Nid, value: Nid) -> Nid {
|
fn store_mem(&mut self, region: Nid, value: Nid) -> Nid {
|
||||||
let mut vc = Vc::from([VOID, value, region]);
|
let mut vc = Vc::from([VOID, value, region]);
|
||||||
if let Some(str) = self.ci.store {
|
if let Some(str) = self.ci.scope.store {
|
||||||
self.ci.nodes.unlock(str);
|
self.ci.nodes.unlock(str);
|
||||||
vc.push(str);
|
vc.push(str);
|
||||||
}
|
}
|
||||||
for load in self.ci.loads.drain(..) {
|
for load in self.ci.scope.loads.drain(..) {
|
||||||
if load == value {
|
if load == value {
|
||||||
self.ci.nodes.unlock(load);
|
self.ci.nodes.unlock(load);
|
||||||
continue;
|
continue;
|
||||||
|
@ -972,18 +1040,18 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
let store = self.ci.nodes.new_node(self.tof(value), Kind::Stre, vc);
|
let store = self.ci.nodes.new_node(self.tof(value), Kind::Stre, vc);
|
||||||
self.ci.nodes.lock(store);
|
self.ci.nodes.lock(store);
|
||||||
self.ci.store = Some(store);
|
self.ci.scope.store = Some(store);
|
||||||
store
|
store
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_mem(&mut self, region: Nid, ty: ty::Id) -> Nid {
|
fn load_mem(&mut self, region: Nid, ty: ty::Id) -> Nid {
|
||||||
let mut vc = Vc::from([VOID, region]);
|
let mut vc = Vc::from([VOID, region]);
|
||||||
if let Some(str) = self.ci.store {
|
if let Some(str) = self.ci.scope.store {
|
||||||
vc.push(str);
|
vc.push(str);
|
||||||
}
|
}
|
||||||
let load = self.ci.nodes.new_node(ty, Kind::Load, vc);
|
let load = self.ci.nodes.new_node(ty, Kind::Load, vc);
|
||||||
self.ci.nodes.lock(load);
|
self.ci.nodes.lock(load);
|
||||||
self.ci.loads.push(load);
|
self.ci.scope.loads.push(load);
|
||||||
load
|
load
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1012,20 +1080,19 @@ impl Codegen {
|
||||||
match *expr {
|
match *expr {
|
||||||
Expr::Comment { .. } => Some(Value::VOID),
|
Expr::Comment { .. } => Some(Value::VOID),
|
||||||
Expr::Ident { pos, id, .. } => {
|
Expr::Ident { pos, id, .. } => {
|
||||||
let Some(index) = self.ci.vars.iter().position(|v| v.id == id) else {
|
let Some(index) = self.ci.scope.vars.iter().position(|v| v.id == id) else {
|
||||||
self.report(pos, msg);
|
self.report(pos, msg);
|
||||||
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,
|
&mut self.ci.scope.vars[index].value,
|
||||||
&mut self.ci.loops,
|
&mut self.ci.loops,
|
||||||
);
|
);
|
||||||
debug_assert_ne!(self.ci.vars[index].value.ty, ty::Id::VOID);
|
debug_assert_ne!(self.ci.scope.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.scope.vars[index].value.ty))
|
||||||
}
|
}
|
||||||
Expr::Number { value, .. } => Some(self.ci.nodes.new_node_lit(
|
Expr::Number { value, .. } => Some(self.ci.nodes.new_node_lit(
|
||||||
ctx.ty.filter(|ty| ty.is_integer() || ty.is_pointer()).unwrap_or(ty::Id::INT),
|
ctx.ty.filter(|ty| ty.is_integer() || ty.is_pointer()).unwrap_or(ty::Id::INT),
|
||||||
|
@ -1040,7 +1107,7 @@ 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.store.iter() {
|
for &m in self.ci.scope.store.iter() {
|
||||||
inps.push(m);
|
inps.push(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1090,7 +1157,7 @@ impl Codegen {
|
||||||
return Value::NEVER;
|
return Value::NEVER;
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(Value::ptr(vtarget.id).off(offset).ty(ty))
|
Some(Value::ptr(self.offset(vtarget.id, ty, offset)).ty(ty))
|
||||||
}
|
}
|
||||||
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)) };
|
||||||
|
@ -1101,7 +1168,6 @@ impl Codegen {
|
||||||
if val.ptr {
|
if val.ptr {
|
||||||
val.ptr = false;
|
val.ptr = false;
|
||||||
val.ty = self.tys.make_ptr(val.ty);
|
val.ty = self.tys.make_ptr(val.ty);
|
||||||
self.offset(&mut val);
|
|
||||||
return Some(val);
|
return Some(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1135,22 +1201,21 @@ impl Codegen {
|
||||||
Expr::BinOp { left: &Expr::Ident { id, .. }, op: TokenKind::Decl, right } => {
|
Expr::BinOp { left: &Expr::Ident { id, .. }, op: TokenKind::Decl, right } => {
|
||||||
let value = self.expr(right)?;
|
let value = self.expr(right)?;
|
||||||
self.ci.nodes.lock(value.id);
|
self.ci.nodes.lock(value.id);
|
||||||
self.ci.vars.push(Variable { id, value });
|
self.ci.scope.vars.push(Variable { id, value });
|
||||||
Some(Value::VOID)
|
Some(Value::VOID)
|
||||||
}
|
}
|
||||||
Expr::BinOp { left, op: TokenKind::Assign, right } => {
|
Expr::BinOp { left, op: TokenKind::Assign, right } => {
|
||||||
let mut dest = self.raw_expr(left)?;
|
let dest = self.raw_expr(left)?;
|
||||||
let value = self.expr(right)?;
|
let value = self.expr(right)?;
|
||||||
|
|
||||||
_ = 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 {
|
||||||
self.ci.nodes.lock(value.id);
|
self.ci.nodes.lock(value.id);
|
||||||
let var = &mut self.ci.vars[(u16::MAX - dest.id) as usize];
|
let var = &mut self.ci.scope.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 {
|
||||||
self.offset(&mut dest);
|
|
||||||
self.store_mem(dest.id, value.id);
|
self.store_mem(dest.id, value.id);
|
||||||
} else {
|
} else {
|
||||||
self.report(left.pos(), "cannot assign to this expression");
|
self.report(left.pos(), "cannot assign to this expression");
|
||||||
|
@ -1158,26 +1223,6 @@ impl Codegen {
|
||||||
|
|
||||||
Some(Value::VOID)
|
Some(Value::VOID)
|
||||||
}
|
}
|
||||||
//Expr::BinOp {
|
|
||||||
// left: &Expr::UnOp { pos, op: TokenKind::Mul, val },
|
|
||||||
// op: TokenKind::Assign,
|
|
||||||
// right,
|
|
||||||
//} => {
|
|
||||||
// //let ctx = Ctx { ty: ctx.ty.map(|ty| self.tys.make_ptr(ty)) };
|
|
||||||
// //let val = self.expr_ctx(val, ctx)?;
|
|
||||||
// //let base = self.get_load_type(val).unwrap_or_else(|| {
|
|
||||||
// // self.report(
|
|
||||||
// // pos,
|
|
||||||
// // fa!("the '{}' can not be dereferneced", self.ty_display(self.tof(val))),
|
|
||||||
// // );
|
|
||||||
// // ty::Id::NEVER
|
|
||||||
// //});
|
|
||||||
// //let value = self.expr_ctx(right, Ctx::default().with_ty(base))?;
|
|
||||||
// //_ = self.assert_ty(right.pos(), self.tof(value), base, true, "stored value");
|
|
||||||
// //self.store_mem(val, 0, value);
|
|
||||||
// //Some(Value::VOID)
|
|
||||||
// todo!()
|
|
||||||
//}
|
|
||||||
Expr::BinOp { left, op, right } if op != TokenKind::Assign => {
|
Expr::BinOp { left, op, right } if op != TokenKind::Assign => {
|
||||||
let lhs = self.expr_ctx(left, ctx)?;
|
let lhs = self.expr_ctx(left, ctx)?;
|
||||||
self.ci.nodes.lock(lhs.id);
|
self.ci.nodes.lock(lhs.id);
|
||||||
|
@ -1248,17 +1293,17 @@ impl Codegen {
|
||||||
inps.push(value.id);
|
inps.push(value.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(str) = self.ci.store {
|
if let Some(str) = self.ci.scope.store {
|
||||||
inps.push(str);
|
inps.push(str);
|
||||||
}
|
}
|
||||||
for load in self.ci.loads.drain(..) {
|
for load in self.ci.scope.loads.drain(..) {
|
||||||
if !self.ci.nodes.unlock_remove(load) {
|
if !self.ci.nodes.unlock_remove(load) {
|
||||||
inps.push(load);
|
inps.push(load);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.store_mem(VOID, VOID);
|
self.store_mem(VOID, VOID);
|
||||||
for load in self.ci.loads.drain(..) {
|
for load in self.ci.scope.loads.drain(..) {
|
||||||
if !self.ci.nodes.unlock_remove(load) {
|
if !self.ci.nodes.unlock_remove(load) {
|
||||||
inps.push(load);
|
inps.push(load);
|
||||||
}
|
}
|
||||||
|
@ -1319,9 +1364,8 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
let value = self.expr_ctx(&field.value, Ctx::default().with_ty(ty))?;
|
let value = self.expr_ctx(&field.value, Ctx::default().with_ty(ty))?;
|
||||||
let mut mem = Value::ptr(mem).ty(ty).off(offset);
|
let mem = self.offset(mem, ty, offset);
|
||||||
self.offset(&mut mem);
|
self.store_mem(mem, value.id);
|
||||||
self.store_mem(mem.id, value.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let field_list = self
|
let field_list = self
|
||||||
|
@ -1341,7 +1385,7 @@ impl Codegen {
|
||||||
Some(Value::ptr(mem).ty(sty))
|
Some(Value::ptr(mem).ty(sty))
|
||||||
}
|
}
|
||||||
Expr::Block { stmts, .. } => {
|
Expr::Block { stmts, .. } => {
|
||||||
let base = self.ci.vars.len();
|
let base = self.ci.scope.vars.len();
|
||||||
|
|
||||||
let mut ret = Some(Value::VOID);
|
let mut ret = Some(Value::VOID);
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
|
@ -1354,7 +1398,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.nodes.lock(self.ci.ctrl);
|
self.ci.nodes.lock(self.ci.ctrl);
|
||||||
for var in self.ci.vars.drain(base..) {
|
for var in self.ci.scope.vars.drain(base..) {
|
||||||
self.ci.nodes.unlock_remove(var.value.id);
|
self.ci.nodes.unlock_remove(var.value.id);
|
||||||
}
|
}
|
||||||
self.ci.nodes.unlock(self.ci.ctrl);
|
self.ci.nodes.unlock(self.ci.ctrl);
|
||||||
|
@ -1366,19 +1410,23 @@ impl Codegen {
|
||||||
self.ci.loops.push(Loop {
|
self.ci.loops.push(Loop {
|
||||||
node: self.ci.ctrl,
|
node: self.ci.ctrl,
|
||||||
ctrl: [Nid::MAX; 2],
|
ctrl: [Nid::MAX; 2],
|
||||||
ctrl_scope: core::array::from_fn(|_| vec![]),
|
ctrl_scope: core::array::from_fn(|_| Default::default()),
|
||||||
scope: self.ci.vars.clone(),
|
scope: self.ci.scope.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
for var in &mut self.ci.vars {
|
for var in &mut self.ci.scope.vars {
|
||||||
var.value = Value::VOID;
|
var.value = Value::VOID;
|
||||||
}
|
}
|
||||||
self.ci.nodes[VOID].lock_rc += self.ci.vars.len() as LockRc;
|
self.ci.nodes.lock_scope(&self.ci.scope);
|
||||||
|
|
||||||
self.expr(body);
|
self.expr(body);
|
||||||
|
|
||||||
let Loop { node, ctrl: [mut con, bre], ctrl_scope: [mut cons, mut bres], scope } =
|
let Loop {
|
||||||
self.ci.loops.pop().unwrap();
|
node,
|
||||||
|
ctrl: [mut con, bre],
|
||||||
|
ctrl_scope: [mut cons, mut bres],
|
||||||
|
mut scope,
|
||||||
|
} = self.ci.loops.pop().unwrap();
|
||||||
|
|
||||||
if con != Nid::MAX {
|
if con != Nid::MAX {
|
||||||
con = self.ci.nodes.new_node(ty::Id::VOID, Kind::Region, [con, self.ci.ctrl]);
|
con = self.ci.nodes.new_node(ty::Id::VOID, Kind::Region, [con, self.ci.ctrl]);
|
||||||
|
@ -1386,7 +1434,7 @@ impl Codegen {
|
||||||
&mut self.ci.nodes,
|
&mut self.ci.nodes,
|
||||||
&mut self.ci.loops,
|
&mut self.ci.loops,
|
||||||
con,
|
con,
|
||||||
&mut self.ci.vars,
|
&mut self.ci.scope,
|
||||||
&mut cons,
|
&mut cons,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
@ -1410,10 +1458,10 @@ impl Codegen {
|
||||||
|
|
||||||
self.ci.nodes.lock(self.ci.ctrl);
|
self.ci.nodes.lock(self.ci.ctrl);
|
||||||
|
|
||||||
core::mem::swap(&mut self.ci.vars, &mut bres);
|
core::mem::swap(&mut self.ci.scope, &mut bres);
|
||||||
|
|
||||||
for ((dest_var, mut scope_var), loop_var) in
|
for ((dest_var, mut scope_var), loop_var) in
|
||||||
self.ci.vars.iter_mut().zip(scope).zip(bres)
|
self.ci.scope.vars.iter_mut().zip(scope.vars.drain(..)).zip(bres.vars.drain(..))
|
||||||
{
|
{
|
||||||
self.ci.nodes.unlock(loop_var.value.id);
|
self.ci.nodes.unlock(loop_var.value.id);
|
||||||
|
|
||||||
|
@ -1457,6 +1505,9 @@ impl Codegen {
|
||||||
self.ci.nodes.unlock_remove(scope_var.value.id);
|
self.ci.nodes.unlock_remove(scope_var.value.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.ci.nodes.unlock_remove_scope(&scope);
|
||||||
|
self.ci.nodes.unlock_remove_scope(&bres);
|
||||||
|
|
||||||
self.ci.nodes.unlock(self.ci.ctrl);
|
self.ci.nodes.unlock(self.ci.ctrl);
|
||||||
|
|
||||||
Some(Value::VOID)
|
Some(Value::VOID)
|
||||||
|
@ -1487,15 +1538,13 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut else_scope = self.ci.vars.clone();
|
let mut else_scope = self.ci.scope.clone();
|
||||||
for &el in &self.ci.vars {
|
self.ci.nodes.lock_scope(&else_scope);
|
||||||
self.ci.nodes.lock(el.value.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.ci.ctrl = self.ci.nodes.new_node(ty::Id::VOID, Kind::Then, [if_node]);
|
self.ci.ctrl = self.ci.nodes.new_node(ty::Id::VOID, Kind::Then, [if_node]);
|
||||||
let lcntrl = self.expr(then).map_or(Nid::MAX, |_| self.ci.ctrl);
|
let lcntrl = self.expr(then).map_or(Nid::MAX, |_| self.ci.ctrl);
|
||||||
|
|
||||||
let mut then_scope = core::mem::replace(&mut self.ci.vars, else_scope);
|
let mut then_scope = core::mem::replace(&mut self.ci.scope, else_scope);
|
||||||
self.ci.ctrl = self.ci.nodes.new_node(ty::Id::VOID, Kind::Else, [if_node]);
|
self.ci.ctrl = self.ci.nodes.new_node(ty::Id::VOID, Kind::Else, [if_node]);
|
||||||
let rcntrl = if let Some(else_) = else_ {
|
let rcntrl = if let Some(else_) = else_ {
|
||||||
self.expr(else_).map_or(Nid::MAX, |_| self.ci.ctrl)
|
self.expr(else_).map_or(Nid::MAX, |_| self.ci.ctrl)
|
||||||
|
@ -1504,27 +1553,21 @@ impl Codegen {
|
||||||
};
|
};
|
||||||
|
|
||||||
if lcntrl == Nid::MAX && rcntrl == Nid::MAX {
|
if lcntrl == Nid::MAX && rcntrl == Nid::MAX {
|
||||||
for then_var in then_scope {
|
self.ci.nodes.unlock_remove_scope(&then_scope);
|
||||||
self.ci.nodes.unlock_remove(then_var.value.id);
|
|
||||||
}
|
|
||||||
return None;
|
return None;
|
||||||
} else if lcntrl == Nid::MAX {
|
} else if lcntrl == Nid::MAX {
|
||||||
for then_var in then_scope {
|
self.ci.nodes.unlock_remove_scope(&then_scope);
|
||||||
self.ci.nodes.unlock_remove(then_var.value.id);
|
|
||||||
}
|
|
||||||
return Some(Value::VOID);
|
return Some(Value::VOID);
|
||||||
} else if rcntrl == Nid::MAX {
|
} else if rcntrl == Nid::MAX {
|
||||||
for else_var in &self.ci.vars {
|
self.ci.nodes.unlock_remove_scope(&self.ci.scope);
|
||||||
self.ci.nodes.unlock_remove(else_var.value.id);
|
self.ci.scope = then_scope;
|
||||||
}
|
|
||||||
self.ci.vars = then_scope;
|
|
||||||
self.ci.ctrl = lcntrl;
|
self.ci.ctrl = lcntrl;
|
||||||
return Some(Value::VOID);
|
return Some(Value::VOID);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.ctrl = self.ci.nodes.new_node(ty::Id::VOID, Kind::Region, [lcntrl, rcntrl]);
|
self.ci.ctrl = self.ci.nodes.new_node(ty::Id::VOID, Kind::Region, [lcntrl, rcntrl]);
|
||||||
|
|
||||||
else_scope = core::mem::take(&mut self.ci.vars);
|
else_scope = core::mem::take(&mut self.ci.scope);
|
||||||
|
|
||||||
Self::merge_scopes(
|
Self::merge_scopes(
|
||||||
&mut self.ci.nodes,
|
&mut self.ci.nodes,
|
||||||
|
@ -1535,7 +1578,7 @@ impl Codegen {
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.ci.vars = else_scope;
|
self.ci.scope = else_scope;
|
||||||
|
|
||||||
Some(Value::VOID)
|
Some(Value::VOID)
|
||||||
}
|
}
|
||||||
|
@ -1550,31 +1593,30 @@ impl Codegen {
|
||||||
let mut n = self.raw_expr_ctx(expr, ctx)?;
|
let mut n = self.raw_expr_ctx(expr, ctx)?;
|
||||||
self.strip_var(&mut n);
|
self.strip_var(&mut n);
|
||||||
if core::mem::take(&mut n.ptr) {
|
if core::mem::take(&mut n.ptr) {
|
||||||
self.offset(&mut n);
|
|
||||||
n.id = self.load_mem(n.id, n.ty);
|
n.id = self.load_mem(n.id, n.ty);
|
||||||
}
|
}
|
||||||
Some(n)
|
Some(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn offset(&mut self, val: &mut Value) {
|
fn offset(&mut self, val: Nid, ty: ty::Id, off: Offset) -> Nid {
|
||||||
if val.off == 0 {
|
if off == 0 {
|
||||||
return;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
let off = self.ci.nodes.new_node_nop(
|
let off = self.ci.nodes.new_node_nop(ty::Id::INT, Kind::CInt { value: off as i64 }, [VOID]);
|
||||||
ty::Id::INT,
|
let inps = [VOID, val, off];
|
||||||
Kind::CInt { value: core::mem::take(&mut val.off) as i64 },
|
self.ci.nodes.new_node(ty, Kind::BinOp { op: TokenKind::Add }, inps)
|
||||||
[VOID],
|
|
||||||
);
|
|
||||||
let inps = [VOID, val.id, off];
|
|
||||||
val.id = self.ci.nodes.new_node(val.ty, Kind::BinOp { op: TokenKind::Add }, inps)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 id = (u16::MAX - n.id) as usize;
|
let id = (u16::MAX - n.id) as usize;
|
||||||
self.ci.nodes.load_loop_value(id, &mut self.ci.vars[id].value, &mut self.ci.loops);
|
self.ci.nodes.load_loop_value(
|
||||||
*n = self.ci.vars[id].value;
|
id,
|
||||||
|
&mut self.ci.scope.vars[id].value,
|
||||||
|
&mut self.ci.loops,
|
||||||
|
);
|
||||||
|
*n = self.ci.scope.vars[id].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1590,10 +1632,9 @@ impl Codegen {
|
||||||
|
|
||||||
if loob.ctrl[id] == Nid::MAX {
|
if loob.ctrl[id] == Nid::MAX {
|
||||||
loob.ctrl[id] = self.ci.ctrl;
|
loob.ctrl[id] = self.ci.ctrl;
|
||||||
loob.ctrl_scope[id] = self.ci.vars[..loob.scope.len()].to_owned();
|
loob.ctrl_scope[id] = self.ci.scope.clone();
|
||||||
for v in &loob.ctrl_scope[id] {
|
loob.ctrl_scope[id].vars.truncate(loob.scope.vars.len());
|
||||||
self.ci.nodes.lock(v.value.id)
|
self.ci.nodes.lock_scope(&loob.ctrl_scope[id]);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let reg =
|
let reg =
|
||||||
self.ci.nodes.new_node(ty::Id::VOID, Kind::Region, [self.ci.ctrl, loob.ctrl[id]]);
|
self.ci.nodes.new_node(ty::Id::VOID, Kind::Region, [self.ci.ctrl, loob.ctrl[id]]);
|
||||||
|
@ -1604,7 +1645,7 @@ impl Codegen {
|
||||||
&mut self.ci.loops,
|
&mut self.ci.loops,
|
||||||
reg,
|
reg,
|
||||||
&mut scope,
|
&mut scope,
|
||||||
&mut self.ci.vars,
|
&mut self.ci.scope,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1621,28 +1662,40 @@ impl Codegen {
|
||||||
nodes: &mut Nodes,
|
nodes: &mut Nodes,
|
||||||
loops: &mut [Loop],
|
loops: &mut [Loop],
|
||||||
ctrl: Nid,
|
ctrl: Nid,
|
||||||
to: &mut [Variable],
|
to: &mut Scope,
|
||||||
from: &mut [Variable],
|
from: &mut Scope,
|
||||||
drop_from: bool,
|
drop_from: bool,
|
||||||
) {
|
) {
|
||||||
for (i, (else_var, then_var)) in to.iter_mut().zip(from).enumerate() {
|
for (i, (to_var, from_var)) in to.vars.iter_mut().zip(&mut from.vars).enumerate() {
|
||||||
if else_var.value.id != then_var.value.id {
|
if to_var.value.id != from_var.value.id {
|
||||||
nodes.load_loop_value(i, &mut then_var.value, loops);
|
nodes.load_loop_value(i, &mut from_var.value, loops);
|
||||||
nodes.load_loop_value(i, &mut else_var.value, loops);
|
nodes.load_loop_value(i, &mut to_var.value, loops);
|
||||||
if else_var.value.id != then_var.value.id {
|
if to_var.value.id != from_var.value.id {
|
||||||
let ty = nodes[else_var.value.id].ty;
|
let ty = nodes[to_var.value.id].ty;
|
||||||
debug_assert_eq!(ty, nodes[then_var.value.id].ty, "TODO: typecheck properly");
|
debug_assert_eq!(ty, nodes[from_var.value.id].ty, "TODO: typecheck properly");
|
||||||
|
|
||||||
let inps = [ctrl, then_var.value.id, else_var.value.id];
|
let inps = [ctrl, from_var.value.id, to_var.value.id];
|
||||||
nodes.unlock(else_var.value.id);
|
nodes.unlock(to_var.value.id);
|
||||||
else_var.value.id = nodes.new_node(ty, Kind::Phi, inps);
|
to_var.value.id = nodes.new_node(ty, Kind::Phi, inps);
|
||||||
nodes.lock(else_var.value.id);
|
nodes.lock(to_var.value.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if drop_from {
|
if to.store != from.store {
|
||||||
nodes.unlock_remove(then_var.value.id);
|
let (to_store, from_store) = (to.store.unwrap(), from.store.unwrap());
|
||||||
}
|
nodes.unlock(to_store);
|
||||||
|
to.store = Some(nodes.new_node(ty::Id::VOID, Kind::Phi, [ctrl, from_store, to_store]));
|
||||||
|
nodes.lock(to.store.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
to.loads.extend(&from.loads);
|
||||||
|
for &load in &from.loads {
|
||||||
|
nodes.lock(load);
|
||||||
|
}
|
||||||
|
|
||||||
|
if drop_from {
|
||||||
|
nodes.unlock_remove_scope(from);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1703,10 +1756,10 @@ impl Codegen {
|
||||||
self.ci.nodes.lock(value);
|
self.ci.nodes.lock(value);
|
||||||
let sym = parser::find_symbol(&ast.symbols, arg.id);
|
let sym = parser::find_symbol(&ast.symbols, arg.id);
|
||||||
assert!(sym.flags & idfl::COMPTIME == 0, "TODO");
|
assert!(sym.flags & idfl::COMPTIME == 0, "TODO");
|
||||||
self.ci.vars.push(Variable { id: arg.id, value: Value::new(value).ty(ty) });
|
self.ci.scope.vars.push(Variable { id: arg.id, value: Value::new(value).ty(ty) });
|
||||||
}
|
}
|
||||||
|
|
||||||
let orig_vars = self.ci.vars.clone();
|
let orig_vars = self.ci.scope.vars.clone();
|
||||||
|
|
||||||
if self.expr(body).is_some() {
|
if self.expr(body).is_some() {
|
||||||
self.report(body.pos(), "expected all paths in the fucntion to return");
|
self.report(body.pos(), "expected all paths in the fucntion to return");
|
||||||
|
@ -1714,18 +1767,9 @@ impl Codegen {
|
||||||
|
|
||||||
self.ci.nodes.unlock(end);
|
self.ci.nodes.unlock(end);
|
||||||
|
|
||||||
if let Some(mem) = self.ci.store.take() {
|
self.ci.nodes.unlock_remove_scope(&core::mem::take(&mut self.ci.scope));
|
||||||
self.ci.nodes.unlock_remove(mem);
|
|
||||||
}
|
|
||||||
for load in self.ci.loads.drain(..) {
|
|
||||||
self.ci.nodes.unlock_remove(load);
|
|
||||||
}
|
|
||||||
self.ci.nodes.unlock(mem);
|
self.ci.nodes.unlock(mem);
|
||||||
|
|
||||||
for var in self.ci.vars.drain(..) {
|
|
||||||
self.ci.nodes.unlock(var.value.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.errors.borrow().is_empty() {
|
if self.errors.borrow().is_empty() {
|
||||||
self.graphviz();
|
self.graphviz();
|
||||||
self.gcm();
|
self.gcm();
|
||||||
|
@ -1756,10 +1800,10 @@ impl Codegen {
|
||||||
self.ci.nodes[mem].outputs = mems;
|
self.ci.nodes[mem].outputs = mems;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.vars = orig_vars;
|
self.ci.scope.vars = orig_vars;
|
||||||
self.ci.nodes.visited.clear(self.ci.nodes.values.len());
|
self.ci.nodes.visited.clear(self.ci.nodes.values.len());
|
||||||
let saved = self.emit_body(sig);
|
let saved = self.emit_body(sig);
|
||||||
self.ci.vars.clear();
|
self.ci.scope.vars.clear();
|
||||||
|
|
||||||
if let Some(last_ret) = self.ci.ret_relocs.last()
|
if let Some(last_ret) = self.ci.ret_relocs.last()
|
||||||
&& last_ret.offset as usize == self.ci.code.len() - 5
|
&& last_ret.offset as usize == self.ci.code.len() - 5
|
||||||
|
@ -1917,6 +1961,7 @@ impl Codegen {
|
||||||
let &[.., rhs] = node.inputs.as_slice() else { unreachable!() };
|
let &[.., rhs] = node.inputs.as_slice() else { unreachable!() };
|
||||||
|
|
||||||
if let Kind::CInt { value } = func.nodes[rhs].kind
|
if let Kind::CInt { value } = func.nodes[rhs].kind
|
||||||
|
&& func.nodes[rhs].lock_rc != 0
|
||||||
&& let Some(op) =
|
&& let Some(op) =
|
||||||
op.imm_binop(node.ty.is_signed(), func.tys.size_of(node.ty))
|
op.imm_binop(node.ty.is_signed(), func.tys.size_of(node.ty))
|
||||||
{
|
{
|
||||||
|
@ -1945,30 +1990,45 @@ impl Codegen {
|
||||||
self.ci.emit(instrs::addi64(atr(allocs[0]), base, offset as _));
|
self.ci.emit(instrs::addi64(atr(allocs[0]), base, offset as _));
|
||||||
}
|
}
|
||||||
Kind::Load => {
|
Kind::Load => {
|
||||||
let region = node.inputs[1];
|
let mut region = node.inputs[1];
|
||||||
|
let mut offset = 0;
|
||||||
|
if func.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
||||||
|
&& let Kind::CInt { value } =
|
||||||
|
func.nodes[func.nodes[region].inputs[2]].kind
|
||||||
|
{
|
||||||
|
region = func.nodes[region].inputs[1];
|
||||||
|
offset = value as Offset;
|
||||||
|
}
|
||||||
let size = self.tys.size_of(node.ty);
|
let size = self.tys.size_of(node.ty);
|
||||||
if size <= 8 {
|
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),
|
Kind::Stck => (reg::STACK_PTR, func.nodes[region].offset + offset),
|
||||||
_ => (atr(allocs[1]), func.nodes[region].offset),
|
_ => (atr(allocs[1]), 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 if node.inputs[2] == VOID => {}
|
||||||
Kind::Stre => {
|
Kind::Stre => {
|
||||||
let region = node.inputs[2];
|
let mut region = node.inputs[2];
|
||||||
if region != VOID {
|
let mut offset = 0;
|
||||||
let size = u16::try_from(self.tys.size_of(node.ty)).expect("TODO");
|
if func.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
||||||
let nd = &func.nodes[region];
|
&& let Kind::CInt { value } =
|
||||||
let (base, offset, src) = match nd.kind {
|
func.nodes[func.nodes[region].inputs[2]].kind
|
||||||
Kind::Stck => (reg::STACK_PTR, nd.offset, allocs[0]),
|
{
|
||||||
_ => (atr(allocs[0]), 0, allocs[1]),
|
region = func.nodes[region].inputs[1];
|
||||||
};
|
offset = value as Offset;
|
||||||
if size > 8 {
|
}
|
||||||
self.ci.emit(instrs::bmc(base, atr(src), size));
|
let size = u16::try_from(self.tys.size_of(node.ty)).expect("TODO");
|
||||||
} else {
|
let nd = &func.nodes[region];
|
||||||
self.ci.emit(instrs::st(atr(src), base, offset as _, size));
|
let (base, offset, src) = match nd.kind {
|
||||||
}
|
Kind::Stck => (reg::STACK_PTR, nd.offset + offset, allocs[0]),
|
||||||
|
_ => (atr(allocs[0]), offset, allocs[1]),
|
||||||
|
};
|
||||||
|
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!(),
|
||||||
|
@ -2158,16 +2218,6 @@ impl Codegen {
|
||||||
self.ci.nodes.visited.clear(self.ci.nodes.values.len());
|
self.ci.nodes.visited.clear(self.ci.nodes.values.len());
|
||||||
push_down(&mut self.ci.nodes, VOID);
|
push_down(&mut self.ci.nodes, VOID);
|
||||||
}
|
}
|
||||||
|
|
||||||
//fn get_load_type(&self, val: Nid) -> Option<ty::Id> {
|
|
||||||
// Some(match self.ci.nodes[val].kind {
|
|
||||||
// Kind::Stre { .. } | Kind::Load { .. } | Kind::Stck | Kind::Arg { .. } => {
|
|
||||||
// self.ci.nodes[val].ty
|
|
||||||
// }
|
|
||||||
// Kind::Ptr { .. } => self.tys.base_of(self.ci.nodes[val].ty).unwrap(),
|
|
||||||
// _ => return None,
|
|
||||||
// })
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: make this more efficient (allocated with arena)
|
// FIXME: make this more efficient (allocated with arena)
|
||||||
|
@ -2272,7 +2322,7 @@ impl<'a> Function<'a> {
|
||||||
let idx = 1 + node.inputs.iter().position(|&i| i == prev).unwrap();
|
let idx = 1 + node.inputs.iter().position(|&i| i == prev).unwrap();
|
||||||
|
|
||||||
for ph in node.outputs {
|
for ph in node.outputs {
|
||||||
if self.nodes[ph].kind != Kind::Phi {
|
if self.nodes[ph].kind != Kind::Phi || self.nodes[ph].ty == ty::Id::VOID {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2334,7 +2384,7 @@ impl<'a> Function<'a> {
|
||||||
}
|
}
|
||||||
let mut block = vec![];
|
let mut block = vec![];
|
||||||
for ph in node.outputs.clone() {
|
for ph in node.outputs.clone() {
|
||||||
if self.nodes[ph].kind != Kind::Phi {
|
if self.nodes[ph].kind != Kind::Phi || self.nodes[ph].ty == ty::Id::VOID {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
self.def_nid(ph);
|
self.def_nid(ph);
|
||||||
|
@ -2357,19 +2407,20 @@ impl<'a> Function<'a> {
|
||||||
self.add_instr(nid, ops);
|
self.add_instr(nid, ops);
|
||||||
self.emit_node(node.outputs[0], nid);
|
self.emit_node(node.outputs[0], nid);
|
||||||
}
|
}
|
||||||
Kind::CInt { .. } => {
|
Kind::CInt { .. }
|
||||||
let unused = node.outputs.into_iter().all(|o| {
|
if node.outputs.iter().all(|&o| {
|
||||||
let ond = &self.nodes[o];
|
let ond = &self.nodes[o];
|
||||||
matches!(ond.kind, Kind::BinOp { op }
|
matches!(ond.kind, Kind::BinOp { op }
|
||||||
if op.imm_binop(ond.ty.is_signed(), 8).is_some()
|
if op.imm_binop(ond.ty.is_signed(), 8).is_some()
|
||||||
&& self.nodes.is_const(ond.inputs[2])
|
&& self.nodes.is_const(ond.inputs[2])
|
||||||
&& op.cond_op(ond.ty.is_signed()).is_none())
|
&& op.cond_op(ond.ty.is_signed()).is_none())
|
||||||
});
|
}) =>
|
||||||
|
{
|
||||||
if !unused {
|
self.nodes.lock(nid)
|
||||||
let ops = vec![self.drg(nid)];
|
}
|
||||||
self.add_instr(nid, ops);
|
Kind::CInt { .. } => {
|
||||||
}
|
let ops = vec![self.drg(nid)];
|
||||||
|
self.add_instr(nid, ops);
|
||||||
}
|
}
|
||||||
Kind::Entry => {
|
Kind::Entry => {
|
||||||
self.nodes[nid].ralloc_backref = self.add_block(nid);
|
self.nodes[nid].ralloc_backref = self.add_block(nid);
|
||||||
|
@ -2410,11 +2461,20 @@ impl<'a> Function<'a> {
|
||||||
self.emit_node(o, nid);
|
self.emit_node(o, nid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Kind::BinOp { op: TokenKind::Add }
|
||||||
|
if self.nodes.is_const(node.inputs[2])
|
||||||
|
&& node
|
||||||
|
.outputs
|
||||||
|
.iter()
|
||||||
|
.all(|&n| matches!(self.nodes[n].kind, Kind::Stre | Kind::Load)) =>
|
||||||
|
{
|
||||||
|
self.nodes.lock(nid)
|
||||||
|
}
|
||||||
Kind::BinOp { op } => {
|
Kind::BinOp { op } => {
|
||||||
let &[_, lhs, rhs] = node.inputs.as_slice() else { unreachable!() };
|
let &[_, lhs, rhs] = node.inputs.as_slice() else { unreachable!() };
|
||||||
|
|
||||||
let ops = if let Kind::CInt { .. } = self.nodes[rhs].kind
|
let ops = if let Kind::CInt { .. } = self.nodes[rhs].kind
|
||||||
&& op.imm_binop(node.ty.is_signed(), 8).is_some()
|
&& self.nodes[rhs].lock_rc != 0
|
||||||
{
|
{
|
||||||
vec![self.drg(nid), self.urg(lhs)]
|
vec![self.drg(nid), self.urg(lhs)]
|
||||||
} else if op.binop(node.ty.is_signed(), 8).is_some() {
|
} else if op.binop(node.ty.is_signed(), 8).is_some() {
|
||||||
|
@ -2479,13 +2539,28 @@ impl<'a> Function<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//Kind::Stck
|
||||||
|
// if node.outputs.iter().all(|&n| {
|
||||||
|
// matches!(self.nodes[n].kind, Kind::Stre | Kind::Load)
|
||||||
|
// || matches!(self.nodes[n].kind, Kind::BinOp { op: TokenKind::Add }
|
||||||
|
// if self.nodes.is_const(self.nodes[n].inputs[2])
|
||||||
|
// && self.nodes[n]
|
||||||
|
// .outputs
|
||||||
|
// .iter()
|
||||||
|
// .all(|&n| matches!(self.nodes[n].kind, Kind::Stre | Kind::Load)))
|
||||||
|
// }) => {}
|
||||||
Kind::Stck => {
|
Kind::Stck => {
|
||||||
let ops = vec![self.drg(nid)];
|
let ops = vec![self.drg(nid)];
|
||||||
self.add_instr(nid, ops);
|
self.add_instr(nid, ops);
|
||||||
}
|
}
|
||||||
Kind::Phi | Kind::Arg { .. } | Kind::Mem => {}
|
Kind::Phi | Kind::Arg { .. } | Kind::Mem => {}
|
||||||
Kind::Load { .. } => {
|
Kind::Load { .. } => {
|
||||||
let region = node.inputs[1];
|
let mut region = node.inputs[1];
|
||||||
|
if self.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
||||||
|
&& self.nodes.is_const(self.nodes[region].inputs[2])
|
||||||
|
{
|
||||||
|
region = self.nodes[region].inputs[1]
|
||||||
|
}
|
||||||
if self.tys.size_of(node.ty) <= 8 {
|
if self.tys.size_of(node.ty) <= 8 {
|
||||||
let ops = match self.nodes[region].kind {
|
let ops = match self.nodes[region].kind {
|
||||||
Kind::Stck => vec![self.drg(nid)],
|
Kind::Stck => vec![self.drg(nid)],
|
||||||
|
@ -2494,18 +2569,22 @@ impl<'a> Function<'a> {
|
||||||
self.add_instr(nid, ops);
|
self.add_instr(nid, ops);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Kind::Stre { .. } if node.inputs[2] == VOID => self.nodes.lock(nid),
|
||||||
Kind::Stre { .. } => {
|
Kind::Stre { .. } => {
|
||||||
let region = node.inputs[2];
|
let mut region = node.inputs[2];
|
||||||
if region != VOID {
|
if self.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
||||||
let ops = match self.nodes[region].kind {
|
&& self.nodes.is_const(self.nodes[region].inputs[2])
|
||||||
_ if self.tys.size_of(node.ty) > 8 => {
|
{
|
||||||
vec![self.urg(region), self.urg(self.nodes[node.inputs[1]].inputs[1])]
|
region = self.nodes[region].inputs[1]
|
||||||
}
|
|
||||||
Kind::Stck => vec![self.urg(node.inputs[1])],
|
|
||||||
_ => vec![self.urg(region), self.urg(node.inputs[1])],
|
|
||||||
};
|
|
||||||
self.add_instr(nid, ops);
|
|
||||||
}
|
}
|
||||||
|
let ops = match self.nodes[region].kind {
|
||||||
|
_ if self.tys.size_of(node.ty) > 8 => {
|
||||||
|
vec![self.urg(region), self.urg(self.nodes[node.inputs[1]].inputs[1])]
|
||||||
|
}
|
||||||
|
Kind::Stck => vec![self.urg(node.inputs[1])],
|
||||||
|
_ => vec![self.urg(region), self.urg(node.inputs[1])],
|
||||||
|
};
|
||||||
|
self.add_instr(nid, ops);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2849,8 +2928,6 @@ mod tests {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//println!("{output}");
|
|
||||||
|
|
||||||
crate::test_run_vm(&out, output);
|
crate::test_run_vm(&out, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2894,5 +2971,6 @@ mod tests {
|
||||||
//tests_ptr_to_ptr_copy;
|
//tests_ptr_to_ptr_copy;
|
||||||
//wide_ret;
|
//wide_ret;
|
||||||
pointer_opts;
|
pointer_opts;
|
||||||
|
conditional_stores;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
lang/tests/son_tests_conditional_stores.txt
Normal file
24
lang/tests/son_tests_conditional_stores.txt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
cond:
|
||||||
|
LI64 r1, 0d
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
main:
|
||||||
|
ADDI64 r254, r254, -48d
|
||||||
|
ST r31, r254, 8a, 40h
|
||||||
|
LI64 r32, 1d
|
||||||
|
ADDI64 r33, r254, 0d
|
||||||
|
ST r32, r254, 0a, 8h
|
||||||
|
JAL r31, r0, :cond
|
||||||
|
LI64 r34, 0d
|
||||||
|
CP r35, r34
|
||||||
|
JNE r1, r35, :0
|
||||||
|
CP r34, r35
|
||||||
|
CP r1, r34
|
||||||
|
JMP :1
|
||||||
|
0: LI64 r1, 2d
|
||||||
|
1: ST r1, r254, 0a, 8h
|
||||||
|
LD r31, r254, 8a, 40h
|
||||||
|
ADDI64 r254, r254, 48d
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
code size: 181
|
||||||
|
ret: 0
|
||||||
|
status: Ok(())
|
|
@ -6,12 +6,12 @@ fib:
|
||||||
JGTU r2, r32, :0
|
JGTU r2, r32, :0
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r33, r2
|
0: CP r33, r2
|
||||||
ADDI64 r2, r33, -1d
|
SUB64 r2, r33, r1
|
||||||
CP r34, r33
|
CP r34, r33
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
CP r2, r34
|
CP r2, r34
|
||||||
CP r35, r1
|
CP r35, r1
|
||||||
ADDI64 r2, r2, -2d
|
SUB64 r2, r2, r32
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
ADD64 r1, r1, r35
|
ADD64 r1, r1, r35
|
||||||
1: LD r31, r254, 0a, 40h
|
1: LD r31, r254, 0a, 40h
|
||||||
|
@ -25,6 +25,6 @@ main:
|
||||||
LD r31, r254, 0a, 8h
|
LD r31, r254, 0a, 8h
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 8d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 225
|
code size: 211
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
fib:
|
fib:
|
||||||
LI64 r7, 1d
|
LI64 r4, 1d
|
||||||
LI64 r4, 0d
|
LI64 r5, 0d
|
||||||
CP r1, r4
|
CP r1, r5
|
||||||
2: JNE r2, r4, :0
|
CP r10, r4
|
||||||
|
2: JNE r2, r5, :0
|
||||||
JMP :1
|
JMP :1
|
||||||
0: ADD64 r3, r7, r1
|
0: ADD64 r3, r10, r1
|
||||||
ADDI64 r2, r2, -1d
|
SUB64 r2, r2, r4
|
||||||
CP r1, r7
|
CP r1, r10
|
||||||
CP r7, r3
|
CP r10, r3
|
||||||
JMP :2
|
JMP :2
|
||||||
1: JALA r0, r31, 0a
|
1: JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
|
@ -18,6 +19,6 @@ main:
|
||||||
LD r31, r254, 0a, 8h
|
LD r31, r254, 0a, 8h
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 8d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 154
|
code size: 150
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -3,23 +3,17 @@ clobber:
|
||||||
ST r3, r2, 0a, 8h
|
ST r3, r2, 0a, 8h
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -64d
|
ADDI64 r254, r254, -32d
|
||||||
ST r31, r254, 8a, 56h
|
ST r31, r254, 8a, 24h
|
||||||
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 r36, r254, 0a, 8h
|
LD r33, r254, 0a, 8h
|
||||||
MULI64 r37, r35, 2d
|
ADDI64 r1, r33, -4d
|
||||||
SUB64 r1, r37, r36
|
LD r31, r254, 8a, 24h
|
||||||
LD r31, r254, 8a, 56h
|
ADDI64 r254, r254, 32d
|
||||||
ADDI64 r254, r254, 64d
|
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 229
|
code size: 166
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
Loading…
Reference in a new issue