@@ -89,6 +89,116 @@ struct CallOpConversionPattern : public OpConversionPattern<P4HIR::CallOp> {
8989 }
9090};
9191
92+ static std::optional<Value> detectNextPattern (P4HIR::CallMethodOp extractOp) {
93+ // Pattern:
94+ // %hs = ... (HeaderStackType)
95+ // %nextIndex_ref = struct_field_ref %hs["nextIndex"]
96+ // %idx = read %nextIndex_ref
97+ // %elt_ref = array_element_ref %array[%idx]
98+ // %var = variable
99+ // call_method @extract(%var) <- extractOp
100+ // %val = read %var <- read from extract result
101+ // assign %val, %elt_ref <- assign extract result to hs[nextIndex]
102+
103+ if (extractOp.getArgOperands ().empty ()) return std::nullopt ;
104+
105+ auto extractArg = extractOp.getArgOperands ()[0 ];
106+
107+ auto varOp = extractArg.getDefiningOp <P4HIR::VariableOp>();
108+ if (!varOp) return std::nullopt ;
109+
110+ P4HIR::ReadOp readOp = nullptr ;
111+ for (auto *user : varOp.getResult ().getUsers ()) {
112+ if (auto read = dyn_cast<P4HIR::ReadOp>(user)) {
113+ if (read->isBeforeInBlock (extractOp)) continue ;
114+ readOp = read;
115+ break ;
116+ }
117+ }
118+ if (!readOp) return std::nullopt ;
119+
120+ P4HIR::AssignOp assignOp = nullptr ;
121+ for (auto *user : readOp.getResult ().getUsers ()) {
122+ if (auto assign = dyn_cast<P4HIR::AssignOp>(user)) {
123+ assignOp = assign;
124+ break ;
125+ }
126+ }
127+ if (!assignOp) return std::nullopt ;
128+
129+ auto target = assignOp.getRef ();
130+ auto arrayEltRef = target.getDefiningOp <P4HIR::ArrayElementRefOp>();
131+ if (!arrayEltRef) return std::nullopt ;
132+
133+ auto index = arrayEltRef.getIndex ();
134+ auto readIdx = index.getDefiningOp <P4HIR::ReadOp>();
135+ if (!readIdx) return std::nullopt ;
136+
137+ auto readSource = readIdx.getRef ();
138+ auto nextIndexRef = readSource.getDefiningOp <P4HIR::StructFieldRefOp>();
139+ if (!nextIndexRef || nextIndexRef.getFieldName () != " nextIndex" ) return std::nullopt ;
140+
141+ auto hsBase = nextIndexRef.getOperand ();
142+ auto hsBaseType = hsBase.getType ();
143+ if (auto refType = mlir::dyn_cast<P4HIR::ReferenceType>(hsBaseType))
144+ hsBaseType = refType.getObjectType ();
145+
146+ if (!mlir::isa<P4HIR::HeaderStackType>(hsBaseType)) return std::nullopt ;
147+
148+ return hsBase;
149+ }
150+
151+ static void insertHeaderStackExtractLogic (P4HIR::CallMethodOp op, Value hsBase,
152+ ConversionPatternRewriter &rewriter) {
153+ auto loc = op.getLoc ();
154+ static constexpr unsigned hsIdBitWidth = 32 ;
155+ auto intType = P4HIR::BitsType::get (op.getContext (), hsIdBitWidth, false );
156+
157+ auto hsBaseType = hsBase.getType ();
158+ if (auto refType = mlir::dyn_cast<P4HIR::ReferenceType>(hsBaseType))
159+ hsBaseType = refType.getObjectType ();
160+
161+ auto hsType = mlir::cast<P4HIR::HeaderStackType>(hsBaseType);
162+ uint64_t arraySize = hsType.getArraySize ();
163+
164+ auto nextIndexRef = rewriter.create <P4HIR::StructFieldRefOp>(loc, hsBase, " nextIndex" );
165+ auto nextIndexVal = rewriter.create <P4HIR::ReadOp>(loc, nextIndexRef);
166+ auto sizeConst = rewriter.create <P4HIR::ConstOp>(loc, P4HIR::IntAttr::get (intType, arraySize));
167+ auto check = rewriter.create <P4HIR::CmpOp>(loc, P4HIR::CmpOpKind::Lt, nextIndexVal, sizeConst);
168+
169+ auto errorType = P4HIR::ErrorType::get (
170+ op.getContext (),
171+ mlir::ArrayAttr::get (op.getContext (),
172+ {mlir::StringAttr::get (op.getContext (), " StackOutOfBounds" )}));
173+ auto errorConst = rewriter.create <P4HIR::ConstOp>(
174+ loc, P4HIR::ErrorCodeAttr::get (errorType, " StackOutOfBounds" ));
175+ rewriter.create <P4CoreLib::VerifyOp>(loc, check, errorConst);
176+
177+ auto varOp = op.getArgOperands ()[0 ].getDefiningOp <P4HIR::VariableOp>();
178+ if (!varOp) return ;
179+
180+ for (auto *user : varOp.getResult ().getUsers ()) {
181+ if (auto readOp = dyn_cast<P4HIR::ReadOp>(user)) {
182+ if (readOp->isBeforeInBlock (op)) continue ;
183+ for (auto *readUser : readOp.getResult ().getUsers ()) {
184+ if (auto assignOp = dyn_cast<P4HIR::AssignOp>(readUser)) {
185+ rewriter.setInsertionPointAfter (assignOp);
186+ auto constOne =
187+ rewriter.create <P4HIR::ConstOp>(loc, P4HIR::IntAttr::get (intType, 1 ));
188+ auto nextIndexRefInc =
189+ rewriter.create <P4HIR::StructFieldRefOp>(loc, hsBase, " nextIndex" );
190+ auto currentNext = rewriter.create <P4HIR::ReadOp>(loc, nextIndexRefInc);
191+ auto incremented = rewriter.create <P4HIR::BinOp>(loc, P4HIR::BinOpKind::Add,
192+ currentNext, constOne);
193+ rewriter.create <P4HIR::AssignOp>(loc, incremented, nextIndexRefInc);
194+ return ;
195+ }
196+ }
197+ break ;
198+ }
199+ }
200+ }
201+
92202struct CallMethodOpConversionPattern : public OpConversionPattern <P4HIR::CallMethodOp> {
93203 using OpConversionPattern<P4HIR::CallMethodOp>::OpConversionPattern;
94204
@@ -103,6 +213,11 @@ struct CallMethodOpConversionPattern : public OpConversionPattern<P4HIR::CallMet
103213 } else if (extSym == " packet_in" ) {
104214 if (methodSym == " extract" ) {
105215 size_t sz = op.getArgOperands ().size ();
216+ if (auto hsBase = detectNextPattern (op)) {
217+ auto savedInsertionPoint = rewriter.saveInsertionPoint ();
218+ insertHeaderStackExtractLogic (op, *hsBase, rewriter);
219+ rewriter.restoreInsertionPoint (savedInsertionPoint);
220+ }
106221 if (sz == 1 ) {
107222 rewriter.replaceOpWithNewOp <P4CoreLib::PacketExtractOp>(op, op.getResultTypes (),
108223 operands.getOperands ());
0 commit comments