345 std::map<const IR::BFN::ParserState *, ordered_set<const IR::BFN::InputBufferRVal *>>
348 std::map<const IR::BFN::InputBufferRVal *, ordered_set<const IR::Expression *>>
353 std::map<const IR::BFN::ParserState *, ordered_set<const PHV::Field *>>
354 state_to_inp_buff_exts;
358 std::map<const IR::BFN::ParserState *, ordered_set<const PHV::Field *>> state_to_const_exts;
362 std::map<const IR::BFN::ParserState *, ordered_set<const PHV::Field *>> state_to_other_exts;
365 state_to_rvals.clear();
366 rval_to_lvals.clear();
367 state_to_inp_buff_exts.clear();
368 state_to_const_exts.clear();
369 state_to_other_exts.clear();
370 return ParserInspector::init_apply(root);
375 bool preorder(
const IR::BFN::Extract *extract)
override {
376 auto state = findContext<IR::BFN::ParserState>();
378 auto f = phv.field(extract->dest->field, &bits);
380 if (
auto rval = extract->source->to<IR::BFN::InputBufferRVal>()) {
381 state_to_rvals[state].insert(rval);
382 rval_to_lvals[rval].insert(extract->dest->field);
383 state_to_inp_buff_exts[state].insert(f);
385 LOG4(state->name <<
" " << rval <<
" -> " << extract->dest->field);
386 }
else if (extract->source->is<IR::BFN::ConstantRVal>()) {
387 state_to_const_exts[state].insert(f);
388 LOG4(state->name <<
" constant -> " << extract->dest->field);
390 state_to_other_exts[state].insert(f);
391 LOG4(state->name <<
" other -> " << extract->dest->field);
407 : phv(phv), parser_info(pi), defs(d), parser_use_def(parser_use_def) {}
410 parser_use_def.clear();
411 return ParserInspector::init_apply(root);
418 const IR::BFN::ParserState *state,
422 if ((defs.state_to_inp_buff_exts.count(state) &&
423 defs.state_to_inp_buff_exts.at(state).count(saved)) ||
424 (defs.state_to_other_exts.count(state) &&
425 defs.state_to_other_exts.at(state).count(saved))) {
426 LOG6(
"State " << state->name <<
" extracts " << saved->
name
427 <<
" from input buffer or other field");
431 }
else if (defs.state_to_const_exts.count(state) &&
432 defs.state_to_const_exts.at(state).count(saved)) {
433 LOG6(
"State " << state->name <<
" extracts " << saved->
name <<
" from a constant");
438 if (!graph.predecessors().count(state)) {
445 LOG6(
"State " << state->name <<
" is the start state/entry point");
448 LOG6(
"State " << state->name <<
" does not extract " << saved->
name
449 <<
", checking predecessors");
450 for (
auto const pred : graph.predecessors().at(state)) {
451 if (!is_source_extracted_on_each_path_to_state(graph, pred, saved)) {
452 LOG6(
"State's " << state->name <<
" predecessor " << pred->name
453 <<
" does not have " << saved->
name
454 <<
" defined on all paths");
458 LOG6(
"State " << state->name <<
" has " << saved->
name <<
" defined on all paths");
464 const IR::BFN::InputBufferRVal *rval) {
465 if (rval->range.lo >= 0) {
471 std::vector<std::pair<const IR::BFN::ParserState *, const IR::BFN::InputBufferRVal *>>
472 defer_defs_to_children(
const IR::BFN::InputBufferRVal *rval,
474 const IR::BFN::ParserState *use_state,
475 const IR::BFN::ParserState *def_state,
const PHV::Field *field,
478 if (def_state == use_state)
return {};
481 auto def_rval = rval->clone();
482 if (saved_bits.
size() != field_bits.
size()) {
483 auto nw_f_bits = field_bits.
toOrder<Endian::Network>(field->
size);
484 auto nw_s_bits = saved_bits.
toOrder<Endian::Network>(saved->
size);
486 auto full_rval = rval->clone();
487 full_rval->range.lo -= nw_f_bits.lo;
488 full_rval->range.hi += field->
size - nw_f_bits.hi + 1;
490 def_rval = full_rval->clone();
491 def_rval->range.lo += nw_s_bits.lo;
492 def_rval->range.hi -= saved->
size - nw_s_bits.hi + 1;
496 bool def_deferred =
false;
497 bool def_invalid =
false;
498 std::vector<std::pair<const IR::BFN::ParserState *, const IR::BFN::InputBufferRVal *>>
500 for (
const auto *trans : def_state->transitions) {
506 if (!trans->next)
continue;
507 if (!graph.
is_reachable(trans->next, use_state))
continue;
509 auto *shifted_rval = def_rval->apply(
ShiftPacketRVal(trans->shift * 8,
true))
510 ->to<IR::BFN::InputBufferRVal>();
512 def_invalid |= shifted_rval->range.lo < 0;
513 new_defs.push_back(std::make_pair(trans->next, shifted_rval));
516 if (def_deferred && !def_invalid)
return new_defs;
524 const IR::BFN::ParserState *state) {
527 if (rval->range.lo < 0) {
528 if (graph.predecessors().count(state)) {
529 for (
auto pred : graph.predecessors().at(state)) {
530 for (
auto t : graph.transitions(pred, state)) {
531 auto shift = t->shift;
534 auto defs = find_defs(shifted_rval->to<IR::BFN::InputBufferRVal>(),
537 for (
auto def : defs) rv.insert(def);
543 }
else if (rval->range.lo >= 0) {
544 add_def(rv, state, rval);
553 const IR::BFN::ParserState *state) {
556 for (
auto &kv : defs.state_to_rvals) {
557 auto def_state = kv.first;
559 if (def_state == state || graph.
is_ancestor(def_state, state)) {
560 for (
auto rval : kv.second) {
561 for (
auto lval : defs.rval_to_lvals.at(rval)) {
563 auto f = phv.field(lval, &f_bits);
564 auto s = phv.field(saved, &s_bits);
567 auto child_rvals = defer_defs_to_children(
568 rval, graph, state, def_state, f, s, f_bits, s_bits);
570 if (child_rvals.size()) {
571 for (
auto &[def_state, rval] : child_rvals)
572 add_def(rv, def_state, rval);
574 if (s_bits.
size() == f_bits.
size()) {
575 add_def(rv, def_state, rval);
577 auto nw_f_bits = f_bits.
toOrder<Endian::Network>(f->size);
578 auto nw_s_bits = s_bits.
toOrder<Endian::Network>(s->size);
580 auto full_rval = rval->clone();
581 full_rval->range.lo -= nw_f_bits.lo;
582 full_rval->range.hi += f->size - nw_f_bits.hi + 1;
584 auto slice_rval = full_rval->clone();
585 slice_rval->range.lo += nw_s_bits.lo;
586 slice_rval->range.hi -= s->size - nw_s_bits.hi + 1;
588 add_def(rv, def_state, slice_rval);
600 bool preorder(
const IR::BFN::SavedRVal *save)
override {
601 auto parser = findOrigCtxt<IR::BFN::Parser>();
602 auto state = findOrigCtxt<IR::BFN::ParserState>();
603 auto select = findOrigCtxt<IR::BFN::Select>();
605 auto &graph = parser_info.graph(parser);
607 auto use = parser_use_def[parser].get_use(state, save, select);
611 if (
auto buf = save->source->to<IR::BFN::InputBufferRVal>())
612 defs = find_defs(buf, graph, state);
614 defs = find_defs(save->source, graph, state);
616 for (
auto def : defs) parser_use_def[parser].add_def(phv, use, def);
618 if (!select)
return false;
621 auto f = phv.field(save->source, &bits);
626 if (!save->source->is<IR::BFN::InputBufferRVal>() &&
627 !is_source_extracted_on_each_path_to_state(graph, state, f)) {
629 "Value used in select statement needs to be set "
630 "from input packet (not a constant) for every possible path "
631 "through the parse graph. This does not hold true for: %1%",
635 if (!parser_use_def[parser].use_to_defs.count(use))
636 ::fatal_error(
"Use of uninitialized parser value in a select statement %1%. ",
639 LOG4(parser_use_def[parser].print(use));
644 bool preorder(
const IR::BFN::Parser *parser)
override {
645 parser_use_def[parser] = {};
647 std::stringstream ss;
648 ss <<
"MapToUse parser:" << std::endl;
650 ss << std::endl << std::endl;