bool ControlConverter::preorder()

in flexsai/p4/backend/json_stage/control.cpp [727:814]


bool ControlConverter::preorder(const IR::ControlBlock* block) {
    auto bt = backend->pipeline_controls.find(block->container->name);
    if (bt == backend->pipeline_controls.end()) {
        return false;
    }

    const IR::P4Control* cont = block->container;
    auto result = new Util::JsonObject();
    auto it = backend->pipeline_namemap.find(block->container->name);
    BUG_CHECK(it != backend->pipeline_namemap.end(),
              "Expected to find %1% in control block name map", block->container->name);
    result->emplace("name", it->second);
    result->emplace("id", nextId("control"));
    result->emplace_non_null("source_info", cont->sourceInfoJsonObj());

    auto cfg = new CFG();
    cfg->build(cont, refMap, typeMap);
    bool success = cfg->checkImplementable();
    if (!success)
        return false;

    if (cfg->entryPoint->successors.size() == 0) {
        result->emplace("init_table", Util::JsonValue::null);
    } else {
        BUG_CHECK(cfg->entryPoint->successors.size() == 1, "Expected 1 start node for %1%", cont);
        auto start = (*(cfg->entryPoint->successors.edges.begin()))->endpoint;
        result->emplace("init_table", nodeName(start));
    }

    auto tables = mkArrayField(result, "tables");
    auto action_profiles = mkArrayField(result, "action_profiles");
    auto conditionals = mkArrayField(result, "conditionals");

    SharedActionSelectorCheck selector_check(refMap, typeMap);
    block->apply(selector_check);

    std::set<const IR::P4Table*> done;

    // Tables are created prior to the other local declarations
    for (auto node : cfg->allNodes) {
        auto tn = node->to<CFG::TableNode>();
        if (tn != nullptr) {
            if (done.find(tn->table) != done.end())
                // The same table may appear in multiple nodes in the CFG.
                // We emit it only once.  Other checks should ensure that
                // the CFG is implementable.
                continue;
            done.emplace(tn->table);
            auto j = convertTable(tn, action_profiles, selector_check);
            if (::errorCount() > 0)
                return false;
            tables->append(j);
        } else if (node->is<CFG::IfNode>()) {
            auto j = convertIf(node->to<CFG::IfNode>(), cont->name);
            if (::errorCount() > 0)
                return false;
            conditionals->append(j);
        }
    }

    // hanw: skip for PSA
    for (auto c : cont->controlLocals) {
        if (c->is<IR::Declaration_Constant>() ||
            c->is<IR::Declaration_Variable>() ||
            c->is<IR::P4Action>() ||
            c->is<IR::P4Table>())
            continue;
        if (c->is<IR::Declaration_Instance>()) {
            auto bl = block->getValue(c);
            CHECK_NULL(bl);
            if (bl->is<IR::ControlBlock>() || bl->is<IR::ParserBlock>())
                // Since this block has not been inlined, it is probably unused
                // So we don't do anything.
                continue;
            if (bl->is<IR::ExternBlock>()) {
                auto eb = bl->to<IR::ExternBlock>();
                std::cout <<"SAI IGNORING extern " << eb->toString() << std::endl;
//                backend->getSaiSwitch()->convertExternInstances(c, eb, action_profiles,
//                                                                   selector_check);
               continue;
            }
        }
        P4C_UNIMPLEMENTED("%1%: not yet handled", c);
    }

    json->pipelines->append(result);
    return false;
}