Skip to content

Commit

Permalink
reticulating codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
rcgoodfellow committed Sep 15, 2024
1 parent b8c9f44 commit 85a1bc2
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 25 deletions.
8 changes: 8 additions & 0 deletions codegen/htq/src/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -94,6 +99,9 @@ fn emit_control_action(
};
parameters.push(p);
}
for p in &parameters {
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(),
Expand Down
93 changes: 81 additions & 12 deletions codegen/htq/src/expression.rs
Original file line number Diff line number Diff line change
@@ -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<String, NameInfo>,
) -> Result<(Vec<Statement>, 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) => {
Expand All @@ -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((
Expand All @@ -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<String, NameInfo>,
) -> Result<(Vec<Statement>, Register, Type), CodegenError> {
let mut result: Vec<Statement> = 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,
Expand Down
21 changes: 14 additions & 7 deletions codegen/htq/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -136,6 +136,12 @@ impl RegisterAllocator {
}
}
}

pub(crate) fn get(&self, name: &str) -> Option<htq::ast::Register> {
self.data
.get(name)
.map(|rev| htq::ast::Register::new(&format!("{}.{}", name, rev)))
}
}

#[derive(Debug, Clone)]
Expand All @@ -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,
}
}
Expand All @@ -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))
}
}
}
12 changes: 6 additions & 6 deletions codegen/htq/src/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -143,7 +143,7 @@ fn emit_assignment(
Ok(instrs)
}

fn member_offsets(
pub(crate) fn member_offsets(
ast: &p4::ast::AST,
names: &HashMap<String, NameInfo>,
lval: &Lvalue,
Expand Down

0 comments on commit 85a1bc2

Please sign in to comment.