From cb9a366f43ad7e13af80d07a0f22769ef15f5ffa Mon Sep 17 00:00:00 2001 From: shadow cat Date: Mon, 7 Apr 2025 19:42:40 -0400 Subject: [PATCH] asm output, random fixes --- data/test.lang | 116 +++++++++++++++++--------- data/test2.lang | 13 +++ src/compiler/arch/riscv/asm.rs | 23 +++-- src/compiler/arch/riscv/compile.rs | 18 +++- src/compiler/arch/riscv/instr/base.rs | 4 +- src/ir/asm.rs | 3 + src/ir/lower/func.rs | 4 +- src/ir/lower/program.rs | 16 +++- src/ir/upper/def.rs | 6 +- src/ir/upper/func.rs | 19 ++++- src/ir/upper/program.rs | 9 +- src/ir/upper/validate.rs | 32 +++++-- src/parser/v3/lower/asm.rs | 65 +++++++++++---- src/parser/v3/lower/def.rs | 8 +- src/parser/v3/lower/expr.rs | 13 ++- src/parser/v3/lower/func.rs | 4 +- src/parser/v3/lower/struc.rs | 2 +- src/parser/v3/nodes/asm_block.rs | 28 ++++--- 18 files changed, 266 insertions(+), 117 deletions(-) create mode 100644 data/test2.lang diff --git a/data/test.lang b/data/test.lang index 4d7d83f..fb0ce53 100644 --- a/data/test.lang +++ b/data/test.lang @@ -1,10 +1,12 @@ struct Test { - a: 64, - b: 64, + a: 64, + b: 64, } fn start() { println("Helld!"); + print_hex(rem(10, 7)); + println(""); println("Hello World!!!!!"); thinger(); let x = 3; @@ -14,7 +16,7 @@ fn start() { println("before:"); x = 0; loop { - if not(lt(x, 5)) { + if not(lt(x, 10)) { break; }; println("RAAAAA"); @@ -28,7 +30,11 @@ fn start() { }; arger("a", "b", "c"); let z = sub(test.a, 10); - exit(add(mul(sub(add(5, test.b), 1), 3), z)); + // exit(add(mul(sub(add(5, test.b), 1), 3), z)); + print("test: 0x"); + print_hex(31); + println(""); + exit(0); } fn structer(test: Test) { @@ -48,7 +54,7 @@ fn println(msg: slice<8>) { } fn print(msg: slice<8>) { - asm (a1 = msg) { + asm (a1 = &msg) { ld a2, 8, a1 ld a1, 0, a1 li a0, 1 @@ -57,58 +63,89 @@ fn print(msg: slice<8>) { } } +fn print_hex(x: 64) { + let i = 32; + loop { + i = sub(i, 4); + let c = and(shr(x, i), 15); + if gt(c, 9) { + c = add(c, 7); + }; + c = add(c, 48); + asm (a1 = &c) { + li a2, 1 + li a0, 1 + li a7, 64 + ecall + }; + if lt(i, 1) { + break; + }; + } +} + fn add(a: 64, b: 64) -> 64 { - let c: 64 = 0; - asm (t0 = a, t1 = b, a0 = c) { - ld t0, 0, t0 - ld t1, 0, t1 + asm (t0 = a, t1 = b, out = t0) { add t0, t0, t1 - sd t0, 0, a0 - }; - c + } } fn mul(a: 64, b: 64) -> 64 { - let c: 64 = 0; - asm (t0 = a, t1 = b, a0 = c) { - ld t0, 0, t0 - ld t1, 0, t1 + asm (t0 = a, t1 = b, out = t0) { mul t0, t0, t1 - sd t0, 0, a0 - }; - c + } +} + +fn div(a: 64, b: 64) -> 64 { + asm (t0 = a, t1 = b, out = t0) { + div t0, t0, t1 + } } fn sub(a: 64, b: 64) -> 64 { - let c: 64 = 0; - asm (t0 = a, t1 = b, a0 = c) { - ld t0, 0, t0 - ld t1, 0, t1 + asm (t0 = a, t1 = b, out = t0) { sub t0, t0, t1 - sd t0, 0, a0 - }; - c + } +} + +fn rem(a: 64, b: 64) -> 64 { + asm (t0 = a, t1 = b, out = t0) { + rem t0, t0, t1 + } +} + +fn shr(a: 64, b: 64) -> 64 { + asm (t0 = a, t1 = b, out = t0) { + srl t0, t0, t1 + } +} + +fn shl(a: 64, b: 64) -> 64 { + asm (t0 = a, t1 = b, out = t0) { + sll t0, t0, t1 + } } fn lt(a: 64, b: 64) -> 64 { - let c: 64 = 0; - asm (t0 = a, t1 = b, a0 = c) { - ld t0, 0, t0 - ld t1, 0, t1 + asm (t0 = a, t1 = b, out = t0) { slt t0, t0, t1 - sd t0, 0, a0 - }; - c + } +} + +fn gt(a: 64, b: 64) -> 64 { + lt(b, a) +} + +fn and(a: 64, b: 64) -> 64 { + asm (t0 = a, t1 = b, out = t0) { + and t0, t0, t1 + } } fn not(a: 64) -> 64 { - let c: 64 = 0; - asm (t0 = a, a0 = c) { - ld t0, 0, t0 + asm (t0 = a, out = t0) { xori t0, t0, 1 - sd t0, 0, a0 - }; - c + } } fn arger(a: slice<8>, b: slice<8>, c: slice<8>) { @@ -119,7 +156,6 @@ fn arger(a: slice<8>, b: slice<8>, c: slice<8>) { fn exit(status: 64) { asm (a0 = status) { - ld a0, 0, a0 li a7, 93 ecall }; diff --git a/data/test2.lang b/data/test2.lang new file mode 100644 index 0000000..7a68ec1 --- /dev/null +++ b/data/test2.lang @@ -0,0 +1,13 @@ +fn start() { + let x = asm(out = t0) { + li t0, 40 + }; + exit(x); +} + +fn exit(status: 64) { + asm (a0 = status) { + li a7, 93 + ecall + }; +} diff --git a/src/compiler/arch/riscv/asm.rs b/src/compiler/arch/riscv/asm.rs index fc53274..9194fc3 100644 --- a/src/compiler/arch/riscv/asm.rs +++ b/src/compiler/arch/riscv/asm.rs @@ -1,7 +1,7 @@ use crate::{ compiler::program::{Addr, Instr, SymTable}, ir::Symbol, - util::LabeledFmt, + util::{Bits32, LabeledFmt}, }; use super::*; @@ -70,7 +70,11 @@ pub enum LinkerInstruction { } pub fn addi(dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> RawInstruction { - opi(op32i::ADD, dest, src, imm) + opi(op32i::ADD, dest, src, imm.to_u()) +} + +pub fn ori(dest: Reg, src: Reg, imm: Bits32<11, 0>) -> RawInstruction { + opi(op32i::OR, dest, src, imm) } impl Instr for LinkerInstruction { @@ -89,7 +93,7 @@ impl Instr for LinkerInstruction { src1, src2, } => opr(*op, *funct, *dest, *src1, *src2), - Self::OpImm { op, dest, src, imm } => opi(*op, *dest, *src, BitsI32::new(*imm)), + Self::OpImm { op, dest, src, imm } => opi(*op, *dest, *src, BitsI32::new(*imm).to_u()), Self::OpImmF7 { op, funct, @@ -113,8 +117,17 @@ impl Instr for LinkerInstruction { Self::La { dest, src } => { if let Some(addr) = sym_map.get(*src) { let offset = addr.val() as i32 - pos.val() as i32; - data.extend(auipc(*dest, BitsI32::new(0)).to_le_bytes()); - addi(*dest, *dest, BitsI32::new(offset)) + let sign = offset.signum(); + let mut lower = offset % 0x1000; + let mut upper = offset - lower; + if (((lower >> 11) & 1) == 1) ^ (sign == -1) { + let add = sign << 12; + upper += add; + lower = offset - upper; + } + assert!(upper + (lower << 20 >> 20) == offset); + data.extend(auipc(*dest, BitsI32::new(upper)).to_le_bytes()); + addi(*dest, *dest, BitsI32::new(lower)) } else { data.extend_from_slice(&[0; 2 * 4]); return Some(*src); diff --git a/src/compiler/arch/riscv/compile.rs b/src/compiler/arch/riscv/compile.rs index 978c296..33318ff 100644 --- a/src/compiler/arch/riscv/compile.rs +++ b/src/compiler/arch/riscv/compile.rs @@ -106,7 +106,10 @@ pub fn compile(program: &IRLProgram) -> UnlinkedProgram
  • { s, ); } - IRI::Ref { dest, src } => todo!(), + IRI::Ref { dest, src } => { + v.push(LI::addi(t0, sp, stack[src])); + v.push(LI::sd(t0, stack[dest], sp)); + } IRI::LoadAddr { dest, offset, src } => { v.extend([ LI::La { @@ -142,9 +145,13 @@ pub fn compile(program: &IRLProgram) -> UnlinkedProgram
  • { } v.push(LI::Call(*f)); } - IRI::AsmBlock { args, instructions } => { - for (reg, var) in args { - v.push(LI::addi(*reg, sp, stack[var])); + IRI::AsmBlock { + inputs, + outputs, + instructions, + } => { + for (reg, var) in inputs { + v.push(LI::ld(*reg, stack[var], sp)); } fn r(rr: RegRef) -> Reg { match rr { @@ -223,6 +230,9 @@ pub fn compile(program: &IRLProgram) -> UnlinkedProgram
  • { AI::Branch { .. } => todo!(), } } + for (reg, var) in outputs { + v.push(LI::sd(*reg, stack[var], sp)); + } } IRI::Ret { src } => { let Some(rva) = stack_rva else { diff --git a/src/compiler/arch/riscv/instr/base.rs b/src/compiler/arch/riscv/instr/base.rs index 9f22ecb..c061d29 100644 --- a/src/compiler/arch/riscv/instr/base.rs +++ b/src/compiler/arch/riscv/instr/base.rs @@ -80,8 +80,8 @@ pub const fn j_type(imm: Bits32<20, 1>, rd: Reg, opcode: u32) -> I { pub fn opr(op: Funct3, funct: Funct7, dest: Reg, src1: Reg, src2: Reg) -> I { r_type(funct, src2, src1, op, dest, OP) } -pub fn opi(op: Funct3, dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> RawInstruction { - i_type(imm.to_u(), src, op, dest, IMM_OP) +pub fn opi(op: Funct3, dest: Reg, src: Reg, imm: Bits32<11, 0>) -> RawInstruction { + i_type(imm, src, op, dest, IMM_OP) } pub fn opif7(op: Funct3, funct: Funct7, dest: Reg, src: Reg, imm: BitsI32<4, 0>) -> I { i_type( diff --git a/src/ir/asm.rs b/src/ir/asm.rs index 08eb182..3c104fc 100644 --- a/src/ir/asm.rs +++ b/src/ir/asm.rs @@ -1,3 +1,5 @@ +use crate::compiler::arch::riscv::Reg; + use super::VarID; #[derive(Clone)] @@ -11,3 +13,4 @@ pub enum RegRef { Var(VarID), Reg(String), } + diff --git a/src/ir/lower/func.rs b/src/ir/lower/func.rs index 7b00e8c..a1d58fa 100644 --- a/src/ir/lower/func.rs +++ b/src/ir/lower/func.rs @@ -42,7 +42,8 @@ pub enum IRLInstruction { }, AsmBlock { instructions: Vec, - args: Vec<(Reg, VarID)>, + inputs: Vec<(Reg, VarID)>, + outputs: Vec<(Reg, VarID)>, }, Ret { src: VarID, @@ -56,3 +57,4 @@ pub enum IRLInstruction { }, Mark(Symbol), } + diff --git a/src/ir/lower/program.rs b/src/ir/lower/program.rs index b9650d3..611e76d 100644 --- a/src/ir/lower/program.rs +++ b/src/ir/lower/program.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::ir::{IRUFunction, IRUInstrInst, Size, SymbolSpace}; +use crate::ir::{AsmBlockArgType, IRUFunction, IRUInstrInst, Size, SymbolSpace}; use super::{ IRLFunction, IRLInstruction, IRUInstruction, IRUProgram, Len, Symbol, SymbolSpaceBuilder, Type, @@ -161,9 +161,21 @@ impl<'a> IRLFunctionBuilder<'a> { }); } IRUInstruction::AsmBlock { instructions, args } => { + let mut inputs = Vec::new(); + let mut outputs = Vec::new(); + for a in args { + match a.ty { + AsmBlockArgType::In => inputs.push((a.reg, a.var.id)), + AsmBlockArgType::Out => { + self.alloc_stack(a.var.id)?; + outputs.push((a.reg, a.var.id)); + } + } + } self.instrs.push(IRLInstruction::AsmBlock { instructions: instructions.clone(), - args: args.iter().cloned().map(|(r, v)| (r, v.id)).collect(), + inputs, + outputs, }) } IRUInstruction::Ret { src } => self.instrs.push(IRLInstruction::Ret { src: src.id }), diff --git a/src/ir/upper/def.rs b/src/ir/upper/def.rs index 646990e..9f450bc 100644 --- a/src/ir/upper/def.rs +++ b/src/ir/upper/def.rs @@ -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 { diff --git a/src/ir/upper/func.rs b/src/ir/upper/func.rs index e44ef1f..4c99827 100644 --- a/src/ir/upper/func.rs +++ b/src/ir/upper/func.rs @@ -45,7 +45,7 @@ pub enum IRUInstruction { }, AsmBlock { instructions: Vec, - args: Vec<(Reg, VarInst)>, + args: Vec, }, 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}")?, diff --git a/src/ir/upper/program.rs b/src/ir/upper/program.rs index ab4c0e2..8bff225 100644 --- a/src/ir/upper/program.rs +++ b/src/ir/upper/program.rs @@ -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 { 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; diff --git a/src/ir/upper/validate.rs b/src/ir/upper/validate.rs index 70bc0ed..72afa8a 100644 --- a/src/ir/upper/validate.rs +++ b/src/ir/upper/validate.rs @@ -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], + }); + } } } diff --git a/src/parser/v3/lower/asm.rs b/src/parser/v3/lower/asm.rs index 232bbb6..239fb09 100644 --- a/src/parser/v3/lower/asm.rs +++ b/src/parser/v3/lower/asm.rs @@ -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; 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 { + 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 { - 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)?, + }, + }) } } diff --git a/src/parser/v3/lower/def.rs b/src/parser/v3/lower/def.rs index 91022d9..e3adc53 100644 --- a/src/parser/v3/lower/def.rs +++ b/src/parser/v3/lower/def.rs @@ -3,11 +3,7 @@ use crate::ir::{IRUProgram, Origin, Type, VarDef}; use super::{CompilerMsg, CompilerOutput, FileSpan, Node, PType, PVarDef}; impl Node { - pub fn lower( - &self, - program: &mut IRUProgram, - output: &mut CompilerOutput, - ) -> Option { + pub fn lower(&self, program: &mut IRUProgram, output: &mut CompilerOutput) -> Option { let s = self.as_ref()?; let name = s.name.as_ref()?.to_string(); let ty = match &s.ty { @@ -17,7 +13,7 @@ impl Node { Some(VarDef { name, ty, - origin: Origin::File(self.span), + origin: self.span, }) } } diff --git a/src/parser/v3/lower/expr.rs b/src/parser/v3/lower/expr.rs index 07d79c8..a92ce20 100644 --- a/src/parser/v3/lower/expr.rs +++ b/src/parser/v3/lower/expr.rs @@ -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::().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(); diff --git a/src/parser/v3/lower/func.rs b/src/parser/v3/lower/func.rs index 83efbd8..778a09e 100644 --- a/src/parser/v3/lower/func.rs +++ b/src/parser/v3/lower/func.rs @@ -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, })) diff --git a/src/parser/v3/lower/struc.rs b/src/parser/v3/lower/struc.rs index ab6edb0..720de40 100644 --- a/src/parser/v3/lower/struc.rs +++ b/src/parser/v3/lower/struc.rs @@ -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, }); diff --git a/src/parser/v3/nodes/asm_block.rs b/src/parser/v3/nodes/asm_block.rs index f438508..8bbf9c9 100644 --- a/src/parser/v3/nodes/asm_block.rs +++ b/src/parser/v3/nodes/asm_block.rs @@ -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>, - pub args: Vec>, + pub args: Vec>, } -pub struct PAsmBlockArg { - pub reg: Node, - pub var: Node, +pub enum PAsmBlockArg { + In { reg: R, var: V }, + Out { reg: R }, } +pub type PUAsmBlockArg = PAsmBlockArg, Node>; + impl Parsable for PAsmBlock { fn parse(ctx: &mut ParserCtx) -> ParseResult { 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 { - let reg = ctx.parse()?; - ctx.expect_sym(Symbol::Equals)?; - let var = ctx.parse()?; - ParseResult::Ok(Self { reg, var }) + let reg = ctx.parse::()?; + 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 } + }) } }