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(
 
  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(
 
  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 = {{
"standard_metadata_t"_cs, 
"type"_cs},
 
  182                                                 {
"standard_metadata"_cs, 
"metadata"_cs},
 
  183                                                 {
"egress"_cs, 
"control"_cs}};
 
  186        auto it = reserved_names.find(nodeName);
 
  187        if (it == reserved_names.end()) 
return;
 
  188        if (it->second != kind)
 
  189            ::error(ErrorType::ERR_INVALID, 
"%1%: invalid name; it can only be used for %2%", node,
 
  193        checkReserved(node, nodeName, 
nullptr);
 
  198        CHECK_NULL(structure);
 
  199        setName(
"DiscoverStructure");
 
  202    void postorder(
const IR::ParserException *ex)
 override {
 
  203        warn(ErrorType::WARN_UNSUPPORTED, 
"%1%: parser exception is not translated to P4-16", ex);
 
  205    void postorder(
const IR::Metadata *md)
 override {
 
  206        structure->metadata.emplace(md);
 
  207        checkReserved(md, md->name, 
"metadata"_cs);
 
  209    void postorder(
const IR::Header *hd)
 override {
 
  210        structure->headers.emplace(hd);
 
  211        checkReserved(hd, hd->name);
 
  213    void postorder(
const IR::Type_StructLike *t)
 override {
 
  214        structure->types.emplace(t);
 
  215        checkReserved(t, t->name, 
"type"_cs);
 
  217    void postorder(
const IR::V1Control *control)
 override {
 
  218        structure->controls.emplace(control);
 
  219        checkReserved(control, control->name, 
"control"_cs);
 
  221    void postorder(
const IR::V1Parser *parser)
 override {
 
  222        structure->parserStates.emplace(parser);
 
  223        checkReserved(parser, parser->name);
 
  225    void postorder(
const IR::V1Table *table)
 override {
 
  226        structure->tables.emplace(table);
 
  227        checkReserved(table, table->name);
 
  229    void postorder(
const IR::ActionFunction *action)
 override {
 
  230        structure->actions.emplace(action);
 
  231        checkReserved(action, action->name);
 
  233    void postorder(
const IR::HeaderStack *stack)
 override {
 
  234        structure->stacks.emplace(stack);
 
  235        checkReserved(stack, stack->name);
 
  237    void postorder(
const IR::Counter *count)
 override {
 
  238        structure->counters.emplace(count);
 
  239        checkReserved(count, count->name);
 
  241    void postorder(
const IR::Register *reg)
 override {
 
  242        structure->registers.emplace(reg);
 
  243        checkReserved(reg, reg->name);
 
  245    void postorder(
const IR::ActionProfile *ap)
 override {
 
  246        structure->action_profiles.emplace(ap);
 
  247        checkReserved(ap, ap->name);
 
  249    void postorder(
const IR::FieldList *fl)
 override {
 
  250        structure->field_lists.emplace(fl);
 
  251        checkReserved(fl, fl->name);
 
  253    void postorder(
const IR::FieldListCalculation *flc)
 override {
 
  254        structure->field_list_calculations.emplace(flc);
 
  255        checkReserved(flc, flc->name);
 
  257    void postorder(
const IR::CalculatedField *cf)
 override {
 
  258        structure->calculated_fields.push_back(cf);
 
  260    void postorder(
const IR::Meter *m)
 override {
 
  261        structure->meters.emplace(m);
 
  262        checkReserved(m, m->name);
 
  264    void postorder(
const IR::ActionSelector *as)
 override {
 
  265        structure->action_selectors.emplace(as);
 
  266        checkReserved(as, as->name);
 
  268    void postorder(
const IR::Type_Extern *ext)
 override {
 
  269        structure->extern_types.emplace(ext);
 
  270        checkReserved(ext, ext->name);
 
  272    void postorder(
const IR::Declaration_Instance *ext)
 override {
 
  273        structure->externs.emplace(ext);
 
  274        checkReserved(ext, ext->name);
 
  276    void postorder(
const IR::ParserValueSet *pvs)
 override {
 
  277        structure->value_sets.emplace(pvs);
 
  278        checkReserved(pvs, pvs->name);
 
 
  287        CHECK_NULL(structure);
 
  288        setName(
"ComputeCallGraph");
 
  291    void postorder(
const IR::V1Parser *parser)
 override {
 
  292        LOG3(
"Scanning parser " << parser->name);
 
  293        structure->parsers.add(parser->name);
 
  294        if (!parser->default_return.name.isNullOrEmpty())
 
  295            structure->parsers.calls(parser->name, parser->default_return);
 
  296        if (parser->cases != 
nullptr)
 
  297            for (
auto ce : *parser->cases) structure->parsers.calls(parser->name, ce->action.name);
 
  298        for (
auto expr : parser->stmts) {
 
  299            if (expr->is<IR::Primitive>()) {
 
  300                auto primitive = expr->to<IR::Primitive>();
 
  301                if (primitive->name == 
"extract") {
 
  302                    BUG_CHECK(primitive->operands.size() == 1, 
"Expected 1 operand for %1%",
 
  304                    auto dest = primitive->operands.at(0);
 
  305                    LOG3(
"Parser " << parser->name << 
" extracts into " << dest);
 
  306                    structure->extracts[parser->name].push_back(dest);
 
  311    void postorder(
const IR::Primitive *primitive)
 override {
 
  312        auto name = primitive->name;
 
  313        const IR::GlobalRef *glob = 
nullptr;
 
  314        const IR::Declaration_Instance *extrn = 
nullptr;
 
  315        if (!primitive->operands.empty()) glob = primitive->operands[0]->to<IR::GlobalRef>();
 
  316        if (glob) extrn = glob->obj->to<IR::Declaration_Instance>();
 
  319            auto parent = findContext<IR::ActionFunction>();
 
  320            BUG_CHECK(parent != 
nullptr, 
"%1%: Extern call not within action", primitive);
 
  321            structure->calledExterns.calls(parent->name, extrn->name.name);
 
  323        } 
else if (primitive->name == 
"count") {
 
  325            auto ctrref = primitive->operands.at(0);
 
  326            const IR::Counter *ctr = 
nullptr;
 
  327            if (
auto gr = ctrref->to<IR::GlobalRef>())
 
  328                ctr = gr->obj->to<IR::Counter>();
 
  329            else if (
auto nr = ctrref->to<IR::PathExpression>())
 
  330                ctr = structure->counters.get(nr->path->name);
 
  331            if (ctr == 
nullptr) {
 
  332                ::error(ErrorType::ERR_NOT_FOUND, 
"%1%: Cannot find counter", ctrref);
 
  335            auto parent = findContext<IR::ActionFunction>();
 
  336            BUG_CHECK(parent != 
nullptr, 
"%1%: Counter call not within action", primitive);
 
  337            structure->calledCounters.calls(parent->name, ctr->name.name);
 
  339        } 
else if (primitive->name == 
"execute_meter") {
 
  340            auto mtrref = primitive->operands.at(0);
 
  341            const IR::Meter *mtr = 
nullptr;
 
  342            if (
auto gr = mtrref->to<IR::GlobalRef>())
 
  343                mtr = gr->obj->to<IR::Meter>();
 
  344            else if (
auto nr = mtrref->to<IR::PathExpression>())
 
  345                mtr = structure->meters.get(nr->path->name);
 
  346            if (mtr == 
nullptr) {
 
  347                ::error(ErrorType::ERR_NOT_FOUND, 
"%1%: Cannot find meter", mtrref);
 
  350            auto parent = findContext<IR::ActionFunction>();
 
  351            BUG_CHECK(parent != 
nullptr, 
"%1%: not within action", primitive);
 
  352            structure->calledMeters.calls(parent->name, mtr->name.name);
 
  354        } 
else if (primitive->name == 
"register_read" || primitive->name == 
"register_write") {
 
  355            const IR::Expression *regref;
 
  356            if (primitive->name == 
"register_read")
 
  357                regref = primitive->operands.at(1);
 
  359                regref = primitive->operands.at(0);
 
  360            const IR::Register *reg = 
nullptr;
 
  361            if (
auto gr = regref->to<IR::GlobalRef>())
 
  362                reg = gr->obj->to<IR::Register>();
 
  363            else if (
auto nr = regref->to<IR::PathExpression>())
 
  364                reg = structure->registers.get(nr->path->name);
 
  365            if (reg == 
nullptr) {
 
  366                ::error(ErrorType::ERR_NOT_FOUND, 
"%1%: Cannot find register", regref);
 
  369            auto parent = findContext<IR::ActionFunction>();
 
  370            BUG_CHECK(parent != 
nullptr, 
"%1%: not within action", primitive);
 
  371            structure->calledRegisters.calls(parent->name, reg->name.name);
 
  373        } 
else if (structure->actions.contains(name)) {
 
  374            auto parent = findContext<IR::ActionFunction>();
 
  375            BUG_CHECK(parent != 
nullptr, 
"%1%: Action call not within action", primitive);
 
  376            structure->calledActions.calls(parent->name, name);
 
  377        } 
else if (structure->controls.contains(name)) {
 
  378            auto parent = findContext<IR::V1Control>();
 
  379            BUG_CHECK(parent != 
nullptr, 
"%1%: Control call not within control", primitive);
 
  380            structure->calledControls.calls(parent->name, name);
 
  383    void postorder(
const IR::GlobalRef *gref)
 override {
 
  385        if (
auto af = findContext<IR::ActionFunction>()) {
 
  387        } 
else if (
auto di = findContext<IR::Declaration_Instance>()) {
 
  390            BUG(
"%1%: GlobalRef not within action or extern", gref);
 
  392        if (
auto ctr = gref->obj->to<IR::Counter>())
 
  393            structure->calledCounters.calls(caller, ctr->name.name);
 
  394        else if (
auto mtr = gref->obj->to<IR::Meter>())
 
  395            structure->calledMeters.calls(caller, mtr->name.name);
 
  396        else if (
auto reg = gref->obj->to<IR::Register>())
 
  397            structure->calledRegisters.calls(caller, reg->name.name);
 
  398        else if (
auto ext = gref->obj->to<IR::Declaration_Instance>())
 
  399            structure->calledExterns.calls(caller, ext->name.name);
 
 
  411        CHECK_NULL(structure);
 
  412        setName(
"ComputeTableCallGraph");
 
  415    void postorder(
const IR::Apply *apply)
 override {
 
  416        LOG3(
"Scanning " << apply->name);
 
  417        auto tbl = structure->tables.get(apply->name.name);
 
  418        if (tbl == 
nullptr) {
 
  419            ::error(ErrorType::ERR_NOT_FOUND, 
"%1%: Could not find table", apply->name);
 
  422        auto parent = findContext<IR::V1Control>();
 
  424            ::error(ErrorType::ERR_UNEXPECTED, 
"%1%: Apply not within a control block?", apply);
 
  428        auto ctrl = get(structure->tableMapping, tbl);
 
  431        if (!structure->calledControls.isCallee(parent->name) &&
 
  432            parent->name != P4V1::V1Model::instance.ingress.name &&
 
  433            parent->name != P4V1::V1Model::instance.egress.name)
 
  436        if (ctrl != 
nullptr && ctrl != parent) {
 
  437            auto previous = get(structure->tableInvocation, tbl);
 
  438            ::error(ErrorType::ERR_INVALID,
 
  439                    "%1%: Table invoked from two different controls: %2% and %3%", tbl, apply,
 
  442        LOG3(
"Invoking " << tbl << 
" in " << parent->name);
 
  443        structure->tableMapping.emplace(tbl, parent);
 
  444        structure->tableInvocation.emplace(tbl, apply);
 
 
  512        const IR::Type_Header *fixedHeaderType;
 
  514        const IR::Expression *headerLength;
 
  524    std::map<cstring, HeaderSplit *> fixedPart;
 
  529    HeaderSplit *splitHeaderType(
const IR::Type_Header *type) {
 
  531        auto fixed = ::get(fixedPart, type->name.name);
 
  532        if (fixed != 
nullptr) 
return fixed;
 
  534        const IR::Expression *headerLength = 
nullptr;
 
  536        const IR::Type_Header *fixedHeaderType = 
nullptr;
 
  539        for (
auto f : type->fields) {
 
  540            if (f->type->is<IR::Type_Varbits>()) {
 
  541                cstring hname = structure->makeUniqueName(type->name.name);
 
  542                if (fixedHeaderType != 
nullptr) {
 
  543                    ::error(ErrorType::ERR_INVALID,
 
  544                            "%1%: header types with multiple varbit fields are not supported",
 
  548                fixedHeaderType = 
new IR::Type_Header(
IR::ID(hname), fields);
 
  550                auto anno = f->getAnnotation(IR::Annotation::lengthAnnotation);
 
  551                BUG_CHECK(anno != 
nullptr, 
"No length annotation on varbit field", f);
 
  552                BUG_CHECK(anno->expr.size() == 1, 
"Expected exactly 1 argument", anno->expr);
 
  553                headerLength = anno->expr.at(0);
 
  556            } 
else if (fixedHeaderType == 
nullptr) {
 
  561        if (fixedHeaderType != 
nullptr) {
 
  562            LOG3(
"Extracted fixed-size header type from " << type << 
" into " << fixedHeaderType);
 
  563            fixed = 
new HeaderSplit;
 
  564            fixed->fixedHeaderType = fixedHeaderType;
 
  565            fixed->headerLength = headerLength;
 
  566            fixedPart.emplace(type->name.name, fixed);
 
  567            allTypeDecls.push_back(fixedHeaderType);
 
  580    class RewriteLength final : 
public Transform {
 
  581        const IR::Type_Header *header;
 
  582        const IR::Declaration *var;
 
  585        explicit RewriteLength(
const IR::Type_Header *header, 
const IR::Declaration *var)
 
  586            : header(header), var(var) {
 
  587            setName(
"RewriteLength");
 
  590        const IR::Node *postorder(IR::PathExpression *expression)
 override {
 
  591            if (expression->path->absolute) 
return expression;
 
  592            for (
auto f : header->fields) {
 
  593                if (f->name == expression->path->name)
 
  594                    return new IR::Member(expression->srcInfo, 
new IR::PathExpression(var->name),
 
  603        CHECK_NULL(structure);
 
  604        setName(
"FixExtracts");
 
  607    const IR::Node *postorder(IR::P4Program *program)
 override {
 
  610        allTypeDecls.append(program->objects);
 
  611        program->objects = allTypeDecls;
 
  615    const IR::Node *postorder(IR::P4Parser *parser)
 override {
 
  616        if (!varDecls.empty()) {
 
  617            parser->parserLocals.append(varDecls);
 
  623    const IR::Node *postorder(IR::MethodCallStatement *statement)
 override {
 
  624        auto mce = getOriginal<IR::MethodCallStatement>()->methodCall;
 
  625        LOG3(
"Looking up in extracts " << dbp(mce));
 
  626        auto ht = ::get(structure->extractsSynthesized, mce);
 
  632        BUG_CHECK(mce->arguments->size() == 1, 
"%1%: expected 1 argument", mce);
 
  633        auto arg = mce->arguments->at(0);
 
  635        auto fixed = splitHeaderType(ht);
 
  636        if (fixed == 
nullptr) 
return statement;
 
  637        CHECK_NULL(fixed->headerLength);
 
  638        CHECK_NULL(fixed->fixedHeaderType);
 
  641        cstring varName = structure->makeUniqueName(
"tmp_hdr"_cs);
 
  643            new IR::Declaration_Variable(
IR::ID(varName), fixed->fixedHeaderType->to<IR::Type>());
 
  644        varDecls.push_back(var);
 
  647        auto member = mce->method->to<IR::Member>();  
 
  650        typeArgs->push_back(fixed->fixedHeaderType->getP4Type());
 
  651        auto lookaheadMethod =
 
  652            new IR::Member(member->expr, P4::P4CoreLibrary::instance().packetIn.lookahead.name);
 
  653        auto lookahead = 
new IR::MethodCallExpression(mce->srcInfo, lookaheadMethod, typeArgs,
 
  656            new IR::AssignmentStatement(mce->srcInfo, 
new IR::PathExpression(varName), lookahead);
 
  657        result->push_back(assign);
 
  658        LOG3(
"Created lookahead " << assign);
 
  661        RewriteLength rewrite(fixed->fixedHeaderType, var);
 
  662        rewrite.setCalledBy(
this);
 
  663        auto length = fixed->headerLength->apply(rewrite);
 
  665        args->push_back(arg->clone());
 
  666        auto type = IR::Type_Bits::get(P4::P4CoreLibrary::instance().packetIn.extractSecondArgSize);
 
  668        args->push_back(
new IR::Argument(cast));
 
  669        auto expression = 
new IR::MethodCallExpression(mce->srcInfo, mce->method->clone(), args);
 
  670        result->push_back(
new IR::MethodCallStatement(expression));
 
 
  736    bool preorder(
const IR::V1Program *program)
 override {
 
  737        auto &map = program->scope;
 
  738        auto firstWithKey = map.begin();
 
  739        while (firstWithKey != map.end()) {
 
  740            auto key = firstWithKey->first;
 
  741            auto range = map.equal_range(key);
 
  742            for (
auto s = range.first; s != range.second; s++) {
 
  744                for (n++; n != range.second; n++) {
 
  747                    if (e1->node_type_name() == e2->node_type_name()) {
 
  748                        if (e1->srcInfo.getStart().isValid())
 
  749                            ::error(ErrorType::ERR_DUPLICATE, 
"%1%: same name as %2%", e1, e2);
 
  752                            ::error(ErrorType::ERR_INVALID, 
"%1% is invalid; name %2% is reserved",
 
  757            firstWithKey = range.second;
 
 
  798        setName(
"InsertCompilerGeneratedStartState");
 
  799        structure->allNames.insert({IR::ParserState::start, 0});
 
  800        structure->allNames.insert({
"InstanceType"_cs, 0});
 
  801        newStartState = structure->makeUniqueName(IR::ParserState::start);
 
  802        newInstanceType = structure->makeUniqueName(
"InstanceType"_cs);
 
  805    const IR::Node *postorder(IR::P4Program *program)
 override {
 
  806        allTypeDecls.append(program->objects);
 
  807        program->objects = allTypeDecls;
 
  812    const IR::Node *postorder(IR::ParserState *state)
 override {
 
  813        if (structure->parserEntryPoints.empty()) 
return state;
 
  814        if (state->name == IR::ParserState::start) {
 
  815            state->name = newStartState;
 
  821    const IR::Node *postorder(IR::Path *path)
 override {
 
  822        if (structure->parserEntryPoints.empty()) 
return path;
 
  826        if (path->name.name != IR::ParserState::start) 
return path;
 
  828        auto pe = getContext()->node->
to<IR::PathExpression>();
 
  829        auto sc = findContext<IR::SelectCase>();
 
  830        auto ps = findContext<IR::ParserState>();
 
  832        if (pe && ((sc && pe->equiv(*sc->state->to<IR::PathExpression>())) ||
 
  834                   (ps && pe->equiv(*ps->selectExpression->to<IR::PathExpression>()))))
 
  835            path->name = newStartState;
 
  839    const IR::Node *postorder(IR::P4Parser *parser)
 override {
 
  840        if (structure->parserEntryPoints.empty()) 
return parser;
 
  843        members.push_back(
new IR::SerEnumMember(
"START", 
new IR::Constant(0)));
 
  844        selCases.push_back(
new IR::SelectCase(
 
  845            new IR::Member(
new IR::TypeNameExpression(
new IR::Type_Name(newInstanceType)),
 
  847            new IR::PathExpression(
new IR::Path(newStartState))));
 
  851        for (
auto p : structure->parserEntryPoints) {
 
  852            members.push_back(
new IR::SerEnumMember(p.first, 
new IR::Constant(idx++)));
 
  853            selCases.push_back(
new IR::SelectCase(
 
  854                new IR::Member(
new IR::TypeNameExpression(
new IR::Type_Name(newInstanceType)),
 
  856                new IR::PathExpression(
new IR::Path(p.second->name))));
 
  858        auto instAnnos = 
new IR::Annotations();
 
  859        instAnnos->add(
new IR::Annotation(IR::Annotation::nameAnnotation, 
".$InstanceType"_cs));
 
  861            new IR::Type_SerEnum(newInstanceType, instAnnos, IR::Type_Bits::get(32), members);
 
  862        allTypeDecls.push_back(instEnum);
 
  865        selExpr.push_back(
new IR::Cast(
 
  866            new IR::Type_Name(newInstanceType),
 
  867            new IR::Member(
new IR::PathExpression(
new IR::Path(
"standard_metadata"_cs)),
 
  868                           "instance_type"_cs)));
 
  869        auto selects = 
new IR::SelectExpression(
new IR::ListExpression(selExpr), selCases);
 
  870        auto annos = 
new IR::Annotations();
 
  871        annos->add(
new IR::Annotation(IR::Annotation::nameAnnotation, 
".$start"_cs));
 
  872        auto startState = 
new IR::ParserState(IR::ParserState::start, annos, selects);
 
  873        parserStates.push_back(startState);
 
  875        if (!parserStates.empty()) {
 
  876            parser->states.append(parserStates);
 
  877            parserStates.clear();
 
 
  905    const IR::Type_Struct *stdType = 
nullptr;
 
  906    const IR::Type_Struct *userType = 
nullptr;
 
  907    const IR::Type_Struct *intrType = 
nullptr;
 
  908    const IR::Type_Struct *queueType = 
nullptr;
 
  909    const IR::StructField *intrField = 
nullptr;
 
  910    const IR::StructField *queueField = 
nullptr;
 
  914        CHECK_NULL(structure);
 
  915        setName(
"MoveIntrinsicMetadata");
 
  917    const IR::Node *preorder(IR::P4Program *program)
 override {
 
  918        stdType = program->getDeclsByName(structure->v1model.standardMetadataType.name)
 
  920                      ->
to<IR::Type_Struct>();
 
  921        userType = program->getDeclsByName(structure->v1model.metadataType.name)
 
  923                       ->to<IR::Type_Struct>();
 
  925        CHECK_NULL(userType);
 
  926        intrField = userType->getField(structure->v1model.intrinsicMetadata.name);
 
  927        if (intrField != 
nullptr) {
 
  928            auto intrTypeName = intrField->type;
 
  929            auto tn = intrTypeName->to<IR::Type_Name>();
 
  930            BUG_CHECK(tn, 
"%1%: expected a Type_Name", intrTypeName);
 
  931            auto nt = program->getDeclsByName(tn->path->name)->nextOrDefault();
 
  932            if (nt == 
nullptr || !nt->is<IR::Type_Struct>()) {
 
  933                ::error(ErrorType::ERR_INVALID, 
"%1%: expected a structure", tn);
 
  936            intrType = nt->to<IR::Type_Struct>();
 
  937            LOG2(
"Intrinsic metadata type " << intrType);
 
  940        queueField = userType->getField(structure->v1model.queueingMetadata.name);
 
  941        if (queueField != 
nullptr) {
 
  942            auto queueTypeName = queueField->type;
 
  943            auto tn = queueTypeName->to<IR::Type_Name>();
 
  944            BUG_CHECK(tn, 
"%1%: expected a Type_Name", queueTypeName);
 
  945            auto nt = program->getDeclsByName(tn->path->name)->nextOrDefault();
 
  946            if (nt == 
nullptr || !nt->is<IR::Type_Struct>()) {
 
  947                ::error(ErrorType::ERR_INVALID, 
"%1%: expected a structure", tn);
 
  950            queueType = nt->to<IR::Type_Struct>();
 
  951            LOG2(
"Queueing metadata type " << queueType);
 
  956    const IR::Node *postorder(IR::Type_Struct *type)
 override {
 
  957        if (getOriginal() == stdType) {
 
  958            if (intrType != 
nullptr) {
 
  959                for (
auto f : intrType->fields) {
 
  960                    if (type->fields.getDeclaration(f->name) == 
nullptr) {
 
  961                        ::error(ErrorType::ERR_NOT_FOUND, 
"%1%: no such field in standard_metadata",
 
  963                        LOG2(
"standard_metadata: " << type);
 
  967            if (queueType != 
nullptr) {
 
  968                for (
auto f : queueType->fields) {
 
  969                    if (type->fields.getDeclaration(f->name) == 
nullptr) {
 
  970                        ::error(ErrorType::ERR_NOT_FOUND, 
"%1%: no such field in standard_metadata",
 
  972                        LOG2(
"standard_metadata: " << type);
 
  980    const IR::Node *postorder(IR::StructField *field)
 override {
 
  981        if (getOriginal() == intrField || getOriginal() == queueField)
 
  987    const IR::Node *postorder(IR::Member *member)
 override {
 
  991        if (member->member != structure->v1model.intrinsicMetadata.name &&
 
  992            member->member != structure->v1model.queueingMetadata.name)
 
  994        auto pe = member->expr->
to<IR::PathExpression>();
 
  995        if (pe == 
nullptr || pe->path->absolute) 
return member;
 
  996        if (pe->path->name == structure->v1model.parser.metadataParam.name) {
 
  997            LOG2(
"Renaming reference " << member);
 
  998            return new IR::PathExpression(
new IR::Path(
 
  999                member->expr->srcInfo,
 
 1000                IR::ID(pe->path->name.srcInfo, structure->v1model.standardMetadata.name)));
 
 
 1011    void add(
const IR::Primitive *primitive, 
unsigned operand) {
 
 1012        if (primitive->operands.size() <= operand) {
 
 1017        auto expression = primitive->operands.at(operand);
 
 1018        if (!expression->is<IR::PathExpression>()) {
 
 1019            ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected a field list", expression);
 
 1022        auto nr = expression->to<IR::PathExpression>();
 
 1023        auto fl = structure->field_lists.get(nr->path->name);
 
 1024        if (fl == 
nullptr) {
 
 1025            ::error(ErrorType::ERR_EXPECTED, 
"%1%: Expected a field list", expression);
 
 1028        LOG3(
"Recirculated " << nr->path->name);
 
 1034        CHECK_NULL(structure);
 
 1035        setName(
"FindRecirculated");
 
 1038    void postorder(
const IR::Primitive *primitive)
 override {
 
 1039        if (primitive->name == 
"recirculate" || primitive->name == 
"resubmit") {
 
 1041        } 
else if (primitive->name.startsWith(
"clone") && primitive->operands.size() == 2) {
 
 
Definition frontends/p4/fromv1.0/programStructure.h:32
 
Definition converters.h:886