mirror of
https://github.com/uutils/awk.git
synced 2026-06-10 16:15:04 -07:00
interpreter: hinted registers
This commit is contained in:
+41
-17
@@ -14,13 +14,10 @@
|
||||
|
||||
mod lower;
|
||||
|
||||
use std::{
|
||||
fmt::{Debug, Display},
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
pub use lower::test_interpreter;
|
||||
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(transparent)]
|
||||
struct NonLocal(u16);
|
||||
@@ -85,7 +82,7 @@ const _: () = const { assert!(size_of::<Instruction>() <= 8) };
|
||||
#[repr(C, align(8))]
|
||||
struct Instruction {
|
||||
opcode: OpCode,
|
||||
// hint: Hint,
|
||||
hint: Hint,
|
||||
args: Arguments,
|
||||
}
|
||||
|
||||
@@ -104,30 +101,39 @@ union Arguments {
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
fn unary(opcode: impl Into<OpCode>, dest: Reg, src: &impl Deref<Target = Reg>) -> Self {
|
||||
fn unary(opcode: impl Into<OpCode>, dest: Reg, src: &impl HintedReg) -> Self {
|
||||
let opcode = opcode.into();
|
||||
debug_assert!(opcode.is_unary());
|
||||
Self {
|
||||
opcode,
|
||||
args: Arguments {
|
||||
unary_local: (dest, **src),
|
||||
unary_local: (dest, src.reg()),
|
||||
},
|
||||
hint: src.hint(),
|
||||
}
|
||||
}
|
||||
|
||||
fn binary(
|
||||
opcode: impl Into<OpCode>,
|
||||
dest: Reg,
|
||||
lhs: &impl Deref<Target = Reg>,
|
||||
rhs: &impl Deref<Target = Reg>,
|
||||
lhs: &impl HintedReg,
|
||||
rhs: &impl HintedReg,
|
||||
) -> Self {
|
||||
let opcode = opcode.into();
|
||||
debug_assert!(opcode.is_binary());
|
||||
let hint = match (lhs.hint(), rhs.hint()) {
|
||||
// TODO: Remove once we get const folding.
|
||||
(Hint::UnboxedFloat64, Hint::UnboxedFloat64) => Hint::UnboxedFloat64,
|
||||
(_, Hint::UnboxedFloat64) => Hint::UnboxedRhsFloat64,
|
||||
(Hint::UnboxedFloat64, _) => Hint::UnboxedLhsFloat64,
|
||||
_ => Hint::None,
|
||||
};
|
||||
Self {
|
||||
opcode,
|
||||
args: Arguments {
|
||||
binary_local: (dest, **lhs, **rhs),
|
||||
binary_local: (dest, lhs.reg(), rhs.reg()),
|
||||
},
|
||||
hint,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +145,7 @@ impl Instruction {
|
||||
args: Arguments {
|
||||
load_store: (dest, src),
|
||||
},
|
||||
hint: Hint::None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,6 +155,7 @@ impl Instruction {
|
||||
Self {
|
||||
opcode,
|
||||
args: Arguments { jump: to },
|
||||
hint: Hint::None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,6 +167,7 @@ impl Instruction {
|
||||
args: Arguments {
|
||||
branch: (cond, true_to, false_to),
|
||||
},
|
||||
hint: Hint::None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,6 +177,7 @@ impl Instruction {
|
||||
Self {
|
||||
opcode,
|
||||
args: Arguments { br_if: (cond, to) },
|
||||
hint: Hint::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,12 +229,19 @@ impl OpCode {
|
||||
}
|
||||
}
|
||||
|
||||
// #[derive(Clone, Copy)]
|
||||
// #[repr(u8, align(1))]
|
||||
// enum Hint {
|
||||
// // Next instruction contains additional data; for use in pipes, etc.
|
||||
// // Also allows us to move past (2^16 - 1) variables if we want to.
|
||||
// }
|
||||
#[repr(u8, align(1))]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum Hint {
|
||||
None = 0,
|
||||
UnboxedFloat64,
|
||||
UnboxedLhsFloat64,
|
||||
UnboxedRhsFloat64,
|
||||
}
|
||||
|
||||
trait HintedReg {
|
||||
fn reg(&self) -> Reg;
|
||||
fn hint(&self) -> Hint;
|
||||
}
|
||||
|
||||
impl Debug for Instruction {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
@@ -323,6 +340,13 @@ impl Display for Instruction {
|
||||
write!(f, "{op} {label}")
|
||||
}
|
||||
_ => todo!(),
|
||||
}?;
|
||||
match self.hint {
|
||||
Hint::UnboxedFloat64 if self.opcode.is_binary() => write!(f, " @ all_unboxedf64"),
|
||||
Hint::UnboxedFloat64 => write!(f, " @ all_unboxedf64"),
|
||||
Hint::UnboxedLhsFloat64 => write!(f, " @ lhs_unboxedf64"),
|
||||
Hint::UnboxedRhsFloat64 => write!(f, " @ rhs_unboxedf64"),
|
||||
Hint::None => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-15
@@ -6,15 +6,14 @@
|
||||
use std::fmt::Display;
|
||||
use std::hash::Hash;
|
||||
use std::mem::forget;
|
||||
use std::ops::Deref;
|
||||
|
||||
use indexmap::IndexSet;
|
||||
use parser::{Atom, BinaryOperator, Expr, ExprNode, UnaryOperator};
|
||||
|
||||
use crate::ir::{Instruction, Label, NonLocal, OpCode, Reg};
|
||||
use crate::ir::{Hint, HintedReg, Instruction, Label, NonLocal, OpCode, Reg};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
||||
struct Value(f64); // TODO: use NaN-boxing.
|
||||
pub struct Value(f64); // TODO: use NaN-boxing.
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Code {
|
||||
@@ -26,16 +25,15 @@ struct Code {
|
||||
|
||||
#[must_use]
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
struct LinearReg(Reg);
|
||||
struct LinearReg(Reg, Hint);
|
||||
|
||||
impl Code {
|
||||
fn lower_expr(&mut self, expr: &Expr) -> LinearReg {
|
||||
let dest = self.alloc_reg();
|
||||
self.lower_expr_into(expr, dest);
|
||||
LinearReg(dest)
|
||||
let hint = self.lower_expr_into(expr, dest);
|
||||
LinearReg(dest, hint)
|
||||
}
|
||||
fn lower_expr_into(&mut self, expr: &Expr, dest: Reg) {
|
||||
fn lower_expr_into(&mut self, expr: &Expr, dest: Reg) -> Hint {
|
||||
match expr {
|
||||
Expr::Leaf(atom) => match atom {
|
||||
Atom::Variable(var) => {
|
||||
@@ -47,6 +45,7 @@ impl Code {
|
||||
let src = self.register_const(Value(n));
|
||||
self.bc
|
||||
.emit(Instruction::load_store(OpCode::LoadConst, dest, src));
|
||||
return Hint::UnboxedFloat64;
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
@@ -84,6 +83,7 @@ impl Code {
|
||||
_ => todo!(),
|
||||
},
|
||||
}
|
||||
Hint::None
|
||||
}
|
||||
|
||||
fn alloc_reg(&mut self) -> Reg {
|
||||
@@ -141,7 +141,7 @@ impl RegsState {
|
||||
n_free_regs: code.free_regs.len(),
|
||||
}
|
||||
}
|
||||
fn scope(self, code: &mut Code, f: impl FnOnce(&mut Code)) -> Self {
|
||||
fn scope<T>(self, code: &mut Code, f: impl FnOnce(&mut Code) -> T) -> Self {
|
||||
f(code);
|
||||
let old = code.reg_pointer;
|
||||
code.reg_pointer = self.reg_pointer;
|
||||
@@ -151,7 +151,7 @@ impl RegsState {
|
||||
n_free_regs: self.n_free_regs,
|
||||
}
|
||||
}
|
||||
fn scope_hwm(self, code: &mut Code, f: impl FnOnce(&mut Code)) {
|
||||
fn scope_hwm<T>(self, code: &mut Code, f: impl FnOnce(&mut Code) -> T) {
|
||||
f(code);
|
||||
code.reg_pointer = code.reg_pointer.max(self.reg_pointer);
|
||||
code.free_regs.truncate(self.n_free_regs);
|
||||
@@ -166,7 +166,6 @@ pub fn test_interpreter(expr: &Expr<'_>) -> impl Display {
|
||||
free_regs: Vec::new(),
|
||||
};
|
||||
let result = c.lower_expr(expr);
|
||||
dbg!(&c, &result);
|
||||
forget(result);
|
||||
c
|
||||
}
|
||||
@@ -254,11 +253,13 @@ impl LinearReg {
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for LinearReg {
|
||||
type Target = Reg;
|
||||
impl HintedReg for LinearReg {
|
||||
fn reg(&self) -> Reg {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
fn hint(&self) -> Hint {
|
||||
self.1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user