Skip to content

Commit

Permalink
Add parser tests and refine some things here and there
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>
  • Loading branch information
asl committed Feb 26, 2025
1 parent fc88aed commit 8b824eb
Show file tree
Hide file tree
Showing 7 changed files with 481 additions and 96 deletions.
9 changes: 5 additions & 4 deletions include/p4mlir/Dialect/P4HIR/P4HIR_ParserOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ def ParserOp : P4HIR_Op<"parser",
[Symbol, SymbolTable, IsolatedFromAbove,
FunctionOpInterface, AutomaticAllocationScope]> {
let arguments = (ins SymbolNameAttr:$sym_name,
TypeAttrOf<FuncType>:$applyType,
TypeAttrOf<FuncType>:$constructorType);
TypeAttrOf<FuncType>:$applyType);
let regions = (region SizedRegion<1>:$body);
let hasCustomAssemblyFormat = 1;

Expand All @@ -26,6 +25,8 @@ def ParserOp : P4HIR_Op<"parser",
llvm::ArrayRef<mlir::Type> getResultTypes() {
return {};
}

void createEntryBlock();
}];
}

Expand Down Expand Up @@ -187,7 +188,7 @@ def RangeOp : P4HIR_Op<"range", [Pure,
let arguments = (ins AnyIntP4Type:$lhs, AnyIntP4Type:$rhs);

let assemblyFormat = [{
`(` $lhs `,` $rhs `)` `:` type($result) attr-dict
`(` $lhs `,` $rhs `)` `:` qualified(type($result)) attr-dict
}];

let builders = [
Expand Down Expand Up @@ -228,7 +229,7 @@ def MaskOp : P4HIR_Op<"mask", [Pure,
let arguments = (ins AnyIntP4Type:$lhs, AnyIntP4Type:$rhs);

let assemblyFormat = [{
`(` $lhs `,` $rhs `)` `:` type($result) attr-dict
`(` $lhs `,` $rhs `)` `:` qualified(type($result)) attr-dict
}];

let builders = [
Expand Down
63 changes: 58 additions & 5 deletions lib/Dialect/P4HIR/P4HIR_Ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1001,29 +1001,82 @@ void P4HIR::TupleExtractOp::build(OpBuilder &builder, OperationState &odsState,
// ParserOp
//===----------------------------------------------------------------------===//

void P4HIR::ParserOp::createEntryBlock() {
assert(empty() && "can only create entry block for empty parser");
Block &first = getFunctionBody().emplaceBlock();
auto loc = getFunctionBody().getLoc();
for (auto argType : getFunctionType().getInputs()) first.addArgument(argType, loc);
}

void P4HIR::ParserOp::print(mlir::OpAsmPrinter &printer) {
// This is essentially function_interface_impl::printFunctionOp, but we
// always print body and we do not have result / argument attributes (for now)

auto funcName = getSymNameAttr().getValue();

printer << ' ';
printer.printSymbolName(funcName);

function_interface_impl::printFunctionSignature(printer, *this, getApplyType().getInputs(),
false, {});
function_interface_impl::printFunctionSignature(printer, *this,
getConstructorType().getInputs(), false, {});

function_interface_impl::printFunctionAttributes(
printer, *this,
// These are all omitted since they are custom printed already.
{getApplyTypeAttrName(), getConstructorTypeAttrName()});
{getApplyTypeAttrName()});

printer << ' ';
printer.printRegion(getRegion(), /*printEntryBlockArgs=*/false, /*printBlockTerminators=*/true);
}

mlir::ParseResult P4HIR::ParserOp::parse(mlir::OpAsmParser &parser, mlir::OperationState &result) {
// TODO
return mlir::failure();
// This is essentially function_interface_impl::parseFunctionOp, but we do not have
// result / argument attributes (for now)
llvm::SMLoc loc = parser.getCurrentLocation();
auto &builder = parser.getBuilder();

// Parse the name as a symbol.
StringAttr nameAttr;
if (parser.parseSymbolName(nameAttr, ::SymbolTable::getSymbolAttrName(), result.attributes))
return mlir::failure();

// We default to private visibility
result.addAttribute(::SymbolTable::getVisibilityAttrName(), builder.getStringAttr("private"));

llvm::SmallVector<OpAsmParser::Argument, 8> arguments;
llvm::SmallVector<DictionaryAttr, 1> resultAttrs;
llvm::SmallVector<Type, 8> argTypes;
llvm::SmallVector<Type, 0> resultTypes;
bool isVariadic = false;
if (function_interface_impl::parseFunctionSignature(parser, /*allowVariadic=*/false, arguments,
isVariadic, resultTypes, resultAttrs))
return mlir::failure();

// Parsers have no results
if (!resultTypes.empty())
return parser.emitError(loc, "parsers should not produce any results");

// Build the function type.
for (auto &arg : arguments) argTypes.push_back(arg.type);

if (auto fnType = P4HIR::FuncType::get(builder.getContext(), argTypes)) {
result.addAttribute(getApplyTypeAttrName(result.name), TypeAttr::get(fnType));
} else
return mlir::failure();

// If additional attributes are present, parse them.
if (parser.parseOptionalAttrDictWithKeyword(result.attributes)) return failure();

// TODO: Support argument attributes

// Parse the parser body.
auto *body = result.addRegion();
if (parser.parseRegion(*body, arguments, /*enableNameShadowing=*/false)) return mlir::failure();

// Make sure its not empty.
if (body->empty()) return parser.emitError(loc, "expected non-empty parser body");

return mlir::success();
}

static mlir::ModuleOp getParentModule(Operation *from) {
Expand Down
70 changes: 70 additions & 0 deletions test/Dialect/P4HIR/parser.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// RUN: p4mlir-opt %s | FileCheck %s

!b10i = !p4hir.bit<10>
#false = #p4hir.bool<false> : !p4hir.bool
#true = #p4hir.bool<true> : !p4hir.bool
#int0_b10i = #p4hir.int<0> : !b10i
#int10_b10i = #p4hir.int<10> : !b10i
#int1_b10i = #p4hir.int<1> : !b10i
#int20_b10i = #p4hir.int<20> : !b10i
// CHECK: module
module {
p4hir.parser @p2(%arg0: !b10i, %arg1: !p4hir.ref<!p4hir.bool>) {
p4hir.state @start {
%true = p4hir.const #true
%tuple = p4hir.tuple (%arg0, %true) : tuple<!b10i, !p4hir.bool>
p4hir.transition_select %tuple : tuple<!b10i, !p4hir.bool> {
p4hir.select_case {
%c1_b10i = p4hir.const #int1_b10i
%set = p4hir.set (%c1_b10i) : !p4hir.set<!b10i>
%false = p4hir.const #false
%set_0 = p4hir.set (%false) : !p4hir.set<!p4hir.bool>
%setproduct = p4hir.set_product (%set, %set_0) : !p4hir.set<tuple<!b10i, !p4hir.bool>>
p4hir.yield %setproduct : !p4hir.set<tuple<!b10i, !p4hir.bool>>
} to @p2::@drop
p4hir.select_case {
%c10_b10i = p4hir.const #int10_b10i
%c20_b10i = p4hir.const #int20_b10i
%range = p4hir.range(%c10_b10i, %c20_b10i) : !p4hir.set<!b10i>
%true_0 = p4hir.const #true
%set = p4hir.set (%true_0) : !p4hir.set<!p4hir.bool>
%setproduct = p4hir.set_product (%range, %set) : !p4hir.set<tuple<!b10i, !p4hir.bool>>
p4hir.yield %setproduct : !p4hir.set<tuple<!b10i, !p4hir.bool>>
} to @p2::@next
p4hir.select_case {
%c0_b10i = p4hir.const #int0_b10i
%c0_b10i_0 = p4hir.const #int0_b10i
%mask = p4hir.mask(%c0_b10i, %c0_b10i_0) : !p4hir.set<!b10i>
%everything = p4hir.universal_set : !p4hir.set<!p4hir.dontcare>
%setproduct = p4hir.set_product (%mask, %everything) : !p4hir.set<tuple<!b10i, !p4hir.dontcare>>
p4hir.yield %setproduct : !p4hir.set<tuple<!b10i, !p4hir.dontcare>>
} to @p2::@next
p4hir.select_case {
%everything = p4hir.universal_set : !p4hir.set<!p4hir.dontcare>
%everything_0 = p4hir.universal_set : !p4hir.set<!p4hir.dontcare>
%setproduct = p4hir.set_product (%everything, %everything_0) : !p4hir.set<tuple<!p4hir.dontcare, !p4hir.dontcare>>
p4hir.yield %setproduct : !p4hir.set<tuple<!p4hir.dontcare, !p4hir.dontcare>>
} to @p2::@reject
p4hir.select_case {
%everything = p4hir.universal_set : !p4hir.set<!p4hir.dontcare>
p4hir.yield %everything : !p4hir.set<!p4hir.dontcare>
} to @p2::@reject
}
}
p4hir.state @drop {
p4hir.transition to @p2::@reject
}
p4hir.state @next {
%true = p4hir.const #true
p4hir.assign %true, %arg1 : <!p4hir.bool>
p4hir.transition to @p2::@accept
}
p4hir.state @accept {
p4hir.parser_accept
}
p4hir.state @reject {
p4hir.parser_reject
}
p4hir.transition to @p2::@start
}
}
33 changes: 33 additions & 0 deletions test/Translate/Parser/parse.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// RUN: p4mlir-translate --typeinference-only %s | FileCheck %s


struct empty {}

parser p(in empty e, in int<10> sinit) {
int<10> s = sinit;

state start {
s = 1;
transition next;
}

state next {
s = 2;
transition accept;
}

state drop {}
}

// CHECK-LABEL: p4hir.parser @p(%arg0: !empty, %arg1: !i10i) {
// CHECK: p4hir.state @start {
// CHECK: p4hir.transition to @p::@next
// CHECK: p4hir.state @next {
// CHECK: p4hir.transition to @p::@accept
// CHECK: p4hir.state @drop {
// CHECK-NEXT: p4hir.transition to @p::@reject
// CHECK: p4hir.state @accept {
// CHECK-NEXT: p4hir.parser_accept
// CHECK: p4hir.state @reject {
// CHECK-NEXT: p4hir.parser_reject
// CHECK: p4hir.transition to @p::@start
Loading

0 comments on commit 8b824eb

Please sign in to comment.