diff --git a/codegen/htq/src/control.rs b/codegen/htq/src/control.rs index 86a5dd3..d79c17a 100644 --- a/codegen/htq/src/control.rs +++ b/codegen/htq/src/control.rs @@ -62,6 +62,11 @@ fn emit_control_apply( let mut ra = RegisterAllocator::default(); let mut names = control.names(); let mut statements = Vec::default(); + + for p in parameters { + ra.alloc(&p.reg.0); + } + for s in &control.apply.statements { statements.extend( emit_statement(s, ast, hlir, &mut names, &mut ra)?.into_iter(), @@ -94,6 +99,9 @@ fn emit_control_action( }; parameters.push(p); } + for p in ¶meters { + ra.alloc(&p.reg.0); + } for s in &action.statement_block.statements { statements.extend( emit_statement(s, ast, hlir, &mut names, &mut ra)?.into_iter(), diff --git a/codegen/htq/src/expression.rs b/codegen/htq/src/expression.rs index a851711..1a7cde7 100644 --- a/codegen/htq/src/expression.rs +++ b/codegen/htq/src/expression.rs @@ -1,15 +1,27 @@ -use htq::ast::{Register, Rset, Statement, Type, Value}; -use p4::ast::{Expression, ExpressionKind}; +use std::collections::HashMap; + +use htq::ast::{Fget, Load, Register, Rset, Statement, Type, Value}; +use p4::{ + ast::{DeclarationInfo, Expression, ExpressionKind, Lvalue, NameInfo}, + hlir::Hlir, +}; // Copyright 2024 Oxide Computer Company -use crate::{error::CodegenError, VersionedRegister}; +use crate::{ + error::CodegenError, p4_type_to_htq_type, statement::member_offsets, + RegisterAllocator, VersionedRegister, +}; // Builds a vector of statements that implement the expression. Returns the // statements and the register the result of the expression is held in. pub(crate) fn emit_expression( expr: &Expression, + hlir: &Hlir, + ast: &p4::ast::AST, + ra: &mut RegisterAllocator, + names: &HashMap, ) -> Result<(Vec, Register, Type), CodegenError> { - let r = VersionedRegister::for_expression(expr); + let r = VersionedRegister::for_token(&expr.token); match &expr.kind { ExpressionKind::BoolLit(value) => emit_bool_lit(*value, r), ExpressionKind::BitLit(width, value) => { @@ -19,6 +31,7 @@ pub(crate) fn emit_expression( ExpressionKind::SignedLit(width, value) => { emit_signed_lit(*width, *value, r) } + ExpressionKind::Lvalue(lval) => emit_lval(lval, hlir, ast, ra, names), ExpressionKind::Call(_) => { //TODO Ok(( @@ -27,18 +40,74 @@ pub(crate) fn emit_expression( Type::User("badtype".to_owned()), )) } - ExpressionKind::Lvalue(_) => { - //TODO - Ok(( - Vec::default(), - Register::new("badreg"), - Type::User("badtype".to_owned()), - )) - } xpr => todo!("expression: {xpr:?}"), } } +fn emit_lval( + lval: &Lvalue, + hlir: &Hlir, + ast: &p4::ast::AST, + ra: &mut RegisterAllocator, + names: &HashMap, +) -> Result<(Vec, Register, Type), CodegenError> { + let mut result: Vec = Vec::default(); + + let info = hlir + .lvalue_decls + .get(lval) + .ok_or(CodegenError::UndefinedLvalue(lval.clone()))?; + + let typ = p4_type_to_htq_type(&info.ty)?; + + match &info.decl { + DeclarationInfo::Parameter(_) => { + let treg = VersionedRegister::for_token(&lval.token); + result.push(Statement::Load(Load { + target: treg.to_reg(), + typ: typ.clone(), + source: Register::new(lval.root()), + offset: Value::number(0), + })); + Ok((result, treg.to_reg(), typ)) + } + DeclarationInfo::ActionParameter(_) => { + let treg = VersionedRegister::for_token(&lval.token); + result.push(Statement::Load(Load { + target: treg.to_reg(), + typ: typ.clone(), + source: Register::new(lval.root()), + offset: Value::number(0), + })); + Ok((result, treg.to_reg(), typ)) + } + DeclarationInfo::StructMember | DeclarationInfo::HeaderMember => { + let offsets = member_offsets(ast, names, lval)?; + let treg = VersionedRegister::for_token(&lval.token); + + let src_root = lval.root(); + let source = ra + .get(src_root) + .ok_or(CodegenError::UndefinedLvalue(lval.clone()))?; + + result.push(Statement::Fget(Fget { + target: treg.to_reg(), + typ: typ.clone(), + source, + offsets, + })); + Ok((result, treg.to_reg(), typ)) + } + DeclarationInfo::Local => { + let reg = ra + .get(&lval.name) + .ok_or(CodegenError::UndefinedLvalue(lval.clone()))?; + Ok((result, reg, typ)) + } + other => todo!("emit lval for \n{other:#?}"), + } +} + pub(crate) fn emit_bool_lit( value: bool, ra: VersionedRegister, diff --git a/codegen/htq/src/lib.rs b/codegen/htq/src/lib.rs index 84ebe0e..a599df7 100644 --- a/codegen/htq/src/lib.rs +++ b/codegen/htq/src/lib.rs @@ -6,7 +6,7 @@ use control::emit_control_functions; use error::CodegenError; use header::{p4_header_to_htq_header, p4_struct_to_htq_header}; use htq::{ast::Register, emit::Emit}; -use p4::{ast::Expression, hlir::Hlir}; +use p4::{hlir::Hlir, lexer::Token}; use parser::emit_parser_functions; use table::p4_table_to_htq_table; @@ -136,6 +136,12 @@ impl RegisterAllocator { } } } + + pub(crate) fn get(&self, name: &str) -> Option { + self.data + .get(name) + .map(|rev| htq::ast::Register::new(&format!("{}.{}", name, rev))) + } } #[derive(Debug, Clone)] @@ -145,12 +151,9 @@ pub(crate) struct VersionedRegister { } impl VersionedRegister { - pub(crate) fn for_expression(expr: &Expression) -> Self { + pub(crate) fn for_token(tk: &Token) -> Self { Self { - reg: Register::new(&format!( - "tmp{}_{}", - expr.token.line, expr.token.col - )), + reg: Register::new(&format!("tmp{}_{}", tk.line, tk.col)), version: 0, } } @@ -164,6 +167,10 @@ impl VersionedRegister { } pub(crate) fn to_reg(&self) -> Register { - Register::new(&format!("{}.{}", self.reg.0, self.version)) + if self.version == 0 { + Register::new(&self.reg.0) + } else { + Register::new(&format!("{}.{}", self.reg.0, self.version)) + } } } diff --git a/codegen/htq/src/statement.rs b/codegen/htq/src/statement.rs index 97d65cd..2d60005 100644 --- a/codegen/htq/src/statement.rs +++ b/codegen/htq/src/statement.rs @@ -83,12 +83,12 @@ fn emit_assignment( // - list // - let target_info = match hlir.lvalue_decls.get(target) { - Some(info) => info, - None => return Err(CodegenError::UndefinedLvalue(target.clone())), - }; + let target_info = hlir + .lvalue_decls + .get(target) + .ok_or(CodegenError::UndefinedLvalue(target.clone()))?; - let (mut instrs, reg, typ) = emit_expression(source)?; + let (mut instrs, reg, typ) = emit_expression(source, hlir, ast, ra, names)?; match &target_info.decl { DeclarationInfo::Parameter(Direction::Out) @@ -143,7 +143,7 @@ fn emit_assignment( Ok(instrs) } -fn member_offsets( +pub(crate) fn member_offsets( ast: &p4::ast::AST, names: &HashMap, lval: &Lvalue,