asm output, random fixes
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
use crate::{
|
||||
compiler::arch::riscv::Reg,
|
||||
ir::{arch::riscv64::RV64Instruction, IRUInstruction, VarInst},
|
||||
ir::{
|
||||
arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, IRUInstruction, Type, VarInst,
|
||||
},
|
||||
parser::PAsmBlockArg,
|
||||
};
|
||||
|
||||
use super::{FnLowerCtx, FnLowerable, PAsmBlock, PAsmBlockArg, PInstruction};
|
||||
use super::{FnLowerCtx, FnLowerable, PAsmBlock, PInstruction, PUAsmBlockArg};
|
||||
|
||||
type PLAsmBlockArg = PAsmBlockArg<Reg, VarInst>;
|
||||
|
||||
impl FnLowerable for PInstruction {
|
||||
type Output = RV64Instruction;
|
||||
@@ -14,9 +19,35 @@ impl FnLowerable for PInstruction {
|
||||
}
|
||||
|
||||
impl FnLowerable for PAsmBlock {
|
||||
type Output = ();
|
||||
type Output = VarInst;
|
||||
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output> {
|
||||
let mut args = Vec::new();
|
||||
let mut output = None;
|
||||
for a in &self.args {
|
||||
if let Some(a) = a.lower(ctx) {
|
||||
match a {
|
||||
PAsmBlockArg::In { reg, var } => args.push(AsmBlockArg {
|
||||
reg,
|
||||
var,
|
||||
ty: AsmBlockArgType::In,
|
||||
}),
|
||||
PAsmBlockArg::Out { reg } => {
|
||||
if output.is_some() {
|
||||
ctx.err("cannot evaluate to more than one register".to_string());
|
||||
continue;
|
||||
}
|
||||
let var = ctx.temp(Type::Bits(64));
|
||||
args.push(AsmBlockArg {
|
||||
var,
|
||||
reg,
|
||||
ty: AsmBlockArgType::Out,
|
||||
});
|
||||
output = Some(var)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let block = IRUInstruction::AsmBlock {
|
||||
instructions: {
|
||||
let mut v = Vec::new();
|
||||
@@ -27,27 +58,25 @@ impl FnLowerable for PAsmBlock {
|
||||
}
|
||||
v
|
||||
},
|
||||
args: {
|
||||
let mut v = Vec::new();
|
||||
for a in &self.args {
|
||||
if let Some(a) = a.lower(ctx) {
|
||||
v.push(a);
|
||||
}
|
||||
}
|
||||
v
|
||||
},
|
||||
args,
|
||||
};
|
||||
ctx.push(block);
|
||||
Some(())
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
impl FnLowerable for PAsmBlockArg {
|
||||
type Output = (Reg, VarInst);
|
||||
impl FnLowerable for PUAsmBlockArg {
|
||||
type Output = PLAsmBlockArg;
|
||||
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output> {
|
||||
let var = ctx.get_var(&self.var)?;
|
||||
let reg = Reg::from_ident(&self.reg, ctx)?;
|
||||
Some((reg, var))
|
||||
Some(match self {
|
||||
PAsmBlockArg::In { reg, var } => PLAsmBlockArg::In {
|
||||
reg: Reg::from_ident(reg, ctx)?,
|
||||
var: var.as_ref()?.lower(ctx)?,
|
||||
},
|
||||
PAsmBlockArg::Out { reg } => PLAsmBlockArg::Out {
|
||||
reg: Reg::from_ident(reg, ctx)?,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,7 @@ use crate::ir::{IRUProgram, Origin, Type, VarDef};
|
||||
use super::{CompilerMsg, CompilerOutput, FileSpan, Node, PType, PVarDef};
|
||||
|
||||
impl Node<PVarDef> {
|
||||
pub fn lower(
|
||||
&self,
|
||||
program: &mut IRUProgram,
|
||||
output: &mut CompilerOutput,
|
||||
) -> Option<VarDef> {
|
||||
pub fn lower(&self, program: &mut IRUProgram, output: &mut CompilerOutput) -> Option<VarDef> {
|
||||
let s = self.as_ref()?;
|
||||
let name = s.name.as_ref()?.to_string();
|
||||
let ty = match &s.ty {
|
||||
@@ -17,7 +13,7 @@ impl Node<PVarDef> {
|
||||
Some(VarDef {
|
||||
name,
|
||||
ty,
|
||||
origin: Origin::File(self.span),
|
||||
origin: self.span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::{func::FnLowerCtx, FnLowerable, PExpr, UnaryOp};
|
||||
use crate::{
|
||||
ir::{DataDef, IRUInstruction, Origin, Type, VarInst},
|
||||
ir::{DataDef, IRUInstruction, Type, VarInst},
|
||||
parser::PInfixOp,
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ impl FnLowerable for PExpr {
|
||||
let src = ctx.program.def_data(
|
||||
DataDef {
|
||||
ty: Type::Bits(8).arr(data.len() as u32),
|
||||
origin: Origin::File(l.span),
|
||||
origin: l.span,
|
||||
label: format!("string \"{}\"", s.replace("\n", "\\n")),
|
||||
},
|
||||
data,
|
||||
@@ -29,7 +29,7 @@ impl FnLowerable for PExpr {
|
||||
let src = ctx.program.def_data(
|
||||
DataDef {
|
||||
ty,
|
||||
origin: Origin::File(l.span),
|
||||
origin: l.span,
|
||||
label: format!("char '{c}'"),
|
||||
},
|
||||
c.to_string().as_bytes().to_vec(),
|
||||
@@ -44,7 +44,7 @@ impl FnLowerable for PExpr {
|
||||
let src = ctx.program.def_data(
|
||||
DataDef {
|
||||
ty,
|
||||
origin: Origin::File(l.span),
|
||||
origin: l.span,
|
||||
label: format!("num {n:?}"),
|
||||
},
|
||||
n.whole.parse::<i64>().unwrap().to_le_bytes().to_vec(),
|
||||
@@ -131,10 +131,7 @@ impl FnLowerable for PExpr {
|
||||
}
|
||||
}
|
||||
PExpr::Block(b) => b.lower(ctx)?,
|
||||
PExpr::AsmBlock(b) => {
|
||||
b.lower(ctx);
|
||||
return None;
|
||||
}
|
||||
PExpr::AsmBlock(b) => b.lower(ctx)?,
|
||||
PExpr::Call(e, args) => {
|
||||
let fe = e.lower(ctx)?;
|
||||
let mut nargs = Vec::new();
|
||||
|
||||
@@ -31,7 +31,7 @@ impl PFunction {
|
||||
.map(|a| {
|
||||
a.lower(map, output).unwrap_or(VarDef {
|
||||
name: "{error}".to_string(),
|
||||
origin: Origin::File(a.span),
|
||||
origin: a.span,
|
||||
ty: Type::Error,
|
||||
})
|
||||
})
|
||||
@@ -42,7 +42,7 @@ impl PFunction {
|
||||
};
|
||||
Some(map.def_fn(FnDef {
|
||||
name: name.to_string(),
|
||||
origin: Origin::File(self.header.span),
|
||||
origin: self.header.span,
|
||||
args,
|
||||
ret,
|
||||
}))
|
||||
|
||||
@@ -81,7 +81,7 @@ impl PStruct {
|
||||
};
|
||||
p.def_type(StructDef {
|
||||
name: self.name.as_ref()?.to_string(),
|
||||
origin: Origin::File(span),
|
||||
origin: span,
|
||||
size: offset,
|
||||
fields,
|
||||
});
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
use super::{
|
||||
util::parse_list, PIdent, Node, Parsable, ParseResult, PInstruction, ParserCtx, Symbol,
|
||||
util::parse_list, Node, PExpr, PIdent, PInstruction, Parsable, ParseResult, ParserCtx, Symbol,
|
||||
};
|
||||
|
||||
pub struct PAsmBlock {
|
||||
pub instructions: Vec<Node<PInstruction>>,
|
||||
pub args: Vec<Node<PAsmBlockArg>>,
|
||||
pub args: Vec<Node<PUAsmBlockArg>>,
|
||||
}
|
||||
|
||||
pub struct PAsmBlockArg {
|
||||
pub reg: Node<PIdent>,
|
||||
pub var: Node<PIdent>,
|
||||
pub enum PAsmBlockArg<R, V> {
|
||||
In { reg: R, var: V },
|
||||
Out { reg: R },
|
||||
}
|
||||
|
||||
pub type PUAsmBlockArg = PAsmBlockArg<Node<PIdent>, Node<PExpr>>;
|
||||
|
||||
impl Parsable for PAsmBlock {
|
||||
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
|
||||
let args = if ctx.expect_peek()?.is_symbol(Symbol::OpenParen) {
|
||||
@@ -34,12 +36,18 @@ impl Parsable for PAsmBlock {
|
||||
}
|
||||
}
|
||||
|
||||
impl Parsable for PAsmBlockArg {
|
||||
impl Parsable for PUAsmBlockArg {
|
||||
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
|
||||
let reg = ctx.parse()?;
|
||||
ctx.expect_sym(Symbol::Equals)?;
|
||||
let var = ctx.parse()?;
|
||||
ParseResult::Ok(Self { reg, var })
|
||||
let reg = ctx.parse::<PIdent>()?;
|
||||
ParseResult::Ok(if reg.inner.as_ref().is_some_and(|s| s.0 == "out") {
|
||||
ctx.expect_sym(Symbol::Equals)?;
|
||||
let reg = ctx.parse()?;
|
||||
Self::Out { reg }
|
||||
} else {
|
||||
ctx.expect_sym(Symbol::Equals)?;
|
||||
let var = ctx.parse()?;
|
||||
Self::In { reg, var }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user