47        auto table = node->table;
 
   48        LOG3(
"Processing " << dbp(table));
 
   50        cstring name = table->controlPlaneName();
 
   51        result->emplace(
"name", name);
 
   52        result->emplace(
"id", nextId(
"tables"_cs));
 
   53        result->emplace_non_null(
"source_info"_cs, table->sourceInfoJsonObj());
 
   54        cstring table_match_type = corelib.exactMatch.name;
 
   55        auto key = table->getKey();
 
   56        auto tkey = mkArrayField(result, 
"key"_cs);
 
   61            for (
auto ke : key->keyElements) {
 
   62                auto expr = ke->expression;
 
   63                auto ket = ctxt->typeMap->getType(expr, 
true);
 
   64                if (!ket->is<IR::Type_Bits>() && !ket->is<IR::Type_Boolean>() &&
 
   65                    !ket->is<IR::Type_Error>())
 
   66                    ::error(ErrorType::ERR_UNSUPPORTED,
 
   67                            "%1%: unsupporded key type %2%. " 
   68                            "Supported key types are be bit<> or boolean, or error.",
 
   71                auto match_type = getKeyMatchType(ke);
 
   79                if (match_type == corelib.lpmMatch.name) count_lpm++;
 
   81                    ::error(ErrorType::ERR_UNSUPPORTED,
 
   82                            "multiple LPM keys in table %1% not supported", table);
 
   83                if (match_type != table_match_type) {
 
   84                    if (match_type == BMV2::MatchImplementation::rangeMatchTypeName)
 
   85                        table_match_type = BMV2::MatchImplementation::rangeMatchTypeName;
 
   86                    if ((match_type == corelib.ternaryMatch.name ||
 
   87                         match_type == BMV2::MatchImplementation::optionalMatchTypeName) &&
 
   88                        table_match_type != BMV2::MatchImplementation::rangeMatchTypeName)
 
   89                        table_match_type = corelib.ternaryMatch.name;
 
   90                    if (match_type == corelib.lpmMatch.name &&
 
   91                        table_match_type == corelib.exactMatch.name)
 
   92                        table_match_type = corelib.lpmMatch.name;
 
   96                if (
auto mexp = expr->to<IR::BAnd>()) {
 
   97                    if (mexp->right->is<IR::Constant>()) {
 
   98                        mask = mexp->right->to<IR::Constant>()->value;
 
  100                    } 
else if (mexp->left->is<IR::Constant>()) {
 
  101                        mask = mexp->left->to<IR::Constant>()->value;
 
  104                        ::error(ErrorType::ERR_EXPECTED, 
"%1% must be a constant", expr);
 
  106                } 
else if (
auto slice = expr->to<IR::Slice>()) {
 
  108                    int h = slice->getH();
 
  109                    int l = slice->getL();
 
  110                    mask = Util::maskFromSlice(h, l);
 
  117                if (match_type == BMV2::MatchImplementation::optionalMatchTypeName) {
 
  118                    keyelement->emplace(
"match_type", corelib.ternaryMatch.name);
 
  120                    keyelement->emplace(
"match_type", match_type);
 
  122                if (
auto na = ke->getAnnotation(IR::Annotation::nameAnnotation)) {
 
  123                    BUG_CHECK(na->expr.size() == 1, 
"%1%: expected 1 name", na);
 
  124                    auto name = na->expr[0]->to<IR::StringLiteral>();
 
  125                    BUG_CHECK(name != 
nullptr, 
"%1%: expected a string", na);
 
  128                    keyelement->emplace(
"name", name->value);
 
  134                    keyelement->emplace(
"mask",
 
  135                                        stringRepr(mask, ROUNDUP(expr->type->width_bits(), 8)));
 
  137                    keyelement->emplace(
"mask", Util::JsonValue::null);
 
  138                tkey->append(keyelement);
 
  141        LOG3(
"table_match_type: " << table_match_type);
 
  142        result->emplace(
"match_type", table_match_type);
 
  146        auto impl = table->properties->getProperty(propertyName);
 
  150        auto sz = table->properties->getProperty(
"size");
 
  152            if (sz->value->is<IR::ExpressionValue>()) {
 
  153                auto expr = sz->value->to<IR::ExpressionValue>()->expression;
 
  154                if (!expr->is<IR::Constant>()) {
 
  155                    ::error(ErrorType::ERR_EXPECTED, 
"%1% must be a constant", sz);
 
  158                    size = expr->to<IR::Constant>()->asInt();
 
  161                ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected a number", sz);
 
  164        if (
auto entries = table->getEntries()) {
 
  165            size = entries->entries.size();
 
  167        if (size == 0) size = BMV2::TableAttributes::defaultTableSize;
 
  169        result->emplace(
"max_size", size);
 
  170        auto ctrs = table->properties->getProperty(
"counters");
 
  171        if (ctrs != 
nullptr) {
 
  175            if (ctrs->value->is<IR::ExpressionValue>()) {
 
  176                auto expr = ctrs->value->to<IR::ExpressionValue>()->expression;
 
  177                if (expr->is<IR::ConstructorCallExpression>()) {
 
  178                    auto type = ctxt->typeMap->getType(expr, 
true);
 
  179                    if (type == 
nullptr) 
return result;
 
  180                    if (!type->is<IR::Type_Extern>()) {
 
  181                        ::error(ErrorType::ERR_UNEXPECTED,
 
  182                                "%1%: Unexpected type %2% for property. " 
  187                    auto te = type->to<IR::Type_Extern>();
 
  188                    if (te->name != 
"direct_counter" && te->name != 
"counter") {
 
  189                        ::error(ErrorType::ERR_UNEXPECTED,
 
  190                                "%1%: Unexpected type %2% for property. " 
  191                                "Must be 'counter' or 'direct_counter'.",
 
  196                    cstring ctrname = ctrs->controlPlaneName(
"counter"_cs);
 
  197                    jctr->emplace(
"name", ctrname);
 
  198                    jctr->emplace(
"id", nextId(
"counter_arrays"_cs));
 
  199                    jctr->emplace_non_null(
"source_info"_cs, ctrs->sourceInfoJsonObj());
 
  202                    bool direct = te->name == 
"direct_counter";
 
  203                    jctr->emplace(
"is_direct", direct);
 
  204                    jctr->emplace(
"binding", table->controlPlaneName());
 
  205                    ctxt->
json->counters->append(jctr);
 
  206                } 
else if (expr->is<IR::PathExpression>()) {
 
  207                    auto pe = expr->
to<IR::PathExpression>();
 
  209                    if (!decl->is<IR::Declaration_Instance>()) {
 
  210                        ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected an instance",
 
  214                    cstring ctrname = decl->controlPlaneName();
 
  216                    LOG3(
"Looking up " << ctrname);
 
  218                        ::error(ErrorType::ERR_INVALID,
 
  219                                "%1%: Direct counters cannot be attached to multiple tables" 
  221                                decl, it->second, table);
 
  226                    ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected a counter", ctrs);
 
  229            result->emplace(
"with_counters", 
true);
 
  231            result->emplace(
"with_counters", 
false);
 
  235        auto timeout = table->properties->getProperty(
"support_timeout");
 
  236        if (timeout != 
nullptr) {
 
  237            if (timeout->value->is<IR::ExpressionValue>()) {
 
  238                auto expr = timeout->value->to<IR::ExpressionValue>()->expression;
 
  239                if (!expr->is<IR::BoolLiteral>()) {
 
  240                    ::error(ErrorType::ERR_EXPECTED, 
"%1%: must true/false", timeout);
 
  242                    sup_to = expr->to<IR::BoolLiteral>()->value;
 
  245                ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected a Boolean", timeout);
 
  248        result->emplace(
"support_timeout", sup_to);
 
  250        auto dm = table->properties->getProperty(
"meters");
 
  252            if (dm->value->is<IR::ExpressionValue>()) {
 
  253                auto expr = dm->value->to<IR::ExpressionValue>()->expression;
 
  254                if (!expr->is<IR::PathExpression>()) {
 
  255                    ::error(ErrorType::ERR_EXPECTED,
 
  256                            "%1%: expected a reference to a meter declaration", expr);
 
  258                    auto pe = expr->to<IR::PathExpression>();
 
  260                    auto type = ctxt->typeMap->getType(expr, 
true);
 
  261                    if (type == 
nullptr) 
return result;
 
  262                    if (type->is<IR::Type_SpecializedCanonical>())
 
  263                        type = type->to<IR::Type_SpecializedCanonical>()->baseType;
 
  264                    if (!type->is<IR::Type_Extern>()) {
 
  265                        ::error(ErrorType::ERR_UNEXPECTED, 
"%1%: Unexpected type %2% for property",
 
  269                    auto te = type->to<IR::Type_Extern>();
 
  270                    if (te->name != 
"direct_meter") {
 
  271                        ::error(ErrorType::ERR_UNEXPECTED, 
"%1%: Unexpected type %2% for property",
 
  275                    if (!decl->is<IR::Declaration_Instance>()) {
 
  276                        ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected an instance",
 
  282                    BUG_CHECK(decl->is<IR::Declaration_Instance>(), 
"%1%: expected an instance",
 
  284                    cstring name = decl->controlPlaneName();
 
  285                    result->emplace(
"direct_meters", name);
 
  288                ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected a meter", dm);
 
  291            result->emplace(
"direct_meters", Util::JsonValue::null);
 
  294        auto action_ids = mkArrayField(result, 
"action_ids"_cs);
 
  295        auto actions = mkArrayField(result, 
"actions"_cs);
 
  296        auto al = table->getActionList();
 
  298        std::map<cstring, cstring> useActionName;
 
  299        for (
auto a : al->actionList) {
 
  300            if (a->expression->is<IR::MethodCallExpression>()) {
 
  301                auto mce = a->expression->to<IR::MethodCallExpression>();
 
  302                if (mce->arguments->size() > 0)
 
  303                    ::error(ErrorType::ERR_UNSUPPORTED,
 
  304                            "%1%: actions in action list with arguments not supported", a);
 
  307            BUG_CHECK(decl->is<IR::P4Action>(), 
"%1%: should be an action name", a);
 
  308            auto action = decl->to<IR::P4Action>();
 
  309            unsigned id = get(ctxt->
structure->
ids, action, INVALID_ACTION_ID);
 
  310            LOG3(
"look up id " << action << 
" " << 
id);
 
  311            BUG_CHECK(
id != INVALID_ACTION_ID, 
"Could not find id for %1%", action);
 
  312            action_ids->append(
id);
 
  313            auto name = action->controlPlaneName();
 
  314            actions->append(name);
 
  315            useActionName.emplace(action->name, name);
 
  321        CFG::Node *defaultLabelDestination = 
nullptr;  
 
  323        bool hitMiss = 
false;
 
  324        for (
auto s : node->successors.edges) {
 
  325            if (s->isUnconditional()) {
 
  326                nextDestination = s->endpoint;
 
  327                LOG3(
"nextDestination " << s->endpoint);
 
  328            } 
else if (s->isBool()) {
 
  331            } 
else if (s->label == 
"default") {
 
  332                defaultLabelDestination = s->endpoint;
 
  333                LOG3(
"default " << s->endpoint);
 
  339            BUG_CHECK(nextDestination, 
"Could not find default destination for %1%",
 
  341            nextLabel = nodeName(nextDestination);
 
  342            result->emplace(
"base_default_next", nextLabel);
 
  345            if (defaultLabelDestination != 
nullptr) nextLabel = nodeName(defaultLabelDestination);
 
  347            result->emplace(
"base_default_next", Util::JsonValue::null);
 
  350        std::set<cstring> labelsDone;
 
  351        for (
auto s : node->successors.edges) {
 
  354                label = s->getBool() ? 
"__HIT__"_cs : 
"__MISS__"_cs;
 
  355            } 
else if (s->isUnconditional()) {
 
  359                if (label == 
"default") 
continue;
 
  360                label = ::get(useActionName, label);
 
  362            next_tables->emplace(label, nodeName(s->endpoint));
 
  363            labelsDone.emplace(label);
 
  369            for (
auto a : al->actionList) {
 
  370                cstring name = a->getName().name;
 
  371                cstring label = ::get(useActionName, name);
 
  372                if (labelsDone.find(label) == labelsDone.end())
 
  373                    next_tables->emplace(label, nextLabel);
 
  377        result->emplace(
"next_tables", next_tables);
 
  379            table->properties->getProperty(IR::TableProperties::defaultActionPropertyName);
 
  380        if (defact != 
nullptr) {
 
  382                ::warning(ErrorType::WARN_UNSUPPORTED,
 
  383                          "Target does not support default_action for %1% (due to action profiles)",
 
  388            if (!defact->value->is<IR::ExpressionValue>()) {
 
  389                ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected an action", defact);
 
  392            auto expr = defact->value->to<IR::ExpressionValue>()->expression;
 
  393            const IR::P4Action *action = 
nullptr;
 
  396            if (expr->is<IR::PathExpression>()) {
 
  397                auto path = expr->
to<IR::PathExpression>()->path;
 
  399                BUG_CHECK(decl->is<IR::P4Action>(), 
"%1%: should be an action name", expr);
 
  400                action = decl->to<IR::P4Action>();
 
  401            } 
else if (expr->is<IR::MethodCallExpression>()) {
 
  402                auto mce = expr->to<IR::MethodCallExpression>();
 
  404                BUG_CHECK(mi->is<
P4::ActionCall>(), 
"%1%: expected an action", expr);
 
  406                args = mce->arguments;
 
  408                BUG(
"%1%: unexpected expression", expr);
 
  411            unsigned actionid = get(ctxt->
structure->
ids, action, INVALID_ACTION_ID);
 
  412            BUG_CHECK(actionid != INVALID_ACTION_ID, 
"Could not find id for %1%", action);
 
  414            entry->emplace(
"action_id", actionid);
 
  415            entry->emplace(
"action_const", defact->isConstant);
 
  416            auto fields = mkArrayField(entry, 
"action_data"_cs);
 
  417            if (args != 
nullptr) {
 
  419                for (
auto a : *args) {
 
  420                    if (a->expression->is<IR::Constant>()) {
 
  421                        cstring repr = stringRepr(a->expression->to<IR::Constant>()->value);
 
  422                        fields->append(repr);
 
  424                        ::error(ErrorType::ERR_EXPECTED,
 
  425                                "%1%: argument must evaluate to a constant integer", a);
 
  430            entry->emplace(
"action_entry_const", defact->isConstant);
 
  431            result->emplace(
"default_entry", entry);
 
  433        convertTableEntries(table, result);
 
  436    void convertTableEntries(
const IR::P4Table *table, 
Util::JsonObject *jsonTable) {
 
  437        auto entriesList = table->getEntries();
 
  438        if (entriesList == 
nullptr) 
return;
 
  440        auto entries = mkArrayField(jsonTable, 
"entries"_cs);
 
  441        int entryPriority = 1;  
 
  442        for (
auto e : entriesList->entries) {
 
  444            entry->emplace_non_null(
"source_info"_cs, e->sourceInfoJsonObj());
 
  446            auto keyset = e->getKeys();
 
  447            auto matchKeys = mkArrayField(entry, 
"match_key"_cs);
 
  449            for (
auto k : keyset->components) {
 
  451                auto tableKey = table->getKey()->keyElements.at(keyIndex);
 
  452                auto keyWidth = tableKey->expression->type->width_bits();
 
  453                auto k8 = ROUNDUP(keyWidth, 8);
 
  454                auto matchType = getKeyMatchType(tableKey);
 
  458                if (matchType == 
"optional") {
 
  459                    key->emplace(
"match_type", 
"ternary");
 
  461                    key->emplace(
"match_type", matchType);
 
  463                if (matchType == corelib.exactMatch.name) {
 
  464                    if (k->is<IR::Constant>())
 
  465                        key->emplace(
"key", stringRepr(k->to<IR::Constant>()->value, k8));
 
  466                    else if (k->is<IR::BoolLiteral>())
 
  469                                     stringRepr(k->to<IR::BoolLiteral>()->value ? 1 : 0, k8));
 
  471                        ::error(ErrorType::ERR_UNSUPPORTED, 
"%1%: unsupported exact key expression",
 
  473                } 
else if (matchType == corelib.ternaryMatch.name) {
 
  474                    if (k->is<IR::Mask>()) {
 
  475                        auto km = k->to<IR::Mask>();
 
  476                        key->emplace(
"key", stringRepr(km->left->to<IR::Constant>()->value, k8));
 
  477                        key->emplace(
"mask", stringRepr(km->right->to<IR::Constant>()->value, k8));
 
  478                    } 
else if (k->is<IR::Constant>()) {
 
  479                        key->emplace(
"key", stringRepr(k->to<IR::Constant>()->value, k8));
 
  480                        key->emplace(
"mask", stringRepr(Util::mask(keyWidth), k8));
 
  481                    } 
else if (k->is<IR::DefaultExpression>()) {
 
  482                        key->emplace(
"key", stringRepr(0, k8));
 
  483                        key->emplace(
"mask", stringRepr(0, k8));
 
  485                        ::error(ErrorType::ERR_UNSUPPORTED,
 
  486                                "%1%: unsupported ternary key expression", k);
 
  488                } 
else if (matchType == corelib.lpmMatch.name) {
 
  489                    if (k->is<IR::Mask>()) {
 
  490                        auto km = k->to<IR::Mask>();
 
  491                        key->emplace(
"key", stringRepr(km->left->to<IR::Constant>()->value, k8));
 
  492                        auto trailing_zeros = [](
unsigned long n, 
unsigned long keyWidth) {
 
  493                            return n ? __builtin_ctzl(n) : 
static_cast<int>(keyWidth);
 
  495                        auto count_ones = [](
unsigned long n) {
 
  496                            return n ? __builtin_popcountl(n) : 0;
 
  499                            static_cast<unsigned long>(km->right->to<IR::Constant>()->value);
 
  500                        auto len = trailing_zeros(mask, keyWidth);
 
  501                        if (len + count_ones(mask) != keyWidth)  
 
  502                            ::error(ErrorType::ERR_INVALID, 
"%1%: invalid mask for LPM key", k);
 
  504                            key->emplace(
"prefix_length", keyWidth - len);
 
  505                    } 
else if (k->is<IR::Constant>()) {
 
  506                        key->emplace(
"key", stringRepr(k->to<IR::Constant>()->value, k8));
 
  507                        key->emplace(
"prefix_length", keyWidth);
 
  508                    } 
else if (k->is<IR::DefaultExpression>()) {
 
  509                        key->emplace(
"key", stringRepr(0, k8));
 
  510                        key->emplace(
"prefix_length", 0);
 
  512                        ::error(ErrorType::ERR_UNSUPPORTED, 
"%1%: unsupported LPM key expression",
 
  515                } 
else if (matchType == 
"range") {
 
  516                    if (k->is<IR::Range>()) {
 
  517                        auto kr = k->to<IR::Range>();
 
  518                        key->emplace(
"start", stringRepr(kr->left->to<IR::Constant>()->value, k8));
 
  519                        key->emplace(
"end", stringRepr(kr->right->to<IR::Constant>()->value, k8));
 
  520                    } 
else if (k->is<IR::Constant>()) {
 
  521                        key->emplace(
"start", stringRepr(k->to<IR::Constant>()->value, k8));
 
  522                        key->emplace(
"end", stringRepr(k->to<IR::Constant>()->value, k8));
 
  523                    } 
else if (k->is<IR::DefaultExpression>()) {
 
  524                        key->emplace(
"start", stringRepr(0, k8));
 
  525                        key->emplace(
"end", stringRepr((1 << keyWidth) - 1, k8));  
 
  527                        ::error(ErrorType::ERR_UNSUPPORTED, 
"%1% unsupported range key expression",
 
  530                } 
else if (matchType == 
"optional") {
 
  538                    if (k->is<IR::Constant>()) {
 
  539                        key->emplace(
"key", stringRepr(k->to<IR::Constant>()->value, k8));
 
  540                        key->emplace(
"mask", stringRepr(Util::mask(keyWidth), k8));
 
  541                    } 
else if (k->is<IR::DefaultExpression>()) {
 
  542                        key->emplace(
"key", stringRepr(0, k8));
 
  543                        key->emplace(
"mask", stringRepr(0, k8));
 
  545                        ::error(ErrorType::ERR_UNSUPPORTED,
 
  546                                "%1%: unsupported optional key expression", k);
 
  549                    ::error(ErrorType::ERR_UNKNOWN, 
"unknown key match type '%2%' for key %1%", k,
 
  552                matchKeys->append(key);
 
  557            auto actionRef = e->getAction();
 
  558            if (!actionRef->is<IR::MethodCallExpression>())
 
  559                ::error(ErrorType::ERR_INVALID, 
"Invalid action '%1%' in entries list.", actionRef);
 
  560            auto actionCall = actionRef->to<IR::MethodCallExpression>();
 
  561            auto method = actionCall->method->to<IR::PathExpression>()->path;
 
  563            auto actionDecl = decl->
to<IR::P4Action>();
 
  564            unsigned id = get(ctxt->
structure->
ids, actionDecl, INVALID_ACTION_ID);
 
  565            BUG_CHECK(
id != INVALID_ACTION_ID, 
"Could not find id for %1%", actionDecl);
 
  566            action->emplace(
"action_id", 
id);
 
  567            auto actionData = mkArrayField(action, 
"action_data"_cs);
 
  568            for (
auto arg : *actionCall->arguments) {
 
  569                actionData->append(stringRepr(arg->expression->to<IR::Constant>()->value, 0));
 
  571            entry->emplace(
"action_entry", action);
 
  573            auto priorityAnnotation = e->getAnnotation(
"priority"_cs);
 
  574            if (priorityAnnotation != 
nullptr) {
 
  575                if (priorityAnnotation->expr.size() > 1)
 
  576                    ::error(ErrorType::ERR_INVALID, 
"Invalid priority value %1%",
 
  577                            priorityAnnotation->expr);
 
  578                auto priValue = priorityAnnotation->expr.front();
 
  579                if (!priValue->is<IR::Constant>())
 
  580                    ::error(ErrorType::ERR_INVALID, 
"Invalid priority value %1%; must be constant.",
 
  581                            priorityAnnotation->expr);
 
  582                entry->emplace(
"priority", priValue->to<IR::Constant>()->value);
 
  584                entry->emplace(
"priority", entryPriority);
 
  588            entries->append(entry);
 
  591    cstring getKeyMatchType(
const IR::KeyElement *ke) {
 
  592        auto path = ke->matchType->path;
 
  594        BUG_CHECK(mt != 
nullptr, 
"%1%: could not find declaration", ke->matchType);
 
  596        if (mt->name.name == corelib.exactMatch.name ||
 
  597            mt->name.name == corelib.ternaryMatch.name || mt->name.name == corelib.lpmMatch.name ||
 
  599            return mt->name.name;
 
  602        ::error(ErrorType::ERR_UNSUPPORTED, 
"%1%: match type not supported on this target", mt);
 
  609        if (implementation == 
nullptr) {
 
  610            table->emplace(
"type", 
"simple");
 
  614        if (!implementation->value->is<IR::ExpressionValue>()) {
 
  615            ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected expression for property",
 
  619        auto propv = implementation->value->to<IR::ExpressionValue>();
 
  621        bool isSimpleTable = 
true;
 
  625        if (propv->expression->is<IR::ConstructorCallExpression>()) {
 
  627                P4::ConstructorCall::resolve(propv->expression->to<IR::ConstructorCallExpression>(),
 
  628                                             ctxt->
refMap, ctxt->typeMap);
 
  630                ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected extern object for property",
 
  635            auto implementationType = ecc->type;
 
  636            auto arguments = ecc->cce->arguments;
 
  637            apname = implementation->controlPlaneName(ctxt->
refMap->
newName(
"action_profile"));
 
  639            action_profiles->append(action_profile);
 
  640            action_profile->emplace(
"name", apname);
 
  641            action_profile->emplace(
"id", nextId(
"action_profiles"_cs));
 
  642            action_profile->emplace_non_null(
"source_info"_cs,
 
  643                                             propv->expression->sourceInfoJsonObj());
 
  647            auto add_size = [&action_profile, &arguments](
size_t arg_index) {
 
  648                auto size_expr = arguments->at(arg_index)->expression;
 
  650                if (!size_expr->is<IR::Constant>()) {
 
  651                    ::error(ErrorType::ERR_EXPECTED, 
"%1% must be a constant", size_expr);
 
  654                    size = size_expr->to<IR::Constant>()->asInt();
 
  656                action_profile->emplace(
"max_size", size);
 
  660            if (implementationType->name == actionSelectorName) {
 
  661                BUG_CHECK(arguments->size() == 3, 
"%1%: expected 3 arguments", arguments);
 
  662                isSimpleTable = 
false;
 
  664                table->emplace(
"type", 
"indirect_ws");
 
  665                action_profile->emplace(
"selector"_cs, selector);
 
  667                auto hash = arguments->at(0)->expression;
 
  670                    ::error(ErrorType::ERR_EXPECTED, 
"%1%: hash must be a constant on this target",
 
  674                    selector->emplace(
"algo", algo);
 
  676                auto input = mkArrayField(selector, 
"input"_cs);
 
  677                for (
auto ke : key->keyElements) {
 
  679                                  ->
to<IR::Declaration_ID>();
 
  680                    BUG_CHECK(mt != 
nullptr, 
"%1%: could not find declaration", ke->matchType);
 
  683                    auto expr = ke->expression;
 
  687            } 
else if (implementationType->name ==
 
  689                isSimpleTable = 
false;
 
  690                table->emplace(
"type", 
"indirect");
 
  693                ::error(ErrorType::ERR_UNEXPECTED, 
"%1%: expected value for property", propv);
 
  695        } 
else if (propv->expression->is<IR::PathExpression>()) {
 
  696            auto pathe = propv->expression->to<IR::PathExpression>();
 
  698            if (!decl->is<IR::Declaration_Instance>()) {
 
  699                ::error(ErrorType::ERR_EXPECTED, 
"%1%: expected a reference to an instance", pathe);
 
  702            apname = decl->controlPlaneName();
 
  703            auto dcltype = ctxt->typeMap->getType(pathe, 
true);
 
  704            if (!dcltype->is<IR::Type_Extern>()) {
 
  705                ::error(ErrorType::ERR_UNEXPECTED, 
"%1%: unexpected type for implementation",
 
  709            auto type_extern_name = dcltype->to<IR::Type_Extern>()->name;
 
  712            if (type_extern_name == actionProfileName) {
 
  713                table->emplace(
"type", 
"indirect");
 
  714            } 
else if (type_extern_name == actionSelectorName) {
 
  715                table->emplace(
"type", 
"indirect_ws");
 
  717                ::error(ErrorType::ERR_UNEXPECTED, 
"%1%: unexpected type for implementation",
 
  721            isSimpleTable = 
false;
 
  722            if (ctxt->toplevel->hasValue(decl->getNode())) {
 
  723                auto eb = ctxt->toplevel->getValue(decl->getNode());
 
  724                BUG_CHECK(eb->is<IR::ExternBlock>(), 
"Not an extern block?");
 
  725                ExternConverter::cvtExternInstance(ctxt, decl->to<IR::Declaration>(),
 
  726                                                   eb->to<IR::ExternBlock>(), emitExterns);
 
  729            ::error(ErrorType::ERR_UNEXPECTED, 
"%1%: unexpected value for property", propv);
 
  732        table->emplace(
"action_profile", apname);
 
  733        return isSimpleTable;
 
 
  739        result->emplace(
"name", node->name);
 
  740        result->emplace(
"id", nextId(
"conditionals"_cs));
 
  741        result->emplace_non_null(
"source_info"_cs, node->statement->condition->sourceInfoJsonObj());
 
  742        auto j = ctxt->
conv->
convert(node->statement->condition, 
true, 
false);
 
  744        result->emplace(
"expression"_cs, j);
 
  745        for (
auto e : node->successors.edges) {
 
  747            cstring label = Util::toString(e->getBool());
 
  749            result->emplace(label, dest);
 
  755    const bool emitExterns;
 
  756    bool preorder(
const IR::P4Control *cont)
 override {
 
  759        result->emplace(
"name", name);
 
  760        result->emplace(
"id", nextId(
"control"_cs));
 
  761        result->emplace_non_null(
"source_info"_cs, cont->sourceInfoJsonObj());
 
  763        auto cfg = 
new CFG();
 
  764        cfg->build(cont, ctxt->
refMap, ctxt->typeMap);
 
  765        bool success = cfg->checkImplementable();
 
  766        if (!success) 
return false;
 
  768        if (cfg->entryPoint->successors.size() == 0) {
 
  769            result->emplace(
"init_table", Util::JsonValue::null);
 
  771            BUG_CHECK(cfg->entryPoint->successors.size() == 1, 
"Expected 1 start node for %1%",
 
  773            auto start = (*(cfg->entryPoint->successors.edges.begin()))->endpoint;
 
  774            result->emplace(
"init_table", nodeName(start));
 
  777        auto tables = mkArrayField(result, 
"tables"_cs);
 
  778        auto action_profiles = mkArrayField(result, 
"action_profiles"_cs);
 
  779        auto conditionals = mkArrayField(result, 
"conditionals"_cs);
 
  783        cont->apply(*selector_check);
 
  785        std::set<const IR::P4Table *> done;
 
  788        for (
auto node : cfg->allNodes) {
 
  789            auto tn = node->
to<CFG::TableNode>();
 
  791                if (done.find(tn->table) != done.end())
 
  796                done.emplace(tn->table);
 
  797                auto j = convertTable(tn, action_profiles, selector_check);
 
  798                if (::errorCount() > 0) 
return false;
 
  800            } 
else if (node->
is<CFG::IfNode>()) {
 
  801                auto j = convertIf(node->
to<CFG::IfNode>(), cont->name);
 
  802                if (::errorCount() > 0) 
return false;
 
  803                conditionals->append(j);
 
  807        for (
auto c : cont->controlLocals) {
 
  808            if (c->is<IR::Declaration_Constant>() || c->is<IR::Declaration_Variable>() ||
 
  809                c->is<IR::P4Action>() || c->is<IR::P4Table>())
 
  811            if (c->is<IR::Declaration_Instance>()) {
 
  814                if (bl->is<IR::ControlBlock>() || bl->is<IR::ParserBlock>())
 
  818                if (bl->is<IR::ExternBlock>()) {
 
  819                    auto eb = bl->to<IR::ExternBlock>();
 
  820                    ExternConverter::cvtExternInstance(ctxt, c, eb, emitExterns);
 
  824            P4C_UNIMPLEMENTED(
"%1%: not yet handled", c);
 
  827        ctxt->
json->pipelines->append(result);
 
  831    explicit ControlConverter(ConversionContext *ctxt, 
cstring name, 
const bool &emitExterns_)
 
  834          corelib(
P4::P4CoreLibrary::instance()),
 
  835          emitExterns(emitExterns_) {
 
  836        setName(
"ControlConverter");