Skip to content

Commit

Permalink
reticulating codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
rcgoodfellow committed Sep 14, 2024
1 parent b793d5f commit b8c9f44
Show file tree
Hide file tree
Showing 15 changed files with 665 additions and 97 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"p4",
"x4c",
"x4c_error_codes",
"codegen/common",
"codegen/rust",
"codegen/htq",
"lang/p4rs",
Expand Down
8 changes: 8 additions & 0 deletions codegen/common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "p4-cg"
version = "0.1.0"
edition = "2021"

[dependencies]
p4 = { path = "../../p4" }
thiserror = "1.0.63"
1 change: 1 addition & 0 deletions codegen/common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Copyright 2024 Oxide Computer Company
108 changes: 108 additions & 0 deletions codegen/htq/src/control.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright 2024 Oxide Computer Company

use htq::ast::Parameter;
use p4::hlir::Hlir;

use crate::{
error::CodegenError, p4_type_to_htq_type, statement::emit_statement,
RegisterAllocator,
};

pub(crate) fn emit_control_functions(
ast: &p4::ast::AST,
hlir: &Hlir,
) -> Result<Vec<htq::ast::Function>, CodegenError> {
let mut result = Vec::default();

for control in &ast.controls {
let cf = emit_control(ast, hlir, control)?;
result.extend(cf.into_iter());
}

Ok(result)
}

fn emit_control(
ast: &p4::ast::AST,
hlir: &Hlir,
control: &p4::ast::Control,
) -> Result<Vec<htq::ast::Function>, CodegenError> {
let mut result = Vec::default();

let mut parameters = Vec::new();
for x in &control.parameters {
let p = htq::ast::Parameter {
reg: htq::ast::Register::new(x.name.as_str()),
pointer: true,
typ: p4_type_to_htq_type(&x.ty)?,
};
parameters.push(p);
}

result.push(emit_control_apply(ast, hlir, control, &parameters)?);

for action in &control.actions {
result.push(emit_control_action(
ast,
hlir,
control,
action,
&parameters,
)?);
}
Ok(result)
}

fn emit_control_apply(
ast: &p4::ast::AST,
hlir: &Hlir,
control: &p4::ast::Control,
parameters: &[Parameter],
) -> Result<htq::ast::Function, CodegenError> {
let mut ra = RegisterAllocator::default();
let mut names = control.names();
let mut statements = Vec::default();
for s in &control.apply.statements {
statements.extend(
emit_statement(s, ast, hlir, &mut names, &mut ra)?.into_iter(),
)
}
let f = htq::ast::Function {
name: format!("{}_apply", control.name),
parameters: parameters.to_owned(),
statements,
};
Ok(f)
}

fn emit_control_action(
ast: &p4::ast::AST,
hlir: &Hlir,
control: &p4::ast::Control,
action: &p4::ast::Action,
parameters: &[Parameter],
) -> Result<htq::ast::Function, CodegenError> {
let mut ra = RegisterAllocator::default();
let mut names = control.names();
let mut statements = Vec::default();
let mut parameters = parameters.to_owned();
for x in &action.parameters {
let p = htq::ast::Parameter {
reg: htq::ast::Register::new(x.name.as_str()),
pointer: true,
typ: p4_type_to_htq_type(&x.ty)?,
};
parameters.push(p);
}
for s in &action.statement_block.statements {
statements.extend(
emit_statement(s, ast, hlir, &mut names, &mut ra)?.into_iter(),
)
}
let f = htq::ast::Function {
name: format!("{}_{}", control.name, action.name),
parameters,
statements,
};
Ok(f)
}
49 changes: 47 additions & 2 deletions codegen/htq/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,63 @@
// Copyright 2024 Oxide Computer Company

use p4::{
ast::{DeclarationInfo, Expression, Lvalue},
lexer::Token,
};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum CodegenError {
#[error("There is no equivalent htq type for {0}")]
NoEquivalentType(p4::ast::Type),

#[error("undefined lvalue \n{0:#?}")]
UndefinedLvalue(Lvalue),

#[error("cannot assign to \n{0:#?}")]
InvalidAssignment(DeclarationInfo),

#[error("cannot convert numeric type \n{0:#?}\n to u128")]
NumericConversion(Expression),

#[error(
"no type information for \n{0:#?}\nthis is likely a type checking bug"
)]
UntypedExpression(Expression),

