Skip to content

Commit 577a63e

Browse files
committed
implement parser extract
1 parent 3a2e3d6 commit 577a63e

File tree

4 files changed

+159
-7
lines changed

4 files changed

+159
-7
lines changed

codegen/htq/src/error.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,21 @@ pub enum CodegenError {
117117

118118
#[error("transition must be in parser context\n{0:#?}")]
119119
TransitionOutsideParser(Transition),
120+
121+
#[error("call does not have enough arguments\n{0:#?}")]
122+
NotEnoughArgs(Lvalue),
123+
124+
#[error("expected expression got\n{0:#?}")]
125+
ExpectedLvalue(Expression),
126+
127+
#[error("header declaration not found\n{0:#?}")]
128+
HeaderDeclNotFound(Lvalue),
129+
130+
#[error("expected header type for lvalue\n{0:#?}")]
131+
ExpectedHeaderType(Lvalue),
132+
133+
#[error("header definition for type {0} not found for lvalue\n{1:#?}")]
134+
HeaderDefnNotFound(String, Lvalue),
120135
}
121136

122137
#[derive(Error, Debug)]

codegen/htq/src/expression.rs

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub(crate) fn emit_expression(
8686
}
8787
ExpressionKind::Call(call) => match context {
8888
P4Context::Control(c) => {
89-
let (stmts, blks, value) = emit_call(
89+
let (stmts, blks, value) = emit_call_in_control(
9090
call,
9191
c,
9292
hlir,
@@ -191,7 +191,44 @@ pub(crate) fn emit_binary_expr_eq(
191191
todo!()
192192
}
193193

194-
pub(crate) fn emit_call(
194+
pub(crate) fn emit_call_in_parser(
195+
call: &p4::ast::Call,
196+
parser: &p4::ast::Parser,
197+
hlir: &Hlir,
198+
ast: &p4::ast::AST,
199+
ra: &mut RegisterAllocator,
200+
afa: &mut AsyncFlagAllocator,
201+
names: &HashMap<String, NameInfo>,
202+
table_context: &mut TableContext,
203+
) -> Result<
204+
(
205+
Vec<Statement>,
206+
Vec<htq::ast::StatementBlock>,
207+
Option<ExpressionValue>,
208+
),
209+
CodegenError,
210+
> {
211+
match call.lval.leaf() {
212+
"extract" => {
213+
let (stmts, result) = emit_extract_call(
214+
call,
215+
parser,
216+
hlir,
217+
ast,
218+
ra,
219+
afa,
220+
names,
221+
table_context,
222+
)?;
223+
Ok((stmts, Vec::default(), result))
224+
}
225+
x => {
226+
todo!("unhandled parser function: {x:#?}");
227+
}
228+
}
229+
}
230+
231+
pub(crate) fn emit_call_in_control(
195232
call: &p4::ast::Call,
196233
control: &p4::ast::Control,
197234
hlir: &Hlir,
@@ -254,6 +291,88 @@ pub(crate) fn emit_call(
254291
}
255292
}
256293

294+
fn emit_extract_call(
295+
call: &p4::ast::Call,
296+
parser: &p4::ast::Parser,
297+
_hlir: &Hlir,
298+
ast: &p4::ast::AST,
299+
ra: &mut RegisterAllocator,
300+
_afa: &mut AsyncFlagAllocator,
301+
names: &HashMap<String, NameInfo>,
302+
_table_context: &mut TableContext,
303+
) -> Result<(Vec<Statement>, Option<ExpressionValue>), CodegenError> {
304+
let src = &parser.parameters[1].name;
305+
let source = ra.get(src).ok_or(CodegenError::NoRegisterForParameter(
306+
src.to_owned(),
307+
ra.clone(),
308+
))?;
309+
310+
let tgt = call
311+
.args
312+
.first()
313+
.ok_or(CodegenError::NotEnoughArgs(call.lval.clone()))?;
314+
let tgt = match &tgt.kind {
315+
ExpressionKind::Lvalue(lval) => lval,
316+
_ => return Err(CodegenError::ExpectedLvalue(tgt.as_ref().clone())),
317+
};
318+
let target = ra
319+
.get(tgt.root())
320+
.ok_or(CodegenError::RegisterDoesNotExistForLval(tgt.clone()))?;
321+
let output = ra.alloc(&tgt.root());
322+
323+
let info = names
324+
.get(tgt.root())
325+
.ok_or(CodegenError::HeaderDeclNotFound(tgt.clone()))?;
326+
327+
let typename = match &info.ty {
328+
p4::ast::Type::UserDefined(name, _) => name.clone(),
329+
_ => return Err(CodegenError::ExpectedHeaderType(tgt.clone())),
330+
};
331+
332+
let offset = if let Some(hdr) = ast.get_header(&typename) {
333+
hdr.index_of(tgt.leaf())
334+
.ok_or(CodegenError::MemberOffsetNotFound(tgt.clone()))?
335+
} else {
336+
let st = ast.get_struct(&typename).ok_or(
337+
CodegenError::HeaderDefnNotFound(typename.clone(), tgt.clone()),
338+
)?;
339+
st.index_of(tgt.leaf())
340+
.ok_or(CodegenError::MemberOffsetNotFound(tgt.clone()))?
341+
};
342+
343+
let sz = type_size(&info.ty, ast);
344+
345+
let offset_reg =
346+
ra.get("offset")
347+
.ok_or(CodegenError::NoRegisterForParameter(
348+
String::from("offset"),
349+
ra.clone(),
350+
))?;
351+
352+
let extract_stmt = htq::ast::Extract {
353+
output,
354+
target,
355+
target_offset: Value::number(offset as i128),
356+
source,
357+
source_offset: Value::reg(offset_reg.clone()), //TODO
358+
};
359+
360+
let add_offset_stmt = htq::ast::Add {
361+
target: ra.alloc(&offset_reg.0),
362+
typ: Type::Unsigned(32),
363+
source_a: Value::reg(offset_reg),
364+
source_b: Value::number(sz as i128),
365+
};
366+
367+
Ok((
368+
vec![
369+
Statement::Extract(extract_stmt),
370+
Statement::Add(add_offset_stmt),
371+
],
372+
None,
373+
))
374+
}
375+
257376
fn emit_apply_call(
258377
call: &p4::ast::Call,
259378
control: &p4::ast::Control,

codegen/htq/src/parser.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,19 @@ fn emit_parser(
5050
parameters.push(p);
5151
}
5252

53+
parameters.push(htq::ast::Parameter {
54+
reg: ra.alloc("offset"),
55+
typ: htq::ast::Type::Unsigned(32),
56+
});
57+
5358
let mut names = parser.names();
5459

5560
// TODO XXX parsers cannot have tables, this indicates broken abstractions
5661
// around code generation control flow.
5762
let mut table_context = HashMap::default();
5863

5964
for state in &parser.states {
65+
let mut ra = ra.clone();
6066
// keeps track of register revisions for locals
6167
let mut statements = Vec::default();
6268
let mut blocks = Vec::default();

codegen/htq/src/statement.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ fn emit_transition(
130130
CodegenError::NoRegisterForParameter(x.name.clone(), ra.clone()),
131131
)?));
132132
}
133+
args.push(Value::reg(ra.get("offset").ok_or(
134+
CodegenError::NoRegisterForParameter(
135+
String::from("offset"),
136+
ra.clone(),
137+
),
138+
)?));
133139

134140
let hdr = targets[0].clone();
135141

@@ -397,7 +403,7 @@ fn emit_call(
397403
CodegenError,
398404
> {
399405
let (instrs, blocks, _result) = match &context {
400-
P4Context::Control(c) => crate::expression::emit_call(
406+
P4Context::Control(c) => crate::expression::emit_call_in_control(
401407
call,
402408
c,
403409
hlir,
@@ -408,10 +414,16 @@ fn emit_call(
408414
names,
409415
table_context,
410416
)?,
411-
P4Context::Parser(_) => {
412-
//TODO
413-
(Vec::default(), Vec::default(), None)
414-
}
417+
P4Context::Parser(p) => crate::expression::emit_call_in_parser(
418+
call,
419+
p,
420+
hlir,
421+
ast,
422+
ra,
423+
afa,
424+
names,
425+
table_context,
426+
)?,
415427
};
416428
Ok((instrs, blocks))
417429
}

0 commit comments

Comments
 (0)