diff --git a/include/p4mlir/Dialect/P4HIR/P4HIR_Ops.td b/include/p4mlir/Dialect/P4HIR/P4HIR_Ops.td index 0c04457..c88c097 100644 --- a/include/p4mlir/Dialect/P4HIR/P4HIR_Ops.td +++ b/include/p4mlir/Dialect/P4HIR/P4HIR_Ops.td @@ -1002,13 +1002,16 @@ def InstantiateOp : P4HIR_Op<"instantiate", DeclareOpInterfaceMethods]> { let summary = "constructor call operation"; let description = [{ - Instantiate P4 object: extern, parser, control or package/ + Instantiate P4 object: extern, parser, control or package. Example: ```mlir - // Direct call of function - %2 = p4hir.call @my_add(%0, %1) : (!p4hir.bit<8>, !p4hir.bit<8>) -> !p4hir.bit<8> + // Instantiate a subparser + %sp = p4hir.instantiate @subparser() as "sp" : () -> !p4hir.parser<"subparser", (!empty)> + // Instantiate a subparser with ctor parameters + %false = p4hir.const #false + %sp2 = p4hir.instantiate @subparser2(%false) as "sp2" : (!p4hir.bool) -> !p4hir.parser<"subparser2", (!empty)> ... ``` }]; @@ -1054,6 +1057,51 @@ def InstantiateOp : P4HIR_Op<"instantiate", }]; } +def ApplyOp : P4HIR_Op<"apply", + [NoRegionArguments, CallOpInterface, + //DeclareOpInterfaceMethods + TypesMatchWith< + "the apply type of the object matches the types of operands", + "callee", "arg_operands", "cast($_self).getInputs()">, + ]> { + let summary = "apply operation"; + let description = [{ + Applies P4 parser, table or control + + Example: + + ```mlir + // Application of a subparser + %sp = p4hir.instantiate @subparser() as "sp" : () -> !p4hir.parser<"subparser", ()> + p4hir.apply %sp() : !p4hir.parser<"subparser", ()> + ... + ``` + }]; + + // TODO: Refine result types, refine parameter type (must be constants!) + let results = (outs); + let arguments = (ins P4ObjectType:$callee, Variadic:$arg_operands); + + // TODO: Add verifier + let hasVerifier = 0; + + let extraClassDeclaration = [{ + /// Return the callee of this operation. + mlir::CallInterfaceCallable getCallableForCallee() { + return getCallee(); + } + + /// Set the callee for this operation. + void setCalleeFromCallable(mlir::CallInterfaceCallable callee) { + getCalleeMutable().assign(callee.get()); + } + }]; + + let assemblyFormat = [{ + $callee `(` $arg_operands `)` attr-dict `:` type($callee) + }]; +} + include "p4mlir/Dialect/P4HIR/P4HIR_ParserOps.td" diff --git a/test/Translate/Parser/subparser.p4 b/test/Translate/Parser/subparser.p4 index cff7c90..ff6e58e 100644 --- a/test/Translate/Parser/subparser.p4 +++ b/test/Translate/Parser/subparser.p4 @@ -14,23 +14,39 @@ parser subparser2(in empty e)(bool ctorArg) { } } -// CHECK-LABEL: p4hir.parser @p -// CHECK: p4hir.instantiate @subparser() as "sp" : () -> !p4hir.parser<"subparser", (!empty)> -// CHECK: %[[false:.*]] = p4hir.const #false -// CHECK: p4hir.instantiate @subparser2(%[[false]]) as "sp2" : (!p4hir.bool) -> !p4hir.parser<"subparser2", (!empty)> +parser subparser3(inout int<10> s, out bool matched)() { + state start { + transition accept; + } +} +// CHECK-LABEL: p4hir.parser @p(%arg0: !empty, %arg1: !i10i)() parser p(in empty e, in int<10> sinit) { int<10> s = sinit; subparser() sp; subparser2(false) sp2; + subparser3() sp3; +// CHECK: %[[sp:.*]] = p4hir.instantiate @subparser() as "sp" : () -> !p4hir.parser<"subparser", (!empty)> +// CHECK: %[[false:.*]] = p4hir.const #false +// CHECK: %[[sp2:.*]] = p4hir.instantiate @subparser2(%[[false]]) as "sp2" : (!p4hir.bool) -> !p4hir.parser<"subparser2", (!empty)> +// CHECK: %[[sp3:.*]] = p4hir.instantiate @subparser3() as "sp3" : () -> !p4hir.parser<"subparser3", (!p4hir.ref, !p4hir.ref)> state start { s = 1; + sp.apply(e); +// CHECK: p4hir.apply %[[sp]](%arg0) : !p4hir.parser<"subparser", (!empty)> transition next; } - + state next { s = 2; + sp2.apply(e); +// CHECK: p4hir.apply %[[sp2]](%arg0) : !p4hir.parser<"subparser2", (!empty)> +// CHECK: p4hir.scope +// CHECK: p4hir.apply %[[sp3]](%s_inout_arg, %matched_out_arg) : !p4hir.parser<"subparser3", (!p4hir.ref, !p4hir.ref)> + bool matched = false; + sp3.apply(s, matched); + transition accept; } diff --git a/tools/p4mlir-translate/translate.cpp b/tools/p4mlir-translate/translate.cpp index f164412..8fd8b5f 100644 --- a/tools/p4mlir-translate/translate.cpp +++ b/tools/p4mlir-translate/translate.cpp @@ -545,8 +545,10 @@ bool P4TypeConverter::preorder(const P4::IR::Type_Parser *type) { ConversionTracer trace("TypeConverting ", type); llvm::SmallVector argTypes; - for (const auto *p : type->getApplyParameters()->parameters) - argTypes.emplace_back(convert(p->type)); + for (const auto *p : type->getApplyParameters()->parameters) { + mlir::Type type = convert(p->type); + argTypes.push_back(p->hasOut() ? P4HIR::ReferenceType::get(type) : type); + } auto mlirType = P4HIR::ParserType::get(converter.context(), type->name.string_view(), argTypes); return setType(type, mlirType); @@ -1340,6 +1342,14 @@ bool P4HIRConverter::preorder(const P4::IR::MethodCallExpression *mce) { BUG_CHECK(fSym, "expected reference function to be converted: %1%", fCall->method); callResult = b.create(loc, fSym, callResultType, operands).getResult(); + } else if (const auto *aCall = instance->to()) { + LOG4("resolved as apply"); + // Apply of something instantiated + if (auto *decl = aCall->object->to()) { + auto val = getValue(decl); + b.create(loc, val, operands); + } else + BUG("Unsuported apply: %1%", aCall->object); } else { BUG("unsupported call type: %1%", mce); } @@ -1699,9 +1709,10 @@ bool P4HIRConverter::preorder(const P4::IR::Declaration_Instance *decl) { auto parserSym = p4Symbols.lookup(parser); BUG_CHECK(parserSym, "expected reference parser to be converted: %1%", dbp(parser)); - builder.create(getLoc(builder, decl), resultType, - parserSym.getRootReference(), operands, - builder.getStringAttr(decl->name.string_view())); + auto instance = builder.create( + getLoc(builder, decl), resultType, parserSym.getRootReference(), operands, + builder.getStringAttr(decl->name.string_view())); + setValue(decl, instance.getResult()); } else { BUG("unsupported instance type: %1%", decl); }