#[error(
"parent {0} for member for \n{1:#?}\nnot found: this is likely a front end bug"
)]
MemberParentNotFound(String, Lvalue),

#[error(
"expected parent of lvalue \n{0:#?}\nto be a struct: this is likely a front end bug"
)]
ExpectedStructParent(Lvalue),

#[error(
"expected parent of lvalue \n{0:#?}\nto be a header: this is likely a front end bug"
)]
ExpectedHeaderParent(Lvalue),

#[error("offset for struct or header member \n{0:#?}\nnot found")]
MemberOffsetNotFound(Lvalue),

#[error("header member {0}\n{1:#?}\nnot found")]
MemberNotFound(String, Lvalue),

#[error("user defined type {0} not found \n{1:#?}")]
UserDefinedTypeNotFound(String, Token),

#[error("cannot calculate offset into extern {0} \n{1:#?}")]
CannotOffsetExtern(String, Token),
}

#[derive(Error, Debug)]
pub enum EmitError {
#[error("io error {0}")]
#[error("io error: {0}")]
Io(#[from] std::io::Error),

#[error("codegen error {0}")]
#[error("codegen error: {0}")]
Codegen(#[from] CodegenError),
}
98 changes: 93 additions & 5 deletions codegen/htq/src/expression.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,96 @@
use htq::ast::{Register, Rset, Statement, Type, Value};
use p4::ast::{Expression, ExpressionKind};

// Copyright 2024 Oxide Computer Company
use crate::error::CodegenError;
use crate::{error::CodegenError, 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,
) -> Result<(Vec<Statement>, Register, Type), CodegenError> {
let r = VersionedRegister::for_expression(expr);
match &expr.kind {
ExpressionKind::BoolLit(value) => emit_bool_lit(*value, r),
ExpressionKind::BitLit(width, value) => {
emit_bit_lit(*width, *value, r, expr)
}
ExpressionKind::IntegerLit(value) => emit_int_lit(*value, r),
ExpressionKind::SignedLit(width, value) => {
emit_signed_lit(*width, *value, r)
}
ExpressionKind::Call(_) => {
//TODO
Ok((
Vec::default(),
Register::new("badreg"),
Type::User("badtype".to_owned()),
))
}
ExpressionKind::Lvalue(_) => {
//TODO
Ok((
Vec::default(),
Register::new("badreg"),
Type::User("badtype".to_owned()),
))
}
xpr => todo!("expression: {xpr:?}"),
}
}

pub(crate) fn emit_bool_lit(
value: bool,
ra: VersionedRegister,
) -> Result<(Vec<Statement>, Register, Type), CodegenError> {
let instrs = vec![Statement::Rset(Rset {
target: ra.clone().to_reg(),
typ: Type::Bool,
source: Value::bool(value),
})];
Ok((instrs, ra.to_reg(), Type::Bool))
}

pub(crate) fn emit_bit_lit(
width: u16,
value: u128,
ra: VersionedRegister,
expr: &Expression,
) -> Result<(Vec<Statement>, Register, Type), CodegenError> {
let value = i128::try_from(value)
.map_err(|_| CodegenError::NumericConversion(expr.clone()))?;
let typ = Type::Bitfield(usize::from(width));
let instrs = vec![Statement::Rset(Rset {
typ: typ.clone(),
target: ra.clone().to_reg(),
source: Value::number(value),
})];
Ok((instrs, ra.to_reg(), typ))
}

pub(crate) fn emit_int_lit(
value: i128,
ra: VersionedRegister,
) -> Result<(Vec<Statement>, Register, Type), CodegenError> {
let typ = Type::Signed(128);
let instrs = vec![Statement::Rset(Rset {
typ: typ.clone(),
target: ra.clone().to_reg(),
source: Value::number(value),
})];
Ok((instrs, ra.to_reg(), typ))
}

pub(crate) fn _emit_expression(
_stmt: &p4::ast::Expression,
) -> Result<Vec<htq::ast::Statement>, CodegenError> {
todo!()
pub(crate) fn emit_signed_lit(
width: u16,
value: i128,
ra: VersionedRegister,
) -> Result<(Vec<Statement>, Register, Type), CodegenError> {
let typ = Type::Signed(usize::from(width));
let instrs = vec![Statement::Rset(Rset {
typ: typ.clone(),
target: ra.clone().to_reg(),
source: Value::number(value),
})];
Ok((instrs, ra.to_reg(), typ))
}
Loading

0 comments on commit b8c9f44

Please sign in to comment.