asm output, random fixes
This commit is contained in:
@@ -39,11 +39,7 @@ pub struct DataDef {
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Origin {
|
||||
Builtin,
|
||||
File(FileSpan),
|
||||
}
|
||||
pub type Origin = FileSpan;
|
||||
|
||||
impl FnDef {
|
||||
pub fn ty(&self) -> Type {
|
||||
|
||||
@@ -45,7 +45,7 @@ pub enum IRUInstruction {
|
||||
},
|
||||
AsmBlock {
|
||||
instructions: Vec<RV64Instruction>,
|
||||
args: Vec<(Reg, VarInst)>,
|
||||
args: Vec<AsmBlockArg>,
|
||||
},
|
||||
Ret {
|
||||
src: VarInst,
|
||||
@@ -64,6 +64,19 @@ pub enum IRUInstruction {
|
||||
Break,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AsmBlockArg {
|
||||
pub var: VarInst,
|
||||
pub reg: Reg,
|
||||
pub ty: AsmBlockArgType,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AsmBlockArgType {
|
||||
In,
|
||||
Out,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for IRUInstruction {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
@@ -77,7 +90,9 @@ impl std::fmt::Debug for IRUInstruction {
|
||||
f: func,
|
||||
args,
|
||||
} => write!(f, "{dest:?} <- {func:?}({args:?})")?,
|
||||
Self::AsmBlock { args, instructions } => write!(f, "asm {args:?} {instructions:#?}")?,
|
||||
Self::AsmBlock { args, instructions } => {
|
||||
write!(f, "asm {args:?} {instructions:#?}")?
|
||||
}
|
||||
Self::Ret { src } => f.debug_struct("Ret").field("src", src).finish()?,
|
||||
Self::Construct { dest, fields } => write!(f, "{dest:?} <- {fields:?}")?,
|
||||
Self::Access { dest, src, field } => write!(f, "{dest:?} <- {src:?}.{field}")?,
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Debug,
|
||||
};
|
||||
use std::{collections::HashMap, fmt::Debug};
|
||||
|
||||
use crate::common::FileSpan;
|
||||
|
||||
@@ -98,10 +95,10 @@ impl IRUProgram {
|
||||
pub fn size_of_var(&self, var: VarID) -> Option<Size> {
|
||||
self.size_of_type(&self.var_defs[var.0].ty)
|
||||
}
|
||||
pub fn temp_var(&mut self, origin: FileSpan, ty: Type) -> VarInst {
|
||||
pub fn temp_var(&mut self, origin: Origin, ty: Type) -> VarInst {
|
||||
let v = self.def_var(VarDef {
|
||||
name: format!("temp{}", self.temp),
|
||||
origin: super::Origin::File(origin),
|
||||
origin,
|
||||
ty,
|
||||
});
|
||||
self.temp += 1;
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
// TODO: move this into ir, not parser
|
||||
use super::{IRUInstrInst, IRUInstruction, IRUProgram, Type};
|
||||
use crate::common::{CompilerMsg, CompilerOutput};
|
||||
use crate::common::{CompilerMsg, CompilerOutput, FileSpan};
|
||||
|
||||
impl IRUProgram {
|
||||
pub fn validate(&self) -> CompilerOutput {
|
||||
let mut output = CompilerOutput::new();
|
||||
for (f, fd) in self.fns.iter().flatten().zip(&self.fn_defs) {
|
||||
self.validate_fn(&f.instructions, &fd.ret, &mut output, false);
|
||||
self.validate_fn(
|
||||
&f.instructions,
|
||||
fd.origin,
|
||||
&fd.ret,
|
||||
&mut output,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
}
|
||||
output
|
||||
}
|
||||
@@ -14,10 +21,13 @@ impl IRUProgram {
|
||||
pub fn validate_fn(
|
||||
&self,
|
||||
instructions: &[IRUInstrInst],
|
||||
origin: FileSpan,
|
||||
ret: &Type,
|
||||
output: &mut CompilerOutput,
|
||||
needs_ret: bool,
|
||||
breakable: bool,
|
||||
) {
|
||||
let mut no_ret = true;
|
||||
for i in instructions {
|
||||
match &i.i {
|
||||
IRUInstruction::Mv { dest, src } => {
|
||||
@@ -25,7 +35,9 @@ impl IRUProgram {
|
||||
let src = self.get_var(src.id);
|
||||
output.check_assign(self, &src.ty, &dest.ty, i.span);
|
||||
}
|
||||
IRUInstruction::Ref { dest, src } => todo!(),
|
||||
IRUInstruction::Ref { dest, src } => {
|
||||
// TODO
|
||||
}
|
||||
IRUInstruction::LoadData { dest, src } => {
|
||||
let dest = self.get_var(dest.id);
|
||||
let src = self.get_data(*src);
|
||||
@@ -64,6 +76,7 @@ impl IRUProgram {
|
||||
IRUInstruction::Ret { src } => {
|
||||
let srcty = &self.get_var(src.id).ty;
|
||||
output.check_assign(self, srcty, ret, src.span);
|
||||
no_ret = false;
|
||||
}
|
||||
IRUInstruction::Construct { dest, fields } => {
|
||||
let dest_def = self.get_var(dest.id);
|
||||
@@ -120,10 +133,10 @@ impl IRUProgram {
|
||||
IRUInstruction::If { cond, body } => {
|
||||
let cond = self.get_var(cond.id);
|
||||
output.check_assign(self, &cond.ty, &Type::Bits(64), i.span);
|
||||
self.validate_fn(body, ret, output, breakable);
|
||||
self.validate_fn(body, origin, ret, output, false, breakable);
|
||||
}
|
||||
IRUInstruction::Loop { body } => {
|
||||
self.validate_fn(body, ret, output, true);
|
||||
self.validate_fn(body, origin, ret, output, false, true);
|
||||
}
|
||||
IRUInstruction::Break => {
|
||||
if !breakable {
|
||||
@@ -136,5 +149,14 @@ impl IRUProgram {
|
||||
}
|
||||
}
|
||||
}
|
||||
if needs_ret && no_ret && *ret != Type::Unit {
|
||||
output.err(CompilerMsg {
|
||||
msg: format!(
|
||||
"Function implicitly returns () at the end, must return {}",
|
||||
self.type_name(ret)
|
||||
),
|
||||
spans: vec![origin],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user