@@ -15,14 +15,22 @@ using namespace P4::P4MLIR;
1515
1616namespace {
1717
18+ // / Convert an MLIR attribute to its JSON string representation
19+ static std::string attrToJsonString (mlir::Attribute attr) {
20+ std::string result;
21+ llvm::raw_string_ostream os (result);
22+ attr.print (os);
23+ return os.str ();
24+ }
25+
26+ // / Serialize parser operation to BMv2 JSON (extract: regular, stack, union_stack).
1827static llvm::json::Object serializeParserOp (Operation *op) {
1928 llvm::json::Object opJson;
20-
29+
2130 if (auto extractOp = dyn_cast<BMv2IR::ExtractOp>(op)) {
2231 opJson[" op" ] = " extract" ;
23- llvm::json::Array parameters;
2432 llvm::json::Object param;
25-
33+
2634 auto extractKind = extractOp.getExtractType ();
2735 if (extractKind == BMv2IR::ExtractKind::Regular) {
2836 param[" type" ] = " regular" ;
@@ -38,17 +46,19 @@ static llvm::json::Object serializeParserOp(Operation *op) {
3846 unionValue.push_back (extractOp.getUnionMember ()->str ());
3947 param[" value" ] = std::move (unionValue);
4048 }
41-
49+
50+ llvm::json::Array parameters;
4251 parameters.push_back (std::move (param));
4352 opJson[" parameters" ] = std::move (parameters);
4453 }
45-
54+
4655 return opJson;
4756}
4857
58+ // / Serialize transition key to BMv2 JSON (field, lookahead, stack_field, union_stack_field).
4959static llvm::json::Object serializeTransitionKey (Operation *op) {
5060 llvm::json::Object keyJson;
51-
61+
5262 if (auto fieldOp = dyn_cast<BMv2IR::FieldOp>(op)) {
5363 keyJson[" type" ] = " field" ;
5464 llvm::json::Array value;
@@ -75,124 +85,113 @@ static llvm::json::Object serializeTransitionKey(Operation *op) {
7585 value.push_back (unionStackFieldOp.getFieldMember ().str ());
7686 keyJson[" value" ] = std::move (value);
7787 }
78-
88+
7989 return keyJson;
8090}
8191
92+ // / Serialize parser state transition to BMv2 JSON (default, hexstr, parse_vset).
8293static llvm::json::Object serializeTransition (BMv2IR::TransitionOp transitionOp) {
8394 llvm::json::Object transJson;
84-
95+
8596 auto kind = transitionOp.getType ();
8697 if (kind == BMv2IR::TransitionKind::Default) {
8798 transJson[" type" ] = " default" ;
8899 transJson[" value" ] = nullptr ;
89100 transJson[" mask" ] = nullptr ;
90101 } else if (kind == BMv2IR::TransitionKind::Hexstr) {
91102 transJson[" type" ] = " hexstr" ;
92- if (transitionOp.getValue ()) {
93- std::string valueStr;
94- llvm::raw_string_ostream os (valueStr);
95- transitionOp.getValue ()->print (os);
96- transJson[" value" ] = os.str ();
97- } else {
98- transJson[" value" ] = nullptr ;
99- }
100- if (transitionOp.getMask ()) {
101- std::string maskStr;
102- llvm::raw_string_ostream os (maskStr);
103- transitionOp.getMask ()->print (os);
104- transJson[" mask" ] = os.str ();
105- } else {
106- transJson[" mask" ] = nullptr ;
107- }
103+ transJson[" value" ] = transitionOp.getValue ()
104+ ? llvm::json::Value (attrToJsonString (*transitionOp.getValue ()))
105+ : llvm::json::Value (nullptr );
106+ transJson[" mask" ] = transitionOp.getMask ()
107+ ? llvm::json::Value (attrToJsonString (*transitionOp.getMask ()))
108+ : llvm::json::Value (nullptr );
108109 } else if (kind == BMv2IR::TransitionKind::Parse_vset) {
109110 transJson[" type" ] = " parse_vset" ;
110- if (transitionOp.getValue ()) {
111- std::string valueStr;
112- llvm::raw_string_ostream os (valueStr);
113- transitionOp.getValue ()->print (os);
114- transJson[" value" ] = os.str ();
115- } else {
116- transJson[" value" ] = nullptr ;
117- }
111+ transJson[" value" ] = transitionOp.getValue ()
112+ ? llvm::json::Value (attrToJsonString (*transitionOp.getValue ()))
113+ : llvm::json::Value (nullptr );
118114 transJson[" mask" ] = nullptr ;
119115 }
120-
121- if (transitionOp.getNextState ()) {
122- auto nextState = transitionOp.getNextState ()->getLeafReference ().str ();
123- transJson[" next_state" ] = nextState;
124- } else {
125- transJson[" next_state" ] = nullptr ;
126- }
127-
116+
117+ // Set next_state: use state name or null for end of parsing
118+ transJson[" next_state" ] = transitionOp.getNextState ()
119+ ? llvm::json::Value (transitionOp.getNextState ()->getLeafReference ().str ())
120+ : llvm::json::Value (nullptr );
121+
128122 return transJson;
129123}
130124
125+ // / Serialize parser state to BMv2 JSON with operations, transition keys, and transitions.
131126static llvm::json::Object serializeParserState (BMv2IR::ParserStateOp stateOp, int stateId) {
132127 llvm::json::Object stateJson;
133128 stateJson[" name" ] = stateOp.getSymName ().str ();
134129 stateJson[" id" ] = stateId;
135130
131+ // Serialize parser operations (e.g., extract header fields)
136132 llvm::json::Array parserOps;
137133 for (auto &op : stateOp.getParserOps ().front ()) {
138- if (! isa<BMv2IR::ExtractOp>(&op)) continue ;
139- parserOps.push_back (serializeParserOp (&op));
134+ if (isa<BMv2IR::ExtractOp>(&op))
135+ parserOps.push_back (serializeParserOp (&op));
140136 }
141137 stateJson[" parser_ops" ] = std::move (parserOps);
142138
139+ // Serialize transition keys (fields used to determine next state)
143140 llvm::json::Array transitionKeys;
144141 for (auto &op : stateOp.getTransitionKeys ().front ()) {
145- if (isa<BMv2IR::FieldOp, BMv2IR::LookaheadOp,
146- BMv2IR::StackFieldOp, BMv2IR::UnionStackFieldOp>(&op)) {
142+ if (isa<BMv2IR::FieldOp, BMv2IR::LookaheadOp,
143+ BMv2IR::StackFieldOp, BMv2IR::UnionStackFieldOp>(&op))
147144 transitionKeys.push_back (serializeTransitionKey (&op));
148- }
149145 }
150146 stateJson[" transition_key" ] = std::move (transitionKeys);
151-
147+
148+ // Serialize state transitions
152149 llvm::json::Array transitions;
153150 for (auto &op : stateOp.getTransitions ().front ()) {
154- if (auto transOp = dyn_cast<BMv2IR::TransitionOp>(&op)) {
151+ if (auto transOp = dyn_cast<BMv2IR::TransitionOp>(&op))
155152 transitions.push_back (serializeTransition (transOp));
156- }
157153 }
158154 stateJson[" transitions" ] = std::move (transitions);
159-
155+
160156 return stateJson;
161157}
162158
159+ // / Serialize complete parser to BMv2 JSON with initial state and parse states.
163160static llvm::json::Object serializeParser (BMv2IR::ParserOp parserOp, int parserId) {
164- llvm::json::Object parserJson;
165- parserJson[" name" ] = parserOp.getSymName ().str ();
166- parserJson[" id" ] = parserId;
167- parserJson[" init_state" ] = parserOp.getInitState ().getLeafReference ().str ();
168-
161+ // Collect all parse states
169162 llvm::json::Array parseStates;
170163 int stateId = 0 ;
171164 for (auto &op : parserOp.getBody ().front ()) {
172- if (auto stateOp = dyn_cast<BMv2IR::ParserStateOp>(&op)) {
165+ if (auto stateOp = dyn_cast<BMv2IR::ParserStateOp>(&op))
173166 parseStates.push_back (serializeParserState (stateOp, stateId++));
174- }
175167 }
168+
169+ // Build parser JSON object
170+ llvm::json::Object parserJson;
171+ parserJson[" name" ] = parserOp.getSymName ().str ();
172+ parserJson[" id" ] = parserId;
173+ parserJson[" init_state" ] = parserOp.getInitState ().getLeafReference ().str ();
176174 parserJson[" parse_states" ] = std::move (parseStates);
177-
175+
178176 return parserJson;
179177}
180178
181- }
179+ } // namespace
182180
181+ // / Convert BMv2IR module to BMv2 JSON. Currently supports parsers only.
183182mlir::FailureOr<llvm::json::Value> P4::P4MLIR::bmv2irToJson (ModuleOp moduleOp) {
184- llvm::json::Object rootJson;
185183 llvm::json::Array parsers;
186184
185+ // Collect all parsers from the module
187186 int parserId = 0 ;
188187 for (auto &op : moduleOp.getBody ()->getOperations ()) {
189- if (auto parserOp = dyn_cast<BMv2IR::ParserOp>(&op)) {
188+ if (auto parserOp = dyn_cast<BMv2IR::ParserOp>(&op))
190189 parsers.push_back (serializeParser (parserOp, parserId++));
191- }
192190 }
193-
191+
192+ llvm::json::Object rootJson;
194193 rootJson[" parsers" ] = std::move (parsers);
195-
194+
196195 return llvm::json::Value (std::move (rootJson));
197196}
198197
0 commit comments