38 using funcType = std::function<
const IR::Node *(
const IR::Node *)>;
39 static std::map<cstring, funcType> *cvtForType;
42 bool replaceNextWithLast;
44 : structure(structure), p4lib(P4::P4CoreLibrary::instance()), replaceNextWithLast(
false) {
45 setName(
"ExpressionConverter");
47 const IR::Type *getFieldType(
const IR::Type_StructLike *ht,
cstring fieldName);
48 const IR::Node *postorder(IR::Constant *expression)
override;
49 const IR::Node *postorder(IR::Member *field)
override;
50 const IR::Node *postorder(IR::FieldList *fl)
override;
51 const IR::Node *postorder(IR::Mask *expression)
override;
52 const IR::Node *postorder(IR::ActionArg *arg)
override;
53 const IR::Node *postorder(IR::Primitive *primitive)
override;
54 const IR::Node *postorder(IR::PathExpression *ref)
override;
55 const IR::Node *postorder(IR::ConcreteHeaderRef *nhr)
override;
56 const IR::Node *postorder(IR::HeaderStackItemRef *ref)
override;
57 const IR::Node *postorder(IR::GlobalRef *gr)
override;
58 const IR::Node *postorder(IR::Equ *equ)
override;
59 const IR::Node *postorder(IR::Neq *neq)
override;
60 const IR::Expression *convert(
const IR::Node *node) {
61 auto result = node->apply(*
this);
62 return result->to<IR::Expression>();
64 static void addConverter(
cstring type, funcType);
65 static funcType get(
cstring type);
98 static std::map<cstring, ExternConverter *> *cvtForType;
101 virtual const IR::Type_Extern *convertExternType(
ProgramStructure *,
const IR::Type_Extern *,
103 virtual const IR::Declaration_Instance *convertExternInstance(
105 IR::IndexedVector<IR::Declaration> *);
107 const IR::Declaration_Instance *,
108 const IR::Primitive *);
109 virtual bool convertAsGlobal(
ProgramStructure *,
const IR::Declaration_Instance *) {
117 static ExternConverter *get(
const IR::Type_Extern *type) {
return get(type->name); }
119 return get(ext->type->to<IR::Type_Extern>());
121 static const IR::Type_Extern *cvtExternType(
ProgramStructure *s,
const IR::Type_Extern *e,
123 return get(e)->convertExternType(s, e, name);
125 static const IR::Declaration_Instance *cvtExternInstance(
127 IR::IndexedVector<IR::Declaration> *scope) {
128 return get(di)->convertExternInstance(s, di, name, scope);
131 const IR::Declaration_Instance *di,
132 const IR::Primitive *p) {
133 return get(di)->convertExternCall(s, di, p);
135 static bool cvtAsGlobal(
ProgramStructure *s,
const IR::Declaration_Instance *di) {
136 return get(di)->convertAsGlobal(s, di);
181 std::map<cstring, cstring> reserved_names = {
182 {
"standard_metadata_t",
"type"}, {
"standard_metadata",
"metadata"}, {
"egress",
"control"}};
184 void checkReserved(
const IR::Node *node,
cstring nodeName,
cstring kind)
const {
185 auto it = reserved_names.find(nodeName);
186 if (it == reserved_names.end())
return;
187 if (it->second != kind)
188 ::error(ErrorType::ERR_INVALID,
"%1%: invalid name; it can only be used for %2%", node,
191 void checkReserved(
const IR::Node *node,
cstring nodeName)
const {
192 checkReserved(node, nodeName,
nullptr);
197 CHECK_NULL(structure);
198 setName(
"DiscoverStructure");
201 void postorder(
const IR::ParserException *ex)
override {
202 warn(ErrorType::WARN_UNSUPPORTED,
"%1%: parser exception is not translated to P4-16", ex);
204 void postorder(
const IR::Metadata *md)
override {
205 structure->metadata.emplace(md);
206 checkReserved(md, md->name,
"metadata");
208 void postorder(
const IR::Header *hd)
override {
209 structure->headers.emplace(hd);
210 checkReserved(hd, hd->name);
212 void postorder(
const IR::Type_StructLike *t)
override {
213 structure->types.emplace(t);
214 checkReserved(t, t->name,
"type");
216 void postorder(
const IR::V1Control *control)
override {
217 structure->controls.emplace(control);
218 checkReserved(control, control->name,
"control");
220 void postorder(
const IR::V1Parser *parser)
override {
221 structure->parserStates.emplace(parser);
222 checkReserved(parser, parser->name);
224 void postorder(
const IR::V1Table *table)
override {
225 structure->tables.emplace(table);
226 checkReserved(table, table->name);
228 void postorder(
const IR::ActionFunction *action)
override {
229 structure->actions.emplace(action);
230 checkReserved(action, action->name);
232 void postorder(
const IR::HeaderStack *stack)
override {
233 structure->stacks.emplace(stack);
234 checkReserved(stack, stack->name);
236 void postorder(
const IR::Counter *count)
override {
237 structure->counters.emplace(count);
238 checkReserved(count, count->name);
240 void postorder(
const IR::Register *reg)
override {
241 structure->registers.emplace(reg);
242 checkReserved(reg, reg->name);
244 void postorder(
const IR::ActionProfile *ap)
override {
245 structure->action_profiles.emplace(ap);
246 checkReserved(ap, ap->name);
248 void postorder(
const IR::FieldList *fl)
override {
249 structure->field_lists.emplace(fl);
250 checkReserved(fl, fl->name);
252 void postorder(
const IR::FieldListCalculation *flc)
override {
253 structure->field_list_calculations.emplace(flc);
254 checkReserved(flc, flc->name);
256 void postorder(
const IR::CalculatedField *cf)
override {
257 structure->calculated_fields.push_back(cf);
259 void postorder(
const IR::Meter *m)
override {
260 structure->meters.emplace(m);
261 checkReserved(m, m->name);
263 void postorder(
const IR::ActionSelector *as)
override {
264 structure->action_selectors.emplace(as);
265 checkReserved(as, as->name);
267 void postorder(
const IR::Type_Extern *ext)
override {
268 structure->extern_types.emplace(ext);
269 checkReserved(ext, ext->name);
271 void postorder(
const IR::Declaration_Instance *ext)
override {
272 structure->externs.emplace(ext);
273 checkReserved(ext, ext->name);
275 void postorder(
const IR::ParserValueSet *pvs)
override {
276 structure->value_sets.emplace(pvs);
277 checkReserved(pvs, pvs->name);
286 CHECK_NULL(structure);
287 setName(
"ComputeCallGraph");
290 void postorder(
const IR::V1Parser *parser)
override {
291 LOG3(
"Scanning parser " << parser->name);
292 structure->parsers.add(parser->name);
293 if (!parser->default_return.name.isNullOrEmpty())
294 structure->parsers.calls(parser->name, parser->default_return);
295 if (parser->cases !=
nullptr)
296 for (
auto ce : *parser->cases) structure->parsers.calls(parser->name, ce->action.name);
297 for (
auto expr : parser->stmts) {
298 if (expr->is<IR::Primitive>()) {
299 auto primitive = expr->to<IR::Primitive>();
300 if (primitive->name ==
"extract") {
301 BUG_CHECK(primitive->operands.size() == 1,
"Expected 1 operand for %1%",
303 auto dest = primitive->operands.at(0);
304 LOG3(
"Parser " << parser->name <<
" extracts into " << dest);
305 structure->extracts[parser->name].push_back(dest);
310 void postorder(
const IR::Primitive *primitive)
override {
311 auto name = primitive->name;
312 const IR::GlobalRef *glob =
nullptr;
313 const IR::Declaration_Instance *extrn =
nullptr;
314 if (!primitive->operands.empty()) glob = primitive->operands[0]->to<IR::GlobalRef>();
315 if (glob) extrn = glob->obj->to<IR::Declaration_Instance>();
318 auto parent = findContext<IR::ActionFunction>();
319 BUG_CHECK(parent !=
nullptr,
"%1%: Extern call not within action", primitive);
320 structure->calledExterns.calls(parent->name, extrn->name.name);
322 }
else if (primitive->name ==
"count") {
324 auto ctrref = primitive->operands.at(0);
325 const IR::Counter *ctr =
nullptr;
326 if (
auto gr = ctrref->to<IR::GlobalRef>())
327 ctr = gr->obj->to<IR::Counter>();
328 else if (
auto nr = ctrref->to<IR::PathExpression>())
329 ctr = structure->counters.get(nr->path->name);
330 if (ctr ==
nullptr) {
331 ::error(ErrorType::ERR_NOT_FOUND,
"%1%: Cannot find counter", ctrref);
334 auto parent = findContext<IR::ActionFunction>();
335 BUG_CHECK(parent !=
nullptr,
"%1%: Counter call not within action", primitive);
336 structure->calledCounters.calls(parent->name, ctr->name.name);
338 }
else if (primitive->name ==
"execute_meter") {
339 auto mtrref = primitive->operands.at(0);
340 const IR::Meter *mtr =
nullptr;
341 if (
auto gr = mtrref->to<IR::GlobalRef>())
342 mtr = gr->obj->to<IR::Meter>();
343 else if (
auto nr = mtrref->to<IR::PathExpression>())
344 mtr = structure->meters.get(nr->path->name);
345 if (mtr ==
nullptr) {
346 ::error(ErrorType::ERR_NOT_FOUND,
"%1%: Cannot find meter", mtrref);
349 auto parent = findContext<IR::ActionFunction>();
350 BUG_CHECK(parent !=
nullptr,
"%1%: not within action", primitive);
351 structure->calledMeters.calls(parent->name, mtr->name.name);
353 }
else if (primitive->name ==
"register_read" || primitive->name ==
"register_write") {
354 const IR::Expression *regref;
355 if (primitive->name ==
"register_read")
356 regref = primitive->operands.at(1);
358 regref = primitive->operands.at(0);
359 const IR::Register *reg =
nullptr;
360 if (
auto gr = regref->to<IR::GlobalRef>())
361 reg = gr->obj->to<IR::Register>();
362 else if (
auto nr = regref->to<IR::PathExpression>())
363 reg = structure->registers.get(nr->path->name);
364 if (reg ==
nullptr) {
365 ::error(ErrorType::ERR_NOT_FOUND,
"%1%: Cannot find register", regref);
368 auto parent = findContext<IR::ActionFunction>();
369 BUG_CHECK(parent !=
nullptr,
"%1%: not within action", primitive);
370 structure->calledRegisters.calls(parent->name, reg->name.name);
372 }
else if (structure->actions.contains(name)) {
373 auto parent = findContext<IR::ActionFunction>();
374 BUG_CHECK(parent !=
nullptr,
"%1%: Action call not within action", primitive);
375 structure->calledActions.calls(parent->name, name);
376 }
else if (structure->controls.contains(name)) {
377 auto parent = findContext<IR::V1Control>();
378 BUG_CHECK(parent !=
nullptr,
"%1%: Control call not within control", primitive);
379 structure->calledControls.calls(parent->name, name);
382 void postorder(
const IR::GlobalRef *gref)
override {
384 if (
auto af = findContext<IR::ActionFunction>()) {
386 }
else if (
auto di = findContext<IR::Declaration_Instance>()) {
389 BUG(
"%1%: GlobalRef not within action or extern", gref);
391 if (
auto ctr = gref->obj->to<IR::Counter>())
392 structure->calledCounters.calls(caller, ctr->name.name);
393 else if (
auto mtr = gref->obj->to<IR::Meter>())
394 structure->calledMeters.calls(caller, mtr->name.name);
395 else if (
auto reg = gref->obj->to<IR::Register>())
396 structure->calledRegisters.calls(caller, reg->name.name);
397 else if (
auto ext = gref->obj->to<IR::Declaration_Instance>())
398 structure->calledExterns.calls(caller, ext->name.name);
410 CHECK_NULL(structure);
411 setName(
"ComputeTableCallGraph");
414 void postorder(
const IR::Apply *apply)
override {
415 LOG3(
"Scanning " << apply->name);
416 auto tbl = structure->tables.get(apply->name.name);
417 if (tbl ==
nullptr) {
418 ::error(ErrorType::ERR_NOT_FOUND,
"%1%: Could not find table", apply->name);
421 auto parent = findContext<IR::V1Control>();
423 ::error(ErrorType::ERR_UNEXPECTED,
"%1%: Apply not within a control block?", apply);
427 auto ctrl = get(structure->tableMapping, tbl);
430 if (!structure->calledControls.isCallee(parent->name) &&
431 parent->name != P4V1::V1Model::instance.ingress.name &&
432 parent->name != P4V1::V1Model::instance.egress.name)
435 if (ctrl !=
nullptr && ctrl != parent) {
436 auto previous = get(structure->tableInvocation, tbl);
437 ::error(ErrorType::ERR_INVALID,
438 "%1%: Table invoked from two different controls: %2% and %3%", tbl, apply,
441 LOG3(
"Invoking " << tbl <<
" in " << parent->name);
442 structure->tableMapping.emplace(tbl, parent);
443 structure->tableInvocation.emplace(tbl, apply);
511 const IR::Type_Header *fixedHeaderType;
513 const IR::Expression *headerLength;
521 IR::IndexedVector<IR::Declaration> varDecls;
523 std::map<cstring, HeaderSplit *> fixedPart;
528 HeaderSplit *splitHeaderType(
const IR::Type_Header *type) {
530 auto fixed = ::get(fixedPart, type->name.name);
531 if (fixed !=
nullptr)
return fixed;
533 const IR::Expression *headerLength =
nullptr;
535 const IR::Type_Header *fixedHeaderType =
nullptr;
536 IR::IndexedVector<IR::StructField> fields;
538 for (
auto f : type->fields) {
539 if (f->type->is<IR::Type_Varbits>()) {
540 cstring hname = structure->makeUniqueName(type->name);
541 if (fixedHeaderType !=
nullptr) {
542 ::error(ErrorType::ERR_INVALID,
543 "%1%: header types with multiple varbit fields are not supported",
547 fixedHeaderType =
new IR::Type_Header(IR::ID(hname), fields);
549 auto anno = f->getAnnotation(IR::Annotation::lengthAnnotation);
550 BUG_CHECK(anno !=
nullptr,
"No length annotation on varbit field", f);
551 BUG_CHECK(anno->expr.size() == 1,
"Expected exactly 1 argument", anno->expr);
552 headerLength = anno->expr.at(0);
555 }
else if (fixedHeaderType ==
nullptr) {
560 if (fixedHeaderType !=
nullptr) {
561 LOG3(
"Extracted fixed-size header type from " << type <<
" into " << fixedHeaderType);
562 fixed =
new HeaderSplit;
563 fixed->fixedHeaderType = fixedHeaderType;
564 fixed->headerLength = headerLength;
565 fixedPart.emplace(type->name.name, fixed);
566 allTypeDecls.push_back(fixedHeaderType);
579 class RewriteLength final :
public Transform {
580 const IR::Type_Header *header;
581 const IR::Declaration *var;
584 explicit RewriteLength(
const IR::Type_Header *header,
const IR::Declaration *var)
585 : header(header), var(var) {
586 setName(
"RewriteLength");
589 const IR::Node *postorder(IR::PathExpression *expression)
override {
590 if (expression->path->absolute)
return expression;
591 for (
auto f : header->fields) {
592 if (f->name == expression->path->name)
593 return new IR::Member(expression->srcInfo,
new IR::PathExpression(var->name),
602 CHECK_NULL(structure);
603 setName(
"FixExtracts");
606 const IR::Node *postorder(IR::P4Program *program)
override {
609 allTypeDecls.append(program->objects);
610 program->objects = allTypeDecls;
614 const IR::Node *postorder(IR::P4Parser *parser)
override {
615 if (!varDecls.empty()) {
616 parser->parserLocals.append(varDecls);
622 const IR::Node *postorder(IR::MethodCallStatement *statement)
override {
623 auto mce = getOriginal<IR::MethodCallStatement>()->methodCall;
624 LOG3(
"Looking up in extracts " << dbp(mce));
625 auto ht = ::get(structure->extractsSynthesized, mce);
631 BUG_CHECK(mce->arguments->size() == 1,
"%1%: expected 1 argument", mce);
632 auto arg = mce->arguments->at(0);
634 auto fixed = splitHeaderType(ht);
635 if (fixed ==
nullptr)
return statement;
636 CHECK_NULL(fixed->headerLength);
637 CHECK_NULL(fixed->fixedHeaderType);
639 auto result =
new IR::IndexedVector<IR::StatOrDecl>();
640 cstring varName = structure->makeUniqueName(
"tmp_hdr");
642 new IR::Declaration_Variable(IR::ID(varName), fixed->fixedHeaderType->to<IR::Type>());
643 varDecls.push_back(var);
646 auto member = mce->method->to<IR::Member>();
649 typeArgs->push_back(fixed->fixedHeaderType->getP4Type());
650 auto lookaheadMethod =
651 new IR::Member(member->expr, P4::P4CoreLibrary::instance().packetIn.lookahead.name);
652 auto lookahead =
new IR::MethodCallExpression(mce->srcInfo, lookaheadMethod, typeArgs,
655 new IR::AssignmentStatement(mce->srcInfo,
new IR::PathExpression(varName), lookahead);
656 result->push_back(assign);
657 LOG3(
"Created lookahead " << assign);
660 RewriteLength rewrite(fixed->fixedHeaderType, var);
661 rewrite.setCalledBy(
this);
662 auto length = fixed->headerLength->apply(rewrite);
664 args->push_back(arg->clone());
665 auto type = IR::Type_Bits::get(P4::P4CoreLibrary::instance().packetIn.extractSecondArgSize);
667 args->push_back(
new IR::Argument(cast));
668 auto expression =
new IR::MethodCallExpression(mce->srcInfo, mce->method->clone(), args);
669 result->push_back(
new IR::MethodCallStatement(expression));
735 bool preorder(
const IR::V1Program *program)
override {
736 auto &map = program->scope;
737 auto firstWithKey = map.begin();
738 while (firstWithKey != map.end()) {
739 auto key = firstWithKey->first;
740 auto range = map.equal_range(key);
741 for (
auto s = range.first; s != range.second; s++) {
743 for (n++; n != range.second; n++) {
746 if (e1->node_type_name() == e2->node_type_name()) {
747 if (e1->srcInfo.getStart().isValid())
748 ::error(ErrorType::ERR_DUPLICATE,
"%1%: same name as %2%", e1, e2);
751 ::error(ErrorType::ERR_INVALID,
"%1% is invalid; name %2% is reserved",
756 firstWithKey = range.second;
790 IR::IndexedVector<IR::ParserState> parserStates;
797 setName(
"InsertCompilerGeneratedStartState");
798 structure->allNames.insert({IR::ParserState::start, 0});
799 structure->allNames.insert({
"InstanceType", 0});
800 newStartState = structure->makeUniqueName(IR::ParserState::start);
801 newInstanceType = structure->makeUniqueName(
"InstanceType");
804 const IR::Node *postorder(IR::P4Program *program)
override {
805 allTypeDecls.append(program->objects);
806 program->objects = allTypeDecls;
811 const IR::Node *postorder(IR::ParserState *state)
override {
812 if (structure->parserEntryPoints.empty())
return state;
813 if (state->name == IR::ParserState::start) {
814 state->name = newStartState;
820 const IR::Node *postorder(IR::Path *path)
override {
821 if (structure->parserEntryPoints.empty())
return path;
825 if (path->name.name != IR::ParserState::start)
return path;
827 auto pe = getContext()->node->to<IR::PathExpression>();
828 auto sc = findContext<IR::SelectCase>();
829 auto ps = findContext<IR::ParserState>();
831 if (pe && ((sc && pe->equiv(*sc->state->to<IR::PathExpression>())) ||
833 (ps && pe->equiv(*ps->selectExpression->to<IR::PathExpression>()))))
834 path->name = newStartState;
838 const IR::Node *postorder(IR::P4Parser *parser)
override {
839 if (structure->parserEntryPoints.empty())
return parser;
840 IR::IndexedVector<IR::SerEnumMember> members;
842 members.push_back(
new IR::SerEnumMember(
"START",
new IR::Constant(0)));
843 selCases.push_back(
new IR::SelectCase(
844 new IR::Member(
new IR::TypeNameExpression(
new IR::Type_Name(newInstanceType)),
"START"),
845 new IR::PathExpression(
new IR::Path(newStartState))));
849 for (
auto p : structure->parserEntryPoints) {
850 members.push_back(
new IR::SerEnumMember(p.first,
new IR::Constant(idx++)));
851 selCases.push_back(
new IR::SelectCase(
852 new IR::Member(
new IR::TypeNameExpression(
new IR::Type_Name(newInstanceType)),
854 new IR::PathExpression(
new IR::Path(p.second->name))));
856 auto instAnnos =
new IR::Annotations();
857 instAnnos->add(
new IR::Annotation(IR::Annotation::nameAnnotation,
".$InstanceType"));
859 new IR::Type_SerEnum(newInstanceType, instAnnos, IR::Type_Bits::get(32), members);
860 allTypeDecls.push_back(instEnum);
864 new IR::Cast(
new IR::Type_Name(newInstanceType),
865 new IR::Member(
new IR::PathExpression(
new IR::Path(
"standard_metadata")),
867 auto selects =
new IR::SelectExpression(
new IR::ListExpression(selExpr), selCases);
868 auto annos =
new IR::Annotations();
869 annos->add(
new IR::Annotation(IR::Annotation::nameAnnotation,
".$start"));
870 auto startState =
new IR::ParserState(IR::ParserState::start, annos, selects);
871 parserStates.push_back(startState);
873 if (!parserStates.empty()) {
874 parser->states.append(parserStates);
875 parserStates.clear();
903 const IR::Type_Struct *stdType =
nullptr;
904 const IR::Type_Struct *userType =
nullptr;
905 const IR::Type_Struct *intrType =
nullptr;
906 const IR::Type_Struct *queueType =
nullptr;
907 const IR::StructField *intrField =
nullptr;
908 const IR::StructField *queueField =
nullptr;
912 CHECK_NULL(structure);
913 setName(
"MoveIntrinsicMetadata");
915 const IR::Node *preorder(IR::P4Program *program)
override {
916 stdType = program->getDeclsByName(structure->v1model.standardMetadataType.name)
918 ->to<IR::Type_Struct>();
919 userType = program->getDeclsByName(structure->v1model.metadataType.name)
921 ->to<IR::Type_Struct>();
923 CHECK_NULL(userType);
924 intrField = userType->getField(structure->v1model.intrinsicMetadata.name);
925 if (intrField !=
nullptr) {
926 auto intrTypeName = intrField->type;
927 auto tn = intrTypeName->to<IR::Type_Name>();
928 BUG_CHECK(tn,
"%1%: expected a Type_Name", intrTypeName);
929 auto nt = program->getDeclsByName(tn->path->name)->nextOrDefault();
930 if (nt ==
nullptr || !nt->is<IR::Type_Struct>()) {
931 ::error(ErrorType::ERR_INVALID,
"%1%: expected a structure", tn);
934 intrType = nt->to<IR::Type_Struct>();
935 LOG2(
"Intrinsic metadata type " << intrType);
938 queueField = userType->getField(structure->v1model.queueingMetadata.name);
939 if (queueField !=
nullptr) {
940 auto queueTypeName = queueField->type;
941 auto tn = queueTypeName->to<IR::Type_Name>();
942 BUG_CHECK(tn,
"%1%: expected a Type_Name", queueTypeName);
943 auto nt = program->getDeclsByName(tn->path->name)->nextOrDefault();
944 if (nt ==
nullptr || !nt->is<IR::Type_Struct>()) {
945 ::error(ErrorType::ERR_INVALID,
"%1%: expected a structure", tn);
948 queueType = nt->to<IR::Type_Struct>();
949 LOG2(
"Queueing metadata type " << queueType);
954 const IR::Node *postorder(IR::Type_Struct *type)
override {
955 if (getOriginal() == stdType) {
956 if (intrType !=
nullptr) {
957 for (
auto f : intrType->fields) {
958 if (type->fields.getDeclaration(f->name) ==
nullptr) {
959 ::error(ErrorType::ERR_NOT_FOUND,
"%1%: no such field in standard_metadata",
961 LOG2(
"standard_metadata: " << type);
965 if (queueType !=
nullptr) {
966 for (
auto f : queueType->fields) {
967 if (type->fields.getDeclaration(f->name) ==
nullptr) {
968 ::error(ErrorType::ERR_NOT_FOUND,
"%1%: no such field in standard_metadata",
970 LOG2(
"standard_metadata: " << type);
978 const IR::Node *postorder(IR::StructField *field)
override {
979 if (getOriginal() == intrField || getOriginal() == queueField)
985 const IR::Node *postorder(IR::Member *member)
override {
989 if (member->member != structure->v1model.intrinsicMetadata.name &&
990 member->member != structure->v1model.queueingMetadata.name)
992 auto pe = member->expr->to<IR::PathExpression>();
993 if (pe ==
nullptr || pe->path->absolute)
return member;
994 if (pe->path->name == structure->v1model.parser.metadataParam.name) {
995 LOG2(
"Renaming reference " << member);
996 return new IR::PathExpression(
new IR::Path(
997 member->expr->srcInfo,
998 IR::ID(pe->path->name.srcInfo, structure->v1model.standardMetadata.name)));
1009 void add(
const IR::Primitive *primitive,
unsigned operand) {
1010 if (primitive->operands.size() <= operand) {
1015 auto expression = primitive->operands.at(operand);
1016 if (!expression->is<IR::PathExpression>()) {
1017 ::error(ErrorType::ERR_EXPECTED,
"%1%: expected a field list", expression);
1020 auto nr = expression->to<IR::PathExpression>();
1021 auto fl = structure->field_lists.get(nr->path->name);
1022 if (fl ==
nullptr) {
1023 ::error(ErrorType::ERR_EXPECTED,
"%1%: Expected a field list", expression);
1026 LOG3(
"Recirculated " << nr->path->name);
1032 CHECK_NULL(structure);
1033 setName(
"FindRecirculated");
1036 void postorder(
const IR::Primitive *primitive)
override {
1037 if (primitive->name ==
"recirculate" || primitive->name ==
"resubmit") {
1039 }
else if (primitive->name.startsWith(
"clone") && primitive->operands.size() == 2) {
Definition programStructure.h:32
Definition converters.h:884