mir function type and using internpool
This commit is contained in:
parent
3be955aebf
commit
7801fefa17
|
@ -2,6 +2,7 @@ use std::{
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
|
marker::PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use num_bigint::{BigInt, BigUint, Sign};
|
use num_bigint::{BigInt, BigUint, Sign};
|
||||||
|
@ -679,7 +680,8 @@ impl InternPool {
|
||||||
Key::ArrayType { .. } => {
|
Key::ArrayType { .. } => {
|
||||||
panic!("arrays can't be directly accessed in mir")
|
panic!("arrays can't be directly accessed in mir")
|
||||||
}
|
}
|
||||||
Key::FunctionType { .. } | Key::PointerType { .. } => Type::QWord,
|
Key::FunctionType { .. } => Type::Function,
|
||||||
|
Key::PointerType { .. } => Type::QWord,
|
||||||
Key::StructType { .. } => {
|
Key::StructType { .. } => {
|
||||||
panic!("arrays can't be directly accessed in mir")
|
panic!("arrays can't be directly accessed in mir")
|
||||||
}
|
}
|
||||||
|
|
88
src/mir.rs
88
src/mir.rs
|
@ -13,7 +13,6 @@ use itertools::Itertools;
|
||||||
use crate::asm::amd64::Register;
|
use crate::asm::amd64::Register;
|
||||||
use crate::ast::IntegralType;
|
use crate::ast::IntegralType;
|
||||||
use crate::ast2::intern;
|
use crate::ast2::intern;
|
||||||
use crate::string_table::{Index as StringsIndex, StringTable};
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
|
@ -29,6 +28,7 @@ pub enum Type {
|
||||||
SinglePrecision,
|
SinglePrecision,
|
||||||
/// 64bit ieee-754
|
/// 64bit ieee-754
|
||||||
DoublePrecision,
|
DoublePrecision,
|
||||||
|
Function,
|
||||||
// XWord,
|
// XWord,
|
||||||
// YWord,
|
// YWord,
|
||||||
// ZWord,
|
// ZWord,
|
||||||
|
@ -43,6 +43,7 @@ impl core::fmt::Display for Type {
|
||||||
Type::QWord => "qword",
|
Type::QWord => "qword",
|
||||||
Type::SinglePrecision => "f32",
|
Type::SinglePrecision => "f32",
|
||||||
Type::DoublePrecision => "f64",
|
Type::DoublePrecision => "f64",
|
||||||
|
Type::Function => "fn",
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "{name}")
|
write!(f, "{name}")
|
||||||
|
@ -64,6 +65,7 @@ impl Type {
|
||||||
Type::DWord => reg.into_dword(),
|
Type::DWord => reg.into_dword(),
|
||||||
Type::QWord => reg.into_qword(),
|
Type::QWord => reg.into_qword(),
|
||||||
Type::SinglePrecision | Type::DoublePrecision => reg,
|
Type::SinglePrecision | Type::DoublePrecision => reg,
|
||||||
|
Type::Function => reg.into_qword(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub const fn is_floating(self) -> bool {
|
pub const fn is_floating(self) -> bool {
|
||||||
|
@ -93,6 +95,7 @@ impl Type {
|
||||||
Type::QWord => 64,
|
Type::QWord => 64,
|
||||||
Type::SinglePrecision => 32,
|
Type::SinglePrecision => 32,
|
||||||
Type::DoublePrecision => 64,
|
Type::DoublePrecision => 64,
|
||||||
|
Type::Function => 64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +104,9 @@ impl Type {
|
||||||
Type::Byte => Inst::ConstantByte,
|
Type::Byte => Inst::ConstantByte,
|
||||||
Type::Word => Inst::ConstantWord,
|
Type::Word => Inst::ConstantWord,
|
||||||
Type::SinglePrecision | Type::DWord => Inst::ConstantDWord,
|
Type::SinglePrecision | Type::DWord => Inst::ConstantDWord,
|
||||||
Type::DoublePrecision | Type::QWord => Inst::ConstantQWord,
|
Type::Function | Type::DoublePrecision | Type::QWord => {
|
||||||
|
Inst::ConstantQWord
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +118,7 @@ impl Type {
|
||||||
Type::QWord => 8,
|
Type::QWord => 8,
|
||||||
Type::SinglePrecision => 4,
|
Type::SinglePrecision => 4,
|
||||||
Type::DoublePrecision => 8,
|
Type::DoublePrecision => 8,
|
||||||
|
Type::Function => 8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,7 +354,7 @@ pub union Data {
|
||||||
imm16: u16,
|
imm16: u16,
|
||||||
imm32: u32,
|
imm32: u32,
|
||||||
imm64: u64,
|
imm64: u64,
|
||||||
index: StringsIndex,
|
index: intern::Index,
|
||||||
node: u32,
|
node: u32,
|
||||||
binary: (u32, u32),
|
binary: (u32, u32),
|
||||||
}
|
}
|
||||||
|
@ -387,7 +393,7 @@ impl Data {
|
||||||
pub fn imm64(v: u64) -> Data {
|
pub fn imm64(v: u64) -> Data {
|
||||||
Self { imm64: v }
|
Self { imm64: v }
|
||||||
}
|
}
|
||||||
pub fn index(v: StringsIndex) -> Data {
|
pub fn index(v: intern::Index) -> Data {
|
||||||
Self { index: v }
|
Self { index: v }
|
||||||
}
|
}
|
||||||
pub fn node(v: u32) -> Data {
|
pub fn node(v: u32) -> Data {
|
||||||
|
@ -417,7 +423,7 @@ impl Data {
|
||||||
pub fn as_imm64(self) -> u64 {
|
pub fn as_imm64(self) -> u64 {
|
||||||
unsafe { self.imm64 }
|
unsafe { self.imm64 }
|
||||||
}
|
}
|
||||||
pub fn as_index(self) -> StringsIndex {
|
pub fn as_index(self) -> intern::Index {
|
||||||
unsafe { self.index }
|
unsafe { self.index }
|
||||||
}
|
}
|
||||||
pub fn as_node(self) -> u32 {
|
pub fn as_node(self) -> u32 {
|
||||||
|
@ -736,7 +742,7 @@ impl<'a> BinaryOperands<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Mir {
|
pub struct Mir {
|
||||||
name: StringsIndex,
|
name: intern::Index,
|
||||||
pub nodes: Vec<Inst>,
|
pub nodes: Vec<Inst>,
|
||||||
pub data: Vec<Data>,
|
pub data: Vec<Data>,
|
||||||
}
|
}
|
||||||
|
@ -808,7 +814,7 @@ impl Mir {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mir {
|
impl Mir {
|
||||||
pub fn new(name: StringsIndex) -> Mir {
|
pub fn new(name: intern::Index) -> Mir {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
nodes: Vec::new(),
|
nodes: Vec::new(),
|
||||||
|
@ -862,6 +868,20 @@ impl Mir {
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_const(&mut self, value: intern::Index, ty: Type) -> u32 {
|
||||||
|
let inst = match ty {
|
||||||
|
Type::Byte => Inst::ConstantByte,
|
||||||
|
Type::Word => Inst::ConstantWord,
|
||||||
|
Type::DWord => Inst::ConstantDWord,
|
||||||
|
Type::QWord => Inst::ConstantQWord,
|
||||||
|
Type::SinglePrecision => Inst::ConstantSinglePrecision,
|
||||||
|
Type::DoublePrecision => Inst::ConstantDoublePrecision,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let data = Data::index(value);
|
||||||
|
self.push(inst, data)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn gen_u8(&mut self, value: u8) -> u32 {
|
pub fn gen_u8(&mut self, value: u8) -> u32 {
|
||||||
self.push(Inst::ConstantByte, Data::imm8(value))
|
self.push(Inst::ConstantByte, Data::imm8(value))
|
||||||
}
|
}
|
||||||
|
@ -1012,10 +1032,10 @@ impl Mir {
|
||||||
alloc
|
alloc
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_label(&mut self, name: StringsIndex) -> u32 {
|
pub fn gen_label(&mut self, name: intern::Index) -> u32 {
|
||||||
self.push(Inst::Label, Data::index(name))
|
self.push(Inst::Label, Data::index(name))
|
||||||
}
|
}
|
||||||
pub fn gen_extern(&mut self, ty: Option<Type>, name: StringsIndex) -> u32 {
|
pub fn gen_extern(&mut self, ty: Option<Type>, name: intern::Index) -> u32 {
|
||||||
self.push(Inst::ExternRef(ty), Data::index(name))
|
self.push(Inst::ExternRef(ty), Data::index(name))
|
||||||
}
|
}
|
||||||
pub fn gen_alloca(&mut self, size: u32, align: u32) -> u32 {
|
pub fn gen_alloca(&mut self, size: u32, align: u32) -> u32 {
|
||||||
|
@ -1085,7 +1105,9 @@ impl Mir {
|
||||||
Type::Byte => self.gen_u8(mask as u8),
|
Type::Byte => self.gen_u8(mask as u8),
|
||||||
Type::Word => self.gen_u16(mask as u16),
|
Type::Word => self.gen_u16(mask as u16),
|
||||||
Type::SinglePrecision | Type::DWord => self.gen_u32(mask as u32),
|
Type::SinglePrecision | Type::DWord => self.gen_u32(mask as u32),
|
||||||
Type::DoublePrecision | Type::QWord => self.gen_u64(mask as u64),
|
Type::Function | Type::DoublePrecision | Type::QWord => {
|
||||||
|
self.gen_u64(mask as u64)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let masked = self.gen_bitand(ty, src, mask);
|
let masked = self.gen_bitand(ty, src, mask);
|
||||||
|
@ -1303,7 +1325,7 @@ impl Mir {
|
||||||
fn render_node<W: core::fmt::Write>(
|
fn render_node<W: core::fmt::Write>(
|
||||||
&self,
|
&self,
|
||||||
w: &mut W,
|
w: &mut W,
|
||||||
strings: &StringTable,
|
ip: &intern::InternPool,
|
||||||
liveness: &Liveness,
|
liveness: &Liveness,
|
||||||
node: u32,
|
node: u32,
|
||||||
) -> core::fmt::Result {
|
) -> core::fmt::Result {
|
||||||
|
@ -1316,15 +1338,13 @@ impl Mir {
|
||||||
}
|
}
|
||||||
|
|
||||||
match inst {
|
match inst {
|
||||||
Inst::Label => writeln!(
|
Inst::Label => {
|
||||||
w,
|
writeln!(w, "%{node} = label {}", ip.get_str(data.as_index()))
|
||||||
"%{node} = label {}",
|
}
|
||||||
strings.get_str(data.as_index())
|
|
||||||
),
|
|
||||||
Inst::ConstantBytes => writeln!(
|
Inst::ConstantBytes => writeln!(
|
||||||
w,
|
w,
|
||||||
"%{node} = bytes({:x?})",
|
"%{node} = bytes({:x?})",
|
||||||
strings.get_bytes(data.as_index())
|
ip.get_bytes(data.as_index())
|
||||||
),
|
),
|
||||||
Inst::ConstantByte => {
|
Inst::ConstantByte => {
|
||||||
writeln!(w, "%{node} = imm8({:x?})", data.as_imm8())
|
writeln!(w, "%{node} = imm8({:x?})", data.as_imm8())
|
||||||
|
@ -1357,7 +1377,7 @@ impl Mir {
|
||||||
if let Some(ty) = ty {
|
if let Some(ty) = ty {
|
||||||
write!(w, "{ty} ")?;
|
write!(w, "{ty} ")?;
|
||||||
}
|
}
|
||||||
writeln!(w, "{}", strings.get_str(data.as_index()))
|
writeln!(w, "{}", ip.get_str(data.as_index()))
|
||||||
}
|
}
|
||||||
Inst::Alloca => {
|
Inst::Alloca => {
|
||||||
let (size, align) = data.as_binary();
|
let (size, align) = data.as_binary();
|
||||||
|
@ -1535,20 +1555,20 @@ impl Mir {
|
||||||
pub fn render<W: core::fmt::Write>(
|
pub fn render<W: core::fmt::Write>(
|
||||||
&self,
|
&self,
|
||||||
w: &mut W,
|
w: &mut W,
|
||||||
strings: &StringTable,
|
ip: &intern::InternPool,
|
||||||
) -> core::fmt::Result {
|
) -> core::fmt::Result {
|
||||||
let reg_alloc = self.build_liveness();
|
let reg_alloc = self.build_liveness();
|
||||||
for node in 0..self.nodes.len() {
|
for node in 0..self.nodes.len() {
|
||||||
self.render_node(w, strings, ®_alloc, node as u32)?;
|
self.render_node(w, ip, ®_alloc, node as u32)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display<'a, 'b>(
|
pub fn display<'a, 'b>(
|
||||||
&'a self,
|
&'a self,
|
||||||
strings: &'b StringTable,
|
ip: &'b intern::InternPool,
|
||||||
) -> DisplayMir<'a, 'b> {
|
) -> DisplayMir<'a, 'b> {
|
||||||
DisplayMir { mir: self, strings }
|
DisplayMir { mir: self, ip }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2440,7 +2460,7 @@ impl core::fmt::Display for RipRelative {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
name: StringsIndex,
|
name: intern::Index,
|
||||||
constants: BTreeMap<usize, String>,
|
constants: BTreeMap<usize, String>,
|
||||||
branches: BTreeMap<NodeRef, String>,
|
branches: BTreeMap<NodeRef, String>,
|
||||||
current_branch: NodeRef,
|
current_branch: NodeRef,
|
||||||
|
@ -2451,7 +2471,7 @@ pub struct Function {
|
||||||
// predefined constants: 0F32, 0F64, NEG1F32, NEG1F64
|
// predefined constants: 0F32, 0F64, NEG1F32, NEG1F64
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
fn new(name: StringsIndex) -> Self {
|
fn new(name: intern::Index) -> Self {
|
||||||
let current_branch = NodeRef::MIN;
|
let current_branch = NodeRef::MIN;
|
||||||
let branches = BTreeMap::from([(current_branch, String::new())]);
|
let branches = BTreeMap::from([(current_branch, String::new())]);
|
||||||
Self {
|
Self {
|
||||||
|
@ -2466,22 +2486,22 @@ impl Function {
|
||||||
|
|
||||||
pub fn finish_as_function(
|
pub fn finish_as_function(
|
||||||
self,
|
self,
|
||||||
strings: &StringTable,
|
ip: &intern::InternPool,
|
||||||
) -> Result<String, core::fmt::Error> {
|
) -> Result<String, core::fmt::Error> {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
self.finish(&mut buf, strings)?;
|
self.finish(&mut buf, ip)?;
|
||||||
|
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish_constants(
|
pub fn finish_constants(
|
||||||
self,
|
self,
|
||||||
strings: &StringTable,
|
ip: &intern::InternPool,
|
||||||
) -> Result<String, core::fmt::Error> {
|
) -> Result<String, core::fmt::Error> {
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let w = &mut buf;
|
let w = &mut buf;
|
||||||
let name = strings.get_str(self.name).to_owned();
|
let name = ip.get_str(self.name).to_owned();
|
||||||
writeln!(w, "{name}:")?;
|
writeln!(w, "{name}:")?;
|
||||||
|
|
||||||
for (_, contents) in self.constants {
|
for (_, contents) in self.constants {
|
||||||
|
@ -2518,7 +2538,7 @@ impl Function {
|
||||||
i: usize,
|
i: usize,
|
||||||
inst: Inst,
|
inst: Inst,
|
||||||
data: Data,
|
data: Data,
|
||||||
strings: &StringTable,
|
strings: &intern::InternPool,
|
||||||
) {
|
) {
|
||||||
match inst {
|
match inst {
|
||||||
Inst::ConstantBytes => {
|
Inst::ConstantBytes => {
|
||||||
|
@ -2552,7 +2572,7 @@ impl Function {
|
||||||
pub fn finish<W: core::fmt::Write>(
|
pub fn finish<W: core::fmt::Write>(
|
||||||
mut self,
|
mut self,
|
||||||
w: &mut W,
|
w: &mut W,
|
||||||
strings: &StringTable,
|
strings: &intern::InternPool,
|
||||||
) -> core::fmt::Result {
|
) -> core::fmt::Result {
|
||||||
let name = strings.get_str(self.name).to_owned();
|
let name = strings.get_str(self.name).to_owned();
|
||||||
writeln!(w, ".globl {name}")?;
|
writeln!(w, ".globl {name}")?;
|
||||||
|
@ -2603,7 +2623,7 @@ impl Mir {
|
||||||
liveness: &Liveness,
|
liveness: &Liveness,
|
||||||
mapping: &BTreeMap<usize, (u32, u32)>,
|
mapping: &BTreeMap<usize, (u32, u32)>,
|
||||||
func: &mut Function,
|
func: &mut Function,
|
||||||
strings: &StringTable,
|
strings: &intern::InternPool,
|
||||||
node: u32,
|
node: u32,
|
||||||
) -> ImmRegMem {
|
) -> ImmRegMem {
|
||||||
let inst = self.nodes[node as usize];
|
let inst = self.nodes[node as usize];
|
||||||
|
@ -2696,7 +2716,7 @@ impl Mir {
|
||||||
|
|
||||||
pub fn assemble(
|
pub fn assemble(
|
||||||
&self,
|
&self,
|
||||||
strings: &StringTable,
|
strings: &intern::InternPool,
|
||||||
) -> Result<Function, core::fmt::Error> {
|
) -> Result<Function, core::fmt::Error> {
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
// mapping if (i, (stack_offset, bytes)) for local stack variables
|
// mapping if (i, (stack_offset, bytes)) for local stack variables
|
||||||
|
@ -4217,11 +4237,11 @@ impl Mir {
|
||||||
|
|
||||||
pub struct DisplayMir<'a, 'b> {
|
pub struct DisplayMir<'a, 'b> {
|
||||||
mir: &'a Mir,
|
mir: &'a Mir,
|
||||||
strings: &'b StringTable,
|
ip: &'b intern::InternPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> core::fmt::Display for DisplayMir<'a, 'b> {
|
impl<'a, 'b> core::fmt::Display for DisplayMir<'a, 'b> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
self.mir.render(f, &self.strings)
|
self.mir.render(f, &self.ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue