30 static std::map<cstring, funcType> *cvtForType;
33 bool replaceNextWithLast;
35 : structure(structure), p4lib(P4::P4CoreLibrary::instance()), replaceNextWithLast(
false) {
36 setName(
"ExpressionConverter");
38 const IR::Type *getFieldType(
const IR::Type_StructLike *ht,
cstring fieldName);
39 const IR::Node *postorder(IR::Constant *expression)
override;
40 const IR::Node *postorder(IR::Member *field)
override;
41 const IR::Node *postorder(IR::FieldList *fl)
override;
42 const IR::Node *postorder(IR::Mask *expression)
override;
43 const IR::Node *postorder(IR::ActionArg *arg)
override;
44 const IR::Node *postorder(IR::Primitive *primitive)
override;
45 const IR::Node *postorder(IR::PathExpression *ref)
override;
46 const IR::Node *postorder(IR::ConcreteHeaderRef *nhr)
override;
47 const IR::Node *postorder(IR::HeaderStackItemRef *ref)
override;
48 const IR::Node *postorder(IR::GlobalRef *gr)
override;
49 const IR::Node *postorder(IR::Equ *equ)
override;
50 const IR::Node *postorder(IR::Neq *neq)
override;
51 const IR::Expression *convert(
const IR::Node *node) {
52 auto result = node->apply(*
this);
53 return result->
to<IR::Expression>();
55 static void addConverter(
cstring type, funcType);
56 static funcType get(
cstring type);
88class ExternConverter {
89 static std::map<cstring, ExternConverter *> *cvtForType;
92 virtual const IR::Type_Extern *convertExternType(
ProgramStructure *,
const IR::Type_Extern *,
94 virtual const IR::Declaration_Instance *convertExternInstance(
98 const IR::Declaration_Instance *,
99 const IR::Primitive *);
100 virtual bool convertAsGlobal(
ProgramStructure *,
const IR::Declaration_Instance *) {
104 virtual ~ExternConverter() =
default;
109 static ExternConverter *get(
cstring type);
110 static ExternConverter *get(
const IR::Type_Extern *type) {
return get(type->name); }
111 static ExternConverter *get(
const IR::Declaration_Instance *ext) {
112 return get(ext->type->to<IR::Type_Extern>());
114 static const IR::Type_Extern *cvtExternType(
ProgramStructure *s,
const IR::Type_Extern *e,
116 return get(e)->convertExternType(s, e, name);
118 static const IR::Declaration_Instance *cvtExternInstance(
121 return get(di)->convertExternInstance(s, di, name, scope);
124 const IR::Declaration_Instance *di,
125 const IR::Primitive *p) {
126 return get(di)->convertExternCall(s, di, p);
128 static bool cvtAsGlobal(
ProgramStructure *s,
const IR::Declaration_Instance *di) {
129 return get(di)->convertAsGlobal(s, di);
174 std::map<cstring, cstring> reserved_names = {{
"standard_metadata_t"_cs,
"type"_cs},
175 {
"standard_metadata"_cs,
"metadata"_cs},
176 {
"egress"_cs,
"control"_cs}};
179 auto it = reserved_names.find(nodeName);
180 if (it == reserved_names.end())
return;
181 if (it->second != kind)
182 ::P4::error(ErrorType::ERR_INVALID,
"%1%: invalid name; it can only be used for %2%",
186 checkReserved(node, nodeName,
nullptr);
190 explicit DiscoverStructure(
ProgramStructure *structure) : structure(structure) {
191 CHECK_NULL(structure);
192 setName(
"DiscoverStructure");
195 void postorder(
const IR::ParserException *ex)
override {
196 warn(ErrorType::WARN_UNSUPPORTED,
"%1%: parser exception is not translated to P4-16", ex);
198 void postorder(
const IR::Metadata *md)
override {
199 structure->metadata.emplace(md);
200 checkReserved(md, md->name,
"metadata"_cs);
202 void postorder(
const IR::Header *hd)
override {
203 structure->headers.emplace(hd);
204 checkReserved(hd, hd->name);
206 void postorder(
const IR::Type_StructLike *t)
override {
207 structure->types.emplace(t);
208 checkReserved(t, t->name,
"type"_cs);
210 void postorder(
const IR::V1Control *control)
override {
211 structure->controls.emplace(control);
212 checkReserved(control, control->name,
"control"_cs);
214 void postorder(
const IR::V1Parser *parser)
override {
215 structure->parserStates.emplace(parser);
216 checkReserved(parser, parser->name);
218 void postorder(
const IR::V1Table *table)
override {
219 structure->tables.emplace(table);
220 checkReserved(table, table->name);
222 void postorder(
const IR::ActionFunction *action)
override {
223 structure->actions.emplace(action);
224 checkReserved(action, action->name);
226 void postorder(
const IR::HeaderStack *stack)
override {
227 structure->stacks.emplace(stack);
228 checkReserved(stack, stack->name);
230 void postorder(
const IR::Counter *count)
override {
231 structure->counters.emplace(count);
232 checkReserved(count, count->name);
234 void postorder(
const IR::Register *reg)
override {
235 structure->registers.emplace(reg);
236 checkReserved(reg, reg->name);
238 void postorder(
const IR::ActionProfile *ap)
override {
239 structure->action_profiles.emplace(ap);
240 checkReserved(ap, ap->name);
242 void postorder(
const IR::FieldList *fl)
override {
243 structure->field_lists.emplace(fl);
244 checkReserved(fl, fl->name);
246 void postorder(
const IR::FieldListCalculation *flc)
override {
247 structure->field_list_calculations.emplace(flc);
248 checkReserved(flc, flc->name);
250 void postorder(
const IR::CalculatedField *cf)
override {
251 structure->calculated_fields.push_back(cf);
253 void postorder(
const IR::Meter *m)
override {
254 structure->meters.emplace(m);
255 checkReserved(m, m->name);
257 void postorder(
const IR::ActionSelector *as)
override {
258 structure->action_selectors.emplace(as);
259 checkReserved(as, as->name);
261 void postorder(
const IR::Type_Extern *ext)
override {
262 structure->extern_types.emplace(ext);
263 checkReserved(ext, ext->name);
265 void postorder(
const IR::Declaration_Instance *ext)
override {
266 structure->externs.emplace(ext);
267 checkReserved(ext, ext->name);
269 void postorder(
const IR::ParserValueSet *pvs)
override {
270 structure->value_sets.emplace(pvs);
271 checkReserved(pvs, pvs->name);
279 explicit ComputeCallGraph(
ProgramStructure *structure) : structure(structure) {
280 CHECK_NULL(structure);
281 setName(
"ComputeCallGraph");
284 void postorder(
const IR::V1Parser *parser)
override {
285 LOG3(
"Scanning parser " << parser->name);
286 structure->parsers.add(parser->name);
287 if (!parser->default_return.name.isNullOrEmpty())
288 structure->parsers.calls(parser->name, parser->default_return);
289 if (parser->cases !=
nullptr)
290 for (
auto ce : *parser->cases) structure->parsers.calls(parser->name, ce->action.name);
291 for (
auto expr : parser->stmts) {
292 if (expr->is<IR::Primitive>()) {
293 auto primitive = expr->to<IR::Primitive>();
294 if (primitive->name ==
"extract") {
295 BUG_CHECK(primitive->operands.size() == 1,
"Expected 1 operand for %1%",
297 auto dest = primitive->operands.at(0);
298 LOG3(
"Parser " << parser->name <<
" extracts into " << dest);
299 structure->extracts[parser->name].push_back(dest);
304 void postorder(
const IR::Primitive *primitive)
override {
305 auto name = primitive->name;
306 const IR::GlobalRef *glob =
nullptr;
307 const IR::Declaration_Instance *extrn =
nullptr;
308 if (!primitive->operands.empty()) glob = primitive->operands[0]->to<IR::GlobalRef>();
309 if (glob) extrn = glob->obj->to<IR::Declaration_Instance>();
312 auto parent = findContext<IR::ActionFunction>();
313 BUG_CHECK(parent !=
nullptr,
"%1%: Extern call not within action", primitive);
314 structure->calledExterns.calls(parent->name, extrn->name.name);
316 }
else if (primitive->name ==
"count") {
318 auto ctrref = primitive->operands.at(0);
319 const IR::Counter *ctr =
nullptr;
320 if (
auto gr = ctrref->to<IR::GlobalRef>())
321 ctr = gr->obj->to<IR::Counter>();
322 else if (
auto nr = ctrref->to<IR::PathExpression>())
323 ctr = structure->counters.get(nr->path->name);
324 if (ctr ==
nullptr) {
325 ::P4::error(ErrorType::ERR_NOT_FOUND,
"%1%: Cannot find counter", ctrref);
328 auto parent = findContext<IR::ActionFunction>();
329 BUG_CHECK(parent !=
nullptr,
"%1%: Counter call not within action", primitive);
330 structure->calledCounters.calls(parent->name, ctr->name.name);
332 }
else if (primitive->name ==
"execute_meter") {
333 auto mtrref = primitive->operands.at(0);
334 const IR::Meter *mtr =
nullptr;
335 if (
auto gr = mtrref->to<IR::GlobalRef>())
336 mtr = gr->obj->to<IR::Meter>();
337 else if (
auto nr = mtrref->to<IR::PathExpression>())
338 mtr = structure->meters.get(nr->path->name);
339 if (mtr ==
nullptr) {
340 ::P4::error(ErrorType::ERR_NOT_FOUND,
"%1%: Cannot find meter", mtrref);
343 auto parent = findContext<IR::ActionFunction>();
344 BUG_CHECK(parent !=
nullptr,
"%1%: not within action", primitive);
345 structure->calledMeters.calls(parent->name, mtr->name.name);
347 }
else if (primitive->name ==
"register_read" || primitive->name ==
"register_write") {
348 const IR::Expression *regref;
349 if (primitive->name ==
"register_read")
350 regref = primitive->operands.at(1);
352 regref = primitive->operands.at(0);
353 const IR::Register *reg =
nullptr;
354 if (
auto gr = regref->to<IR::GlobalRef>())
355 reg = gr->obj->to<IR::Register>();
356 else if (
auto nr = regref->to<IR::PathExpression>())
357 reg = structure->registers.get(nr->path->name);
358 if (reg ==
nullptr) {
359 ::P4::error(ErrorType::ERR_NOT_FOUND,
"%1%: Cannot find register", regref);
362 auto parent = findContext<IR::ActionFunction>();
363 BUG_CHECK(parent !=
nullptr,
"%1%: not within action", primitive);
364 structure->calledRegisters.calls(parent->name, reg->name.name);
366 }
else if (structure->actions.contains(name)) {
367 auto parent = findContext<IR::ActionFunction>();
368 BUG_CHECK(parent !=
nullptr,
"%1%: Action call not within action", primitive);
369 structure->calledActions.calls(parent->name, name);
370 }
else if (structure->controls.contains(name)) {
371 auto parent = findContext<IR::V1Control>();
372 BUG_CHECK(parent !=
nullptr,
"%1%: Control call not within control", primitive);
373 structure->calledControls.calls(parent->name, name);
376 void postorder(
const IR::GlobalRef *gref)
override {
378 if (
auto af = findContext<IR::ActionFunction>()) {
380 }
else if (
auto di = findContext<IR::Declaration_Instance>()) {
383 BUG(
"%1%: GlobalRef not within action or extern", gref);
385 if (
auto ctr = gref->obj->to<IR::Counter>())
386 structure->calledCounters.calls(caller, ctr->name.name);
387 else if (
auto mtr = gref->obj->to<IR::Meter>())
388 structure->calledMeters.calls(caller, mtr->name.name);
389 else if (
auto reg = gref->obj->to<IR::Register>())
390 structure->calledRegisters.calls(caller, reg->name.name);
391 else if (
auto ext = gref->obj->to<IR::Declaration_Instance>())
392 structure->calledExterns.calls(caller, ext->name.name);
403 explicit ComputeTableCallGraph(
ProgramStructure *structure) : structure(structure) {
404 CHECK_NULL(structure);
405 setName(
"ComputeTableCallGraph");
408 void postorder(
const IR::Apply *apply)
override {
409 LOG3(
"Scanning " << apply->name);
410 auto tbl = structure->tables.get(apply->name.name);
411 if (tbl ==
nullptr) {
412 ::P4::error(ErrorType::ERR_NOT_FOUND,
"%1%: Could not find table", apply->name);
415 auto parent = findContext<IR::V1Control>();
417 ::P4::error(ErrorType::ERR_UNEXPECTED,
"%1%: Apply not within a control block?", apply);
421 auto ctrl = get(structure->tableMapping, tbl);
424 if (!structure->calledControls.isCallee(parent->name) &&
425 parent->name != P4V1::V1Model::instance().ingress.name &&
426 parent->name != P4V1::V1Model::instance().egress.name)
429 if (ctrl !=
nullptr && ctrl != parent) {
430 auto previous = get(structure->tableInvocation, tbl);
432 "%1%: Table invoked from two different controls: %2% and %3%", tbl, apply,
435 LOG3(
"Invoking " << tbl <<
" in " << parent->name);
436 structure->tableMapping.emplace(tbl, parent);
437 structure->tableInvocation.emplace(tbl, apply);
505 const IR::Type_Header *fixedHeaderType;
507 const IR::Expression *headerLength;
517 std::map<cstring, HeaderSplit *> fixedPart;
522 HeaderSplit *splitHeaderType(
const IR::Type_Header *type) {
524 auto fixed = ::P4::get(fixedPart, type->name.name);
525 if (fixed !=
nullptr)
return fixed;
527 const IR::Expression *headerLength =
nullptr;
529 const IR::Type_Header *fixedHeaderType =
nullptr;
532 for (
auto f : type->fields) {
533 if (f->type->is<IR::Type_Varbits>()) {
534 cstring hname = structure->makeUniqueName(type->name.name);
535 if (fixedHeaderType !=
nullptr) {
537 "%1%: header types with multiple varbit fields are not supported",
541 fixedHeaderType =
new IR::Type_Header(
IR::ID(hname), fields);
543 auto anno = f->getAnnotation(IR::Annotation::lengthAnnotation);
544 BUG_CHECK(anno !=
nullptr,
"%1%: no length annotation on varbit field", f);
545 BUG_CHECK(anno->getExpr().size() == 1,
"%1%: expected exactly 1 argument", anno);
546 headerLength = anno->getExpr(0);
549 }
else if (fixedHeaderType ==
nullptr) {
554 if (fixedHeaderType !=
nullptr) {
555 LOG3(
"Extracted fixed-size header type from " << type <<
" into " << fixedHeaderType);
556 fixed =
new HeaderSplit;
557 fixed->fixedHeaderType = fixedHeaderType;
558 fixed->headerLength = headerLength;
559 fixedPart.emplace(type->name.name, fixed);
560 allTypeDecls.push_back(fixedHeaderType);
573 class RewriteLength final :
public Transform {
574 const IR::Type_Header *header;
575 const IR::Declaration *var;
578 explicit RewriteLength(
const IR::Type_Header *header,
const IR::Declaration *var)
579 : header(header), var(var) {
580 setName(
"RewriteLength");
583 const IR::Node *postorder(IR::PathExpression *expression)
override {
584 if (expression->path->absolute)
return expression;
585 for (
auto f : header->fields) {
586 if (f->name == expression->path->name)
587 return new IR::Member(expression->srcInfo,
new IR::PathExpression(var->name),
596 CHECK_NULL(structure);
597 setName(
"FixExtracts");
600 const IR::Node *postorder(IR::P4Program *program)
override {
603 allTypeDecls.append(program->objects);
604 program->objects = allTypeDecls;
608 const IR::Node *postorder(IR::P4Parser *parser)
override {
609 if (!varDecls.empty()) {
610 parser->parserLocals.append(varDecls);
616 const IR::Node *postorder(IR::MethodCallStatement *statement)
override {
617 auto mce = getOriginal<IR::MethodCallStatement>()->methodCall;
618 LOG3(
"Looking up in extracts " << dbp(mce));
619 auto ht = ::P4::get(structure->extractsSynthesized, mce);
625 BUG_CHECK(mce->arguments->size() == 1,
"%1%: expected 1 argument", mce);
626 auto arg = mce->arguments->at(0);
628 auto fixed = splitHeaderType(ht);
629 if (fixed ==
nullptr)
return statement;
630 CHECK_NULL(fixed->headerLength);
631 CHECK_NULL(fixed->fixedHeaderType);
634 cstring varName = structure->makeUniqueName(
"tmp_hdr"_cs);
636 new IR::Declaration_Variable(
IR::ID(varName), fixed->fixedHeaderType->to<IR::Type>());
637 varDecls.push_back(var);
640 auto member = mce->method->to<IR::Member>();
643 typeArgs->push_back(fixed->fixedHeaderType->getP4Type());
644 auto lookaheadMethod =
645 new IR::Member(member->expr, P4::P4CoreLibrary::instance().packetIn.lookahead.name);
646 auto lookahead =
new IR::MethodCallExpression(mce->srcInfo, lookaheadMethod, typeArgs,
649 new IR::AssignmentStatement(mce->srcInfo,
new IR::PathExpression(varName), lookahead);
650 result->push_back(assign);
651 LOG3(
"Created lookahead " << assign);
654 RewriteLength rewrite(fixed->fixedHeaderType, var);
655 rewrite.setCalledBy(
this);
656 auto length = fixed->headerLength->apply(rewrite);
658 args->push_back(arg->clone());
659 auto type = IR::Type_Bits::get(P4::P4CoreLibrary::instance().packetIn.extractSecondArgSize);
661 args->push_back(
new IR::Argument(cast));
662 auto expression =
new IR::MethodCallExpression(mce->srcInfo, mce->method->clone(), args);
663 result->push_back(
new IR::MethodCallStatement(expression));
727 DetectDuplicates() { setName(
"DetectDuplicates"); }
729 bool preorder(
const IR::V1Program *program)
override {
730 auto &map = program->scope;
731 auto firstWithKey = map.begin();
732 while (firstWithKey != map.end()) {
733 auto key = firstWithKey->first;
734 auto range = map.equal_range(key);
735 for (
auto s = range.first; s != range.second; s++) {
737 for (n++; n != range.second; n++) {
740 if (e1->node_type_name() == e2->node_type_name()) {
741 if (e1->srcInfo.getStart().isValid())
742 ::P4::error(ErrorType::ERR_DUPLICATE,
"%1%: same name as %2%", e1, e2);
746 "%1% is invalid; name %2% is reserved", e2, key);
750 firstWithKey = range.second;
781class InsertCompilerGeneratedStartState :
public Transform {
790 explicit InsertCompilerGeneratedStartState(
ProgramStructure *structure) : structure(structure) {
791 setName(
"InsertCompilerGeneratedStartState");
792 structure->allNames.insert({IR::ParserState::start, 0});
793 structure->allNames.insert({
"InstanceType"_cs, 0});
794 newStartState = structure->makeUniqueName(IR::ParserState::start);
795 newInstanceType = structure->makeUniqueName(
"InstanceType"_cs);
798 const IR::Node *postorder(IR::P4Program *program)
override {
799 allTypeDecls.append(program->objects);
800 program->objects = allTypeDecls;
805 const IR::Node *postorder(IR::ParserState *state)
override {
806 if (structure->parserEntryPoints.empty())
return state;
807 if (state->name == IR::ParserState::start) {
808 state->name = newStartState;
814 const IR::Node *postorder(IR::Path *path)
override {
815 if (structure->parserEntryPoints.empty())
return path;
819 if (path->name.name != IR::ParserState::start)
return path;
821 auto pe = getContext()->node->
to<IR::PathExpression>();
822 auto sc = findContext<IR::SelectCase>();
823 auto ps = findContext<IR::ParserState>();
825 if (pe && ((sc && pe->equiv(*sc->state->to<IR::PathExpression>())) ||
827 (ps && pe->equiv(*ps->selectExpression->to<IR::PathExpression>()))))
828 path->name = newStartState;
832 const IR::Node *postorder(IR::P4Parser *parser)
override {
833 if (structure->parserEntryPoints.empty())
return parser;
836 members.push_back(
new IR::SerEnumMember(
"START",
new IR::Constant(0)));
837 selCases.push_back(
new IR::SelectCase(
838 new IR::Member(
new IR::TypeNameExpression(
new IR::Type_Name(newInstanceType)),
840 new IR::PathExpression(
new IR::Path(newStartState))));
844 for (
auto p : structure->parserEntryPoints) {
845 members.push_back(
new IR::SerEnumMember(p.first,
new IR::Constant(idx++)));
846 selCases.push_back(
new IR::SelectCase(
847 new IR::Member(
new IR::TypeNameExpression(
new IR::Type_Name(newInstanceType)),
849 new IR::PathExpression(
new IR::Path(p.second->name))));
851 auto instEnum =
new IR::Type_SerEnum(
853 {
new IR::Annotation(IR::Annotation::nameAnnotation,
".$InstanceType"_cs)},
854 IR::Type_Bits::get(32), members);
855 allTypeDecls.push_back(instEnum);
858 selExpr.push_back(
new IR::Cast(
859 new IR::Type_Name(newInstanceType),
860 new IR::Member(
new IR::PathExpression(
new IR::Path(
"standard_metadata"_cs)),
861 "instance_type"_cs)));
862 auto selects =
new IR::SelectExpression(
new IR::ListExpression(selExpr), selCases);
863 auto startState =
new IR::ParserState(
864 IR::ParserState::start,
865 {
new IR::Annotation(IR::Annotation::nameAnnotation,
".$start"_cs)}, selects);
866 parserStates.push_back(startState);
868 if (!parserStates.empty()) {
869 parser->states.append(parserStates);
870 parserStates.clear();
898 const IR::Type_Struct *stdType =
nullptr;
899 const IR::Type_Struct *userType =
nullptr;
900 const IR::Type_Struct *intrType =
nullptr;
901 const IR::Type_Struct *queueType =
nullptr;
902 const IR::StructField *intrField =
nullptr;
903 const IR::StructField *queueField =
nullptr;
906 explicit MoveIntrinsicMetadata(
ProgramStructure *structure) : structure(structure) {
907 CHECK_NULL(structure);
908 setName(
"MoveIntrinsicMetadata");
910 const IR::Node *preorder(IR::P4Program *program)
override {
911 stdType = program->getDeclsByName(structure->v1model.standardMetadataType.name)
913 ->
to<IR::Type_Struct>();
914 userType = program->getDeclsByName(structure->v1model.metadataType.name)
916 ->to<IR::Type_Struct>();
918 CHECK_NULL(userType);
919 intrField = userType->getField(structure->v1model.intrinsicMetadata.name);
920 if (intrField !=
nullptr) {
921 auto intrTypeName = intrField->type;
922 auto tn = intrTypeName->to<IR::Type_Name>();
923 BUG_CHECK(tn,
"%1%: expected a Type_Name", intrTypeName);
924 auto nt = program->getDeclsByName(tn->path->name)->nextOrDefault();
925 if (nt ==
nullptr || !nt->is<IR::Type_Struct>()) {
926 ::P4::error(ErrorType::ERR_INVALID,
"%1%: expected a structure", tn);
929 intrType = nt->to<IR::Type_Struct>();
930 LOG2(
"Intrinsic metadata type " << intrType);
933 queueField = userType->getField(structure->v1model.queueingMetadata.name);
934 if (queueField !=
nullptr) {
935 auto queueTypeName = queueField->type;
936 auto tn = queueTypeName->to<IR::Type_Name>();
937 BUG_CHECK(tn,
"%1%: expected a Type_Name", queueTypeName);
938 auto nt = program->getDeclsByName(tn->path->name)->nextOrDefault();
939 if (nt ==
nullptr || !nt->is<IR::Type_Struct>()) {
940 ::P4::error(ErrorType::ERR_INVALID,
"%1%: expected a structure", tn);
943 queueType = nt->to<IR::Type_Struct>();
944 LOG2(
"Queueing metadata type " << queueType);
949 const IR::Node *postorder(IR::Type_Struct *type)
override {
950 if (getOriginal() == stdType) {
951 if (intrType !=
nullptr) {
952 for (
auto f : intrType->fields) {
953 if (type->fields.getDeclaration(f->name) ==
nullptr) {
955 "%1%: no such field in standard_metadata", f->name);
956 LOG2(
"standard_metadata: " << type);
960 if (queueType !=
nullptr) {
961 for (
auto f : queueType->fields) {
962 if (type->fields.getDeclaration(f->name) ==
nullptr) {
964 "%1%: no such field in standard_metadata", f->name);
965 LOG2(
"standard_metadata: " << type);
973 const IR::Node *postorder(IR::StructField *field)
override {
974 if (getOriginal() == intrField || getOriginal() == queueField)
980 const IR::Node *postorder(IR::Member *member)
override {
984 if (member->member != structure->v1model.intrinsicMetadata.name &&
985 member->member != structure->v1model.queueingMetadata.name)
987 auto pe = member->expr->
to<IR::PathExpression>();
988 if (pe ==
nullptr || pe->path->absolute)
return member;
989 if (pe->path->name == structure->v1model.parser.metadataParam.name) {
990 LOG2(
"Renaming reference " << member);
991 return new IR::PathExpression(
new IR::Path(
992 member->expr->srcInfo,
993 IR::ID(pe->path->name.srcInfo, structure->v1model.standardMetadata.name)));
1004 void add(
const IR::Primitive *primitive,
unsigned operand) {
1005 if (primitive->operands.size() <= operand) {
1010 auto expression = primitive->operands.at(operand);
1011 if (!expression->is<IR::PathExpression>()) {
1012 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected a field list", expression);
1015 auto nr = expression->to<IR::PathExpression>();
1016 auto fl = structure->field_lists.get(nr->path->name);
1017 if (fl ==
nullptr) {
1018 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: Expected a field list", expression);
1021 LOG3(
"Recirculated " << nr->path->name);
1022 structure->allFieldLists.emplace(fl);
1026 explicit FindRecirculated(
ProgramStructure *structure) : structure(structure) {
1027 CHECK_NULL(structure);
1028 setName(
"FindRecirculated");
1031 void postorder(
const IR::Primitive *primitive)
override {
1032 if (primitive->name ==
"recirculate" || primitive->name ==
"resubmit") {
1034 }
else if (primitive->name.startsWith(
"clone") && primitive->operands.size() == 2) {
Definition frontends/p4-14/fromv1.0/programStructure.h:23