From f2e9be98e885a7e117b0cf4efdfed0eac748ea2d Mon Sep 17 00:00:00 2001 From: Fabian Ruffy <5960321+fruffy@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:16:56 +0200 Subject: [PATCH 1/2] Fix a nullptr access in the DPDK back end. (#4712) * Fix a nullptr access in the DPDK back end. * Need to initialize metaCopyNeeded to false because of a flaw in key traversal. --- backends/dpdk/backend.cpp | 36 ++++++++++++++++++++++++------------ backends/dpdk/dpdkArch.cpp | 10 ++++++---- backends/dpdk/dpdkArch.h | 2 +- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/backends/dpdk/backend.cpp b/backends/dpdk/backend.cpp index 01fe4e52bc..815a06c4e6 100644 --- a/backends/dpdk/backend.cpp +++ b/backends/dpdk/backend.cpp @@ -32,6 +32,7 @@ limitations under the License. #include "midend/eliminateTypedefs.h" #include "midend/removeComplexExpressions.h" #include "midend/simplifyKey.h" + namespace DPDK { void DpdkBackend::convert(const IR::ToplevelBlock *tlb) { @@ -129,29 +130,40 @@ void DpdkBackend::convert(const IR::ToplevelBlock *tlb) { }; simplify.addDebugHook(hook, true); program = program->apply(simplify); - ordered_set used_fields; + if (errorCount() > 0) { + return; + } + dpdk_program = convertToDpdk->getDpdkProgram(); - if (!dpdk_program) return; + if (dpdk_program == nullptr) { + return; + } + + PassManager postCodeGen; + ordered_map newNameMap; + ordered_set usedFields; if (structure.p4arch == "pna") { - PassManager post_code_gen = { + postCodeGen.addPasses({ new PrependPassRecircId(), new DirectionToRegRead(), - }; - dpdk_program = dpdk_program->apply(post_code_gen)->to(); + }); } - ordered_map newNameMap; - PassManager post_code_gen = { + postCodeGen.addPasses({ new EliminateUnusedAction(), new DpdkAsmOptimization, new CopyPropagationAndElimination(typeMap), - new CollectUsedMetadataField(used_fields), - new RemoveUnusedMetadataFields(used_fields), + new CollectUsedMetadataField(usedFields), + new RemoveUnusedMetadataFields(usedFields), new ShortenTokenLength(newNameMap), new EmitDpdkTableConfig(refMap, typeMap, newNameMap), - }; - - dpdk_program = dpdk_program->apply(post_code_gen)->to(); + }); + const auto *optimizedProgram = dpdk_program->apply(postCodeGen); + if (errorCount() > 0) { + return; + } + dpdk_program = optimizedProgram->to(); } void DpdkBackend::codegen(std::ostream &out) const { dpdk_program->toSpec(out) << std::endl; } + } // namespace DPDK diff --git a/backends/dpdk/dpdkArch.cpp b/backends/dpdk/dpdkArch.cpp index 0d45e49d11..2fa91d69d1 100644 --- a/backends/dpdk/dpdkArch.cpp +++ b/backends/dpdk/dpdkArch.cpp @@ -1566,6 +1566,11 @@ cstring CopyMatchKeysToSingleStruct::getTableKeyName(const IR::Expression *e) { } const IR::Node *CopyMatchKeysToSingleStruct::preorder(IR::Key *keys) { + // If copyNeeded is false at this point, it means the keys are from same struct. + // Check remaining conditions to see if the copy is needed or not + // TODO: This indirection should not be needed. Instead of using a visitor for IR::KeyElement + // just resolve each key element directly. + metaCopyNeeded = false; // If any key field is from different structure, put all keys in metadata LOG3("Visiting " << keys); bool copyNeeded = false; @@ -1645,10 +1650,6 @@ const IR::Node *CopyMatchKeysToSingleStruct::preorder(IR::Key *keys) { } else { structure->table_type_map.emplace(table->name.name, InternalTableType::WILDCARD); } - - // If copyNeeded is false at this point, it means the keys are from same struct. - // Check remaining conditions to see if the copy is needed or not - metaCopyNeeded = false; if (copyNeeded) contiguous = false; if (!contiguous && @@ -1670,6 +1671,7 @@ const IR::Node *CopyMatchKeysToSingleStruct::preorder(IR::Key *keys) { } return keys; } + const IR::Node *CopyMatchKeysToSingleStruct::postorder(IR::KeyElement *element) { // If we got here we need to put the key element in metadata. LOG3("Extracting key element " << element); diff --git a/backends/dpdk/dpdkArch.h b/backends/dpdk/dpdkArch.h index 26dd960e1f..856d023461 100644 --- a/backends/dpdk/dpdkArch.h +++ b/backends/dpdk/dpdkArch.h @@ -826,7 +826,7 @@ struct keyInfo { class CopyMatchKeysToSingleStruct : public P4::KeySideEffect { IR::IndexedVector decls; DpdkProgramStructure *structure; - bool metaCopyNeeded; + bool metaCopyNeeded = false; public: CopyMatchKeysToSingleStruct(P4::ReferenceMap *refMap, P4::TypeMap *typeMap, From c3c24015fb947287edef938497f251e05d9f8864 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Thu, 6 Jun 2024 13:03:27 -0700 Subject: [PATCH 2/2] Get rid of implicit char* => cstring conversions (#4694) * Switch to explicit cstring literals * Get rid of implicit char* => cstring conversion. The amount of changes effectively shows how often this was misused. * Unbreak bazel * Allocate string cache data from non-GC arena * Address review comments * Address review feedback --- backends/bmv2/common/JsonObjects.cpp | 226 ++++++------- backends/bmv2/common/action.cpp | 36 +- backends/bmv2/common/annotations.h | 16 +- backends/bmv2/common/backend.h | 7 +- backends/bmv2/common/control.h | 202 +++++------ backends/bmv2/common/controlFlowGraph.cpp | 6 +- backends/bmv2/common/deparser.cpp | 16 +- backends/bmv2/common/deparser.h | 2 +- backends/bmv2/common/expression.cpp | 316 +++++++++--------- backends/bmv2/common/extern.cpp | 75 ++--- backends/bmv2/common/extern.h | 40 +-- backends/bmv2/common/header.cpp | 6 +- backends/bmv2/common/helpers.cpp | 54 +-- backends/bmv2/common/helpers.h | 66 ++-- backends/bmv2/common/midend.h | 2 +- backends/bmv2/common/options.h | 4 +- backends/bmv2/common/parser.cpp | 112 +++---- backends/bmv2/common/parser.h | 2 +- .../bmv2/common/sharedActionSelectorCheck.h | 2 +- backends/bmv2/psa_switch/main.cpp | 2 +- backends/bmv2/psa_switch/midend.cpp | 15 +- backends/bmv2/psa_switch/options.cpp | 4 +- .../bmv2/psa_switch/psaProgramStructure.cpp | 30 +- backends/bmv2/psa_switch/psaSwitch.cpp | 316 +++++++++--------- backends/bmv2/psa_switch/psaSwitch.h | 16 +- backends/bmv2/simple_switch/main.cpp | 2 +- backends/bmv2/simple_switch/midend.cpp | 15 +- backends/bmv2/simple_switch/simpleSwitch.cpp | 248 +++++++------- backends/bmv2/simple_switch/simpleSwitch.h | 12 +- backends/dpdk/constants.h | 5 +- .../control-plane/bfruntime_arch_handler.h | 18 +- backends/dpdk/control-plane/bfruntime_ext.cpp | 97 +++--- backends/dpdk/dpdk.def | 44 +-- backends/dpdk/dpdkArch.cpp | 111 +++--- backends/dpdk/dpdkArch.h | 17 +- backends/dpdk/dpdkAsmOpt.cpp | 10 +- backends/dpdk/dpdkAsmOpt.h | 15 +- backends/dpdk/dpdkCheckExternInvocation.h | 25 +- backends/dpdk/dpdkContext.cpp | 174 +++++----- backends/dpdk/dpdkContext.h | 13 +- backends/dpdk/dpdkHelpers.cpp | 39 ++- backends/dpdk/dpdkMetadata.cpp | 4 +- backends/dpdk/dpdkProgram.cpp | 29 +- backends/dpdk/dpdkProgram.h | 4 +- backends/dpdk/dpdkProgramStructure.cpp | 51 +-- backends/dpdk/dpdkProgramStructure.h | 8 +- backends/dpdk/dpdkUtils.cpp | 13 +- backends/dpdk/dpdkUtils.h | 2 +- backends/dpdk/main.cpp | 8 +- backends/dpdk/midend.cpp | 42 +-- backends/dpdk/options.cpp | 10 +- backends/dpdk/options.h | 20 +- backends/dpdk/spec.cpp | 22 +- backends/dpdk/tdiConf.cpp | 10 +- backends/ebpf/codeGen.cpp | 22 +- backends/ebpf/ebpfControl.cpp | 13 +- backends/ebpf/ebpfDeparser.cpp | 14 +- backends/ebpf/ebpfModel.cpp | 2 +- backends/ebpf/ebpfModel.h | 32 +- backends/ebpf/ebpfOptions.cpp | 4 +- backends/ebpf/ebpfParser.cpp | 2 +- backends/ebpf/ebpfProgram.cpp | 18 +- backends/ebpf/ebpfProgram.h | 26 +- backends/ebpf/ebpfTable.cpp | 37 +- backends/ebpf/ebpfTable.h | 2 +- backends/ebpf/ebpfType.cpp | 17 +- backends/ebpf/midend.cpp | 10 +- backends/ebpf/p4c-ebpf.cpp | 2 +- backends/ebpf/psa/ebpfPipeline.cpp | 16 +- backends/ebpf/psa/ebpfPipeline.h | 50 +-- backends/ebpf/psa/ebpfPsaDeparser.cpp | 8 +- backends/ebpf/psa/ebpfPsaGen.cpp | 109 +++--- backends/ebpf/psa/ebpfPsaTable.cpp | 46 +-- backends/ebpf/psa/ebpfPsaTable.h | 6 +- backends/ebpf/psa/externs/ebpfPsaCounter.cpp | 4 +- backends/ebpf/psa/externs/ebpfPsaDigest.cpp | 2 +- .../ebpf/psa/externs/ebpfPsaHashAlgorithm.cpp | 8 +- .../ebpf/psa/externs/ebpfPsaHashAlgorithm.h | 16 +- backends/ebpf/psa/externs/ebpfPsaMeter.cpp | 45 +-- backends/ebpf/psa/externs/ebpfPsaMeter.h | 4 +- .../externs/ebpfPsaTableImplementation.cpp | 25 +- backends/ebpf/psa/xdpHelpProgram.h | 10 +- backends/ebpf/target.cpp | 33 +- backends/ebpf/target.h | 74 ++-- backends/graphs/controls.cpp | 15 +- backends/graphs/graph_visitor.cpp | 50 +-- backends/graphs/graphs.cpp | 4 +- backends/graphs/graphs.h | 39 ++- backends/graphs/p4c-graphs.cpp | 6 +- backends/graphs/parsers.cpp | 12 +- backends/p4test/midend.cpp | 2 +- backends/p4test/p4test.cpp | 4 +- .../p4tools/common/compiler/reachability.cpp | 4 +- .../p4tools/common/compiler/reachability.h | 2 +- .../control_plane/symbolic_variables.cpp | 4 +- backends/p4tools/common/lib/table_utils.cpp | 10 +- backends/p4tools/common/lib/taint.cpp | 2 +- backends/p4tools/common/lib/util.cpp | 8 +- backends/p4tools/common/lib/util.h | 2 +- backends/p4tools/common/lib/variables.h | 4 +- backends/p4tools/common/options.cpp | 4 +- backends/p4tools/common/options.h | 2 +- .../core/small_step/abstract_stepper.cpp | 2 +- .../testgen/core/small_step/cmd_stepper.cpp | 24 +- .../testgen/core/small_step/expr_stepper.cpp | 2 +- .../core/small_step/extern_stepper.cpp | 86 ++--- .../testgen/core/small_step/table_stepper.cpp | 20 +- .../modules/testgen/lib/execution_state.cpp | 16 +- .../modules/testgen/lib/packet_vars.cpp | 4 +- .../modules/testgen/lib/test_backend.cpp | 14 +- .../modules/testgen/lib/test_framework.h | 11 +- .../p4tools/modules/testgen/lib/test_spec.cpp | 18 +- backends/p4tools/modules/testgen/options.cpp | 18 +- .../testgen/targets/bmv2/cmd_stepper.cpp | 6 +- .../modules/testgen/targets/bmv2/concolic.cpp | 14 +- .../testgen/targets/bmv2/expr_stepper.cpp | 218 ++++++------ .../targets/bmv2/map_direct_externs.cpp | 2 +- .../targets/bmv2/p4_asserts_parser.cpp | 21 +- .../targets/bmv2/p4_refers_to_parser.cpp | 22 +- .../targets/bmv2/p4runtime_translation.cpp | 4 +- .../targets/bmv2/p4runtime_translation.h | 2 + .../testgen/targets/bmv2/program_info.cpp | 46 +-- .../testgen/targets/bmv2/table_stepper.cpp | 27 +- .../modules/testgen/targets/bmv2/target.cpp | 2 +- .../small-step/p4_asserts_parser_test.cpp | 28 +- .../bmv2/test/small-step/reachability.cpp | 16 +- .../targets/bmv2/test/test_backend/ptf.cpp | 56 ++-- .../targets/bmv2/test/test_backend/stf.cpp | 56 ++-- .../bmv2/test/testgen_api/api_test.cpp | 12 +- .../bmv2/test/testgen_api/benchmark.cpp | 10 +- .../testgen_api/control_plane_filter_test.cpp | 17 +- .../test/testgen_api/output_option_test.cpp | 10 +- .../transformations/saturation_arithm.cpp | 4 +- .../bmv2/test/z3-solver/asrt_model.cpp | 4 +- .../bmv2/test/z3-solver/expressions.cpp | 4 +- .../testgen/targets/bmv2/test_backend.cpp | 25 +- .../targets/bmv2/test_backend/common.cpp | 2 +- .../targets/bmv2/test_backend/metadata.cpp | 2 +- .../targets/bmv2/test_backend/protobuf.cpp | 6 +- .../targets/bmv2/test_backend/protobuf_ir.cpp | 10 +- .../testgen/targets/bmv2/test_backend/ptf.cpp | 4 +- .../testgen/targets/bmv2/test_backend/stf.cpp | 2 +- .../testgen/targets/bmv2/test_spec.cpp | 20 +- .../testgen/targets/ebpf/backend/stf/stf.cpp | 2 +- .../testgen/targets/ebpf/expr_stepper.cpp | 22 +- .../testgen/targets/ebpf/program_info.cpp | 10 +- .../testgen/targets/ebpf/test_backend.cpp | 4 +- .../targets/pna/backend/metadata/metadata.cpp | 2 +- .../testgen/targets/pna/backend/ptf/ptf.cpp | 2 +- .../modules/testgen/targets/pna/constants.cpp | 4 +- .../testgen/targets/pna/dpdk/program_info.cpp | 59 ++-- .../targets/pna/shared_expr_stepper.cpp | 20 +- .../targets/pna/shared_table_stepper.cpp | 27 +- .../testgen/targets/pna/test_backend.cpp | 17 +- .../modules/testgen/targets/pna/test_spec.cpp | 14 +- .../modules/testgen/test/small-step/util.h | 6 +- .../testgen/test/z3-solver/constraints.cpp | 37 +- backends/p4tools/modules/testgen/testgen.cpp | 4 +- backends/p4tools/p4tools.def | 14 +- backends/tc/backend.cpp | 66 ++-- backends/tc/backend.h | 2 +- backends/tc/ebpfCodeGen.cpp | 76 ++--- backends/tc/ebpfCodeGen.h | 19 +- backends/tc/introspection.cpp | 94 +++--- backends/tc/introspection.h | 4 +- backends/tc/midend.cpp | 2 +- backends/tc/options.h | 6 +- backends/tc/pnaProgramStructure.cpp | 8 +- backends/tc/tc.def | 12 +- backends/tc/tcAnnotations.cpp | 32 +- backends/ubpf/midend.cpp | 2 +- backends/ubpf/p4c-ubpf.cpp | 2 +- backends/ubpf/target.cpp | 6 +- backends/ubpf/target.h | 20 +- backends/ubpf/ubpfControl.cpp | 8 +- backends/ubpf/ubpfDeparser.cpp | 8 +- backends/ubpf/ubpfModel.cpp | 2 +- backends/ubpf/ubpfModel.h | 39 ++- backends/ubpf/ubpfParser.cpp | 2 +- backends/ubpf/ubpfProgram.cpp | 4 +- backends/ubpf/ubpfProgram.h | 6 +- backends/ubpf/ubpfRegister.cpp | 4 +- backends/ubpf/ubpfTable.cpp | 10 +- backends/ubpf/ubpfType.cpp | 22 +- bazel/example/main.cc | 4 +- control-plane/bfruntime.cpp | 263 +++++++-------- control-plane/bfruntime.h | 65 ++-- control-plane/flattenHeader.cpp | 9 +- control-plane/flattenHeader.h | 2 +- control-plane/p4RuntimeAnnotations.h | 20 +- control-plane/p4RuntimeArchHandler.cpp | 2 +- control-plane/p4RuntimeArchHandler.h | 11 +- control-plane/p4RuntimeArchStandard.h | 122 +++---- control-plane/p4RuntimeSerializer.cpp | 76 ++--- control-plane/p4RuntimeSerializer.h | 4 +- control-plane/p4RuntimeSymbolTable.cpp | 6 +- control-plane/typeSpecConverter.cpp | 2 +- frontends/common/applyOptionsPragmas.cpp | 6 +- frontends/common/constantFolding.h | 4 +- frontends/common/options.cpp | 21 +- frontends/common/parser_options.cpp | 41 +-- frontends/common/parser_options.h | 6 +- frontends/common/programMap.h | 2 +- .../common/resolveReferences/referenceMap.cpp | 26 +- .../common/resolveReferences/referenceMap.h | 6 +- frontends/p4-14/header_type.cpp | 10 +- frontends/p4-14/typecheck.cpp | 6 +- frontends/p4/actionsInlining.cpp | 2 +- frontends/p4/alias.h | 4 +- frontends/p4/callGraph.cpp | 3 +- frontends/p4/callGraph.h | 2 +- frontends/p4/commonInlining.h | 4 +- frontends/p4/coreLibrary.h | 24 +- frontends/p4/createBuiltins.cpp | 4 +- frontends/p4/def_use.cpp | 6 +- frontends/p4/deprecated.cpp | 6 +- frontends/p4/entryPriorities.cpp | 4 +- frontends/p4/fromv1.0/converters.cpp | 18 +- frontends/p4/fromv1.0/converters.h | 36 +- frontends/p4/fromv1.0/programStructure.cpp | 34 +- frontends/p4/fromv1.0/v1model.h | 175 +++++----- frontends/p4/frontend.cpp | 2 +- frontends/p4/functionsInlining.cpp | 2 +- frontends/p4/hierarchicalNames.cpp | 2 +- frontends/p4/inlining.cpp | 10 +- frontends/p4/localizeActions.cpp | 8 +- frontends/p4/moveDeclarations.cpp | 2 +- frontends/p4/parseAnnotations.cpp | 2 +- frontends/p4/reassociation.h | 4 +- frontends/p4/removeReturns.cpp | 8 +- frontends/p4/removeReturns.h | 5 +- frontends/p4/reservedWords.cpp | 23 +- frontends/p4/reservedWords.h | 2 +- frontends/p4/simplifyDefUse.cpp | 10 +- frontends/p4/specialize.cpp | 6 +- frontends/p4/specializeGenericFunctions.h | 2 +- frontends/p4/specializeGenericTypes.cpp | 2 +- frontends/p4/staticAssert.h | 9 +- frontends/p4/strengthReduction.h | 4 +- frontends/p4/symbol_table.cpp | 17 +- frontends/p4/tableKeyNames.cpp | 11 +- frontends/p4/ternaryBool.cpp | 12 +- frontends/p4/toP4/toP4.cpp | 12 +- frontends/p4/typeChecking/typeChecker.cpp | 17 +- frontends/p4/typeChecking/typeChecker.h | 6 +- frontends/p4/typeChecking/typeConstraints.h | 4 +- .../p4/typeChecking/typeSubstitution.cpp | 14 +- frontends/p4/typeChecking/typeUnification.cpp | 4 +- frontends/p4/uniqueNames.h | 4 +- frontends/p4/validateParsedProgram.h | 4 +- frontends/parsers/p4/p4lexer.ll | 22 +- frontends/parsers/p4/p4parser.ypp | 49 +-- frontends/parsers/parserDriver.cpp | 4 +- frontends/parsers/v1/v1lexer.ll | 36 +- frontends/parsers/v1/v1parser.ypp | 8 +- ir/base.cpp | 4 +- ir/base.def | 10 +- ir/dump.cpp | 10 +- ir/expression.def | 26 +- ir/id.h | 6 +- ir/ir.cpp | 26 +- ir/ir.def | 18 +- ir/irutils.cpp | 4 +- ir/loop-visitor.cpp | 16 +- ir/namemap.h | 2 +- ir/node.cpp | 16 +- ir/node.h | 6 +- ir/type.cpp | 58 ++-- ir/type.def | 78 ++--- ir/v1.cpp | 118 +++---- ir/v1.def | 18 +- ir/visitor.cpp | 4 +- ir/visitor.h | 2 +- lib/cstring.cpp | 31 +- lib/cstring.h | 35 +- lib/error.h | 2 +- lib/error_catalog.cpp | 89 ++--- lib/error_catalog.h | 10 +- lib/error_reporter.h | 12 +- lib/json.cpp | 6 +- lib/json.h | 2 +- lib/nullstream.cpp | 1 + lib/options.cpp | 8 +- lib/options.h | 3 +- lib/path.cpp | 2 +- lib/path.h | 7 +- lib/sourceCodeBuilder.h | 4 + lib/source_file.cpp | 28 +- lib/source_file.h | 10 +- midend/actionSynthesis.cpp | 12 +- midend/def_use.cpp | 7 +- midend/eliminateTuples.cpp | 6 +- midend/expr_uses.h | 4 +- midend/flattenHeaders.cpp | 5 +- midend/flattenInterfaceStructs.cpp | 5 +- midend/flattenInterfaceStructs.h | 5 +- midend/global_copyprop.cpp | 4 +- midend/interpreter.h | 4 +- midend/local_copyprop.cpp | 21 +- midend/nestedStructs.cpp | 11 +- midend/parserUnroll.h | 4 +- midend/removeExits.cpp | 2 +- midend/removeExits.h | 2 +- midend/simplifySelectList.cpp | 4 +- midend/simplifySelectList.h | 1 + test/gtest/constant_folding.cpp | 8 +- test/gtest/cstring.cpp | 37 +- test/gtest/equiv_test.cpp | 20 +- test/gtest/expr_uses_test.cpp | 28 +- test/gtest/format_test.cpp | 8 +- test/gtest/indexed_vector.cpp | 18 +- test/gtest/json_test.cpp | 4 +- test/gtest/midend_pass.cpp | 2 +- test/gtest/p4runtime.cpp | 135 ++++---- test/gtest/parser_unroll.cpp | 2 +- test/gtest/path_test.cpp | 6 +- tools/ir-generator/generator.cpp | 6 +- tools/ir-generator/ir-generator-lex.l | 20 +- tools/ir-generator/ir-generator.ypp | 39 ++- tools/ir-generator/irclass.cpp | 47 +-- tools/ir-generator/irclass.h | 8 +- tools/ir-generator/methods.cpp | 52 +-- tools/ir-generator/type.cpp | 36 +- tools/ir-generator/type.h | 8 +- 324 files changed, 3998 insertions(+), 3657 deletions(-) diff --git a/backends/bmv2/common/JsonObjects.cpp b/backends/bmv2/common/JsonObjects.cpp index 18c2ead837..9b81a5e6df 100644 --- a/backends/bmv2/common/JsonObjects.cpp +++ b/backends/bmv2/common/JsonObjects.cpp @@ -27,37 +27,37 @@ const int JSON_MINOR_VERSION = 23; JsonObjects::JsonObjects() { toplevel = new Util::JsonObject(); meta = new Util::JsonObject(); - header_types = insert_array_field(toplevel, "header_types"); - headers = insert_array_field(toplevel, "headers"); - header_stacks = insert_array_field(toplevel, "header_stacks"); - header_union_types = insert_array_field(toplevel, "header_union_types"); - header_unions = insert_array_field(toplevel, "header_unions"); - header_union_stacks = insert_array_field(toplevel, "header_union_stacks"); - field_lists = insert_array_field(toplevel, "field_lists"); - errors = insert_array_field(toplevel, "errors"); - enums = insert_array_field(toplevel, "enums"); - parsers = insert_array_field(toplevel, "parsers"); - parse_vsets = insert_array_field(toplevel, "parse_vsets"); - deparsers = insert_array_field(toplevel, "deparsers"); - meter_arrays = insert_array_field(toplevel, "meter_arrays"); - counters = insert_array_field(toplevel, "counter_arrays"); - register_arrays = insert_array_field(toplevel, "register_arrays"); - calculations = insert_array_field(toplevel, "calculations"); - learn_lists = insert_array_field(toplevel, "learn_lists"); - actions = insert_array_field(toplevel, "actions"); - pipelines = insert_array_field(toplevel, "pipelines"); - checksums = insert_array_field(toplevel, "checksums"); - force_arith = insert_array_field(toplevel, "force_arith"); - externs = insert_array_field(toplevel, "extern_instances"); - field_aliases = insert_array_field(toplevel, "field_aliases"); + header_types = insert_array_field(toplevel, "header_types"_cs); + headers = insert_array_field(toplevel, "headers"_cs); + header_stacks = insert_array_field(toplevel, "header_stacks"_cs); + header_union_types = insert_array_field(toplevel, "header_union_types"_cs); + header_unions = insert_array_field(toplevel, "header_unions"_cs); + header_union_stacks = insert_array_field(toplevel, "header_union_stacks"_cs); + field_lists = insert_array_field(toplevel, "field_lists"_cs); + errors = insert_array_field(toplevel, "errors"_cs); + enums = insert_array_field(toplevel, "enums"_cs); + parsers = insert_array_field(toplevel, "parsers"_cs); + parse_vsets = insert_array_field(toplevel, "parse_vsets"_cs); + deparsers = insert_array_field(toplevel, "deparsers"_cs); + meter_arrays = insert_array_field(toplevel, "meter_arrays"_cs); + counters = insert_array_field(toplevel, "counter_arrays"_cs); + register_arrays = insert_array_field(toplevel, "register_arrays"_cs); + calculations = insert_array_field(toplevel, "calculations"_cs); + learn_lists = insert_array_field(toplevel, "learn_lists"_cs); + actions = insert_array_field(toplevel, "actions"_cs); + pipelines = insert_array_field(toplevel, "pipelines"_cs); + checksums = insert_array_field(toplevel, "checksums"_cs); + force_arith = insert_array_field(toplevel, "force_arith"_cs); + externs = insert_array_field(toplevel, "extern_instances"_cs); + field_aliases = insert_array_field(toplevel, "field_aliases"_cs); } Util::JsonArray *JsonObjects::get_field_list_contents(unsigned id) const { for (auto e : *field_lists) { auto obj = e->to(); - auto val = obj->get("id")->to(); + auto val = obj->get("id"_cs)->to(); if (val != nullptr && val->isNumber() && val->getInt() == static_cast(id)) { - return obj->get("elements")->to(); + return obj->get("elements"_cs)->to(); } } return nullptr; @@ -66,7 +66,7 @@ Util::JsonArray *JsonObjects::get_field_list_contents(unsigned id) const { Util::JsonObject *JsonObjects::find_object_by_name(Util::JsonArray *array, const cstring &name) { for (auto e : *array) { auto obj = e->to(); - auto val = obj->get("name")->to(); + auto val = obj->get("name"_cs)->to(); if (val != nullptr && val->isString() && val->getString() == name) { return obj; } @@ -87,19 +87,19 @@ Util::JsonArray *JsonObjects::append_array(Util::JsonArray *parent) { } Util::JsonArray *JsonObjects::create_parameters(Util::JsonObject *object) { - return insert_array_field(object, "parameters"); + return insert_array_field(object, "parameters"_cs); } -void JsonObjects::add_program_info(const cstring &name) { toplevel->emplace("program", name); } +void JsonObjects::add_program_info(const cstring &name) { toplevel->emplace("program"_cs, name); } void JsonObjects::add_meta_info() { static constexpr int version_major = JSON_MAJOR_VERSION; static constexpr int version_minor = JSON_MINOR_VERSION; - auto version = insert_array_field(meta, "version"); + auto version = insert_array_field(meta, "version"_cs); version->append(version_major); version->append(version_minor); - meta->emplace("compiler", "https://github.com/p4lang/p4c"); - toplevel->emplace("__meta__", meta); + meta->emplace("compiler"_cs, "https://github.com/p4lang/p4c"); + toplevel->emplace("__meta__"_cs, meta); } /// Create a header type in json. /// @param name header name @@ -115,17 +115,17 @@ unsigned JsonObjects::add_header_type(const cstring &name, Util::JsonArray *&fie return header_type_id_it->second; } auto header_type = new Util::JsonObject(); - unsigned id = BMV2::nextId("header_types"); + unsigned id = BMV2::nextId("header_types"_cs); header_type_id[sname] = id; - header_type->emplace("name", name); - header_type->emplace("id", id); + header_type->emplace("name"_cs, name); + header_type->emplace("id"_cs, id); if (fields != nullptr) { - header_type->emplace("fields", fields); + header_type->emplace("fields"_cs, fields); } else { auto temp = new Util::JsonArray(); - header_type->emplace("fields", temp); + header_type->emplace("fields"_cs, temp); } - if (max_length > 0) header_type->emplace("max_length", max_length); + if (max_length > 0) header_type->emplace("max_length"_cs, max_length); header_types->append(header_type); return id; } @@ -135,15 +135,15 @@ unsigned JsonObjects::add_union_type(const cstring &name, Util::JsonArray *&fiel auto it = union_type_id.find(sname); if (it != union_type_id.end()) return it->second; auto union_type = new Util::JsonObject(); - unsigned id = BMV2::nextId("header_union_types"); + unsigned id = BMV2::nextId("header_union_types"_cs); union_type_id[sname] = id; - union_type->emplace("name", name); - union_type->emplace("id", id); + union_type->emplace("name"_cs, name); + union_type->emplace("id"_cs, id); if (fields != nullptr) { - union_type->emplace("headers", fields); + union_type->emplace("headers"_cs, fields); } else { auto temp = new Util::JsonArray(); - union_type->emplace("headers", temp); + union_type->emplace("headers"_cs, temp); } header_union_types->append(union_type); return id; @@ -156,12 +156,12 @@ unsigned JsonObjects::add_header_type(const cstring &name) { return header_type_id_it->second; } auto header_type = new Util::JsonObject(); - unsigned id = BMV2::nextId("header_types"); + unsigned id = BMV2::nextId("header_types"_cs); header_type_id[sname] = id; - header_type->emplace("name", name); - header_type->emplace("id", id); + header_type->emplace("name"_cs, name); + header_type->emplace("id"_cs, id); auto temp = new Util::JsonArray(); - header_type->emplace("fields", temp); + header_type->emplace("fields"_cs, temp); header_types->append(header_type); return id; } @@ -169,20 +169,20 @@ unsigned JsonObjects::add_header_type(const cstring &name) { void JsonObjects::add_header_field(const cstring &name, Util::JsonArray *&field) { CHECK_NULL(field); Util::JsonObject *headerType = find_object_by_name(header_types, name); - Util::JsonArray *fields = headerType->get("fields")->to(); + Util::JsonArray *fields = headerType->get("fields"_cs)->to(); BUG_CHECK(fields != nullptr, "header '%1%' not found", name); fields->append(field); } unsigned JsonObjects::add_header(const cstring &type, const cstring &name) { auto header = new Util::JsonObject(); - unsigned id = BMV2::nextId("headers"); + unsigned id = BMV2::nextId("headers"_cs); LOG1("add header id " << id); - header->emplace("name", name); - header->emplace("id", id); - header->emplace("header_type", type); - header->emplace("metadata", false); - header->emplace("pi_omit", true); + header->emplace("name"_cs, name); + header->emplace("id"_cs, id); + header->emplace("header_type"_cs, type); + header->emplace("metadata"_cs, false); + header->emplace("pi_omit"_cs, true); headers->append(header); return id; } @@ -190,26 +190,26 @@ unsigned JsonObjects::add_header(const cstring &type, const cstring &name) { unsigned JsonObjects::add_union(const cstring &type, Util::JsonArray *&headers, const cstring &name) { auto u = new Util::JsonObject(); - unsigned id = BMV2::nextId("header_unions"); + unsigned id = BMV2::nextId("header_unions"_cs); LOG3("add header_union id " << id); - u->emplace("name", name); - u->emplace("id", id); - u->emplace("union_type", type); - u->emplace("header_ids", headers); - u->emplace("pi_omit", true); + u->emplace("name"_cs, name); + u->emplace("id"_cs, id); + u->emplace("union_type"_cs, type); + u->emplace("header_ids"_cs, headers); + u->emplace("pi_omit"_cs, true); header_unions->append(u); return id; } unsigned JsonObjects::add_metadata(const cstring &type, const cstring &name) { auto header = new Util::JsonObject(); - unsigned id = BMV2::nextId("headers"); + unsigned id = BMV2::nextId("headers"_cs); LOG3("add metadata header id " << id); - header->emplace("name", name); - header->emplace("id", id); - header->emplace("header_type", type); - header->emplace("metadata", true); - header->emplace("pi_omit", true); // Don't expose in PI. + header->emplace("name"_cs, name); + header->emplace("id"_cs, id); + header->emplace("header_type"_cs, type); + header->emplace("metadata"_cs, true); + header->emplace("pi_omit"_cs, true); // Don't expose in PI. headers->append(header); return id; } @@ -217,13 +217,13 @@ unsigned JsonObjects::add_metadata(const cstring &type, const cstring &name) { void JsonObjects::add_header_stack(const cstring &type, const cstring &name, const unsigned size, const std::vector &ids) { auto stack = new Util::JsonObject(); - unsigned id = BMV2::nextId("stack"); - stack->emplace("name", name); - stack->emplace("id", id); - stack->emplace("header_type", type); - stack->emplace("size", size); + unsigned id = BMV2::nextId("stack"_cs); + stack->emplace("name"_cs, name); + stack->emplace("id"_cs, id); + stack->emplace("header_type"_cs, type); + stack->emplace("size"_cs, size); auto members = new Util::JsonArray(); - stack->emplace("header_ids", members); + stack->emplace("header_ids"_cs, members); for (auto id : ids) { members->append(id); } @@ -233,13 +233,13 @@ void JsonObjects::add_header_stack(const cstring &type, const cstring &name, con void JsonObjects::add_header_union_stack(const cstring &type, const cstring &name, const unsigned size, const std::vector &ids) { auto stack = new Util::JsonObject(); - unsigned id = BMV2::nextId("union_stack"); - stack->emplace("name", name); - stack->emplace("id", id); - stack->emplace("union_type", type); - stack->emplace("size", size); + unsigned id = BMV2::nextId("union_stack"_cs); + stack->emplace("name"_cs, name); + stack->emplace("id"_cs, id); + stack->emplace("union_type"_cs, type); + stack->emplace("size"_cs, size); auto members = new Util::JsonArray(); - stack->emplace("header_union_ids", members); + stack->emplace("header_union_ids"_cs, members); for (auto id : ids) { members->append(id); } @@ -258,8 +258,8 @@ void JsonObjects::add_enum(const cstring &enum_name, const cstring &entry_name, Util::JsonObject *enum_json = find_object_by_name(enums, enum_name); if (enum_json == nullptr) { // first entry in a new enum enum_json = new Util::JsonObject(); - enum_json->emplace("name", enum_name); - auto entries = insert_array_field(enum_json, "entries"); + enum_json->emplace("name"_cs, enum_name); + auto entries = insert_array_field(enum_json, "entries"_cs); auto entry = new Util::JsonArray(); entry->append(entry_name); entry->append(entry_value); @@ -267,7 +267,7 @@ void JsonObjects::add_enum(const cstring &enum_name, const cstring &entry_name, enums->append(enum_json); LOG3("new enum object: " << enum_name << " " << entry_name << " " << entry_value); } else { // add entry to existing enum - auto entries = enum_json->get("entries")->to(); + auto entries = enum_json->get("entries"_cs)->to(); auto entry = new Util::JsonArray(); entry->append(entry_name); entry->append(entry_value); @@ -278,12 +278,12 @@ void JsonObjects::add_enum(const cstring &enum_name, const cstring &entry_name, unsigned JsonObjects::add_parser(const cstring &name) { auto parser = new Util::JsonObject(); - unsigned id = BMV2::nextId("parser"); - parser->emplace("name", name); - parser->emplace("id", id); - parser->emplace("init_state", IR::ParserState::start); + unsigned id = BMV2::nextId("parser"_cs); + parser->emplace("name"_cs, name); + parser->emplace("id"_cs, id); + parser->emplace("init_state"_cs, IR::ParserState::start); auto parse_states = new Util::JsonArray(); - parser->emplace("parse_states", parse_states); + parser->emplace("parse_states"_cs, parse_states); parsers->append(parser); map_parser.emplace(id, parser); @@ -293,18 +293,18 @@ unsigned JsonObjects::add_parser(const cstring &name) { unsigned JsonObjects::add_parser_state(const unsigned parser_id, const cstring &state_name) { if (map_parser.find(parser_id) == map_parser.end()) BUG("parser %1% not found.", parser_id); auto parser = map_parser[parser_id]; - auto states = parser->get("parse_states")->to(); + auto states = parser->get("parse_states"_cs)->to(); auto state = new Util::JsonObject(); - unsigned state_id = BMV2::nextId("parse_states"); - state->emplace("name", state_name); - state->emplace("id", state_id); + unsigned state_id = BMV2::nextId("parse_states"_cs); + state->emplace("name"_cs, state_name); + state->emplace("id"_cs, state_id); auto operations = new Util::JsonArray(); - state->emplace("parser_ops", operations); + state->emplace("parser_ops"_cs, operations); auto transitions = new Util::JsonArray(); - state->emplace("transitions", transitions); + state->emplace("transitions"_cs, transitions); states->append(state); auto key = new Util::JsonArray(); - state->emplace("transition_key", key); + state->emplace("transition_key"_cs, key); map_parser_state.emplace(state_id, state); return state_id; @@ -314,7 +314,7 @@ void JsonObjects::add_parser_transition(const unsigned state_id, Util::IJson *tr if (map_parser_state.find(state_id) == map_parser_state.end()) BUG("parser state %1% not found.", state_id); auto state = map_parser_state[state_id]; - auto transitions = state->get("transitions")->to(); + auto transitions = state->get("transitions"_cs)->to(); CHECK_NULL(transitions); auto trans = transition->to(); CHECK_NULL(trans); @@ -325,7 +325,7 @@ void JsonObjects::add_parser_op(const unsigned state_id, Util::IJson *op) { if (map_parser_state.find(state_id) == map_parser_state.end()) BUG("parser state %1% not found.", state_id); auto state = map_parser_state[state_id]; - auto statements = state->get("parser_ops")->to(); + auto statements = state->get("parser_ops"_cs)->to(); CHECK_NULL(statements); statements->append(op); } @@ -333,7 +333,7 @@ void JsonObjects::add_parser_op(const unsigned state_id, Util::IJson *op) { void JsonObjects::add_parser_transition_key(const unsigned state_id, Util::IJson *newKey) { if (map_parser_state.find(state_id) != map_parser_state.end()) { auto state = map_parser_state[state_id]; - auto keys = state->get("transition_key")->to(); + auto keys = state->get("transition_key"_cs)->to(); CHECK_NULL(keys); auto new_keys = newKey->to(); for (auto k : *new_keys) { @@ -345,11 +345,11 @@ void JsonObjects::add_parser_transition_key(const unsigned state_id, Util::IJson void JsonObjects::add_parse_vset(const cstring &name, const unsigned bitwidth, const big_int &size) { auto parse_vset = new Util::JsonObject(); - unsigned id = BMV2::nextId("parse_vsets"); - parse_vset->emplace("name", name); - parse_vset->emplace("id", id); - parse_vset->emplace("compressed_bitwidth", bitwidth); - parse_vset->emplace("max_size", size); + unsigned id = BMV2::nextId("parse_vsets"_cs); + parse_vset->emplace("name"_cs, name); + parse_vset->emplace("id"_cs, id); + parse_vset->emplace("compressed_bitwidth"_cs, bitwidth); + parse_vset->emplace("max_size"_cs, size); parse_vsets->append(parse_vset); } @@ -358,11 +358,11 @@ unsigned JsonObjects::add_action(const cstring &name, Util::JsonArray *¶ms, CHECK_NULL(params); CHECK_NULL(body); auto action = new Util::JsonObject(); - action->emplace("name", name); - unsigned id = BMV2::nextId("actions"); - action->emplace("id", id); - action->emplace("runtime_data", params); - action->emplace("primitives", body); + action->emplace("name"_cs, name); + unsigned id = BMV2::nextId("actions"_cs); + action->emplace("id"_cs, id); + action->emplace("runtime_data"_cs, params); + action->emplace("primitives"_cs, body); actions->append(action); return id; } @@ -370,20 +370,20 @@ unsigned JsonObjects::add_action(const cstring &name, Util::JsonArray *¶ms, void JsonObjects::add_extern_attribute(const cstring &name, const cstring &type, const cstring &value, Util::JsonArray *attributes) { auto attr = new Util::JsonObject(); - attr->emplace("name", name); - attr->emplace("type", type); - attr->emplace("value", value); + attr->emplace("name"_cs, name); + attr->emplace("type"_cs, type); + attr->emplace("value"_cs, value); attributes->append(attr); } void JsonObjects::add_extern(const cstring &name, const cstring &type, Util::JsonArray *attributes) { auto extn = new Util::JsonObject(); - unsigned id = BMV2::nextId("extern_instances"); - extn->emplace("name", name); - extn->emplace("id", id); - extn->emplace("type", type); - extn->emplace("attribute_values", attributes); + unsigned id = BMV2::nextId("extern_instances"_cs); + extn->emplace("name"_cs, name); + extn->emplace("id"_cs, id); + extn->emplace("type"_cs, type); + extn->emplace("attribute_values"_cs, attributes); externs->append(extn); } diff --git a/backends/bmv2/common/action.cpp b/backends/bmv2/common/action.cpp index 82f1f17a45..41af3497cc 100644 --- a/backends/bmv2/common/action.cpp +++ b/backends/bmv2/common/action.cpp @@ -20,18 +20,20 @@ limitations under the License. namespace BMV2 { +using namespace P4::literals; + cstring ActionConverter::jsonAssignment(const IR::Type *type) { - if (type->is()) return "assign_VL"; - if (type->is()) return "assign_union"; - if (type->is() || type->is()) return "assign_header"; + if (type->is()) return "assign_VL"_cs; + if (type->is()) return "assign_union"_cs; + if (type->is() || type->is()) return "assign_header"_cs; if (auto ts = type->to()) { auto et = ts->elementType; if (et->is()) - return "assign_union_stack"; + return "assign_union_stack"_cs; else - return "assign_header_stack"; + return "assign_header_stack"_cs; } - return "assign"; + return "assign"_cs; } void ActionConverter::convertActionBody(const IR::Vector *body, @@ -98,9 +100,9 @@ void ActionConverter::convertActionBody(const IR::Vector *body, } else if (s->is()) { break; } else if (s->is()) { - auto primitive = mkPrimitive("exit", result); + auto primitive = mkPrimitive("exit"_cs, result); (void)mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); break; } else if (s->is()) { const IR::Expression *l, *r; @@ -111,7 +113,7 @@ void ActionConverter::convertActionBody(const IR::Vector *body, cstring operation = jsonAssignment(type); auto primitive = mkPrimitive(operation, result); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", assign->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, assign->sourceInfoJsonObj()); bool convertBool = type->is(); Util::IJson *left; if (ctxt->conv->isArrayIndexRuntime(l)) { @@ -141,25 +143,25 @@ void ActionConverter::convertActionBody(const IR::Vector *body, parameters->append(obj); if (builtin->name == IR::Type_Header::setValid) { - prim = "add_header"; + prim = "add_header"_cs; } else if (builtin->name == IR::Type_Header::setInvalid) { - prim = "remove_header"; + prim = "remove_header"_cs; } else if (builtin->name == IR::Type_Stack::push_front) { BUG_CHECK(mc->arguments->size() == 1, "Expected 1 argument for %1%", mc); auto arg = ctxt->conv->convert(mc->arguments->at(0)->expression); - prim = "push"; + prim = "push"_cs; parameters->append(arg); } else if (builtin->name == IR::Type_Stack::pop_front) { BUG_CHECK(mc->arguments->size() == 1, "Expected 1 argument for %1%", mc); auto arg = ctxt->conv->convert(mc->arguments->at(0)->expression); - prim = "pop"; + prim = "pop"_cs; parameters->append(arg); } else { BUG("%1%: Unexpected built-in method", s); } auto primitive = mkPrimitive(prim, result); - primitive->emplace("parameters", parameters); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace("parameters"_cs, parameters); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); continue; } else if (mi->is()) { auto em = mi->to(); @@ -190,14 +192,14 @@ void ActionConverter::convertActionParams(const IR::ParameterList *parameters, warn(ErrorType::WARN_UNUSED, "Unused action parameter %1%", p); auto param = new Util::JsonObject(); - param->emplace("name", p->externalName()); + param->emplace("name"_cs, p->externalName()); auto type = ctxt->typeMap->getType(p, true); // TODO: added IR::Type_Enum here to support PSA_MeterColor_t // should re-consider how to support action parameters that is neither bit<> nor int<> if (!(type->is() || type->is())) ::error(ErrorType::ERR_INVALID, "%1%: action parameters must be bit<> or int<> on this target", p); - param->emplace("bitwidth", type->width_bits()); + param->emplace("bitwidth"_cs, type->width_bits()); params->append(param); } } diff --git a/backends/bmv2/common/annotations.h b/backends/bmv2/common/annotations.h index dacea7f161..f2354d8268 100644 --- a/backends/bmv2/common/annotations.h +++ b/backends/bmv2/common/annotations.h @@ -22,18 +22,20 @@ limitations under the License. namespace BMV2 { +using namespace P4::literals; + /// Parses BMV2-specific annotations. class ParseAnnotations : public P4::ParseAnnotations { public: ParseAnnotations() - : P4::ParseAnnotations("BMV2", false, + : P4::ParseAnnotations("BMV2"_cs, false, { - PARSE_EMPTY("metadata"), - PARSE_EXPRESSION_LIST("field_list"), - PARSE("alias", StringLiteral), - PARSE("priority", Constant), - PARSE_EXPRESSION_LIST("p4runtime_translation_mappings"), - PARSE_P4RUNTIME_TRANSLATION("p4runtime_translation"), + PARSE_EMPTY("metadata"_cs), + PARSE_EXPRESSION_LIST("field_list"_cs), + PARSE("alias"_cs, StringLiteral), + PARSE("priority"_cs, Constant), + PARSE_EXPRESSION_LIST("p4runtime_translation_mappings"_cs), + PARSE_P4RUNTIME_TRANSLATION("p4runtime_translation"_cs), }) {} }; diff --git a/backends/bmv2/common/backend.h b/backends/bmv2/common/backend.h index 3593dd2dd3..4e4fd50c4a 100644 --- a/backends/bmv2/common/backend.h +++ b/backends/bmv2/common/backend.h @@ -24,6 +24,7 @@ limitations under the License. #include "frontends/p4/coreLibrary.h" #include "helpers.h" #include "ir/ir.h" +#include "lib/cstring.h" #include "lib/error.h" #include "lib/exceptions.h" #include "lib/gc.h" @@ -153,7 +154,7 @@ class RenameUserMetadata : public Transform { IR::IndexedVector fields; for (auto f : type->fields) { auto anno = f->getAnnotation(IR::Annotation::nameAnnotation); - cstring suffix = ""; + cstring suffix = cstring::empty; if (anno != nullptr) suffix = anno->getName(); if (suffix.startsWith(".")) { // We can't change the name of this field. @@ -163,9 +164,9 @@ class RenameUserMetadata : public Transform { } if (!suffix.isNullOrEmpty()) - suffix = cstring(".") + suffix; + suffix = "."_cs + suffix; else - suffix = cstring(".") + f->name; + suffix = "."_cs + f->name; cstring newName = namePrefix + suffix; auto stringLit = new IR::StringLiteral(newName); LOG2("Renaming " << f << " to " << newName); diff --git a/backends/bmv2/common/control.h b/backends/bmv2/common/control.h index f35835564d..f43d9ac36a 100644 --- a/backends/bmv2/common/control.h +++ b/backends/bmv2/common/control.h @@ -48,12 +48,12 @@ class ControlConverter : public Inspector { LOG3("Processing " << dbp(table)); auto result = new Util::JsonObject(); cstring name = table->controlPlaneName(); - result->emplace("name", name); - result->emplace("id", nextId("tables")); - result->emplace_non_null("source_info", table->sourceInfoJsonObj()); + result->emplace("name"_cs, name); + result->emplace("id"_cs, nextId("tables"_cs)); + result->emplace_non_null("source_info"_cs, table->sourceInfoJsonObj()); cstring table_match_type = corelib.exactMatch.name; auto key = table->getKey(); - auto tkey = mkArrayField(result, "key"); + auto tkey = mkArrayField(result, "key"_cs); ctxt->conv->simpleExpressionsOnly = true; if (key != nullptr) { @@ -115,9 +115,9 @@ class ControlConverter : public Inspector { // represented in the BMv2 JSON file the same as a ternary // field would be. if (match_type == BMV2::MatchImplementation::optionalMatchTypeName) { - keyelement->emplace("match_type", corelib.ternaryMatch.name); + keyelement->emplace("match_type"_cs, corelib.ternaryMatch.name); } else { - keyelement->emplace("match_type", match_type); + keyelement->emplace("match_type"_cs, match_type); } if (auto na = ke->getAnnotation(IR::Annotation::nameAnnotation)) { BUG_CHECK(na->expr.size() == 1, "%1%: expected 1 name", na); @@ -125,21 +125,21 @@ class ControlConverter : public Inspector { BUG_CHECK(name != nullptr, "%1%: expected a string", na); // This is a BMv2 JSON extension: specify a // control-plane name for this key - keyelement->emplace("name", name->value); + keyelement->emplace("name"_cs, name->value); } auto jk = ctxt->conv->convert(expr); - keyelement->emplace("target", jk->to()->get("value")); + keyelement->emplace("target"_cs, jk->to()->get("value"_cs)); if (mask != 0) - keyelement->emplace("mask", + keyelement->emplace("mask"_cs, stringRepr(mask, ROUNDUP(expr->type->width_bits(), 8))); else - keyelement->emplace("mask", Util::JsonValue::null); + keyelement->emplace("mask"_cs, Util::JsonValue::null); tkey->append(keyelement); } } LOG3("table_match_type: " << table_match_type); - result->emplace("match_type", table_match_type); + result->emplace("match_type"_cs, table_match_type); ctxt->conv->simpleExpressionsOnly = false; auto propertyName = Standard::ActionProfileTraits::propertyName(); @@ -147,7 +147,7 @@ class ControlConverter : public Inspector { bool simple = handleTableImplementation(impl, key, result, action_profiles, selector_check); unsigned size = 0; - auto sz = table->properties->getProperty("size"); + auto sz = table->properties->getProperty("size"_cs); if (sz != nullptr) { if (sz->value->is()) { auto expr = sz->value->to()->expression; @@ -166,8 +166,8 @@ class ControlConverter : public Inspector { } if (size == 0) size = BMV2::TableAttributes::defaultTableSize; - result->emplace("max_size", size); - auto ctrs = table->properties->getProperty("counters"); + result->emplace("max_size"_cs, size); + auto ctrs = table->properties->getProperty("counters"_cs); if (ctrs != nullptr) { // The counters attribute should list the counters of the table, accessed in // actions of the table. We should be checking that this attribute and the @@ -193,15 +193,15 @@ class ControlConverter : public Inspector { return result; } auto jctr = new Util::JsonObject(); - cstring ctrname = ctrs->controlPlaneName("counter"); - jctr->emplace("name", ctrname); - jctr->emplace("id", nextId("counter_arrays")); - jctr->emplace_non_null("source_info", ctrs->sourceInfoJsonObj()); + cstring ctrname = ctrs->controlPlaneName("counter"_cs); + jctr->emplace("name"_cs, ctrname); + jctr->emplace("id"_cs, nextId("counter_arrays"_cs)); + jctr->emplace_non_null("source_info"_cs, ctrs->sourceInfoJsonObj()); // TODO(jafingerhut) - what kind of P4_16 code causes this // code to run, if any? bool direct = te->name == "direct_counter"; - jctr->emplace("is_direct", direct); - jctr->emplace("binding", table->controlPlaneName()); + jctr->emplace("is_direct"_cs, direct); + jctr->emplace("binding"_cs, table->controlPlaneName()); ctxt->json->counters->append(jctr); } else if (expr->is()) { auto pe = expr->to(); @@ -226,13 +226,13 @@ class ControlConverter : public Inspector { ::error(ErrorType::ERR_EXPECTED, "%1%: expected a counter", ctrs); } } - result->emplace("with_counters", true); + result->emplace("with_counters"_cs, true); } else { - result->emplace("with_counters", false); + result->emplace("with_counters"_cs, false); } bool sup_to = false; - auto timeout = table->properties->getProperty("support_timeout"); + auto timeout = table->properties->getProperty("support_timeout"_cs); if (timeout != nullptr) { if (timeout->value->is()) { auto expr = timeout->value->to()->expression; @@ -245,9 +245,9 @@ class ControlConverter : public Inspector { ::error(ErrorType::ERR_EXPECTED, "%1%: expected a Boolean", timeout); } } - result->emplace("support_timeout", sup_to); + result->emplace("support_timeout"_cs, sup_to); - auto dm = table->properties->getProperty("meters"); + auto dm = table->properties->getProperty("meters"_cs); if (dm != nullptr) { if (dm->value->is()) { auto expr = dm->value->to()->expression; @@ -282,17 +282,17 @@ class ControlConverter : public Inspector { BUG_CHECK(decl->is(), "%1%: expected an instance", decl->getNode()); cstring name = decl->controlPlaneName(); - result->emplace("direct_meters", name); + result->emplace("direct_meters"_cs, name); } } else { ::error(ErrorType::ERR_EXPECTED, "%1%: expected a meter", dm); } } else { - result->emplace("direct_meters", Util::JsonValue::null); + result->emplace("direct_meters"_cs, Util::JsonValue::null); } - auto action_ids = mkArrayField(result, "action_ids"); - auto actions = mkArrayField(result, "actions"); + auto action_ids = mkArrayField(result, "action_ids"_cs); + auto actions = mkArrayField(result, "actions"_cs); auto al = table->getActionList(); std::map useActionName; @@ -339,19 +339,19 @@ class ControlConverter : public Inspector { BUG_CHECK(nextDestination, "Could not find default destination for %1%", node->invocation); nextLabel = nodeName(nextDestination); - result->emplace("base_default_next", nextLabel); + result->emplace("base_default_next"_cs, nextLabel); // So if a "default:" switch case exists we set the nextLabel // to be the destination of the default: label. if (defaultLabelDestination != nullptr) nextLabel = nodeName(defaultLabelDestination); } else { - result->emplace("base_default_next", Util::JsonValue::null); + result->emplace("base_default_next"_cs, Util::JsonValue::null); } std::set labelsDone; for (auto s : node->successors.edges) { cstring label; if (s->isBool()) { - label = s->getBool() ? "__HIT__" : "__MISS__"; + label = s->getBool() ? "__HIT__"_cs : "__MISS__"_cs; } else if (s->isUnconditional()) { continue; } else { @@ -374,7 +374,7 @@ class ControlConverter : public Inspector { } } - result->emplace("next_tables", next_tables); + result->emplace("next_tables"_cs, next_tables); auto defact = table->properties->getProperty(IR::TableProperties::defaultActionPropertyName); if (defact != nullptr) { @@ -411,9 +411,9 @@ class ControlConverter : public Inspector { unsigned actionid = get(ctxt->structure->ids, action, INVALID_ACTION_ID); BUG_CHECK(actionid != INVALID_ACTION_ID, "Could not find id for %1%", action); auto entry = new Util::JsonObject(); - entry->emplace("action_id", actionid); - entry->emplace("action_const", defact->isConstant); - auto fields = mkArrayField(entry, "action_data"); + entry->emplace("action_id"_cs, actionid); + entry->emplace("action_const"_cs, defact->isConstant); + auto fields = mkArrayField(entry, "action_data"_cs); if (args != nullptr) { // TODO: use argument names for (auto a : *args) { @@ -427,8 +427,8 @@ class ControlConverter : public Inspector { } } } - entry->emplace("action_entry_const", defact->isConstant); - result->emplace("default_entry", entry); + entry->emplace("action_entry_const"_cs, defact->isConstant); + result->emplace("default_entry"_cs, entry); } convertTableEntries(table, result); return result; @@ -437,14 +437,14 @@ class ControlConverter : public Inspector { auto entriesList = table->getEntries(); if (entriesList == nullptr) return; - auto entries = mkArrayField(jsonTable, "entries"); + auto entries = mkArrayField(jsonTable, "entries"_cs); int entryPriority = 1; // default priority is defined by index position for (auto e : entriesList->entries) { auto entry = new Util::JsonObject(); - entry->emplace_non_null("source_info", e->sourceInfoJsonObj()); + entry->emplace_non_null("source_info"_cs, e->sourceInfoJsonObj()); auto keyset = e->getKeys(); - auto matchKeys = mkArrayField(entry, "match_key"); + auto matchKeys = mkArrayField(entry, "match_key"_cs); int keyIndex = 0; for (auto k : keyset->components) { auto key = new Util::JsonObject(); @@ -456,16 +456,16 @@ class ControlConverter : public Inspector { // represented in the BMv2 JSON file the same as a ternary // field would be. if (matchType == "optional") { - key->emplace("match_type", "ternary"); + key->emplace("match_type"_cs, "ternary"); } else { - key->emplace("match_type", matchType); + key->emplace("match_type"_cs, matchType); } if (matchType == corelib.exactMatch.name) { if (k->is()) - key->emplace("key", stringRepr(k->to()->value, k8)); + key->emplace("key"_cs, stringRepr(k->to()->value, k8)); else if (k->is()) // booleans are converted to ints - key->emplace("key", + key->emplace("key"_cs, stringRepr(k->to()->value ? 1 : 0, k8)); else ::error(ErrorType::ERR_UNSUPPORTED, "%1%: unsupported exact key expression", @@ -473,14 +473,15 @@ class ControlConverter : public Inspector { } else if (matchType == corelib.ternaryMatch.name) { if (k->is()) { auto km = k->to(); - key->emplace("key", stringRepr(km->left->to()->value, k8)); - key->emplace("mask", stringRepr(km->right->to()->value, k8)); + key->emplace("key"_cs, stringRepr(km->left->to()->value, k8)); + key->emplace("mask"_cs, + stringRepr(km->right->to()->value, k8)); } else if (k->is()) { - key->emplace("key", stringRepr(k->to()->value, k8)); - key->emplace("mask", stringRepr(Util::mask(keyWidth), k8)); + key->emplace("key"_cs, stringRepr(k->to()->value, k8)); + key->emplace("mask"_cs, stringRepr(Util::mask(keyWidth), k8)); } else if (k->is()) { - key->emplace("key", stringRepr(0, k8)); - key->emplace("mask", stringRepr(0, k8)); + key->emplace("key"_cs, stringRepr(0, k8)); + key->emplace("mask"_cs, stringRepr(0, k8)); } else { ::error(ErrorType::ERR_UNSUPPORTED, "%1%: unsupported ternary key expression", k); @@ -488,7 +489,7 @@ class ControlConverter : public Inspector { } else if (matchType == corelib.lpmMatch.name) { if (k->is()) { auto km = k->to(); - key->emplace("key", stringRepr(km->left->to()->value, k8)); + key->emplace("key"_cs, stringRepr(km->left->to()->value, k8)); auto trailing_zeros = [](unsigned long n, unsigned long keyWidth) { return n ? __builtin_ctzl(n) : static_cast(keyWidth); }; @@ -501,13 +502,13 @@ class ControlConverter : public Inspector { if (len + count_ones(mask) != keyWidth) // any remaining 0s in the prefix? ::error(ErrorType::ERR_INVALID, "%1%: invalid mask for LPM key", k); else - key->emplace("prefix_length", keyWidth - len); + key->emplace("prefix_length"_cs, keyWidth - len); } else if (k->is()) { - key->emplace("key", stringRepr(k->to()->value, k8)); - key->emplace("prefix_length", keyWidth); + key->emplace("key"_cs, stringRepr(k->to()->value, k8)); + key->emplace("prefix_length"_cs, keyWidth); } else if (k->is()) { - key->emplace("key", stringRepr(0, k8)); - key->emplace("prefix_length", 0); + key->emplace("key"_cs, stringRepr(0, k8)); + key->emplace("prefix_length"_cs, 0); } else { ::error(ErrorType::ERR_UNSUPPORTED, "%1%: unsupported LPM key expression", k); @@ -515,14 +516,16 @@ class ControlConverter : public Inspector { } else if (matchType == "range") { if (k->is()) { auto kr = k->to(); - key->emplace("start", stringRepr(kr->left->to()->value, k8)); - key->emplace("end", stringRepr(kr->right->to()->value, k8)); + key->emplace("start"_cs, + stringRepr(kr->left->to()->value, k8)); + key->emplace("end"_cs, + stringRepr(kr->right->to()->value, k8)); } else if (k->is()) { - key->emplace("start", stringRepr(k->to()->value, k8)); - key->emplace("end", stringRepr(k->to()->value, k8)); + key->emplace("start"_cs, stringRepr(k->to()->value, k8)); + key->emplace("end"_cs, stringRepr(k->to()->value, k8)); } else if (k->is()) { - key->emplace("start", stringRepr(0, k8)); - key->emplace("end", stringRepr((1 << keyWidth) - 1, k8)); // 2^N -1 + key->emplace("start"_cs, stringRepr(0, k8)); + key->emplace("end"_cs, stringRepr((1 << keyWidth) - 1, k8)); // 2^N -1 } else { ::error(ErrorType::ERR_UNSUPPORTED, "%1% unsupported range key expression", k); @@ -536,11 +539,11 @@ class ControlConverter : public Inspector { // allow exact values or a DefaultExpression (_ or // default), no &&& expression. if (k->is()) { - key->emplace("key", stringRepr(k->to()->value, k8)); - key->emplace("mask", stringRepr(Util::mask(keyWidth), k8)); + key->emplace("key"_cs, stringRepr(k->to()->value, k8)); + key->emplace("mask"_cs, stringRepr(Util::mask(keyWidth), k8)); } else if (k->is()) { - key->emplace("key", stringRepr(0, k8)); - key->emplace("mask", stringRepr(0, k8)); + key->emplace("key"_cs, stringRepr(0, k8)); + key->emplace("mask"_cs, stringRepr(0, k8)); } else { ::error(ErrorType::ERR_UNSUPPORTED, "%1%: unsupported optional key expression", k); @@ -563,14 +566,14 @@ class ControlConverter : public Inspector { auto actionDecl = decl->to(); unsigned id = get(ctxt->structure->ids, actionDecl, INVALID_ACTION_ID); BUG_CHECK(id != INVALID_ACTION_ID, "Could not find id for %1%", actionDecl); - action->emplace("action_id", id); - auto actionData = mkArrayField(action, "action_data"); + action->emplace("action_id"_cs, id); + auto actionData = mkArrayField(action, "action_data"_cs); for (auto arg : *actionCall->arguments) { actionData->append(stringRepr(arg->expression->to()->value, 0)); } - entry->emplace("action_entry", action); + entry->emplace("action_entry"_cs, action); - auto priorityAnnotation = e->getAnnotation("priority"); + auto priorityAnnotation = e->getAnnotation("priority"_cs); if (priorityAnnotation != nullptr) { if (priorityAnnotation->expr.size() > 1) ::error(ErrorType::ERR_INVALID, "Invalid priority value %1%", @@ -579,9 +582,9 @@ class ControlConverter : public Inspector { if (!priValue->is()) ::error(ErrorType::ERR_INVALID, "Invalid priority value %1%; must be constant.", priorityAnnotation->expr); - entry->emplace("priority", priValue->to()->value); + entry->emplace("priority"_cs, priValue->to()->value); } else { - entry->emplace("priority", entryPriority); + entry->emplace("priority"_cs, entryPriority); } entryPriority += 1; @@ -600,14 +603,14 @@ class ControlConverter : public Inspector { } ::error(ErrorType::ERR_UNSUPPORTED, "%1%: match type not supported on this target", mt); - return "invalid"; + return "invalid"_cs; } /// Return 'true' if the table is 'simple' bool handleTableImplementation(const IR::Property *implementation, const IR::Key *key, Util::JsonObject *table, Util::JsonArray *action_profiles, BMV2::SharedActionSelectorCheck *) { if (implementation == nullptr) { - table->emplace("type", "simple"); + table->emplace("type"_cs, "simple"); return true; } @@ -637,9 +640,10 @@ class ControlConverter : public Inspector { apname = implementation->controlPlaneName(ctxt->refMap->newName("action_profile")); action_profile = new Util::JsonObject(); action_profiles->append(action_profile); - action_profile->emplace("name", apname); - action_profile->emplace("id", nextId("action_profiles")); - action_profile->emplace_non_null("source_info", propv->expression->sourceInfoJsonObj()); + action_profile->emplace("name"_cs, apname); + action_profile->emplace("id"_cs, nextId("action_profiles"_cs)); + action_profile->emplace_non_null("source_info"_cs, + propv->expression->sourceInfoJsonObj()); // TODO(jafingerhut) - add line/col here? // TBD what about the else if cases below? @@ -652,7 +656,7 @@ class ControlConverter : public Inspector { } else { size = size_expr->to()->asInt(); } - action_profile->emplace("max_size", size); + action_profile->emplace("max_size"_cs, size); }; auto actionSelectorName = Standard::ActionSelectorTraits::typeName(); @@ -660,8 +664,8 @@ class ControlConverter : public Inspector { BUG_CHECK(arguments->size() == 3, "%1%: expected 3 arguments", arguments); isSimpleTable = false; auto selector = new Util::JsonObject(); - table->emplace("type", "indirect_ws"); - action_profile->emplace("selector", selector); + table->emplace("type"_cs, "indirect_ws"); + action_profile->emplace("selector"_cs, selector); add_size(1); auto hash = arguments->at(0)->expression; auto ei = P4::EnumInstance::resolve(hash, ctxt->typeMap); @@ -670,9 +674,9 @@ class ControlConverter : public Inspector { hash); } else { cstring algo = ei->name; - selector->emplace("algo", algo); + selector->emplace("algo"_cs, algo); } - auto input = mkArrayField(selector, "input"); + auto input = mkArrayField(selector, "input"_cs); for (auto ke : key->keyElements) { auto mt = ctxt->refMap->getDeclaration(ke->matchType->path, true) ->to(); @@ -686,7 +690,7 @@ class ControlConverter : public Inspector { } else if (implementationType->name == Standard::ActionProfileTraits::typeName()) { isSimpleTable = false; - table->emplace("type", "indirect"); + table->emplace("type"_cs, "indirect"); add_size(0); } else { ::error(ErrorType::ERR_UNEXPECTED, "%1%: expected value for property", propv); @@ -709,9 +713,9 @@ class ControlConverter : public Inspector { auto actionProfileName = Standard::ActionProfileTraits::typeName(); auto actionSelectorName = Standard::ActionSelectorTraits::typeName(); if (type_extern_name == actionProfileName) { - table->emplace("type", "indirect"); + table->emplace("type"_cs, "indirect"); } else if (type_extern_name == actionSelectorName) { - table->emplace("type", "indirect_ws"); + table->emplace("type"_cs, "indirect_ws"); } else { ::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected type for implementation", dcltype); @@ -728,19 +732,19 @@ class ControlConverter : public Inspector { ::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected value for property", propv); return false; } - table->emplace("action_profile", apname); + table->emplace("action_profile"_cs, apname); return isSimpleTable; } Util::IJson *convertIf(const CFG::IfNode *node, cstring prefix) { (void)prefix; auto result = new Util::JsonObject(); - result->emplace("name", node->name); - result->emplace("id", nextId("conditionals")); - result->emplace_non_null("source_info", node->statement->condition->sourceInfoJsonObj()); + result->emplace("name"_cs, node->name); + result->emplace("id"_cs, nextId("conditionals"_cs)); + result->emplace_non_null("source_info"_cs, node->statement->condition->sourceInfoJsonObj()); auto j = ctxt->conv->convert(node->statement->condition, true, false); CHECK_NULL(j); - result->emplace("expression", j); + result->emplace("expression"_cs, j); for (auto e : node->successors.edges) { Util::IJson *dest = nodeName(e->endpoint); cstring label = Util::toString(e->getBool()); @@ -755,9 +759,9 @@ class ControlConverter : public Inspector { bool preorder(const IR::P4Control *cont) override { auto result = new Util::JsonObject(); - result->emplace("name", name); - result->emplace("id", nextId("control")); - result->emplace_non_null("source_info", cont->sourceInfoJsonObj()); + result->emplace("name"_cs, name); + result->emplace("id"_cs, nextId("control"_cs)); + result->emplace_non_null("source_info"_cs, cont->sourceInfoJsonObj()); auto cfg = new CFG(); cfg->build(cont, ctxt->refMap, ctxt->typeMap); @@ -765,17 +769,17 @@ class ControlConverter : public Inspector { if (!success) return false; if (cfg->entryPoint->successors.size() == 0) { - result->emplace("init_table", Util::JsonValue::null); + result->emplace("init_table"_cs, 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)); + result->emplace("init_table"_cs, nodeName(start)); } - auto tables = mkArrayField(result, "tables"); - auto action_profiles = mkArrayField(result, "action_profiles"); - auto conditionals = mkArrayField(result, "conditionals"); + auto tables = mkArrayField(result, "tables"_cs); + auto action_profiles = mkArrayField(result, "action_profiles"_cs); + auto conditionals = mkArrayField(result, "conditionals"_cs); ctxt->action_profiles = action_profiles; auto selector_check = new BMV2::SharedActionSelectorCheck(ctxt); diff --git a/backends/bmv2/common/controlFlowGraph.cpp b/backends/bmv2/common/controlFlowGraph.cpp index 3fde0cffbb..d532f88161 100644 --- a/backends/bmv2/common/controlFlowGraph.cpp +++ b/backends/bmv2/common/controlFlowGraph.cpp @@ -27,6 +27,8 @@ limitations under the License. namespace BMV2 { +using namespace P4::literals; + unsigned CFG::Node::crtId = 0; void CFG::EdgeSet::dbprint(std::ostream &out) const { @@ -260,7 +262,7 @@ class CFGBuilder : public Inspector { for (auto sw : statement->cases) { cstring label; if (sw->label->is()) { - label = "default"; + label = "default"_cs; } else { auto pe = sw->label->to(); CHECK_NULL(pe); @@ -294,7 +296,7 @@ class CFGBuilder : public Inspector { void CFG::build(const IR::P4Control *cc, P4::ReferenceMap *refMap, P4::TypeMap *typeMap) { container = cc; entryPoint = makeNode(cc->name + ".entry"); - exitPoint = makeNode(""); // the only node with an empty name + exitPoint = makeNode(cstring::empty); // the only node with an empty name CFGBuilder builder(this, refMap, typeMap); auto startValue = new CFG::EdgeSet(new CFG::Edge(entryPoint)); diff --git a/backends/bmv2/common/deparser.cpp b/backends/bmv2/common/deparser.cpp index 30124c7a1d..bbd7b9d75a 100644 --- a/backends/bmv2/common/deparser.cpp +++ b/backends/bmv2/common/deparser.cpp @@ -59,9 +59,9 @@ void DeparserConverter::convertDeparserBody(const IR::Vector *bo } else if (assign->right->is()) { ctxt->conv->simpleExpressionsOnly = false; auto json = new Util::JsonObject(); - auto params = mkArrayField(json, "parameters"); + auto params = mkArrayField(json, "parameters"_cs); auto type = ctxt->typeMap->getType(assign->left, true); - json->emplace("op", "set"); + json->emplace("op"_cs, "set"); auto l = ctxt->conv->convertLeftValue(assign->left); bool convertBool = type->is(); auto r = ctxt->conv->convert(assign->right, true, true, convertBool); @@ -85,7 +85,7 @@ void DeparserConverter::convertDeparserBody(const IR::Vector *bo auto type = ctxt->typeMap->getType(arg, true); if (type->is()) { auto j = ctxt->conv->convert(arg->expression); - auto val = j->to()->get("value"); + auto val = j->to()->get("value"_cs); order->append(val); } else { // We don't need to handle other types, @@ -132,11 +132,11 @@ void DeparserConverter::convertDeparserBody(const IR::Vector *bo Util::IJson *DeparserConverter::convertDeparser(const IR::P4Control *ctrl) { auto result = new Util::JsonObject(); - result->emplace("name", name); - result->emplace("id", nextId("deparser")); - result->emplace_non_null("source_info", ctrl->sourceInfoJsonObj()); - auto order = mkArrayField(result, "order"); - auto primitives = mkArrayField(result, "primitives"); + result->emplace("name"_cs, name); + result->emplace("id"_cs, nextId("deparser"_cs)); + result->emplace_non_null("source_info"_cs, ctrl->sourceInfoJsonObj()); + auto order = mkArrayField(result, "order"_cs); + auto primitives = mkArrayField(result, "primitives"_cs); convertDeparserBody(&ctrl->body->components, order, primitives); return result; } diff --git a/backends/bmv2/common/deparser.h b/backends/bmv2/common/deparser.h index 97e0ccc000..f273199454 100644 --- a/backends/bmv2/common/deparser.h +++ b/backends/bmv2/common/deparser.h @@ -39,7 +39,7 @@ class DeparserConverter : public Inspector { public: bool preorder(const IR::P4Control *ctrl) override; - explicit DeparserConverter(ConversionContext *ctxt, cstring name = "deparser") + explicit DeparserConverter(ConversionContext *ctxt, cstring name = "deparser"_cs) : ctxt(ctxt), name(name), corelib(P4::P4CoreLibrary::instance()) { setName("DeparserConverter"); } diff --git a/backends/bmv2/common/expression.cpp b/backends/bmv2/common/expression.cpp index 92212679de..f7de266ee2 100644 --- a/backends/bmv2/common/expression.cpp +++ b/backends/bmv2/common/expression.cpp @@ -99,8 +99,8 @@ Util::IJson *ExpressionConverter::get(const IR::Expression *expression) const { void ExpressionConverter::postorder(const IR::BoolLiteral *expression) { auto result = new Util::JsonObject(); - result->emplace("type", "bool"); - result->emplace("value", expression->value); + result->emplace("type"_cs, "bool"); + result->emplace("value"_cs, expression->value); mapExpression(expression, result); } @@ -116,8 +116,8 @@ void ExpressionConverter::postorder(const IR::MethodCallExpression *expression) int width = typearg->width_bits(); BUG_CHECK(width > 0, "%1%: unknown width", targ); auto j = new Util::JsonObject(); - j->emplace("type", "lookahead"); - auto v = mkArrayField(j, "value"); + j->emplace("type"_cs, "lookahead"); + auto v = mkArrayField(j, "value"_cs); v->append(0); v->append(width); mapExpression(expression, j); @@ -130,18 +130,18 @@ void ExpressionConverter::postorder(const IR::MethodCallExpression *expression) auto l = get(bim->appliedTo); if (!l) return; if (type->is()) { - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - result->emplace("value", e); - e->emplace("op", "valid_union"); - e->emplace("left", Util::JsonValue::null); - e->emplace("right", l); + result->emplace("value"_cs, e); + e->emplace("op"_cs, "valid_union"); + e->emplace("left"_cs, Util::JsonValue::null); + e->emplace("right"_cs, l); } else { // Treat this as appliedTo.$valid$ - result->emplace("type", "field"); - auto e = mkArrayField(result, "value"); + result->emplace("type"_cs, "field"); + auto e = mkArrayField(result, "value"_cs); if (l->is()) - e->append(l->to()->get("value")); + e->append(l->to()->get("value"_cs)); else e->append(l); e->append(V1ModelProperties::validField); @@ -150,11 +150,11 @@ void ExpressionConverter::postorder(const IR::MethodCallExpression *expression) // for table keys we don't need the casts. auto cast = new Util::JsonObject(); auto value = new Util::JsonObject(); - cast->emplace("type", "expression"); - cast->emplace("value", value); - value->emplace("op", "d2b"); // data to Boolean cast - value->emplace("left", Util::JsonValue::null); - value->emplace("right", result); + cast->emplace("type"_cs, "expression"); + cast->emplace("value"_cs, value); + value->emplace("op"_cs, "d2b"); // data to Boolean cast + value->emplace("left"_cs, Util::JsonValue::null); + value->emplace("right"_cs, result); result = cast; } } @@ -175,11 +175,11 @@ void ExpressionConverter::postorder(const IR::Cast *expression) { void ExpressionConverter::postorder(const IR::Constant *expression) { auto result = new Util::JsonObject(); - result->emplace("type", "hexstr"); + result->emplace("type"_cs, "hexstr"); auto bitwidth = expression->type->width_bits(); cstring repr = stringRepr(expression->value, ROUNDUP(bitwidth, 8)); - result->emplace("value", repr); - if (withConstantWidths) result->emplace("bitwidth", bitwidth); + result->emplace("value"_cs, repr); + if (withConstantWidths) result->emplace("bitwidth"_cs, bitwidth); mapExpression(expression, result); } @@ -213,21 +213,21 @@ void ExpressionConverter::postorder(const IR::ArrayIndex *expression) { } BUG_CHECK(fresult, "%1%: Runtime array index json generation failed", ex); Util::JsonObject *fres = fresult->to(); - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - e->emplace("op", "dereference_header_stack"); + e->emplace("op"_cs, "dereference_header_stack"); auto l = new Util::JsonObject(); - l->emplace("type", "header_stack"); - l->emplace("value", elementAccess); - e->emplace("left", l); - e->emplace("right", fres); - result->emplace("value", e); + l->emplace("type"_cs, "header_stack"); + l->emplace("value"_cs, elementAccess); + e->emplace("left"_cs, l); + e->emplace("right"_cs, fres); + result->emplace("value"_cs, e); } else { - result->emplace("type", "header"); + result->emplace("type"_cs, "header"); int index = expression->right->to()->asInt(); elementAccess += "[" + Util::toString(index) + "]"; - result->emplace("value", elementAccess); + result->emplace("value"_cs, elementAccess); } mapExpression(expression, result); } @@ -266,12 +266,12 @@ void ExpressionConverter::postorder(const IR::Member *expression) { // handle error if (type->is() && expression->expr->is()) { // this deals with constants that have type 'error' - result->emplace("type", "hexstr"); + result->emplace("type"_cs, "hexstr"); auto decl = type->to()->getDeclByName(expression->member.name); auto errorValue = structure->errorCodesMap.at(decl); // this generates error constant like hex value auto reprValue = stringRepr(errorValue); - result->emplace("value", reprValue); + result->emplace("value"_cs, reprValue); mapExpression(expression, result); return; } @@ -287,27 +287,27 @@ void ExpressionConverter::postorder(const IR::Member *expression) { if (auto st = type->to()) { auto et = typeMap->getTypeType(st->elementType, true); if (et->is()) - result->emplace("type", "header_union_stack"); + result->emplace("type"_cs, "header_union_stack"); else - result->emplace("type", "header_stack"); - result->emplace("value", fieldName); + result->emplace("type"_cs, "header_stack"); + result->emplace("value"_cs, fieldName); } else if (type->is()) { - result->emplace("type", "header_union"); - result->emplace("value", fieldName); + result->emplace("type"_cs, "header_union"); + result->emplace("value"_cs, fieldName); } else if (parentType->is()) { auto l = get(expression->expr); if (!l) return; cstring nestedField = fieldName; if (auto lv = l->to()) { - lv->get("value"); + lv->get("value"_cs); if (lv->is()) { // header in union reference ["u", "f"] => "u.f" cstring prefix = lv->to()->getString(); nestedField = prefix + "." + nestedField; } } - result->emplace("type", "header"); - result->emplace("value", nestedField); + result->emplace("type"_cs, "header"); + result->emplace("value"_cs, nestedField); } else if (parentType->is() && (type->is() || type->is() || type->is())) { @@ -318,32 +318,32 @@ void ExpressionConverter::postorder(const IR::Member *expression) { BUG_CHECK((name != nullptr), "NULL name: %1%", field->name); if (type->is() || type->is() || leftValue || simpleExpressionsOnly) { - result->emplace("type", "field"); - auto e = mkArrayField(result, "value"); + result->emplace("type"_cs, "field"); + auto e = mkArrayField(result, "value"_cs); e->append(scalarsName); e->append(name); } else if (type->is()) { // Boolean variables are stored as ints, so we // have to insert a conversion when reading such a // variable - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - result->emplace("value", e); - e->emplace("op", "d2b"); // data to Boolean cast - e->emplace("left", Util::JsonValue::null); + result->emplace("value"_cs, e); + e->emplace("op"_cs, "d2b"); // data to Boolean cast + e->emplace("left"_cs, Util::JsonValue::null); auto r = new Util::JsonObject(); - e->emplace("right", r); + e->emplace("right"_cs, r); - r->emplace("type", "field"); - auto a = mkArrayField(r, "value"); + r->emplace("type"_cs, "field"); + auto a = mkArrayField(r, "value"_cs); a->append(scalarsName); a->append(name); } } else { // This may be wrong, but the caller will handle it properly // (e.g., this can be a method, such as packet.lookahead) - result->emplace("type", "header"); - result->emplace("value", fieldName); + result->emplace("type"_cs, "header"); + result->emplace("value"_cs, fieldName); } mapExpression(expression, result); return; @@ -359,10 +359,10 @@ void ExpressionConverter::postorder(const IR::Member *expression) { if (memtype->is() && mem->member == IR::Type_Stack::last) { auto l = get(mem->expr); if (!l) return; - result->emplace("type", "stack_field"); - auto e = mkArrayField(result, "value"); + result->emplace("type"_cs, "stack_field"); + auto e = mkArrayField(result, "value"_cs); if (l->is()) - e->append(l->to()->get("value")); + e->append(l->to()->get("value"_cs)); else e->append(l); e->append(fieldName); @@ -375,42 +375,42 @@ void ExpressionConverter::postorder(const IR::Member *expression) { if (!l) return; if (parentType->is()) { BUG_CHECK(l->is(), "Not a JsonObject"); - auto lv = l->to()->get("value"); + auto lv = l->to()->get("value"_cs); if (lv->is()) { fieldName = lv->to()->getString() + "." + fieldName; // Each header in a union is allocated a separate header instance. // Refer to that instance directly. - result->emplace("type", "header"); - result->emplace("value", fieldName); + result->emplace("type"_cs, "header"); + result->emplace("value"_cs, fieldName); } else { // lv must be a reference to a union stack field auto a = lv->to()->clone(); CHECK_NULL(a); - result->emplace("type", "union_stack_field"); + result->emplace("type"_cs, "union_stack_field"); a->append(fieldName); - result->emplace("value", a); + result->emplace("value"_cs, a); } } else if (parentType->is() && expression->member == IR::Type_Stack::lastIndex) { auto l = get(expression->expr); if (!l) return; - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - result->emplace("value", e); - e->emplace("op", "last_stack_index"); - e->emplace("left", Util::JsonValue::null); - e->emplace("right", l); + result->emplace("value"_cs, e); + e->emplace("op"_cs, "last_stack_index"); + e->emplace("left"_cs, Util::JsonValue::null); + e->emplace("right"_cs, l); } else { const char *fieldRef = parentType->is() ? "stack_field" : "field"; Util::JsonArray *e = nullptr; bool st = isArrayIndexRuntime(expression); if (!st) { - result->emplace("type", fieldRef); - e = mkArrayField(result, "value"); + result->emplace("type"_cs, fieldRef); + e = mkArrayField(result, "value"_cs); } if (l->is()) { - auto lv = l->to()->get("value"); + auto lv = l->to()->get("value"_cs); if (lv->is()) { // TODO: is this case still necessary after eliminating nested structs? // nested struct reference [ ["m", "f"], "x" ] => [ "m", "f.x" ] @@ -436,12 +436,12 @@ void ExpressionConverter::postorder(const IR::Member *expression) { "for runtime index computation %1%", st); } - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - result->emplace("value", e); - e->emplace("op", "access_field"); - e->emplace("left", jo); - e->emplace("right", index_pos); + result->emplace("value"_cs, e); + e->emplace("op"_cs, "access_field"); + e->emplace("left"_cs, jo); + e->emplace("right"_cs, index_pos); } } else { BUG("%1%: Unexpected json", lv); @@ -454,11 +454,11 @@ void ExpressionConverter::postorder(const IR::Member *expression) { if (!simpleExpressionsOnly && !leftValue && type->is()) { auto cast = new Util::JsonObject(); auto value = new Util::JsonObject(); - cast->emplace("type", "expression"); - cast->emplace("value", value); - value->emplace("op", "d2b"); // data to Boolean cast - value->emplace("left", Util::JsonValue::null); - value->emplace("right", result); + cast->emplace("type"_cs, "expression"); + cast->emplace("value"_cs, value); + value->emplace("op"_cs, "d2b"); // data to Boolean cast + value->emplace("left"_cs, Util::JsonValue::null); + value->emplace("right"_cs, result); result = cast; } } @@ -469,12 +469,12 @@ void ExpressionConverter::postorder(const IR::Member *expression) { Util::IJson *ExpressionConverter::fixLocal(Util::IJson *json) { if (!json) return new Util::JsonValue(); // null if (auto jo = json->to()) { - auto to = jo->get("type"); + auto to = jo->get("type"_cs); if (to != nullptr && to->to() != nullptr && (*to->to()) == "runtime_data") { auto result = new Util::JsonObject(); - result->emplace("type", "local"); - result->emplace("value", jo->get("value")); + result->emplace("type"_cs, "local"); + result->emplace("value"_cs, jo->get("value"_cs)); return result; } } @@ -490,36 +490,36 @@ void ExpressionConverter::postorder(const IR::Mux *expression) { return; } - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - result->emplace("value", e); - e->emplace("op", "?"); + result->emplace("value"_cs, e); + e->emplace("op"_cs, "?"); auto l = get(expression->e1); if (!l) return; - e->emplace("left", fixLocal(l)); + e->emplace("left"_cs, fixLocal(l)); auto r = get(expression->e2); if (!r) return; - e->emplace("right", fixLocal(r)); + e->emplace("right"_cs, fixLocal(r)); auto c = get(expression->e0); if (!c) return; - e->emplace("cond", fixLocal(c)); + e->emplace("cond"_cs, fixLocal(c)); } void ExpressionConverter::postorder(const IR::IntMod *expression) { auto result = new Util::JsonObject(); mapExpression(expression, result); - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - result->emplace("value", e); - e->emplace("op", "two_comp_mod"); + result->emplace("value"_cs, e); + e->emplace("op"_cs, "two_comp_mod"); auto l = get(expression->expr); if (!l) return; - e->emplace("left", fixLocal(l)); + e->emplace("left"_cs, fixLocal(l)); auto r = new Util::JsonObject(); - r->emplace("type", "hexstr"); + r->emplace("type"_cs, "hexstr"); cstring repr = stringRepr(expression->width); - r->emplace("value", repr); - e->emplace("right", r); + r->emplace("value"_cs, repr); + e->emplace("right"_cs, r); } void ExpressionConverter::postorder(const IR::Operation_Binary *expression) { binary(expression); } @@ -533,21 +533,21 @@ void ExpressionConverter::binary(const IR::Operation_Binary *expression) { return; } - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - result->emplace("value", e); + result->emplace("value"_cs, e); cstring op = expression->getStringOp(); if (op == "&&") - op = "and"; + op = "and"_cs; else if (op == "||") - op = "or"; - e->emplace("op", op); + op = "or"_cs; + e->emplace("op"_cs, op); auto l = get(expression->left); if (!l) return; - e->emplace("left", fixLocal(l)); + e->emplace("left"_cs, fixLocal(l)); auto r = get(expression->right); if (!r) return; - e->emplace("right", fixLocal(r)); + e->emplace("right"_cs, fixLocal(r)); } void ExpressionConverter::saturated_binary(const IR::Operation_Binary *expression) { @@ -556,30 +556,30 @@ void ExpressionConverter::saturated_binary(const IR::Operation_Binary *expressio auto result = new Util::JsonObject(); mapExpression(expression, result); - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - result->emplace("value", e); + result->emplace("value"_cs, e); auto eType = expression->type->to(); CHECK_NULL(eType); auto opType = eType->isSigned ? "sat_cast" : "usat_cast"; - e->emplace("op", opType); + e->emplace("op"_cs, opType); // the left operand is the binary expression, but as a simple add/sub auto eLeft = new Util::JsonObject(); - eLeft->emplace("type", "expression"); + eLeft->emplace("type"_cs, "expression"); auto e1 = new Util::JsonObject(); - e1->emplace("op", expression->getStringOp() == "|+|" ? "+" : "-"); - e1->emplace("left", fixLocal(get(expression->left))); - e1->emplace("right", fixLocal(get(expression->right))); - eLeft->emplace("value", e1); - e->emplace("left", eLeft); + e1->emplace("op"_cs, expression->getStringOp() == "|+|" ? "+" : "-"); + e1->emplace("left"_cs, fixLocal(get(expression->left))); + e1->emplace("right"_cs, fixLocal(get(expression->right))); + eLeft->emplace("value"_cs, e1); + e->emplace("left"_cs, eLeft); // the right operand is the width of the type auto r = new Util::JsonObject(); - r->emplace("type", "hexstr"); + r->emplace("type"_cs, "hexstr"); cstring repr = stringRepr(eType->width_bits()); - r->emplace("value", repr); - e->emplace("right", r); + r->emplace("value"_cs, repr); + e->emplace("right"_cs, r); } void ExpressionConverter::postorder(const IR::ListExpression *expression) { @@ -624,16 +624,16 @@ void ExpressionConverter::postorder(const IR::Operation_Unary *expression) { return; } - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - result->emplace("value", e); + result->emplace("value"_cs, e); cstring op = expression->getStringOp(); - if (op == "!") op = "not"; - e->emplace("op", op); - e->emplace("left", Util::JsonValue::null); + if (op == "!") op = "not"_cs; + e->emplace("op"_cs, op); + e->emplace("left"_cs, Util::JsonValue::null); auto r = get(expression->expr); if (!r) return; - e->emplace("right", fixLocal(r)); + e->emplace("right"_cs, fixLocal(r)); } void ExpressionConverter::postorder(const IR::PathExpression *expression) { @@ -643,11 +643,11 @@ void ExpressionConverter::postorder(const IR::PathExpression *expression) { if (structure->nonActionParameters.find(param) != structure->nonActionParameters.end()) { auto type = typeMap->getType(param, true); if (type->is()) { - auto result = convertParam(param, ""); + auto result = convertParam(param, cstring::empty); if (result == nullptr) { auto r = new Util::JsonObject(); - r->emplace("type", "header"); - r->emplace("value", param->name.name); + r->emplace("type"_cs, "header"); + r->emplace("value"_cs, param->name.name); result = r; } mapExpression(expression, result); @@ -657,56 +657,56 @@ void ExpressionConverter::postorder(const IR::PathExpression *expression) { return; } auto result = new Util::JsonObject(); - result->emplace("type", "runtime_data"); + result->emplace("type"_cs, "runtime_data"); unsigned paramIndex = ::get(&structure->index, param); - result->emplace("value", paramIndex); + result->emplace("value"_cs, paramIndex); mapExpression(expression, result); } else if (auto var = decl->to()) { LOG3("Variable to json " << var); auto result = new Util::JsonObject(); auto type = typeMap->getType(var, true); if (type->is()) { - result->emplace("type", "header"); - result->emplace("value", var->name); + result->emplace("type"_cs, "header"); + result->emplace("value"_cs, var->name); } else if (type->is() || (type->is() && (leftValue || simpleExpressionsOnly))) { // no conversion d2b when writing (leftValue is true) to a boolean - result->emplace("type", "field"); - auto e = mkArrayField(result, "value"); + result->emplace("type"_cs, "field"); + auto e = mkArrayField(result, "value"_cs); e->append(scalarsName); e->append(var->name); } else if (type->is()) { // varbits are synthesized in separate metadata instances // with a single field each, where the field is named // "field". - result->emplace("type", "field"); - auto e = mkArrayField(result, "value"); + result->emplace("type"_cs, "field"); + auto e = mkArrayField(result, "value"_cs); e->append(var->name); e->append("field"); } else if (type->is()) { // Boolean variables are stored as ints, so we have to insert a conversion when // reading such a variable - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto e = new Util::JsonObject(); - result->emplace("value", e); - e->emplace("op", "d2b"); // data to Boolean cast - e->emplace("left", Util::JsonValue::null); + result->emplace("value"_cs, e); + e->emplace("op"_cs, "d2b"); // data to Boolean cast + e->emplace("left"_cs, Util::JsonValue::null); auto r = new Util::JsonObject(); - e->emplace("right", r); - r->emplace("type", "field"); - auto f = mkArrayField(r, "value"); + e->emplace("right"_cs, r); + r->emplace("type"_cs, "field"); + auto f = mkArrayField(r, "value"_cs); f->append(scalarsName); f->append(var->name); } else if (auto st = type->to()) { auto et = typeMap->getTypeType(st->elementType, true); if (et->is()) - result->emplace("type", "header_union_stack"); + result->emplace("type"_cs, "header_union_stack"); else - result->emplace("type", "header_stack"); - result->emplace("value", var->name); + result->emplace("type"_cs, "header_stack"); + result->emplace("value"_cs, var->name); } else if (type->is()) { - result->emplace("type", "field"); - auto f = mkArrayField(result, "value"); + result->emplace("type"_cs, "field"); + auto f = mkArrayField(result, "value"_cs); f->append(scalarsName); f->append(var->name); } else { @@ -718,8 +718,8 @@ void ExpressionConverter::postorder(const IR::PathExpression *expression) { void ExpressionConverter::postorder(const IR::StringLiteral *expression) { auto result = new Util::JsonObject(); - result->emplace("type", "string"); - result->emplace("value", expression->value); + result->emplace("type"_cs, "string"); + result->emplace("value"_cs, expression->value); mapExpression(expression, result); } @@ -731,18 +731,18 @@ void ExpressionConverter::postorder(const IR::Slice *expression) { int h = expression->getH(); int l = expression->getL(); auto mask = Util::maskFromSlice(h, l); - result->emplace("type", "expression"); + result->emplace("type"_cs, "expression"); auto band = new Util::JsonObject(); - result->emplace("value", band); - band->emplace("op", "&"); + result->emplace("value"_cs, band); + band->emplace("op"_cs, "&"); auto right = new Util::JsonObject(); auto bitwidth = expression->type->width_bits(); - right->emplace("type", "hexstr"); - right->emplace("value", stringRepr(mask, ROUNDUP(bitwidth, 8))); + right->emplace("type"_cs, "hexstr"); + right->emplace("value"_cs, stringRepr(mask, ROUNDUP(bitwidth, 8))); auto le = get(expr); if (!le) return; - band->emplace("left", le); - band->emplace("right", right); + band->emplace("left"_cs, le); + band->emplace("right"_cs, right); mapExpression(expression, result); } @@ -785,27 +785,27 @@ Util::IJson *ExpressionConverter::convert(const IR::Expression *e, bool doFixup, auto type = typeMap->getType(e, true); if (convertBool && type->is()) { auto obj = new Util::JsonObject(); - obj->emplace("type", "expression"); + obj->emplace("type"_cs, "expression"); auto conv = new Util::JsonObject(); - obj->emplace("value", conv); - conv->emplace("op", "b2d"); // boolean to data cast - conv->emplace("left", Util::JsonValue::null); - conv->emplace("right", result); + obj->emplace("value"_cs, conv); + conv->emplace("op"_cs, "b2d"); // boolean to data cast + conv->emplace("left"_cs, Util::JsonValue::null); + conv->emplace("right"_cs, result); result = obj; } - std::set to_wrap({"expression", "stack_field"}); + std::set to_wrap({"expression"_cs, "stack_field"_cs}); // This is weird, but that's how it is: expression and stack_field must be wrapped in // another outer object. In a future version of the bmv2 JSON, this will not be needed // anymore as expressions will be treated in a more uniform way. if (wrap) { if (auto ro = result->to()) { - if (auto to = ro->get("type")) { + if (auto to = ro->get("type"_cs)) { if (auto jv = to->to()) { if (jv->isString() && to_wrap.find(jv->getString()) != to_wrap.end()) { auto rwrap = new Util::JsonObject(); - rwrap->emplace("type", "expression"); - rwrap->emplace("value", result); + rwrap->emplace("type"_cs, "expression"); + rwrap->emplace("value"_cs, result); result = rwrap; } } diff --git a/backends/bmv2/common/extern.cpp b/backends/bmv2/common/extern.cpp index 5af3931084..f7926b5bab 100644 --- a/backends/bmv2/common/extern.cpp +++ b/backends/bmv2/common/extern.cpp @@ -60,10 +60,10 @@ Util::IJson *ExternConverter::convertExternObject(ConversionContext *ctxt, if (emitExterns) { auto primitive = mkPrimitive("_" + em->originalExternType->name + "_" + em->method->name); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", mc->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, mc->sourceInfoJsonObj()); auto etr = new Util::JsonObject(); - etr->emplace("type", "extern"); - etr->emplace("value", em->object->controlPlaneName()); + etr->emplace("type"_cs, "extern"); + etr->emplace("value"_cs, em->object->controlPlaneName()); parameters->append(etr); for (auto arg : *mc->arguments) { auto args = ctxt->conv->convert(arg->expression); @@ -92,10 +92,10 @@ void ExternConverter::convertExternInstance(ConversionContext *ctxt, const IR::D cstring type; cstring value; if (auto cst = val->to()) { - type = "hexstr"; + type = "hexstr"_cs; value = Util::toString(cst->value, 0, false, 16); } else if (auto str = val->to()) { - type = "string"; + type = "string"_cs; value = str->value; } else { modelError("%1%: parameter type not unsupported", param->type); @@ -116,7 +116,7 @@ Util::IJson *ExternConverter::convertExternFunction(ConversionContext *ctxt, return nullptr; } auto primitive = mkPrimitive(ef->method->name); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto parameters = mkParameters(primitive); for (auto arg : *mc->arguments) { auto args = ctxt->conv->convert(arg->expression); @@ -161,14 +161,14 @@ void ExternConverter::addToFieldList(ConversionContext *ctxt, const IR::Expressi auto j = ctxt->conv->convert(expr); ctxt->conv->simpleExpressionsOnly = simple; // restore state if (auto jo = j->to()) { - if (auto t = jo->get("type")) { + if (auto t = jo->get("type"_cs)) { if (auto type = t->to()) { if (*type == "runtime_data") { // Can't have runtime_data in field lists -- need hexstr instead - auto val = jo->get("value")->to(); + auto val = jo->get("value"_cs)->to(); j = jo = new Util::JsonObject(); - jo->emplace("type", "hexstr"); - jo->emplace("value", stringRepr(val->getValue())); + jo->emplace("type"_cs, "hexstr"); + jo->emplace("value"_cs, stringRepr(val->getValue())); } } } @@ -182,10 +182,10 @@ int ExternConverter::createFieldList(ConversionContext *ctxt, const IR::Expressi auto fl = new Util::JsonObject(); field_lists->append(fl); int id = nextId(group); - fl->emplace("id", id); - fl->emplace("name", listName); - fl->emplace_non_null("source_info", expr->sourceInfoJsonObj()); - auto elements = mkArrayField(fl, "elements"); + fl->emplace("id"_cs, id); + fl->emplace("name"_cs, listName); + fl->emplace_non_null("source_info"_cs, expr->sourceInfoJsonObj()); + auto elements = mkArrayField(fl, "elements"_cs); addToFieldList(ctxt, expr, elements); return id; } @@ -196,11 +196,11 @@ cstring ExternConverter::createCalculation(ConversionContext *ctxt, cstring algo const IR::Node *sourcePositionNode = nullptr) { cstring calcName = ctxt->refMap->newName("calc_"); auto calc = new Util::JsonObject(); - calc->emplace("name", calcName); - calc->emplace("id", nextId("calculations")); + calc->emplace("name"_cs, calcName); + calc->emplace("id"_cs, nextId("calculations"_cs)); if (sourcePositionNode != nullptr) - calc->emplace_non_null("source_info", sourcePositionNode->sourceInfoJsonObj()); - calc->emplace("algo", algo); + calc->emplace_non_null("source_info"_cs, sourcePositionNode->sourceInfoJsonObj()); + calc->emplace("algo"_cs, algo); fields = convertToList(fields, ctxt->typeMap); if (!fields) { modelError("%1%: expected a struct", fields); @@ -211,36 +211,27 @@ cstring ExternConverter::createCalculation(ConversionContext *ctxt, cstring algo auto array = jright->to(); BUG_CHECK(array, "expected a JSON array"); auto payload = new Util::JsonObject(); - payload->emplace("type", "payload"); - payload->emplace("value", (Util::IJson *)nullptr); + payload->emplace("type"_cs, "payload"); + payload->emplace("value"_cs, (Util::IJson *)nullptr); array->append(payload); } - calc->emplace("input", jright); + calc->emplace("input"_cs, jright); calculations->append(calc); return calcName; } cstring ExternConverter::convertHashAlgorithm(cstring algorithm) { - cstring result; - if (algorithm == P4V1::V1Model::instance.algorithm.crc32.name) - result = "crc32"; - else if (algorithm == P4V1::V1Model::instance.algorithm.crc32_custom.name) - result = "crc32_custom"; - else if (algorithm == P4V1::V1Model::instance.algorithm.crc16.name) - result = "crc16"; - else if (algorithm == P4V1::V1Model::instance.algorithm.crc16_custom.name) - result = "crc16_custom"; - else if (algorithm == P4V1::V1Model::instance.algorithm.random.name) - result = "random"; - else if (algorithm == P4V1::V1Model::instance.algorithm.identity.name) - result = "identity"; - else if (algorithm == P4V1::V1Model::instance.algorithm.csum16.name) - result = "csum16"; - else if (algorithm == P4V1::V1Model::instance.algorithm.xor16.name) - result = "xor16"; - else - ::error(ErrorType::ERR_UNSUPPORTED, "Unsupported algorithm %1%", algorithm); - return result; + if (algorithm == P4V1::V1Model::instance.algorithm.crc32.name) return "crc32"_cs; + if (algorithm == P4V1::V1Model::instance.algorithm.crc32_custom.name) return "crc32_custom"_cs; + if (algorithm == P4V1::V1Model::instance.algorithm.crc16.name) return "crc16"_cs; + if (algorithm == P4V1::V1Model::instance.algorithm.crc16_custom.name) return "crc16_custom"_cs; + if (algorithm == P4V1::V1Model::instance.algorithm.random.name) return "random"_cs; + if (algorithm == P4V1::V1Model::instance.algorithm.identity.name) return "identity"_cs; + if (algorithm == P4V1::V1Model::instance.algorithm.csum16.name) return "csum16"_cs; + if (algorithm == P4V1::V1Model::instance.algorithm.xor16.name) return "xor16"_cs; + + ::error(ErrorType::ERR_UNSUPPORTED, "Unsupported algorithm %1%", algorithm); + return cstring::empty; } ExternConverter_assert ExternConverter_assert::singleton; @@ -260,7 +251,7 @@ Util::IJson *ExternConverter::convertAssertAssume(ConversionContext *ctxt, // cast the result of expression to b2d auto jsonExpr = ctxt->conv->convert(cond->expression, true, true, true); parameters->append(jsonExpr); - primitive->emplace_non_null("source_info", methodCall->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, methodCall->sourceInfoJsonObj()); return primitive; } diff --git a/backends/bmv2/common/extern.h b/backends/bmv2/common/extern.h index 18dc14054e..463b12b441 100644 --- a/backends/bmv2/common/extern.h +++ b/backends/bmv2/common/extern.h @@ -74,7 +74,7 @@ class ExternConverter { class ExternConverter_##extern_name : public ExternConverter { \ model_type &model_name; \ ExternConverter_##extern_name() : model_name(model_type::instance) { \ - registerExternConverter(#extern_name, this); \ + registerExternConverter(cstring(#extern_name), this); \ } \ static ExternConverter_##extern_name singleton; \ Util::IJson *convertExternFunction(ConversionContext *ctxt, const P4::ExternFunction *ef, \ @@ -85,7 +85,7 @@ class ExternConverter { #define EXTERN_CONVERTER_W_FUNCTION(extern_name) \ class ExternConverter_##extern_name : public ExternConverter { \ - ExternConverter_##extern_name() { registerExternConverter(#extern_name, this); } \ + ExternConverter_##extern_name() { registerExternConverter(cstring(#extern_name), this); } \ static ExternConverter_##extern_name singleton; \ Util::IJson *convertExternFunction(ConversionContext *ctxt, const P4::ExternFunction *ef, \ const IR::MethodCallExpression *mc, \ @@ -97,26 +97,26 @@ class ExternConverter { class ExternConverter_##extern_name : public ExternConverter { \ model_type &model_name; \ ExternConverter_##extern_name() : model_name(model_type::instance) { \ - registerExternConverter(#extern_name, this); \ + registerExternConverter(cstring(#extern_name), this); \ } \ static ExternConverter_##extern_name singleton; \ void convertExternInstance(ConversionContext *ctxt, const IR::Declaration *c, \ const IR::ExternBlock *eb, const bool &emitExterns) override; \ }; -#define EXTERN_CONVERTER_W_INSTANCE(extern_name) \ - class ExternConverter_##extern_name : public ExternConverter { \ - ExternConverter_##extern_name() { registerExternConverter(#extern_name, this); } \ - static ExternConverter_##extern_name singleton; \ - void convertExternInstance(ConversionContext *ctxt, const IR::Declaration *c, \ - const IR::ExternBlock *eb, const bool &emitExterns) override; \ +#define EXTERN_CONVERTER_W_INSTANCE(extern_name) \ + class ExternConverter_##extern_name : public ExternConverter { \ + ExternConverter_##extern_name() { registerExternConverter(cstring(#extern_name), this); } \ + static ExternConverter_##extern_name singleton; \ + void convertExternInstance(ConversionContext *ctxt, const IR::Declaration *c, \ + const IR::ExternBlock *eb, const bool &emitExterns) override; \ }; #define EXTERN_CONVERTER_W_OBJECT_AND_INSTANCE_AND_MODEL(extern_name, type, name) \ class ExternConverter_##extern_name : public ExternConverter { \ type &name; \ ExternConverter_##extern_name() : name(type::instance) { \ - registerExternConverter(#extern_name, this); \ + registerExternConverter(cstring(#extern_name), this); \ } \ static ExternConverter_##extern_name singleton; \ void convertExternInstance(ConversionContext *ctxt, const IR::Declaration *c, \ @@ -127,16 +127,16 @@ class ExternConverter { const bool &emitExterns) override; \ }; -#define EXTERN_CONVERTER_W_OBJECT_AND_INSTANCE(extern_name) \ - class ExternConverter_##extern_name : public ExternConverter { \ - ExternConverter_##extern_name() { registerExternConverter(#extern_name, this); } \ - static ExternConverter_##extern_name singleton; \ - void convertExternInstance(ConversionContext *ctxt, const IR::Declaration *c, \ - const IR::ExternBlock *eb, const bool &emitExterns) override; \ - Util::IJson *convertExternObject(ConversionContext *ctxt, const P4::ExternMethod *em, \ - const IR::MethodCallExpression *mc, \ - const IR::StatOrDecl *s, \ - const bool &emitExterns) override; \ +#define EXTERN_CONVERTER_W_OBJECT_AND_INSTANCE(extern_name) \ + class ExternConverter_##extern_name : public ExternConverter { \ + ExternConverter_##extern_name() { registerExternConverter(cstring(#extern_name), this); } \ + static ExternConverter_##extern_name singleton; \ + void convertExternInstance(ConversionContext *ctxt, const IR::Declaration *c, \ + const IR::ExternBlock *eb, const bool &emitExterns) override; \ + Util::IJson *convertExternObject(ConversionContext *ctxt, const P4::ExternMethod *em, \ + const IR::MethodCallExpression *mc, \ + const IR::StatOrDecl *s, \ + const bool &emitExterns) override; \ }; EXTERN_CONVERTER_W_FUNCTION(assert) diff --git a/backends/bmv2/common/header.cpp b/backends/bmv2/common/header.cpp index 0a059d86bd..ff1b158a3d 100644 --- a/backends/bmv2/common/header.cpp +++ b/backends/bmv2/common/header.cpp @@ -287,7 +287,7 @@ void HeaderConverter::addHeaderType(const IR::Type_StructLike *st) { LOG2("... creating aliases for metadata fields " << st); for (auto f : st->fields) { - if (auto aliasAnnotation = f->getAnnotation("alias")) { + if (auto aliasAnnotation = f->getAnnotation("alias"_cs)) { auto container = new Util::JsonArray(); auto alias = new Util::JsonArray(); auto target_name = ""; @@ -399,7 +399,7 @@ Visitor::profile_t HeaderConverter::init_apply(const IR::Node *node) { // always-have metadata instance ctxt->json->add_metadata(scalarsTypeName, scalarsName); - ctxt->json->add_metadata("standard_metadata", "standard_metadata"); + ctxt->json->add_metadata("standard_metadata"_cs, "standard_metadata"_cs); return Inspector::init_apply(node); } @@ -443,7 +443,7 @@ bool HeaderConverter::preorder(const IR::Parameter *param) { else visitedHeaders.emplace(st->getName()); - if (st->getAnnotation("metadata")) { + if (st->getAnnotation("metadata"_cs)) { addHeaderType(st); } else { auto isHeader = isHeaders(st); diff --git a/backends/bmv2/common/helpers.cpp b/backends/bmv2/common/helpers.cpp index 3fc64dc49b..15cc47bbe8 100644 --- a/backends/bmv2/common/helpers.cpp +++ b/backends/bmv2/common/helpers.cpp @@ -19,12 +19,12 @@ limitations under the License. namespace BMV2 { /// constant definition for bmv2 -const cstring MatchImplementation::selectorMatchTypeName = "selector"; -const cstring MatchImplementation::rangeMatchTypeName = "range"; -const cstring MatchImplementation::optionalMatchTypeName = "optional"; +const cstring MatchImplementation::selectorMatchTypeName = "selector"_cs; +const cstring MatchImplementation::rangeMatchTypeName = "range"_cs; +const cstring MatchImplementation::optionalMatchTypeName = "optional"_cs; const unsigned TableAttributes::defaultTableSize = 1024; -const cstring V1ModelProperties::jsonMetadataParameterName = "standard_metadata"; -const cstring V1ModelProperties::validField = "$valid$"; +const cstring V1ModelProperties::jsonMetadataParameterName = "standard_metadata"_cs; +const cstring V1ModelProperties::validField = "$valid$"_cs; Util::IJson *nodeName(const CFG::Node *node) { if (node->name.isNullOrEmpty()) @@ -40,26 +40,26 @@ Util::JsonArray *mkArrayField(Util::JsonObject *parent, cstring name) { } Util::JsonArray *mkParameters(Util::JsonObject *object) { - return mkArrayField(object, "parameters"); + return mkArrayField(object, "parameters"_cs); } Util::JsonObject *mkPrimitive(cstring name, Util::JsonArray *appendTo) { auto result = new Util::JsonObject(); - result->emplace("op", name); + result->emplace("op"_cs, name); appendTo->append(result); return result; } Util::JsonObject *mkPrimitive(cstring name) { auto result = new Util::JsonObject(); - result->emplace("op", name); + result->emplace("op"_cs, name); return result; } cstring stringRepr(big_int value, unsigned bytes) { - cstring sign = ""; + std::string sign; std::stringstream r; - cstring filler = ""; + std::string filler; if (value < 0) { value = -value; sign = "-"; @@ -109,14 +109,14 @@ void ConversionContext::addToFieldList(const IR::Expression *expr, Util::JsonArr auto j = conv->convert(expr); conv->simpleExpressionsOnly = simple; // restore state if (auto jo = j->to()) { - if (auto t = jo->get("type")) { + if (auto t = jo->get("type"_cs)) { if (auto type = t->to()) { if (*type == "runtime_data") { // Can't have runtime_data in field lists -- need hexstr instead - auto val = jo->get("value")->to(); + auto val = jo->get("value"_cs)->to(); j = jo = new Util::JsonObject(); - jo->emplace("type", "hexstr"); - jo->emplace("value", stringRepr(val->getValue())); + jo->emplace("type"_cs, "hexstr"); + jo->emplace("value"_cs, stringRepr(val->getValue())); } } } @@ -128,17 +128,17 @@ int ConversionContext::createFieldList(const IR::Expression *expr, cstring listN cstring group; auto fl = new Util::JsonObject(); if (learn) { - group = "learn_lists"; + group = "learn_lists"_cs; json->learn_lists->append(fl); } else { - group = "field_lists"; + group = "field_lists"_cs; json->field_lists->append(fl); } int id = nextId(group); - fl->emplace("id", id); - fl->emplace("name", listName); - fl->emplace_non_null("source_info", expr->sourceInfoJsonObj()); - auto elements = mkArrayField(fl, "elements"); + fl->emplace("id"_cs, id); + fl->emplace("name"_cs, listName); + fl->emplace_non_null("source_info"_cs, expr->sourceInfoJsonObj()); + auto elements = mkArrayField(fl, "elements"_cs); addToFieldList(expr, elements); return id; } @@ -153,11 +153,11 @@ cstring ConversionContext::createCalculation(cstring algo, const IR::Expression const IR::Node *sourcePositionNode = nullptr) { cstring calcName = refMap->newName("calc_"); auto calc = new Util::JsonObject(); - calc->emplace("name", calcName); - calc->emplace("id", nextId("calculations")); + calc->emplace("name"_cs, calcName); + calc->emplace("id"_cs, nextId("calculations"_cs)); if (sourcePositionNode != nullptr) - calc->emplace_non_null("source_info", sourcePositionNode->sourceInfoJsonObj()); - calc->emplace("algo", algo); + calc->emplace_non_null("source_info"_cs, sourcePositionNode->sourceInfoJsonObj()); + calc->emplace("algo"_cs, algo); auto listFields = convertToList(fields, typeMap); if (!listFields) { modelError("%1%: expected a struct", fields); @@ -168,11 +168,11 @@ cstring ConversionContext::createCalculation(cstring algo, const IR::Expression auto array = jright->to(); BUG_CHECK(array, "expected a JSON array"); auto payload = new Util::JsonObject(); - payload->emplace("type", "payload"); - payload->emplace("value", (Util::IJson *)nullptr); + payload->emplace("type"_cs, "payload"_cs); + payload->emplace("value"_cs, (Util::IJson *)nullptr); array->append(payload); } - calc->emplace("input", jright); + calc->emplace("input"_cs, jright); calculations->append(calc); return calcName; } diff --git a/backends/bmv2/common/helpers.h b/backends/bmv2/common/helpers.h index c92415257b..6ce84f6d9a 100644 --- a/backends/bmv2/common/helpers.h +++ b/backends/bmv2/common/helpers.h @@ -30,6 +30,8 @@ limitations under the License. namespace BMV2 { +using namespace P4::literals; + #ifndef UNUSED #define UNUSED __attribute__((__unused__)) #endif @@ -75,12 +77,12 @@ struct ActionProfileTraits; template <> struct ActionProfileTraits { - static const cstring name() { return "action profile"; } + static const cstring name() { return "action profile"_cs; } static const cstring propertyName() { return P4V1::V1Model::instance.tableAttributes.tableImplementation.name; } static const cstring typeName() { return P4V1::V1Model::instance.action_profile.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } }; template <> @@ -88,10 +90,10 @@ struct ActionProfileTraits : public ActionProfileTraits struct ActionProfileTraits { - static const cstring name() { return "action profile"; } - static const cstring propertyName() { return "implementation"; } - static const cstring typeName() { return "ActionProfile"; } - static const cstring sizeParamName() { return "size"; } + static const cstring name() { return "action profile"_cs; } + static const cstring propertyName() { return "implementation"_cs; } + static const cstring typeName() { return "ActionProfile"_cs; } + static const cstring sizeParamName() { return "size"_cs; } }; /// Traits for the action selector extern, must be specialized for v1model and @@ -101,7 +103,7 @@ struct ActionSelectorTraits; template <> struct ActionSelectorTraits : public ActionProfileTraits { - static const cstring name() { return "action selector"; } + static const cstring name() { return "action selector"_cs; } static const cstring typeName() { return P4V1::V1Model::instance.action_selector.name; } }; @@ -110,8 +112,8 @@ struct ActionSelectorTraits : public ActionProfileTraits struct ActionSelectorTraits : public ActionProfileTraits { - static const cstring name() { return "action selector"; } - static const cstring typeName() { return "ActionSelector"; } + static const cstring name() { return "action selector"_cs; } + static const cstring typeName() { return "ActionSelector"_cs; } }; /// Traits for the register extern, must be specialized for v1model and PSA. @@ -120,9 +122,9 @@ struct RegisterTraits; template <> struct RegisterTraits { - static const cstring name() { return "register"; } + static const cstring name() { return "register"_cs; } static const cstring typeName() { return P4V1::V1Model::instance.registers.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } /// the index of the type parameter for the data stored in the register, in /// the type parameter list of the extern type declaration. static size_t dataTypeParamIdx() { return 0; } @@ -136,9 +138,9 @@ struct RegisterTraits : public RegisterTraits template <> struct RegisterTraits { - static const cstring name() { return "register"; } - static const cstring typeName() { return "Register"; } - static const cstring sizeParamName() { return "size"; } + static const cstring name() { return "register"_cs; } + static const cstring typeName() { return "Register"_cs; } + static const cstring sizeParamName() { return "size"_cs; } static size_t dataTypeParamIdx() { return 0; } /// the index of the type parameter for the register index, in the type /// parameter list of the extern type declaration. @@ -174,36 +176,36 @@ struct CounterlikeTraits; /// @ref CounterlikeTraits<> specialization for @ref CounterExtern for v1model template <> struct CounterlikeTraits> { - static const cstring name() { return "counter"; } + static const cstring name() { return "counter"_cs; } static const cstring directPropertyName() { return P4V1::V1Model::instance.tableAttributes.counters.name; } static const cstring typeName() { return P4V1::V1Model::instance.counter.name; } static const cstring directTypeName() { return P4V1::V1Model::instance.directCounter.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } static std::optional indexTypeParamIdx() { return std::nullopt; } }; template <> struct CounterlikeTraits> { - static const cstring name() { return "counter"; } + static const cstring name() { return "counter"_cs; } static const cstring directPropertyName() { return P4V1::V1Model::instance.tableAttributes.counters.name; } static const cstring typeName() { return P4V1::V1Model::instance.counter.name; } static const cstring directTypeName() { return P4V1::V1Model::instance.directCounter.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } static std::optional indexTypeParamIdx() { return 0; } }; /// @ref CounterlikeTraits<> specialization for @ref CounterExtern for PSA template <> struct CounterlikeTraits> { - static const cstring name() { return "counter"; } - static const cstring directPropertyName() { return "psa_direct_counter"; } - static const cstring typeName() { return "Counter"; } - static const cstring directTypeName() { return "DirectCounter"; } - static const cstring sizeParamName() { return "n_counters"; } + static const cstring name() { return "counter"_cs; } + static const cstring directPropertyName() { return "psa_direct_counter"_cs; } + static const cstring typeName() { return "Counter"_cs; } + static const cstring directTypeName() { return "DirectCounter"_cs; } + static const cstring sizeParamName() { return "n_counters"_cs; } /// the index of the type parameter for the counter index, in the type /// parameter list of the extern type declaration. static std::optional indexTypeParamIdx() { return 1; } @@ -212,36 +214,36 @@ struct CounterlikeTraits> { /// @ref CounterlikeTraits<> specialization for @ref MeterExtern for v1model template <> struct CounterlikeTraits> { - static const cstring name() { return "meter"; } + static const cstring name() { return "meter"_cs; } static const cstring directPropertyName() { return P4V1::V1Model::instance.tableAttributes.meters.name; } static const cstring typeName() { return P4V1::V1Model::instance.meter.name; } static const cstring directTypeName() { return P4V1::V1Model::instance.directMeter.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } static std::optional indexTypeParamIdx() { return std::nullopt; } }; template <> struct CounterlikeTraits> { - static const cstring name() { return "meter"; } + static const cstring name() { return "meter"_cs; } static const cstring directPropertyName() { return P4V1::V1Model::instance.tableAttributes.meters.name; } static const cstring typeName() { return P4V1::V1Model::instance.meter.name; } static const cstring directTypeName() { return P4V1::V1Model::instance.directMeter.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } static std::optional indexTypeParamIdx() { return 0; } }; /// @ref CounterlikeTraits<> specialization for @ref MeterExtern for PSA template <> struct CounterlikeTraits> { - static const cstring name() { return "meter"; } - static const cstring directPropertyName() { return "psa_direct_meter"; } - static const cstring typeName() { return "Meter"; } - static const cstring directTypeName() { return "DirectMeter"; } - static const cstring sizeParamName() { return "n_meters"; } + static const cstring name() { return "meter"_cs; } + static const cstring directPropertyName() { return "psa_direct_meter"_cs; } + static const cstring typeName() { return "Meter"_cs; } + static const cstring directTypeName() { return "DirectMeter"_cs; } + static const cstring sizeParamName() { return "n_meters"_cs; } /// the index of the type parameter for the meter index, in the type /// parameter list of the extern type declaration. static std::optional indexTypeParamIdx() { return 0; } diff --git a/backends/bmv2/common/midend.h b/backends/bmv2/common/midend.h index f976bec4bf..1a4d7e73b2 100644 --- a/backends/bmv2/common/midend.h +++ b/backends/bmv2/common/midend.h @@ -33,7 +33,7 @@ class EnumOn32Bits : public P4::ChooseEnumRepresentation { bool convert(const IR::Type_Enum *type) const override { if (type->srcInfo.isValid()) { auto sourceFile = type->srcInfo.getSourceFile(); - if (sourceFile.endsWith(filename)) + if (sourceFile.endsWith(filename.string_view())) // Don't convert any of the standard enums return false; } diff --git a/backends/bmv2/common/options.h b/backends/bmv2/common/options.h index 48b12a12b9..108904e0cc 100644 --- a/backends/bmv2/common/options.h +++ b/backends/bmv2/common/options.h @@ -44,7 +44,7 @@ class BMV2Options : public CompilerOptions { registerOption( "-o", "outfile", [this](const char *arg) { - outputFile = arg; + outputFile = cstring(arg); return true; }, "Write output to outfile"); @@ -52,7 +52,7 @@ class BMV2Options : public CompilerOptions { "--fromJSON", "file", [this](const char *arg) { loadIRFromJson = true; - file = arg; + file = cstring(arg); return true; }, "Use IR representation from JsonFile dumped previously," diff --git a/backends/bmv2/common/parser.cpp b/backends/bmv2/common/parser.cpp index a2a21110fe..4f105f8c42 100644 --- a/backends/bmv2/common/parser.cpp +++ b/backends/bmv2/common/parser.cpp @@ -26,23 +26,23 @@ limitations under the License. namespace BMV2 { cstring ParserConverter::jsonAssignment(const IR::Type *type) { - if (type->is()) return "assign_union"; - if (type->is() || type->is()) return "assign_header"; + if (type->is()) return "assign_union"_cs; + if (type->is() || type->is()) return "assign_header"_cs; if (auto ts = type->to()) { auto et = ts->elementType; if (et->is()) - return "assign_union_stack"; + return "assign_union_stack"_cs; else - return "assign_header_stack"; + return "assign_header_stack"_cs; } // Unfortunately set can do some things that assign cannot, e.g., handle // lookahead on the RHS. - return "set"; + return "set"_cs; } Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) { auto result = new Util::JsonObject(); - auto params = mkArrayField(result, "parameters"); + auto params = mkArrayField(result, "parameters"_cs); auto isR = false; IR::MethodCallExpression *mce2 = nullptr; if (stat->is()) { @@ -104,7 +104,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) auto assign = stat->to(); auto type = ctxt->typeMap->getType(assign->left, true); cstring operation = jsonAssignment(type); - result->emplace("op", operation); + result->emplace("op"_cs, operation); auto l = ctxt->conv->convertLeftValue(assign->left); bool convertBool = type->is(); auto r = ctxt->conv->convert(assign->right, true, true, convertBool); @@ -114,7 +114,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) if (operation != "set") { // must wrap into another outer object auto wrap = new Util::JsonObject(); - wrap->emplace("op", "primitive"); + wrap->emplace("op"_cs, "primitive"); auto params = mkParameters(wrap); params->append(result); result = wrap; @@ -134,8 +134,8 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) return result; } - cstring ename = argCount == 1 ? "extract" : "extract_VL"; - result->emplace("op", ename); + cstring ename = argCount == 1 ? "extract"_cs : "extract_VL"_cs; + result->emplace("op"_cs, ename); auto arg = mce->arguments->at(0); auto argtype = ctxt->typeMap->getType(arg->expression, true); if (!argtype->is()) { @@ -154,7 +154,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) if (baseType->is()) { if (mem->member == IR::Type_Stack::next) { // stack.next - type = "stack"; + type = "stack"_cs; j = ctxt->conv->convert(mem->expr); } else { BUG("%1%: unsupported", mem); @@ -166,20 +166,20 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) if (parentType->is()) { // stack.next.unionfield if (parent->member == IR::Type_Stack::next) { - type = "union_stack"; + type = "union_stack"_cs; j = ctxt->conv->convert(parent->expr); Util::JsonArray *a; if (j->is()) { a = j->to()->clone(); } else if (j->is()) { a = new Util::JsonArray(); - a->push_back(j->to()->get("value")); + a->push_back(j->to()->get("value"_cs)); } else { BUG("unexpected"); } a->append(mem->member.name); auto j0 = new Util::JsonObject(); - j = j0->emplace("value", a); + j = j0->emplace("value"_cs, a); } else { BUG("%1%: unsupported", mem); } @@ -188,12 +188,12 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) } } if (j == nullptr) { - type = "regular"; + type = "regular"_cs; j = ctxt->conv->convert(arg->expression); } - auto value = j->to()->get("value"); - param->emplace("type", type); - param->emplace("value", value); + auto value = j->to()->get("value"_cs); + param->emplace("type"_cs, type); + param->emplace("value"_cs, value); if (argCount == 2) { auto arg2 = mce->arguments->at(1); @@ -202,8 +202,8 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) // does not do that. auto jexpr = ctxt->conv->convert(arg2->expression, true, false); auto rwrap = new Util::JsonObject(); - rwrap->emplace("type", "expression"); - rwrap->emplace("value", jexpr); + rwrap->emplace("type"_cs, "expression"); + rwrap->emplace("value"_cs, jexpr); params->append(rwrap); } return result; @@ -218,7 +218,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) } auto arg = mce->arguments->at(0); auto jexpr = ctxt->conv->convert(arg->expression, true, false); - result->emplace("op", "advance"); + result->emplace("op"_cs, "advance"); params->append(jexpr); return result; } else if ((extmeth->originalExternType->name == "InternetChecksum" && @@ -236,7 +236,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) json = ExternConverter::cvtExternObject(ctxt, extmeth, mce, stat, true); } if (json) { - result->emplace("op", "primitive"); + result->emplace("op"_cs, "primitive"); params->append(json); } return result; @@ -245,7 +245,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) auto extfn = minst->to(); auto extFuncName = extfn->method->name.name; if (extFuncName == IR::ParserState::verify) { - result->emplace("op", "verify"); + result->emplace("op"_cs, "verify"); BUG_CHECK(mce->arguments->size() == 2, "%1%: Expected 2 arguments", mce); { auto cond = mce->arguments->at(0); @@ -264,19 +264,19 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) return result; } else if (extFuncName == "assert" || extFuncName == "assume") { BUG_CHECK(mce->arguments->size() == 1, "%1%: Expected 1 argument ", mce); - result->emplace("op", "primitive"); + result->emplace("op"_cs, "primitive"); auto paramValue = new Util::JsonObject(); params->append(paramValue); - auto paramsArray = mkArrayField(paramValue, "parameters"); + auto paramsArray = mkArrayField(paramValue, "parameters"_cs); auto cond = mce->arguments->at(0); auto expr = ctxt->conv->convert(cond->expression, true, true, true); paramsArray->append(expr); - paramValue->emplace("op", extFuncName); - paramValue->emplace_non_null("source_info", mce->sourceInfoJsonObj()); + paramValue->emplace("op"_cs, extFuncName); + paramValue->emplace_non_null("source_info"_cs, mce->sourceInfoJsonObj()); } else if (extFuncName == P4V1::V1Model::instance.log_msg.name) { BUG_CHECK(mce->arguments->size() == 2 || mce->arguments->size() == 1, "%1%: Expected 1 or 2 arguments", mce); - result->emplace("op", "primitive"); + result->emplace("op"_cs, "primitive"); auto ef = minst->to(); auto ijson = ExternConverter::cvtExternFunction(ctxt, ef, mce, stat, false); params->append(ijson); @@ -293,27 +293,27 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) ], "op" : "primitive" } */ - result->emplace("op", "primitive"); + result->emplace("op"_cs, "primitive"); auto bi = minst->to(); cstring primitive; auto paramsValue = new Util::JsonObject(); params->append(paramsValue); - auto pp = mkArrayField(paramsValue, "parameters"); + auto pp = mkArrayField(paramsValue, "parameters"_cs); auto obj = ctxt->conv->convert(bi->appliedTo); pp->append(obj); if (bi->name == IR::Type_Header::setValid) { - primitive = "add_header"; + primitive = "add_header"_cs; } else if (bi->name == IR::Type_Header::setInvalid) { - primitive = "remove_header"; + primitive = "remove_header"_cs; } else if (bi->name == IR::Type_Stack::push_front || bi->name == IR::Type_Stack::pop_front) { if (bi->name == IR::Type_Stack::push_front) - primitive = "push"; + primitive = "push"_cs; else - primitive = "pop"; + primitive = "pop"_cs; BUG_CHECK(mce->arguments->size() == 1, "Expected 1 argument for %1%", mce); auto arg = ctxt->conv->convert(mce->arguments->at(0)->expression); @@ -322,7 +322,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) BUG("%1%: Unexpected built-in method", bi->name); } - paramsValue->emplace("op", primitive); + paramsValue->emplace("op"_cs, primitive); return result; } } @@ -460,24 +460,24 @@ std::vector ParserConverter::convertSelectExpression( cstring vset_name; unsigned bytes = combine(sc->keyset, se->select, value, mask, is_vset, vset_name); if (is_vset) { - trans->emplace("type", "parse_vset"); - trans->emplace("value", vset_name); - trans->emplace("mask", Util::JsonValue::null); - trans->emplace("next_state", stateName(sc->state->path->name)); + trans->emplace("type"_cs, "parse_vset"); + trans->emplace("value"_cs, vset_name); + trans->emplace("mask"_cs, Util::JsonValue::null); + trans->emplace("next_state"_cs, stateName(sc->state->path->name)); } else { if (mask == 0) { - trans->emplace("type", "default"); - trans->emplace("value", Util::JsonValue::null); - trans->emplace("mask", Util::JsonValue::null); - trans->emplace("next_state", stateName(sc->state->path->name)); + trans->emplace("type"_cs, "default"); + trans->emplace("value"_cs, Util::JsonValue::null); + trans->emplace("mask"_cs, Util::JsonValue::null); + trans->emplace("next_state"_cs, stateName(sc->state->path->name)); } else { - trans->emplace("type", "hexstr"); - trans->emplace("value", stringRepr(value, bytes)); + trans->emplace("type"_cs, "hexstr"); + trans->emplace("value"_cs, stringRepr(value, bytes)); if (mask == -1) - trans->emplace("mask", Util::JsonValue::null); + trans->emplace("mask"_cs, Util::JsonValue::null); else - trans->emplace("mask", stringRepr(mask, bytes)); - trans->emplace("next_state", stateName(sc->state->path->name)); + trans->emplace("mask"_cs, stringRepr(mask, bytes)); + trans->emplace("next_state"_cs, stateName(sc->state->path->name)); } } result.push_back(trans); @@ -494,19 +494,19 @@ Util::IJson *ParserConverter::convertSelectKey(const IR::SelectExpression *expr) Util::IJson *ParserConverter::convertPathExpression(const IR::PathExpression *pe) { auto trans = new Util::JsonObject(); - trans->emplace("type", "default"); - trans->emplace("value", Util::JsonValue::null); - trans->emplace("mask", Util::JsonValue::null); - trans->emplace("next_state", stateName(pe->path->name)); + trans->emplace("type"_cs, "default"); + trans->emplace("value"_cs, Util::JsonValue::null); + trans->emplace("mask"_cs, Util::JsonValue::null); + trans->emplace("next_state"_cs, stateName(pe->path->name)); return trans; } Util::IJson *ParserConverter::createDefaultTransition() { auto trans = new Util::JsonObject(); - trans->emplace("type", "default"); - trans->emplace("value", Util::JsonValue::null); - trans->emplace("mask", Util::JsonValue::null); - trans->emplace("next_state", Util::JsonValue::null); + trans->emplace("type"_cs, "default"); + trans->emplace("value"_cs, Util::JsonValue::null); + trans->emplace("mask"_cs, Util::JsonValue::null); + trans->emplace("next_state"_cs, Util::JsonValue::null); return trans; } diff --git a/backends/bmv2/common/parser.h b/backends/bmv2/common/parser.h index 97e611d1cf..d2c6fe0ee4 100644 --- a/backends/bmv2/common/parser.h +++ b/backends/bmv2/common/parser.h @@ -48,7 +48,7 @@ class ParserConverter : public Inspector { public: bool preorder(const IR::P4Parser *p) override; - explicit ParserConverter(ConversionContext *ctxt, cstring name = "parser") + explicit ParserConverter(ConversionContext *ctxt, cstring name = "parser"_cs) : ctxt(ctxt), name(name), corelib(P4::P4CoreLibrary::instance()) { setName("ParserConverter"); } diff --git a/backends/bmv2/common/sharedActionSelectorCheck.h b/backends/bmv2/common/sharedActionSelectorCheck.h index 0cb68d570b..ed875ecc9c 100644 --- a/backends/bmv2/common/sharedActionSelectorCheck.h +++ b/backends/bmv2/common/sharedActionSelectorCheck.h @@ -69,7 +69,7 @@ class SharedActionSelectorCheck : public Inspector { } bool preorder(const IR::P4Table *table) override { - auto implementation = table->properties->getProperty("implementation"); + auto implementation = table->properties->getProperty("implementation"_cs); if (implementation == nullptr) return false; if (!implementation->value->is()) { ::error(ErrorType::ERR_EXPECTED, "%1%: expected expression for property", diff --git a/backends/bmv2/psa_switch/main.cpp b/backends/bmv2/psa_switch/main.cpp index bbd7604ffb..4694e02fad 100644 --- a/backends/bmv2/psa_switch/main.cpp +++ b/backends/bmv2/psa_switch/main.cpp @@ -43,7 +43,7 @@ int main(int argc, char *const argv[]) { AutoCompileContext autoPsaSwitchContext(new BMV2::PsaSwitchContext); auto &options = BMV2::PsaSwitchContext::get().options(); options.langVersion = CompilerOptions::FrontendVersion::P4_16; - options.compilerVersion = BMV2_PSA_VERSION_STRING; + options.compilerVersion = cstring(BMV2_PSA_VERSION_STRING); if (options.process(argc, argv) != nullptr) { if (options.loadIRFromJson == false) options.setInputFile(); diff --git a/backends/bmv2/psa_switch/midend.cpp b/backends/bmv2/psa_switch/midend.cpp index f782342be3..be044d82bb 100644 --- a/backends/bmv2/psa_switch/midend.cpp +++ b/backends/bmv2/psa_switch/midend.cpp @@ -64,6 +64,8 @@ limitations under the License. namespace BMV2 { +using namespace P4::literals; + /// This class implements a policy suitable for the ConvertEnums pass. /// The policy is: convert all enums that are not part of the psa. /// Use 32-bit values for all enums. @@ -76,7 +78,7 @@ class PsaEnumOn32Bits : public P4::ChooseEnumRepresentation { if (type->name == "PSA_MeterColor_t") return true; if (type->srcInfo.isValid()) { auto sourceFile = type->srcInfo.getSourceFile(); - if (sourceFile.endsWith(filename)) + if (sourceFile.endsWith(filename.string_view())) // Don't convert any of the standard enums return false; } @@ -90,7 +92,7 @@ class PsaEnumOn32Bits : public P4::ChooseEnumRepresentation { PsaSwitchMidEnd::PsaSwitchMidEnd(CompilerOptions &options, std::ostream *outStream) : MidEnd(options) { - auto convertEnums = new P4::ConvertEnums(&refMap, &typeMap, new PsaEnumOn32Bits("psa.p4")); + auto convertEnums = new P4::ConvertEnums(&refMap, &typeMap, new PsaEnumOn32Bits("psa.p4"_cs)); auto evaluator = new P4::EvaluatorPass(&refMap, &typeMap); std::function policy = [=](const Context *, const IR::Expression *e) -> bool { @@ -143,8 +145,9 @@ PsaSwitchMidEnd::PsaSwitchMidEnd(CompilerOptions &options, std::ostream *outStre new PassRepeated({new P4::ConstantFolding(&refMap, &typeMap), new P4::StrengthReduction(&refMap, &typeMap)}), new P4::MoveDeclarations(), - new P4::ValidateTableProperties({"psa_implementation", "psa_direct_counter", - "psa_direct_meter", "psa_idle_timeout", "size"}), + new P4::ValidateTableProperties({"psa_implementation"_cs, "psa_direct_counter"_cs, + "psa_direct_meter"_cs, "psa_idle_timeout"_cs, + "size"_cs}), new P4::SimplifyControlFlow(&refMap, &typeMap), new P4::CompileTimeOperations(), new P4::TableHit(&refMap, &typeMap), @@ -157,7 +160,7 @@ PsaSwitchMidEnd::PsaSwitchMidEnd(CompilerOptions &options, std::ostream *outStre [this, evaluator]() { toplevel = evaluator->getToplevelBlock(); }, }); if (options.listMidendPasses) { - listPasses(*outStream, "\n"); + listPasses(*outStream, cstring::newline); *outStream << std::endl; return; } @@ -165,7 +168,7 @@ PsaSwitchMidEnd::PsaSwitchMidEnd(CompilerOptions &options, std::ostream *outStre removePasses(options.passesToExcludeMidend); } } else { - auto fillEnumMap = new P4::FillEnumMap(new PsaEnumOn32Bits("psa.p4"), &typeMap); + auto fillEnumMap = new P4::FillEnumMap(new PsaEnumOn32Bits("psa.p4"_cs), &typeMap); addPasses({ new P4::ResolveReferences(&refMap), new P4::TypeChecking(&refMap, &typeMap), diff --git a/backends/bmv2/psa_switch/options.cpp b/backends/bmv2/psa_switch/options.cpp index f1bb1ccf97..d6e7a1a4e3 100644 --- a/backends/bmv2/psa_switch/options.cpp +++ b/backends/bmv2/psa_switch/options.cpp @@ -5,9 +5,11 @@ namespace BMV2 { +using namespace P4::literals; + std::vector *PsaSwitchOptions::process(int argc, char *const argv[]) { searchForIncludePath(p4includePath, - {"p4include/bmv2", "../p4include/bmv2", "../../p4include/bmv2"}, + {"p4include/bmv2"_cs, "../p4include/bmv2"_cs, "../../p4include/bmv2"_cs}, exename(argv[0])); auto remainingOptions = CompilerOptions::process(argc, argv); diff --git a/backends/bmv2/psa_switch/psaProgramStructure.cpp b/backends/bmv2/psa_switch/psaProgramStructure.cpp index f0f64dc5d6..791ce29efb 100644 --- a/backends/bmv2/psa_switch/psaProgramStructure.cpp +++ b/backends/bmv2/psa_switch/psaProgramStructure.cpp @@ -19,6 +19,8 @@ limitations under the License. namespace BMV2 { +using namespace P4::literals; + void InspectPsaProgram::postorder(const IR::Declaration_Instance *di) { if (!pinfo->resourceMap.count(di)) return; auto blk = pinfo->resourceMap.at(di); @@ -204,9 +206,9 @@ void InspectPsaProgram::postorder(const IR::P4Parser *p) { if (pinfo->block_type.count(p)) { auto info = pinfo->block_type.at(p); if (info.first == INGRESS && info.second == PARSER) - pinfo->parsers.emplace("ingress", p); + pinfo->parsers.emplace("ingress"_cs, p); else if (info.first == EGRESS && info.second == PARSER) - pinfo->parsers.emplace("egress", p); + pinfo->parsers.emplace("egress"_cs, p); } } @@ -214,13 +216,13 @@ void InspectPsaProgram::postorder(const IR::P4Control *c) { if (pinfo->block_type.count(c)) { auto info = pinfo->block_type.at(c); if (info.first == INGRESS && info.second == PIPELINE) - pinfo->pipelines.emplace("ingress", c); + pinfo->pipelines.emplace("ingress"_cs, c); else if (info.first == EGRESS && info.second == PIPELINE) - pinfo->pipelines.emplace("egress", c); + pinfo->pipelines.emplace("egress"_cs, c); else if (info.first == INGRESS && info.second == DEPARSER) - pinfo->deparsers.emplace("ingress", c); + pinfo->deparsers.emplace("ingress"_cs, c); else if (info.first == EGRESS && info.second == DEPARSER) - pinfo->deparsers.emplace("egress", c); + pinfo->deparsers.emplace("egress"_cs, c); } } @@ -238,13 +240,13 @@ bool ParsePsaArchitecture::preorder(const IR::ExternBlock *block) { } bool ParsePsaArchitecture::preorder(const IR::PackageBlock *block) { - auto pkg = block->findParameterValue("ingress"); + auto pkg = block->findParameterValue("ingress"_cs); if (pkg == nullptr) { modelError("Package %1% has no parameter named 'ingress'", block); return false; } if (auto ingress = pkg->to()) { - auto p = ingress->findParameterValue("ip"); + auto p = ingress->findParameterValue("ip"_cs); if (p == nullptr) { modelError("'ingress' package %1% has no parameter named 'ip'", block); return false; @@ -254,7 +256,7 @@ bool ParsePsaArchitecture::preorder(const IR::PackageBlock *block) { modelError("%1%: 'ip' argument of 'ingress' should be bound to a parser", block); return false; } - p = ingress->findParameterValue("ig"); + p = ingress->findParameterValue("ig"_cs); if (p == nullptr) { modelError("'ingress' package %1% has no parameter named 'ig'", block); return false; @@ -264,7 +266,7 @@ bool ParsePsaArchitecture::preorder(const IR::PackageBlock *block) { modelError("%1%: 'ig' argument of 'ingress' should be bound to a control", block); return false; } - p = ingress->findParameterValue("id"); + p = ingress->findParameterValue("id"_cs); if (p == nullptr) { modelError("'ingress' package %1% has no parameter named 'id'", block); return false; @@ -283,13 +285,13 @@ bool ParsePsaArchitecture::preorder(const IR::PackageBlock *block) { modelError("'ingress' %1% is not bound to a package", pkg); return false; } - pkg = block->findParameterValue("egress"); + pkg = block->findParameterValue("egress"_cs); if (pkg == nullptr) { modelError("Package %1% has no parameter named 'egress'", block); return false; } if (auto egress = pkg->to()) { - auto p = egress->findParameterValue("ep"); + auto p = egress->findParameterValue("ep"_cs); if (p == nullptr) { modelError("'egress' package %1% has no parameter named 'ep'", block); return false; @@ -299,7 +301,7 @@ bool ParsePsaArchitecture::preorder(const IR::PackageBlock *block) { modelError("%1%: 'ep' argument of 'egress' should be bound to a parser", block); return false; } - p = egress->findParameterValue("eg"); + p = egress->findParameterValue("eg"_cs); if (p == nullptr) { modelError("'egress' package %1% has no parameter named 'eg'", block); return false; @@ -309,7 +311,7 @@ bool ParsePsaArchitecture::preorder(const IR::PackageBlock *block) { modelError("%1%: 'ig' argument of 'egress' should be bound to a control", block); return false; } - p = egress->findParameterValue("ed"); + p = egress->findParameterValue("ed"_cs); if (p == nullptr) { modelError("'egress' package %1% has no parameter named 'ed'", block); return false; diff --git a/backends/bmv2/psa_switch/psaSwitch.cpp b/backends/bmv2/psa_switch/psaSwitch.cpp index 06f0aea149..d3bd0c7853 100644 --- a/backends/bmv2/psa_switch/psaSwitch.cpp +++ b/backends/bmv2/psa_switch/psaSwitch.cpp @@ -21,6 +21,8 @@ limitations under the License. namespace BMV2 { +using namespace P4::literals; + void PsaCodeGenerator::create(ConversionContext *ctxt) { createTypes(ctxt); createHeaders(ctxt); @@ -119,8 +121,8 @@ void PsaCodeGenerator::createTypes(ConversionContext *ctxt) { void PsaCodeGenerator::createScalars(ConversionContext *ctxt) { auto name = scalars.begin()->first; - ctxt->json->add_header("scalars_t", name); - ctxt->json->add_header_type("scalars_t"); + ctxt->json->add_header("scalars_t"_cs, name); + ctxt->json->add_header_type("scalars_t"_cs); unsigned max_length = 0; for (auto kv : scalars) { LOG5("Adding a scalar field " << kv.second << " to generated json"); @@ -139,7 +141,7 @@ void PsaCodeGenerator::createScalars(ConversionContext *ctxt) { } else { BUG_CHECK(kv.second, "%1 is not of Type_Bits or Type_Boolean"); } - ctxt->json->add_header_field("scalars_t", field); + ctxt->json->add_header_field("scalars_t"_cs, field); } // must add padding unsigned padding = max_length % 8; @@ -149,7 +151,7 @@ void PsaCodeGenerator::createScalars(ConversionContext *ctxt) { field->append(name); field->append(8 - padding); field->append(false); - ctxt->json->add_header_field("scalars_t", field); + ctxt->json->add_header_field("scalars_t"_cs, field); } } @@ -186,13 +188,13 @@ void PsaCodeGenerator::createHeaders(ConversionContext *ctxt) { void PsaCodeGenerator::createParsers(ConversionContext *ctxt) { { - auto cvt = new ParserConverter(ctxt, "ingress_parser"); - auto ingress = parsers.at("ingress"); + auto cvt = new ParserConverter(ctxt, "ingress_parser"_cs); + auto ingress = parsers.at("ingress"_cs); ingress->apply(*cvt); } { - auto cvt = new ParserConverter(ctxt, "egress_parser"); - auto ingress = parsers.at("egress"); + auto cvt = new ParserConverter(ctxt, "egress_parser"_cs); + auto ingress = parsers.at("egress"_cs); ingress->apply(*cvt); } } @@ -218,24 +220,24 @@ void PsaCodeGenerator::createActions(ConversionContext *ctxt) { } void PsaCodeGenerator::createControls(ConversionContext *ctxt) { - auto cvt = new BMV2::ControlConverter(ctxt, "ingress", true); - auto ingress = pipelines.at("ingress"); + auto cvt = new BMV2::ControlConverter(ctxt, "ingress"_cs, true); + auto ingress = pipelines.at("ingress"_cs); ingress->apply(*cvt); - cvt = new BMV2::ControlConverter(ctxt, "egress", true); - auto egress = pipelines.at("egress"); + cvt = new BMV2::ControlConverter(ctxt, "egress"_cs, true); + auto egress = pipelines.at("egress"_cs); egress->apply(*cvt); } void PsaCodeGenerator::createDeparsers(ConversionContext *ctxt) { { - auto cvt = new DeparserConverter(ctxt, "ingress_deparser"); - auto ingress = deparsers.at("ingress"); + auto cvt = new DeparserConverter(ctxt, "ingress_deparser"_cs); + auto ingress = deparsers.at("ingress"_cs); ingress->apply(*cvt); } { - auto cvt = new DeparserConverter(ctxt, "egress_deparser"); - auto egress = deparsers.at("egress"); + auto cvt = new DeparserConverter(ctxt, "egress_deparser"_cs); + auto egress = deparsers.at("egress"_cs); egress->apply(*cvt); } } @@ -317,21 +319,23 @@ void PsaSwitchBackend::convert(const IR::ToplevelBlock *tlb) { } cstring PsaCodeGenerator::convertHashAlgorithm(cstring algo) { - cstring result; - if (algo == "CRC16") { - result = "crc16"; - } else if (algo == "CRC16_CUSTOM") { - result = "crc16_custom"; - } else if (algo == "CRC32") { - result = "crc32"; - } else if (algo == "CRC32_CUSTOM") { - result = "crc32_custom"; - } else if (algo == "IDENTITY") { - result = "identity"; + return "crc16"_cs; + } + if (algo == "CRC16_CUSTOM") { + return "crc16_custom"_cs; + } + if (algo == "CRC32") { + return "crc32"_cs; + } + if (algo == "CRC32_CUSTOM") { + return "crc32_custom"_cs; + } + if (algo == "IDENTITY") { + return "identity"_cs; } - return result; + return nullptr; } ExternConverter_Hash ExternConverter_Hash::singleton; @@ -362,26 +366,26 @@ Util::IJson *ExternConverter_Hash::convertExternObject(UNUSED ConversionContext return nullptr; } auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto hash = new Util::JsonObject(); - hash->emplace("type", "extern"); - hash->emplace("value", em->object->controlPlaneName()); + hash->emplace("type"_cs, "extern"); + hash->emplace("value"_cs, em->object->controlPlaneName()); parameters->append(hash); if (mc->arguments->size() == 2) { // get_hash auto dst = ctxt->conv->convertLeftValue(mc->arguments->at(0)->expression); auto fieldList = new Util::JsonObject(); - fieldList->emplace("type", "field_list"); + fieldList->emplace("type"_cs, "field_list"); auto fieldsJson = ctxt->conv->convert(mc->arguments->at(1)->expression, true, false); - fieldList->emplace("value", fieldsJson); + fieldList->emplace("value"_cs, fieldsJson); parameters->append(dst); parameters->append(fieldList); } else { // get_hash with base and mod auto dst = ctxt->conv->convertLeftValue(mc->arguments->at(0)->expression); auto base = ctxt->conv->convert(mc->arguments->at(1)->expression); auto fieldList = new Util::JsonObject(); - fieldList->emplace("type", "field_list"); + fieldList->emplace("type"_cs, "field_list"); auto fieldsJson = ctxt->conv->convert(mc->arguments->at(2)->expression, true, false); - fieldList->emplace("value", fieldsJson); + fieldList->emplace("value"_cs, fieldsJson); auto max = ctxt->conv->convert(mc->arguments->at(3)->expression); parameters->append(dst); parameters->append(base); @@ -395,7 +399,7 @@ Util::IJson *ExternConverter_Checksum::convertExternObject( UNUSED ConversionContext *ctxt, UNUSED const P4::ExternMethod *em, UNUSED const IR::MethodCallExpression *mc, UNUSED const IR::StatOrDecl *s, UNUSED const bool &emitExterns) { - auto primitive = mkPrimitive("Checksum"); + auto primitive = mkPrimitive("Checksum"_cs); return primitive; } @@ -428,16 +432,16 @@ Util::IJson *ExternConverter_InternetChecksum::convertExternObject( primitive = mkPrimitive("_" + em->originalExternType->name + "_" + em->method->name); } auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto cksum = new Util::JsonObject(); - cksum->emplace("type", "extern"); - cksum->emplace("value", em->object->controlPlaneName()); + cksum->emplace("type"_cs, "extern"); + cksum->emplace("value"_cs, em->object->controlPlaneName()); parameters->append(cksum); if (em->method->name == "add" || em->method->name == "subtract") { auto fieldList = new Util::JsonObject(); - fieldList->emplace("type", "field_list"); + fieldList->emplace("type"_cs, "field_list"); auto fieldsJson = ctxt->conv->convert(mc->arguments->at(0)->expression, true, false); - fieldList->emplace("value", fieldsJson); + fieldList->emplace("value"_cs, fieldsJson); parameters->append(fieldList); } else if (em->method->name != "clear") { if (mc->arguments->size() == 2) { // get_verify @@ -464,10 +468,10 @@ Util::IJson *ExternConverter_Counter::convertExternObject(UNUSED ConversionConte } auto primitive = mkPrimitive("_" + em->originalExternType->name + "_" + em->method->name); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto ctr = new Util::JsonObject(); - ctr->emplace("type", "extern"); - ctr->emplace("value", em->object->controlPlaneName()); + ctr->emplace("type"_cs, "extern"); + ctr->emplace("value"_cs, em->object->controlPlaneName()); parameters->append(ctr); auto index = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(index); @@ -497,10 +501,10 @@ Util::IJson *ExternConverter_Meter::convertExternObject(UNUSED ConversionContext } auto primitive = mkPrimitive("_" + em->originalExternType->name + "_" + em->method->name); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto mtr = new Util::JsonObject(); - mtr->emplace("type", "extern"); - mtr->emplace("value", em->object->controlPlaneName()); + mtr->emplace("type"_cs, "extern"); + mtr->emplace("value"_cs, em->object->controlPlaneName()); parameters->append(mtr); if (mc->arguments->size() == 2) { auto result = ctxt->conv->convert(mc->arguments->at(1)->expression); @@ -540,13 +544,13 @@ Util::IJson *ExternConverter_Register::convertExternObject( return nullptr; } auto reg = new Util::JsonObject(); - reg->emplace("type", "register_array"); + reg->emplace("type"_cs, "register_array"); cstring name = em->object->controlPlaneName(); - reg->emplace("value", name); + reg->emplace("value"_cs, name); if (em->method->name == "read") { - auto primitive = mkPrimitive("register_read"); + auto primitive = mkPrimitive("register_read"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto dest = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(dest); parameters->append(reg); @@ -554,9 +558,9 @@ Util::IJson *ExternConverter_Register::convertExternObject( parameters->append(index); return primitive; } else if (em->method->name == "write") { - auto primitive = mkPrimitive("register_write"); + auto primitive = mkPrimitive("register_write"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); parameters->append(reg); auto index = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(index); @@ -576,9 +580,9 @@ Util::IJson *ExternConverter_Random::convertExternObject(UNUSED ConversionContex modelError("Expected 3 arguments for %1%", mc); return nullptr; } - auto primitive = mkPrimitive("modify_field_rng_uniform"); + auto primitive = mkPrimitive("modify_field_rng_uniform"_cs); auto params = mkParameters(primitive); - primitive->emplace_non_null("source_info", em->method->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, em->method->sourceInfoJsonObj()); auto dest = ctxt->conv->convert(mc->arguments->at(0)->expression); /* TODO */ // auto lo = ctxt->conv->convert(mc->arguments->at(1)->expression); @@ -598,10 +602,10 @@ Util::IJson *ExternConverter_Digest::convertExternObject(UNUSED ConversionContex modelError("Expected 1 arguments for %1%", mc); return nullptr; } - auto primitive = mkPrimitive("generate_digest"); + auto primitive = mkPrimitive("generate_digest"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", em->method->sourceInfoJsonObj()); - cstring listName = "digest"; + primitive->emplace_non_null("source_info"_cs, em->method->sourceInfoJsonObj()); + cstring listName = "digest"_cs; // If we are supplied a type argument that is a named type use // that for the list name. if (mc->typeArguments->size() == 1) { @@ -633,10 +637,10 @@ void ExternConverter_Hash::convertExternInstance(ConversionContext *ctxt, const // add hash instance auto jhash = new Util::JsonObject(); - jhash->emplace("name", name); - jhash->emplace("id", nextId("extern_instances")); - jhash->emplace("type", eb->getName()); - jhash->emplace_non_null("source_info", inst->sourceInfoJsonObj()); + jhash->emplace("name"_cs, name); + jhash->emplace("id"_cs, nextId("extern_instances"_cs)); + jhash->emplace("type"_cs, eb->getName()); + jhash->emplace_non_null("source_info"_cs, inst->sourceInfoJsonObj()); ctxt->json->externs->append(jhash); // add attributes @@ -645,9 +649,9 @@ void ExternConverter_Hash::convertExternInstance(ConversionContext *ctxt, const return; } - Util::JsonArray *arr = ctxt->json->insert_array_field(jhash, "attribute_values"); + Util::JsonArray *arr = ctxt->json->insert_array_field(jhash, "attribute_values"_cs); - auto algo = eb->findParameterValue("algo"); + auto algo = eb->findParameterValue("algo"_cs); CHECK_NULL(algo); if (!algo->is()) { modelError("%1%: expected a declaration", algo->getNode()); @@ -656,9 +660,9 @@ void ExternConverter_Hash::convertExternInstance(ConversionContext *ctxt, const cstring algo_name = algo->to()->name; algo_name = psaStructure->convertHashAlgorithm(algo_name); auto k = new Util::JsonObject(); - k->emplace("name", "algo"); - k->emplace("type", "string"); - k->emplace("value", algo_name); + k->emplace("name"_cs, "algo"); + k->emplace("type"_cs, "string"); + k->emplace("value"_cs, algo_name); arr->append(k); } @@ -676,20 +680,20 @@ void ExternConverter_InternetChecksum::convertExternInstance(UNUSED ConversionCo auto trim = inst->controlPlaneName().find("."); auto block = inst->controlPlaneName().trim(trim); auto psaStructure = static_cast(ctxt->structure); - auto ingressParser = psaStructure->parsers.at("ingress")->controlPlaneName(); - auto ingressDeparser = psaStructure->deparsers.at("ingress")->controlPlaneName(); - auto egressParser = psaStructure->parsers.at("egress")->controlPlaneName(); - auto egressDeparser = psaStructure->deparsers.at("egress")->controlPlaneName(); + auto ingressParser = psaStructure->parsers.at("ingress"_cs)->controlPlaneName(); + auto ingressDeparser = psaStructure->deparsers.at("ingress"_cs)->controlPlaneName(); + auto egressParser = psaStructure->parsers.at("egress"_cs)->controlPlaneName(); + auto egressDeparser = psaStructure->deparsers.at("egress"_cs)->controlPlaneName(); if (block != ingressParser && block != ingressDeparser && block != egressParser && block != egressDeparser) { ::error(ErrorType::ERR_UNSUPPORTED, "%1%: not supported in pipeline on this target", eb); } // add checksum instance auto jcksum = new Util::JsonObject(); - jcksum->emplace("name", name); - jcksum->emplace("id", nextId("extern_instances")); - jcksum->emplace("type", eb->getName()); - jcksum->emplace_non_null("source_info", inst->sourceInfoJsonObj()); + jcksum->emplace("name"_cs, name); + jcksum->emplace("id"_cs, nextId("extern_instances"_cs)); + jcksum->emplace("type"_cs, eb->getName()); + jcksum->emplace_non_null("source_info"_cs, inst->sourceInfoJsonObj()); ctxt->json->externs->append(jcksum); } @@ -699,7 +703,7 @@ void ExternConverter_Counter::convertExternInstance(UNUSED ConversionContext *ct UNUSED const bool &emitExterns) { auto inst = c->to(); cstring name = inst->controlPlaneName(); - auto sz = eb->findParameterValue("n_counters"); + auto sz = eb->findParameterValue("n_counters"_cs); CHECK_NULL(sz); if (!sz->is()) { modelError("%1%: expected a constant", sz->getNode()); @@ -708,21 +712,21 @@ void ExternConverter_Counter::convertExternInstance(UNUSED ConversionContext *ct // adding counter instance to counter_arrays[] auto jctr = new Util::JsonObject(); - jctr->emplace("name", name); - jctr->emplace("id", nextId("counter_arrays")); - jctr->emplace_non_null("source_info", eb->sourceInfoJsonObj()); - jctr->emplace("size", sz->to()->value); - jctr->emplace("is_direct", false); + jctr->emplace("name"_cs, name); + jctr->emplace("id"_cs, nextId("counter_arrays"_cs)); + jctr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); + jctr->emplace("size"_cs, sz->to()->value); + jctr->emplace("is_direct"_cs, false); ctxt->json->counters->append(jctr); // add counter instance to extern_instances auto extern_obj = new Util::JsonObject(); - extern_obj->emplace("name", name); - extern_obj->emplace("id", nextId("extern_instances")); - extern_obj->emplace("type", eb->getName()); - extern_obj->emplace("source_info", inst->sourceInfoJsonObj()); + extern_obj->emplace("name"_cs, name); + extern_obj->emplace("id"_cs, nextId("extern_instances"_cs)); + extern_obj->emplace("type"_cs, eb->getName()); + extern_obj->emplace("source_info"_cs, inst->sourceInfoJsonObj()); ctxt->json->externs->append(extern_obj); - Util::JsonArray *arr = ctxt->json->insert_array_field(extern_obj, "attribute_values"); + Util::JsonArray *arr = ctxt->json->insert_array_field(extern_obj, "attribute_values"_cs); if (eb->getConstructorParameters()->size() != 2) { modelError("%1%: expected two parameters", eb); @@ -735,14 +739,14 @@ void ExternConverter_Counter::convertExternInstance(UNUSED ConversionContext *ct auto param1 = eb->getConstructorParameters()->getParameter(0); auto bitwidth = ctxt->typeMap->widthBits(arg1->type, sz->getNode(), false); cstring repr = BMV2::stringRepr(arg1->value, ROUNDUP(bitwidth, 8)); - attr_obj->emplace("name", param1->toString()); - attr_obj->emplace("type", "hexstr"); - attr_obj->emplace("value", repr); + attr_obj->emplace("name"_cs, param1->toString()); + attr_obj->emplace("type"_cs, "hexstr"); + attr_obj->emplace("value"_cs, repr); arr->append(attr_obj); // second argument is the counter type, this is psa metadata, the converter // in conversion context will handle that for us - auto tp = eb->findParameterValue("type"); + auto tp = eb->findParameterValue("type"_cs); if (!tp || !tp->is()) { modelError("%1%: expected a declaration_id", tp ? tp->getNode() : eb->getNode()); return; @@ -766,26 +770,26 @@ void ExternConverter_DirectCounter::convertExternInstance(UNUSED ConversionConte ::warning(ErrorType::WARN_UNUSED, "%1%: Direct counter not used; ignoring", inst); } else { auto jctr = new Util::JsonObject(); - jctr->emplace("name", name); - jctr->emplace("id", nextId("counter_arrays")); - jctr->emplace_non_null("source_info", eb->sourceInfoJsonObj()); - jctr->emplace("is_direct", true); - jctr->emplace("binding", it->second->controlPlaneName()); + jctr->emplace("name"_cs, name); + jctr->emplace("id"_cs, nextId("counter_arrays"_cs)); + jctr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); + jctr->emplace("is_direct"_cs, true); + jctr->emplace("binding"_cs, it->second->controlPlaneName()); ctxt->json->counters->append(jctr); // Adding direct counter to EXTERN_INSTANCES auto extern_obj = new Util::JsonObject(); - extern_obj->emplace("name", name); - extern_obj->emplace("id", nextId("extern_instances")); - extern_obj->emplace("type", eb->getName()); - extern_obj->emplace("source_info", inst->sourceInfoJsonObj()); + extern_obj->emplace("name"_cs, name); + extern_obj->emplace("id"_cs, nextId("extern_instances"_cs)); + extern_obj->emplace("type"_cs, eb->getName()); + extern_obj->emplace("source_info"_cs, inst->sourceInfoJsonObj()); ctxt->json->externs->append(extern_obj); - Util::JsonArray *arr = ctxt->json->insert_array_field(extern_obj, "attribute_values"); + Util::JsonArray *arr = ctxt->json->insert_array_field(extern_obj, "attribute_values"_cs); // Direct Counter only has a single argument, which is psa metadata // converter in conversion context will handle this for us - auto tp = eb->findParameterValue("type"); + auto tp = eb->findParameterValue("type"_cs); if (!tp || !tp->is()) { modelError("%1%: expected a declaration_id", tp ? tp->getNode() : eb->getNode()); return; @@ -817,24 +821,24 @@ void ExternConverter_Meter::convertExternInstance(UNUSED ConversionContext *ctxt // adding meter instance into extern_instances auto jext_mtr = new Util::JsonObject(); - jext_mtr->emplace("name", name); - jext_mtr->emplace("id", nextId("extern_instances")); - jext_mtr->emplace("type", eb->getName()); - jext_mtr->emplace_non_null("source_info", eb->sourceInfoJsonObj()); + jext_mtr->emplace("name"_cs, name); + jext_mtr->emplace("id"_cs, nextId("extern_instances"_cs)); + jext_mtr->emplace("type"_cs, eb->getName()); + jext_mtr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); ctxt->json->externs->append(jext_mtr); // adding attributes to meter extern_instance - Util::JsonArray *arr = ctxt->json->insert_array_field(jext_mtr, "attribute_values"); + Util::JsonArray *arr = ctxt->json->insert_array_field(jext_mtr, "attribute_values"_cs); // is_direct auto is_direct = new Util::JsonObject(); - is_direct->emplace("name", "is_direct"); - is_direct->emplace("type", "hexstr"); - is_direct->emplace("value", 0); + is_direct->emplace("name"_cs, "is_direct"); + is_direct->emplace("type"_cs, "hexstr"); + is_direct->emplace("value"_cs, 0); arr->append(is_direct); // meter_array size - auto sz = eb->findParameterValue("n_meters"); + auto sz = eb->findParameterValue("n_meters"_cs); CHECK_NULL(sz); if (!sz->is()) { modelError("%1%: expected a constant", sz->getNode()); @@ -845,37 +849,37 @@ void ExternConverter_Meter::convertExternInstance(UNUSED ConversionContext *ctxt auto bitwidth = ctxt->typeMap->widthBits(s->type, sz->getNode(), false); cstring val = BMV2::stringRepr(s->value, ROUNDUP(bitwidth, 8)); auto msz = new Util::JsonObject(); - msz->emplace("name", attr_name->toString()); - msz->emplace("type", "hexstr"); - msz->emplace("value", val); + msz->emplace("name"_cs, attr_name->toString()); + msz->emplace("type"_cs, "hexstr"); + msz->emplace("value"_cs, val); arr->append(msz); // rate count auto rc = new Util::JsonObject(); - rc->emplace("name", "rate_count"); - rc->emplace("type", "hexstr"); - rc->emplace("value", 2); + rc->emplace("name"_cs, "rate_count"); + rc->emplace("type"_cs, "hexstr"); + rc->emplace("value"_cs, 2); arr->append(rc); // meter kind - auto mkind = eb->findParameterValue("type"); + auto mkind = eb->findParameterValue("type"_cs); CHECK_NULL(mkind); if (!mkind->is()) { modelError("%1%: expected a member", mkind->getNode()); return; } cstring mkind_name = mkind->to()->name; - cstring type = "?"; + cstring type; if (mkind_name == "PACKETS") - type = "packets"; + type = "packets"_cs; else if (mkind_name == "BYTES") - type = "bytes"; + type = "bytes"_cs; else ::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected meter type", mkind->getNode()); auto k = new Util::JsonObject(); - k->emplace("name", "type"); - k->emplace("type", "string"); - k->emplace("value", type); + k->emplace("name"_cs, "type"); + k->emplace("type"_cs, "string"); + k->emplace("value"_cs, type); arr->append(k); } @@ -891,33 +895,33 @@ void ExternConverter_DirectMeter::convertExternInstance(UNUSED ConversionContext CHECK_NULL(info->destinationField); auto jmtr = new Util::JsonObject(); - jmtr->emplace("name", name); - jmtr->emplace("id", nextId("meter_arrays")); - jmtr->emplace_non_null("source_info", eb->sourceInfoJsonObj()); - jmtr->emplace("is_direct", true); - jmtr->emplace("rate_count", 2); - auto mkind = eb->findParameterValue("type"); + jmtr->emplace("name"_cs, name); + jmtr->emplace("id"_cs, nextId("meter_arrays"_cs)); + jmtr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); + jmtr->emplace("is_direct"_cs, true); + jmtr->emplace("rate_count"_cs, 2); + auto mkind = eb->findParameterValue("type"_cs); CHECK_NULL(mkind); if (!mkind->is()) { modelError("%1%: expected a member", mkind->getNode()); return; } cstring mkind_name = mkind->to()->name; - cstring type = "?"; + cstring type; if (mkind_name == "PACKETS") { - type = "packets"; + type = "packets"_cs; } else if (mkind_name == "BYTES") { - type = "bytes"; + type = "bytes"_cs; } else { modelError("%1%: unexpected meter type", mkind->getNode()); return; } - jmtr->emplace("type", type); - jmtr->emplace("size", info->tableSize); + jmtr->emplace("type"_cs, type); + jmtr->emplace("size"_cs, info->tableSize); cstring tblname = info->table->controlPlaneName(); - jmtr->emplace("binding", tblname); + jmtr->emplace("binding"_cs, tblname); auto result = ctxt->conv->convert(info->destinationField); - jmtr->emplace("result_target", result->to()->get("value")); + jmtr->emplace("result_target"_cs, result->to()->get("value"_cs)); ctxt->json->meter_arrays->append(jmtr); } @@ -932,10 +936,10 @@ void ExternConverter_Register::convertExternInstance(UNUSED ConversionContext *c auto inst = c->to(); cstring name = inst->controlPlaneName(); auto jreg = new Util::JsonObject(); - jreg->emplace("name", name); - jreg->emplace("id", nextId("register_arrays")); - jreg->emplace_non_null("source_info", eb->sourceInfoJsonObj()); - auto sz = eb->findParameterValue("size"); + jreg->emplace("name"_cs, name); + jreg->emplace("id"_cs, nextId("register_arrays"_cs)); + jreg->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); + auto sz = eb->findParameterValue("size"_cs); CHECK_NULL(sz); if (!sz->is()) { modelError("%1%: expected a constant", sz->getNode()); @@ -943,7 +947,7 @@ void ExternConverter_Register::convertExternInstance(UNUSED ConversionContext *c } if (sz->to()->value == 0) error(ErrorType::ERR_UNSUPPORTED, "%1%: direct registers are not supported", inst); - jreg->emplace("size", sz->to()->value); + jreg->emplace("size"_cs, sz->to()->value); if (!eb->instanceType->is()) { modelError("%1%: Expected a generic specialized type", eb->instanceType); return; @@ -964,7 +968,7 @@ void ExternConverter_Register::convertExternInstance(UNUSED ConversionContext *c ::error(ErrorType::ERR_UNKNOWN, "%1%: unknown width", st->arguments->at(0)); return; } - jreg->emplace("bitwidth", width); + jreg->emplace("bitwidth"_cs, width); ctxt->json->register_arrays->append(jreg); } @@ -983,18 +987,18 @@ void ExternConverter_ActionProfile::convertExternInstance(UNUSED ConversionConte // once in a pipeline, so only add it to the action_profiles once if (BMV2::JsonObjects::find_object_by_name(ctxt->action_profiles, name)) return; auto action_profile = new Util::JsonObject(); - action_profile->emplace("name", name); - action_profile->emplace("id", nextId("action_profiles")); - action_profile->emplace_non_null("source_info", eb->sourceInfoJsonObj()); + action_profile->emplace("name"_cs, name); + action_profile->emplace("id"_cs, nextId("action_profiles"_cs)); + action_profile->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); - auto sz = eb->findParameterValue("size"); + auto sz = eb->findParameterValue("size"_cs); BUG_CHECK(sz, "%1%Invalid declaration of extern ActionProfile ctor: no size param", eb->constructor->srcInfo); if (!sz->is()) { ::error(ErrorType::ERR_EXPECTED, "%1%: expected a constant", sz); } - action_profile->emplace("max_size", sz->to()->value); + action_profile->emplace("max_size"_cs, sz->to()->value); ctxt->action_profiles->append(action_profile); } @@ -1009,28 +1013,28 @@ void ExternConverter_ActionSelector::convertExternInstance(UNUSED ConversionCont // once in a pipeline, so only add it to the action_profiles once if (BMV2::JsonObjects::find_object_by_name(ctxt->action_profiles, name)) return; auto action_profile = new Util::JsonObject(); - action_profile->emplace("name", name); - action_profile->emplace("id", nextId("action_profiles")); - action_profile->emplace_non_null("source_info", eb->sourceInfoJsonObj()); + action_profile->emplace("name"_cs, name); + action_profile->emplace("id"_cs, nextId("action_profiles"_cs)); + action_profile->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); - auto sz = eb->findParameterValue("size"); + auto sz = eb->findParameterValue("size"_cs); BUG_CHECK(sz, "%1%Invalid declaration of extern ActionSelector: no size param", eb->constructor->srcInfo); if (!sz->is()) { ::error(ErrorType::ERR_EXPECTED, "%1%: expected a constant", sz); return; } - action_profile->emplace("max_size", sz->to()->value); + action_profile->emplace("max_size"_cs, sz->to()->value); auto selector = new Util::JsonObject(); - auto hash = eb->findParameterValue("algo"); + auto hash = eb->findParameterValue("algo"_cs); if (!hash->is()) { modelError("%1%: expected a member", hash->getNode()); return; } auto algo = ExternConverter::convertHashAlgorithm(hash->to()->name); - selector->emplace("algo", algo); + selector->emplace("algo"_cs, algo); auto input = ctxt->get_selector_input(c->to()); if (input == nullptr) { // the selector is never used by any table, we cannot figure out its @@ -1041,12 +1045,12 @@ void ExternConverter_ActionSelector::convertExternInstance(UNUSED ConversionCont c); return; } - auto j_input = mkArrayField(selector, "input"); + auto j_input = mkArrayField(selector, "input"_cs); for (auto expr : *input) { auto jk = ctxt->conv->convert(expr); j_input->append(jk); } - action_profile->emplace("selector", selector); + action_profile->emplace("selector"_cs, selector); ctxt->action_profiles->append(action_profile); } diff --git a/backends/bmv2/psa_switch/psaSwitch.h b/backends/bmv2/psa_switch/psaSwitch.h index 482604bf02..92102fcc08 100644 --- a/backends/bmv2/psa_switch/psaSwitch.h +++ b/backends/bmv2/psa_switch/psaSwitch.h @@ -58,20 +58,20 @@ class PsaSwitchExpressionConverter : public ExpressionConverter { cstring ptName = param->type->toString(); if (PsaProgramStructure::isCounterMetadata(ptName)) { // check if its counter metadata auto jsn = new Util::JsonObject(); - jsn->emplace("name", param->toString()); - jsn->emplace("type", "hexstr"); + jsn->emplace("name"_cs, param->toString()); + jsn->emplace("type"_cs, "hexstr"); auto bitwidth = param->type->width_bits(); // encode the counter type from enum -> int if (fieldName == "BYTES") { cstring repr = BMV2::stringRepr(0, ROUNDUP(bitwidth, 32)); - jsn->emplace("value", repr); + jsn->emplace("value"_cs, repr); } else if (fieldName == "PACKETS") { cstring repr = BMV2::stringRepr(1, ROUNDUP(bitwidth, 32)); - jsn->emplace("value", repr); + jsn->emplace("value"_cs, repr); } else if (fieldName == "PACKETS_AND_BYTES") { cstring repr = BMV2::stringRepr(2, ROUNDUP(bitwidth, 32)); - jsn->emplace("value", repr); + jsn->emplace("value"_cs, repr); } else { modelError("%1%: Exptected a PSA_CounterType_t", fieldName); return nullptr; @@ -81,8 +81,8 @@ class PsaSwitchExpressionConverter : public ExpressionConverter { auto jsn = new Util::JsonObject(); // encode the metadata type and field in json - jsn->emplace("type", "field"); - auto a = mkArrayField(jsn, "value"); + jsn->emplace("type"_cs, "field"); + auto a = mkArrayField(jsn, "value"_cs); a->append(ptName.exceptLast(2)); a->append(fieldName); return jsn; @@ -133,7 +133,7 @@ class ConvertPsaToJson : public Inspector { } void postorder(UNUSED const IR::P4Program *program) override { - cstring scalarsName = "scalars"; + cstring scalarsName = "scalars"_cs; // This visitor is used in multiple passes to convert expression to json auto conv = new PsaSwitchExpressionConverter(refMap, typeMap, structure, scalarsName); auto ctxt = new ConversionContext(refMap, typeMap, toplevel, structure, conv, json); diff --git a/backends/bmv2/simple_switch/main.cpp b/backends/bmv2/simple_switch/main.cpp index cc5493d3c1..cfcfde15ef 100644 --- a/backends/bmv2/simple_switch/main.cpp +++ b/backends/bmv2/simple_switch/main.cpp @@ -44,7 +44,7 @@ int main(int argc, char *const argv[]) { AutoCompileContext autoBMV2Context(new BMV2::SimpleSwitchContext); auto &options = BMV2::SimpleSwitchContext::get().options(); options.langVersion = CompilerOptions::FrontendVersion::P4_16; - options.compilerVersion = BMV2_SIMPLESWITCH_VERSION_STRING; + options.compilerVersion = cstring(BMV2_SIMPLESWITCH_VERSION_STRING); if (options.process(argc, argv) != nullptr) { if (options.loadIRFromJson == false) options.setInputFile(); diff --git a/backends/bmv2/simple_switch/midend.cpp b/backends/bmv2/simple_switch/midend.cpp index e07d23fdd5..3b3035310b 100644 --- a/backends/bmv2/simple_switch/midend.cpp +++ b/backends/bmv2/simple_switch/midend.cpp @@ -30,6 +30,7 @@ limitations under the License. #include "frontends/p4/typeMap.h" #include "frontends/p4/uniqueNames.h" #include "frontends/p4/unusedDeclarations.h" +#include "lib/cstring.h" #include "midend/actionSynthesis.h" #include "midend/checkSize.h" #include "midend/compileTimeOps.h" @@ -67,12 +68,14 @@ limitations under the License. namespace BMV2 { +using namespace P4::literals; + SimpleSwitchMidEnd::SimpleSwitchMidEnd(CompilerOptions &options, std::ostream *outStream) : MidEnd(options) { auto *evaluator = new P4::EvaluatorPass(&refMap, &typeMap); - if (BMV2::SimpleSwitchContext::get().options().loadIRFromJson == false) { + if (!BMV2::SimpleSwitchContext::get().options().loadIRFromJson) { auto *convertEnums = - new P4::ConvertEnums(&refMap, &typeMap, new EnumOn32Bits("v1model.p4")); + new P4::ConvertEnums(&refMap, &typeMap, new EnumOn32Bits("v1model.p4"_cs)); addPasses( {options.ndebug ? new P4::RemoveAssertAssume(&refMap, &typeMap) : nullptr, new P4::CheckTableSize(), @@ -114,8 +117,8 @@ SimpleSwitchMidEnd::SimpleSwitchMidEnd(CompilerOptions &options, std::ostream *o &refMap, &typeMap, new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsMask())), new P4::MoveDeclarations(), - new P4::ValidateTableProperties( - {"implementation", "size", "counters", "meters", "support_timeout"}), + new P4::ValidateTableProperties({"implementation"_cs, "size"_cs, "counters"_cs, + "meters"_cs, "support_timeout"_cs}), new P4::SimplifyControlFlow(&refMap, &typeMap), new P4::EliminateTypedef(&refMap, &typeMap), new P4::CompileTimeOperations(), @@ -131,7 +134,7 @@ SimpleSwitchMidEnd::SimpleSwitchMidEnd(CompilerOptions &options, std::ostream *o [this, evaluator]() { toplevel = evaluator->getToplevelBlock(); }, new P4::MidEndLast()}); if (options.listMidendPasses) { - listPasses(*outStream, "\n"); + listPasses(*outStream, cstring::newline); *outStream << std::endl; return; } @@ -139,7 +142,7 @@ SimpleSwitchMidEnd::SimpleSwitchMidEnd(CompilerOptions &options, std::ostream *o removePasses(options.passesToExcludeMidend); } } else { - auto *fillEnumMap = new P4::FillEnumMap(new EnumOn32Bits("v1model.p4"), &typeMap); + auto *fillEnumMap = new P4::FillEnumMap(new EnumOn32Bits("v1model.p4"_cs), &typeMap); addPasses({ new P4::ResolveReferences(&refMap), new P4::TypeChecking(&refMap, &typeMap), diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index 4959ed8388..e154cedcd5 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -135,14 +135,14 @@ Util::IJson *ExternConverter_clone::convertExternFunction(ConversionContext *ctx } cstring prim; if (ei->name == "I2E") { - prim = "clone_ingress_pkt_to_egress"; + prim = "clone_ingress_pkt_to_egress"_cs; if (ctxt->blockConverted != BlockConverted::Ingress) { ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "'clone(I2E, ...) not invoked in ingress %1%", mc); return nullptr; } } else { - prim = "clone_egress_pkt_to_egress"; + prim = "clone_egress_pkt_to_egress"_cs; if (ctxt->blockConverted != BlockConverted::Egress) { ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "'clone(E2E, ...) not invoked in egress %1%", mc); @@ -153,7 +153,7 @@ Util::IJson *ExternConverter_clone::convertExternFunction(ConversionContext *ctx auto session = ctxt->conv->convert(mc->arguments->at(1)->expression); auto primitive = mkPrimitive(prim); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", mc->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, mc->sourceInfoJsonObj()); parameters->append(session); if (id >= 0) { @@ -172,9 +172,9 @@ static unsigned getFieldListById(ConversionContext *ctxt, unsigned index) { for (auto it : *ctxt->json->field_lists) { auto j = it->to(); CHECK_NULL(j); - auto name = j->get("name")->to()->getString(); + auto name = j->get("name"_cs)->to()->getString(); if (name == search) { - id = j->get("id")->to()->getInt(); + id = j->get("id"_cs)->to()->getInt(); break; } } @@ -206,14 +206,14 @@ Util::IJson *ExternConverter_clone_preserving_field_list::convertExternFunction( } cstring prim; if (ei->name == "I2E") { - prim = "clone_ingress_pkt_to_egress"; + prim = "clone_ingress_pkt_to_egress"_cs; if (ctxt->blockConverted != BlockConverted::Ingress) { ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "'clone_preserving_field_list(I2E, ...) not invoked in ingress %1%", mc); return nullptr; } } else { - prim = "clone_egress_pkt_to_egress"; + prim = "clone_egress_pkt_to_egress"_cs; if (ctxt->blockConverted != BlockConverted::Egress) { ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "'clone_preserving_field_list(E2E, ...) not invoked in egress %1%", mc); @@ -223,7 +223,7 @@ Util::IJson *ExternConverter_clone_preserving_field_list::convertExternFunction( auto session = ctxt->conv->convert(mc->arguments->at(1)->expression); auto primitive = mkPrimitive(prim); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", mc->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, mc->sourceInfoJsonObj()); parameters->append(session); auto fl = mc->arguments->at(2); @@ -256,9 +256,9 @@ Util::IJson *ExternConverter_hash::convertExternFunction(ConversionContext *ctxt modelError("Expected 5 arguments for %1%", mc); return nullptr; } - auto primitive = mkPrimitive("modify_field_with_hash_based_offset"); + auto primitive = mkPrimitive("modify_field_with_hash_based_offset"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto dest = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(dest); auto base = ctxt->conv->convert(mc->arguments->at(2)->expression); @@ -273,8 +273,8 @@ Util::IJson *ExternConverter_hash::convertExternFunction(ConversionContext *ctxt auto fields = mc->arguments->at(3); auto calcName = ctxt->createCalculation(ei->name, fields->expression, ctxt->json->calculations, false, nullptr); - calculation->emplace("type", "calculation"); - calculation->emplace("value", calcName); + calculation->emplace("type"_cs, "calculation"); + calculation->emplace("value"_cs, calcName); parameters->append(calculation); auto max = ctxt->conv->convert(mc->arguments->at(4)->expression); parameters->append(max); @@ -290,12 +290,12 @@ Util::IJson *ExternConverter_digest::convertExternFunction(ConversionContext *ct modelError("Expected 2 arguments for %1%", mc); return nullptr; } - auto primitive = mkPrimitive("generate_digest"); + auto primitive = mkPrimitive("generate_digest"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", mc->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, mc->sourceInfoJsonObj()); auto dest = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(dest); - cstring listName = "digest"; + cstring listName = "digest"_cs; // If we are supplied a type argument that is a named type use // that for the list name. if (mc->typeArguments->size() == 1) { @@ -328,9 +328,9 @@ Util::IJson *ExternConverter_resubmit_preserving_field_list::convertExternFuncti return nullptr; } if (mc->arguments->size() == 1) { - auto primitive = mkPrimitive("resubmit"); + auto primitive = mkPrimitive("resubmit"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", mc->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, mc->sourceInfoJsonObj()); auto arg = mc->arguments->at(0); auto cst = arg->expression->to(); if (cst == nullptr) { @@ -359,9 +359,9 @@ Util::IJson *ExternConverter_recirculate_preserving_field_list::convertExternFun return nullptr; } if (mc->arguments->size() == 1) { - auto primitive = mkPrimitive("recirculate"); + auto primitive = mkPrimitive("recirculate"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", mc->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, mc->sourceInfoJsonObj()); auto arg = mc->arguments->at(0); auto cst = arg->expression->to(); if (cst == nullptr) { @@ -389,11 +389,11 @@ Util::IJson *ExternConverter_mark_to_drop::convertExternFunction( modelError("Expected 1 argument for %1%", mc); return nullptr; } - auto primitive = mkPrimitive("mark_to_drop"); + auto primitive = mkPrimitive("mark_to_drop"_cs); auto params = mkParameters(primitive); auto dest = ctxt->conv->convert(mc->arguments->at(0)->expression); params->append(dest); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); return primitive; } @@ -408,7 +408,7 @@ Util::IJson *ExternConverter_random::convertExternFunction(ConversionContext *ct } auto primitive = mkPrimitive(v1model.random.modify_field_rng_uniform.name); auto params = mkParameters(primitive); - primitive->emplace_non_null("source_info", mc->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, mc->sourceInfoJsonObj()); auto dest = ctxt->conv->convert(mc->arguments->at(0)->expression); auto lo = ctxt->conv->convert(mc->arguments->at(1)->expression); auto hi = ctxt->conv->convert(mc->arguments->at(2)->expression); @@ -429,7 +429,7 @@ Util::IJson *ExternConverter_truncate::convertExternFunction(UNUSED ConversionCo } auto primitive = mkPrimitive(v1model.truncate.name); auto params = mkParameters(primitive); - primitive->emplace_non_null("source_info", mc->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, mc->sourceInfoJsonObj()); auto len = ctxt->conv->convert(mc->arguments->at(0)->expression); params->append(len); return primitive; @@ -444,12 +444,12 @@ Util::IJson *ExternConverter_counter::convertExternObject(ConversionContext *ctx modelError("Expected 1 argument for %1%", mc); return nullptr; } - auto primitive = mkPrimitive("count"); + auto primitive = mkPrimitive("count"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto ctr = new Util::JsonObject(); - ctr->emplace("type", "counter_array"); - ctr->emplace("value", em->object->controlPlaneName()); + ctr->emplace("type"_cs, "counter_array"); + ctr->emplace("value"_cs, em->object->controlPlaneName()); parameters->append(ctr); auto index = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(index); @@ -463,17 +463,17 @@ void ExternConverter_counter::convertExternInstance(ConversionContext *ctxt, auto inst = c->to(); cstring name = inst->controlPlaneName(); auto jctr = new Util::JsonObject(); - jctr->emplace("name", name); - jctr->emplace("id", nextId("counter_arrays")); - jctr->emplace_non_null("source_info", eb->sourceInfoJsonObj()); + jctr->emplace("name"_cs, name); + jctr->emplace("id"_cs, nextId("counter_arrays"_cs)); + jctr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto sz = eb->findParameterValue(v1model.counter.sizeParam.name); CHECK_NULL(sz); if (!sz->is()) { modelError("%1%: expected a constant", sz->getNode()); return; } - jctr->emplace("size", sz->to()->value); - jctr->emplace("is_direct", false); + jctr->emplace("size"_cs, sz->to()->value); + jctr->emplace("is_direct"_cs, false); ctxt->json->counters->append(jctr); } @@ -486,12 +486,12 @@ Util::IJson *ExternConverter_meter::convertExternObject(ConversionContext *ctxt, modelError("Expected 2 arguments for %1%", mc); return nullptr; } - auto primitive = mkPrimitive("execute_meter"); + auto primitive = mkPrimitive("execute_meter"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto mtr = new Util::JsonObject(); - mtr->emplace("type", "meter_array"); - mtr->emplace("value", em->object->controlPlaneName()); + mtr->emplace("type"_cs, "meter_array"); + mtr->emplace("value"_cs, em->object->controlPlaneName()); parameters->append(mtr); auto index = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(index); @@ -506,18 +506,18 @@ void ExternConverter_meter::convertExternInstance(ConversionContext *ctxt, const auto inst = c->to(); cstring name = inst->controlPlaneName(); auto jmtr = new Util::JsonObject(); - jmtr->emplace("name", name); - jmtr->emplace("id", nextId("meter_arrays")); - jmtr->emplace_non_null("source_info", eb->sourceInfoJsonObj()); - jmtr->emplace("is_direct", false); + jmtr->emplace("name"_cs, name); + jmtr->emplace("id"_cs, nextId("meter_arrays"_cs)); + jmtr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); + jmtr->emplace("is_direct"_cs, false); auto sz = eb->findParameterValue(v1model.meter.sizeParam.name); CHECK_NULL(sz); if (!sz->is()) { modelError("%1%: expected a constant", sz->getNode()); return; } - jmtr->emplace("size", sz->to()->value); - jmtr->emplace("rate_count", 2); + jmtr->emplace("size"_cs, sz->to()->value); + jmtr->emplace("rate_count"_cs, 2); auto mkind = eb->findParameterValue(v1model.meter.typeParam.name); CHECK_NULL(mkind); if (!mkind->is()) { @@ -525,15 +525,15 @@ void ExternConverter_meter::convertExternInstance(ConversionContext *ctxt, const return; } cstring mkind_name = mkind->to()->name; - cstring type = "?"; + cstring type = "?"_cs; if (mkind_name == v1model.meter.meterType.packets.name) - type = "packets"; + type = "packets"_cs; else if (mkind_name == v1model.meter.meterType.bytes.name) - type = "bytes"; + type = "bytes"_cs; else ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "Unexpected meter type %1%", mkind->getNode()); - jmtr->emplace("type", type); + jmtr->emplace("type"_cs, type); ctxt->json->meter_arrays->append(jmtr); } @@ -547,13 +547,13 @@ Util::IJson *ExternConverter_register::convertExternObject(ConversionContext *ct return nullptr; } auto reg = new Util::JsonObject(); - reg->emplace("type", "register_array"); + reg->emplace("type"_cs, "register_array"); cstring name = em->object->controlPlaneName(); - reg->emplace("value", name); + reg->emplace("value"_cs, name); if (em->method->name == v1model.registers.read.name) { - auto primitive = mkPrimitive("register_read"); + auto primitive = mkPrimitive("register_read"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto dest = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(dest); parameters->append(reg); @@ -561,9 +561,9 @@ Util::IJson *ExternConverter_register::convertExternObject(ConversionContext *ct parameters->append(index); return primitive; } else if (em->method->name == v1model.registers.write.name) { - auto primitive = mkPrimitive("register_write"); + auto primitive = mkPrimitive("register_write"_cs); auto parameters = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); parameters->append(reg); auto index = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(index); @@ -581,9 +581,9 @@ void ExternConverter_register::convertExternInstance(ConversionContext *ctxt, auto inst = c->to(); cstring name = inst->controlPlaneName(); auto jreg = new Util::JsonObject(); - jreg->emplace("name", name); - jreg->emplace("id", nextId("register_arrays")); - jreg->emplace_non_null("source_info", eb->sourceInfoJsonObj()); + jreg->emplace("name"_cs, name); + jreg->emplace("id"_cs, nextId("register_arrays"_cs)); + jreg->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto sz = eb->findParameterValue(v1model.registers.sizeParam.name); CHECK_NULL(sz); if (!sz->is()) { @@ -593,7 +593,7 @@ void ExternConverter_register::convertExternInstance(ConversionContext *ctxt, if (sz->to()->value == 0) error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "%1%: direct registers are not supported in bmv2", inst); - jreg->emplace("size", sz->to()->value); + jreg->emplace("size"_cs, sz->to()->value); if (auto st = eb->instanceType->to()) { if (st->arguments->size() < 1 || st->arguments->size() > 2) { modelError("%1%: expected 1 or 2 type arguments", st); @@ -610,7 +610,7 @@ void ExternConverter_register::convertExternInstance(ConversionContext *ctxt, ::error(ErrorType::ERR_EXPRESSION, "%1%: unknown width", st->arguments->at(0)); return; } - jreg->emplace("bitwidth", width); + jreg->emplace("bitwidth"_cs, width); ctxt->json->register_arrays->append(jreg); } else { modelError("%1%: Expected a generic specialized type", eb->instanceType); @@ -641,11 +641,11 @@ void ExternConverter_direct_counter::convertExternInstance(ConversionContext *ct ::warning(ErrorType::WARN_UNUSED, "%1%: Direct counter not used; ignoring", inst); } else { auto jctr = new Util::JsonObject(); - jctr->emplace("name", name); - jctr->emplace("id", nextId("counter_arrays")); - jctr->emplace("is_direct", true); - jctr->emplace("binding", it->second->controlPlaneName()); - jctr->emplace_non_null("source_info", eb->sourceInfoJsonObj()); + jctr->emplace("name"_cs, name); + jctr->emplace("id"_cs, nextId("counter_arrays"_cs)); + jctr->emplace("is_direct"_cs, true); + jctr->emplace("binding"_cs, it->second->controlPlaneName()); + jctr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); ctxt->json->counters->append(jctr); } } @@ -696,11 +696,11 @@ void ExternConverter_direct_meter::convertExternInstance(ConversionContext *ctxt CHECK_NULL(info->destinationField); auto jmtr = new Util::JsonObject(); - jmtr->emplace("name", name); - jmtr->emplace("id", nextId("meter_arrays")); - jmtr->emplace_non_null("source_info", eb->sourceInfoJsonObj()); - jmtr->emplace("is_direct", true); - jmtr->emplace("rate_count", 2); + jmtr->emplace("name"_cs, name); + jmtr->emplace("id"_cs, nextId("meter_arrays"_cs)); + jmtr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); + jmtr->emplace("is_direct"_cs, true); + jmtr->emplace("rate_count"_cs, 2); auto mkind = eb->findParameterValue(v1model.directMeter.typeParam.name); CHECK_NULL(mkind); if (!mkind->is()) { @@ -708,21 +708,21 @@ void ExternConverter_direct_meter::convertExternInstance(ConversionContext *ctxt return; } cstring mkind_name = mkind->to()->name; - cstring type = "?"; + cstring type = "?"_cs; if (mkind_name == v1model.meter.meterType.packets.name) { - type = "packets"; + type = "packets"_cs; } else if (mkind_name == v1model.meter.meterType.bytes.name) { - type = "bytes"; + type = "bytes"_cs; } else { modelError("%1%: unexpected meter type", mkind->getNode()); return; } - jmtr->emplace("type", type); - jmtr->emplace("size", info->tableSize); + jmtr->emplace("type"_cs, type); + jmtr->emplace("size"_cs, info->tableSize); cstring tblname = info->table->controlPlaneName(); - jmtr->emplace("binding", tblname); + jmtr->emplace("binding"_cs, tblname); auto result = ctxt->conv->convert(info->destinationField); - jmtr->emplace("result_target", result->to()->get("value")); + jmtr->emplace("result_target"_cs, result->to()->get("value"_cs)); ctxt->json->meter_arrays->append(jmtr); } @@ -736,9 +736,9 @@ void ExternConverter_action_profile::convertExternInstance(ConversionContext *ct // once in a pipeline, so only add it to the action_profiles once if (BMV2::JsonObjects::find_object_by_name(ctxt->action_profiles, name)) return; auto action_profile = new Util::JsonObject(); - action_profile->emplace("name", name); - action_profile->emplace("id", nextId("action_profiles")); - action_profile->emplace_non_null("source_info", eb->sourceInfoJsonObj()); + action_profile->emplace("name"_cs, name); + action_profile->emplace("id"_cs, nextId("action_profiles"_cs)); + action_profile->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto add_size = [&action_profile, &eb](const cstring &pname) { auto sz = eb->findParameterValue(pname); @@ -748,7 +748,7 @@ void ExternConverter_action_profile::convertExternInstance(ConversionContext *ct ::error(ErrorType::ERR_EXPECTED, "%1%: expected a constant", sz); return; } - action_profile->emplace("max_size", sz->to()->value); + action_profile->emplace("max_size"_cs, sz->to()->value); }; if (eb->type->name == v1model.action_profile.name) { @@ -762,7 +762,7 @@ void ExternConverter_action_profile::convertExternInstance(ConversionContext *ct return; } auto algo = ExternConverter::convertHashAlgorithm(hash->to()->name); - selector->emplace("algo", algo); + selector->emplace("algo"_cs, algo); auto input = ctxt->get_selector_input(inst); if (input == nullptr) { // the selector is never used by any table, we cannot figure out its @@ -773,12 +773,12 @@ void ExternConverter_action_profile::convertExternInstance(ConversionContext *ct c); return; } - auto j_input = mkArrayField(selector, "input"); + auto j_input = mkArrayField(selector, "input"_cs); for (auto expr : *input) { auto jk = ctxt->conv->convert(expr); j_input->append(jk); } - action_profile->emplace("selector", selector); + action_profile->emplace("selector"_cs, selector); } ctxt->action_profiles->append(action_profile); @@ -795,9 +795,9 @@ void ExternConverter_action_selector::convertExternInstance(ConversionContext *c // once in a pipeline, so only add it to the action_profiles once if (BMV2::JsonObjects::find_object_by_name(ctxt->action_profiles, name)) return; auto action_profile = new Util::JsonObject(); - action_profile->emplace("name", name); - action_profile->emplace("id", nextId("action_profiles")); - action_profile->emplace_non_null("source_info", eb->sourceInfoJsonObj()); + action_profile->emplace("name"_cs, name); + action_profile->emplace("id"_cs, nextId("action_profiles"_cs)); + action_profile->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto add_size = [&action_profile, &eb](const cstring &pname) { auto sz = eb->findParameterValue(pname); @@ -807,7 +807,7 @@ void ExternConverter_action_selector::convertExternInstance(ConversionContext *c ::error(ErrorType::ERR_EXPECTED, "%1%: expected a constant", sz); return; } - action_profile->emplace("max_size", sz->to()->value); + action_profile->emplace("max_size"_cs, sz->to()->value); }; if (eb->type->name == v1model.action_profile.name) { @@ -821,7 +821,7 @@ void ExternConverter_action_selector::convertExternInstance(ConversionContext *c return; } auto algo = ExternConverter::convertHashAlgorithm(hash->to()->name); - selector->emplace("algo", algo); + selector->emplace("algo"_cs, algo); auto input = ctxt->get_selector_input(inst); if (input == nullptr) { // the selector is never used by any table, we cannot figure out its @@ -832,12 +832,12 @@ void ExternConverter_action_selector::convertExternInstance(ConversionContext *c c); return; } - auto j_input = mkArrayField(selector, "input"); + auto j_input = mkArrayField(selector, "input"_cs); for (auto expr : *input) { auto jk = ctxt->conv->convert(expr); j_input->append(jk); } - action_profile->emplace("selector", selector); + action_profile->emplace("selector"_cs, selector); } ctxt->action_profiles->append(action_profile); @@ -852,11 +852,11 @@ Util::IJson *ExternConverter_log_msg::convertExternFunction(ConversionContext *c modelError("Expected 1 or 2 arguments for %1%", mc); return nullptr; } - auto primitive = mkPrimitive("log_msg"); + auto primitive = mkPrimitive("log_msg"_cs); auto params = mkParameters(primitive); - primitive->emplace_non_null("source_info", s->sourceInfoJsonObj()); + primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto paramsValue = new Util::JsonObject(); - paramsValue->emplace("type", "parameters_vector"); + paramsValue->emplace("type"_cs, "parameters_vector"); auto str = ctxt->conv->convert(mc->arguments->at(0)->expression); params->append(str); if (mc->arguments->size() == 2) { @@ -882,18 +882,18 @@ Util::IJson *ExternConverter_log_msg::convertExternFunction(ConversionContext *c auto val = ctxt->conv->convert(v, false, true, true); arr->append(val); } - paramsValue->emplace("value", arr); + paramsValue->emplace("value"_cs, arr); } else { auto tmp = new Util::JsonObject(); - paramsValue->emplace("value", tmp); + paramsValue->emplace("value"_cs, tmp); } params->append(paramsValue); return primitive; } void SimpleSwitchBackend::modelError(const char *format, const IR::Node *node) const { - ::error(ErrorType::ERR_MODEL, - (cstring("%1%") + format + "\nAre you using an up-to-date v1model.p4?").c_str(), node); + ::errorWithSuffix(ErrorType::ERR_MODEL, format, "\nAre you using an up-to-date v1model.p4?", + node); } cstring SimpleSwitchBackend::createCalculation(cstring algo, const IR::Expression *fields, @@ -901,11 +901,11 @@ cstring SimpleSwitchBackend::createCalculation(cstring algo, const IR::Expressio const IR::Node *sourcePositionNode = nullptr) { cstring calcName = refMap->newName("calc_"); auto calc = new Util::JsonObject(); - calc->emplace("name", calcName); - calc->emplace("id", nextId("calculations")); + calc->emplace("name"_cs, calcName); + calc->emplace("id"_cs, nextId("calculations"_cs)); if (sourcePositionNode != nullptr) - calc->emplace_non_null("source_info", sourcePositionNode->sourceInfoJsonObj()); - calc->emplace("algo", algo); + calc->emplace_non_null("source_info"_cs, sourcePositionNode->sourceInfoJsonObj()); + calc->emplace("algo"_cs, algo); fields = convertToList(fields, typeMap); if (!fields) { modelError("%1%: expected a struct", fields); @@ -916,11 +916,11 @@ cstring SimpleSwitchBackend::createCalculation(cstring algo, const IR::Expressio auto array = jright->to(); BUG_CHECK(array, "expected a JSON array"); auto payload = new Util::JsonObject(); - payload->emplace("type", "payload"); - payload->emplace("value", (Util::IJson *)nullptr); + payload->emplace("type"_cs, "payload"); + payload->emplace("value"_cs, (Util::IJson *)nullptr); array->append(payload); } - calc->emplace("input", jright); + calc->emplace("input"_cs, jright); calculations->append(calc); return calcName; } @@ -978,18 +978,18 @@ void SimpleSwitchBackend::convertChecksum(const IR::BlockStatement *block, (void)calcExpr->apply(eeis); cstring calcName = createCalculation(algo, calcExpr, calculations, usePayload, mc); - cksum->emplace("name", refMap->newName("cksum_")); - cksum->emplace("id", nextId("checksums")); - cksum->emplace_non_null("source_info", stat->sourceInfoJsonObj()); + cksum->emplace("name"_cs, refMap->newName("cksum_")); + cksum->emplace("id"_cs, nextId("checksums"_cs)); + cksum->emplace_non_null("source_info"_cs, stat->sourceInfoJsonObj()); auto jleft = conv->convert(mi->expr->arguments->at(2)->expression); - cksum->emplace("target", jleft->to()->get("value")); - cksum->emplace("type", "generic"); - cksum->emplace("calculation", calcName); - cksum->emplace("verify", verify); - cksum->emplace("update", !verify); + cksum->emplace("target"_cs, jleft->to()->get("value"_cs)); + cksum->emplace("type"_cs, "generic"); + cksum->emplace("calculation"_cs, calcName); + cksum->emplace("verify"_cs, verify); + cksum->emplace("update"_cs, !verify); auto ifcond = conv->convert(mi->expr->arguments->at(0)->expression, true, false); - cksum->emplace("if_cond", ifcond); + cksum->emplace("if_cond"_cs, ifcond); checksums->append(cksum); continue; } @@ -1037,7 +1037,7 @@ void SimpleSwitchBackend::createRecirculateFieldsList(ConversionContext *ctxt, LOG2("Scanning user metadata fields for annotations"); for (auto f : userMetaType->fields) { LOG3("Scanning field " << f); - auto anno = f->getAnnotations()->getSingle("field_list"); + auto anno = f->getAnnotations()->getSingle("field_list"_cs); if (anno == nullptr) continue; for (auto e : anno->expr) { @@ -1055,23 +1055,23 @@ void SimpleSwitchBackend::createRecirculateFieldsList(ConversionContext *ctxt, fl = new Util::JsonObject(); ctxt->json->field_lists->append(fl); fieldLists.emplace(index, fl); - int id = nextId("field_lists"); - fl->emplace("id", id); - cstring listName = cstring("field_list") + Util::toString(index); - fl->emplace("name", listName); - elements = mkArrayField(fl, "elements"); + int id = nextId("field_lists"_cs); + fl->emplace("id"_cs, id); + cstring listName = "field_list"_cs + Util::toString(index); + fl->emplace("name"_cs, listName); + elements = mkArrayField(fl, "elements"_cs); } else { - elements = fl->get("elements")->to(); + elements = fl->get("elements"_cs)->to(); CHECK_NULL(elements); } auto field = new Util::JsonObject(); - field->emplace("type", "field"); + field->emplace("type"_cs, "field"); auto value = new Util::JsonArray(); value->append(scalarName); auto name = ::get(ctxt->structure->scalarMetadataFields, f); value->append(name); - field->emplace("value", value); + field->emplace("value"_cs, value); elements->append(field); } } @@ -1205,8 +1205,8 @@ void SimpleSwitchBackend::convert(const IR::ToplevelBlock *tlb) { // other objects: they need to start at 1 (not 0) since the id is also used // as a "flag" to indicate that a certain simple_switch primitive has been // called (e.g. resubmit or generate_digest) - BMV2::nextId("field_lists"); - BMV2::nextId("learn_lists"); + BMV2::nextId("field_lists"_cs); + BMV2::nextId("learn_lists"_cs); json->add_program_info(options.file); json->add_meta_info(); @@ -1250,11 +1250,11 @@ void SimpleSwitchBackend::convert(const IR::ToplevelBlock *tlb) { ctxt->blockConverted = BlockConverted::Ingress; auto cconv = - new ControlConverter(ctxt, "ingress", options.emitExterns); + new ControlConverter(ctxt, "ingress"_cs, options.emitExterns); structure->ingress->apply(*cconv); ctxt->blockConverted = BlockConverted::Egress; - cconv = new ControlConverter(ctxt, "egress", options.emitExterns); + cconv = new ControlConverter(ctxt, "egress"_cs, options.emitExterns); structure->egress->apply(*cconv); ctxt->blockConverted = BlockConverted::Deparser; diff --git a/backends/bmv2/simple_switch/simpleSwitch.h b/backends/bmv2/simple_switch/simpleSwitch.h index a17c9b5d46..e0e43fa75a 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.h +++ b/backends/bmv2/simple_switch/simpleSwitch.h @@ -79,8 +79,8 @@ class SimpleSwitchExpressionConverter : public ExpressionConverter { : ExpressionConverter(refMap, typeMap, structure, scalarsName), structure(structure) {} void modelError(const char *format, const IR::Node *node) { - ::error(ErrorType::ERR_MODEL, - (cstring(format) + "\nAre you using an up-to-date v1model.p4?").c_str(), node); + ::errorWithSuffix(ErrorType::ERR_MODEL, format, "\nAre you using an up-to-date v1model.p4?", + node); } bool isStandardMetadataParameter(const IR::Parameter *param) { @@ -112,13 +112,13 @@ class SimpleSwitchExpressionConverter : public ExpressionConverter { if (isStandardMetadataParameter(param)) { auto result = new Util::JsonObject(); if (fieldName != "") { - result->emplace("type", "field"); - auto e = BMV2::mkArrayField(result, "value"); + result->emplace("type"_cs, "field"); + auto e = BMV2::mkArrayField(result, "value"_cs); e->append("standard_metadata"); e->append(fieldName); } else { - result->emplace("type", "header"); - result->emplace("value", "standard_metadata"); + result->emplace("type"_cs, "header"); + result->emplace("value"_cs, "standard_metadata"); } return result; } diff --git a/backends/dpdk/constants.h b/backends/dpdk/constants.h index 0e07bcc2ee..03fe6aa731 100644 --- a/backends/dpdk/constants.h +++ b/backends/dpdk/constants.h @@ -35,10 +35,11 @@ const unsigned default_learner_table_timeout[dpdk_learner_max_configurable_timeo 10, 30, 60, 120, 300, 43200, 120, 120}; /// JSON schema versions -const cstring bfrtSchemaVersion = "1.0.0"; -const cstring tdiSchemaVersion = "0.1"; +const cstring bfrtSchemaVersion = cstring::literal("1.0.0"); +const cstring tdiSchemaVersion = cstring::literal("0.1"); /// HASH Values +// FIXME: These should be enum #define JHASH0 0 #define CRC1 1 #define CRC2 2 diff --git a/backends/dpdk/control-plane/bfruntime_arch_handler.h b/backends/dpdk/control-plane/bfruntime_arch_handler.h index d77d6a9216..ab0b1103db 100644 --- a/backends/dpdk/control-plane/bfruntime_arch_handler.h +++ b/backends/dpdk/control-plane/bfruntime_arch_handler.h @@ -136,7 +136,7 @@ class BFRuntimeArchHandler : public P4RuntimeArchHandlerCommon { cstring getBlockNamePrefix(const IR::Block *blk) { if (blockNamePrefixMap.count(blk) > 0) return blockNamePrefixMap[blk]; - return "pipe"; + return "pipe"_cs; } static p4configv1::Extern *getP4InfoExtern(P4RuntimeSymbolType typeId, cstring typeName, @@ -154,7 +154,8 @@ class BFRuntimeArchHandler : public P4RuntimeArchHandlerCommon { P4RuntimeSymbolType typeId, cstring typeName, cstring name, const IR::IAnnotated *annotations, const ::google::protobuf::Message &message, - p4configv1::P4Info *p4info, cstring pipeName = "") { + p4configv1::P4Info *p4info, + cstring pipeName = cstring::empty) { auto *externType = getP4InfoExtern(typeId, typeName, p4info); auto *externInstance = externType->add_instances(); auto *pre = externInstance->mutable_preamble(); @@ -169,7 +170,7 @@ class BFRuntimeArchHandler : public P4RuntimeArchHandlerCommon { std::optional getActionSelector(const IR::ExternBlock *instance) { auto actionSelDecl = instance->node->to(); // to be deleted, used to support deprecated ActionSelector constructor. - auto size = instance->getParameterValue("size"); + auto size = instance->getParameterValue("size"_cs); BUG_CHECK(size->is(), "Non-constant size"); return ActionSelector{actionSelDecl->controlPlaneName(), size->to()->asInt(), ActionSelector::defaultMaxGroupSize, @@ -178,7 +179,8 @@ class BFRuntimeArchHandler : public P4RuntimeArchHandlerCommon { } void addActionSelector(const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4Info, - const ActionSelector &actionSelector, cstring pipeName = "") { + const ActionSelector &actionSelector, + cstring pipeName = cstring::empty) { ::dpdk::ActionSelector selector; selector.set_max_group_size(actionSelector.maxGroupSize); selector.set_num_groups(actionSelector.numGroups); @@ -197,9 +199,9 @@ class BFRuntimeArchHandler : public P4RuntimeArchHandlerCommon { selector.set_action_profile_id( symbols.getId(SymbolType::P4RT_ACTION_PROFILE(), profileName)); cstring selectorName = profileName + "_sel"; - addP4InfoExternInstance(symbols, SymbolTypeDPDK::P4RT_ACTION_SELECTOR(), "ActionSelector", - selectorName, actionSelector.annotations, selector, p4Info, - pipeName); + addP4InfoExternInstance(symbols, SymbolTypeDPDK::P4RT_ACTION_SELECTOR(), + "ActionSelector"_cs, selectorName, actionSelector.annotations, + selector, p4Info, pipeName); } void collectExternInstance(P4RuntimeSymbolTableIface *symbols, @@ -316,7 +318,7 @@ class BFRuntimeArchHandler : public P4RuntimeArchHandlerCommon { /// @return true if @table's 'psa_idle_timeout' property exists and is true. This /// indicates that @table supports entry ageing. static bool getSupportsTimeout(const IR::P4Table *table) { - auto timeout = table->properties->getProperty("psa_idle_timeout"); + auto timeout = table->properties->getProperty("psa_idle_timeout"_cs); if (timeout == nullptr) return false; diff --git a/backends/dpdk/control-plane/bfruntime_ext.cpp b/backends/dpdk/control-plane/bfruntime_ext.cpp index f81468cc3c..693735baf5 100644 --- a/backends/dpdk/control-plane/bfruntime_ext.cpp +++ b/backends/dpdk/control-plane/bfruntime_ext.cpp @@ -60,22 +60,22 @@ void BFRuntimeSchemaGenerator::addMatchActionData(const p4configv1::Table &table Util::JsonObject *tableJson, Util::JsonArray *dataJson, P4Id maxActionParamId) const { - cstring tableType = tableJson->get("table_type")->to()->getString(); + cstring tableType = tableJson->get("table_type"_cs)->to()->getString(); if (tableType == "MatchAction_Direct") { - tableJson->emplace("action_specs", makeActionSpecs(table, &maxActionParamId)); + tableJson->emplace("action_specs"_cs, makeActionSpecs(table, &maxActionParamId)); } else if (tableType == "MatchAction_Indirect") { - auto *f = makeCommonDataField(BF_RT_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID", - makeType("uint32"), false /* repeated */); + auto *f = makeCommonDataField(BF_RT_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID"_cs, + makeType("uint32"_cs), false /* repeated */); addSingleton(dataJson, f, true /* mandatory */, false /* read-only */); } else if (tableType == "MatchAction_Indirect_Selector") { // action member id and selector group id are mutually-exclusive, so // we use a "oneof" here. auto *choicesDataJson = new Util::JsonArray(); choicesDataJson->append(makeCommonDataField(BF_RT_DATA_ACTION_MEMBER_ID, - "$ACTION_MEMBER_ID", makeType("uint32"), + "$ACTION_MEMBER_ID"_cs, makeType("uint32"_cs), false /* repeated */)); choicesDataJson->append(makeCommonDataField(BF_RT_DATA_SELECTOR_GROUP_ID, - "$SELECTOR_GROUP_ID", makeType("uint32"), + "$SELECTOR_GROUP_ID"_cs, makeType("uint32"_cs), false /* repeated */)); addOneOf(dataJson, choicesDataJson, true /* mandatory */, false /* read-only */); } else { @@ -85,26 +85,27 @@ void BFRuntimeSchemaGenerator::addMatchActionData(const p4configv1::Table &table void BFRuntimeSchemaGenerator::addActionSelectorGetMemberCommon( Util::JsonArray *tablesJson, const ActionSelector &actionSelector) const { - auto *tableJson = initTableJson(actionSelector.get_mem_name, actionSelector.get_mem_id, - "SelectorGetMember", 1 /* size */, actionSelector.annotations); + auto *tableJson = + initTableJson(actionSelector.get_mem_name, actionSelector.get_mem_id, + "SelectorGetMember"_cs, 1 /* size */, actionSelector.annotations); auto *keyJson = new Util::JsonArray(); - addKeyField(keyJson, BF_RT_DATA_SELECTOR_GROUP_ID, "$SELECTOR_GROUP_ID", true /* mandatory */, - "Exact", makeType("uint64")); - addKeyField(keyJson, BF_RT_DATA_HASH_VALUE, "hash_value", true /* mandatory */, "Exact", - makeType("uint64")); - tableJson->emplace("key", keyJson); + addKeyField(keyJson, BF_RT_DATA_SELECTOR_GROUP_ID, "$SELECTOR_GROUP_ID"_cs, + true /* mandatory */, "Exact"_cs, makeType("uint64"_cs)); + addKeyField(keyJson, BF_RT_DATA_HASH_VALUE, "hash_value"_cs, true /* mandatory */, "Exact"_cs, + makeType("uint64"_cs)); + tableJson->emplace("key"_cs, keyJson); auto *dataJson = new Util::JsonArray(); { - auto *f = makeCommonDataField(BF_RT_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID", - makeType("uint64"), false /* repeated */); + auto *f = makeCommonDataField(BF_RT_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID"_cs, + makeType("uint64"_cs), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } - tableJson->emplace("data", dataJson); + tableJson->emplace("data"_cs, dataJson); - tableJson->emplace("supported_operations", new Util::JsonArray()); - tableJson->emplace("attributes", new Util::JsonArray()); + tableJson->emplace("supported_operations"_cs, new Util::JsonArray()); + tableJson->emplace("attributes"_cs, new Util::JsonArray()); addToDependsOn(tableJson, actionSelector.id); tablesJson->append(tableJson); @@ -115,35 +116,35 @@ void BFRuntimeSchemaGenerator::addActionSelectorCommon(Util::JsonArray *tablesJs // TODO(antonin): formalize ID allocation for selector tables // repeat same annotations as for action table // the maximum number of groups is the table size for the selector table - auto *tableJson = initTableJson(actionSelector.name, actionSelector.id, "Selector", + auto *tableJson = initTableJson(actionSelector.name, actionSelector.id, "Selector"_cs, actionSelector.num_groups, actionSelector.annotations); auto *keyJson = new Util::JsonArray(); - addKeyField(keyJson, BF_RT_DATA_SELECTOR_GROUP_ID, "$SELECTOR_GROUP_ID", true /* mandatory */, - "Exact", makeType("uint32")); - tableJson->emplace("key", keyJson); + addKeyField(keyJson, BF_RT_DATA_SELECTOR_GROUP_ID, "$SELECTOR_GROUP_ID"_cs, + true /* mandatory */, "Exact"_cs, makeType("uint32"_cs)); + tableJson->emplace("key"_cs, keyJson); auto *dataJson = new Util::JsonArray(); { - auto *f = makeCommonDataField(BF_RT_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID", - makeType("uint32"), true /* repeated */); + auto *f = makeCommonDataField(BF_RT_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID"_cs, + makeType("uint32"_cs), true /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } { - auto *f = makeCommonDataField(BF_RT_DATA_ACTION_MEMBER_STATUS, "$ACTION_MEMBER_STATUS", + auto *f = makeCommonDataField(BF_RT_DATA_ACTION_MEMBER_STATUS, "$ACTION_MEMBER_STATUS"_cs, makeTypeBool(), true /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } { - auto *f = makeCommonDataField(BF_RT_DATA_MAX_GROUP_SIZE, "$MAX_GROUP_SIZE", - makeType("uint32", actionSelector.max_group_size), + auto *f = makeCommonDataField(BF_RT_DATA_MAX_GROUP_SIZE, "$MAX_GROUP_SIZE"_cs, + makeType("uint32"_cs, actionSelector.max_group_size), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } - tableJson->emplace("data", dataJson); + tableJson->emplace("data"_cs, dataJson); - tableJson->emplace("supported_operations", new Util::JsonArray()); - tableJson->emplace("attributes", new Util::JsonArray()); + tableJson->emplace("supported_operations"_cs, new Util::JsonArray()); + tableJson->emplace("attributes"_cs, new Util::JsonArray()); addToDependsOn(tableJson, actionSelector.action_profile_id); auto oneTableId = actionSelector.tableIds.at(0); @@ -168,16 +169,16 @@ bool BFRuntimeSchemaGenerator::addActionProfIds(const p4configv1::Table &table, implementationId); return false; } - cstring tableType = ""; + cstring tableType; if (*hasSelector) { - tableType = "MatchAction_Indirect_Selector"; + tableType = "MatchAction_Indirect_Selector"_cs; // actSelectorId & actProfId will be set while visiting action profile externs } else { actProfId = BFRuntimeSchemaGenerator::ActionProf::makeActProfId(implementationId); - tableType = "MatchAction_Indirect"; + tableType = "MatchAction_Indirect"_cs; } - tableJson->erase("table_type"); - tableJson->emplace("table_type", tableType); + tableJson->erase("table_type"_cs); + tableJson->emplace("table_type"_cs, tableType); } if (actProfId > 0) addToDependsOn(tableJson, actProfId); @@ -199,7 +200,7 @@ void BFRuntimeSchemaGenerator::addActionProfs(Util::JsonArray *tablesJson) const bool BFRuntimeSchemaGenerator::addMatchTypePriority(std::optional &matchType) const { if (*matchType == "Ternary" || *matchType == "Range" || *matchType == "Optional") { - *matchType = "Ternary"; + *matchType = "Ternary"_cs; return true; } return false; @@ -224,22 +225,22 @@ const Util::JsonObject *BFRuntimeSchemaGenerator::genSchema() const { auto fileName = progName.findlast('/'); // Handle the case when input file is in the current working directory. // fileName would be null in that case, hence progName should remain unchanged. - if (fileName) progName = fileName; - auto fileext = progName.find("."); - progName = progName.replace(fileext, ""); + if (fileName) progName = cstring(fileName); + auto fileext = cstring(progName.find(".")); + progName = cstring(progName.replace(fileext, cstring::empty)); progName = progName.trim("/\t\n\r"); - json->emplace("program_name", progName); - json->emplace("build_date", cstring(options.getBuildDate())); - json->emplace("compile_command", cstring(options.getCompileCommand())); - json->emplace("compiler_version", cstring(options.compilerVersion)); - json->emplace("schema_version", tdiSchemaVersion); - json->emplace("target", cstring("DPDK")); + json->emplace("program_name"_cs, progName); + json->emplace("build_date"_cs, cstring(options.getBuildDate())); + json->emplace("compile_command"_cs, cstring(options.getCompileCommand())); + json->emplace("compiler_version"_cs, cstring(options.compilerVersion)); + json->emplace("schema_version"_cs, tdiSchemaVersion); + json->emplace("target"_cs, "DPDK"); } else { - json->emplace("schema_version", bfrtSchemaVersion); + json->emplace("schema_version"_cs, bfrtSchemaVersion); } auto *tablesJson = new Util::JsonArray(); - json->emplace("tables", tablesJson); + json->emplace("tables"_cs, tablesJson); addMatchTables(tablesJson); addActionProfs(tablesJson); @@ -248,7 +249,7 @@ const Util::JsonObject *BFRuntimeSchemaGenerator::genSchema() const { addRegisters(tablesJson); auto *learnFiltersJson = new Util::JsonArray(); - json->emplace("learn_filters", learnFiltersJson); + json->emplace("learn_filters"_cs, learnFiltersJson); addLearnFilters(learnFiltersJson); addDPDKExterns(tablesJson, learnFiltersJson); diff --git a/backends/dpdk/dpdk.def b/backends/dpdk/dpdk.def index 02b3a464b7..3e59bb6ff8 100644 --- a/backends/dpdk/dpdk.def +++ b/backends/dpdk/dpdk.def @@ -160,21 +160,21 @@ abstract DpdkJmpStatement : DpdkAsmStatement { class DpdkJmpLabelStatement : DpdkJmpStatement { #noconstructor DpdkJmpLabelStatement(cstring label) : - DpdkJmpStatement("jmp", label) { } + DpdkJmpStatement("jmp"_cs, label) { } } class DpdkJmpHitStatement : DpdkJmpStatement { #nodbprint #noconstructor DpdkJmpHitStatement(cstring label) : - DpdkJmpStatement("jmph", label) { } + DpdkJmpStatement("jmph"_cs, label) { } } class DpdkJmpMissStatement : DpdkJmpStatement { #nodbprint #noconstructor DpdkJmpMissStatement(cstring label) : - DpdkJmpStatement("jmpnh", label) { } + DpdkJmpStatement("jmpnh"_cs, label) { } } abstract DpdkJmpActionStatement : DpdkJmpStatement { @@ -190,14 +190,14 @@ class DpdkJmpIfActionRunStatement : DpdkJmpActionStatement { #nodbprint #noconstructor DpdkJmpIfActionRunStatement(cstring label, cstring act) : - DpdkJmpActionStatement("jmpa", label, act) { } + DpdkJmpActionStatement("jmpa"_cs, label, act) { } } class DpdkJmpIfActionNotRunStatement : DpdkJmpActionStatement { #nodbprint #noconstructor DpdkJmpIfActionNotRunStatement(cstring label, cstring act) : - DpdkJmpActionStatement("jmpna", label, act) { } + DpdkJmpActionStatement("jmpna"_cs, label, act) { } } abstract DpdkJmpHeaderStatement : DpdkJmpStatement { @@ -211,14 +211,14 @@ abstract DpdkJmpHeaderStatement : DpdkJmpStatement { class DpdkJmpIfInvalidStatement : DpdkJmpHeaderStatement { #noconstructor DpdkJmpIfInvalidStatement(cstring label, Expression hdr) : - DpdkJmpHeaderStatement("jmpnv", label, hdr) { } + DpdkJmpHeaderStatement("jmpnv"_cs, label, hdr) { } } class DpdkJmpIfValidStatement : DpdkJmpHeaderStatement { #nodbprint #noconstructor DpdkJmpIfValidStatement(cstring label, Expression hdr) : - DpdkJmpHeaderStatement("jmpv", label, hdr) { } + DpdkJmpHeaderStatement("jmpv"_cs, label, hdr) { } } abstract DpdkJmpCondStatement : DpdkJmpStatement { @@ -232,42 +232,42 @@ abstract DpdkJmpCondStatement : DpdkJmpStatement { class DpdkJmpEqualStatement: DpdkJmpCondStatement, IDPDKNode { DpdkJmpEqualStatement(cstring label, Expression src1, Expression src2) : - DpdkJmpCondStatement("jmpeq", label, src1, src2) { } + DpdkJmpCondStatement("jmpeq"_cs, label, src1, src2) { } #noconstructor } class DpdkJmpNotEqualStatement: DpdkJmpCondStatement, IDPDKNode { #noconstructor DpdkJmpNotEqualStatement(cstring label, Expression src1, Expression src2) : - DpdkJmpCondStatement("jmpneq", label, src1, src2) { } + DpdkJmpCondStatement("jmpneq"_cs, label, src1, src2) { } } class DpdkJmpGreaterEqualStatement: DpdkJmpCondStatement, IDPDKNode { #nodbprint #noconstructor DpdkJmpGreaterEqualStatement(cstring label, Expression src1, Expression src2) : - DpdkJmpCondStatement("jmpge", label, src1, src2) { } + DpdkJmpCondStatement("jmpge"_cs, label, src1, src2) { } } class DpdkJmpGreaterStatement: DpdkJmpCondStatement, IDPDKNode { #nodbprint #noconstructor DpdkJmpGreaterStatement(cstring label, Expression src1, Expression src2) : - DpdkJmpCondStatement("jmpgt", label, src1, src2) { } + DpdkJmpCondStatement("jmpgt"_cs, label, src1, src2) { } } class DpdkJmpLessOrEqualStatement: DpdkJmpCondStatement, IDPDKNode { #nodbprint #noconstructor DpdkJmpLessOrEqualStatement(cstring label, Expression src1, Expression src2) : - DpdkJmpCondStatement("jmple", label, src1, src2) { } + DpdkJmpCondStatement("jmple"_cs, label, src1, src2) { } } class DpdkJmpLessStatement: DpdkJmpCondStatement, IDPDKNode { #nodbprint #noconstructor DpdkJmpLessStatement(cstring label, Expression src1, Expression src2) : - DpdkJmpCondStatement("jmplt", label, src1, src2) { } + DpdkJmpCondStatement("jmplt"_cs, label, src1, src2) { } } class DpdkRxStatement : DpdkAsmStatement, IDPDKNode { @@ -300,7 +300,7 @@ abstract DpdkUnaryStatement : DpdkAssignmentStatement { class DpdkMovStatement : DpdkUnaryStatement { DpdkMovStatement(Expression dst, Expression src) : - DpdkUnaryStatement("mov", dst, src) { } + DpdkUnaryStatement("mov"_cs, dst, src) { } #noconstructor } @@ -317,49 +317,49 @@ class DpdkAddStatement : DpdkBinaryStatement { #nodbprint #noconstructor DpdkAddStatement(Expression dst, Expression src1, Expression src2) : - DpdkBinaryStatement("add", dst, src1, src2) { } + DpdkBinaryStatement("add"_cs, dst, src1, src2) { } } class DpdkAndStatement : DpdkBinaryStatement, IDPDKNode { #nodbprint #noconstructor DpdkAndStatement(Expression dst, Expression src1, Expression src2) : - DpdkBinaryStatement("and", dst, src1, src2) { } + DpdkBinaryStatement("and"_cs, dst, src1, src2) { } } class DpdkShlStatement : DpdkBinaryStatement, IDPDKNode { #nodbprint #noconstructor DpdkShlStatement(Expression dst, Expression src1, Expression src2) : - DpdkBinaryStatement("shl", dst, src1, src2) { } + DpdkBinaryStatement("shl"_cs, dst, src1, src2) { } } class DpdkShrStatement : DpdkBinaryStatement, IDPDKNode { #nodbprint #noconstructor DpdkShrStatement(Expression dst, Expression src1, Expression src2) : - DpdkBinaryStatement("shr", dst, src1, src2) { } + DpdkBinaryStatement("shr"_cs, dst, src1, src2) { } } class DpdkSubStatement : DpdkBinaryStatement, IDPDKNode { #nodbprint #noconstructor DpdkSubStatement(Expression dst, Expression src1, Expression src2) : - DpdkBinaryStatement("sub", dst, src1, src2) { } + DpdkBinaryStatement("sub"_cs, dst, src1, src2) { } } class DpdkOrStatement : DpdkBinaryStatement, IDPDKNode { #nodbprint #noconstructor DpdkOrStatement(Expression dst, Expression src1, Expression src2) : - DpdkBinaryStatement("or", dst, src1, src2) { } + DpdkBinaryStatement("or"_cs, dst, src1, src2) { } } class DpdkXorStatement : DpdkBinaryStatement, IDPDKNode { #nodbprint #noconstructor DpdkXorStatement(Expression dst, Expression src1, Expression src2) : - DpdkBinaryStatement("xor", dst, src1, src2) { } + DpdkBinaryStatement("xor"_cs, dst, src1, src2) { } } class DpdkRecircidStatement : DpdkAsmStatement, IDPDKNode { @@ -499,7 +499,7 @@ class DpdkRegisterReadStatement: DpdkAssignmentStatement { #nodbprint #noconstructor DpdkRegisterReadStatement(Expression dst, cstring reg, Expression index) : - DpdkAssignmentStatement("read", dst), reg(reg), index(index) { } + DpdkAssignmentStatement("read"_cs, dst), reg(reg), index(index) { } } class DpdkRegisterWriteStatement: DpdkAsmStatement, IDPDKNode { diff --git a/backends/dpdk/dpdkArch.cpp b/backends/dpdk/dpdkArch.cpp index 2fa91d69d1..0f774047ee 100644 --- a/backends/dpdk/dpdkArch.cpp +++ b/backends/dpdk/dpdkArch.cpp @@ -29,6 +29,7 @@ limitations under the License. #include "frontends/p4/externInstance.h" #include "frontends/p4/tableApply.h" #include "frontends/p4/typeMap.h" +#include "lib/cstring.h" namespace DPDK { @@ -36,7 +37,7 @@ cstring TypeStruct2Name(const cstring s) { if (isStandardMetadata(s)) { return s.substr(0, s.size() - 2); } else { - return "local_metadata"; + return "local_metadata"_cs; } } @@ -498,7 +499,7 @@ const IR::Node *AlignHdrMetaField::preorder(IR::Type_StructLike *st) { field_name_list.emplace(field->name, obj); } } - cstring modifiedName = ""; + cstring modifiedName = cstring::empty; auto size = field_name_list.size(); unsigned i = 0; // Check if the sum of width of non-aligned field is divisble by 8. @@ -552,7 +553,7 @@ const IR::Node *AlignHdrMetaField::preorder(IR::Type_StructLike *st) { fields->push_back( new IR::StructField(IR::ID(modifiedName), IR::Type_Bits::get(size_sum_so_far))); size_sum_so_far = 0; - modifiedName = ""; + modifiedName = cstring::empty; field_name_list.clear(); } } @@ -592,7 +593,7 @@ const IR::Node *AlignHdrMetaField::preorder(IR::Type_StructLike *st) { if (hdrs.ipv4.flags_fragOffset[15:3] == 4) .... */ const IR::Node *AlignHdrMetaField::preorder(IR::Member *m) { - cstring hdrStrName = ""; + cstring hdrStrName = cstring::empty; // Get the member's header structure name. if ((m != nullptr) && (m->expr != nullptr) && (m->expr->type != nullptr) && (m->expr->type->is())) { @@ -1225,7 +1226,7 @@ const IR::Node *CollectLocalVariables::postorder(IR::P4Parser *p) { /// This function stores the information about parameters of default action /// for each table. void DefActionValue::postorder(const IR::P4Table *t) { - auto default_action = t->properties->getProperty("default_action"); + auto default_action = t->properties->getProperty("default_action"_cs); if (default_action != nullptr && default_action->value->is()) { auto expr = default_action->value->to()->expression; auto mi = @@ -1456,7 +1457,7 @@ const IR::Node *DismantleMuxExpressions::postorder(IR::AssignmentStatement *stat bool CopyMatchKeysToSingleStruct::isLearnerTable(const IR::P4Table *t) { bool use_add_on_miss = false; - auto add_on_miss = t->properties->getProperty("add_on_miss"); + auto add_on_miss = t->properties->getProperty("add_on_miss"_cs); if (add_on_miss == nullptr) return false; if (add_on_miss->value->is()) { auto expr = add_on_miss->value->to()->expression; @@ -1580,7 +1581,7 @@ const IR::Node *CopyMatchKeysToSingleStruct::preorder(IR::Key *keys) { return keys; } - cstring firstKeyStr = ""; + cstring firstKeyStr = cstring::empty; bool firstKeyHdr = false; if (auto firstKeyField = keys->keyElements.at(0)->expression->to()) { @@ -1593,7 +1594,7 @@ const IR::Node *CopyMatchKeysToSingleStruct::preorder(IR::Key *keys) { // Key fields should be part of same header/metadata struct. for (auto key : keys->keyElements) { - cstring keyTypeStr = ""; + cstring keyTypeStr = cstring::empty; if (auto keyField = key->expression->to()) { keyTypeStr = keyField->expr->toString(); } else if (auto m = key->expression->to()) { @@ -1696,19 +1697,19 @@ const IR::Node *CopyMatchKeysToSingleStruct::postorder(IR::KeyElement *element) isHeader = true; keyName = keyName.replace('.', '_'); keyName = - keyName.replace("h_", control->name.toString() + "_" + table->name.toString() + "_"); + keyName.replace("h_"_cs, control->name.toString() + "_" + table->name.toString() + "_"); } else if (metaCopyNeeded) { if (keyName.startsWith("m.")) { keyName = keyName.replace('.', '_'); keyName = keyName.replace( - "m_", control->name.toString() + "_" + table->name.toString() + "_"); + "m_"_cs, control->name.toString() + "_" + table->name.toString() + "_"); } else { keyName = control->name.toString() + "_" + table->name.toString() + "_" + keyName; } } if (isHeader || metaCopyNeeded) { - IR::ID keyNameId(refMap->newName(keyName)); + IR::ID keyNameId(refMap->newName(keyName.string_view())); auto decl = new IR::Declaration_Variable(keyNameId, element->expression->type, nullptr); // Store the compiler generated table keys in Program structure. These will be // inserted to Metadata by CollectLocalVariables pass. @@ -1782,7 +1783,7 @@ std::optional getExternInstanceFromProperty( /// for subsequent table lookup. std::tuple SplitP4TableCommon::create_match_table( const IR::P4Table *tbl) { - cstring grpActionName = "", memActionName; + cstring grpActionName = cstring::empty, memActionName; if (implementation == TableImplementation::ACTION_SELECTOR) { grpActionName = refMap->newName(tbl->name.originalName + "_set_group_id"); memActionName = refMap->newName(tbl->name.originalName + "_set_member_id"); @@ -1814,7 +1815,7 @@ std::tuple SplitP4TableCommon::create_mat } } - auto constDefAction = tbl->properties->getProperty("default_action"); + auto constDefAction = tbl->properties->getProperty("default_action"_cs); bool isConstDefAction = constDefAction ? constDefAction->isConstant : false; IR::IndexedVector properties; @@ -1858,7 +1859,7 @@ const IR::P4Table *SplitP4TableCommon::create_member_table(const IR::P4Table *tb hidden->add(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); auto nameAnnon = tbl->getAnnotation(IR::Annotation::nameAnnotation); cstring nameA = nameAnnon->getSingleString(); - cstring memName = nameA.replace(nameA.findlast('.'), "." + memberTableName); + cstring memName = nameA.replace(cstring(nameA.findlast('.')), "."_cs + memberTableName); hidden->addAnnotation(IR::Annotation::nameAnnotation, new IR::StringLiteral(memName), false); IR::IndexedVector memberActionList; @@ -1893,7 +1894,7 @@ const IR::P4Table *SplitP4TableCommon::create_group_table(const IR::P4Table *tbl hidden->add(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); auto nameAnnon = tbl->getAnnotation(IR::Annotation::nameAnnotation); cstring nameA = nameAnnon->getSingleString(); - cstring selName = nameA.replace(nameA.findlast('.'), "." + selectorTableName); + cstring selName = nameA.replace(cstring(nameA.findlast('.')), "."_cs + selectorTableName); hidden->addAnnotation(IR::Annotation::nameAnnotation, new IR::StringLiteral(selName), false); IR::IndexedVector selector_properties; selector_properties.push_back(new IR::Property("selector", new IR::Key(selector_keys), false)); @@ -1917,16 +1918,16 @@ const IR::P4Table *SplitP4TableCommon::create_group_table(const IR::P4Table *tbl const IR::Node *SplitActionSelectorTable::postorder(IR::P4Table *tbl) { bool isConstructedInPlace = false; bool isAsInstanceShared = false; - cstring externName = ""; - cstring prefix = "psa_"; + cstring externName = cstring::empty; + cstring prefix = "psa_"_cs; if (structure->isPNA()) { - prefix = "pna_"; + prefix = "pna_"_cs; } - auto property = tbl->properties->getProperty(prefix + "implementation"); - auto counterProperty = tbl->properties->getProperty(prefix + "direct_counter"); - auto meterProperty = tbl->properties->getProperty(prefix + "direct_meter"); + auto property = tbl->properties->getProperty(prefix + "implementation"_cs); + auto counterProperty = tbl->properties->getProperty(prefix + "direct_counter"_cs); + auto meterProperty = tbl->properties->getProperty(prefix + "direct_meter"_cs); if (property != nullptr && (counterProperty != nullptr || meterProperty != nullptr)) { ::error(ErrorType::ERR_UNEXPECTED, @@ -1973,7 +1974,7 @@ const IR::Node *SplitActionSelectorTable::postorder(IR::P4Table *tbl) { // Remove the control block name prefix from instance name cstring instance_name = *instance->name; - instance_name = instance_name.findlast('.'); + instance_name = cstring(instance_name.findlast('.')); instance_name = instance_name.trim(".\t\n\r"); cstring member_id = instance_name + "_member_id"; @@ -1999,8 +2000,8 @@ const IR::Node *SplitActionSelectorTable::postorder(IR::P4Table *tbl) { cstring grpActionName, memActionName; const IR::P4Table *match_table; std::tie(match_table, grpActionName, memActionName) = create_match_table(tbl); - auto grpAction = create_action(grpActionName, group_id, "group_id"); - auto memAction = create_action(memActionName, member_id, "member_id"); + auto grpAction = create_action(grpActionName, group_id, "group_id"_cs); + auto memAction = create_action(memActionName, member_id, "member_id"_cs); decls->push_back(grpAction); decls->push_back(memAction); decls->push_back(match_table); @@ -2048,10 +2049,10 @@ const IR::Node *SplitActionSelectorTable::postorder(IR::P4Table *tbl) { const IR::Node *SplitActionProfileTable::postorder(IR::P4Table *tbl) { bool isConstructedInPlace = false; bool isApInstanceShared = false; - cstring externName = ""; - cstring implementation = "psa_implementation"; + cstring externName = cstring::empty; + cstring implementation = "psa_implementation"_cs; - if (structure->isPNA()) implementation = "pna_implementation"; + if (structure->isPNA()) implementation = "pna_implementation"_cs; auto instance = Helpers::getExternInstanceFromProperty(tbl, implementation, refMap, typeMap, &isConstructedInPlace, externName); @@ -2071,8 +2072,9 @@ const IR::Node *SplitActionProfileTable::postorder(IR::P4Table *tbl) { } // Remove the control block name prefix from instance name + // FIXME: simplify cstring instance_name = *instance->name; - instance_name = instance_name.findlast('.'); + instance_name = cstring(instance_name.findlast('.')); instance_name = instance_name.trim(".\t\n\r"); auto decls = new IR::IndexedVector(); @@ -2094,7 +2096,7 @@ const IR::Node *SplitActionProfileTable::postorder(IR::P4Table *tbl) { cstring actionName, ignoreGroup; const IR::P4Table *match_table; std::tie(match_table, ignoreGroup, actionName) = create_match_table(tbl); - auto action = create_action(actionName, member_id, "member_id"); + auto action = create_action(actionName, member_id, "member_id"_cs); decls->push_back(action); decls->push_back(match_table); cstring member_table_name = instance_name; @@ -2486,7 +2488,7 @@ bool CollectDirectCounterMeter::preorder(const IR::AssignmentStatement *assn) { bool CollectDirectCounterMeter::ifMethodFound(const IR::P4Action *a, cstring methodName, cstring instance) { - oneInstance = ""; + oneInstance = cstring::empty; instancename = instance; method = methodName; methodCallFound = false; @@ -2498,23 +2500,23 @@ bool CollectDirectCounterMeter::ifMethodFound(const IR::P4Action *a, cstring met /// method calls for only one Direct counter/meter instance. The error for the same is emitted /// in the ifMethodFound function itself and return value is not required to be checked here. bool CollectDirectCounterMeter::preorder(const IR::P4Action *a) { - ifMethodFound(a, "count"); - ifMethodFound(a, "dpdk_execute"); + ifMethodFound(a, "count"_cs); + ifMethodFound(a, "dpdk_execute"_cs); return false; } bool CollectDirectCounterMeter::preorder(const IR::P4Table *tbl) { bool isConstructedInPlace = false; - cstring implementation = "psa_implementation"; - cstring counterExternName = ""; - cstring meterExternName = ""; - cstring direct_counter = "psa_direct_counter"; - cstring direct_meter = "psa_direct_meter"; + cstring implementation = "psa_implementation"_cs; + cstring counterExternName = cstring::empty; + cstring meterExternName = cstring::empty; + cstring direct_counter = "psa_direct_counter"_cs; + cstring direct_meter = "psa_direct_meter"_cs; if (structure->isPNA()) { - implementation = "pna_implementation"; - direct_counter = "pna_direct_counter"; - direct_meter = "pna_direct_meter"; + implementation = "pna_implementation"_cs; + direct_counter = "pna_direct_counter"_cs; + direct_meter = "pna_direct_meter"_cs; } auto counterInstance = Helpers::getExternInstanceFromProperty( @@ -2545,7 +2547,7 @@ bool CollectDirectCounterMeter::preorder(const IR::P4Table *tbl) { BUG_CHECK(path, "Default action path %s cannot be found", default_action); if (auto defaultActionDecl = refMap->getDeclaration(path->path)->to()) { if (defaultActionDecl->name.originalName != "NoAction") { - if (!ifMethodFound(defaultActionDecl, "count", counterExternName)) { + if (!ifMethodFound(defaultActionDecl, "count"_cs, counterExternName)) { if (counterInstance) { ::error(ErrorType::ERR_EXPECTED, "Expected default action %1% to have " @@ -2554,7 +2556,7 @@ bool CollectDirectCounterMeter::preorder(const IR::P4Table *tbl) { return false; } } - if (!ifMethodFound(defaultActionDecl, "dpdk_execute", meterExternName)) { + if (!ifMethodFound(defaultActionDecl, "dpdk_execute"_cs, meterExternName)) { if (meterInstance) { ::error(ErrorType::ERR_EXPECTED, "Expected default action %1% to have " @@ -2640,8 +2642,8 @@ void ValidateDirectCounterMeter::postorder(const IR::MethodCallStatement *mcs) { void CollectAddOnMissTable::postorder(const IR::P4Table *t) { bool use_add_on_miss = false; - auto add_on_miss = t->properties->getProperty("add_on_miss"); - cstring default_actname = "NoAction"; + auto add_on_miss = t->properties->getProperty("add_on_miss"_cs); + cstring default_actname = "NoAction"_cs; if (add_on_miss == nullptr) return; if (add_on_miss->value->is()) { auto expr = add_on_miss->value->to()->expression; @@ -2656,7 +2658,7 @@ void CollectAddOnMissTable::postorder(const IR::P4Table *t) { } // sanity checks - auto default_action = t->properties->getProperty("default_action"); + auto default_action = t->properties->getProperty("default_action"_cs); if (use_add_on_miss && default_action == nullptr) { ::error(ErrorType::ERR_UNEXPECTED, "%1%: add_on_miss property is defined, " @@ -2686,8 +2688,9 @@ void CollectAddOnMissTable::postorder(const IR::P4Table *t) { // Map the compiler generated internal name of action (emitted in .spec file) with // user visible name in P4 program. // To get the user visible name, strip any prefixes from externalName. + // FIXME: Simplify cstring userVisibleName = action_decl->externalName(); - userVisibleName = userVisibleName.findlast('.'); + userVisibleName = cstring(userVisibleName.findlast('.')); userVisibleName = userVisibleName.trim(".\t\n\r"); structure->learner_action_map.emplace(std::make_pair(userVisibleName, default_actname), action_decl->name.name); @@ -2719,7 +2722,7 @@ void CollectAddOnMissTable::postorder(const IR::MethodCallStatement *mcs) { void ValidateAddOnMissExterns::postorder(const IR::MethodCallStatement *mcs) { bool isValidExternCall = false; - cstring propName = ""; + cstring propName = cstring::empty; auto mce = mcs->methodCall; auto mi = P4::MethodInstance::resolve(mce, refMap, typeMap); if (!mi->is()) { @@ -2737,9 +2740,9 @@ void ValidateAddOnMissExterns::postorder(const IR::MethodCallStatement *mcs) { bool use_idle_timeout_with_auto_delete = false; if (tbl) { auto idle_timeout_with_auto_delete = - tbl->properties->getProperty("idle_timeout_with_auto_delete"); + tbl->properties->getProperty("idle_timeout_with_auto_delete"_cs); if (idle_timeout_with_auto_delete != nullptr) { - propName = "idle_timeout_with_auto_delete"; + propName = "idle_timeout_with_auto_delete"_cs; if (idle_timeout_with_auto_delete->value->is()) { auto expr = idle_timeout_with_auto_delete->value->to()->expression; @@ -2763,9 +2766,9 @@ void ValidateAddOnMissExterns::postorder(const IR::MethodCallStatement *mcs) { auto args = mce->arguments; auto at = args->at(0)->expression; auto an = at->to()->value; - auto add_on_miss = tbl->properties->getProperty("add_on_miss"); + auto add_on_miss = tbl->properties->getProperty("add_on_miss"_cs); if (add_on_miss != nullptr) { - propName = "add_on_miss"; + propName = "add_on_miss"_cs; if (add_on_miss->value->is()) { auto expr = add_on_miss->value->to()->expression; if (!expr->is()) { @@ -3048,7 +3051,7 @@ const IR::Node *MoveNonHeaderFieldsToPseudoHeader::postorder(IR::MethodCallState fields.push_back( new IR::StructField(f->name, getEightBitAlignedType(type))); } - auto newName = refMap->newName(tmps0->name); + auto newName = refMap->newName(tmps0->name.name.string_view()); newTname = new IR::Type_Name(newName); auto newStructType = new IR::Type_Struct(tmps0->srcInfo, newName, tmps0->annotations, @@ -3100,7 +3103,7 @@ const IR::Node *MoveNonHeaderFieldsToPseudoHeader::postorder(IR::MethodCallState const IR::Node *AddFieldsToPseudoHeader::preorder(IR::Type_Header *h) { if (is_all_args_header) return h; - auto annon = h->getAnnotation("__pseudo_header__"); + auto annon = h->getAnnotation("__pseudo_header__"_cs); if (annon == nullptr) return h; IR::IndexedVector fields = h->fields; for (auto &p : MoveNonHeaderFieldsToPseudoHeader::pseudoFieldNameType) { @@ -3227,7 +3230,7 @@ IR::IndexedVector *InsertReqDeclForIPSec::addRegDeclInstance( const IR::Node *InsertReqDeclForIPSec::preorder(IR::P4Program *program) { if (!is_ipsec_used) return program; - cstring resName = ""; + cstring resName = cstring::empty; if (!reservedNames(refMap, registerInstanceNames, resName)) { ::error(ErrorType::ERR_RESERVED, "%1% name is reserved for DPDK IPSec port register", resName); diff --git a/backends/dpdk/dpdkArch.h b/backends/dpdk/dpdkArch.h index 856d023461..8d4905915a 100644 --- a/backends/dpdk/dpdkArch.h +++ b/backends/dpdk/dpdkArch.h @@ -31,6 +31,8 @@ limitations under the License. namespace DPDK { +using namespace P4::literals; + cstring TypeStruct2Name(const cstring *s); bool isSimpleExpression(const IR::Expression *e); bool isNonConstantSimpleExpression(const IR::Expression *e); @@ -1009,7 +1011,8 @@ class CollectDirectCounterMeter : public Inspector { cstring oneInstance; bool methodCallFound; int getTableSize(const IR::P4Table *tbl); - bool ifMethodFound(const IR::P4Action *a, cstring method, cstring instancename = ""); + bool ifMethodFound(const IR::P4Action *a, cstring method, + cstring instancename = cstring::empty); void checkMethodCallInAction(const P4::ExternMethod *); public: @@ -1019,9 +1022,9 @@ class CollectDirectCounterMeter : public Inspector { : refMap(refMap), typeMap(typeMap), structure(structure) { setName("CollectDirectCounterMeter"); visitDagOnce = false; - method = ""; - instancename = ""; - oneInstance = ""; + method = cstring::empty; + instancename = cstring::empty; + oneInstance = cstring::empty; methodCallFound = false; } @@ -1502,11 +1505,11 @@ class InsertReqDeclForIPSec : public Transform { DpdkProgramStructure *structure; bool &is_ipsec_used; int &sa_id_width; - cstring newHeaderName = "platform_hdr_t"; + cstring newHeaderName = "platform_hdr_t"_cs; IR::Type_Header *ipsecHeader = nullptr; std::vector registerInstanceNames = { - "ipsec_port_out_inbound", "ipsec_port_out_outbound", "ipsec_port_in_inbound", - "ipsec_port_in_outbound"}; + "ipsec_port_out_inbound"_cs, "ipsec_port_out_outbound"_cs, "ipsec_port_in_inbound"_cs, + "ipsec_port_in_outbound"_cs}; public: InsertReqDeclForIPSec(P4::ReferenceMap *refMap, DpdkProgramStructure *structure, diff --git a/backends/dpdk/dpdkAsmOpt.cpp b/backends/dpdk/dpdkAsmOpt.cpp index 2b8412c6ca..4267c9521f 100644 --- a/backends/dpdk/dpdkAsmOpt.cpp +++ b/backends/dpdk/dpdkAsmOpt.cpp @@ -370,9 +370,11 @@ int EmitDpdkTableConfig::getTypeWidth(const IR::Type *type, P4::TypeMap *typeMap return typeMap->widthBits(type, type->getNode(), false); } -void EmitDpdkTableConfig::print(cstring str, cstring sep) { dpdkTableConfigFile << str << sep; } +void EmitDpdkTableConfig::print(std::string_view str, std::string_view sep) { + dpdkTableConfigFile << str << sep; +} -void EmitDpdkTableConfig::print(big_int str, cstring sep) { +void EmitDpdkTableConfig::print(big_int str, std::string_view sep) { try { dpdkTableConfigFile << "0x" << std::hex << str << sep; } catch (const std::runtime_error &re) { @@ -423,7 +425,7 @@ void EmitDpdkTableConfig::addAction(const IR::Expression *actionRef, P4::Referen actionName = newNameMap[actionDecl->name.name]; else actionName = actionDecl->name.name; - print(actionName, " "); + print(actionName.string_view(), " "); if (actionDecl->parameters->parameters.size() == 1) { std::vector paramNames; std::vector argVals; @@ -455,7 +457,7 @@ void EmitDpdkTableConfig::addAction(const IR::Expression *actionRef, P4::Referen } for (size_t i = 0; i < argVals.size(); i++) { - print(paramNames[i], " "); + print(paramNames[i].string_view(), " "); print(argVals[i], " "); } } diff --git a/backends/dpdk/dpdkAsmOpt.h b/backends/dpdk/dpdkAsmOpt.h index 2d9d3096a1..25c95e642d 100644 --- a/backends/dpdk/dpdkAsmOpt.h +++ b/backends/dpdk/dpdkAsmOpt.h @@ -36,6 +36,9 @@ limitations under the License. #define DPDK_TABLE_MAX_KEY_SIZE 64 * 8 namespace DPDK { + +using namespace P4::literals; + /// This pass removes label that no jmps jump to class RemoveRedundantLabel : public Transform { public: @@ -207,7 +210,7 @@ class ShortenTokenLength : public Transform { } const IR::Node *preorder(IR::DpdkStructType *s) override { - if (s->getAnnotations()->getSingle("__packet_data__")) { + if (s->getAnnotations()->getSingle("__packet_data__"_cs)) { s->name = shortenString(s->name); IR::IndexedVector changedFields; for (auto field : s->fields) { @@ -350,9 +353,9 @@ class CollectUseDefInfo : public Inspector { std::unordered_map dontEliminate; explicit CollectUseDefInfo(P4::TypeMap *typeMap) : typeMap(typeMap) { - dontEliminate["m.pna_main_output_metadata_output_port"] = true; - dontEliminate["m.psa_ingress_output_metadata_drop"] = true; - dontEliminate["m.psa_ingress_output_metadata_egress_port"] = true; + dontEliminate["m.pna_main_output_metadata_output_port"_cs] = true; + dontEliminate["m.psa_ingress_output_metadata_drop"_cs] = true; + dontEliminate["m.psa_ingress_output_metadata_egress_port"_cs] = true; } bool preorder(const IR::DpdkJmpCondStatement *b) override { @@ -624,8 +627,8 @@ class EmitDpdkTableConfig : public Inspector { P4::TypeMap *typeMap); bool tableNeedsPriority(const IR::DpdkTable *table, P4::ReferenceMap *refMap); bool isAllKeysDefaultExpression(const IR::ListExpression *keyset); - void print(cstring str, cstring sep = ""); - void print(big_int, cstring sep = ""); + void print(std::string_view str, std::string_view sep = ""); + void print(big_int, std::string_view sep = ""); public: EmitDpdkTableConfig(P4::ReferenceMap *refMap, P4::TypeMap *typeMap, diff --git a/backends/dpdk/dpdkCheckExternInvocation.h b/backends/dpdk/dpdkCheckExternInvocation.h index 6405556c16..5599470fef 100644 --- a/backends/dpdk/dpdkCheckExternInvocation.h +++ b/backends/dpdk/dpdkCheckExternInvocation.h @@ -17,9 +17,13 @@ limitations under the License. #ifndef BACKENDS_DPDK_DPDKCHECKEXTERNINVOCATION_H_ #define BACKENDS_DPDK_DPDKCHECKEXTERNINVOCATION_H_ +#include + +#include "dpdkProgramStructure.h" #include "frontends/p4/methodInstance.h" #include "ir/ir.h" #include "ir/visitor.h" +#include "lib/cstring.h" #include "midend/checkExternInvocationCommon.h" namespace P4 { @@ -29,6 +33,8 @@ class TypeMap; namespace DPDK { +using namespace P4::literals; + /// @brief Class for checking constraints for invocations of PNA architecture extern /// methods and functions. @@ -46,15 +52,14 @@ class CheckPNAExternInvocation : public P4::CheckExternInvocationCommon { void initPipeConstraints() override { bitvec validInMainControl; validInMainControl.setbit(MAIN_CONTROL); - setPipeConstraints("send_to_port", validInMainControl); - setPipeConstraints("mirror_packet", validInMainControl); + setPipeConstraints("send_to_port"_cs, validInMainControl); + setPipeConstraints("mirror_packet"_cs, validInMainControl); // Add new constraints here } cstring getBlockName(int bit) override { - static const char *lookup[] = {"main parser", "pre control", "main control", - "main deparser"}; - BUG_CHECK(sizeof(lookup) / sizeof(lookup[0]) == BLOCK_COUNT, "Bad lookup table"); + static const std::array lookup = { + "main parser"_cs, "pre control"_cs, "main control"_cs, "main deparser"_cs}; return lookup[bit % BLOCK_COUNT]; } @@ -95,19 +100,19 @@ class CheckPNAExternInvocation : public P4::CheckExternInvocationCommon { LOG4("externType: " << externType << ", externName: " << externName); if (pipeConstraints.count(externType)) { - if (auto block = getParser("MainParserT")) { + if (auto block = getParser("MainParserT"_cs)) { LOG4("MainParser: " << (void *)block << " " << dbp(block)); pos.setbit(MAIN_PARSER); checkPipeConstraints(externType, pos, expr, externName, block->name); - } else if (auto block = getControl("PreControlT")) { + } else if (auto block = getControl("PreControlT"_cs)) { LOG4("PreControl: " << (void *)block << " " << dbp(block)); pos.setbit(PRE_CONTROL); checkPipeConstraints(externType, pos, expr, externName, block->name); - } else if (auto block = getControl("MainControlT")) { + } else if (auto block = getControl("MainControlT"_cs)) { LOG4("MainControl: " << (void *)block << " " << dbp(block)); pos.setbit(MAIN_CONTROL); checkPipeConstraints(externType, pos, expr, externName, block->name); - } else if (auto block = getDeparser("MainDeparserT")) { + } else if (auto block = getDeparser("MainDeparserT"_cs)) { LOG4("MainDeparser: " << (void *)block << " " << dbp(block)); pos.setbit(MAIN_DEPARSER); checkPipeConstraints(externType, pos, expr, externName, block->name); @@ -128,7 +133,7 @@ class CheckPNAExternInvocation : public P4::CheckExternInvocationCommon { void checkExtern(const P4::ExternFunction *extFunction, const IR::MethodCallExpression *expr) override { LOG3("ExternFunction: " << extFunction << ", MethodCallExpression: " << expr); - checkBlock(expr, expr->method->toString(), ""); + checkBlock(expr, expr->method->toString(), cstring::empty); } public: diff --git a/backends/dpdk/dpdkContext.cpp b/backends/dpdk/dpdkContext.cpp index 6cd17ecf24..c418099a61 100644 --- a/backends/dpdk/dpdkContext.cpp +++ b/backends/dpdk/dpdkContext.cpp @@ -24,7 +24,7 @@ namespace DPDK { cstring DpdkContextGenerator::removePipePrefix(cstring tableName) { if (!options.bfRtSchema.isNullOrEmpty() || !options.tdiFile.isNullOrEmpty()) { - cstring tablename = tableName.find('.'); + cstring tablename = cstring(tableName.find('.')); tablename = tablename.trim(".\t\n\r"); return tablename; } @@ -37,11 +37,11 @@ void DpdkContextGenerator::CollectTablesAndSetAttributes() { IR::IndexedVector selector_tables; IR::IndexedVector action_data_tables; for (auto kv : structure->pipelines) { - cstring direction = ""; + cstring direction = cstring::empty; if (kv.first == "Ingress") - direction = "ingress"; + direction = "ingress"_cs; else if (kv.first == "Egress") - direction = "egress"; + direction = "egress"_cs; auto control = kv.second->to(); for (auto d : control->controlLocals) { if (auto tbl = d->to()) { @@ -54,10 +54,10 @@ void DpdkContextGenerator::CollectTablesAndSetAttributes() { tblAttr.size = dpdk_default_table_size; if (size) tblAttr.size = size->asUnsigned(); auto hidden = tbl->annotations->getSingle(IR::Annotation::hiddenAnnotation); - auto selector = tbl->properties->getProperty("selector"); + auto selector = tbl->properties->getProperty("selector"_cs); tblAttr.is_add_on_miss = false; tblAttr.idle_timeout_with_auto_delete = false; - auto add_on_miss = tbl->properties->getProperty("add_on_miss"); + auto add_on_miss = tbl->properties->getProperty("add_on_miss"_cs); if (add_on_miss != nullptr) { if (add_on_miss->value->is()) { auto expr = add_on_miss->value->to()->expression; @@ -72,7 +72,7 @@ void DpdkContextGenerator::CollectTablesAndSetAttributes() { } } auto idle_timeout_with_auto_delete = - tbl->properties->getProperty("idle_timeout_with_auto_delete"); + tbl->properties->getProperty("idle_timeout_with_auto_delete"_cs); if (idle_timeout_with_auto_delete != nullptr) { if (idle_timeout_with_auto_delete->value->is()) { auto expr = idle_timeout_with_auto_delete->value->to() @@ -90,11 +90,11 @@ void DpdkContextGenerator::CollectTablesAndSetAttributes() { } } if (hidden) { - tblAttr.tableType = selector ? "selection" : "action"; + tblAttr.tableType = selector ? "selection"_cs : "action"_cs; tblAttr.isHidden = true; } else { tblAttr.isHidden = false; - tblAttr.tableType = "match"; + tblAttr.tableType = "match"_cs; tblAttr.tableKeys = ::get(structure->key_map, kv.second->name.originalName + "_" + tbl->name.originalName); } @@ -110,7 +110,7 @@ void DpdkContextGenerator::CollectTablesAndSetAttributes() { } for (auto ed : structure->externDecls) { - cstring externTypeName = ""; + cstring externTypeName = cstring::empty; if (auto type = ed->type->to()) { externTypeName = type->path->name.name; } else if (auto type = ed->type->to()) { @@ -137,13 +137,13 @@ void DpdkContextGenerator::CollectTablesAndSetAttributes() { auto value = counter_type->to()->asUnsigned(); switch (value) { case 0: - externAttr.counterType = "packets"; + externAttr.counterType = "packets"_cs; break; case 1: - externAttr.counterType = "bytes"; + externAttr.counterType = "bytes"_cs; break; case 2: - externAttr.counterType = "packets_and_bytes"; + externAttr.counterType = "packets_and_bytes"_cs; break; } } @@ -167,23 +167,23 @@ void DpdkContextGenerator::addKeyField(Util::JsonArray *keyJson, const cstring n const cstring nameAnnotation, const IR::KeyElement *key, int position) { auto *keyField = new Util::JsonObject(); - cstring fieldName = name.findlast('.'); - auto instanceName = name.replace(fieldName, ""); + cstring fieldName = cstring(name.findlast('.')); + auto instanceName = name.replace(fieldName, cstring::empty); fieldName = fieldName.trim(".\t\n\r"); std::string keyName(nameAnnotation); // Replace header stack indices hdr[] with hdr$. std::regex hdrStackRegex(R"(\[([0-9]+)\])"); keyName = std::regex_replace(keyName, hdrStackRegex, "$$$1"); - keyField->emplace("name", keyName); - keyField->emplace("instance_name", instanceName); - keyField->emplace("field_name", fieldName); + keyField->emplace("name"_cs, keyName); + keyField->emplace("instance_name"_cs, instanceName); + keyField->emplace("field_name"_cs, fieldName); auto match_kind = toStr(key->matchType); - if (match_kind == "optional" || match_kind == "range") match_kind = "ternary"; - keyField->emplace("match_type", match_kind); - keyField->emplace("start_bit", 0); - keyField->emplace("bit_width", key->expression->type->width_bits()); - keyField->emplace("bit_width_full", key->expression->type->width_bits()); - keyField->emplace("position", position); + if (match_kind == "optional" || match_kind == "range") match_kind = "ternary"_cs; + keyField->emplace("match_type"_cs, match_kind); + keyField->emplace("start_bit"_cs, 0); + keyField->emplace("bit_width"_cs, key->expression->type->width_bits()); + keyField->emplace("bit_width_full"_cs, key->expression->type->width_bits()); + keyField->emplace("position"_cs, position); keyJson->append(keyField); } @@ -192,15 +192,15 @@ Util::JsonObject *DpdkContextGenerator::initTableCommonJson(const cstring name, const struct TableAttributes &attr) { auto *tableJson = new Util::JsonObject(); cstring tableName = name; - tableJson->emplace("name", attr.externalName); - tableJson->emplace("target_name", tableName); - tableJson->emplace("direction", attr.direction); - tableJson->emplace("handle", attr.tableHandle); - tableJson->emplace("table_type", attr.tableType); - tableJson->emplace("size", attr.size); - tableJson->emplace("p4_hidden", attr.isHidden); - tableJson->emplace("add_on_miss", attr.is_add_on_miss); - tableJson->emplace("idle_timeout_with_auto_delete", attr.idle_timeout_with_auto_delete); + tableJson->emplace("name"_cs, attr.externalName); + tableJson->emplace("target_name"_cs, tableName); + tableJson->emplace("direction"_cs, attr.direction); + tableJson->emplace("handle"_cs, attr.tableHandle); + tableJson->emplace("table_type"_cs, attr.tableType); + tableJson->emplace("size"_cs, attr.size); + tableJson->emplace("p4_hidden"_cs, attr.isHidden); + tableJson->emplace("add_on_miss"_cs, attr.is_add_on_miss); + tableJson->emplace("idle_timeout_with_auto_delete"_cs, attr.idle_timeout_with_auto_delete); return tableJson; } @@ -301,7 +301,7 @@ void DpdkContextGenerator::setActionAttributes(const IR::P4Table *tbl) { // This functions updates the table attribute map entry with default action handle // for the specified table. void DpdkContextGenerator::setDefaultActionHandle(const IR::P4Table *table) { - cstring default_action_name = ""; + cstring default_action_name = cstring::empty; if (table->getDefaultAction()) default_action_name = toStr(table->getDefaultAction()); auto tableAttr = ::get(tableAttrmap, table->name.originalName); @@ -320,9 +320,9 @@ void DpdkContextGenerator::setDefaultActionHandle(const IR::P4Table *table) { void DpdkContextGenerator::addImmediateField(Util::JsonArray *paramJson, const cstring name, int dest_start, int dest_width) { auto *oneParam = new Util::JsonObject(); - oneParam->emplace("param_name", name); - oneParam->emplace("dest_start", dest_start); - oneParam->emplace("dest_width", dest_width); + oneParam->emplace("param_name"_cs, name); + oneParam->emplace("dest_start"_cs, dest_start); + oneParam->emplace("dest_width"_cs, dest_width); paramJson->append(oneParam); } @@ -341,8 +341,8 @@ Util::JsonObject *DpdkContextGenerator::addMatchAttributes(const IR::P4Table *ta if (name != "NoAction") { name = ctrlName + "." + name; } - oneAction->emplace("action_name", name); - oneAction->emplace("action_handle", attr.actionHandle); + oneAction->emplace("action_name"_cs, name); + oneAction->emplace("action_handle"_cs, attr.actionHandle); auto *immFldArray = new Util::JsonArray(); if (attr.params) { int index = 0; @@ -358,12 +358,12 @@ Util::JsonObject *DpdkContextGenerator::addMatchAttributes(const IR::P4Table *ta index += param_width; } } - oneAction->emplace("immediate_fields", immFldArray); + oneAction->emplace("immediate_fields"_cs, immFldArray); actFmtArray->append(oneAction); } - oneStageTbl->emplace("action_format", actFmtArray); + oneStageTbl->emplace("action_format"_cs, actFmtArray); stageTblArray->append(oneStageTbl); - match_attributes->emplace("stage_tables", stageTblArray); + match_attributes->emplace("stage_tables"_cs, stageTblArray); return match_attributes; } @@ -371,11 +371,11 @@ Util::JsonObject *DpdkContextGenerator::addMatchAttributes(const IR::P4Table *ta void DpdkContextGenerator::addActionParam(Util::JsonArray *paramJson, const cstring name, int bitWidth, int position, int byte_array_index) { auto *oneParam = new Util::JsonObject(); - oneParam->emplace("name", name); - oneParam->emplace("start_bit", 0); - oneParam->emplace("bit_width", bitWidth); - oneParam->emplace("position", position); - oneParam->emplace("byte_array_index", byte_array_index); + oneParam->emplace("name"_cs, name); + oneParam->emplace("start_bit"_cs, 0); + oneParam->emplace("bit_width"_cs, bitWidth); + oneParam->emplace("position"_cs, position); + oneParam->emplace("byte_array_index"_cs, byte_array_index); paramJson->append(oneParam); } @@ -395,15 +395,14 @@ Util::JsonArray *DpdkContextGenerator::addActions(const IR::P4Table *table, } else { actName = name; } - act->emplace("name", attr.externalName); - act->emplace("target_name", actName); - act->emplace("handle", attr.actionHandle); + act->emplace("name"_cs, attr.externalName); + act->emplace("target_name"_cs, actName); + act->emplace("handle"_cs, attr.actionHandle); if (isMatch) { - act->emplace("constant_default_action", attr.constant_default_action); - act->emplace("is_compiler_added_action", attr.is_compiler_added_action); - act->emplace("allowed_as_hit_action", attr.allowed_as_hit_action); - act->emplace("allowed_as_default_action", attr.allowed_as_default_action); - ; + act->emplace("constant_default_action"_cs, attr.constant_default_action); + act->emplace("is_compiler_added_action"_cs, attr.is_compiler_added_action); + act->emplace("allowed_as_hit_action"_cs, attr.allowed_as_hit_action); + act->emplace("allowed_as_default_action"_cs, attr.allowed_as_default_action); } auto *paramJson = new Util::JsonArray(); if (attr.params) { @@ -423,7 +422,7 @@ Util::JsonArray *DpdkContextGenerator::addActions(const IR::P4Table *table, position++; } } - act->emplace("p4_parameters", paramJson); + act->emplace("p4_parameters"_cs, paramJson); actArray->append(act); } } @@ -437,9 +436,9 @@ bool DpdkContextGenerator::addRefTables(const cstring tbl_name, const IR::P4Tabl // Below empty arrays are currently required by the control plane software. // May be removed in future. - tableJson->emplace("stateful_table_refs", new Util::JsonArray()); - tableJson->emplace("statistics_table_refs", new Util::JsonArray()); - tableJson->emplace("meter_table_refs", new Util::JsonArray()); + tableJson->emplace("stateful_table_refs"_cs, new Util::JsonArray()); + tableJson->emplace("statistics_table_refs"_cs, new Util::JsonArray()); + tableJson->emplace("meter_table_refs"_cs, new Util::JsonArray()); // Reference to compiler generated member table in case of action profile and action selector. if (structure->member_tables.count(tbl_name)) { @@ -449,10 +448,10 @@ bool DpdkContextGenerator::addRefTables(const cstring tbl_name, const IR::P4Tabl auto *actionDataField = new Util::JsonObject(); auto tableAttr = ::get(tableAttrmap, (*memberTable)->name.originalName); auto tableName = tableAttr.controlName + "." + (*memberTable)->name.originalName; - actionDataField->emplace("name", tableName); - actionDataField->emplace("handle", tableAttr.tableHandle); + actionDataField->emplace("name"_cs, tableName); + actionDataField->emplace("handle"_cs, tableAttr.tableHandle); actionDataJson->append(actionDataField); - tableJson->emplace("action_data_table_refs", actionDataJson); + tableJson->emplace("action_data_table_refs"_cs, actionDataJson); } // Reference to compiler generated group table in case of action selector @@ -463,14 +462,14 @@ bool DpdkContextGenerator::addRefTables(const cstring tbl_name, const IR::P4Tabl auto *selectField = new Util::JsonObject(); auto tableAttr = ::get(tableAttrmap, groupTable->name.originalName); auto tableName = tableAttr.controlName + "." + groupTable->name.originalName; - selectField->emplace("name", tableName); - selectField->emplace("handle", tableAttr.tableHandle); + selectField->emplace("name"_cs, tableName); + selectField->emplace("handle"_cs, tableAttr.tableHandle); selectionJson->append(selectField); - tableJson->emplace("selection_table_refs", selectionJson); + tableJson->emplace("selection_table_refs"_cs, selectionJson); } if (hasActionProfileSelector) { - tableJson->emplace("action_profile", (*memberTable)->name.originalName); + tableJson->emplace("action_profile"_cs, (*memberTable)->name.originalName); } return hasActionProfileSelector; } @@ -496,7 +495,7 @@ void DpdkContextGenerator::addMatchTables(Util::JsonArray *tablesJson) { match_keys->keyElements.at(position), position); position++; } - tableJson->emplace("match_key_fields", keyJson); + tableJson->emplace("match_key_fields"_cs, keyJson); } } // If table implementation is action profile or action selector, all actions from member @@ -512,18 +511,19 @@ void DpdkContextGenerator::addMatchTables(Util::JsonArray *tablesJson) { setDefaultActionHandle(table); tableAttr = ::get(tableAttrmap, table->name.originalName); - tableJson->emplace("actions", addActions(table, tableAttr.controlName, isMatchTable)); + tableJson->emplace("actions"_cs, + addActions(table, tableAttr.controlName, isMatchTable)); if (isMatchTable) { - tableJson->emplace("match_attributes", + tableJson->emplace("match_attributes"_cs, addMatchAttributes(table, tableAttr.controlName)); } - tableJson->emplace("default_action_handle", tableAttr.default_action_handle); + tableJson->emplace("default_action_handle"_cs, tableAttr.default_action_handle); } else { SelectionTable sel; sel.setAttributes(tbl, tableAttrmap); - tableJson->emplace("max_n_groups", sel.max_n_groups); - tableJson->emplace("max_n_members_per_group", sel.max_n_members_per_group); - tableJson->emplace("bound_to_action_data_table_handle", + tableJson->emplace("max_n_groups"_cs, sel.max_n_groups); + tableJson->emplace("max_n_members_per_group"_cs, sel.max_n_members_per_group); + tableJson->emplace("bound_to_action_data_table_handle"_cs, sel.bound_to_action_data_table_handle); } tablesJson->append(tableJson); @@ -535,17 +535,17 @@ void DpdkContextGenerator::addExternInfo(Util::JsonArray *externsJson) { for (auto t : externs) { auto externAttr = ::get(externAttrMap, t->name.name); auto *externJson = new Util::JsonObject(); - externJson->emplace("name", externAttr.externalName); - externJson->emplace("target_name", t->name.name); - externJson->emplace("type", externAttr.externType); + externJson->emplace("name"_cs, externAttr.externalName); + externJson->emplace("target_name"_cs, t->name.name); + externJson->emplace("type"_cs, externAttr.externType); auto *attrJson = new Util::JsonObject(); if (externAttr.externType == "Counter" || externAttr.externType == "DirectCounter") { - attrJson->emplace("type", externAttr.counterType); + attrJson->emplace("type"_cs, externAttr.counterType); } if (externAttr.externType == "DirectCounter" || externAttr.externType == "DirectMeter") { - attrJson->emplace("table_id", externAttr.table_id); + attrJson->emplace("table_id"_cs, externAttr.table_id); } - externJson->emplace("attributes", attrJson); + externJson->emplace("attributes"_cs, attrJson); externsJson->append(externJson); } } @@ -556,15 +556,15 @@ const Util::JsonObject *DpdkContextGenerator::genContextJsonObject() { auto *externsJson = new Util::JsonArray(); struct TopLevelCtxt tlinfo; tlinfo.initTopLevelCtxt(options); - json->emplace("program_name", tlinfo.progName); - json->emplace("build_date", tlinfo.buildDate); - json->emplace("compile_command", tlinfo.compileCommand); - json->emplace("compiler_version", tlinfo.compilerVersion); - json->emplace("schema_version", cstring("0.1")); - json->emplace("target", cstring("DPDK")); - json->emplace("tables", tablesJson); + json->emplace("program_name"_cs, tlinfo.progName); + json->emplace("build_date"_cs, tlinfo.buildDate); + json->emplace("compile_command"_cs, tlinfo.compileCommand); + json->emplace("compiler_version"_cs, tlinfo.compilerVersion); + json->emplace("schema_version"_cs, "0.1"_cs); + json->emplace("target"_cs, "DPDK"_cs); + json->emplace("tables"_cs, tablesJson); addMatchTables(tablesJson); - json->emplace("externs", externsJson); + json->emplace("externs"_cs, externsJson); addExternInfo(externsJson); return json; } diff --git a/backends/dpdk/dpdkContext.h b/backends/dpdk/dpdkContext.h index e04ec8ad86..11e49a218d 100644 --- a/backends/dpdk/dpdkContext.h +++ b/backends/dpdk/dpdkContext.h @@ -22,6 +22,7 @@ limitations under the License. #include "constants.h" #include "control-plane/bfruntime.h" #include "dpdkProgramStructure.h" +#include "lib/cstring.h" #include "lib/json.h" #include "lib/nullstream.h" #include "options.h" @@ -36,6 +37,8 @@ namespace p4configv1 = ::p4::config::v1; namespace DPDK { +using namespace P4::literals; + /// This structure holds table attributes required for context JSON which are not /// part of P4Table. struct TableAttributes { @@ -90,9 +93,9 @@ struct TopLevelCtxt { auto fileName = progName.findlast('/'); // Handle the case when input file is in the current working directory. // fileName would be null in that case, hence progName should remain unchanged. - if (fileName) progName = fileName; + if (fileName) progName = cstring(fileName); auto fileext = progName.find("."); - progName = progName.replace(fileext, ""); + progName = progName.replace(cstring(fileext), cstring::empty); progName = progName.trim("/\t\n\r"); compilerVersion = options.compilerVersion; } @@ -107,19 +110,19 @@ struct SelectionTable { const std::map &tableAttrmap) { max_n_groups = 0; max_n_members_per_group = 0; - auto n_groups = tbl->properties->getProperty("n_groups_max"); + auto n_groups = tbl->properties->getProperty("n_groups_max"_cs); if (n_groups) { auto n_groups_expr = n_groups->value->to()->expression; max_n_groups = n_groups_expr->to()->asInt(); } - auto n_members = tbl->properties->getProperty("n_members_per_group_max"); + auto n_members = tbl->properties->getProperty("n_members_per_group_max"_cs); if (n_members) { auto n_members_expr = n_members->value->to()->expression; max_n_members_per_group = n_members_expr->to()->asInt(); } // Fetch associated member table handle cstring actionDataTableName = tbl->name.originalName; - actionDataTableName = actionDataTableName.replace("_sel", ""); + actionDataTableName = actionDataTableName.replace("_sel"_cs, cstring::empty); auto actionTableAttr = ::get(tableAttrmap, actionDataTableName); bound_to_action_data_table_handle = actionTableAttr.tableHandle; } diff --git a/backends/dpdk/dpdkHelpers.cpp b/backends/dpdk/dpdkHelpers.cpp index 66578ea69b..e8955d2d0f 100644 --- a/backends/dpdk/dpdkHelpers.cpp +++ b/backends/dpdk/dpdkHelpers.cpp @@ -20,9 +20,12 @@ limitations under the License. #include "dpdkUtils.h" #include "frontends/p4/tableApply.h" #include "ir/ir.h" +#include "lib/cstring.h" namespace DPDK { +using namespace P4::literals; + /// convert relation comparison statements into the corresponding branching /// instructions in dpdk. void ConvertStatementToDpdk::process_relation_operation(const IR::Expression *dst, @@ -244,17 +247,17 @@ bool ConvertStatementToDpdk::preorder(const IR::AssignmentStatement *a) { } auto hash_alg = declArgs->at(0)->expression; unsigned hashAlgValue = CRC1; - cstring hashInstr = "hash"; + cstring hashInstr = "hash"_cs; if (hash_alg->is()) hashAlgValue = hash_alg->to()->asUnsigned(); - cstring hashAlgName = "crc32"; + cstring hashAlgName = "crc32"_cs; if (hashAlgValue == JHASH0 || hashAlgValue == JHASH5) - hashAlgName = "jhash"; + hashAlgName = "jhash"_cs; else if (hashAlgValue >= CRC1 && hashAlgValue <= CRC4) - hashAlgName = "crc32"; + hashAlgName = "crc32"_cs; else if (hashAlgValue == TOEPLITZ) { hashAlgName = e->object->getName().name; - hashInstr = "rss"; + hashInstr = "rss"_cs; } IR::Vector components; @@ -345,7 +348,7 @@ bool ConvertStatementToDpdk::preorder(const IR::AssignmentStatement *a) { } else if (e->originalExternType->getName().name == "InternetChecksum") { if (e->method->getName().name == "get") { auto res = structure->csum_map.find(e->object->to()); - cstring intermediate = ""; + cstring intermediate = cstring::empty; if (res != structure->csum_map.end()) { intermediate = res->second; } else { @@ -443,9 +446,9 @@ bool ConvertStatementToDpdk::preorder(const IR::AssignmentStatement *a) { metadataStruct->fields.push_back( new IR::StructField(portInOutbound, IR::Type_Bits::get(32))); add_instr(new IR::DpdkRegisterReadStatement( - port_in_inbound, "ipsec_port_in_inbound", new IR::Constant(0))); + port_in_inbound, "ipsec_port_in_inbound"_cs, new IR::Constant(0))); add_instr(new IR::DpdkRegisterReadStatement( - port_in_outbound, "ipsec_port_in_outbound", new IR::Constant(0))); + port_in_outbound, "ipsec_port_in_outbound"_cs, new IR::Constant(0))); add_instr(new IR::DpdkMovStatement(left, new IR::Constant(false))); auto true_label = refmap->newName("label_true"); auto end_label = refmap->newName("label_end"); @@ -686,7 +689,7 @@ void ConvertStatementToDpdk::updateMdStrAndGenInstr(const IR::Argument *field, /// This function returns the header/metadata structure name cstring ConvertStatementToDpdk::getHdrMdStrName(const IR::Member *mem) { - cstring sName = ""; + cstring sName = cstring::empty; if ((mem != nullptr) && (mem->expr != nullptr) && (mem->expr->type != nullptr)) { if (auto st = mem->expr->type->to()) { sName = st->name.name; @@ -703,9 +706,9 @@ bool ConvertStatementToDpdk::checkIfBelongToSameHdrMdStructure(const IR::Argumen if (auto s = field->expression->to()) { if (s->components.size() == 1) return true; - cstring hdrStrName = ""; + cstring hdrStrName = cstring::empty; for (auto field1 : s->components) { - cstring sName = ""; + cstring sName = cstring::empty; if (auto exp = field1->expression->to()) { auto type = typemap->getType(exp, true); if (type->is()) { @@ -717,7 +720,7 @@ bool ConvertStatementToDpdk::checkIfBelongToSameHdrMdStructure(const IR::Argumen } } - if (hdrStrName == "") + if (hdrStrName.isNullOrEmpty()) hdrStrName = sName; else if (hdrStrName != sName) return false; @@ -745,12 +748,12 @@ bool ConvertStatementToDpdk::checkIfBelongToSameHdrMdStructure(const IR::Argumen bool ConvertStatementToDpdk::checkIfConsecutiveHdrMdfields(const IR::Argument *field) { if (auto s = field->expression->to()) { if (s->components.size() == 1) return true; - cstring stName = ""; + cstring stName = cstring::empty; const IR::Type *hdrMdType = nullptr; std::vector fldList; for (auto field1 : s->components) { if (auto exp = field1->expression->to()) { - if (stName == "") stName = getHdrMdStrName(exp); + if (stName.isNullOrEmpty()) stName = getHdrMdStrName(exp); auto type = typemap->getType(exp, true); if (type->is()) { @@ -1003,7 +1006,7 @@ bool ConvertStatementToDpdk::preorder(const IR::MethodCallStatement *s) { // Checksum function call if (a->originalExternType->getName().name == "InternetChecksum") { auto res = structure->csum_map.find(a->object->to()); - cstring intermediate = ""; + cstring intermediate = cstring::empty; if (res != structure->csum_map.end()) { intermediate = res->second; } else { @@ -1081,9 +1084,9 @@ bool ConvertStatementToDpdk::preorder(const IR::MethodCallStatement *s) { // // @warning If the value is not aligned to 8 bits, the remainder after // division is dropped during runtime (this is a target limitation). - cstring baseName = ""; + cstring baseName; if (length->expression->is()) { - baseName = "varbit"; + baseName = "varbit"_cs; } else if (length->expression->is()) { baseName = length->expression->to()->member.name; } else { @@ -1401,7 +1404,7 @@ bool ConvertStatementToDpdk::preorder(const IR::SwitchStatement *s) { auto size = s->cases.size(); std::vector labels; cstring label; - cstring default_label = ""; + cstring default_label = cstring::empty; auto end_label = refmap->newName("label_endswitch"); if (tc) { add_instr(new IR::DpdkApplyStatement(tc->name.toString())); diff --git a/backends/dpdk/dpdkMetadata.cpp b/backends/dpdk/dpdkMetadata.cpp index 2023aabf65..749942e6cd 100644 --- a/backends/dpdk/dpdkMetadata.cpp +++ b/backends/dpdk/dpdkMetadata.cpp @@ -20,11 +20,13 @@ limitations under the License. namespace DPDK { +using namespace P4::literals; + /// Make sure new decls and fields name are unique. void DirectionToRegRead::uniqueNames(IR::DpdkAsmProgram *p) { // "direction" name is used in dpdk for initialzing direction port mask // make sure no such decls exist with that name - registerInstanceName = "direction"; + registerInstanceName = "direction"_cs; for (auto decl : p->externDeclarations) { usedNames.insert(decl->name); } diff --git a/backends/dpdk/dpdkProgram.cpp b/backends/dpdk/dpdkProgram.cpp index 611f8736b6..c4cc7ca15b 100644 --- a/backends/dpdk/dpdkProgram.cpp +++ b/backends/dpdk/dpdkProgram.cpp @@ -87,7 +87,7 @@ IR::IndexedVector ConvertToDpdkProgram::create_psa_postamb IR::IndexedVector instr; instr.push_back(new IR::DpdkTxStatement( new IR::Member(new IR::PathExpression("m"), "psa_ingress_output_metadata_egress_port"))); - instr.push_back(new IR::DpdkLabelStatement("label_drop")); + instr.push_back(new IR::DpdkLabelStatement("label_drop"_cs)); instr.push_back(new IR::DpdkDropStatement()); return instr; } @@ -253,7 +253,8 @@ cstring ConvertToDpdkParser::append_parser_name(const IR::P4Parser *p, cstring l IR::Declaration_Variable *ConvertToDpdkParser::addNewTmpVarToMetadata(cstring name, const IR::Type *type) { - auto newTmpVar = new IR::Declaration_Variable(IR::ID(refmap->newName(name)), type); + auto newTmpVar = + new IR::Declaration_Variable(IR::ID(refmap->newName(name.string_view())), type); metadataStruct->fields.push_back( new IR::StructField(IR::ID(newTmpVar->name.name), newTmpVar->type)); return newTmpVar; @@ -284,7 +285,7 @@ void ConvertToDpdkParser::getCondVars(const IR::Expression *sv, const IR::Expres auto right = maskexpr->right; unsigned value = right->to()->asUnsigned() & left->to()->asUnsigned(); - auto tmpDecl = addNewTmpVarToMetadata("tmpMask", IR::Type_Bits::get(byteAlignedWidth)); + auto tmpDecl = addNewTmpVarToMetadata("tmpMask"_cs, IR::Type_Bits::get(byteAlignedWidth)); auto tmpMask = new IR::Member(new IR::PathExpression(IR::ID("m")), IR::ID(tmpDecl->name.name)); structure->push_variable(new IR::DpdkDeclaration(tmpDecl)); @@ -363,8 +364,8 @@ bool ConvertToDpdkParser::preorder(const IR::P4Parser *p) { } } } - degree_map.erase("start"); - state_map.erase("start"); + degree_map.erase("start"_cs); + state_map.erase("start"_cs); while (stack.size() > 0) { auto state = stack.back(); @@ -422,7 +423,7 @@ bool ConvertToDpdkParser::preorder(const IR::P4Parser *p) { if (!sc->keyset->is()) { // Create label names, falseLabel for next keyset comparison and // trueLabel for the state to jump on match. - falseLabel = refmap->newName(state->name); + falseLabel = refmap->newName(state->name.name.string_view()); trueLabel = sc->state->path->name; handleTupleExpression(sc->keyset->to(), tupleInputExpr, inputSize, @@ -497,7 +498,7 @@ bool ConvertToDpdkControl::preorder(const IR::P4Action *a) { for (auto i : helper->get_instr()) stmt_list->push_back(i); auto actName = a->name.name; - if (a->name.originalName == "NoAction") actName = "NoAction"; + if (a->name.originalName == "NoAction") actName = a->name.originalName; auto action = new IR::DpdkAction(*stmt_list, actName, *a->parameters); actions.push_back(action); return false; @@ -586,12 +587,12 @@ std::optional ConvertToDpdkControl::getNumberFromProperty(const IR::P4Table bool ConvertToDpdkControl::preorder(const IR::P4Table *t) { if (!checkTableValid(t)) return false; - if (t->properties->getProperty("selector") != nullptr) { - auto group_id = getMemExprFromProperty(t, "group_id"); - auto member_id = getMemExprFromProperty(t, "member_id"); - auto selector_key = t->properties->getProperty("selector"); - auto n_groups_max = getNumberFromProperty(t, "n_groups_max"); - auto n_members_per_group_max = getNumberFromProperty(t, "n_members_per_group_max"); + if (t->properties->getProperty("selector"_cs) != nullptr) { + auto group_id = getMemExprFromProperty(t, "group_id"_cs); + auto member_id = getMemExprFromProperty(t, "member_id"_cs); + auto selector_key = t->properties->getProperty("selector"_cs); + auto n_groups_max = getNumberFromProperty(t, "n_groups_max"_cs); + auto n_members_per_group_max = getNumberFromProperty(t, "n_members_per_group_max"_cs); if (group_id == std::nullopt || member_id == std::nullopt || n_groups_max == std::nullopt || n_members_per_group_max == std::nullopt) @@ -627,7 +628,7 @@ bool ConvertToDpdkControl::preorder(const IR::P4Control *c) { c->body->apply(*helper); if (deparser && structure->isPSA()) { add_inst(new IR::DpdkJmpNotEqualStatement( - "LABEL_DROP", + "LABEL_DROP"_cs, new IR::Member(new IR::PathExpression("m"), "psa_ingress_output_metadata_drop"), new IR::Constant(0))); } diff --git a/backends/dpdk/dpdkProgram.h b/backends/dpdk/dpdkProgram.h index d193825e2e..9a14aa3472 100644 --- a/backends/dpdk/dpdkProgram.h +++ b/backends/dpdk/dpdkProgram.h @@ -35,6 +35,8 @@ limitations under the License. namespace DPDK { +using namespace P4::literals; + class ConvertToDpdkProgram : public Transform { P4::TypeMap *typemap; P4::ReferenceMap *refmap; @@ -135,7 +137,7 @@ class CollectActionUses : public Inspector { if (auto mce = ale->expression->to()) { if (auto path = mce->method->to()) { if (path->path->name.originalName == "NoAction") - actions.insert("NoAction"); + actions.insert("NoAction"_cs); else actions.insert(path->path->name.name); } diff --git a/backends/dpdk/dpdkProgramStructure.cpp b/backends/dpdk/dpdkProgramStructure.cpp index 523067e085..5173f265df 100644 --- a/backends/dpdk/dpdkProgramStructure.cpp +++ b/backends/dpdk/dpdkProgramStructure.cpp @@ -3,6 +3,8 @@ #include "ir/ir.h" #include "options.h" +using namespace P4::literals; + bool ParseDpdkArchitecture::preorder(const IR::ToplevelBlock *block) { // Blocks are not in IR tree, use a custom visitor to traverse. for (auto it : block->constantValue) { @@ -12,89 +14,89 @@ bool ParseDpdkArchitecture::preorder(const IR::ToplevelBlock *block) { } void ParseDpdkArchitecture::parse_pna_block(const IR::PackageBlock *block) { - structure->p4arch = "pna"; - auto p = block->findParameterValue("main_parser"); + structure->p4arch = "pna"_cs; + auto p = block->findParameterValue("main_parser"_cs); if (p == nullptr) { ::error(ErrorType::ERR_MODEL, "Package %1% has no parameter named 'main_parser'", block); return; } auto parser = p->to(); - structure->parsers.emplace("MainParserT", parser->container); - p = block->findParameterValue("pre_control"); + structure->parsers.emplace("MainParserT"_cs, parser->container); + p = block->findParameterValue("pre_control"_cs); auto pre_control = p->to(); - structure->pipelines.emplace("PreControlT", pre_control->container); - p = block->findParameterValue("main_control"); + structure->pipelines.emplace("PreControlT"_cs, pre_control->container); + p = block->findParameterValue("main_control"_cs); auto pipeline = p->to(); - structure->pipelines.emplace("MainControlT", pipeline->container); + structure->pipelines.emplace("MainControlT"_cs, pipeline->container); structure->pipeline_controls.emplace(pipeline->container->name); - p = block->findParameterValue("main_deparser"); + p = block->findParameterValue("main_deparser"_cs); auto deparser = p->to(); - structure->deparsers.emplace("MainDeparserT", deparser->container); + structure->deparsers.emplace("MainDeparserT"_cs, deparser->container); structure->non_pipeline_controls.emplace(deparser->container->name); } void ParseDpdkArchitecture::parse_psa_block(const IR::PackageBlock *block) { - structure->p4arch = "psa"; - auto pkg = block->findParameterValue("ingress"); + structure->p4arch = "psa"_cs; + auto pkg = block->findParameterValue("ingress"_cs); if (pkg == nullptr) { ::error(ErrorType::ERR_MODEL, "Package %1% has no parameter named 'ingress'", block); return; } if (auto ingress = pkg->to()) { - auto p = ingress->findParameterValue("ip"); + auto p = ingress->findParameterValue("ip"_cs); if (!p) { ::error(ErrorType::ERR_MODEL, "'ingress' package %1% has no parameter named 'ip'", block); return; } auto parser = p->to(); - structure->parsers.emplace("IngressParser", parser->container); - p = ingress->findParameterValue("ig"); + structure->parsers.emplace("IngressParser"_cs, parser->container); + p = ingress->findParameterValue("ig"_cs); if (!p) { ::error(ErrorType::ERR_MODEL, "'ingress' package %1% has no parameter named 'ig'", block); return; } auto pipeline = p->to(); - structure->pipelines.emplace("Ingress", pipeline->container); + structure->pipelines.emplace("Ingress"_cs, pipeline->container); structure->pipeline_controls.emplace(pipeline->container->name); - p = ingress->findParameterValue("id"); + p = ingress->findParameterValue("id"_cs); if (!p) { ::error(ErrorType::ERR_MODEL, "'ingress' package %1% has no parameter named 'id'", block); return; } auto deparser = p->to(); - structure->deparsers.emplace("IngressDeparser", deparser->container); + structure->deparsers.emplace("IngressDeparser"_cs, deparser->container); structure->non_pipeline_controls.emplace(deparser->container->name); } - pkg = block->findParameterValue("egress"); + pkg = block->findParameterValue("egress"_cs); if (auto egress = pkg->to()) { - auto p = egress->findParameterValue("ep"); + auto p = egress->findParameterValue("ep"_cs); if (!p) { ::error(ErrorType::ERR_MODEL, "'egress' package %1% has no parameter named 'ep'", block); return; } auto parser = p->to(); - structure->parsers.emplace("EgressParser", parser->container); - p = egress->findParameterValue("eg"); + structure->parsers.emplace("EgressParser"_cs, parser->container); + p = egress->findParameterValue("eg"_cs); if (!p) { ::error(ErrorType::ERR_MODEL, "'egress' package %1% has no parameter named 'eg'", block); return; } auto pipeline = p->to(); - structure->pipelines.emplace("Egress", pipeline->container); + structure->pipelines.emplace("Egress"_cs, pipeline->container); structure->pipeline_controls.emplace(pipeline->container->name); - p = egress->findParameterValue("ed"); + p = egress->findParameterValue("ed"_cs); if (!p) { ::error(ErrorType::ERR_MODEL, "'egress' package %1% has no parameter named 'ed'", block); return; } auto deparser = p->to(); - structure->deparsers.emplace("EgressDeparser", deparser->container); + structure->deparsers.emplace("EgressDeparser"_cs, deparser->container); structure->non_pipeline_controls.emplace(deparser->container->name); } } @@ -237,6 +239,7 @@ void InspectDpdkProgram::addTypesAndInstances(const IR::Type_StructLike *type, b } bool InspectDpdkProgram::isStandardMetadata(cstring ptName) { + // FIXME: do we really need strcmp here? return (!strcmp(ptName, "psa_ingress_parser_input_metadata_t") || !strcmp(ptName, "psa_egress_parser_input_metadata_t") || !strcmp(ptName, "psa_ingress_input_metadata_t") || diff --git a/backends/dpdk/dpdkProgramStructure.h b/backends/dpdk/dpdkProgramStructure.h index 2bd778ccb0..5f05dbd606 100644 --- a/backends/dpdk/dpdkProgramStructure.h +++ b/backends/dpdk/dpdkProgramStructure.h @@ -57,8 +57,8 @@ struct DpdkProgramStructure { IR::Type_Struct *metadataStruct; IR::Expression *ipsec_header; - cstring local_metadata_type = ""; - cstring header_type = ""; + cstring local_metadata_type = cstring::empty; + cstring header_type = cstring::empty; IR::IndexedVector compiler_added_fields; IR::IndexedVector key_fields; IR::Vector used_metadata; @@ -104,8 +104,8 @@ struct hdrFieldInfo { unsigned msb; unsigned fieldWidth; hdrFieldInfo() { - modifiedName = ""; - headerStr = ""; + modifiedName = cstring::empty; + headerStr = cstring::empty; modifiedWidth = 0; offset = 0; lsb = 0; diff --git a/backends/dpdk/dpdkUtils.cpp b/backends/dpdk/dpdkUtils.cpp index 6b06d203bf..1d90f09512 100644 --- a/backends/dpdk/dpdkUtils.cpp +++ b/backends/dpdk/dpdkUtils.cpp @@ -16,6 +16,8 @@ limitations under the License. #include "dpdkUtils.h" namespace DPDK { +using namespace P4::literals; + bool isSimpleExpression(const IR::Expression *e) { if (e->is() || e->is() || e->is() || e->is()) @@ -38,6 +40,7 @@ bool isCommutativeBinaryOperation(const IR::Operation_Binary *bin) { } bool isStandardMetadata(cstring name) { + // FIXME: should be better structured (e.g. a set) bool isStdMeta = name == "psa_ingress_parser_input_metadata_t" || name == "psa_ingress_input_metadata_t" || name == "psa_ingress_output_metadata_t" || name == "psa_egress_parser_input_metadata_t" || @@ -50,13 +53,13 @@ bool isStandardMetadata(cstring name) { bool isHeadersStruct(const IR::Type_Struct *st) { if (!st) return false; - auto annon = st->getAnnotation("__packet_data__"); + auto annon = st->getAnnotation("__packet_data__"_cs); if (annon) return true; return false; } bool isMetadataStruct(const IR::Type_Struct *st) { for (auto anno : st->annotations->annotations) { - if (anno->name == "__metadata__") { + if (anno->name == "__metadata__"_cs) { return true; } } @@ -143,9 +146,9 @@ IR::Declaration_Instance *createRegDeclarationInstance(cstring instanceName, int } /// Check for reserved names for DPDK target. -bool reservedNames(P4::ReferenceMap *refMap, std::vector names, cstring &resName) { - for (auto name : names) { - auto newname = refMap->newName(name); +bool reservedNames(P4::ReferenceMap *refMap, const std::vector &names, cstring &resName) { + for (const auto &name : names) { + auto newname = refMap->newName(name.string_view()); if (newname != name) { resName = name; return false; diff --git a/backends/dpdk/dpdkUtils.h b/backends/dpdk/dpdkUtils.h index 0bdf7a1893..cc9c98ff39 100644 --- a/backends/dpdk/dpdkUtils.h +++ b/backends/dpdk/dpdkUtils.h @@ -37,7 +37,7 @@ int getMetadataFieldWidth(int width); const IR::Type_Bits *getEightBitAlignedType(const IR::Type_Bits *tb); /// Check for reserved names for DPDK target. -bool reservedNames(P4::ReferenceMap *refMap, std::vector names, cstring &resName); +bool reservedNames(P4::ReferenceMap *refMap, const std::vector &names, cstring &resName); /// Creates Register extern declaration for holding persistent information. IR::Declaration_Instance *createRegDeclarationInstance(cstring instanceName, int regSize, int indexBitWidth, int initValBitwidth); diff --git a/backends/dpdk/main.cpp b/backends/dpdk/main.cpp index 7d0e83c8f6..67f4d522b5 100644 --- a/backends/dpdk/main.cpp +++ b/backends/dpdk/main.cpp @@ -40,14 +40,16 @@ limitations under the License. #include "lib/log.h" #include "lib/nullstream.h" +using namespace P4::literals; + void generateTDIBfrtJson(bool isTDI, const IR::P4Program *program, DPDK::DpdkOptions &options) { auto p4RuntimeSerializer = P4::P4RuntimeSerializer::get(); if (options.arch == "psa") p4RuntimeSerializer->registerArch( - "psa", new P4::ControlPlaneAPI::Standard::PSAArchHandlerBuilderForDPDK()); + "psa"_cs, new P4::ControlPlaneAPI::Standard::PSAArchHandlerBuilderForDPDK()); if (options.arch == "pna") p4RuntimeSerializer->registerArch( - "pna", new P4::ControlPlaneAPI::Standard::PNAArchHandlerBuilderForDPDK()); + "pna"_cs, new P4::ControlPlaneAPI::Standard::PNAArchHandlerBuilderForDPDK()); auto p4Runtime = P4::generateP4Runtime(program, options.arch); cstring filename = isTDI ? options.tdiFile : options.bfRtSchema; @@ -66,7 +68,7 @@ int main(int argc, char *const argv[]) { AutoCompileContext autoDpdkContext(new DPDK::DpdkContext); auto &options = DPDK::DpdkContext::get().options(); options.langVersion = CompilerOptions::FrontendVersion::P4_16; - options.compilerVersion = DPDK_VERSION_STRING; + options.compilerVersion = cstring(DPDK_VERSION_STRING); if (options.process(argc, argv) != nullptr) { if (options.loadIRFromJson == false) options.setInputFile(); diff --git a/backends/dpdk/midend.cpp b/backends/dpdk/midend.cpp index a0245ce17f..39ff4cb4d2 100644 --- a/backends/dpdk/midend.cpp +++ b/backends/dpdk/midend.cpp @@ -30,6 +30,7 @@ limitations under the License. #include "frontends/p4/typeMap.h" #include "frontends/p4/uniqueNames.h" #include "frontends/p4/unusedDeclarations.h" +#include "lib/cstring.h" #include "midend/actionSynthesis.h" #include "midend/compileTimeOps.h" #include "midend/complexComparison.h" @@ -119,17 +120,17 @@ DpdkMidEnd::DpdkMidEnd(CompilerOptions &options, std::ostream *outStream) { cstring externMethod = em->method->getName().name; std::vector> doNotCopyPropList = { - {"Checksum", "update"}, - {"Hash", "get_hash"}, - {"InternetChecksum", "add"}, - {"InternetChecksum", "subtract"}, - {"InternetChecksum", "set_state"}, - {"Register", "read"}, - {"Register", "write"}, - {"Counter", "count"}, - {"Meter", "execute"}, - {"Meter", "dpdk_execute"}, - {"Digest", "pack"}, + {"Checksum"_cs, "update"_cs}, + {"Hash"_cs, "get_hash"_cs}, + {"InternetChecksum"_cs, "add"_cs}, + {"InternetChecksum"_cs, "subtract"_cs}, + {"InternetChecksum"_cs, "set_state"_cs}, + {"Register"_cs, "read"_cs}, + {"Register"_cs, "write"_cs}, + {"Counter"_cs, "count"_cs}, + {"Meter"_cs, "execute"_cs}, + {"Meter"_cs, "dpdk_execute"_cs}, + {"Digest"_cs, "pack"_cs}, }; for (auto f : doNotCopyPropList) { if (externType == f.first && externMethod == f.second) { @@ -139,7 +140,7 @@ DpdkMidEnd::DpdkMidEnd(CompilerOptions &options, std::ostream *outStream) { } else if (auto ef = mi->to()) { cstring externFuncName = ef->method->getName().name; std::vector doNotCopyPropList = { - "verify", + "verify"_cs, }; for (auto f : doNotCopyPropList) { if (externFuncName == f) return false; @@ -152,19 +153,20 @@ DpdkMidEnd::DpdkMidEnd(CompilerOptions &options, std::ostream *outStream) { std::function validateTableProperties = [=](cstring arch) -> Inspector * { if (arch == "pna") { return new P4::ValidateTableProperties( - {"pna_implementation", "pna_direct_counter", "pna_direct_meter", "pna_idle_timeout", - "size", "add_on_miss", "idle_timeout_with_auto_delete", - "default_idle_timeout_for_data_plane_added_entries"}); + {"pna_implementation"_cs, "pna_direct_counter"_cs, "pna_direct_meter"_cs, + "pna_idle_timeout"_cs, "size"_cs, "add_on_miss"_cs, + "idle_timeout_with_auto_delete"_cs, + "default_idle_timeout_for_data_plane_added_entries"_cs}); } else if (arch == "psa") { - return new P4::ValidateTableProperties({"psa_implementation", "psa_direct_counter", - "psa_direct_meter", "psa_idle_timeout", - "size"}); + return new P4::ValidateTableProperties({"psa_implementation"_cs, + "psa_direct_counter"_cs, "psa_direct_meter"_cs, + "psa_idle_timeout"_cs, "size"_cs}); } else { return nullptr; } }; - if (DPDK::DpdkContext::get().options().loadIRFromJson == false) { + if (!DPDK::DpdkContext::get().options().loadIRFromJson) { addPasses({ options.ndebug ? new P4::RemoveAssertAssume(&refMap, &typeMap) : nullptr, new P4::RemoveMiss(&refMap, &typeMap), @@ -225,7 +227,7 @@ DpdkMidEnd::DpdkMidEnd(CompilerOptions &options, std::ostream *outStream) { new VisitFunctor([this, evaluator]() { toplevel = evaluator->getToplevelBlock(); }), }); if (options.listMidendPasses) { - listPasses(*outStream, "\n"); + listPasses(*outStream, cstring::newline); *outStream << std::endl; return; } diff --git a/backends/dpdk/options.cpp b/backends/dpdk/options.cpp index bd8e914990..03275d0fe6 100644 --- a/backends/dpdk/options.cpp +++ b/backends/dpdk/options.cpp @@ -5,9 +5,11 @@ namespace DPDK { +using namespace P4::literals; + std::vector *DpdkOptions::process(int argc, char *const argv[]) { searchForIncludePath(p4includePath, - {"p4include/dpdk", "../p4include/dpdk", "../../p4include/dpdk"}, + {"p4include/dpdk"_cs, "../p4include/dpdk"_cs, "../../p4include/dpdk"_cs}, exename(argv[0])); auto remainingOptions = CompilerOptions::process(argc, argv); @@ -18,11 +20,11 @@ std::vector *DpdkOptions::process(int argc, char *const argv[]) { const char *DpdkOptions::getIncludePath() { char *driverP4IncludePath = isv1() ? getenv("P4C_14_INCLUDE_PATH") : getenv("P4C_16_INCLUDE_PATH"); - cstring path = ""; - if (driverP4IncludePath != nullptr) path += cstring(" -I") + cstring(driverP4IncludePath); + cstring path = cstring::empty; + if (driverP4IncludePath != nullptr) path += " -I"_cs + cstring(driverP4IncludePath); path += cstring(" -I") + (isv1() ? p4_14includePath : p4includePath); - if (!isv1()) path += cstring(" -I") + p4includePath + cstring("/dpdk"); + if (!isv1()) path += " -I"_cs + p4includePath + "/dpdk"_cs; return path.c_str(); } diff --git a/backends/dpdk/options.h b/backends/dpdk/options.h index c50006359c..f4ec5166f6 100644 --- a/backends/dpdk/options.h +++ b/backends/dpdk/options.h @@ -23,15 +23,15 @@ namespace DPDK { class DpdkOptions : public CompilerOptions { public: - cstring bfRtSchema = ""; + cstring bfRtSchema = cstring::empty; /// File to output to. cstring outputFile = nullptr; /// File to output TDI JSON to. - cstring tdiFile = ""; + cstring tdiFile = cstring::empty; /// File to output context JSON to. - cstring ctxtFile = ""; + cstring ctxtFile = cstring::empty; /// File to output the TDI builder configuration to. - cstring tdiBuilderConf = ""; + cstring tdiBuilderConf = cstring::empty; /// Read from JSON. bool loadIRFromJson = false; /// Enable/disable Egress pipeline in PSA. @@ -58,35 +58,35 @@ class DpdkOptions : public CompilerOptions { registerOption( "--bf-rt-schema", "file", [this](const char *arg) { - bfRtSchema = arg; + bfRtSchema = cstring(arg); return true; }, "Generate and write BF-RT JSON schema to the specified file"); registerOption( "-o", "outfile", [this](const char *arg) { - outputFile = arg; + outputFile = cstring(arg); return true; }, "Write output to outfile"); registerOption( "--tdi-builder-conf", "file", [this](const char *arg) { - tdiBuilderConf = arg; + tdiBuilderConf = cstring(arg); return true; }, "Generate and write the TDI builder configuration to the specified file"); registerOption( "--tdi", "file", [this](const char *arg) { - tdiFile = arg; + tdiFile = cstring(arg); return true; }, "Generate and write TDI JSON to the specified file"); registerOption( "--context", "file", [this](const char *arg) { - ctxtFile = arg; + ctxtFile = cstring(arg); return true; }, "Generate and write context JSON to the specified file"); @@ -94,7 +94,7 @@ class DpdkOptions : public CompilerOptions { "--fromJSON", "file", [this](const char *arg) { loadIRFromJson = true; - file = arg; + file = cstring(arg); return true; }, "Use IR representation from JsonFile dumped previously," diff --git a/backends/dpdk/spec.cpp b/backends/dpdk/spec.cpp index b2a66d8d7d..ea6f685925 100644 --- a/backends/dpdk/spec.cpp +++ b/backends/dpdk/spec.cpp @@ -14,7 +14,7 @@ auto &origNameMap = DPDK::ShortenTokenLength::origNameMap; void add_space(std::ostream &out, int size) { out << std::setfill(' ') << std::setw(size) << " "; } -void add_comment(std::ostream &out, cstring str, cstring sep = "") { +void add_comment(std::ostream &out, cstring str, std::string_view sep = "") { if (origNameMap.count(str)) { out << sep << ";oldname:" << origNameMap.at(str) << "\n"; } @@ -211,7 +211,7 @@ std::ostream &IR::DpdkHeaderType::toSpec(std::ostream &out) const { } std::ostream &IR::DpdkStructType::toSpec(std::ostream &out) const { - if (getAnnotations()->getSingle("__packet_data__")) { + if (getAnnotations()->getSingle("__packet_data__"_cs)) { for (auto it = fields.begin(); it != fields.end(); ++it) { add_comment(out, (*it)->name.toString()); if (auto t = (*it)->type->to()) { @@ -258,7 +258,7 @@ std::ostream &IR::DpdkStructType::toSpec(std::ostream &out) const { out << std::endl; } out << "}" << std::endl; - if (getAnnotations()->getSingle("__metadata__")) { + if (getAnnotations()->getSingle("__metadata__"_cs)) { out << "metadata instanceof " << name << std::endl; } } @@ -402,8 +402,8 @@ std::ostream &IR::DpdkTable::toSpec(std::ostream &out) const { } else { out << "\t\t" << DPDK::toStr(action->expression); } - if (action->annotations->getAnnotation("tableonly")) out << " @tableonly"; - if (action->annotations->getAnnotation("defaultonly")) out << " @defaultonly"; + if (action->annotations->getAnnotation("tableonly"_cs)) out << " @tableonly"; + if (action->annotations->getAnnotation("defaultonly"_cs)) out << " @defaultonly"; out << std::endl; } out << "\t}" << std::endl; @@ -444,13 +444,13 @@ std::ostream &IR::DpdkTable::toSpec(std::ostream &out) const { } } } - auto def = properties->getProperty("default_action"); + auto def = properties->getProperty("default_action"_cs); if (def->isConstant) out << "const"; out << std::endl; - if (auto psa_implementation = properties->getProperty("psa_implementation")) { + if (auto psa_implementation = properties->getProperty("psa_implementation"_cs)) { out << "\taction_selector " << DPDK::toStr(psa_implementation->value) << std::endl; } - if (auto size = properties->getProperty("size")) { + if (auto size = properties->getProperty("size"_cs)) { out << "\tsize " << DPDK::toStr(size->value) << "" << std::endl; } else { out << "\tsize 0x10000" << std::endl; @@ -489,8 +489,8 @@ std::ostream &IR::DpdkLearner::toSpec(std::ostream &out) const { out << "\tactions {" << std::endl; for (auto action : actions->actionList) { out << "\t\t" << DPDK::toStr(action->expression); - if (action->getAnnotation("tableonly")) out << " @tableonly"; - if (action->getAnnotation("defaultonly")) out << " @defaultonly"; + if (action->getAnnotation("tableonly"_cs)) out << " @tableonly"; + if (action->getAnnotation("defaultonly"_cs)) out << " @defaultonly"; out << std::endl; } out << "\t}" << std::endl; @@ -502,7 +502,7 @@ std::ostream &IR::DpdkLearner::toSpec(std::ostream &out) const { BUG("non-zero default action arguments not supported yet"); } out << std::endl; - if (auto size = properties->getProperty("size")) { + if (auto size = properties->getProperty("size"_cs)) { out << "\tsize " << DPDK::toStr(size->value) << "" << std::endl; } else { out << "\tsize 0x" << std::hex << std::uppercase << default_learner_table_size << std::endl; diff --git a/backends/dpdk/tdiConf.cpp b/backends/dpdk/tdiConf.cpp index a8eaa79697..cdeef5e60c 100644 --- a/backends/dpdk/tdiConf.cpp +++ b/backends/dpdk/tdiConf.cpp @@ -21,6 +21,8 @@ limitations under the License. namespace DPDK { +using namespace P4::literals; + std::vector TdiBfrtConf::getPipeNames(const IR::Declaration_Instance *main) { std::vector pipeNames; for (const auto *arg : *main->arguments) { @@ -42,11 +44,11 @@ std::optional TdiBfrtConf::findPipeName(const IR::P4Program *prog, DPDK::DpdkOptions &options) { if (options.arch == "pna") { // The PNA pipename is currently fixed to "pipe". - return "pipe"; + return "pipe"_cs; } if (options.arch == "psa") { // We try to infer the pipename by looking up the "main" declaration. - auto *decls = prog->getDeclsByName("main"); + auto *decls = prog->getDeclsByName("main"_cs); const IR::Declaration_Instance *main = nullptr; for (const auto *decl : *decls) { main = decl->checkedTo(); @@ -78,14 +80,14 @@ void TdiBfrtConf::generate(const IR::P4Program *prog, DPDK::DpdkOptions &options auto programName = inputFile.stem(); if (options.bfRtSchema.isNullOrEmpty()) { - options.bfRtSchema = (outDir / programName).replace_filename("json").c_str(); + options.bfRtSchema = cstring((outDir / programName).replace_filename("json").c_str()); ::warning( "BF-Runtime Schema file name not provided, but is required for the TDI builder " "configuration. Generating file %1%", options.bfRtSchema); } if (options.ctxtFile.isNullOrEmpty()) { - options.ctxtFile = (outDir / "context.json").c_str(); + options.ctxtFile = cstring((outDir / "context.json").c_str()); ::warning( "DPDK context file name not provided, but is required for the TDI builder " "configuration. Generating file %1%", diff --git a/backends/ebpf/codeGen.cpp b/backends/ebpf/codeGen.cpp index ebdb8a718c..1fd82e232d 100644 --- a/backends/ebpf/codeGen.cpp +++ b/backends/ebpf/codeGen.cpp @@ -63,7 +63,7 @@ bool CodeGenInspector::preorder(const IR::Declaration_Variable *decl) { static cstring getMask(P4::TypeMap *typeMap, const IR::Node *node) { auto type = typeMap->getType(node, true); - cstring mask = ""; + cstring mask = cstring::empty; if (auto tb = type->to()) { if (tb->size != 8 && tb->size != 16 && tb->size != 32 && tb->size != 64) mask = " & ((1 << " + Util::toString(tb->size) + ") - 1)"; @@ -478,16 +478,16 @@ void CodeGenInspector::emitAndConvertByteOrder(const IR::Expression *expr, cstri auto ftype = typeMap->getType(expr); auto et = EBPFTypeFactory::instance->create(ftype); unsigned widthToEmit = dynamic_cast(et)->widthInBits(); - cstring emit = ""; + cstring emit = cstring::empty; unsigned loadSize = 64; if (widthToEmit <= 16) { - emit = byte_order == "HOST" ? "bpf_ntohs" : "bpf_htons"; + emit = byte_order == "HOST" ? "bpf_ntohs"_cs : "bpf_htons"_cs; loadSize = 16; } else if (widthToEmit <= 32) { - emit = byte_order == "HOST" ? "bpf_ntohl" : "bpf_htonl"; + emit = byte_order == "HOST" ? "bpf_ntohl"_cs : "bpf_htonl"_cs; loadSize = 32; } else if (widthToEmit <= 64) { - emit = byte_order == "HOST" ? "ntohll" : "bpf_cpu_to_be64"; + emit = byte_order == "HOST" ? "ntohll"_cs : "bpf_cpu_to_be64"_cs; loadSize = 64; } unsigned shift = loadSize - widthToEmit; @@ -504,7 +504,7 @@ void CodeGenInspector::emitTCBinaryOperation(const IR::Operation_Binary *b, bool auto action = findContext(); auto tcTarget = dynamic_cast(builder->target); - cstring lByteOrder = "HOST", rByteOrder = "HOST"; + cstring lByteOrder = "HOST"_cs, rByteOrder = "HOST"_cs; if (lexpr) { lByteOrder = tcTarget->getByteOrder(typeMap, action, lexpr); } @@ -532,7 +532,7 @@ void CodeGenInspector::emitTCBinaryOperation(const IR::Operation_Binary *b, bool if (width <= 8) { visit(lexpr); } else { - emitAndConvertByteOrder(lexpr, "NETWORK"); + emitAndConvertByteOrder(lexpr, "NETWORK"_cs); } if (isScalar) { builder->spc(); @@ -561,7 +561,7 @@ void CodeGenInspector::emitTCBinaryOperation(const IR::Operation_Binary *b, bool if (width <= 8) { visit(rexpr); } else { - emitAndConvertByteOrder(rexpr, "NETWORK"); + emitAndConvertByteOrder(rexpr, "NETWORK"_cs); } } return; @@ -571,7 +571,7 @@ void CodeGenInspector::emitTCAssignmentEndianessConversion(const IR::Expression const IR::Expression *rexpr) { auto action = findContext(); auto b = dynamic_cast(builder->target); - cstring lByteOrder = "HOST", rByteOrder = "HOST"; + cstring lByteOrder = "HOST"_cs, rByteOrder = "HOST"_cs; if (lexpr) { lByteOrder = b->getByteOrder(typeMap, action, lexpr); } @@ -596,7 +596,7 @@ void CodeGenInspector::emitTCAssignmentEndianessConversion(const IR::Expression // select_0 = hdr.ipv4.diffserv // select_0 = bntoh(hdr.ipv4.diffserv) // - emitAndConvertByteOrder(rexpr, "HOST"); + emitAndConvertByteOrder(rexpr, "HOST"_cs); } if (lByteOrder == "NETWORK") { // If left side of assignment is annotated field i.e network endian, we need to convert @@ -605,7 +605,7 @@ void CodeGenInspector::emitTCAssignmentEndianessConversion(const IR::Expression // hdr.opv4.diffserv = 0x1; // hdr.opv4.diffserv = bhton(0x1) // - emitAndConvertByteOrder(rexpr, "NETWORK"); + emitAndConvertByteOrder(rexpr, "NETWORK"_cs); } return; diff --git a/backends/ebpf/ebpfControl.cpp b/backends/ebpf/ebpfControl.cpp index 2c0c8c2c7a..ad4563a8aa 100644 --- a/backends/ebpf/ebpfControl.cpp +++ b/backends/ebpf/ebpfControl.cpp @@ -22,6 +22,7 @@ limitations under the License. #include "frontends/p4/parameterSubstitution.h" #include "frontends/p4/tableApply.h" #include "frontends/p4/typeMap.h" +#include "lib/cstring.h" #include "lib/error.h" namespace EBPF { @@ -67,7 +68,7 @@ void ControlBodyTranslator::processCustomExternFunction(const P4::ExternFunction builder->append("(const "); auto type = typeMap->getType(arg); auto ebpfType = typeFactory->create(type); - ebpfType->declare(builder, "", false); + ebpfType->declare(builder, cstring::empty, false); builder->append(") "); } visit(arg); @@ -156,11 +157,11 @@ void ControlBodyTranslator::compileEmitField(const IR::Expression *expr, cstring unsigned hdrOffsetBits, EBPFType *type) { unsigned alignment = hdrOffsetBits % 8; unsigned widthToEmit = type->as().widthInBits(); - cstring swap = ""; + cstring swap = cstring::empty; if (widthToEmit == 16) - swap = "htons"; + swap = "htons"_cs; else if (widthToEmit == 32) - swap = "htonl"; + swap = "htonl"_cs; if (!swap.isNullOrEmpty()) { builder->emitIndent(); visit(expr); @@ -318,7 +319,7 @@ void ControlBodyTranslator::processApply(const P4::ApplyMethod *method) { builder->blockStart(); BUG_CHECK(method->expr->arguments->size() == 0, "%1%: table apply with arguments", method); - cstring keyname = "key"; + cstring keyname = "key"_cs; if (table->keyGenerator != nullptr) { builder->emitIndent(); builder->appendLine("/* construct key */"); @@ -330,7 +331,7 @@ void ControlBodyTranslator::processApply(const P4::ApplyMethod *method) { builder->emitIndent(); builder->appendLine("/* value */"); builder->emitIndent(); - cstring valueName = "value"; + cstring valueName = "value"_cs; builder->appendFormat("struct %s *%s = NULL", table->valueTypeName.c_str(), valueName.c_str()); builder->endOfStatement(true); diff --git a/backends/ebpf/ebpfDeparser.cpp b/backends/ebpf/ebpfDeparser.cpp index 24a99feccd..41a8b3d424 100644 --- a/backends/ebpf/ebpfDeparser.cpp +++ b/backends/ebpf/ebpfDeparser.cpp @@ -190,7 +190,7 @@ void DeparserHdrEmitTranslator::emitField(CodeBuilder *builder, cstring field, } unsigned widthToEmit = et->widthInBits(); unsigned emitSize = 0; - cstring swap = "", msgStr; + cstring swap = cstring::empty, msgStr; if (widthToEmit <= 64) { if (program->options.emitTraceMessages) { @@ -214,13 +214,13 @@ void DeparserHdrEmitTranslator::emitField(CodeBuilder *builder, cstring field, if (widthToEmit <= 8) { emitSize = 8; } else if (widthToEmit <= 16) { - swap = "bpf_htons"; + swap = "bpf_htons"_cs; emitSize = 16; } else if (widthToEmit <= 32) { - swap = "htonl"; + swap = "htonl"_cs; emitSize = 32; } else if (widthToEmit <= 64) { - swap = "htonll"; + swap = "htonll"_cs; emitSize = 64; } unsigned shift = @@ -329,7 +329,7 @@ void EBPFDeparser::emitBufferAdjusts(CodeBuilder *builder) const { builder->endOfStatement(true); builder->emitIndent(); builder->appendFormat("%s = ", returnCode.c_str()); - program->progTarget->emitResizeBuffer(builder, program->model.CPacketName.str(), + program->progTarget->emitResizeBuffer(builder, program->model.CPacketName.toString(), outerHdrOffsetVar); builder->endOfStatement(true); @@ -371,14 +371,14 @@ void EBPFDeparser::emit(CodeBuilder *builder) { builder->emitIndent(); builder->appendFormat("%s = %s;", program->packetStartVar, - builder->target->dataOffset(program->model.CPacketName.str())); + builder->target->dataOffset(program->model.CPacketName.toString())); builder->newline(); builder->emitIndent(); builder->appendFormat("%s = %s;", program->headerStartVar, program->packetStartVar); builder->newline(); builder->emitIndent(); builder->appendFormat("%s = %s;", program->packetEndVar, - builder->target->dataEnd(program->model.CPacketName.str())); + builder->target->dataEnd(program->model.CPacketName.toString())); builder->newline(); // emit headers diff --git a/backends/ebpf/ebpfModel.cpp b/backends/ebpf/ebpfModel.cpp index 792cde33b1..7476c373be 100644 --- a/backends/ebpf/ebpfModel.cpp +++ b/backends/ebpf/ebpfModel.cpp @@ -18,7 +18,7 @@ limitations under the License. namespace EBPF { -cstring EBPFModel::reservedPrefix = "ebpf_"; +cstring EBPFModel::reservedPrefix = "ebpf_"_cs; EBPFModel EBPFModel::instance; } // namespace EBPF diff --git a/backends/ebpf/ebpfModel.h b/backends/ebpf/ebpfModel.h index 0757027703..9f819e325d 100644 --- a/backends/ebpf/ebpfModel.h +++ b/backends/ebpf/ebpfModel.h @@ -24,18 +24,20 @@ limitations under the License. namespace EBPF { +using namespace P4::literals; + struct TableImpl_Model : public ::Model::Extern_Model { - explicit TableImpl_Model(cstring name) : Extern_Model(name), size("size") {} + explicit TableImpl_Model(cstring name) : Extern_Model(name), size("size"_cs) {} ::Model::Elem size; }; struct CounterArray_Model : public ::Model::Extern_Model { CounterArray_Model() - : Extern_Model("CounterArray"), - increment("increment"), - add("add"), - max_index("max_index"), - sparse("sparse") {} + : Extern_Model("CounterArray"_cs), + increment("increment"_cs), + add("add"_cs), + max_index("max_index"_cs), + sparse("sparse"_cs) {} ::Model::Elem increment; ::Model::Elem add; ::Model::Elem max_index; @@ -48,14 +50,14 @@ enum ModelArchitecture { }; struct Xdp_Model : public ::Model::Elem { - Xdp_Model() : Elem("xdp"), parser("p"), switch_("s"), deparser("d") {} + Xdp_Model() : Elem("xdp"_cs), parser("p"_cs), switch_("s"_cs), deparser("d"_cs) {} ::Model::Elem parser; ::Model::Elem switch_; ::Model::Elem deparser; }; struct Filter_Model : public ::Model::Elem { - Filter_Model() : Elem("ebpf_filter"), parser("prs"), filter("filt") {} + Filter_Model() : Elem("ebpf_filter"_cs), parser("prs"_cs), filter("filt"_cs) {} ::Model::Elem parser; ::Model::Elem filter; }; @@ -65,16 +67,16 @@ class EBPFModel : public ::Model::Model { protected: EBPFModel() : counterArray(), - array_table("array_table"), - hash_table("hash_table"), - tableImplProperty("implementation"), - CPacketName("skb"), - packet("packet", P4::P4CoreLibrary::instance().packetIn, 0), + array_table("array_table"_cs), + hash_table("hash_table"_cs), + tableImplProperty("implementation"_cs), + CPacketName("skb"_cs), + packet("packet"_cs, P4::P4CoreLibrary::instance().packetIn, 0), arch(EbpfFilter), filter(), xdp(), - counterIndexType("u32"), - counterValueType("u32") {} + counterIndexType("u32"_cs), + counterValueType("u32"_cs) {} public: static EBPFModel instance; diff --git a/backends/ebpf/ebpfOptions.cpp b/backends/ebpf/ebpfOptions.cpp index 315fbb2160..fc96635a32 100644 --- a/backends/ebpf/ebpfOptions.cpp +++ b/backends/ebpf/ebpfOptions.cpp @@ -23,7 +23,7 @@ EbpfOptions::EbpfOptions() { registerOption( "-o", "outfile", [this](const char *arg) { - outputFile = arg; + outputFile = cstring(arg); return true; }, "Write output to outfile"); @@ -42,7 +42,7 @@ EbpfOptions::EbpfOptions() { "--fromJSON", "file", [this](const char *arg) { loadIRFromJson = true; - file = arg; + file = cstring(arg); return true; }, "Use IR representation from JsonFile dumped previously," diff --git a/backends/ebpf/ebpfParser.cpp b/backends/ebpf/ebpfParser.cpp index 34297002c3..26bdb52a18 100644 --- a/backends/ebpf/ebpfParser.cpp +++ b/backends/ebpf/ebpfParser.cpp @@ -388,7 +388,7 @@ void StateTranslationVisitor::compileExtractField(const IR::Expression *expr, if (expr->is() && expr->to()->expr->is() && isPointerVariable( expr->to()->expr->to()->path->name.name)) { - exprStr = exprStr.replace(".", "->"); + exprStr = exprStr.replace("."_cs, "->"_cs); } cstring tmp = Util::printf_format("(unsigned long long) %s.%s", exprStr, fieldName); diff --git a/backends/ebpf/ebpfProgram.cpp b/backends/ebpf/ebpfProgram.cpp index 356efb2299..a70883dab3 100644 --- a/backends/ebpf/ebpfProgram.cpp +++ b/backends/ebpf/ebpfProgram.cpp @@ -105,11 +105,11 @@ void EBPFProgram::emitC(CodeBuilder *builder, cstring header) { builder->emitIndent(); // Use different section name for XDP - this is used by the runtime test framework. if (model.arch == ModelArchitecture::XdpSwitch) - builder->target->emitCodeSection(builder, "xdp"); + builder->target->emitCodeSection(builder, "xdp"_cs); else - builder->target->emitCodeSection(builder, "prog"); + builder->target->emitCodeSection(builder, "prog"_cs); builder->emitIndent(); - builder->target->emitMain(builder, functionName, model.CPacketName.str()); + builder->target->emitMain(builder, functionName, model.CPacketName.toString()); builder->blockStart(); emitHeaderInstances(builder); @@ -280,14 +280,14 @@ void EBPFProgram::emitLocalVariables(CodeBuilder *builder) { builder->emitIndent(); builder->appendFormat("void* %s = %s;", packetStartVar.c_str(), - builder->target->dataOffset(model.CPacketName.str()).c_str()); + builder->target->dataOffset(model.CPacketName.toString()).c_str()); builder->newline(); builder->emitIndent(); builder->appendFormat("u8* %s = %s;", headerStartVar.c_str(), packetStartVar.c_str()); builder->newline(); builder->emitIndent(); builder->appendFormat("void* %s = %s;", packetEndVar.c_str(), - builder->target->dataEnd(model.CPacketName.str()).c_str()); + builder->target->dataEnd(model.CPacketName.toString()).c_str()); builder->newline(); if (model.arch == ModelArchitecture::EbpfFilter) { @@ -315,7 +315,7 @@ void EBPFProgram::emitLocalVariables(CodeBuilder *builder) { builder->emitIndent(); builder->appendFormat("u32 %s = %s", lengthVar.c_str(), - builder->target->dataLength(model.CPacketName.str()).c_str()); + builder->target->dataLength(model.CPacketName.toString()).c_str()); builder->endOfStatement(true); } @@ -351,14 +351,14 @@ void EBPFProgram::emitPipeline(CodeBuilder *builder) { } bool EBPFProgram::isLibraryMethod(cstring methodName) { - static std::set DEFAULT_METHODS = {"static_assert", "verify"}; + static std::set DEFAULT_METHODS = {"static_assert"_cs, "verify"_cs}; if (DEFAULT_METHODS.find(methodName) != DEFAULT_METHODS.end() && options.target != "xdp") { return true; } static std::set XDP_METHODS = { - "ebpf_ipv4_checksum", "csum_replace2", "csum_replace4", - "BPF_PERF_EVENT_OUTPUT", "BPF_KTIME_GET_NS", + "ebpf_ipv4_checksum"_cs, "csum_replace2"_cs, "csum_replace4"_cs, + "BPF_PERF_EVENT_OUTPUT"_cs, "BPF_KTIME_GET_NS"_cs, }; return XDP_METHODS.find(methodName) != XDP_METHODS.end(); } diff --git a/backends/ebpf/ebpfProgram.h b/backends/ebpf/ebpfProgram.h index b354ab0282..385f3d412e 100644 --- a/backends/ebpf/ebpfProgram.h +++ b/backends/ebpf/ebpfProgram.h @@ -57,8 +57,8 @@ class EBPFProgram : public EBPFObject { cstring zeroKey, functionName, errorVar; cstring packetStartVar, packetEndVar, byteVar; cstring errorEnum; - cstring license = "GPL"; /// TODO: this should be a compiler option probably - cstring arrayIndexType = "u32"; + cstring license = "GPL"_cs; /// TODO: this should be a compiler option probably + cstring arrayIndexType = "u32"_cs; virtual bool build(); /// return 'true' on success @@ -75,17 +75,17 @@ class EBPFProgram : public EBPFObject { model(EBPFModel::instance), deparser(nullptr) { // NB: offsetVar not used in eBPF backend - uBPF and TC only - offsetVar = EBPFModel::reserved("packetOffsetInBits"); - zeroKey = EBPFModel::reserved("zero"); - functionName = EBPFModel::reserved("filter"); - errorVar = EBPFModel::reserved("errorCode"); - packetStartVar = EBPFModel::reserved("packetStart"); - packetEndVar = EBPFModel::reserved("packetEnd"); - headerStartVar = EBPFModel::reserved("headerStart"); - lengthVar = EBPFModel::reserved("pkt_len"); - byteVar = EBPFModel::reserved("byte"); - endLabel = EBPFModel::reserved("end"); - errorEnum = EBPFModel::reserved("errorCodes"); + offsetVar = EBPFModel::reserved("packetOffsetInBits"_cs); + zeroKey = EBPFModel::reserved("zero"_cs); + functionName = EBPFModel::reserved("filter"_cs); + errorVar = EBPFModel::reserved("errorCode"_cs); + packetStartVar = EBPFModel::reserved("packetStart"_cs); + packetEndVar = EBPFModel::reserved("packetEnd"_cs); + headerStartVar = EBPFModel::reserved("headerStart"_cs); + lengthVar = EBPFModel::reserved("pkt_len"_cs); + byteVar = EBPFModel::reserved("byte"_cs); + endLabel = EBPFModel::reserved("end"_cs); + errorEnum = EBPFModel::reserved("errorCodes"_cs); } protected: diff --git a/backends/ebpf/ebpfTable.cpp b/backends/ebpf/ebpfTable.cpp index fb4ed36adb..2c0c866f4c 100644 --- a/backends/ebpf/ebpfTable.cpp +++ b/backends/ebpf/ebpfTable.cpp @@ -356,7 +356,7 @@ void EBPFTable::emitTernaryInstance(CodeBuilder *builder) { "struct " + valueTypeName + "_mask", size); builder->target->emitMapInMapDecl(builder, instanceName + "_tuple", TableHash, "struct " + keyTypeName, "struct " + valueTypeName, size, - instanceName + "_tuples_map", TableArray, "__u32", size); + instanceName + "_tuples_map", TableArray, "__u32"_cs, size); } void EBPFTable::emitInstance(CodeBuilder *builder) { @@ -471,13 +471,13 @@ void EBPFTable::emitKey(CodeBuilder *builder, cstring keyName) { memcpy = !EBPFScalarType::generatesScalar(width); if (width <= 8) { - swap = ""; // single byte, nothing to swap + swap = cstring::empty; // single byte, nothing to swap } else if (width <= 16) { - swap = "bpf_htons"; + swap = "bpf_htons"_cs; } else if (width <= 32) { - swap = "bpf_htonl"; + swap = "bpf_htonl"_cs; } else if (width <= 64) { - swap = "bpf_htonll"; + swap = "bpf_htonll"_cs; } else { // The code works with fields wider than 64 bits for PSA architecture. It is shared // with filter model, so should work but has not been tested. Error message is @@ -603,10 +603,10 @@ void EBPFTable::emitInitializer(CodeBuilder *builder) { BUG_CHECK(ac != nullptr, "%1%: expected an action call", mce); auto action = ac->action; cstring name = EBPFObject::externalName(action); - cstring fd = "tableFileDescriptor"; + cstring fd = "tableFileDescriptor"_cs; cstring defaultTable = defaultActionMapName; - cstring value = "value"; - cstring key = "key"; + cstring value = "value"_cs; + cstring key = "key"_cs; builder->emitIndent(); builder->blockStart(); @@ -744,7 +744,7 @@ void EBPFTable::emitLookup(CodeBuilder *builder, cstring key, cstring value) { builder->newline(); builder->emitIndent(); builder->appendFormat("struct %s_mask *", valueTypeName); - builder->target->emitTableLookup(builder, instanceName + "_prefixes", "head", "val"); + builder->target->emitTableLookup(builder, instanceName + "_prefixes", "head"_cs, "val"_cs); builder->endOfStatement(true); builder->emitIndent(); builder->append("if (val && val->has_next != 0) "); @@ -759,7 +759,7 @@ void EBPFTable::emitLookup(CodeBuilder *builder, cstring key, cstring value) { builder->blockStart(); builder->emitIndent(); builder->appendFormat("struct %s_mask *", valueTypeName); - builder->target->emitTableLookup(builder, instanceName + "_prefixes", "next", "v"); + builder->target->emitTableLookup(builder, instanceName + "_prefixes", "next"_cs, "v"_cs); builder->endOfStatement(true); builder->emitIndent(); builder->append("if (!v) "); @@ -769,7 +769,7 @@ void EBPFTable::emitLookup(CodeBuilder *builder, cstring key, cstring value) { builder->appendLine("break;"); builder->blockEnd(true); builder->emitIndent(); - cstring new_key = "k"; + cstring new_key = "k"_cs; builder->appendFormat("struct %s %s = {};", keyTypeName, new_key); builder->newline(); builder->emitIndent(); @@ -799,7 +799,8 @@ void EBPFTable::emitLookup(CodeBuilder *builder, cstring key, cstring value) { builder->newline(); builder->emitIndent(); builder->append("struct bpf_elf_map *"); - builder->target->emitTableLookup(builder, instanceName + "_tuples_map", "tuple_id", "tuple"); + builder->target->emitTableLookup(builder, instanceName + "_tuples_map", "tuple_id"_cs, + "tuple"_cs); builder->endOfStatement(true); builder->emitIndent(); builder->append("if (!tuple) "); @@ -855,7 +856,7 @@ void EBPFTable::emitLookup(CodeBuilder *builder, cstring key, cstring value) { cstring EBPFTable::p4ActionToActionIDName(const IR::P4Action *action) const { if (action->name.originalName == P4::P4CoreLibrary::instance().noAction.name) { // NoAction always gets ID=0. - return "0"; + return "0"_cs; } cstring actionName = EBPFObject::externalName(action); @@ -984,7 +985,7 @@ void EBPFCounterTable::emitCounterIncrement(CodeBuilder *builder, builder->appendLine("else"); builder->increaseIndent(); builder->emitIndent(); - builder->target->emitTableUpdate(builder, dataMapName, keyName, "init_val"); + builder->target->emitTableUpdate(builder, dataMapName, keyName, "init_val"_cs); builder->newline(); builder->decreaseIndent(); } @@ -1047,7 +1048,7 @@ void EBPFCounterTable::emitCounterAdd(CodeBuilder *builder, builder->appendLine("else"); builder->increaseIndent(); builder->emitIndent(); - builder->target->emitTableUpdate(builder, dataMapName, keyName, "init_val"); + builder->target->emitTableUpdate(builder, dataMapName, keyName, "init_val"_cs); builder->newline(); builder->decreaseIndent(); } @@ -1082,7 +1083,7 @@ EBPFValueSet::EBPFValueSet(const EBPFProgram *program, const IR::P4ValueSet *p4v cstring instanceName, CodeGenInspector *codeGen) : EBPFTableBase(program, instanceName, codeGen), size(0), pvs(p4vs) { CHECK_NULL(pvs); - valueTypeName = "u32"; // map value is not used, so its type can be anything + valueTypeName = "u32"_cs; // map value is not used, so its type can be anything // validate size if (pvs->size->is()) { @@ -1138,7 +1139,7 @@ void EBPFValueSet::emitTypes(CodeBuilder *builder) { }; if (auto tb = elemType->to()) { - cstring name = "field0"; + cstring name = "field0"_cs; fieldEmitter(tb, name); fieldNames.emplace_back(std::make_pair(name, tb)); } else if (auto tuple = elemType->to()) { @@ -1212,7 +1213,7 @@ void EBPFValueSet::emitKeyInitializer(CodeBuilder *builder, const IR::SelectExpr } void EBPFValueSet::emitLookup(CodeBuilder *builder) { - builder->target->emitTableLookup(builder, instanceName, keyVarName, ""); + builder->target->emitTableLookup(builder, instanceName, keyVarName, cstring::empty); } } // namespace EBPF diff --git a/backends/ebpf/ebpfTable.h b/backends/ebpf/ebpfTable.h index 8dd3108272..8bfaa93e45 100644 --- a/backends/ebpf/ebpfTable.h +++ b/backends/ebpf/ebpfTable.h @@ -97,7 +97,7 @@ class EBPFTable : public EBPFTableBase { /// Use 1024 by default. /// TODO: make it configurable using compiler options. size_t size = 1024; - const cstring prefixFieldName = "prefixlen"; + const cstring prefixFieldName = "prefixlen"_cs; EBPFTable(const EBPFProgram *program, const IR::TableBlock *table, CodeGenInspector *codeGen); EBPFTable(const EBPFProgram *program, CodeGenInspector *codeGen, cstring name); diff --git a/backends/ebpf/ebpfType.cpp b/backends/ebpf/ebpfType.cpp index 9814f46d7c..4305d74a06 100644 --- a/backends/ebpf/ebpfType.cpp +++ b/backends/ebpf/ebpfType.cpp @@ -168,11 +168,11 @@ void EBPFScalarType::emitInitializer(CodeBuilder *builder) { EBPFStructType::EBPFStructType(const IR::Type_StructLike *strct) : EBPFType(strct) { if (strct->is()) - kind = "struct"; + kind = "struct"_cs; else if (strct->is()) - kind = "struct"; + kind = "struct"_cs; else if (strct->is()) - kind = "union"; + kind = "union"_cs; else BUG("Unexpected struct type %1%", strct); name = strct->name.name; @@ -216,7 +216,8 @@ void EBPFStructType::emitInitializer(CodeBuilder *builder) { } } else if (type->is()) { builder->emitIndent(); - builder->appendLine(".ebpf_valid = 0"); + builder->append(".ebpf_valid = 0"); + builder->newline(); } else { BUG("Unexpected type %1%", type); } @@ -251,7 +252,7 @@ void EBPFStructType::emit(CodeBuilder *builder) { builder->emitIndent(); auto type = EBPFTypeFactory::instance->create(IR::Type_Boolean::get()); if (type != nullptr) { - type->declare(builder, "ebpf_valid", false); + type->declare(builder, "ebpf_valid"_cs, false); builder->endOfStatement(true); } } @@ -322,7 +323,8 @@ void EBPFEnumType::emit(EBPF::CodeBuilder *builder) { builder->blockStart(); for (auto m : et->members) { builder->append(m->name); - builder->appendLine(","); + builder->append(","); + builder->newline(); } builder->blockEnd(true); } @@ -348,7 +350,8 @@ void EBPFErrorType::emit(EBPF::CodeBuilder *builder) { builder->blockStart(); for (auto m : et->members) { builder->append(m->name); - builder->appendLine(","); + builder->append(","); + builder->newline(); } builder->blockEnd(true); } diff --git a/backends/ebpf/midend.cpp b/backends/ebpf/midend.cpp index b5b56f2dcb..cef8eee8a8 100644 --- a/backends/ebpf/midend.cpp +++ b/backends/ebpf/midend.cpp @@ -53,6 +53,8 @@ limitations under the License. namespace EBPF { +using namespace P4::literals; + class EnumOn32Bits : public P4::ChooseEnumRepresentation { bool convert(const IR::Type_Enum *type) const override { if (type->srcInfo.isValid()) { @@ -111,14 +113,14 @@ const IR::ToplevelBlock *MidEnd::run(EbpfOptions &options, const IR::P4Program * if (options.arch == "psa") { midEnd.addPasses({new P4::ValidateTableProperties( - {"size", "psa_direct_counter", "psa_direct_meter", "psa_empty_group_action", - "psa_implementation"})}); + {"size"_cs, "psa_direct_counter"_cs, "psa_direct_meter"_cs, + "psa_empty_group_action"_cs, "psa_implementation"_cs})}); } else { - midEnd.addPasses({new P4::ValidateTableProperties({"size", "implementation"})}); + midEnd.addPasses({new P4::ValidateTableProperties({"size"_cs, "implementation"_cs})}); } if (options.listMidendPasses) { - midEnd.listPasses(*outStream, "\n"); + midEnd.listPasses(*outStream, cstring::newline); *outStream << std::endl; } if (options.excludeMidendPasses) { diff --git a/backends/ebpf/p4c-ebpf.cpp b/backends/ebpf/p4c-ebpf.cpp index 83ce91b5e8..1e56271fbe 100644 --- a/backends/ebpf/p4c-ebpf.cpp +++ b/backends/ebpf/p4c-ebpf.cpp @@ -94,7 +94,7 @@ int main(int argc, char *const argv[]) { AutoCompileContext autoEbpfContext(new EbpfContext); auto &options = EbpfContext::get().options(); - options.compilerVersion = P4C_EBPF_VERSION_STRING; + options.compilerVersion = cstring(P4C_EBPF_VERSION_STRING); if (options.process(argc, argv) != nullptr) { if (options.loadIRFromJson == false) options.setInputFile(); diff --git a/backends/ebpf/psa/ebpfPipeline.cpp b/backends/ebpf/psa/ebpfPipeline.cpp index ce12f25553..f66546875b 100644 --- a/backends/ebpf/psa/ebpfPipeline.cpp +++ b/backends/ebpf/psa/ebpfPipeline.cpp @@ -54,14 +54,14 @@ void EBPFPipeline::emitLocalVariables(CodeBuilder *builder) { builder->newline(); builder->emitIndent(); builder->appendFormat("void* %s = %s;", packetStartVar.c_str(), - builder->target->dataOffset(model.CPacketName.str()).c_str()); + builder->target->dataOffset(model.CPacketName.toString()).c_str()); builder->newline(); builder->emitIndent(); builder->appendFormat("u8* %s = %s;", headerStartVar.c_str(), packetStartVar.c_str()); builder->newline(); builder->emitIndent(); builder->appendFormat("void* %s = %s;", packetEndVar.c_str(), - builder->target->dataEnd(model.CPacketName.str()).c_str()); + builder->target->dataEnd(model.CPacketName.toString()).c_str()); builder->newline(); builder->emitIndent(); builder->appendFormat("u32 %s = 0;", zeroKey.c_str()); @@ -123,7 +123,7 @@ void EBPFPipeline::emitHeaderInstances(CodeBuilder *builder) { void EBPFPipeline::emitCPUMAPLookup(CodeBuilder *builder) { builder->emitIndent(); - builder->target->emitTableLookup(builder, "hdr_md_cpumap", zeroKey.c_str(), "hdrMd"); + builder->target->emitTableLookup(builder, "hdr_md_cpumap"_cs, zeroKey, "hdrMd"_cs); builder->endOfStatement(true); } @@ -391,7 +391,7 @@ void EBPFEgressPipeline::emitPSAControlOutputMetadata(CodeBuilder *builder) { void EBPFEgressPipeline::emitCPUMAPLookup(CodeBuilder *builder) { builder->emitIndent(); - builder->target->emitTableLookup(builder, "hdr_md_cpumap", oneKey.c_str(), "hdrMd"); + builder->target->emitTableLookup(builder, "hdr_md_cpumap"_cs, oneKey, "hdrMd"_cs); builder->endOfStatement(true); } @@ -401,7 +401,7 @@ void EBPFEgressPipeline::emit(CodeBuilder *builder) { builder->newline(); progTarget->emitCodeSection(builder, sectionName); builder->emitIndent(); - progTarget->emitMain(builder, functionName, model.CPacketName.str()); + progTarget->emitMain(builder, functionName, model.CPacketName.toString()); builder->spc(); builder->blockStart(); @@ -773,7 +773,7 @@ void TCTrafficManagerForXDP::emit(CodeBuilder *builder) { cstring msgStr; progTarget->emitCodeSection(builder, sectionName); builder->emitIndent(); - progTarget->emitMain(builder, functionName, model.CPacketName.str()); + progTarget->emitMain(builder, functionName, model.CPacketName.toString()); builder->spc(); builder->blockStart(); emitGlobalMetadataInitializer(builder); @@ -855,8 +855,8 @@ void TCTrafficManagerForXDP::emitReadXDP2TCMetadataFromHead(CodeBuilder *builder void TCTrafficManagerForXDP::emitReadXDP2TCMetadataFromCPUMAP(CodeBuilder *builder) { builder->emitIndent(); - builder->target->emitTableLookup(builder, "xdp2tc_shared_map", this->zeroKey.c_str(), - "struct xdp2tc_metadata *md"); + builder->target->emitTableLookup(builder, "xdp2tc_shared_map"_cs, this->zeroKey, + "struct xdp2tc_metadata *md"_cs); builder->endOfStatement(true); builder->emitIndent(); builder->append("if (!md) "); diff --git a/backends/ebpf/psa/ebpfPipeline.h b/backends/ebpf/psa/ebpfPipeline.h index 85b38de234..31d23629bf 100644 --- a/backends/ebpf/psa/ebpfPipeline.h +++ b/backends/ebpf/psa/ebpfPipeline.h @@ -61,21 +61,21 @@ class EBPFPipeline : public EBPFProgram { control(nullptr), deparser(nullptr) { sectionName = "classifier/" + name; - functionName = name.replace("-", "_") + "_func"; - errorEnum = "ParserError_t"; - packetStartVar = cstring("pkt"); - headerStartVar = cstring("hdr_start"); - contextVar = cstring("skb"); - lengthVar = cstring("pkt_len"); - endLabel = cstring("deparser"); - timestampVar = cstring("tstamp"); - ifindexVar = cstring("skb->ifindex"); - compilerGlobalMetadata = cstring("compiler_meta__"); - packetPathVar = compilerGlobalMetadata + cstring("->packet_path"); - pktInstanceVar = compilerGlobalMetadata + cstring("->instance"); - priorityVar = cstring("skb->priority"); - oneKey = EBPFModel::reserved("one"); - inputPortVar = cstring("ebpf_input_port"); + functionName = name.replace('-', '_') + "_func"; + errorEnum = "ParserError_t"_cs; + packetStartVar = "pkt"_cs; + headerStartVar = "hdr_start"_cs; + contextVar = "skb"_cs; + lengthVar = "pkt_len"_cs; + endLabel = "deparser"_cs; + timestampVar = "tstamp"_cs; + ifindexVar = "skb->ifindex"_cs; + compilerGlobalMetadata = "compiler_meta__"_cs; + packetPathVar = compilerGlobalMetadata + "->packet_path"_cs; + pktInstanceVar = compilerGlobalMetadata + "->instance"_cs; + priorityVar = "skb->priority"_cs; + oneKey = EBPFModel::reserved("one"_cs); + inputPortVar = "ebpf_input_port"_cs; progTarget = new KernelSamplesTarget(options.emitTraceMessages); } @@ -85,19 +85,19 @@ class EBPFPipeline : public EBPFProgram { virtual cstring dropReturnCode() { if (sectionName.startsWith("xdp")) { - return "XDP_DROP"; + return "XDP_DROP"_cs; } // TC is the default hookpoint - return "TC_ACT_SHOT"; + return "TC_ACT_SHOT"_cs; } virtual cstring forwardReturnCode() { if (sectionName.startsWith("xdp")) { - return "XDP_PASS"; + return "XDP_PASS"_cs; } // TC is the default hookpoint - return "TC_ACT_OK"; + return "TC_ACT_OK"_cs; } virtual void emit(CodeBuilder *builder) = 0; @@ -231,8 +231,8 @@ class XDPIngressPipeline : public EBPFIngressPipeline { P4::TypeMap *typeMap) : EBPFIngressPipeline(name, options, refMap, typeMap) { sectionName = "xdp_ingress/" + name; - ifindexVar = cstring("skb->ingress_ifindex"); - packetPathVar = cstring(compilerGlobalMetadata + "->packet_path"); + ifindexVar = "skb->ingress_ifindex"_cs; + packetPathVar = compilerGlobalMetadata + "->packet_path"_cs; progTarget = new XdpTarget(options.emitTraceMessages); } @@ -248,11 +248,11 @@ class XDPEgressPipeline : public EBPFEgressPipeline { P4::TypeMap *typeMap) : EBPFEgressPipeline(name, options, refMap, typeMap) { sectionName = "xdp_devmap/" + name; - ifindexVar = cstring("skb->egress_ifindex"); + ifindexVar = "skb->egress_ifindex"_cs; // we do not support packet path, instance & priority in the XDP egress. - packetPathVar = cstring("0"); - pktInstanceVar = cstring("0"); - priorityVar = cstring("0"); + packetPathVar = "0"_cs; + pktInstanceVar = "0"_cs; + priorityVar = "0"_cs; progTarget = new XdpTarget(options.emitTraceMessages); } diff --git a/backends/ebpf/psa/ebpfPsaDeparser.cpp b/backends/ebpf/psa/ebpfPsaDeparser.cpp index 4f41f9a6db..4c6821e667 100644 --- a/backends/ebpf/psa/ebpfPsaDeparser.cpp +++ b/backends/ebpf/psa/ebpfPsaDeparser.cpp @@ -200,8 +200,8 @@ void XDPIngressDeparserPSA::emitPreDeparser(CodeBuilder *builder) { // resubmitted or multicasted because this check is not at the end of deparser. cstring conditionSendToTC = "if (%s->clone || %s->multicast_group != 0 ||" - " (!%s->drop && %s->egress_port == 0 && !%s->resubmit && %s->multicast_group == 0)) "; - conditionSendToTC = conditionSendToTC.replace("%s", istd->name.name); + " (!%s->drop && %s->egress_port == 0 && !%s->resubmit && %s->multicast_group == 0)) "_cs; + conditionSendToTC = conditionSendToTC.replace("%s"_cs, istd->name); builder->append(conditionSendToTC); builder->blockStart(); builder->emitIndent(); @@ -253,8 +253,8 @@ void XDPIngressDeparserPSA::emitPreDeparser(CodeBuilder *builder) { "&xdp2tc_md, sizeof(struct xdp2tc_metadata));"); } else if (program->options.xdp2tcMode == XDP2TC_CPUMAP) { builder->emitIndent(); - builder->target->emitTableUpdate(builder, "xdp2tc_shared_map", - this->program->zeroKey.c_str(), "xdp2tc_md"); + builder->target->emitTableUpdate(builder, "xdp2tc_shared_map"_cs, this->program->zeroKey, + "xdp2tc_md"_cs); builder->newline(); } builder->target->emitTraceMessage(builder, "Sending packet up to TC for cloning or to kernel"); diff --git a/backends/ebpf/psa/ebpfPsaGen.cpp b/backends/ebpf/psa/ebpfPsaGen.cpp index 2d9b0fe2c4..cccba821cf 100644 --- a/backends/ebpf/psa/ebpfPsaGen.cpp +++ b/backends/ebpf/psa/ebpfPsaGen.cpp @@ -140,13 +140,13 @@ void PSAEbpfGenerator::emitGlobalHeadersMetadata(CodeBuilder *builder) const { builder->blockStart(); builder->emitIndent(); - ingress->parser->headerType->declare(builder, "cpumap_hdr", false); + ingress->parser->headerType->declare(builder, "cpumap_hdr"_cs, false); builder->endOfStatement(true); builder->emitIndent(); auto user_md_type = ingress->typeMap->getType(ingress->control->user_metadata); BUG_CHECK(user_md_type != nullptr, "cannot declare user metadata"); auto userMetadataType = EBPFTypeFactory::instance->create(user_md_type); - userMetadataType->declare(builder, "cpumap_usermeta", false); + userMetadataType->declare(builder, "cpumap_usermeta"_cs, false); builder->endOfStatement(true); // Additional field to avoid compiler errors when both headers and user_metadata are empty. @@ -160,12 +160,12 @@ void PSAEbpfGenerator::emitGlobalHeadersMetadata(CodeBuilder *builder) const { } void PSAEbpfGenerator::emitPacketReplicationTables(CodeBuilder *builder) const { - builder->target->emitMapInMapDecl(builder, "clone_session_tbl_inner", TableHash, "elem_t", - "struct element", MaxClones, "clone_session_tbl", TableArray, - "__u32", MaxCloneSessions); - builder->target->emitMapInMapDecl(builder, "multicast_grp_tbl_inner", TableHash, "elem_t", - "struct element", MaxClones, "multicast_grp_tbl", TableArray, - "__u32", MaxCloneSessions); + builder->target->emitMapInMapDecl(builder, "clone_session_tbl_inner"_cs, TableHash, "elem_t"_cs, + "struct element"_cs, MaxClones, "clone_session_tbl"_cs, + TableArray, "__u32"_cs, MaxCloneSessions); + builder->target->emitMapInMapDecl(builder, "multicast_grp_tbl_inner"_cs, TableHash, "elem_t"_cs, + "struct element"_cs, MaxClones, "multicast_grp_tbl"_cs, + TableArray, "__u32"_cs, MaxCloneSessions); } void PSAEbpfGenerator::emitPipelineInstances(CodeBuilder *builder) const { @@ -176,8 +176,8 @@ void PSAEbpfGenerator::emitPipelineInstances(CodeBuilder *builder) const { egress->parser->emitValueSetInstances(builder); egress->control->emitTableInstances(builder); - builder->target->emitTableDecl(builder, "hdr_md_cpumap", TablePerCPUArray, "u32", - "struct hdr_md", 2); + builder->target->emitTableDecl(builder, "hdr_md_cpumap"_cs, TablePerCPUArray, "u32"_cs, + "struct hdr_md"_cs, 2); } void PSAEbpfGenerator::emitInitializer(CodeBuilder *builder) const { @@ -228,13 +228,13 @@ void PSAEbpfGenerator::emitHelperFunctions(CodeBuilder *builder) const { " next_id = elem->next_id;\n" " }\n" " return 0;\n" - "}"; + "}"_cs; if (options.emitTraceMessages) { forEachFunc = forEachFunc.replace( - "%trace_msg_no_elements%", - " bpf_trace_message(\"do_for_each: No elements found in list\\n\");\n"); + "%trace_msg_no_elements%"_cs, + " bpf_trace_message(\"do_for_each: No elements found in list\\n\");\n"_cs); } else { - forEachFunc = forEachFunc.replace("%trace_msg_no_elements%", ""); + forEachFunc = forEachFunc.replace("%trace_msg_no_elements%"_cs, ""_cs); } builder->appendLine(forEachFunc); builder->newline(); @@ -247,14 +247,14 @@ void PSAEbpfGenerator::emitHelperFunctions(CodeBuilder *builder) const { " struct clone_session_entry *entry = (struct clone_session_entry *) data;\n" "%trace_msg_redirect%" " bpf_clone_redirect(skb, entry->egress_port, 0);\n" - "}"; + "}"_cs; if (options.emitTraceMessages) { cloneFunction = cloneFunction.replace( cstring("%trace_msg_redirect%"), - " bpf_trace_message(\"do_clone: cloning pkt, egress_port=%d, cos=%d\\n\", " - "entry->egress_port, entry->class_of_service);\n"); + " bpf_trace_message(\"do_clone: cloning pkt, egress_port=%d, cos=%d\\n\", "_cs + "entry->egress_port, entry->class_of_service);\n"_cs); } else { - cloneFunction = cloneFunction.replace(cstring("%trace_msg_redirect%"), ""); + cloneFunction = cloneFunction.replace("%trace_msg_redirect%"_cs, ""_cs); } builder->appendLine(cloneFunction); builder->newline(); @@ -281,27 +281,27 @@ void PSAEbpfGenerator::emitHelperFunctions(CodeBuilder *builder) const { " }\n" "%trace_msg_cloning_done%" " return 0;\n" - " }"; + " }"_cs; if (options.emitTraceMessages) { pktClonesFunc = pktClonesFunc.replace( - cstring("%trace_msg_clone_requested%"), + "%trace_msg_clone_requested%"_cs, " bpf_trace_message(\"Clone#%d: pkt clone requested, session=%d\\n\", " - "caller_id, session_id);\n"); + "caller_id, session_id);\n"_cs); pktClonesFunc = pktClonesFunc.replace( - cstring("%trace_msg_clone_failed%"), - " bpf_trace_message(\"Clone#%d: failed to clone packet\", caller_id);\n"); + "%trace_msg_clone_failed%"_cs, + " bpf_trace_message(\"Clone#%d: failed to clone packet\", caller_id);\n"_cs); pktClonesFunc = - pktClonesFunc.replace(cstring("%trace_msg_no_session%"), + pktClonesFunc.replace("%trace_msg_no_session%"_cs, " bpf_trace_message(\"Clone#%d: session_id not found, " - "no clones created\\n\", caller_id);\n"); + "no clones created\\n\", caller_id);\n"_cs); pktClonesFunc = pktClonesFunc.replace( - cstring("%trace_msg_cloning_done%"), - " bpf_trace_message(\"Clone#%d: packet cloning finished\\n\", caller_id);\n"); + "%trace_msg_cloning_done%"_cs, + " bpf_trace_message(\"Clone#%d: packet cloning finished\\n\", caller_id);\n"_cs); } else { - pktClonesFunc = pktClonesFunc.replace(cstring("%trace_msg_clone_requested%"), ""); - pktClonesFunc = pktClonesFunc.replace(cstring("%trace_msg_clone_failed%"), ""); - pktClonesFunc = pktClonesFunc.replace(cstring("%trace_msg_no_session%"), ""); - pktClonesFunc = pktClonesFunc.replace(cstring("%trace_msg_cloning_done%"), ""); + pktClonesFunc = pktClonesFunc.replace("%trace_msg_clone_requested%"_cs, cstring::empty); + pktClonesFunc = pktClonesFunc.replace("%trace_msg_clone_failed%"_cs, cstring::empty); + pktClonesFunc = pktClonesFunc.replace("%trace_msg_no_session%"_cs, cstring::empty); + pktClonesFunc = pktClonesFunc.replace("%trace_msg_cloning_done%"_cs, cstring::empty); } builder->appendLine(pktClonesFunc); @@ -330,14 +330,14 @@ void PSAEbpfGenerator::emitCRC32LookupTableTypes(CodeBuilder *builder) const { } void PSAEbpfGenerator::emitCRC32LookupTableInstance(CodeBuilder *builder) const { - builder->target->emitTableDecl(builder, cstring("crc_lookup_tbl"), TableArray, "u32", + builder->target->emitTableDecl(builder, cstring("crc_lookup_tbl"), TableArray, "u32"_cs, cstring("struct lookup_tbl_val"), 1); } void PSAEbpfGenerator::emitCRC32LookupTableInitializer(CodeBuilder *builder) const { - cstring keyName = "lookup_tbl_key"; - cstring valueName = "lookup_tbl_value"; - cstring instanceName = "crc_lookup_tbl"; + cstring keyName = "lookup_tbl_key"_cs; + cstring valueName = "lookup_tbl_value"_cs; + cstring instanceName = "crc_lookup_tbl"_cs; builder->emitIndent(); builder->appendFormat("u32 %s = 0", keyName.c_str()); @@ -476,7 +476,8 @@ void PSAArchTC::emitInstances(CodeBuilder *builder) const { builder->appendLine("REGISTER_START()"); if (options.xdp2tcMode == XDP2TC_CPUMAP) { - builder->target->emitTableDecl(builder, "xdp2tc_cpumap", TablePerCPUArray, "u32", "u16", 1); + builder->target->emitTableDecl(builder, "xdp2tc_cpumap"_cs, TablePerCPUArray, "u32"_cs, + "u16"_cs, 1); } emitPacketReplicationTables(builder); @@ -547,11 +548,11 @@ void PSAArchXDP::emitInstances(CodeBuilder *builder) const { tcEgressForXDP->control->tables.insert(egress->control->tables.begin(), egress->control->tables.end()); - builder->target->emitTableDecl(builder, "xdp2tc_shared_map", TablePerCPUArray, "u32", - "struct xdp2tc_metadata", 1); + builder->target->emitTableDecl(builder, "xdp2tc_shared_map"_cs, TablePerCPUArray, "u32"_cs, + "struct xdp2tc_metadata"_cs, 1); - builder->target->emitTableDecl(builder, "tx_port", TableDevmap, "u32", "struct bpf_devmap_val", - egressDevmapSize); + builder->target->emitTableDecl(builder, "tx_port"_cs, TableDevmap, "u32"_cs, + "struct bpf_devmap_val"_cs, egressDevmapSize); emitCRC32LookupTableInstance(builder); @@ -617,30 +618,30 @@ const PSAEbpfGenerator *ConvertToEbpfPSA::build(const IR::ToplevelBlock *tlb) { /* * INGRESS */ - auto ingress = tlb->getMain()->getParameterValue("ingress")->to(); - auto ingressParser = ingress->getParameterValue("ip"); + auto ingress = tlb->getMain()->getParameterValue("ingress"_cs)->to(); + auto ingressParser = ingress->getParameterValue("ip"_cs); BUG_CHECK(ingressParser != nullptr, "No ingress parser block found"); - auto ingressControl = ingress->getParameterValue("ig"); + auto ingressControl = ingress->getParameterValue("ig"_cs); BUG_CHECK(ingressControl != nullptr, "No ingress control block found"); - auto ingressDeparser = ingress->getParameterValue("id"); + auto ingressDeparser = ingress->getParameterValue("id"_cs); BUG_CHECK(ingressDeparser != nullptr, "No ingress deparser block found"); /* * EGRESS */ - auto egress = tlb->getMain()->getParameterValue("egress")->to(); - auto egressParser = egress->getParameterValue("ep"); + auto egress = tlb->getMain()->getParameterValue("egress"_cs)->to(); + auto egressParser = egress->getParameterValue("ep"_cs); BUG_CHECK(egressParser != nullptr, "No egress parser block found"); - auto egressControl = egress->getParameterValue("eg"); + auto egressControl = egress->getParameterValue("eg"_cs); BUG_CHECK(egressControl != nullptr, "No egress control block found"); - auto egressDeparser = egress->getParameterValue("ed"); + auto egressDeparser = egress->getParameterValue("ed"_cs); BUG_CHECK(egressDeparser != nullptr, "No egress deparser block found"); if (!options.generateToXDP) { auto xdp = new XDPHelpProgram(options); auto ingress_pipeline_converter = new ConvertToEbpfPipeline( - "tc-ingress", TC_INGRESS, options, ingressParser->to(), + "tc-ingress"_cs, TC_INGRESS, options, ingressParser->to(), ingressControl->to(), ingressDeparser->to(), refmap, typemap); ingress->apply(*ingress_pipeline_converter); @@ -648,7 +649,7 @@ const PSAEbpfGenerator *ConvertToEbpfPSA::build(const IR::ToplevelBlock *tlb) { auto tcIngress = ingress_pipeline_converter->getEbpfPipeline(); auto egress_pipeline_converter = new ConvertToEbpfPipeline( - "tc-egress", TC_EGRESS, options, egressParser->to(), + "tc-egress"_cs, TC_EGRESS, options, egressParser->to(), egressControl->to(), egressDeparser->to(), refmap, typemap); egress->apply(*egress_pipeline_converter); @@ -658,7 +659,7 @@ const PSAEbpfGenerator *ConvertToEbpfPSA::build(const IR::ToplevelBlock *tlb) { return new PSAArchTC(options, ebpfTypes, xdp, tcIngress, tcEgress); } else { auto ingress_pipeline_converter = new ConvertToEbpfPipeline( - "xdp-ingress", XDP_INGRESS, options, ingressParser->to(), + "xdp-ingress"_cs, XDP_INGRESS, options, ingressParser->to(), ingressControl->to(), ingressDeparser->to(), refmap, typemap); ingress->apply(*ingress_pipeline_converter); @@ -667,7 +668,7 @@ const PSAEbpfGenerator *ConvertToEbpfPSA::build(const IR::ToplevelBlock *tlb) { BUG_CHECK(xdpIngress != nullptr, "Cannot create xdpIngress block."); auto egress_pipeline_converter = new ConvertToEbpfPipeline( - "xdp-egress", XDP_EGRESS, options, egressParser->to(), + "xdp-egress"_cs, XDP_EGRESS, options, egressParser->to(), egressControl->to(), egressDeparser->to(), refmap, typemap); egress->apply(*egress_pipeline_converter); @@ -676,7 +677,7 @@ const PSAEbpfGenerator *ConvertToEbpfPSA::build(const IR::ToplevelBlock *tlb) { BUG_CHECK(xdpEgress != nullptr, "Cannot create xdpEgress block."); auto tc_trafficmanager_converter = new ConvertToEbpfPipeline( - "tc-ingress", TC_TRAFFIC_MANAGER, options, ingressParser->to(), + "tc-ingress"_cs, TC_TRAFFIC_MANAGER, options, ingressParser->to(), ingressControl->to(), ingressDeparser->to(), refmap, typemap); ingress->apply(*tc_trafficmanager_converter); @@ -684,7 +685,7 @@ const PSAEbpfGenerator *ConvertToEbpfPSA::build(const IR::ToplevelBlock *tlb) { BUG_CHECK(tcTrafficManager != nullptr, "Cannot create tcTrafficManager block."); auto tc_egress_pipeline_converter = new ConvertToEbpfPipeline( - "tc-egress", TC_EGRESS, options, egressParser->to(), + "tc-egress"_cs, TC_EGRESS, options, egressParser->to(), egressControl->to(), egressDeparser->to(), refmap, typemap); egress->apply(*tc_egress_pipeline_converter); diff --git a/backends/ebpf/psa/ebpfPsaTable.cpp b/backends/ebpf/psa/ebpfPsaTable.cpp index e77101579f..2a53fa8824 100644 --- a/backends/ebpf/psa/ebpfPsaTable.cpp +++ b/backends/ebpf/psa/ebpfPsaTable.cpp @@ -70,7 +70,7 @@ class EBPFTablePSADirectCounterPropertyVisitor : public EBPFTablePsaPropertyVisi } void visitTableProperty() { - EBPFTablePsaPropertyVisitor::visitTableProperty("psa_direct_counter"); + EBPFTablePsaPropertyVisitor::visitTableProperty("psa_direct_counter"_cs); } }; @@ -96,7 +96,7 @@ class EBPFTablePSADirectMeterPropertyVisitor : public EBPFTablePsaPropertyVisito } void visitTableProperty() { - EBPFTablePsaPropertyVisitor::visitTableProperty("psa_direct_meter"); + EBPFTablePsaPropertyVisitor::visitTableProperty("psa_direct_meter"_cs); } }; @@ -133,7 +133,7 @@ class EBPFTablePSAImplementationPropertyVisitor : public EBPFTablePsaPropertyVis } void visitTableProperty() { - EBPFTablePsaPropertyVisitor::visitTableProperty("psa_implementation"); + EBPFTablePsaPropertyVisitor::visitTableProperty("psa_implementation"_cs); } }; @@ -418,7 +418,7 @@ cstring ActionTranslationVisitorPSA::getParamName(const IR::PathExpression *expr EBPFTablePSA::EBPFTablePSA(const EBPFProgram *program, const IR::TableBlock *table, CodeGenInspector *codeGen) : EBPFTable(program, table, codeGen), implementation(nullptr) { - auto sizeProperty = table->container->properties->getProperty("size"); + auto sizeProperty = table->container->properties->getProperty("size"_cs); if (keyGenerator == nullptr && sizeProperty != nullptr) { ::warning(ErrorType::WARN_IGNORE_PROPERTY, "%1%: property ignored because table does not have a key", sizeProperty); @@ -482,7 +482,7 @@ void EBPFTablePSA::initImplementation() { "%1%: implementation not found, ActionSelector is required", selectorKey->matchType); } - auto emptyGroupAction = table->container->properties->getProperty("psa_empty_group_action"); + auto emptyGroupAction = table->container->properties->getProperty("psa_empty_group_action"_cs); if (!hasActionSelector && emptyGroupAction != nullptr) { ::warning(ErrorType::WARN_UNUSED, "%1%: unused property (ActionSelector not provided)", emptyGroupAction); @@ -601,7 +601,7 @@ void EBPFTablePSA::emitConstEntriesInitializer(CodeBuilder *builder) { auto ret = program->refMap->newName("ret"); builder->emitIndent(); builder->appendFormat("int %s = ", ret.c_str()); - builder->target->emitTableUpdate(builder, instanceName, keyName.c_str(), valueName.c_str()); + builder->target->emitTableUpdate(builder, instanceName, keyName, valueName); builder->newline(); emitMapUpdateTraceMsg(builder, instanceName, ret); @@ -619,8 +619,7 @@ void EBPFTablePSA::emitDefaultActionInitializer(CodeBuilder *builder) { auto ret = program->refMap->newName("ret"); builder->emitIndent(); builder->appendFormat("int %s = ", ret.c_str()); - builder->target->emitTableUpdate(builder, defaultActionMapName, program->zeroKey.c_str(), - value.c_str()); + builder->target->emitTableUpdate(builder, defaultActionMapName, program->zeroKey, value); builder->newline(); emitMapUpdateTraceMsg(builder, defaultActionMapName, ret); @@ -931,25 +930,26 @@ cstring EBPFTablePSA::addPrefixFunc(bool trace) { "%trace_msg_tuple_not_found%" " return;\n" " }\n" - "}"; + "}"_cs; if (trace) { addPrefixFunc = addPrefixFunc.replace( - "%trace_msg_prefix_map_fail%", - " bpf_trace_message(\"Prefixes map update failed\\n\");\n"); + "%trace_msg_prefix_map_fail%"_cs, + " bpf_trace_message(\"Prefixes map update failed\\n\");\n"_cs); addPrefixFunc = addPrefixFunc.replace( - "%trace_msg_tuple_update_fail%", - " bpf_trace_message(\"Tuple map update failed\\n\");\n"); + "%trace_msg_tuple_update_fail%"_cs, + " bpf_trace_message(\"Tuple map update failed\\n\");\n"_cs); addPrefixFunc = addPrefixFunc.replace( - "%trace_msg_tuple_update_success%", - " bpf_trace_message(\"Tuple map update succeed\\n\");\n"); - addPrefixFunc = addPrefixFunc.replace( - "%trace_msg_tuple_not_found%", " bpf_trace_message(\"Tuple not found\\n\");\n"); + "%trace_msg_tuple_update_success%"_cs, + " bpf_trace_message(\"Tuple map update succeed\\n\");\n"_cs); + addPrefixFunc = + addPrefixFunc.replace("%trace_msg_tuple_not_found%"_cs, + " bpf_trace_message(\"Tuple not found\\n\");\n"_cs); } else { - addPrefixFunc = addPrefixFunc.replace("%trace_msg_prefix_map_fail%", ""); - addPrefixFunc = addPrefixFunc.replace("%trace_msg_tuple_update_fail%", ""); - addPrefixFunc = addPrefixFunc.replace("%trace_msg_tuple_update_success%", ""); - addPrefixFunc = addPrefixFunc.replace("%trace_msg_tuple_not_found%", ""); + addPrefixFunc = addPrefixFunc.replace("%trace_msg_prefix_map_fail%"_cs, ""_cs); + addPrefixFunc = addPrefixFunc.replace("%trace_msg_tuple_update_fail%"_cs, ""_cs); + addPrefixFunc = addPrefixFunc.replace("%trace_msg_tuple_update_success%"_cs, ""_cs); + addPrefixFunc = addPrefixFunc.replace("%trace_msg_tuple_not_found%"_cs, ""_cs); } return addPrefixFunc; @@ -1012,7 +1012,7 @@ void EBPFTablePSA::emitCacheInstance(CodeBuilder *builder) { } void EBPFTablePSA::emitCacheLookup(CodeBuilder *builder, cstring key, cstring value) { - cstring cacheVal = "cached_value"; + cstring cacheVal = "cached_value"_cs; builder->appendFormat("struct %s* %s = NULL", cacheValueTypeName.c_str(), cacheVal.c_str()); builder->endOfStatement(true); @@ -1048,7 +1048,7 @@ void EBPFTablePSA::emitCacheLookup(CodeBuilder *builder, cstring key, cstring va } void EBPFTablePSA::emitCacheUpdate(CodeBuilder *builder, cstring key, cstring value) { - cstring cacheUpdateVarName = "cache_update"; + cstring cacheUpdateVarName = "cache_update"_cs; builder->emitIndent(); builder->appendFormat("if (%s != NULL) ", value.c_str()); diff --git a/backends/ebpf/psa/ebpfPsaTable.h b/backends/ebpf/psa/ebpfPsaTable.h index 5161e36192..2f3d9e32bd 100644 --- a/backends/ebpf/psa/ebpfPsaTable.h +++ b/backends/ebpf/psa/ebpfPsaTable.h @@ -36,9 +36,9 @@ class EBPFTablePSA : public EBPFTable { typedef std::vector EntriesGroupedByMask_t; EntriesGroupedByMask_t getConstEntriesGroupedByMask(); bool hasConstEntries(); - const cstring addPrefixFunctionName = "add_prefix_and_entries"; - const cstring tuplesMapName = instanceName + "_tuples_map"; - const cstring prefixesMapName = instanceName + "_prefixes"; + const cstring addPrefixFunctionName = "add_prefix_and_entries"_cs; + const cstring tuplesMapName = instanceName + "_tuples_map"_cs; + const cstring prefixesMapName = instanceName + "_prefixes"_cs; protected: ActionTranslationVisitor *createActionTranslationVisitor( diff --git a/backends/ebpf/psa/externs/ebpfPsaCounter.cpp b/backends/ebpf/psa/externs/ebpfPsaCounter.cpp index d461499004..145c9459d1 100644 --- a/backends/ebpf/psa/externs/ebpfPsaCounter.cpp +++ b/backends/ebpf/psa/externs/ebpfPsaCounter.cpp @@ -100,7 +100,7 @@ EBPFCounterPSA::EBPFCounterPSA(const EBPFProgram *program, const IR::Declaration if (isHash) { indexWidthType = EBPFTypeFactory::instance->create(istype); } else { - keyTypeName = "u32"; + keyTypeName = "u32"_cs; } auto declaredSize = di->arguments->at(0)->expression->to(); @@ -204,7 +204,7 @@ void EBPFCounterPSA::emitDirectMethodInvocation(CodeBuilder *builder, cstring varStr = Util::printf_format("%s", pipeline->lengthVar.c_str()); builder->target->emitTraceMessage(builder, msgStr.c_str(), 1, varStr.c_str()); - emitCounterUpdate(builder, target, ""); + emitCounterUpdate(builder, target, ""_cs); msgStr = Util::printf_format("Counter: %s updated", instanceName.c_str()); builder->target->emitTraceMessage(builder, msgStr.c_str()); diff --git a/backends/ebpf/psa/externs/ebpfPsaDigest.cpp b/backends/ebpf/psa/externs/ebpfPsaDigest.cpp index aa14abc168..11f91cbc93 100644 --- a/backends/ebpf/psa/externs/ebpfPsaDigest.cpp +++ b/backends/ebpf/psa/externs/ebpfPsaDigest.cpp @@ -126,7 +126,7 @@ void EBPFDigestPSA::emitInstance(CodeBuilder *builder) const { builder->appendFormat("REGISTER_TABLE_NO_KEY_TYPE(%s, BPF_MAP_TYPE_QUEUE, 0, ", instanceName); if (valueTypeName.isNullOrEmpty()) { - valueType->declare(builder, "", false); + valueType->declare(builder, cstring::empty, false); } else { builder->append(valueTypeName); } diff --git a/backends/ebpf/psa/externs/ebpfPsaHashAlgorithm.cpp b/backends/ebpf/psa/externs/ebpfPsaHashAlgorithm.cpp index 5375a0dd74..653b6a4a8e 100644 --- a/backends/ebpf/psa/externs/ebpfPsaHashAlgorithm.cpp +++ b/backends/ebpf/psa/externs/ebpfPsaHashAlgorithm.cpp @@ -59,7 +59,7 @@ void CRCChecksumAlgorithm::emitUpdateMethod(CodeBuilder *builder, int crcWidth) // incremented. For data shorter than or equal 64 bits, bytes are processed in little endian // byte order - data pointer is decremented by outer loop in this case. // There is no need for lookup table. - cstring code = + const char *code = "static __always_inline\n" "void crc16_update(u16 * reg, const u8 * data, " "u16 data_size, const u16 poly) {\n" @@ -91,7 +91,7 @@ void CRCChecksumAlgorithm::emitUpdateMethod(CodeBuilder *builder, int crcWidth) // 4. Data size more than 8 bytes and not multiply of 8 bytes - calculated using slice-by-8 // and Standard Implementation both in big endian byte order. // Lookup table is necessary for both algorithms. - cstring code = + const char *code = "static __always_inline\n" "void crc32_update(u32 * reg, const u8 * data, u16 data_size, const u32 poly) {\n" " u32* current = (u32*) data;\n" @@ -333,7 +333,7 @@ void CRCChecksumAlgorithm::emitSetInternalState(CodeBuilder *builder, void CRC16ChecksumAlgorithm::emitGlobals(CodeBuilder *builder) { CRCChecksumAlgorithm::emitUpdateMethod(builder, 16); - cstring code = + const char *code = "static __always_inline " "u16 crc16_finalize(u16 reg) {\n" " return reg;\n" @@ -346,7 +346,7 @@ void CRC16ChecksumAlgorithm::emitGlobals(CodeBuilder *builder) { void CRC32ChecksumAlgorithm::emitGlobals(CodeBuilder *builder) { CRCChecksumAlgorithm::emitUpdateMethod(builder, 32); - cstring code = + const char *code = "static __always_inline " "u32 crc32_finalize(u32 reg) {\n" " return reg ^ 0xFFFFFFFF;\n" diff --git a/backends/ebpf/psa/externs/ebpfPsaHashAlgorithm.h b/backends/ebpf/psa/externs/ebpfPsaHashAlgorithm.h index ed37042fe3..c56f1c9557 100644 --- a/backends/ebpf/psa/externs/ebpfPsaHashAlgorithm.h +++ b/backends/ebpf/psa/externs/ebpfPsaHashAlgorithm.h @@ -110,12 +110,12 @@ class CRC16ChecksumAlgorithm : public CRCChecksumAlgorithm { public: CRC16ChecksumAlgorithm(const EBPFProgram *program, cstring name) : CRCChecksumAlgorithm(program, name, 16) { - initialValue = "0"; + initialValue = "0"_cs; // We use a 0x8005 polynomial. // 0xA001 comes from 0x8005 value bits reflection. - polynomial = "0xA001"; - updateMethod = "crc16_update"; - finalizeMethod = "crc16_finalize"; + polynomial = "0xA001"_cs; + updateMethod = "crc16_update"_cs; + finalizeMethod = "crc16_finalize"_cs; } static void emitGlobals(CodeBuilder *builder); @@ -132,12 +132,12 @@ class CRC32ChecksumAlgorithm : public CRCChecksumAlgorithm { public: CRC32ChecksumAlgorithm(const EBPFProgram *program, cstring name) : CRCChecksumAlgorithm(program, name, 32) { - initialValue = "0xffffffff"; + initialValue = "0xffffffff"_cs; // We use a 0x04C11DB7 polynomial. // 0xEDB88320 comes from 0x04C11DB7 value bits reflection. - polynomial = "0xEDB88320"; - updateMethod = "crc32_update"; - finalizeMethod = "crc32_finalize"; + polynomial = "0xEDB88320"_cs; + updateMethod = "crc32_update"_cs; + finalizeMethod = "crc32_finalize"_cs; } static void emitGlobals(CodeBuilder *builder); diff --git a/backends/ebpf/psa/externs/ebpfPsaMeter.cpp b/backends/ebpf/psa/externs/ebpfPsaMeter.cpp index d640e255a3..b96e001c96 100644 --- a/backends/ebpf/psa/externs/ebpfPsaMeter.cpp +++ b/backends/ebpf/psa/externs/ebpfPsaMeter.cpp @@ -99,11 +99,11 @@ EBPFMeterPSA::MeterType EBPFMeterPSA::toType(const int typeCode) { IR::IndexedVector EBPFMeterPSA::getValueFields() { auto vec = IR::IndexedVector(); auto bits_64 = IR::Type_Bits::get(64, false); - const std::initializer_list fieldsNames = {"pir_period", "pir_unit_per_period", - "cir_period", "cir_unit_per_period", - "pbs", "cbs", - "pbs_left", "cbs_left", - "time_p", "time_c"}; + const std::vector fieldsNames = {"pir_period"_cs, "pir_unit_per_period"_cs, + "cir_period"_cs, "cir_unit_per_period"_cs, + "pbs"_cs, "cbs"_cs, + "pbs_left"_cs, "cbs_left"_cs, + "time_p"_cs, "time_c"_cs}; for (auto fieldName : fieldsNames) { vec.push_back(new IR::StructField(IR::ID(fieldName), bits_64)); } @@ -163,9 +163,9 @@ void EBPFMeterPSA::emitExecute(CodeBuilder *builder, const P4::ExternMethod *met cstring functionNameSuffix; if (method->expr->arguments->size() == 2) { - functionNameSuffix = "_color_aware"; + functionNameSuffix = "_color_aware"_cs; } else { - functionNameSuffix = ""; + functionNameSuffix = ""_cs; } if (type == BYTES) { @@ -207,9 +207,9 @@ void EBPFMeterPSA::emitDirectExecute(CodeBuilder *builder, const P4::ExternMetho cstring functionNameSuffix; if (method->expr->arguments->size() == 1) { - functionNameSuffix = "_color_aware"; + functionNameSuffix = "_color_aware"_cs; } else { - functionNameSuffix = ""; + functionNameSuffix = ""_cs; } cstring lockVar = valuePtr + "->" + spinlockField; @@ -409,36 +409,37 @@ cstring EBPFMeterPSA::meterExecuteFunc(bool trace, P4::ReferenceMap *refMap) { " return meter_execute_packets_value_color_aware(value, ((void *)value) + " "sizeof(%meter_struct%), " "time_ns, color);\n" - "}\n"; + "}\n"_cs; if (trace) { meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_green%"), " bpf_trace_message(\"" - "Meter: GREEN\\n\");\n"); + "Meter: GREEN\\n\");\n"_cs); meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_yellow%"), " bpf_trace_message(\"" - "Meter: YELLOW\\n\");\n"); + "Meter: YELLOW\\n\");\n"_cs); meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_red%"), " bpf_trace_message(\"" - "Meter: RED\\n\");\n"); + "Meter: RED\\n\");\n"_cs); meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_no_value%"), " bpf_trace_message(\"Meter: No meter value! " - "Returning default GREEN\\n\");\n"); + "Returning default GREEN\\n\");\n"_cs); meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_execute_bytes%"), - " bpf_trace_message(\"Meter: execute BYTES\\n\");\n"); + " bpf_trace_message(\"Meter: execute BYTES\\n\");\n"_cs); meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_execute_packets%"), - " bpf_trace_message(\"Meter: execute PACKETS\\n\");\n"); + " bpf_trace_message(\"Meter: execute PACKETS\\n\");\n"_cs); } else { - meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_green%"), ""); - meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_yellow%"), ""); - meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_red%"), ""); - meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_no_value%"), ""); - meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_execute_bytes%"), ""); + meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_green%"), ""_cs); + meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_yellow%"), ""_cs); + meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_red%"), ""_cs); + meterExecuteFunc = meterExecuteFunc.replace(cstring("%trace_msg_meter_no_value%"), ""_cs); meterExecuteFunc = - meterExecuteFunc.replace(cstring("%trace_msg_meter_execute_packets%"), ""); + meterExecuteFunc.replace(cstring("%trace_msg_meter_execute_bytes%"), ""_cs); + meterExecuteFunc = + meterExecuteFunc.replace(cstring("%trace_msg_meter_execute_packets%"), ""_cs); } meterExecuteFunc = meterExecuteFunc.replace(cstring("%meter_struct%"), diff --git a/backends/ebpf/psa/externs/ebpfPsaMeter.h b/backends/ebpf/psa/externs/ebpfPsaMeter.h index 9eca09c9ee..55973ad19c 100644 --- a/backends/ebpf/psa/externs/ebpfPsaMeter.h +++ b/backends/ebpf/psa/externs/ebpfPsaMeter.h @@ -33,8 +33,8 @@ class EBPFMeterPSA : public EBPFTableBase { ControlBodyTranslatorPSA *translator) const; protected: - const cstring indirectValueField = "value"; - const cstring spinlockField = "lock"; + const cstring indirectValueField = "value"_cs; + const cstring spinlockField = "lock"_cs; size_t size{}; EBPFType *keyType{}; diff --git a/backends/ebpf/psa/externs/ebpfPsaTableImplementation.cpp b/backends/ebpf/psa/externs/ebpfPsaTableImplementation.cpp index 0d265576a6..1383e54638 100644 --- a/backends/ebpf/psa/externs/ebpfPsaTableImplementation.cpp +++ b/backends/ebpf/psa/externs/ebpfPsaTableImplementation.cpp @@ -159,8 +159,8 @@ void EBPFActionProfilePSA::emitInstance(CodeBuilder *builder) { // If user change action for given reference to NoAction, it will be hard to // distinguish it from non-existing entry using only key value. auto tableKind = TableHash; - builder->target->emitTableDecl(builder, instanceName, tableKind, "u32", - cstring("struct ") + valueTypeName, size); + builder->target->emitTableDecl(builder, instanceName, tableKind, "u32"_cs, + "struct "_cs + valueTypeName, size); } void EBPFActionProfilePSA::applyImplementation(CodeBuilder *builder, cstring tableValueName, @@ -304,16 +304,17 @@ void EBPFActionSelectorPSA::emitInstance(CodeBuilder *builder) { // group map (group ref -> {action refs}) // TODO: group size (inner size) is assumed to be 128. Make more logic for this. // One additional entry is for group size. - builder->target->emitMapInMapDecl(builder, groupsMapName + "_inner", TableArray, "u32", "u32", - 128 + 1, groupsMapName, TableHash, "u32", groupsMapSize); + builder->target->emitMapInMapDecl(builder, groupsMapName + "_inner", TableArray, "u32"_cs, + "u32"_cs, 128 + 1, groupsMapName, TableHash, "u32"_cs, + groupsMapSize); // default empty group action (0 -> action) builder->target->emitTableDecl(builder, emptyGroupActionMapName, TableArray, - program->arrayIndexType, cstring("struct ") + valueTypeName, 1); + program->arrayIndexType, "struct "_cs + valueTypeName, 1); // action map (ref -> action) - builder->target->emitTableDecl(builder, actionsMapName, TableHash, "u32", - cstring("struct ") + valueTypeName, size); + builder->target->emitTableDecl(builder, actionsMapName, TableHash, "u32"_cs, + "struct "_cs + valueTypeName, size); emitCacheInstance(builder); } @@ -339,8 +340,8 @@ void EBPFActionSelectorPSA::applyImplementation(CodeBuilder *builder, cstring ta cstring innerGroupName = program->refMap->newName("as_group_map"); groupStateVarName = program->refMap->newName("as_group_state"); // these can be hardcoded because they are declared inside of a block - cstring checksumValName = "as_checksum_val"; - cstring mapEntryName = "as_map_entry"; + cstring checksumValName = "as_checksum_val"_cs; + cstring mapEntryName = "as_map_entry"_cs; emitCacheVariables(builder); @@ -547,7 +548,7 @@ void EBPFActionSelectorPSA::registerTable(const EBPFTablePSA *instance) { if (table == nullptr) { selectors = getSelectorsFromTable(instance); emptyGroupAction = - instance->table->container->properties->getProperty("psa_empty_group_action"); + instance->table->container->properties->getProperty("psa_empty_group_action"_cs); groupsMapSize = instance->size; } else { verifyTableSelectorKeySet(instance); @@ -587,7 +588,7 @@ void EBPFActionSelectorPSA::verifyTableSelectorKeySet(const EBPFTablePSA *instan } void EBPFActionSelectorPSA::verifyTableEmptyGroupAction(const EBPFTablePSA *instance) { - auto iega = instance->table->container->properties->getProperty("psa_empty_group_action"); + auto iega = instance->table->container->properties->getProperty("psa_empty_group_action"_cs); if (emptyGroupAction == nullptr && iega == nullptr) return; // nothing to do here if (emptyGroupAction == nullptr && iega != nullptr) { @@ -607,7 +608,7 @@ void EBPFActionSelectorPSA::verifyTableEmptyGroupAction(const EBPFTablePSA *inst } bool same = true; - cstring additionalNote; + const char *additionalNote = ""; if (emptyGroupAction->isConstant != iega->isConstant) { same = false; diff --git a/backends/ebpf/psa/xdpHelpProgram.h b/backends/ebpf/psa/xdpHelpProgram.h index 760e2156a6..f8e44e9028 100644 --- a/backends/ebpf/psa/xdpHelpProgram.h +++ b/backends/ebpf/psa/xdpHelpProgram.h @@ -22,7 +22,7 @@ limitations under the License. namespace EBPF { class XDPHelpProgram : public EBPFProgram { - cstring XDPProgUsingMetaForXDP2TC = + const char *XDPProgUsingMetaForXDP2TC = " void *data_end = (void *)(long)skb->data_end;\n" " struct ethhdr *eth = (struct ethhdr *)(long)skb->data;\n" " if ((void *)((struct ethhdr *) eth + 1) > data_end) {\n" @@ -50,7 +50,7 @@ class XDPHelpProgram : public EBPFProgram { "\n" " return XDP_PASS;"; - cstring XDPProgUsingHeadForXDP2TC = + const char *XDPProgUsingHeadForXDP2TC = " void *data = (void *)(long)skb->data;\n" " void *data_end = (void *)(long)skb->data_end;\n" " struct ethhdr *eth = data;\n" @@ -80,7 +80,7 @@ class XDPHelpProgram : public EBPFProgram { "\n" " return XDP_PASS;"; - cstring XDPProgUsingCPUMAPForXDP2TC = + const char *XDPProgUsingCPUMAPForXDP2TC = " void *data = (void *)(long)skb->data;\n" " void *data_end = (void *)(long)skb->data_end;\n" " struct ethhdr *eth = data;\n" @@ -97,8 +97,8 @@ class XDPHelpProgram : public EBPFProgram { cstring sectionName; explicit XDPHelpProgram(const EbpfOptions &options) : EBPFProgram(options, nullptr, nullptr, nullptr, nullptr) { - sectionName = "xdp/xdp-ingress"; - functionName = "xdp_func"; + sectionName = "xdp/xdp-ingress"_cs; + functionName = "xdp_func"_cs; } void emit(CodeBuilder *builder) { diff --git a/backends/ebpf/target.cpp b/backends/ebpf/target.cpp index df8c974ea6..a00b35f38c 100644 --- a/backends/ebpf/target.cpp +++ b/backends/ebpf/target.cpp @@ -67,8 +67,8 @@ void KernelSamplesTarget::emitTableDecl(Util::SourceCodeBuilder *builder, cstrin TableKind tableKind, cstring keyType, cstring valueType, unsigned size) const { cstring kind, flags; - cstring registerTable = "REGISTER_TABLE(%s, %s, %s, %s, %d)"; - cstring registerTableWithFlags = "REGISTER_TABLE_FLAGS(%s, %s, %s, %s, %d, %s)"; + cstring registerTable = "REGISTER_TABLE(%s, %s, %s, %s, %d)"_cs; + cstring registerTableWithFlags = "REGISTER_TABLE_FLAGS(%s, %s, %s, %s, %d, %s)"_cs; kind = getBPFMapType(tableKind); @@ -77,18 +77,18 @@ void KernelSamplesTarget::emitTableDecl(Util::SourceCodeBuilder *builder, cstrin // as array map must have u32 key type. ::warning(ErrorType::WARN_INVALID, "Invalid key type (%1%) for table kind %2%, replacing with u32", keyType, kind); - keyType = "u32"; + keyType = "u32"_cs; } else if (tableKind == TableProgArray && (keyType != "u32" || valueType != "u32")) { ::warning(ErrorType::WARN_INVALID, "Invalid key type (%1%) or value type (%2%) for table kind %3%, " "replacing with u32", keyType, valueType, kind); - keyType = "u32"; - valueType = "u32"; + keyType = "u32"_cs; + valueType = "u32"_cs; } if (tableKind == TableLPMTrie) { - flags = "BPF_F_NO_PREALLOC"; + flags = "BPF_F_NO_PREALLOC"_cs; } if (flags.isNullOrEmpty()) { @@ -121,8 +121,8 @@ void KernelSamplesTarget::emitMapInMapDecl(Util::SourceCodeBuilder *builder, cst BUG("Unsupported type of outer map for map-in-map"); } - cstring registerOuterTable = "REGISTER_TABLE_OUTER(%s, %s_OF_MAPS, %s, %s, %d, %d, %s)"; - cstring registerInnerTable = "REGISTER_TABLE_INNER(%s, %s, %s, %s, %d, %d, %d)"; + cstring registerOuterTable = "REGISTER_TABLE_OUTER(%s, %s_OF_MAPS, %s, %s, %d, %d, %s)"_cs; + cstring registerInnerTable = "REGISTER_TABLE_INNER(%s, %s, %s, %s, %d, %d, %d)"_cs; innerMapIndex++; @@ -133,11 +133,11 @@ void KernelSamplesTarget::emitMapInMapDecl(Util::SourceCodeBuilder *builder, cst annotateTableWithBTF(builder, innerName, innerKeyType, innerValueType); kind = getBPFMapType(outerTableKind); - cstring keyType = outerTableKind == TableArray ? "__u32" : outerKeyType; + cstring keyType = outerTableKind == TableArray ? "__u32"_cs : outerKeyType; builder->appendFormat(registerOuterTable, outerName, kind, keyType, "__u32", outerSize, innerMapIndex, innerName); builder->newline(); - annotateTableWithBTF(builder, outerName, keyType, "__u32"); + annotateTableWithBTF(builder, outerName, keyType, "__u32"_cs); } void KernelSamplesTarget::emitLicense(Util::SourceCodeBuilder *builder, cstring license) const { @@ -157,7 +157,7 @@ void KernelSamplesTarget::emitMain(Util::SourceCodeBuilder *builder, cstring fun } void KernelSamplesTarget::emitPreamble(Util::SourceCodeBuilder *builder) const { - cstring macro; + const char *macro; if (emitTraceMessages) { macro = "#define bpf_trace_message(fmt, ...) \\\n" @@ -174,11 +174,12 @@ void KernelSamplesTarget::emitPreamble(Util::SourceCodeBuilder *builder) const { builder->newline(); } +// FIXME: Fix terrible implementation void KernelSamplesTarget::emitTraceMessage(Util::SourceCodeBuilder *builder, const char *format, int argc, ...) const { if (!emitTraceMessages) return; - cstring msg = format; + cstring msg = cstring(format); va_list ap; // Older kernels do not append new line when printing message but newer do that, @@ -186,7 +187,7 @@ void KernelSamplesTarget::emitTraceMessage(Util::SourceCodeBuilder *builder, con // will look better than everything in a single line. if (!msg.endsWith("\\n")) msg = msg + "\\n"; - msg = cstring("\"") + msg + "\""; + msg = "\""_cs + msg + "\""_cs; va_start(ap, argc); for (int i = 0; i < argc; ++i) { auto arg = va_arg(ap, const char *); @@ -261,11 +262,11 @@ void BccTarget::emitTableDecl(Util::SourceCodeBuilder *builder, cstring tblName, unsigned size) const { cstring kind; if (tableKind == TableHash) - kind = "hash"; + kind = "hash"_cs; else if (tableKind == TableArray) - kind = "array"; + kind = "array"_cs; else if (tableKind == TableLPMTrie) - kind = "lpm_trie"; + kind = "lpm_trie"_cs; else BUG("%1%: unsupported table kind", tableKind); diff --git a/backends/ebpf/target.h b/backends/ebpf/target.h index b928548eb5..d3c0573593 100644 --- a/backends/ebpf/target.h +++ b/backends/ebpf/target.h @@ -29,6 +29,8 @@ limitations under the License. namespace EBPF { +using namespace P4::literals; + enum TableKind { TableHash, TableArray, @@ -131,19 +133,19 @@ class KernelSamplesTarget : public Target { cstring getBPFMapType(TableKind kind) const { if (kind == TableHash) { - return "BPF_MAP_TYPE_HASH"; + return "BPF_MAP_TYPE_HASH"_cs; } else if (kind == TableArray) { - return "BPF_MAP_TYPE_ARRAY"; + return "BPF_MAP_TYPE_ARRAY"_cs; } else if (kind == TablePerCPUArray) { - return "BPF_MAP_TYPE_PERCPU_ARRAY"; + return "BPF_MAP_TYPE_PERCPU_ARRAY"_cs; } else if (kind == TableLPMTrie) { - return "BPF_MAP_TYPE_LPM_TRIE"; + return "BPF_MAP_TYPE_LPM_TRIE"_cs; } else if (kind == TableHashLRU) { - return "BPF_MAP_TYPE_LRU_HASH"; + return "BPF_MAP_TYPE_LRU_HASH"_cs; } else if (kind == TableProgArray) { - return "BPF_MAP_TYPE_PROG_ARRAY"; + return "BPF_MAP_TYPE_PROG_ARRAY"_cs; } else if (kind == TableDevmap) { - return "BPF_MAP_TYPE_DEVMAP"; + return "BPF_MAP_TYPE_DEVMAP"_cs; } BUG("Unknown table kind"); } @@ -152,7 +154,7 @@ class KernelSamplesTarget : public Target { bool emitTraceMessages; public: - explicit KernelSamplesTarget(bool emitTrace = false, cstring name = "Linux kernel") + explicit KernelSamplesTarget(bool emitTrace = false, cstring name = "Linux kernel"_cs) : Target(name), innerMapIndex(0), emitTraceMessages(emitTrace) {} void emitLicense(Util::SourceCodeBuilder *builder, cstring license) const override; @@ -187,12 +189,12 @@ class KernelSamplesTarget : public Target { return cstring("((void*)(long)") + base + "->data_end)"; } cstring dataLength(cstring base) const override { return cstring(base) + "->len"; } - cstring forwardReturnCode() const override { return "TC_ACT_OK"; } - cstring dropReturnCode() const override { return "TC_ACT_SHOT"; } - cstring abortReturnCode() const override { return "TC_ACT_SHOT"; } - cstring sysMapPath() const override { return "/sys/fs/bpf/tc/globals"; } + cstring forwardReturnCode() const override { return "TC_ACT_OK"_cs; } + cstring dropReturnCode() const override { return "TC_ACT_SHOT"_cs; } + cstring abortReturnCode() const override { return "TC_ACT_SHOT"_cs; } + cstring sysMapPath() const override { return "/sys/fs/bpf/tc/globals"_cs; } - cstring packetDescriptorType() const override { return "struct __sk_buff"; } + cstring packetDescriptorType() const override { return "struct __sk_buff"_cs; } void annotateTableWithBTF(Util::SourceCodeBuilder *builder, cstring name, cstring keyType, cstring valueType) const; @@ -200,7 +202,7 @@ class KernelSamplesTarget : public Target { class P4TCTarget : public KernelSamplesTarget { public: - explicit P4TCTarget(bool emitTrace) : KernelSamplesTarget(emitTrace, "P4TC") {} + explicit P4TCTarget(bool emitTrace) : KernelSamplesTarget(emitTrace, "P4TC"_cs) {} cstring getByteOrderFromAnnotation(const IR::Vector annotations) const { for (auto anno : annotations) { if (anno->name != "tc_type") continue; @@ -208,11 +210,11 @@ class P4TCTarget : public KernelSamplesTarget { if (annoVal->text == "macaddr" || annoVal->text == "ipv4" || annoVal->text == "ipv6" || annoVal->text == "be16" || annoVal->text == "be32" || annoVal->text == "be64") { - return "NETWORK"; + return "NETWORK"_cs; } } } - return "HOST"; + return "HOST"_cs; } cstring getByteOrder(P4::TypeMap *typeMap, const IR::P4Action *action, @@ -233,21 +235,21 @@ class P4TCTarget : public KernelSamplesTarget { } } } - return "HOST"; + return "HOST"_cs; } }; /// Target XDP. class XdpTarget : public KernelSamplesTarget { public: - explicit XdpTarget(bool emitTrace) : KernelSamplesTarget(emitTrace, "XDP") {} + explicit XdpTarget(bool emitTrace) : KernelSamplesTarget(emitTrace, "XDP"_cs) {} - cstring forwardReturnCode() const override { return "XDP_PASS"; } - cstring dropReturnCode() const override { return "XDP_DROP"; } - cstring abortReturnCode() const override { return "XDP_ABORTED"; } - cstring redirectReturnCode() const { return "XDP_REDIRECT"; } - cstring sysMapPath() const override { return "/sys/fs/bpf/xdp/globals"; } - cstring packetDescriptorType() const override { return "struct xdp_md"; } + cstring forwardReturnCode() const override { return "XDP_PASS"_cs; } + cstring dropReturnCode() const override { return "XDP_DROP"_cs; } + cstring abortReturnCode() const override { return "XDP_ABORTED"_cs; } + cstring redirectReturnCode() const { return "XDP_REDIRECT"_cs; } + cstring sysMapPath() const override { return "/sys/fs/bpf/xdp/globals"_cs; } + cstring packetDescriptorType() const override { return "struct xdp_md"_cs; } cstring dataLength(cstring base) const override { return cstring("(") + base + "->data_end - " + base + "->data)"; @@ -264,7 +266,7 @@ class XdpTarget : public KernelSamplesTarget { /// Represents a target compiled by bcc that uses the TC. class BccTarget : public Target { public: - BccTarget() : Target("BCC") {} + BccTarget() : Target("BCC"_cs) {} void emitLicense(Util::SourceCodeBuilder *, cstring) const override {} void emitCodeSection(Util::SourceCodeBuilder *, cstring) const override {} void emitIncludes(Util::SourceCodeBuilder *builder) const override; @@ -284,18 +286,18 @@ class BccTarget : public Target { return cstring("(") + base + " + " + base + "->len)"; } cstring dataLength(cstring base) const override { return cstring(base) + "->len"; } - cstring forwardReturnCode() const override { return "0"; } - cstring dropReturnCode() const override { return "1"; } - cstring abortReturnCode() const override { return "1"; } - cstring sysMapPath() const override { return "/sys/fs/bpf"; } - cstring packetDescriptorType() const override { return "struct __sk_buff"; } + cstring forwardReturnCode() const override { return "0"_cs; } + cstring dropReturnCode() const override { return "1"_cs; } + cstring abortReturnCode() const override { return "1"_cs; } + cstring sysMapPath() const override { return "/sys/fs/bpf"_cs; } + cstring packetDescriptorType() const override { return "struct __sk_buff"_cs; } }; /// A userspace test version with functionality equivalent to the kernel. /// Compiles with GCC. class TestTarget : public EBPF::KernelSamplesTarget { public: - TestTarget() : KernelSamplesTarget(false, "Userspace Test") {} + TestTarget() : KernelSamplesTarget(false, "Userspace Test"_cs) {} void emitResizeBuffer(Util::SourceCodeBuilder *, cstring, cstring) const override {} void emitIncludes(Util::SourceCodeBuilder *builder) const override; @@ -307,11 +309,11 @@ class TestTarget : public EBPF::KernelSamplesTarget { cstring dataEnd(cstring base) const override { return cstring("((void*)(long)(") + base + "->data + " + base + "->len))"; } - cstring forwardReturnCode() const override { return "true"; } - cstring dropReturnCode() const override { return "false"; } - cstring abortReturnCode() const override { return "false"; } - cstring sysMapPath() const override { return "/sys/fs/bpf"; } - cstring packetDescriptorType() const override { return "struct __sk_buff"; } + cstring forwardReturnCode() const override { return "true"_cs; } + cstring dropReturnCode() const override { return "false"_cs; } + cstring abortReturnCode() const override { return "false"_cs; } + cstring sysMapPath() const override { return "/sys/fs/bpf"_cs; } + cstring packetDescriptorType() const override { return "struct __sk_buff"_cs; } }; } // namespace EBPF diff --git a/backends/graphs/controls.cpp b/backends/graphs/controls.cpp index 0e559daae8..a1b75738d2 100644 --- a/backends/graphs/controls.cpp +++ b/backends/graphs/controls.cpp @@ -23,6 +23,7 @@ limitations under the License. #include "frontends/p4/methodInstance.h" #include "frontends/p4/tableApply.h" #include "graphs.h" +#include "lib/cstring.h" #include "lib/log.h" #include "lib/nullstream.h" @@ -33,12 +34,12 @@ using Graph = ControlGraphs::Graph; Graph *ControlGraphs::ControlStack::pushBack(Graph ¤tSubgraph, const cstring &name) { auto &newSubgraph = currentSubgraph.create_subgraph(); auto fullName = getName(name); - boost::get_property(newSubgraph, boost::graph_name) = "cluster" + fullName; - boost::get_property(newSubgraph, boost::graph_graph_attribute)["label"] = + boost::get_property(newSubgraph, boost::graph_name) = "cluster"_cs + fullName; + boost::get_property(newSubgraph, boost::graph_graph_attribute)["label"_cs] = boost::get_property(currentSubgraph, boost::graph_name) + (fullName != "" ? "." + fullName : fullName); - boost::get_property(newSubgraph, boost::graph_graph_attribute)["fontsize"] = "22pt"; - boost::get_property(newSubgraph, boost::graph_graph_attribute)["style"] = "bold"; + boost::get_property(newSubgraph, boost::graph_graph_attribute)["fontsize"_cs] = "22pt"_cs; + boost::get_property(newSubgraph, boost::graph_graph_attribute)["style"_cs] = "bold"_cs; names.push_back(name); subgraphs.push_back(&newSubgraph); return getSubgraph(); @@ -85,9 +86,9 @@ bool ControlGraphs::preorder(const IR::PackageBlock *block) { instanceName = std::nullopt; boost::get_property(*g_, boost::graph_name) = name; BUG_CHECK(controlStack.isEmpty(), "Invalid control stack state"); - g = controlStack.pushBack(*g_, ""); - start_v = add_vertex("__START__", VertexType::OTHER); - exit_v = add_vertex("__EXIT__", VertexType::OTHER); + g = controlStack.pushBack(*g_, cstring::empty); + start_v = add_vertex("__START__"_cs, VertexType::OTHER); + exit_v = add_vertex("__EXIT__"_cs, VertexType::OTHER); parents = {{start_v, new EdgeUnconditional()}}; visit(it.second->getNode()); diff --git a/backends/graphs/graph_visitor.cpp b/backends/graphs/graph_visitor.cpp index 11c01c28b3..39f9810a8e 100644 --- a/backends/graphs/graph_visitor.cpp +++ b/backends/graphs/graph_visitor.cpp @@ -81,17 +81,17 @@ const char *Graph_visitor::getPrevType(const PrevType &prev_type) { void Graph_visitor::forLoopJson(std::vector &graphsArray, PrevType node_type) { for (auto g : graphsArray) { - auto block = new Util::JsonObject(); + auto *block = new Util::JsonObject(); programBlocks->emplace_back(block); - block->emplace("type", getPrevType(node_type)); - block->emplace("name", boost::get_property(*g, boost::graph_name)); + block->emplace("type"_cs, getPrevType(node_type)); + block->emplace("name"_cs, boost::get_property(*g, boost::graph_name)); - auto nodesArray = new Util::JsonArray(); - block->emplace("nodes", nodesArray); + auto *nodesArray = new Util::JsonArray(); + block->emplace("nodes"_cs, nodesArray); - auto parserEdges = new Util::JsonArray(); - block->emplace("transitions", parserEdges); + auto *parserEdges = new Util::JsonArray(); + block->emplace("transitions"_cs, parserEdges); auto subg = *g; @@ -99,13 +99,13 @@ void Graph_visitor::forLoopJson(std::vector &graphsArray, PrevType node for (auto &vit = vertices.first; vit != vertices.second; ++vit) { auto node = new Util::JsonObject(); nodesArray->emplace_back(node); - node->emplace("node_nmb", *vit); + node->emplace("node_nmb"_cs, *vit); const auto &vinfo = subg[*vit]; - node->emplace("name", vinfo.name.escapeJson()); - node->emplace("type", getType(vinfo.type)); - node->emplace("type_enum", (unsigned)vinfo.type); + node->emplace("name"_cs, vinfo.name.escapeJson()); + node->emplace("type"_cs, getType(vinfo.type)); + node->emplace("type_enum"_cs, (unsigned)vinfo.type); } auto edges = boost::edges(subg); @@ -117,10 +117,10 @@ void Graph_visitor::forLoopJson(std::vector &graphsArray, PrevType node auto from = boost::source(*eit, subg); auto to = boost::target(*eit, subg); - edge->emplace("from", from); - edge->emplace("to", to); + edge->emplace("from"_cs, from); + edge->emplace("to"_cs, to); - edge->emplace("cond", boost::get(boost::edge_name, subg, *eit).escapeJson()); + edge->emplace("cond"_cs, boost::get(boost::edge_name, subg, *eit).escapeJson()); } } } @@ -136,10 +136,10 @@ void Graph_visitor::forLoopFullGraph(std::vector &graphsArray, fullGrap // set subg properties boost::get_property(subfg, boost::graph_name) = "cluster" + Util::toString(opts->cluster_i++); - boost::get_property(subfg, boost::graph_graph_attribute)["label"] = + boost::get_property(subfg, boost::graph_graph_attribute)["label"_cs] = boost::get_property(*g_, boost::graph_name); - boost::get_property(subfg, boost::graph_graph_attribute)["style"] = "bold"; - boost::get_property(subfg, boost::graph_graph_attribute)["fontsize"] = "22pt"; + boost::get_property(subfg, boost::graph_graph_attribute)["style"_cs] = "bold"_cs; + boost::get_property(subfg, boost::graph_graph_attribute)["fontsize"_cs] = "22pt"_cs; // No statements in graph, merge "__START__" and "__EXIT__" nodes if (g_->m_global_vertex.size() == 2) { @@ -151,10 +151,10 @@ void Graph_visitor::forLoopFullGraph(std::vector &graphsArray, fullGrap // Connect subgraphs if (opts->cluster_i > 1) { if (prev_type == PrevType::Parser) { - add_edge(opts->node_i - 2, opts->node_i, "", opts->cluster_i); + add_edge(opts->node_i - 2, opts->node_i, cstring::empty, opts->cluster_i); prev_type = PrevType::Control; } else { - add_edge(t_prev_adder, opts->node_i, "", opts->cluster_i); + add_edge(t_prev_adder, opts->node_i, cstring::empty, opts->cluster_i); } } @@ -185,15 +185,15 @@ void Graph_visitor::process(std::vector &controlGraphsArray, if (fullGraph) { fullGraphOpts opts; - boost::get_property(opts.fg, boost::graph_name) = "fullGraph"; + boost::get_property(opts.fg, boost::graph_name) = "fullGraph"_cs; // Enables edges with tails between clusters. - boost::get_property(opts.fg, boost::graph_graph_attribute)["compound"] = "true"; + boost::get_property(opts.fg, boost::graph_graph_attribute)["compound"_cs] = "true"_cs; forLoopFullGraph(parserGraphsArray, &opts, PrevType::Parser); forLoopFullGraph(controlGraphsArray, &opts, PrevType::Parser); GraphAttributeSetter()(opts.fg); - writeGraphToFile(opts.fg, "fullGraph"); + writeGraphToFile(opts.fg, "fullGraph"_cs); } if (jsonOut) { @@ -208,15 +208,15 @@ void Graph_visitor::process(std::vector &controlGraphsArray, file_without_path = file_without_p4.findlast('/') + 1; // char* without '/' } - json->emplace("name", file_without_path); + json->emplace("name"_cs, file_without_path); programBlocks = new Util::JsonArray(); - json->emplace("nodes", programBlocks); + json->emplace("nodes"_cs, programBlocks); forLoopJson(parserGraphsArray, PrevType::Parser); forLoopJson(controlGraphsArray, PrevType::Control); std::ofstream file; - auto path = Util::PathName(graphsDir).join("fullGraph.json"); + auto path = Util::PathName(graphsDir).join("fullGraph.json"_cs); file.open(path.toString()); file << json->toString() << std::endl; file.close(); diff --git a/backends/graphs/graphs.cpp b/backends/graphs/graphs.cpp index 06c3be4879..835bcc6c1a 100644 --- a/backends/graphs/graphs.cpp +++ b/backends/graphs/graphs.cpp @@ -44,8 +44,8 @@ void Graphs::add_edge(const vertex_t &from, const vertex_t &to, const cstring &n auto attrs = boost::get(boost::edge_attribute, g->root()); - attrs[ep.first]["ltail"] = "cluster" + Util::toString(cluster_id - 2); - attrs[ep.first]["lhead"] = "cluster" + Util::toString(cluster_id - 1); + attrs[ep.first]["ltail"_cs] = "cluster"_cs + Util::toString(cluster_id - 2); + attrs[ep.first]["lhead"_cs] = "cluster"_cs + Util::toString(cluster_id - 1); } void Graphs::limitStringSize(std::stringstream &sstream, std::stringstream &helper_sstream) { diff --git a/backends/graphs/graphs.h b/backends/graphs/graphs.h index 4e4b04aff3..28adbbb33a 100644 --- a/backends/graphs/graphs.h +++ b/backends/graphs/graphs.h @@ -18,6 +18,7 @@ limitations under the License. #define BACKENDS_GRAPHS_GRAPHS_H_ #include "config.h" +#include "lib/cstring.h" /// Shouldn't happen as cmake will not try to build this backend if the boost /// graph headers couldn't be found. @@ -47,6 +48,8 @@ class TypeMap; namespace graphs { +using namespace P4::literals; + class EdgeTypeIface { public: virtual ~EdgeTypeIface() {} @@ -56,7 +59,7 @@ class EdgeTypeIface { class EdgeUnconditional : public EdgeTypeIface { public: EdgeUnconditional() = default; - cstring label() const override { return ""; }; + cstring label() const override { return cstring::empty; }; }; class EdgeIf : public EdgeTypeIface { @@ -66,12 +69,12 @@ class EdgeIf : public EdgeTypeIface { cstring label() const override { switch (branch) { case Branch::TRUE: - return "TRUE"; + return "TRUE"_cs; case Branch::FALSE: - return "FALSE"; + return "FALSE"_cs; } BUG("unreachable"); - return ""; + return cstring::empty; }; private: @@ -156,15 +159,15 @@ class Graphs : public Inspector { for (auto &vit = vertices.first; vit != vertices.second; ++vit) { const auto &vinfo = g[*vit]; auto attrs = boost::get(boost::vertex_attribute, g); - attrs[*vit]["label"] = vinfo.name; - attrs[*vit]["style"] = vertexTypeGetStyle(vinfo.type); - attrs[*vit]["shape"] = vertexTypeGetShape(vinfo.type); - attrs[*vit]["margin"] = vertexTypeGetMargin(vinfo.type); + attrs[*vit]["label"_cs] = vinfo.name; + attrs[*vit]["style"_cs] = vertexTypeGetStyle(vinfo.type); + attrs[*vit]["shape"_cs] = vertexTypeGetShape(vinfo.type); + attrs[*vit]["margin"_cs] = vertexTypeGetMargin(vinfo.type); } auto edges = boost::edges(g); for (auto &eit = edges.first; eit != edges.second; ++eit) { auto attrs = boost::get(boost::edge_attribute, g); - attrs[*eit]["label"] = boost::get(boost::edge_name, g, *eit); + attrs[*eit]["label"_cs] = boost::get(boost::edge_name, g, *eit); } } @@ -173,35 +176,35 @@ class Graphs : public Inspector { switch (type) { case VertexType::TABLE: case VertexType::ACTION: - return "ellipse"; + return "ellipse"_cs; default: - return "rectangle"; + return "rectangle"_cs; } BUG("unreachable"); - return ""; + return cstring::empty; } static cstring vertexTypeGetStyle(VertexType type) { switch (type) { case VertexType::CONTROL: - return "dashed"; + return "dashed"_cs; case VertexType::EMPTY: - return "invis"; + return "invis"_cs; case VertexType::KEY: case VertexType::CONDITION: case VertexType::SWITCH: - return "rounded"; + return "rounded"_cs; default: - return "solid"; + return "solid"_cs; } BUG("unreachable"); - return ""; + return cstring::empty; } static cstring vertexTypeGetMargin(VertexType type) { switch (type) { default: - return ""; + return cstring::empty; } } }; // end class GraphAttributeSetter diff --git a/backends/graphs/p4c-graphs.cpp b/backends/graphs/p4c-graphs.cpp index 7fd9f8cddd..a0519aefd4 100644 --- a/backends/graphs/p4c-graphs.cpp +++ b/backends/graphs/p4c-graphs.cpp @@ -71,7 +71,7 @@ class Options : public CompilerOptions { registerOption( "--graphs-dir", "dir", [this](const char *arg) { - graphsDir = arg; + graphsDir = cstring(arg); return true; }, "Use this directory to dump graphs in dot format " @@ -80,7 +80,7 @@ class Options : public CompilerOptions { "--fromJSON", "file", [this](const char *arg) { loadIRFromJson = true; - file = arg; + file = cstring(arg); return true; }, "Use IR representation from JsonFile dumped previously, " @@ -129,7 +129,7 @@ int main(int argc, char *const argv[]) { AutoCompileContext autoGraphsContext(new ::graphs::GraphsContext); auto &options = ::graphs::GraphsContext::get().options(); options.langVersion = CompilerOptions::FrontendVersion::P4_16; - options.compilerVersion = P4C_GRAPHS_VERSION_STRING; + options.compilerVersion = cstring(P4C_GRAPHS_VERSION_STRING); if (options.process(argc, argv) != nullptr) { if (options.loadIRFromJson == false) options.setInputFile(); diff --git a/backends/graphs/parsers.cpp b/backends/graphs/parsers.cpp index d49680f6ed..862e71b7af 100644 --- a/backends/graphs/parsers.cpp +++ b/backends/graphs/parsers.cpp @@ -36,10 +36,10 @@ static cstring toString(const IR::Expression *expression) { /// We always have only one subgraph. Graph *ParserGraphs::CreateSubGraph(Graph ¤tSubgraph, const cstring &name) { auto &newSubgraph = currentSubgraph.create_subgraph(); - boost::get_property(newSubgraph, boost::graph_name) = "cluster" + name; - boost::get_property(newSubgraph, boost::graph_graph_attribute)["label"] = name; - boost::get_property(newSubgraph, boost::graph_graph_attribute)["fontsize"] = "22pt"; - boost::get_property(newSubgraph, boost::graph_graph_attribute)["style"] = "bold"; + boost::get_property(newSubgraph, boost::graph_name) = "cluster"_cs + name; + boost::get_property(newSubgraph, boost::graph_graph_attribute)["label"_cs] = name; + boost::get_property(newSubgraph, boost::graph_graph_attribute)["fontsize"_cs] = "22pt"_cs; + boost::get_property(newSubgraph, boost::graph_graph_attribute)["style"_cs] = "bold"_cs; return &newSubgraph; } @@ -91,7 +91,7 @@ void ParserGraphs::postorder(const IR::PathExpression *expression) { auto sc = findContext(); cstring label; if (sc == nullptr) { - label = "always"; + label = "always"_cs; } else { label = toString(sc->keyset); } @@ -116,7 +116,7 @@ void ParserGraphs::postorder(const IR::SelectExpression *expression) { auto reject = parser->getDeclByName(IR::ParserState::reject); CHECK_NULL(reject); transitions[parser].push_back( - new TransitionEdge(state, reject->to(), "fallthrough")); + new TransitionEdge(state, reject->to(), "fallthrough"_cs)); } } // namespace graphs diff --git a/backends/p4test/midend.cpp b/backends/p4test/midend.cpp index 050595a99a..29ba7426c5 100644 --- a/backends/p4test/midend.cpp +++ b/backends/p4test/midend.cpp @@ -169,7 +169,7 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::SimplifyControlFlow(&refMap, &typeMap), new P4::MidEndLast()}); if (options.listMidendPasses) { - listPasses(*outStream, "\n"); + listPasses(*outStream, cstring::newline); *outStream << std::endl; return; } diff --git a/backends/p4test/p4test.cpp b/backends/p4test/p4test.cpp index 2656084f18..eff0ed611f 100644 --- a/backends/p4test/p4test.cpp +++ b/backends/p4test/p4test.cpp @@ -69,7 +69,7 @@ class P4TestOptions : public CompilerOptions { "--fromJSON", "file", [this](const char *arg) { loadIRFromJson = true; - file = arg; + file = cstring(arg); return true; }, "read previously dumped json instead of P4 source code"); @@ -108,7 +108,7 @@ int main(int argc, char *const argv[]) { AutoCompileContext autoP4TestContext(new P4TestContext); auto &options = P4TestContext::get().options(); options.langVersion = CompilerOptions::FrontendVersion::P4_16; - options.compilerVersion = P4TEST_VERSION_STRING; + options.compilerVersion = cstring(P4TEST_VERSION_STRING); if (options.process(argc, argv) != nullptr) { if (options.loadIRFromJson == false) options.setInputFile(); diff --git a/backends/p4tools/common/compiler/reachability.cpp b/backends/p4tools/common/compiler/reachability.cpp index bd14be3f89..0dcf3ae58b 100644 --- a/backends/p4tools/common/compiler/reachability.cpp +++ b/backends/p4tools/common/compiler/reachability.cpp @@ -17,6 +17,8 @@ namespace P4Tools { +using namespace P4::literals; + P4ProgramDCGCreator::P4ProgramDCGCreator(NodesCallGraph *dcg) : dcg(dcg), p4program(nullptr) { CHECK_NULL(dcg); setName("P4ProgramDCGCreator"); @@ -125,7 +127,7 @@ bool P4ProgramDCGCreator::preorder(const IR::P4Action *action) { bool P4ProgramDCGCreator::preorder(const IR::P4Parser *parser) { addEdge(parser, parser->name); - visit(parser->states.getDeclaration("start")); + visit(parser->states.getDeclaration("start"_cs)); return false; } diff --git a/backends/p4tools/common/compiler/reachability.h b/backends/p4tools/common/compiler/reachability.h index 188a86cb31..a18bf6fda6 100644 --- a/backends/p4tools/common/compiler/reachability.h +++ b/backends/p4tools/common/compiler/reachability.h @@ -29,7 +29,7 @@ class ExtendedCallGraph : public P4::CallGraph { ReachabilityHashType hash; public: - explicit ExtendedCallGraph(cstring name) : P4::CallGraph(name) {} + explicit ExtendedCallGraph(std::string_view name) : P4::CallGraph(name) {} const ReachabilityHashType &getHash() const { return hash; } /// Function adds current vertex to a hash which allows to get access /// for vertexes from string in DCG. diff --git a/backends/p4tools/common/control_plane/symbolic_variables.cpp b/backends/p4tools/common/control_plane/symbolic_variables.cpp index a1f735faca..0e8e2fe59a 100644 --- a/backends/p4tools/common/control_plane/symbolic_variables.cpp +++ b/backends/p4tools/common/control_plane/symbolic_variables.cpp @@ -46,11 +46,11 @@ const IR::SymbolicVariable *getTableActionChoice(cstring tableName) { namespace Bmv2ControlPlaneState { const IR::SymbolicVariable *getCloneActive() { - return ToolsVariables::getSymbolicVariable(IR::Type_Boolean::get(), "clone_session_active"); + return ToolsVariables::getSymbolicVariable(IR::Type_Boolean::get(), "clone_session_active"_cs); } const IR::SymbolicVariable *getCloneSessionId(const IR::Type *type) { - return ToolsVariables::getSymbolicVariable(type, "clone_session_id"); + return ToolsVariables::getSymbolicVariable(type, "clone_session_id"_cs); } std::pair getTableRange( diff --git a/backends/p4tools/common/lib/table_utils.cpp b/backends/p4tools/common/lib/table_utils.cpp index d003c063ad..73f6e49b22 100644 --- a/backends/p4tools/common/lib/table_utils.cpp +++ b/backends/p4tools/common/lib/table_utils.cpp @@ -4,16 +4,18 @@ namespace P4Tools::TableUtils { +using namespace P4::literals; + void checkTableImmutability(const IR::P4Table &table, TableProperties &properties) { bool isConstant = false; - const auto *entriesAnnotation = table.properties->getProperty("entries"); + const auto *entriesAnnotation = table.properties->getProperty("entries"_cs); if (entriesAnnotation != nullptr) { isConstant = entriesAnnotation->isConstant; } // Also check if the table is invisible to the control plane. // This also implies that it cannot be modified. - properties.tableIsImmutable = isConstant || table.getAnnotation("hidden") != nullptr; - const auto *defaultAction = table.properties->getProperty("default_action"); + properties.tableIsImmutable = isConstant || table.getAnnotation("hidden"_cs) != nullptr; + const auto *defaultAction = table.properties->getProperty("default_action"_cs); CHECK_NULL(defaultAction); properties.defaultIsImmutable = defaultAction->isConstant; } @@ -26,7 +28,7 @@ std::vector buildTableActionList(const IR::P4Tabl } for (size_t idx = 0; idx < actionList->size(); idx++) { const auto *action = actionList->actionList.at(idx); - if (action->getAnnotation("defaultonly") != nullptr) { + if (action->getAnnotation("defaultonly"_cs) != nullptr) { continue; } tableActionList.emplace_back(action); diff --git a/backends/p4tools/common/lib/taint.cpp b/backends/p4tools/common/lib/taint.cpp index 038b024115..10410c4a4f 100644 --- a/backends/p4tools/common/lib/taint.cpp +++ b/backends/p4tools/common/lib/taint.cpp @@ -21,7 +21,7 @@ namespace P4Tools { -const IR::StringLiteral Taint::TAINTED_STRING_LITERAL = IR::StringLiteral(cstring("Taint")); +const IR::StringLiteral Taint::TAINTED_STRING_LITERAL = IR::StringLiteral("Taint"_cs); /// Returns a bitmask that indicates which bits of given expression are tainted given a complex /// expression. diff --git a/backends/p4tools/common/lib/util.cpp b/backends/p4tools/common/lib/util.cpp index 2513191406..c6b6a5df08 100644 --- a/backends/p4tools/common/lib/util.cpp +++ b/backends/p4tools/common/lib/util.cpp @@ -90,17 +90,17 @@ const IR::Constant *Utils::getRandConstantForType(const IR::Type_Bits *type) { * ========================================================================================= */ const IR::MethodCallExpression *Utils::generateInternalMethodCall( - cstring methodName, const std::vector &argVector, + std::string_view methodName, const std::vector &argVector, const IR::Type *returnType, const IR::ParameterList *paramList) { auto *args = new IR::Vector(); for (const auto *expr : argVector) { args->push_back(new IR::Argument(expr)); } + cstring name(methodName); return new IR::MethodCallExpression( returnType, - new IR::Member(new IR::Type_Method(paramList, methodName), - new IR::PathExpression(new IR::Type_Extern("*"), new IR::Path("*")), - methodName), + new IR::Member(new IR::Type_Method(paramList, name), + new IR::PathExpression(new IR::Type_Extern("*"), new IR::Path("*")), name), args); } diff --git a/backends/p4tools/common/lib/util.h b/backends/p4tools/common/lib/util.h index 69d1bdea0a..b007fb67cf 100644 --- a/backends/p4tools/common/lib/util.h +++ b/backends/p4tools/common/lib/util.h @@ -88,7 +88,7 @@ class Utils { /// @returns a method call to an internal extern consumed by the interpreter. The return type /// is typically Type_Void. static const IR::MethodCallExpression *generateInternalMethodCall( - cstring methodName, const std::vector &argVector, + std::string_view methodName, const std::vector &argVector, const IR::Type *returnType = IR::Type_Void::get(), const IR::ParameterList *paramList = new IR::ParameterList()); diff --git a/backends/p4tools/common/lib/variables.h b/backends/p4tools/common/lib/variables.h index 254de3d9e4..f7c90c3588 100644 --- a/backends/p4tools/common/lib/variables.h +++ b/backends/p4tools/common/lib/variables.h @@ -9,6 +9,8 @@ /// variables are also used for SMT solvers as symbolic variables. namespace P4Tools { +using namespace P4::literals; + /// A list of constraints. These constraints may take the form of "x == 8w1","x != y", where "x" and /// "y" are symbolic variables. They are expressed in P4C IR form and may be consumed by SMT or /// similar solvers. @@ -19,7 +21,7 @@ namespace ToolsVariables { /// To represent header validity, we pretend that every header has a field that reflects the /// header's validity state. This is the name of that field. This is not a valid P4 identifier, /// so it is guaranteed to not conflict with any other field in the header. -static const cstring VALID = "*valid"; +static const cstring VALID = "*valid"_cs; /// @returns the variable with the given @type, @incarnation, and @name. /// diff --git a/backends/p4tools/common/options.cpp b/backends/p4tools/common/options.cpp index 710af5ef86..b4671dab6b 100644 --- a/backends/p4tools/common/options.cpp +++ b/backends/p4tools/common/options.cpp @@ -76,7 +76,7 @@ std::optional AbstractP4cToolOptions::process( usage(); return std::nullopt; } - P4CContext::get().options().file = remainingArgs->at(0); + P4CContext::get().options().file = cstring(remainingArgs->at(0)); if (!validateOptions()) { return std::nullopt; @@ -108,7 +108,7 @@ struct InheritedCompilerOptionSpec { std::optional> handler; }; -AbstractP4cToolOptions::AbstractP4cToolOptions(std::string_view toolName, cstring message) +AbstractP4cToolOptions::AbstractP4cToolOptions(std::string_view toolName, std::string_view message) : Options(message), _toolName(toolName) { // Register some common options. registerOption( diff --git a/backends/p4tools/common/options.h b/backends/p4tools/common/options.h index a1b145a743..050ea9f3b8 100644 --- a/backends/p4tools/common/options.h +++ b/backends/p4tools/common/options.h @@ -56,7 +56,7 @@ class AbstractP4cToolOptions : protected Util::Options { /// Converts a vector of command-line arguments into the traditional (argc, argv) format. static std::tuple convertArgs(const std::vector &args); - explicit AbstractP4cToolOptions(std::string_view toolName, cstring message); + explicit AbstractP4cToolOptions(std::string_view toolName, std::string_view message); }; } // namespace P4Tools diff --git a/backends/p4tools/modules/testgen/core/small_step/abstract_stepper.cpp b/backends/p4tools/modules/testgen/core/small_step/abstract_stepper.cpp index 4a907f5df7..b8e8dbb75e 100644 --- a/backends/p4tools/modules/testgen/core/small_step/abstract_stepper.cpp +++ b/backends/p4tools/modules/testgen/core/small_step/abstract_stepper.cpp @@ -83,7 +83,7 @@ bool AbstractStepper::stepToSubexpr( const IR::Expression *subexpr, SmallStepEvaluator::Result &result, const ExecutionState &state, std::function rebuildCmd) { // Create a parameter for the continuation we're about to build. - const auto *v = Continuation::genParameter(subexpr->type, "v", state.getNamespaceContext()); + const auto *v = Continuation::genParameter(subexpr->type, "v"_cs, state.getNamespaceContext()); // Create the continuation itself. Continuation::Body kBody(state.getBody()); diff --git a/backends/p4tools/modules/testgen/core/small_step/cmd_stepper.cpp b/backends/p4tools/modules/testgen/core/small_step/cmd_stepper.cpp index 4b0115a02d..9ffb551e06 100644 --- a/backends/p4tools/modules/testgen/core/small_step/cmd_stepper.cpp +++ b/backends/p4tools/modules/testgen/core/small_step/cmd_stepper.cpp @@ -103,7 +103,7 @@ bool CmdStepper::preorder(const IR::P4Parser *p4parser) { nextState.pushCurrentContinuation(handlers); // Set the start state as the new body. - const auto *startState = p4parser->states.getDeclaration("start"); + const auto *startState = p4parser->states.getDeclaration("start"_cs); std::vector cmds; // Initialize parser-local declarations. @@ -194,14 +194,14 @@ bool CmdStepper::preorder(const IR::IfStatement *ifStatement) { if (Taint::hasTaint(ifStatement->condition)) { auto &nextState = state.clone(); std::vector cmds; - auto currentTaint = state.getProperty("inUndefinedState"); + auto currentTaint = state.getProperty("inUndefinedState"_cs); nextState.add(*new TraceEvents::IfStatementCondition(ifStatement->condition)); - cmds.emplace_back(Continuation::PropertyUpdate("inUndefinedState", true)); + cmds.emplace_back(Continuation::PropertyUpdate("inUndefinedState"_cs, true)); cmds.emplace_back(ifStatement->ifTrue); if (ifStatement->ifFalse != nullptr) { cmds.emplace_back(ifStatement->ifFalse); } - cmds.emplace_back(Continuation::PropertyUpdate("inUndefinedState", currentTaint)); + cmds.emplace_back(Continuation::PropertyUpdate("inUndefinedState"_cs, currentTaint)); nextState.replaceTopBody(&cmds); result->emplace_back(nextState); return false; @@ -376,7 +376,7 @@ bool CmdStepper::preorder(const IR::ParserState *parserState) { if (select->is()) { // Push a new continuation that will take the next state as an argument and execute the // state as a command. Create a parameter for the continuation we're about to build. - const auto *v = Continuation::genParameter(IR::Type_State::get(), "nextState", + const auto *v = Continuation::genParameter(IR::Type_State::get(), "nextState"_cs, state.getNamespaceContext()); // Create the continuation itself. @@ -432,7 +432,7 @@ bool CmdStepper::preorder(const IR::ExitStatement *e) { logStep(e); auto &nextState = state.clone(); nextState.markVisited(e); - nextState.add(*new TraceEvents::Generic("Exit")); + nextState.add(*new TraceEvents::Generic("Exit"_cs)); nextState.replaceTopBody(Continuation::Exception::Exit); result->emplace_back(nextState); return false; @@ -492,15 +492,15 @@ bool CmdStepper::preorder(const IR::SwitchStatement *switchStatement) { // If the switch expression is tainted, we can not predict which case will be chosen. We taint // the program counter and execute all of the statements. if (Taint::hasTaint(switchExpr)) { - auto currentTaint = state.getProperty("inUndefinedState"); - cmds.emplace_back(Continuation::PropertyUpdate("inUndefinedState", true)); + auto currentTaint = state.getProperty("inUndefinedState"_cs); + cmds.emplace_back(Continuation::PropertyUpdate("inUndefinedState"_cs, true)); for (const auto *switchCase : switchCases) { if (switchCase->statement != nullptr) { cmds.emplace_back(switchCase->statement); } } - state.add(*new TraceEvents::Generic("TaintedSwitchCase")); - cmds.emplace_back(Continuation::PropertyUpdate("inUndefinedState", currentTaint)); + state.add(*new TraceEvents::Generic("TaintedSwitchCase"_cs)); + cmds.emplace_back(Continuation::PropertyUpdate("inUndefinedState"_cs, currentTaint)); state.replaceTopBody(&cmds); return false; } @@ -527,7 +527,7 @@ bool CmdStepper::preorder(const IR::SwitchStatement *switchStatement) { collector.updateNodeCoverage(switchCase->statement, coveredNodes); } nextState.add(*new TraceEvents::GenericDescription( - "SwitchCase", switchCase->label->getSourceInfo().toBriefSourceFragment())); + "SwitchCase"_cs, switchCase->label->getSourceInfo().toBriefSourceFragment())); cmds.emplace_back(switchCase->statement); // If the statement is a block, we do not fall through and terminate execution. if (switchCase->statement->is()) { @@ -536,7 +536,7 @@ bool CmdStepper::preorder(const IR::SwitchStatement *switchStatement) { } // The default label must be last. Always break here. if (switchCase->label->is()) { - nextState.add(*new TraceEvents::GenericDescription("SwitchCase", "default")); + nextState.add(*new TraceEvents::GenericDescription("SwitchCase"_cs, "default"_cs)); cmds.emplace_back(switchCase->statement); break; } diff --git a/backends/p4tools/modules/testgen/core/small_step/expr_stepper.cpp b/backends/p4tools/modules/testgen/core/small_step/expr_stepper.cpp index 9b101a52ba..3e3c64dda6 100644 --- a/backends/p4tools/modules/testgen/core/small_step/expr_stepper.cpp +++ b/backends/p4tools/modules/testgen/core/small_step/expr_stepper.cpp @@ -510,7 +510,7 @@ bool ExprStepper::preorder(const IR::Slice *slice) { void ExprStepper::stepNoMatch(std::string traceLog, const IR::Expression *condition) { auto &noMatchState = condition ? state.clone() : state; - noMatchState.add(*new TraceEvents::GenericDescription("NoMatch", traceLog)); + noMatchState.add(*new TraceEvents::GenericDescription("NoMatch"_cs, traceLog)); noMatchState.replaceTopBody(Continuation::Exception::NoMatch); if (condition) { result->emplace_back(condition, state, noMatchState); diff --git a/backends/p4tools/modules/testgen/core/small_step/extern_stepper.cpp b/backends/p4tools/modules/testgen/core/small_step/extern_stepper.cpp index 47f9ef1703..59145092ab 100644 --- a/backends/p4tools/modules/testgen/core/small_step/extern_stepper.cpp +++ b/backends/p4tools/modules/testgen/core/small_step/extern_stepper.cpp @@ -154,8 +154,8 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c * the prepending of metadata that some P4 targets perform. * ====================================================================================== */ - {"*.prepend_to_prog_header", - {"hdr"}, + {"*.prepend_to_prog_header"_cs, + {"hdr"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -164,7 +164,7 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c auto &nextState = state.clone(); const auto *prependType = state.resolveType(prependVar->type); - nextState.add(*new TraceEvents::Expression(prependVar, "PrependToProgramHeader")); + nextState.add(*new TraceEvents::Expression(prependVar, "PrependToProgramHeader"_cs)); // Prepend the field to the packet buffer. if (const auto *structExpr = prependVar->to()) { auto exprList = IR::flattenStructExpression(structExpr); @@ -188,8 +188,8 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c * the appending of metadata that some P4 targets perform. * ====================================================================================== */ - {"*.append_to_prog_header", - {"hdr"}, + {"*.append_to_prog_header"_cs, + {"hdr"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -198,7 +198,7 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c auto &nextState = state.clone(); const auto *appendType = state.resolveType(appendVar->type); - nextState.add(*new TraceEvents::Expression(appendVar, "AppendToProgramHeader")); + nextState.add(*new TraceEvents::Expression(appendVar, "AppendToProgramHeader"_cs)); // Append the field to the packet buffer. if (const auto *structExpr = appendVar->to()) { auto exprList = IR::flattenStructExpression(structExpr); @@ -221,7 +221,7 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c * the output packet, which can either be emitted or forwarded to the next parser. * ====================================================================================== */ - {"*.prepend_emit_buffer", + {"*.prepend_emit_buffer"_cs, {}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, @@ -230,7 +230,7 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c const auto *emitBuffer = state.getEmitBuffer(); nextState.prependToPacketBuffer(emitBuffer); nextState.add( - *new TraceEvents::Generic("Prepending the emit buffer to the program packet")); + *new TraceEvents::Generic("Prepending the emit buffer to the program packet"_cs)); nextState.popBody(); result->emplace_back(nextState); }}, @@ -240,7 +240,7 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c * We do this by clearing the packet variable and pushing an exit continuation. * ====================================================================================== */ - {"*.drop_and_exit", + {"*.drop_and_exit"_cs, {}, [this](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, @@ -253,8 +253,8 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c programInfo.createTargetUninitialized( programInfo.getTargetOutputPortVar()->type, true)); } - nextState.add(*new TraceEvents::Generic("Packet marked dropped")); - nextState.setProperty("drop", true); + nextState.add(*new TraceEvents::Generic("Packet marked dropped"_cs)); + nextState.setProperty("drop"_cs, true); nextState.replaceTopBody(Continuation::Exception::Drop); result->emplace_back(nextState); }}, @@ -265,8 +265,8 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c * appropriately. * ====================================================================================== */ - {"*.copy_in", - {"blockRef"}, + {"*.copy_in"_cs, + {"blockRef"_cs}, [this](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -282,14 +282,14 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c // Copy-in. // Get the current level and disable it for these operations to avoid overtainting. - auto currentTaint = state.getProperty("inUndefinedState"); - nextState.setProperty("inUndefinedState", false); + auto currentTaint = state.getProperty("inUndefinedState"_cs); + nextState.setProperty("inUndefinedState"_cs, false); for (size_t paramIdx = 0; paramIdx < blockParams->size(); ++paramIdx) { const auto *internalParam = blockParams->getParameter(paramIdx); auto externalParamName = archSpec.getParamName(canonicalName, paramIdx); nextState.copyIn(TestgenTarget::get(), internalParam, externalParamName); } - nextState.setProperty("inUndefinedState", currentTaint); + nextState.setProperty("inUndefinedState"_cs, currentTaint); nextState.popBody(); result->emplace_back(nextState); }}, @@ -300,8 +300,8 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c * appropriately. * ====================================================================================== */ - {"*.copy_out", - {"blockRef"}, + {"*.copy_out"_cs, + {"blockRef"_cs}, [this](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -317,14 +317,14 @@ void ExprStepper::evalInternalExternMethodCall(const IR::MethodCallExpression *c // Copy-in. // Get the current level and disable it for these operations to avoid overtainting. - auto currentTaint = state.getProperty("inUndefinedState"); - nextState.setProperty("inUndefinedState", false); + auto currentTaint = state.getProperty("inUndefinedState"_cs); + nextState.setProperty("inUndefinedState"_cs, false); for (size_t paramIdx = 0; paramIdx < blockParams->size(); ++paramIdx) { const auto *internalParam = blockParams->getParameter(paramIdx); auto externalParamName = archSpec.getParamName(canonicalName, paramIdx); nextState.copyOut(internalParam, externalParamName); } - nextState.setProperty("inUndefinedState", currentTaint); + nextState.setProperty("inUndefinedState"_cs, currentTaint); nextState.popBody(); result->emplace_back(nextState); }}, @@ -350,7 +350,7 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, * T lookahead(); * ====================================================================================== */ - {"packet_in.lookahead", + {"packet_in.lookahead"_cs, {}, [this](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, @@ -376,7 +376,7 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, auto &nextState = state.clone(); // Peek into the buffer, we do NOT slice from it. const auto *lookaheadVar = nextState.peekPacketBuffer(lookaheadSize); - nextState.add(*new TraceEvents::Expression(lookaheadVar, "Lookahead result")); + nextState.add(*new TraceEvents::Expression(lookaheadVar, "Lookahead result"_cs)); // Record the condition we are passing at this at this point. nextState.add(*new TraceEvents::Generic(condStream.str())); nextState.replaceTopBody(Continuation::Return(lookaheadVar)); @@ -386,7 +386,7 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, if (condInfo.advanceFailCond != nullptr) { auto &rejectState = state.clone(); // Record the condition we are failing at this at this point. - rejectState.add(*new TraceEvents::Generic("Lookahead: Packet too short")); + rejectState.add(*new TraceEvents::Generic("Lookahead: Packet too short"_cs)); rejectState.replaceTopBody(Continuation::Exception::PacketTooShort); result->emplace_back(condInfo.advanceFailCond, state, rejectState); } @@ -396,8 +396,8 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, * Advance the packet cursor by the specified number of bits. * ====================================================================================== */ - {"packet_in.advance", - {"sizeInBits"}, + {"packet_in.advance"_cs, + {"sizeInBits"_cs}, [this](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -459,7 +459,7 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, // Advancing by zero can be considered a no-op. if (condInfo.advanceSize == 0) { auto &nextState = state.clone(); - nextState.add(*new TraceEvents::Generic("Advance: 0 bits.")); + nextState.add(*new TraceEvents::Generic("Advance: 0 bits."_cs)); nextState.popBody(); result->emplace_back(nextState); } else { @@ -477,7 +477,7 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, // Handle the case where the packet is too short. auto &rejectState = state.clone(); // Record the condition we are failing at this at this point. - rejectState.add(*new TraceEvents::Generic("Advance: Packet too short")); + rejectState.add(*new TraceEvents::Generic("Advance: Packet too short"_cs)); rejectState.replaceTopBody(Continuation::Exception::PacketTooShort); result->emplace_back(condInfo.advanceFailCond, state, rejectState); } @@ -489,8 +489,8 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, * remains in the most recent position until we enter a new start parser. * ====================================================================================== */ - {"packet_in.extract", - {"hdr"}, + {"packet_in.extract"_cs, + {"hdr"_cs}, [this](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -545,8 +545,8 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, result->emplace_back(condInfo.advanceFailCond, state, rejectState); } }}, - {"packet_in.extract", - {"hdr", "sizeInBits"}, + {"packet_in.extract"_cs, + {"hdr"_cs, "sizeInBits"_cs}, [this](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -674,7 +674,7 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, * some target architectures. * ====================================================================================== */ - {"packet_in.length", + {"packet_in.length"_cs, {}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*name*/, const IR::Vector * /*args*/, @@ -684,7 +684,7 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, const auto *divVar = new IR::Div(lengthVar->type, ExecutionState::getInputPacketSizeVar(), IR::Constant::get(lengthVar->type, 8)); - nextState.add(*new TraceEvents::Expression(divVar, "Return packet length")); + nextState.add(*new TraceEvents::Expression(divVar, "Return packet length"_cs)); nextState.replaceTopBody(Continuation::Return(divVar)); result->emplace_back(std::nullopt, state, nextState); }}, @@ -694,8 +694,8 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, * We use a concatenation for this. * ====================================================================================== */ - {"packet_out.emit", - {"hdr"}, + {"packet_out.emit"_cs, + {"hdr"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -774,8 +774,8 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, * argument. * ====================================================================================== */ - {"*method.verify", - {"bool", "error"}, + {"*method.verify"_cs, + {"bool"_cs, "error"_cs}, [this](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*name*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -824,8 +824,8 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, /* ====================================================================================== * assume * ====================================================================================== */ - {"*method.testgen_assume", - {"check"}, + {"*method.testgen_assume"_cs, + {"check"_cs}, [](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -870,8 +870,8 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, /* ====================================================================================== * assert * ====================================================================================== */ - {"*method.testgen_assert", - {"check"}, + {"*method.testgen_assert"_cs, + {"check"_cs}, [](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -917,7 +917,7 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, cond->dbprint(condStream); nextState.add(*new TraceEvents::Generic(condStream.str())); // Do not bother executing further. We have triggered an assertion. - nextState.setProperty("assertionTriggered", true); + nextState.setProperty("assertionTriggered"_cs, true); nextState.replaceTopBody(Continuation::Exception::Abort); result->emplace_back(new IR::LNot(cond), state, nextState); } diff --git a/backends/p4tools/modules/testgen/core/small_step/table_stepper.cpp b/backends/p4tools/modules/testgen/core/small_step/table_stepper.cpp index 2ed93b978f..eab57bc4ea 100644 --- a/backends/p4tools/modules/testgen/core/small_step/table_stepper.cpp +++ b/backends/p4tools/modules/testgen/core/small_step/table_stepper.cpp @@ -68,15 +68,15 @@ const IR::StateVariable &TableStepper::getTableActionVar(const IR::P4Table *tabl size_t max = 255; BUG_CHECK(numActions < max, "Number of actions in the table (%1%) exceeds the maximum of %2%.", numActions, max); - return getTableStateVariable(IR::Type_Bits::get(8), table, "*action"); + return getTableStateVariable(IR::Type_Bits::get(8), table, "*action"_cs); } const IR::StateVariable &TableStepper::getTableResultVar(const IR::P4Table *table) { - return getTableStateVariable(IR::Type::Boolean::get(), table, "*result"); + return getTableStateVariable(IR::Type::Boolean::get(), table, "*result"_cs); } const IR::StateVariable &TableStepper::getTableHitVar(const IR::P4Table *table) { - return getTableStateVariable(IR::Type::Boolean::get(), table, "*hit"); + return getTableStateVariable(IR::Type::Boolean::get(), table, "*hit"_cs); } const IR::Expression *TableStepper::computeTargetMatchType( @@ -272,8 +272,8 @@ void TableStepper::setTableDefaultEntries( // Finally, add all the new rules to the execution stepper->state. auto *tableConfig = new TableConfig(table, {}); // Add the action selector to the table. This signifies a slightly different implementation. - tableConfig->addTableProperty("overriden_default_action", ctrlPlaneActionCall); - nextState.addTestObject("tableconfigs", properties.tableName, tableConfig); + tableConfig->addTableProperty("overriden_default_action"_cs, ctrlPlaneActionCall); + nextState.addTestObject("tableconfigs"_cs, properties.tableName, tableConfig); // Update all the tracking variables for tables. std::vector replacements; @@ -340,7 +340,7 @@ void TableStepper::evalTableControlEntries( auto tableRule = TableRule(matches, TestSpec::LOW_PRIORITY, ctrlPlaneActionCall, TestSpec::TTL); auto *tableConfig = new TableConfig(table, {tableRule}); - nextState.addTestObject("tableconfigs", properties.tableName, tableConfig); + nextState.addTestObject("tableconfigs"_cs, properties.tableName, tableConfig); // Update all the tracking variables for tables. std::vector replacements; @@ -389,8 +389,8 @@ void TableStepper::evalTaintedTable() { // If the table is immutable, we execute all the constant entries in its list. // We get the current value of the inUndefinedState property. - auto currentTaint = stepper->state.getProperty("inUndefinedState"); - replacements.emplace_back(Continuation::PropertyUpdate("inUndefinedState", true)); + auto currentTaint = stepper->state.getProperty("inUndefinedState"_cs); + replacements.emplace_back(Continuation::PropertyUpdate("inUndefinedState"_cs, true)); const auto *entries = table->getEntries(); // Sometimes, there are no entries. Just return. @@ -414,7 +414,7 @@ void TableStepper::evalTaintedTable() { nextState.set(hitVar, stepper->programInfo.createTargetUninitialized(hitVar->type, true)); // Reset the property to its previous stepper->state. - replacements.emplace_back(Continuation::PropertyUpdate("inUndefinedState", currentTaint)); + replacements.emplace_back(Continuation::PropertyUpdate("inUndefinedState"_cs, currentTaint)); nextState.replaceTopBody(&replacements); stepper->result->emplace_back(nextState); } @@ -466,7 +466,7 @@ bool TableStepper::resolveTableKeys() { return true; } - const auto *nameAnnot = keyElement->getAnnotation("name"); + const auto *nameAnnot = keyElement->getAnnotation("name"_cs); // Some hidden tables do not have any key name annotations. BUG_CHECK(nameAnnot != nullptr || properties.tableIsImmutable, "Non-constant table key without an annotation"); diff --git a/backends/p4tools/modules/testgen/lib/execution_state.cpp b/backends/p4tools/modules/testgen/lib/execution_state.cpp index 6fb6c5db01..97e7e4d923 100644 --- a/backends/p4tools/modules/testgen/lib/execution_state.cpp +++ b/backends/p4tools/modules/testgen/lib/execution_state.cpp @@ -70,25 +70,25 @@ ExecutionState::ExecutionState(const IR::P4Program *program) env.set(&PacketVars::INPUT_PACKET_LABEL, IR::Constant::get(IR::Type_Bits::get(0), 0)); env.set(&PacketVars::PACKET_BUFFER_LABEL, IR::Constant::get(IR::Type_Bits::get(0), 0)); // We also add the taint property and set it to false. - setProperty("inUndefinedState", false); + setProperty("inUndefinedState"_cs, false); // Drop is initialized to false, too. - setProperty("drop", false); + setProperty("drop"_cs, false); // If a user-pattern is provided, initialize the reachability engine state. if (!TestgenOptions::get().pattern.empty()) { reachabilityEngineState = ReachabilityEngineState::getInitial(); } // If assertion mode is enabled, set the assertion property to false. if (TestgenOptions::get().assertionModeEnabled) { - setProperty("assertionTriggered", false); + setProperty("assertionTriggered"_cs, false); } } ExecutionState::ExecutionState(Continuation::Body body) : body(std::move(body)), stack(*(new std::stack>())) { // We also add the taint property and set it to false. - setProperty("inUndefinedState", false); + setProperty("inUndefinedState"_cs, false); // Drop is initialized to false, too. - setProperty("drop", false); + setProperty("drop"_cs, false); // If a user-pattern is provided, initialize the reachability engine state. if (!TestgenOptions::get().pattern.empty()) { reachabilityEngineState = ReachabilityEngineState::getInitial(); @@ -200,7 +200,7 @@ void ExecutionState::set(const IR::StateVariable &var, const IR::Expression *val const auto *type = value->type; BUG_CHECK(type && !type->is(), "Cannot set value with unspecified type: %1%", value); - if (getProperty("inUndefinedState")) { + if (getProperty("inUndefinedState"_cs)) { // If we are in an undefined state, the variable we set is tainted. value = ToolsVariables::getTaintExpression(type); } else { @@ -304,7 +304,7 @@ void ExecutionState::pushCurrentContinuation(std::optional par std::optional parameterOpt = std::nullopt; if (parameterType_opt) { const auto *parameter = - Continuation::genParameter(*parameterType_opt, "_", getNamespaceContext()); + Continuation::genParameter(*parameterType_opt, "_"_cs, getNamespaceContext()); parameterOpt = parameter; } @@ -369,7 +369,7 @@ void ExecutionState::pushBranchDecision(uint64_t bIdx) { selectedBranches.push_b const IR::SymbolicVariable *ExecutionState::getInputPacketSizeVar() { return ToolsVariables::getSymbolicVariable(&PacketVars::PACKET_SIZE_VAR_TYPE, - "*packetLen_bits"); + "*packetLen_bits"_cs); } int ExecutionState::getMaxPacketLength() { return TestgenOptions::get().maxPktSize; } diff --git a/backends/p4tools/modules/testgen/lib/packet_vars.cpp b/backends/p4tools/modules/testgen/lib/packet_vars.cpp index fc5ba29268..162a8d7007 100644 --- a/backends/p4tools/modules/testgen/lib/packet_vars.cpp +++ b/backends/p4tools/modules/testgen/lib/packet_vars.cpp @@ -4,6 +4,8 @@ namespace P4Tools::P4Testgen { +using namespace P4::literals; + // The methods in P4's packet_in uses 32-bit values. Conform with this to make it easier to produce // well-typed expressions when manipulating the parser cursor. const IR::Type_Bits PacketVars::PACKET_SIZE_VAR_TYPE = IR::Type_Bits(32, false); @@ -18,6 +20,6 @@ const IR::Member PacketVars::EMIT_BUFFER_LABEL = IR::Member(new IR::PathExpression("*"), "emitBuffer"); const IR::SymbolicVariable PacketVars::PAYLOAD_SYMBOL = - IR::SymbolicVariable(&PacketVars::PACKET_SIZE_VAR_TYPE, "*payload"); + IR::SymbolicVariable(&PacketVars::PACKET_SIZE_VAR_TYPE, "*payload"_cs); } // namespace P4Tools::P4Testgen diff --git a/backends/p4tools/modules/testgen/lib/test_backend.cpp b/backends/p4tools/modules/testgen/lib/test_backend.cpp index b5ab60fa1b..4701ae4b40 100644 --- a/backends/p4tools/modules/testgen/lib/test_backend.cpp +++ b/backends/p4tools/modules/testgen/lib/test_backend.cpp @@ -54,7 +54,7 @@ bool TestBackEnd::run(const FinalState &state) { // produce a test with an output packet. if (testgenOptions.outputPacketOnly) { if (executionState->getPacketBufferSize() <= 0 || - executionState->getProperty("drop")) { + executionState->getProperty("drop"_cs)) { return needsToTerminate(testCount); } } @@ -62,14 +62,14 @@ bool TestBackEnd::run(const FinalState &state) { // Don't increase the test count if --dropped-packet-only is enabled and we produce a test // with an output packet. if (testgenOptions.droppedPacketOnly) { - if (!executionState->getProperty("drop")) { + if (!executionState->getProperty("drop"_cs)) { return needsToTerminate(testCount); } } // If assertion mode is active, ignore any test that does not trigger an assertion. if (testgenOptions.assertionModeEnabled) { - if (!executionState->getProperty("assertionTriggered")) { + if (!executionState->getProperty("assertionTriggered"_cs)) { return needsToTerminate(testCount); } printFeature("test_info", 4, @@ -217,10 +217,10 @@ TestBackEnd::TestInfo TestBackEnd::produceTestInfo( auto inputPortInt = IR::getIntFromLiteral(inputPort); auto outputPortInt = IR::getIntFromLiteral(outputPortVar); - return {inputPacket->checkedTo(), inputPortInt, - outputPacket->checkedTo(), outputPortInt, - evalMask->checkedTo(), *programTraces, - executionState->getProperty("drop")}; + return {inputPacket->checkedTo(), inputPortInt, + outputPacket->checkedTo(), outputPortInt, + evalMask->checkedTo(), *programTraces, + executionState->getProperty("drop"_cs)}; } bool TestBackEnd::printTestInfo(const ExecutionState * /*executionState*/, const TestInfo &testInfo, diff --git a/backends/p4tools/modules/testgen/lib/test_framework.h b/backends/p4tools/modules/testgen/lib/test_framework.h index 516337c079..229edeee7c 100644 --- a/backends/p4tools/modules/testgen/lib/test_framework.h +++ b/backends/p4tools/modules/testgen/lib/test_framework.h @@ -23,6 +23,8 @@ namespace P4Tools::P4Testgen { +using namespace P4::literals; + /// Type definitions for abstract tests. struct AbstractTest : ICastable {}; /// TODO: It would be nice if this were a reference to signal non-nullness. @@ -77,14 +79,14 @@ class TestFramework { template static void checkForTableActionProfile(inja::json &tblJson, std::map &apAsMap, const TableConfig *tblConfig) { - const auto *apObject = tblConfig->getProperty("action_profile", false); + const auto *apObject = tblConfig->getProperty("action_profile"_cs, false); if (apObject != nullptr) { const auto *actionProfile = apObject->checkedTo(); tblJson["has_ap"] = true; // Check if we have an Action Selector too. // TODO: Change this to check in ActionSelector with table // property "action_selectors". - const auto *asObject = tblConfig->getProperty("action_selector", false); + const auto *asObject = tblConfig->getProperty("action_selector"_cs, false); if (asObject != nullptr) { const auto *actionSelector = asObject->checkedTo(); apAsMap[actionProfile->getProfileDecl()->controlPlaneName()] = @@ -97,7 +99,8 @@ class TestFramework { /// Check whether the table object has an overridden default action. /// In this case, we assume there are no keys and we just set the default action of the table. static void checkForDefaultActionOverride(inja::json &tblJson, const TableConfig *tblConfig) { - const auto *defaultOverrideObj = tblConfig->getProperty("overriden_default_action", false); + const auto *defaultOverrideObj = + tblConfig->getProperty("overriden_default_action"_cs, false); if (defaultOverrideObj != nullptr) { const auto *defaultAction = defaultOverrideObj->checkedTo(); inja::json a; @@ -120,7 +123,7 @@ class TestFramework { static void collectActionProfileDeclarations(const TestSpec *testSpec, inja::json &controlPlaneJson, const std::map &apAsMap) { - auto actionProfiles = testSpec->getTestObjectCategory("action_profiles"); + auto actionProfiles = testSpec->getTestObjectCategory("action_profiles"_cs); if (!actionProfiles.empty()) { controlPlaneJson["action_profiles"] = inja::json::array(); } diff --git a/backends/p4tools/modules/testgen/lib/test_spec.cpp b/backends/p4tools/modules/testgen/lib/test_spec.cpp index 4acb1a7e16..2bff6db08f 100644 --- a/backends/p4tools/modules/testgen/lib/test_spec.cpp +++ b/backends/p4tools/modules/testgen/lib/test_spec.cpp @@ -16,6 +16,8 @@ namespace P4Tools::P4Testgen { +using namespace P4::literals; + /* ========================================================================================= * Test Specification Objects * ========================================================================================= */ @@ -23,7 +25,7 @@ namespace P4Tools::P4Testgen { Packet::Packet(int port, const IR::Expression *payload, const IR::Expression *payloadIgnoreMask) : port(port), payload(payload), payloadIgnoreMask(payloadIgnoreMask) {} -cstring Packet::getObjectName() const { return "Packet"; } +cstring Packet::getObjectName() const { return "Packet"_cs; } int Packet::getPort() const { return port; } @@ -74,7 +76,7 @@ const IR::Constant *ActionArg::getEvaluatedValue() const { return constant; } -cstring ActionArg::getObjectName() const { return "ActionArg"; } +cstring ActionArg::getObjectName() const { return "ActionArg"_cs; } const ActionArg *ActionArg::evaluate(const Model &model, bool doComplete) const { const auto &newValue = model.evaluate(value, doComplete); @@ -100,7 +102,7 @@ const ActionCall *ActionCall::evaluate(const Model &model, bool doComplete) cons return new ActionCall(identifier, action, evaluatedArgs); } -cstring ActionCall::getObjectName() const { return "ActionCall"; } +cstring ActionCall::getObjectName() const { return "ActionCall"_cs; } const std::vector *ActionCall::getArgs() const { return &args; } @@ -135,7 +137,7 @@ const Ternary *Ternary::evaluate(const Model &model, bool doComplete) const { return new Ternary(getKey(), evaluatedValue, evaluatedMask); } -cstring Ternary::getObjectName() const { return "Ternary"; } +cstring Ternary::getObjectName() const { return "Ternary"_cs; } LPM::LPM(const IR::KeyElement *key, const IR::Expression *value, const IR::Expression *prefixLength) : TableMatch(key), value(value), prefixLength(prefixLength) {} @@ -164,7 +166,7 @@ const LPM *LPM::evaluate(const Model &model, bool doComplete) const { return new LPM(getKey(), evaluatedValue, evaluatedPrefixLength); } -cstring LPM::getObjectName() const { return "LPM"; } +cstring LPM::getObjectName() const { return "LPM"_cs; } Exact::Exact(const IR::KeyElement *key, const IR::Expression *val) : TableMatch(key), value(val) {} @@ -182,7 +184,7 @@ const Exact *Exact::evaluate(const Model &model, bool doComplete) const { return new Exact(getKey(), evaluatedValue); } -cstring Exact::getObjectName() const { return "Exact"; } +cstring Exact::getObjectName() const { return "Exact"_cs; } TableRule::TableRule(TableMatchMap matches, int priority, ActionCall action, int ttl) : matches(std::move(matches)), priority(priority), action(std::move(action)), ttl(ttl) {} @@ -195,7 +197,7 @@ const ActionCall *TableRule::getActionCall() const { return &action; } int TableRule::getTTL() const { return ttl; } -cstring TableRule::getObjectName() const { return "TableRule"; } +cstring TableRule::getObjectName() const { return "TableRule"_cs; } const TableRule *TableRule::evaluate(const Model &model, bool doComplete) const { TableMatchMap evaluatedMatches; @@ -212,7 +214,7 @@ const TableRule *TableRule::evaluate(const Model &model, bool doComplete) const const IR::P4Table *TableConfig::getTable() const { return table; } -cstring TableConfig::getObjectName() const { return "TableConfig"; } +cstring TableConfig::getObjectName() const { return "TableConfig"_cs; } TableConfig::TableConfig(const IR::P4Table *table, std::vector rules) : table(table), rules(std::move(rules)) {} diff --git a/backends/p4tools/modules/testgen/options.cpp b/backends/p4tools/modules/testgen/options.cpp index faa37f665d..518b92ad45 100644 --- a/backends/p4tools/modules/testgen/options.cpp +++ b/backends/p4tools/modules/testgen/options.cpp @@ -17,6 +17,8 @@ namespace P4Tools::P4Testgen { +using namespace P4::literals; + TestgenOptions &TestgenOptions::get() { static TestgenOptions INSTANCE; return INSTANCE; @@ -26,7 +28,7 @@ const char *TestgenOptions::getIncludePath() { P4C_UNIMPLEMENTED("getIncludePath not implemented for P4Testgen."); } -const std::set TestgenOptions::SUPPORTED_STOP_METRICS = {"MAX_NODE_COVERAGE"}; +const std::set TestgenOptions::SUPPORTED_STOP_METRICS = {"MAX_NODE_COVERAGE"_cs}; TestgenOptions::TestgenOptions() : AbstractP4cToolOptions(TOOL_NAME, "Generate packet tests for a P4 program.") { @@ -182,7 +184,7 @@ TestgenOptions::TestgenOptions() registerOption( "--test-backend", "testBackend", [this](const char *arg) { - testBackend = arg; + testBackend = cstring(arg); testBackend = testBackend.toUpper(); return true; }, @@ -254,9 +256,9 @@ TestgenOptions::TestgenOptions() using P4Testgen::PathSelectionPolicy; static std::map const PATH_SELECTION_OPTIONS = { - {"DEPTH_FIRST", PathSelectionPolicy::DepthFirst}, - {"RANDOM_BACKTRACK", PathSelectionPolicy::RandomBacktrack}, - {"GREEDY_STATEMENT_SEARCH", PathSelectionPolicy::GreedyStmtCoverage}, + {"DEPTH_FIRST"_cs, PathSelectionPolicy::DepthFirst}, + {"RANDOM_BACKTRACK"_cs, PathSelectionPolicy::RandomBacktrack}, + {"GREEDY_STATEMENT_SEARCH"_cs, PathSelectionPolicy::GreedyStmtCoverage}, }; auto selectionString = cstring(arg).toUpper(); auto it = PATH_SELECTION_OPTIONS.find(selectionString); @@ -283,8 +285,8 @@ TestgenOptions::TestgenOptions() registerOption( "--track-coverage", "coverageItem", [this](const char *arg) { - static std::set const COVERAGE_OPTIONS = {"STATEMENTS", "TABLE_ENTRIES", - "ACTIONS"}; + static std::set const COVERAGE_OPTIONS = {"STATEMENTS"_cs, "TABLE_ENTRIES"_cs, + "ACTIONS"_cs}; hasCoverageTracking = true; auto selectionString = cstring(arg).toUpper(); auto it = COVERAGE_OPTIONS.find(selectionString); @@ -398,7 +400,7 @@ TestgenOptions::TestgenOptions() registerOption( "--test-name", "testBaseName", [this](const char *arg) { - testBaseName = arg; + testBaseName = cstring(arg); return true; }, "The base name of the tests which are generated."); diff --git a/backends/p4tools/modules/testgen/targets/bmv2/cmd_stepper.cpp b/backends/p4tools/modules/testgen/targets/bmv2/cmd_stepper.cpp index 3cdcaa272b..02d6e13269 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/cmd_stepper.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/cmd_stepper.cpp @@ -80,7 +80,7 @@ void Bmv2V1ModelCmdStepper::initializeTargetEnvironment(ExecutionState &nextStat const auto *nineBitType = IR::Type_Bits::get(9); const auto *oneBitType = IR::Type_Bits::get(1); nextState.set(programInfo.getTargetInputPortVar(), - ToolsVariables::getSymbolicVariable(nineBitType, "bmv2_ingress_port")); + ToolsVariables::getSymbolicVariable(nineBitType, "bmv2_ingress_port"_cs)); // BMv2 implicitly sets the output port to 0. nextState.set(programInfo.getTargetOutputPortVar(), IR::Constant::get(nineBitType, 0)); // Initialize parser_err with no error. @@ -105,7 +105,7 @@ std::optional Bmv2V1ModelCmdStepper::startParserImpl( const IR::P4Parser *parser, ExecutionState &nextState) const { // We need to explicitly map the parser error const auto *errVar = Bmv2V1ModelProgramInfo::getParserParamVar( - parser, programInfo.getParserErrorType(), 3, "parser_error"); + parser, programInfo.getParserErrorType(), 3, "parser_error"_cs); nextState.setParserErrorLabel(errVar); return std::nullopt; @@ -119,7 +119,7 @@ std::map Bmv2V1ModelCmdStepper::getExcept auto gress = programInfo.getGress(parser); const auto *errVar = Bmv2V1ModelProgramInfo::getParserParamVar( - parser, programInfo.getParserErrorType(), 3, "parser_error"); + parser, programInfo.getParserErrorType(), 3, "parser_error"_cs); switch (gress) { case BMV2_INGRESS: diff --git a/backends/p4tools/modules/testgen/targets/bmv2/concolic.cpp b/backends/p4tools/modules/testgen/targets/bmv2/concolic.cpp index a56d32ce7c..2c37bf3e09 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/concolic.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/concolic.cpp @@ -28,6 +28,8 @@ namespace P4Tools::P4Testgen::Bmv2 { +using namespace P4::literals; + static big_int checksum(Bmv2HashAlgorithm algo, const uint8_t *buf, size_t len) { // Pick a checksum according to the algorithm value. switch (algo) { @@ -97,8 +99,8 @@ const ConcolicMethodImpls::ImplList Bmv2Concolic::BMV2_CONCOLIC_METHOD_IMPLS{ /// int) or varbits. /// @param T Must be a type bit /// @param M Must be a type bit - {"*method_hash", - {"result", "algo", "base", "data", "max"}, + {"*method_hash"_cs, + {"result"_cs, "algo"_cs, "base"_cs, "data"_cs, "max"_cs}, [](cstring /*concolicMethodName*/, const IR::ConcolicVariable *var, const ExecutionState & /*state*/, const Model &finalModel, ConcolicVariableMap *resolvedConcolicVariables) { @@ -163,8 +165,8 @@ const ConcolicMethodImpls::ImplList Bmv2Concolic::BMV2_CONCOLIC_METHOD_IMPLS{ * ====================================================================================== */ /// This method is almost equivalent to the hash method. Except that when the checksum output is /// out of bounds, this method assigns the maximum instead of using a modulo operation. - {"*method_checksum", - {"result", "algo", "data"}, + {"*method_checksum"_cs, + {"result"_cs, "algo"_cs, "data"_cs}, [](cstring /*concolicMethodName*/, const IR::ConcolicVariable *var, const ExecutionState & /*state*/, const Model &finalModel, ConcolicVariableMap *resolvedConcolicVariables) { @@ -212,8 +214,8 @@ const ConcolicMethodImpls::ImplList Bmv2Concolic::BMV2_CONCOLIC_METHOD_IMPLS{ } }}, - {"*method_checksum_with_payload", - {"result", "algo", "data"}, + {"*method_checksum_with_payload"_cs, + {"result"_cs, "algo"_cs, "data"_cs}, [](cstring /*concolicMethodName*/, const IR::ConcolicVariable *var, const ExecutionState & /*state*/, const Model &finalModel, ConcolicVariableMap *resolvedConcolicVariables) { diff --git a/backends/p4tools/modules/testgen/targets/bmv2/expr_stepper.cpp b/backends/p4tools/modules/testgen/targets/bmv2/expr_stepper.cpp index da83307864..7bf3c39d88 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/expr_stepper.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/expr_stepper.cpp @@ -47,7 +47,7 @@ std::string Bmv2V1ModelExprStepper::getClassName() { return "Bmv2V1ModelExprStep bool Bmv2V1ModelExprStepper::isPartOfFieldList(const IR::StructField *field, uint64_t recirculateIndex) { // Check whether the field has a "field_list" annotation associated with it. - const auto *annotation = field->getAnnotation("field_list"); + const auto *annotation = field->getAnnotation("field_list"_cs); if (annotation != nullptr) { // Grab the index of the annotation. auto annoExprs = annotation->expr; @@ -84,16 +84,17 @@ void Bmv2V1ModelExprStepper::processClone(const ExecutionState &state, SmallStepEvaluator::Result &result) { const auto *progInfo = getProgramInfo().checkedTo(); // Pick a clone port var. It must adhere to the constraints of the target. - const auto *cloneInfo = state.getTestObject("clone_infos", "clone_info"); + const auto *cloneInfo = + state.getTestObject("clone_infos"_cs, "clone_info"_cs); const auto *sessionIdExpr = cloneInfo->getSessionId(); const auto &preserveIndex = cloneInfo->getPreserveIndex(); const auto &egressPortVar = programInfo.getTargetOutputPortVar(); const auto &clonePortVar = - ToolsVariables::getSymbolicVariable(egressPortVar->type, "clone_port_var"); + ToolsVariables::getSymbolicVariable(egressPortVar->type, "clone_port_var"_cs); uint64_t recirculateCount = 0; - if (state.hasProperty("recirculate_count")) { - recirculateCount = state.getProperty("recirculate_count"); + if (state.hasProperty("recirculate_count"_cs)) { + recirculateCount = state.getProperty("recirculate_count"_cs); } // Pick a clone port var. It must adhere to the constraints of the target. @@ -119,13 +120,13 @@ void Bmv2V1ModelExprStepper::processClone(const ExecutionState &state, { auto &defaultState = state.clone(); // Delete the stale clone info to free up some space and reset the clone_active flag. - defaultState.deleteTestObjectCategory("clone_infos"); - defaultState.setProperty("clone_active", false); + defaultState.deleteTestObjectCategory("clone_infos"_cs); + defaultState.setProperty("clone_active"_cs, false); // Increment the recirculation count. - defaultState.setProperty("recirculate_count", ++recirculateCount); + defaultState.setProperty("recirculate_count"_cs, ++recirculateCount); // Attach the clone specification for test generation. const auto *defaultCloneInfo = new Bmv2V1ModelCloneSpec(sessionIdExpr, clonePortVar, false); - defaultState.addTestObject("clone_specs", "clone_spec", defaultCloneInfo); + defaultState.addTestObject("clone_specs"_cs, "clone_spec"_cs, defaultCloneInfo); defaultState.popBody(); result->emplace_back(cond, state, defaultState); } @@ -156,7 +157,7 @@ void Bmv2V1ModelExprStepper::processClone(const ExecutionState &state, // information for that, including the exact parameter names of the ingress // block we are in. Just grab the ingress from the programmable blocks. const auto *programmableBlocks = progInfo->getProgrammableBlocks(); - const auto *typeDecl = programmableBlocks->at("Ingress"); + const auto *typeDecl = programmableBlocks->at("Ingress"_cs); const auto *applyBlock = typeDecl->checkedTo(); const auto *params = applyBlock->getApplyParameters(); auto blockIndex = 2; @@ -195,7 +196,7 @@ void Bmv2V1ModelExprStepper::processClone(const ExecutionState &state, // 0. However, fields in the user metadata that have the field_list // annotation and the appropriate index will not be reset. The user // metadata is the third parameter of the parser control. - const auto *paramPath = progInfo->getBlockParam("Parser", 2); + const auto *paramPath = progInfo->getBlockParam("Parser"_cs, 2); resetPreservingFieldList(*cloneState, paramPath, preserveIndex.value()); } @@ -219,13 +220,13 @@ void Bmv2V1ModelExprStepper::processClone(const ExecutionState &state, TESTGEN_UNIMPLEMENTED("Unsupported clone type %1%.", cloneType); } // Attach the clone specification for test generation. - cloneState->addTestObject("clone_specs", "clone_spec", + cloneState->addTestObject("clone_specs"_cs, "clone_spec"_cs, new Bmv2V1ModelCloneSpec(sessionIdExpr, clonePortVar, true)); // Delete the stale clone info to free up some space and reset the clone_active flag. - cloneState->setProperty("clone_active", false); - cloneState->deleteTestObjectCategory("clone_infos"); + cloneState->setProperty("clone_active"_cs, false); + cloneState->deleteTestObjectCategory("clone_infos"_cs); // Increment the recirculation count. - cloneState->setProperty("recirculate_count", ++recirculateCount); + cloneState->setProperty("recirculate_count"_cs, ++recirculateCount); /// Reset the packet buffer for recirculation. cloneState->resetPacketBuffer(); cloneState->replaceTopBody(&cmds); @@ -234,13 +235,13 @@ void Bmv2V1ModelExprStepper::processClone(const ExecutionState &state, void Bmv2V1ModelExprStepper::processRecirculate(const ExecutionState &state, SmallStepEvaluator::Result &result) { - auto instanceType = state.getProperty("recirculate_instance_type"); + auto instanceType = state.getProperty("recirculate_instance_type"_cs); const auto *progInfo = getProgramInfo().checkedTo(); auto &recState = state.clone(); // Check whether the packet needs to be reset. // If that is the case, reset the packet buffer to the calculated input packet. - auto recirculateReset = state.hasProperty("recirculate_reset_pkt"); + auto recirculateReset = state.hasProperty("recirculate_reset_pkt"_cs); if (recirculateReset) { // Reset the packet buffer, which corresponds to the output packet. recState.resetPacketBuffer(); @@ -257,15 +258,15 @@ void Bmv2V1ModelExprStepper::processRecirculate(const ExecutionState &state, IR::Constant::get(&PacketVars::PACKET_SIZE_VAR_TYPE, recState.getPacketBufferSize() / 8); recState.set(packetSizeVar, packetSizeConst); - if (recState.hasProperty("recirculate_index")) { + if (recState.hasProperty("recirculate_index"_cs)) { // Get the index set by the recirculate/resubmit function. Will fail if no index is // set. - auto recirculateIndex = recState.getProperty("recirculate_index"); + auto recirculateIndex = recState.getProperty("recirculate_index"_cs); // This program segment resets the user metadata of the v1model program to 0. // However, fields in the user metadata that have the field_list annotation and the // appropriate index will not be reset. // The user metadata is the third parameter of the parser control. - const auto *paramPath = progInfo->getBlockParam("Parser", 2); + const auto *paramPath = progInfo->getBlockParam("Parser"_cs, 2); resetPreservingFieldList(recState, paramPath, recirculateIndex); } @@ -276,7 +277,7 @@ void Bmv2V1ModelExprStepper::processRecirculate(const ExecutionState &state, recState.set(instanceTypeVar, IR::Constant::get(bitType, instanceType)); // Set recirculate to false to avoid infinite loops. - recState.setProperty("recirculate_active", false); + recState.setProperty("recirculate_active"_cs, false); // "Recirculate" by attaching the sequence again. // Does NOT initialize state or adds new conditions. @@ -336,8 +337,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * ====================================================================================== */ // TODO: Implement extern path expression calls. - {"*method.mark_to_drop", - {"standard_metadata"}, + {"*method.mark_to_drop"_cs, + {"standard_metadata"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -348,7 +349,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression // This variable will be processed in the deparser. const auto *portVar = new IR::Member(nineBitType, metadataLabel->ref, "egress_spec"); nextState.set(portVar, IR::Constant::get(nineBitType, BMv2Constants::DROP_PORT)); - nextState.add(*new TraceEvents::Generic("mark_to_drop executed.")); + nextState.add(*new TraceEvents::Generic("mark_to_drop executed."_cs)); nextState.popBody(); result->emplace_back(nextState); }}, @@ -358,8 +359,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * it to the result parameter. * ====================================================================================== */ - {"*method.random", - {"result", "lo", "hi"}, + {"*method.random"_cs, + {"result"_cs, "lo"_cs, "hi"_cs}, [this](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -421,7 +422,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * is likely that your assumption was wrong, and should be reexamined. * ====================================================================================== */ - {"*method.assume", {"check"}, assertAssumeExecute}, + {"*method.assume"_cs, {"check"_cs}, assertAssumeExecute}, /* ====================================================================================== * assert * Calling assert when the argument is true has no effect, except any @@ -445,7 +446,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * same way when assert statements are removed. * ====================================================================================== */ - {"*method.assert", {"check"}, assertAssumeExecute}, + {"*method.assert"_cs, {"check"_cs}, assertAssumeExecute}, /* ====================================================================================== * log_msg * Log user defined messages @@ -453,8 +454,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * or log_msg("Value1 = {}, Value2 = {}",{value1, value2}); * ====================================================================================== */ - {"*method.log_msg", - {"msg", "args"}, + {"*method.log_msg"_cs, + {"msg"_cs, "args"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -470,12 +471,12 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression assignString.cend()); auto &nextState = state.clone(); - nextState.add(*new TraceEvents::Generic(assignString.c_str())); + nextState.add(*new TraceEvents::Generic(assignString)); nextState.popBody(); result->emplace_back(nextState); }}, - {"*method.log_msg", - {"msg"}, + {"*method.log_msg"_cs, + {"msg"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -501,8 +502,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * @param M Must be a type bit * ====================================================================================== */ - {"*method.hash", - {"result", "algo", "base", "data", "max"}, + {"*method.hash"_cs, + {"result"_cs, "algo"_cs, "base"_cs, "data"_cs, "max"_cs}, [this](const IR::MethodCallExpression *call, const IR::Expression *receiver, IR::ID &name, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -558,8 +559,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * * ====================================================================================== */ - {"register.read", - {"result", "index"}, + {"register.read"_cs, + {"result"_cs, "index"_cs}, [this](const IR::MethodCallExpression * /*call*/, const IR::Expression *receiver, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -573,8 +574,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression // Retrieve the register state from the object store. If it is already present, just // cast the object to the correct class and retrieve the current value according to the // index. If the register has not been added yet, create a new register object. - const auto *registerState = - state.getTestObject("registervalues", externInstance->controlPlaneName(), false); + const auto *registerState = state.getTestObject( + "registervalues"_cs, externInstance->controlPlaneName(), false); const Bmv2V1ModelRegisterValue *registerValue = nullptr; if (registerState != nullptr) { registerValue = registerState->checkedTo(); @@ -582,7 +583,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression const auto *inputValue = programInfo.createTargetUninitialized(readOutput->type, false); registerValue = new Bmv2V1ModelRegisterValue(inputValue); - nextState.addTestObject("registervalues", externInstance->controlPlaneName(), + nextState.addTestObject("registervalues"_cs, externInstance->controlPlaneName(), registerValue); } const IR::Expression *baseExpr = registerValue->getValueAtIndex(index); @@ -633,8 +634,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * * ====================================================================================== */ - {"register.write", - {"index", "value"}, + {"register.write"_cs, + {"index"_cs, "value"_cs}, [this](const IR::MethodCallExpression * /*call*/, const IR::Expression *receiver, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -661,7 +662,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression // "Write" to the register by update the internal test object state. If the register // did not exist previously, update it with the value to write as initial value. const auto *registerState = nextState.getTestObject( - "registervalues", externInstance->controlPlaneName(), false); + "registervalues"_cs, externInstance->controlPlaneName(), false); Bmv2V1ModelRegisterValue *registerValue = nullptr; if (registerState != nullptr) { registerValue = new Bmv2V1ModelRegisterValue( @@ -673,7 +674,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression registerValue = new Bmv2V1ModelRegisterValue(writeValue); registerValue->writeToIndex(index, inputValue); } - nextState.addTestObject("registervalues", externInstance->controlPlaneName(), + nextState.addTestObject("registervalues"_cs, externInstance->controlPlaneName(), registerValue); nextState.popBody(); result->emplace_back(nextState); @@ -706,8 +707,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * ====================================================================================== */ // TODO: Count currently has no effect in the symbolic interpreter. - {"counter.count", - {"index"}, + {"counter.count"_cs, + {"index"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -743,7 +744,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * ====================================================================================== */ // TODO: Count currently has no effect in the symbolic interpreter. - {"direct_counter.count", + {"direct_counter.count"_cs, {}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, @@ -783,8 +784,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * range, the final value of result is not specified, * and should be ignored by the caller. * ====================================================================================== */ - {"meter.execute_meter", - {"index", "result"}, + {"meter.execute_meter"_cs, + {"index"_cs, "result"_cs}, [](const IR::MethodCallExpression *call, const IR::Expression *receiver, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -816,7 +817,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression // cast the object to the correct class and retrieve the current value according to the // index. If the meter has not been added had, create a new meter object. const auto *meterState = - state.getTestObject("meter_values", externInstance->controlPlaneName(), false); + state.getTestObject("meter_values"_cs, externInstance->controlPlaneName(), false); Bmv2V1ModelMeterValue *meterValue = nullptr; const auto &inputValue = ToolsVariables::getSymbolicVariable( meterResult->type, "meter_value" + std::to_string(call->clone_id)); @@ -829,7 +830,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression meterValue = new Bmv2V1ModelMeterValue(inputValue, false); } meterValue->writeToIndex(index, inputValue); - nextState.addTestObject("meter_values", externInstance->controlPlaneName(), + nextState.addTestObject("meter_values"_cs, externInstance->controlPlaneName(), meterValue); if (meterResult->type->is()) { @@ -881,8 +882,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * color YELLOW, and 2 for color RED (see RFC 2697 * and RFC 2698 for the meaning of these colors). * ====================================================================================== */ - {"direct_meter.read", - {"result"}, + {"direct_meter.read"_cs, + {"result"_cs}, [this](const IR::MethodCallExpression *call, const IR::Expression *receiver, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -892,7 +893,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression const auto *externInstance = state.findDecl(receiverPath); const auto *table = progInfo->getTableofDirectExtern(externInstance); const auto *tableEntry = - state.getTestObject("tableconfigs", table->controlPlaneName(), false); + state.getTestObject("tableconfigs"_cs, table->controlPlaneName(), false); auto &nextState = state.clone(); std::vector replacements; @@ -919,7 +920,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression // cast the object to the correct class and retrieve the current value according to the // index. If the meter has not been added had, create a new meter object. const auto *meterState = - state.getTestObject("meter_values", externInstance->controlPlaneName(), false); + state.getTestObject("meter_values"_cs, externInstance->controlPlaneName(), false); Bmv2V1ModelMeterValue *meterValue = nullptr; const auto &inputValue = ToolsVariables::getSymbolicVariable( meterResult->type, "meter_value" + std::to_string(call->clone_id)); @@ -932,7 +933,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression meterValue = new Bmv2V1ModelMeterValue(inputValue, true); } meterValue->writeToIndex(IR::Constant::get(IR::Type_Bits::get(1), 0), inputValue); - nextState.addTestObject("meter_values", externInstance->controlPlaneName(), + nextState.addTestObject("meter_values"_cs, externInstance->controlPlaneName(), meterValue); if (meterResult->type->is()) { @@ -978,8 +979,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * value of the receiver parameter. * ====================================================================================== */ - {"*method.digest", - {"receiver", "data"}, + {"*method.digest"_cs, + {"receiver"_cs, "data"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -1024,16 +1025,16 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * v1model architecture documentation (Note 1) for more details. * ====================================================================================== */ - {"*method.clone_preserving_field_list", - {"type", "session", "data"}, + {"*method.clone_preserving_field_list"_cs, + {"type"_cs, "session"_cs, "data"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { // Grab the recirculate count. Stop after more than 1 circulation loop to avoid // infinite recirculation loops. // TODO: Determine the exact count. - if (state.hasProperty("recirculate_count")) { - if (state.getProperty("recirculate_count") > 0) { + if (state.hasProperty("recirculate_count"_cs)) { + if (state.getProperty("recirculate_count"_cs) > 0) { auto &nextState = state.clone(); ::warning("Only single recirculation supported for now. Dropping packet."); auto *dropStmt = new IR::MethodCallStatement( @@ -1066,9 +1067,9 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression sessionIdExpr, static_cast(cloneType), state.clone(), preserveIndex); auto &nextState = state.clone(); - nextState.addTestObject("clone_infos", "clone_info", cloneInfo); + nextState.addTestObject("clone_infos"_cs, "clone_info"_cs, cloneInfo); // Also set clone as active, which will trigger "processClone" in the deparser. - nextState.setProperty("clone_active", true); + nextState.setProperty("clone_active"_cs, true); nextState.popBody(); result->emplace_back(nextState); }}, @@ -1108,8 +1109,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * resubmit_preserving_field_list(2) will only preserve field y. * ====================================================================================== */ - {"*method.resubmit_preserving_field_list", - {"data"}, + {"*method.resubmit_preserving_field_list"_cs, + {"data"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -1118,8 +1119,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression // Grab the recirculate count. Stop after more than 1 circulation loop to avoid // infinite recirculation loops. // TODO: Determine the exact count. - if (state.hasProperty("recirculate_count")) { - recirculateCount = state.getProperty("recirculate_count"); + if (state.hasProperty("recirculate_count"_cs)) { + recirculateCount = state.getProperty("recirculate_count"_cs); if (recirculateCount > 0) { ::warning("Only single resubmit supported for now. Dropping packet."); auto *dropStmt = new IR::MethodCallStatement( @@ -1130,19 +1131,19 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression } } // Increment the recirculation count. - nextState.setProperty("recirculate_count", ++recirculateCount); + nextState.setProperty("recirculate_count"_cs, ++recirculateCount); // Recirculate is now active and "processRecirculate" will be triggered in the // deparser. - nextState.setProperty("recirculate_active", true); + nextState.setProperty("recirculate_active"_cs, true); // Grab the index and save it to the execution state. auto index = args->at(0)->expression->checkedTo()->asUint64(); - nextState.setProperty("recirculate_index", index); + nextState.setProperty("recirculate_index"_cs, index); // Resubmit actually uses the original input packet, not the deparsed packet. // We have to reset the packet content to the input packet in "processRecirculate". - nextState.setProperty("recirculate_reset_pkt", true); + nextState.setProperty("recirculate_reset_pkt"_cs, true); // Set the appropriate instance type, which will be processed by // "processRecirculate". - nextState.setProperty("recirculate_instance_type", + nextState.setProperty("recirculate_instance_type"_cs, BMv2Constants::PKT_INSTANCE_TYPE_RESUBMIT); nextState.popBody(); result->emplace_back(nextState); @@ -1169,8 +1170,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * for more details. * ====================================================================================== */ - {"*method.recirculate_preserving_field_list", - {"index"}, + {"*method.recirculate_preserving_field_list"_cs, + {"index"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -1179,8 +1180,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression // Grab the recirculate count. Stop after more than 1 circulation loop to avoid // infinite recirculation loops. // TODO: Determine the exact count. - if (state.hasProperty("recirculate_count")) { - recirculateCount = state.getProperty("recirculate_count"); + if (state.hasProperty("recirculate_count"_cs)) { + recirculateCount = state.getProperty("recirculate_count"_cs); if (recirculateCount > 0) { ::warning("Only single recirculation supported for now. Dropping packet."); auto *dropStmt = new IR::MethodCallStatement( @@ -1191,16 +1192,16 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression } } // Increment the recirculation count. - nextState.setProperty("recirculate_count", ++recirculateCount); + nextState.setProperty("recirculate_count"_cs, ++recirculateCount); // Recirculate is now active and "processRecirculate" will be triggered in the // deparser. - nextState.setProperty("recirculate_active", true); + nextState.setProperty("recirculate_active"_cs, true); // Grab the index and save it to the execution state. auto index = args->at(0)->expression->checkedTo()->asUint64(); - nextState.setProperty("recirculate_index", index); + nextState.setProperty("recirculate_index"_cs, index); // Set the appropriate instance type, which will be processed by // "processRecirculate". - nextState.setProperty("recirculate_instance_type", + nextState.setProperty("recirculate_instance_type"_cs, BMv2Constants::PKT_INSTANCE_TYPE_RECIRC); nextState.popBody(); result->emplace_back(nextState); @@ -1214,16 +1215,16 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * type and session parameter values, with empty data. * ====================================================================================== */ - {"*method.clone", - {"type", "session"}, + {"*method.clone"_cs, + {"type"_cs, "session"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { // Grab the recirculate count. Stop after more than 1 circulation loop to avoid // infinite recirculation loops. // TODO: Determine the exact count. - if (state.hasProperty("recirculate_count")) { - if (state.getProperty("recirculate_count") > 0) { + if (state.hasProperty("recirculate_count"_cs)) { + if (state.getProperty("recirculate_count"_cs) > 0) { auto &nextState = state.clone(); ::warning("Only single recirculation supported for now. Dropping packet."); auto *dropStmt = new IR::MethodCallStatement( @@ -1255,9 +1256,9 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression auto *cloneInfo = new Bmv2V1ModelCloneInfo( sessionIdExpr, static_cast(cloneType), state.clone(), std::nullopt); - nextState.addTestObject("clone_infos", "clone_info", cloneInfo); + nextState.addTestObject("clone_infos"_cs, "clone_info"_cs, cloneInfo); // Also set clone as active, which will trigger "processClone" in the deparser. - nextState.setProperty("clone_active", true); + nextState.setProperty("clone_active"_cs, true); nextState.popBody(); result->emplace_back(nextState); }}, @@ -1267,21 +1268,22 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression */ /// Helper extern that processes the parameters set by the recirculate, clone and resubmit /// externs. This extern assume the TM is executed at the end of the deparser. - {"*.invoke_traffic_manager", + {"*.invoke_traffic_manager"_cs, {}, [this](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, const ExecutionState &state, SmallStepEvaluator::Result &result) { // Check whether the clone variant is active. // Clone triggers a branch and slightly different processing. - if (state.hasProperty("clone_active") && state.getProperty("clone_active")) { + if (state.hasProperty("clone_active"_cs) && + state.getProperty("clone_active"_cs)) { processClone(state, result); return; } // Check whether recirculate is active. - if (state.hasProperty("recirculate_active") && - state.getProperty("recirculate_active")) { + if (state.hasProperty("recirculate_active"_cs) && + state.getProperty("recirculate_active"_cs)) { processRecirculate(state, result); return; } @@ -1294,8 +1296,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * Checksum16.get * ====================================================================================== */ - {"Checksum16.get", - {"data"}, + {"Checksum16.get"_cs, + {"data"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, const ExecutionState & /*state*/, SmallStepEvaluator::Result & /*result*/) { @@ -1325,8 +1327,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * constant. * ====================================================================================== */ - {"*method.verify_checksum", - {"condition", "data", "checksum", "algo"}, + {"*method.verify_checksum"_cs, + {"condition"_cs, "data"_cs, "checksum"_cs, "algo"_cs}, [this](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -1379,7 +1381,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression // Try to force the checksum expression to be equal to the result. auto &nextState = state.clone(); const auto *concolicVar = new IR::ConcolicVariable( - checksumValueType, "*method_checksum", checksumArgs, call->clone_id, 0); + checksumValueType, "*method_checksum"_cs, checksumArgs, call->clone_id, 0); std::vector replacements; // We use a guard to enforce that the match condition after the call is true. auto *checksumMatchCond = new IR::Equ(concolicVar, checksumValue); @@ -1391,8 +1393,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression // The condition is true and the checksum does not match. { auto &nextState = state.clone(); - auto *concolicVar = new IR::ConcolicVariable(checksumValueType, "*method_checksum", - checksumArgs, call->clone_id, 0); + auto *concolicVar = new IR::ConcolicVariable( + checksumValueType, "*method_checksum"_cs, checksumArgs, call->clone_id, 0); std::vector replacements; auto *checksumMatchCond = new IR::Neq(concolicVar, checksumValue); @@ -1433,8 +1435,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * constant. * ====================================================================================== */ - {"*method.update_checksum", - {"condition", "data", "checksum", "algo"}, + {"*method.update_checksum"_cs, + {"condition"_cs, "data"_cs, "checksum"_cs, "algo"_cs}, [this](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -1486,7 +1488,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression auto &nextState = state.clone(); const auto *concolicVar = new IR::ConcolicVariable( - checksumVarType, "*method_checksum", checksumArgs, call->clone_id, 0); + checksumVarType, "*method_checksum"_cs, checksumArgs, call->clone_id, 0); nextState.set(checksumVar, concolicVar); nextState.popBody(); result->emplace_back(updateCond, state, nextState); @@ -1509,8 +1511,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * ComputeChecksum control. * ====================================================================================== */ - {"*method.update_checksum_with_payload", - {"condition", "data", "checksum", "algo"}, + {"*method.update_checksum_with_payload"_cs, + {"condition"_cs, "data"_cs, "checksum"_cs, "algo"_cs}, [this](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -1548,7 +1550,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression auto &nextState = state.clone(); const auto *concolicVar = - new IR::ConcolicVariable(checksumVarType, "*method_checksum_with_payload", + new IR::ConcolicVariable(checksumVarType, "*method_checksum_with_payload"_cs, checksumArgs, call->clone_id, 0); nextState.set(checksumVar, concolicVar); nextState.popBody(); @@ -1572,8 +1574,8 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression * VerifyChecksum control. * ====================================================================================== */ - {"*method.verify_checksum_with_payload", - {"condition", "data", "checksum", "algo"}, + {"*method.verify_checksum_with_payload"_cs, + {"condition"_cs, "data"_cs, "checksum"_cs, "algo"_cs}, [this](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -1614,7 +1616,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression // Try to force the checksum expression to be equal to the result. auto &nextState = state.clone(); const auto *concolicVar = - new IR::ConcolicVariable(checksumValueType, "*method_checksum_with_payload", + new IR::ConcolicVariable(checksumValueType, "*method_checksum_with_payload"_cs, checksumArgs, call->clone_id, 0); // We use a guard to enforce that the match condition after the call is true. auto *checksumMatchCond = new IR::Equ(concolicVar, checksumValue); @@ -1627,7 +1629,7 @@ void Bmv2V1ModelExprStepper::evalExternMethodCall(const IR::MethodCallExpression { auto &nextState = state.clone(); auto *concolicVar = - new IR::ConcolicVariable(checksumValueType, "*method_checksum_with_payload", + new IR::ConcolicVariable(checksumValueType, "*method_checksum_with_payload"_cs, checksumArgs, call->clone_id, 0); std::vector replacements; auto *checksumMatchCond = new IR::Neq(concolicVar, checksumValue); diff --git a/backends/p4tools/modules/testgen/targets/bmv2/map_direct_externs.cpp b/backends/p4tools/modules/testgen/targets/bmv2/map_direct_externs.cpp index 1bb9202adb..ac2f3bd724 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/map_direct_externs.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/map_direct_externs.cpp @@ -51,7 +51,7 @@ std::optional MapDirectExterns::getExternFromT bool MapDirectExterns::preorder(const IR::P4Table *table) { // Try to get extern implementation properties from the table. for (const auto *tableProperty : kTableExternProperties) { - const auto *impl = table->properties->getProperty(tableProperty); + const auto *impl = table->properties->getProperty(cstring(tableProperty)); if (impl != nullptr) { auto declInstanceOpt = getExternFromTableImplementation(impl); if (declInstanceOpt.has_value()) { diff --git a/backends/p4tools/modules/testgen/targets/bmv2/p4_asserts_parser.cpp b/backends/p4tools/modules/testgen/targets/bmv2/p4_asserts_parser.cpp index e5a4c3a4d1..8348b8926a 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/p4_asserts_parser.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/p4_asserts_parser.cpp @@ -304,7 +304,8 @@ const IR::Expression *getIR(std::vector tokens, const IdenitifierTypeMap std::vector combineTokensToNames(const std::vector &inputVector) { std::vector result; Token prevToken = Token(Token::Kind::Unknown, " ", 1); - cstring txt = ""; + std::string txt; + // FIXME: Can try to use absl::Cord for (const auto &input : inputVector) { if (prevToken.is(Token::Kind::Text) && input.is(Token::Kind::Number)) { txt += std::string(input.lexeme()); @@ -324,7 +325,8 @@ std::vector combineTokensToNames(const std::vector &inputVector) { } } else { if (txt.size() > 0) { - result.emplace_back(Token::Kind::Text, txt, txt.size()); + cstring buf(txt); + result.emplace_back(Token::Kind::Text, buf, buf.size()); txt = ""; } result.push_back(input); @@ -346,7 +348,8 @@ std::vector combineTokensToNames(const std::vector &inputVector) { /// [2(Number), 5(number), 5(number), ==(Equal), 0xff(Text)] -> [255(number), ==(Equal), /// 0xff(Number)] - This example is possible only after executing combineTokensToNames std::vector combineTokensToNumbers(std::vector input) { - cstring numb = ""; + // FIXME: Can try to use absl::cord + std::string numb; std::vector result; for (uint64_t i = 0; i < input.size(); i++) { if (input[i].is(Token::Kind::Minus)) { @@ -376,13 +379,15 @@ std::vector combineTokensToNumbers(std::vector input) { if (input[i].is(Token::Kind::Number)) { numb += std::string(input[i].lexeme()); if (i + 1 == input.size()) { - result.emplace_back(Token::Kind::Number, numb, numb.size()); + cstring cstr(numb); + result.emplace_back(Token::Kind::Number, cstr, cstr.size()); numb = ""; continue; } } else { if (numb.size() > 0) { - result.emplace_back(Token::Kind::Number, numb, numb.size()); + cstring cstr(numb); + result.emplace_back(Token::Kind::Number, cstr, cstr.size()); numb = ""; } result.push_back(input[i]); @@ -509,7 +514,7 @@ std::vector AssertsParser::genIRStructs(cstring tableNam } const IR::Node *AssertsParser::postorder(IR::P4Action *actionContext) { - const auto *annotation = actionContext->getAnnotation("action_restriction"); + const auto *annotation = actionContext->getAnnotation("action_restriction"_cs); if (annotation == nullptr) { return actionContext; } @@ -531,7 +536,7 @@ const IR::Node *AssertsParser::postorder(IR::P4Action *actionContext) { } const IR::Node *AssertsParser::postorder(IR::P4Table *tableContext) { - const auto *annotation = tableContext->getAnnotation("entry_restriction"); + const auto *annotation = tableContext->getAnnotation("entry_restriction"_cs); const auto *key = tableContext->getKey(); if (annotation == nullptr || key == nullptr) { return tableContext; @@ -539,7 +544,7 @@ const IR::Node *AssertsParser::postorder(IR::P4Table *tableContext) { IdenitifierTypeMap typeMap; for (const auto *keyElement : tableContext->getKey()->keyElements) { - const auto *nameAnnot = keyElement->getAnnotation("name"); + const auto *nameAnnot = keyElement->getAnnotation("name"_cs); BUG_CHECK(nameAnnot != nullptr, "%1% table key without a name annotation", annotation->name.name); typeMap[nameAnnot->getName()] = keyElement->expression->type; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/p4_refers_to_parser.cpp b/backends/p4tools/modules/testgen/targets/bmv2/p4_refers_to_parser.cpp index f9e59ebe0a..e65c9fa682 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/p4_refers_to_parser.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/p4_refers_to_parser.cpp @@ -18,19 +18,19 @@ namespace P4Tools::P4Testgen::Bmv2 { RefersToParser::RefersToParser() { setName("RefersToParser"); } const RefersToParser::RefersToBuiltinMap RefersToParser::REFERS_TO_BUILTIN_MAP = {{ - "multicast_group_table", + "multicast_group_table"_cs, { { - "multicast_group_id", - IR::SymbolicVariable(IR::Type_Bits::get(16), "refers_to_multicast_group_id"), + "multicast_group_id"_cs, + IR::SymbolicVariable(IR::Type_Bits::get(16), "refers_to_multicast_group_id"_cs), }, { - "replica.port", - IR::SymbolicVariable(IR::Type_Bits::get(9), "refers_to_replica.port"), + "replica.port"_cs, + IR::SymbolicVariable(IR::Type_Bits::get(9), "refers_to_replica.port"_cs), }, { - "replica.instance", - IR::SymbolicVariable(IR::Type_Bits::get(16), "refers_to_replica.instance"), + "replica.instance"_cs, + IR::SymbolicVariable(IR::Type_Bits::get(16), "refers_to_replica.instance"_cs), }, }, }}; @@ -53,7 +53,7 @@ const IR::SymbolicVariable *RefersToParser::lookUpBuiltinKey( refersAnno); BUG_CHECK(annotationList.at(1)->text == ":" && annotationList.at(2)->text == ":", "'@refers_to' annotation %1% does not have the correct format.", refersAnno); - cstring tableReference = ""; + cstring tableReference = cstring::empty; size_t offset = 3; for (; offset < annotationList.size(); offset++) { auto token = annotationList[offset]->text; @@ -79,7 +79,7 @@ const IR::SymbolicVariable *RefersToParser::lookUpKeyInTable(const IR::P4Table & BUG_CHECK(key != nullptr, "Table %1% does not have any keys.", srcTable); for (const auto *keyElement : key->keyElements) { auto annotations = keyElement->annotations->annotations; - const auto *nameAnnot = keyElement->getAnnotation("name"); + const auto *nameAnnot = keyElement->getAnnotation("name"_cs); // Some hidden tables do not have any key name annotations. BUG_CHECK(nameAnnot != nullptr, "Refers-to table key without a name annotation"); if (keyReference == nameAnnot->getName()) { @@ -110,7 +110,7 @@ const IR::SymbolicVariable *RefersToParser::getReferencedKey(const IR::P4Control const IR::IDeclaration *tableDeclaration = nullptr; for (const auto *decl : *ctrlContext.getDeclarations()) { auto declName = decl->controlPlaneName(); - if (declName.endsWith(tableReference)) { + if (declName.endsWith(tableReference.string_view())) { tableDeclaration = decl; break; } @@ -134,7 +134,7 @@ bool RefersToParser::preorder(const IR::P4Table *tableContext) { auto annotations = keyElement->annotations->annotations; for (const auto *annotation : annotations) { if (annotation->name.name == "refers_to" || annotation->name.name == "referenced_by") { - const auto *nameAnnot = keyElement->getAnnotation("name"); + const auto *nameAnnot = keyElement->getAnnotation("name"_cs); BUG_CHECK(nameAnnot != nullptr, "%1% table key without a name annotation", annotation->name.name); const auto *srcKey = ControlPlaneState::getTableKey( diff --git a/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.cpp b/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.cpp index 1674567593..ecc46dea79 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.cpp @@ -17,14 +17,14 @@ P4Tools::P4Testgen::Bmv2::PropagateP4RuntimeTranslation::lookupP4RuntimeAnnotati if (annotatedType == nullptr) { return p4RuntimeAnnotations; } - const auto *p4runtimeAnnotation = annotatedType->getAnnotation("p4runtime_translation"); + const auto *p4runtimeAnnotation = annotatedType->getAnnotation("p4runtime_translation"_cs); if (p4runtimeAnnotation != nullptr) { BUG_CHECK(!p4runtimeAnnotation->needsParsing, "The @p4runtime_translation annotation should have been parsed already."); p4RuntimeAnnotations.push_back(p4runtimeAnnotation); } const auto *p4runtimeTranslationMappings = - annotatedType->getAnnotation("p4runtime_translation_mappings"); + annotatedType->getAnnotation("p4runtime_translation_mappings"_cs); if (p4runtimeTranslationMappings != nullptr) { BUG_CHECK( !p4runtimeTranslationMappings->needsParsing, diff --git a/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.h b/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.h index d13ea270f1..d1b09c4767 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.h +++ b/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.h @@ -8,6 +8,8 @@ namespace P4Tools::P4Testgen::Bmv2 { +using namespace P4::literals; + /// Propagates P4Runtime annotations attached to type definitions to the nodes which use these type /// definitions. For now, this is restricted to key elements and action parameters. class PropagateP4RuntimeTranslation : public Transform { diff --git a/backends/p4tools/modules/testgen/targets/bmv2/program_info.cpp b/backends/p4tools/modules/testgen/targets/bmv2/program_info.cpp index a5ff40602b..0e1e0a8780 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/program_info.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/program_info.cpp @@ -244,32 +244,32 @@ const IR::Member *Bmv2V1ModelProgramInfo::getParserParamVar(const IR::P4Parser * const auto *paramString = parser->getApplyParameters()->parameters.at(paramIndex); structLabel = paramString->name; } else { - structLabel = ARCH_SPEC.getParamName("Parser", paramIndex); + structLabel = ARCH_SPEC.getParamName("Parser"_cs, paramIndex); } return new IR::Member(type, new IR::PathExpression(structLabel), paramLabel); } -const ArchSpec Bmv2V1ModelProgramInfo::ARCH_SPEC = - ArchSpec("V1Switch", {// parser Parser(packet_in b, - // out H parsedHdr, - // inout M meta, - // inout standard_metadata_t standard_metadata); - {"Parser", {nullptr, "*hdr", "*meta", "*standard_metadata"}}, - // control VerifyChecksum(inout H hdr, - // inout M meta); - {"VerifyChecksum", {"*hdr", "*meta"}}, - // control Ingress(inout H hdr, - // inout M meta, - // inout standard_metadata_t standard_metadata); - {"Ingress", {"*hdr", "*meta", "*standard_metadata"}}, - // control Egress(inout H hdr, - // inout M meta, - // inout standard_metadata_t standard_metadata); - {"Egress", {"*hdr", "*meta", "*standard_metadata"}}, - // control ComputeChecksum(inout H hdr, - // inout M meta); - {"ComputeChecksum", {"*hdr", "*meta"}}, - // control Deparser(packet_out b, in H hdr); - {"Deparser", {nullptr, "*hdr"}}}); +const ArchSpec Bmv2V1ModelProgramInfo::ARCH_SPEC = ArchSpec( + "V1Switch"_cs, {// parser Parser(packet_in b, + // out H parsedHdr, + // inout M meta, + // inout standard_metadata_t standard_metadata); + {"Parser"_cs, {nullptr, "*hdr"_cs, "*meta"_cs, "*standard_metadata"_cs}}, + // control VerifyChecksum(inout H hdr, + // inout M meta); + {"VerifyChecksum"_cs, {"*hdr"_cs, "*meta"_cs}}, + // control Ingress(inout H hdr, + // inout M meta, + // inout standard_metadata_t standard_metadata); + {"Ingress"_cs, {"*hdr"_cs, "*meta"_cs, "*standard_metadata"_cs}}, + // control Egress(inout H hdr, + // inout M meta, + // inout standard_metadata_t standard_metadata); + {"Egress"_cs, {"*hdr"_cs, "*meta"_cs, "*standard_metadata"_cs}}, + // control ComputeChecksum(inout H hdr, + // inout M meta); + {"ComputeChecksum"_cs, {"*hdr"_cs, "*meta"_cs}}, + // control Deparser(packet_out b, in H hdr); + {"Deparser"_cs, {nullptr, "*hdr"_cs}}}); } // namespace P4Tools::P4Testgen::Bmv2 diff --git a/backends/p4tools/modules/testgen/targets/bmv2/table_stepper.cpp b/backends/p4tools/modules/testgen/targets/bmv2/table_stepper.cpp index 31d65bf815..c61fb54e3a 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/table_stepper.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/table_stepper.cpp @@ -34,6 +34,8 @@ namespace P4Tools::P4Testgen::Bmv2 { +using namespace P4::literals; + const IR::Expression *Bmv2V1ModelTableStepper::computeTargetMatchType( const TableUtils::KeyProperties &keyProperties, TableMatchMap *matches, const IR::Expression *hitCondition) { @@ -140,7 +142,7 @@ void Bmv2V1ModelTableStepper::evalTableActionProfile( // TODO: Should we check if we exceed the maximum number of possible profile entries? actionProfile->addToActionMap(actionName, ctrlPlaneArgs); // Update the action profile in the execution state. - nextState.addTestObject("action_profile", actionProfile->getObjectName(), actionProfile); + nextState.addTestObject("action_profile"_cs, actionProfile->getObjectName(), actionProfile); // We add the arguments to our action call, effectively creating a const entry call. auto *synthesizedAction = tableAction->clone(); @@ -154,8 +156,8 @@ void Bmv2V1ModelTableStepper::evalTableActionProfile( // Add the action profile to the table. // This implies a slightly different implementation to usual control plane table behavior. - tableConfig->addTableProperty("action_profile", actionProfile); - nextState.addTestObject("tableconfigs", table->controlPlaneName(), tableConfig); + tableConfig->addTableProperty("action_profile"_cs, actionProfile); + nextState.addTestObject("tableconfigs"_cs, table->controlPlaneName(), tableConfig); // Update all the tracking variables for tables. std::vector replacements; @@ -222,9 +224,10 @@ void Bmv2V1ModelTableStepper::evalTableActionSelector( bmv2V1ModelProperties.actionSelector->getSelectorDecl(), actionProfile); // Update the action profile in the execution state. - nextState.addTestObject("action_profile", actionProfile->getObjectName(), actionProfile); + nextState.addTestObject("action_profile"_cs, actionProfile->getObjectName(), actionProfile); // Update the action selector in the execution state. - nextState.addTestObject("action_selector", actionSelector->getObjectName(), actionSelector); + nextState.addTestObject("action_selector"_cs, actionSelector->getObjectName(), + actionSelector); // We add the arguments to our action call, effectively creating a const entry call. auto *synthesizedAction = tableAction->clone(); @@ -237,11 +240,11 @@ void Bmv2V1ModelTableStepper::evalTableActionSelector( auto *tableConfig = new TableConfig(table, {tableRule}); // Add the action profile to the table. This signifies a slightly different implementation. - tableConfig->addTableProperty("action_profile", actionProfile); + tableConfig->addTableProperty("action_profile"_cs, actionProfile); // Add the action selector to the table. This signifies a slightly different implementation. - tableConfig->addTableProperty("action_selector", actionSelector); + tableConfig->addTableProperty("action_selector"_cs, actionSelector); - nextState.addTestObject("tableconfigs", table->controlPlaneName(), tableConfig); + nextState.addTestObject("tableconfigs"_cs, table->controlPlaneName(), tableConfig); // Update all the tracking variables for tables. std::vector replacements; @@ -267,7 +270,7 @@ void Bmv2V1ModelTableStepper::evalTableActionSelector( } bool Bmv2V1ModelTableStepper::checkForActionProfile() { - const auto *impl = table->properties->getProperty("implementation"); + const auto *impl = table->properties->getProperty("implementation"_cs); if (impl == nullptr) { return false; } @@ -295,7 +298,7 @@ bool Bmv2V1ModelTableStepper::checkForActionProfile() { } const auto *testObject = - state->getTestObject("action_profile", implDecl->controlPlaneName(), false); + state->getTestObject("action_profile"_cs, implDecl->controlPlaneName(), false); if (testObject == nullptr) { // This means, for every possible control plane entry (and with that, new execution state) // add the generated action profile. @@ -309,7 +312,7 @@ bool Bmv2V1ModelTableStepper::checkForActionProfile() { } bool Bmv2V1ModelTableStepper::checkForActionSelector() { - const auto *impl = table->properties->getProperty("implementation"); + const auto *impl = table->properties->getProperty("implementation"_cs); if (impl == nullptr) { return false; } @@ -338,7 +341,7 @@ bool Bmv2V1ModelTableStepper::checkForActionSelector() { // Treat action selectors like action profiles for now. // The behavioral model P4Runtime is unclear how to configure action selectors. const auto *testObject = - state->getTestObject("action_profile", selectorDecl->controlPlaneName(), false); + state->getTestObject("action_profile"_cs, selectorDecl->controlPlaneName(), false); if (testObject == nullptr) { // This means, for every possible control plane entry (and with that, new execution state) // add the generated action profile. diff --git a/backends/p4tools/modules/testgen/targets/bmv2/target.cpp b/backends/p4tools/modules/testgen/targets/bmv2/target.cpp index a77168437d..6882b43fe3 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/target.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/target.cpp @@ -48,7 +48,7 @@ CompilerResultOrError Bmv2V1ModelTestgenTarget::runCompilerImpl( } /// After the front end, get the P4Runtime API for the V1model architecture. - auto p4runtimeApi = P4::P4RuntimeSerializer::get()->generateP4Runtime(program, "v1model"); + auto p4runtimeApi = P4::P4RuntimeSerializer::get()->generateP4Runtime(program, "v1model"_cs); if (::errorCount() > 0) { return std::nullopt; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/p4_asserts_parser_test.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/p4_asserts_parser_test.cpp index 5945cfb49b..a0ba39f3a9 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/p4_asserts_parser_test.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/p4_asserts_parser_test.cpp @@ -30,6 +30,8 @@ extern const char *sourcePath; extern const char *buildPath; namespace Test { +using namespace P4::literals; + class P4AssertsParserTest : public P4ToolsTest {}; class P4TestOptions : public CompilerOptions { public: @@ -54,11 +56,11 @@ ConstraintsVector loadExample(const char *curFile, bool flag) { auto *originalEnv = getenv("P4C_16_INCLUDE_PATH"); setenv("P4C_16_INCLUDE_PATH", includeDir.c_str(), 1); const IR::P4Program *program = nullptr; - options.file = sourcePath; + options.file = cstring(sourcePath); options.file += curFile; if (access(options.file, 0) != 0) { // Subpath for bf-p4c-compilers. - options.file = sourcePath; + options.file = cstring(sourcePath); options.file += curFile; } program = P4::parseP4File(options); @@ -98,9 +100,9 @@ TEST_F(P4AssertsParserTest, Restrictions) { ASSERT_EQ(parsingResult.size(), (unsigned long)3); { const auto &expr1 = P4Tools::ToolsVariables::getSymbolicVariable( - IR::Type_Bits::get(8), "ingress.ternary_table_mask_h.h.a1"); + IR::Type_Bits::get(8), "ingress.ternary_table_mask_h.h.a1"_cs); const auto &expr2 = P4Tools::ToolsVariables::getSymbolicVariable( - IR::Type_Bits::get(8), "ingress.ternary_table_lpm_prefix_h.h.a1"); + IR::Type_Bits::get(8), "ingress.ternary_table_lpm_prefix_h.h.a1"_cs); const auto *const1 = IR::Constant::get(IR::Type_Bits::get(8), 0); const auto *const2 = IR::Constant::get(IR::Type_Bits::get(8), 64); const auto *operation = @@ -109,14 +111,14 @@ TEST_F(P4AssertsParserTest, Restrictions) { } { const auto &expr1 = P4Tools::ToolsVariables::getSymbolicVariable( - IR::Type_Bits::get(8), "ingress.ternary_table_key_h.h.a1"); + IR::Type_Bits::get(8), "ingress.ternary_table_key_h.h.a1"_cs); const auto *const1 = IR::Constant::get(IR::Type_Bits::get(8), 0); const auto *operation1 = new IR::Neq(expr1, const1); ASSERT_TRUE(parsingResult[1]->equiv(*operation1)); } { const auto &expr1 = P4Tools::ToolsVariables::getSymbolicVariable( - IR::Type_Bits::get(8), "ingress.ternary_table_key_h.h.a"); + IR::Type_Bits::get(8), "ingress.ternary_table_key_h.h.a"_cs); const auto *const2 = IR::Constant::get(IR::Type_Bits::get(8), 255); const auto *operation2 = new IR::Neq(expr1, const2); ASSERT_TRUE(parsingResult[2]->equiv(*operation2)); @@ -128,10 +130,10 @@ TEST_F(P4AssertsParserTest, RestrictionMiddleblockReferToInTable) { "backends/p4tools/modules/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions_2.p4", false); ASSERT_EQ(parsingResult.size(), (unsigned long)3); - const auto &expr1 = P4Tools::ToolsVariables::getSymbolicVariable(IR::Type_Bits::get(8), - "ingress.table_1_key_h.h.a"); - const auto &expr2 = P4Tools::ToolsVariables::getSymbolicVariable(IR::Type_Bits::get(8), - "ingress.table_2_key_h.h.b"); + const auto &expr1 = P4Tools::ToolsVariables::getSymbolicVariable( + IR::Type_Bits::get(8), "ingress.table_1_key_h.h.a"_cs); + const auto &expr2 = P4Tools::ToolsVariables::getSymbolicVariable( + IR::Type_Bits::get(8), "ingress.table_2_key_h.h.b"_cs); const auto *operation = new IR::Equ(expr1, expr2); ASSERT_TRUE(parsingResult[0]->equiv(*operation)); } @@ -142,9 +144,9 @@ TEST_F(P4AssertsParserTest, RestrictionMiddleblockReferToInAction) { false); ASSERT_EQ(parsingResult.size(), (unsigned long)3); const auto *expr1 = P4Tools::ToolsVariables::getSymbolicVariable( - IR::Type_Bits::get(8), "ingress.table_1_ingress.MyAction1_arg_input_val"); - const auto *expr2 = P4Tools::ToolsVariables::getSymbolicVariable(IR::Type_Bits::get(8), - "ingress.table_1_key_h.h.a"); + IR::Type_Bits::get(8), "ingress.table_1_ingress.MyAction1_arg_input_val"_cs); + const auto *expr2 = P4Tools::ToolsVariables::getSymbolicVariable( + IR::Type_Bits::get(8), "ingress.table_1_key_h.h.a"_cs); auto *operation = new IR::Equ(expr1, expr2); ASSERT_TRUE(parsingResult[1]->equiv(*operation)); } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/reachability.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/reachability.cpp index 2cebe93857..4a51c644a1 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/reachability.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/reachability.cpp @@ -24,6 +24,8 @@ namespace Test { +using namespace P4::literals; + class P4ReachabilityOptions : public CompilerOptions { public: virtual ~P4ReachabilityOptions() = default; @@ -52,7 +54,7 @@ ReturnedInfo loadExampleForReachability(const char *curFile) { auto *originalEnv = getenv("P4C_16_INCLUDE_PATH"); setenv("P4C_16_INCLUDE_PATH", includeDir.c_str(), 1); const IR::P4Program *program = nullptr; - options.file = sourcePath; + options.file = cstring(sourcePath); options.file += curFile; program = P4::parseP4File(options); if (originalEnv == nullptr) { @@ -109,13 +111,13 @@ TEST_F(P4CReachability, testParserStatesAndAnnotations) { const auto *program = std::get<0>(result); ASSERT_TRUE(program); const auto *dcg = std::get<1>(result); - const auto *parser = getSpecificNode(program, "ParserI"); + const auto *parser = getSpecificNode(program, "ParserI"_cs); ASSERT_TRUE(parser); // Parser ParserI is reachable. ASSERT_TRUE(dcg->isReachable(program, parser)); - const auto *ingress = getSpecificNode(program, "IngressI"); + const auto *ingress = getSpecificNode(program, "IngressI"_cs); ASSERT_TRUE(ingress); - const auto *engress = getSpecificNode(program, "EgressI"); + const auto *engress = getSpecificNode(program, "EgressI"_cs); ASSERT_TRUE(engress); // IngressI is reachable. ASSERT_TRUE(dcg->isReachable(program, ingress)); @@ -126,10 +128,10 @@ TEST_F(P4CReachability, testParserStatesAndAnnotations) { // IgressI is not reachable from EngressI. ASSERT_TRUE(!dcg->isReachable(engress, ingress)); const auto *indirect = - ingress->to()->getDeclByName("indirect_0")->to(); + ingress->to()->getDeclByName("indirect_0"_cs)->to(); ASSERT_TRUE(indirect); const auto *indirectWs = - ingress->to()->getDeclByName("indirect_ws_0")->to(); + ingress->to()->getDeclByName("indirect_ws_0"_cs)->to(); ASSERT_TRUE(indirectWs); // Inderect table is reachable from ingress ASSERT_TRUE(dcg->isReachable(ingress, indirect)); @@ -164,7 +166,7 @@ TEST_F(P4CReachability, testLoops) { const IR::Node *getFromHash(const P4Tools::ReachabilityHashType &hash, const char *name) { CHECK_NULL(name); - auto s = hash.find(name); + auto s = hash.find(cstring(name)); if (s == hash.end()) { std::string nm = name; nm += "_table"; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/test_backend/ptf.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/test_backend/ptf.cpp index 39fcaf0726..915edf4f6a 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/test_backend/ptf.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/test_backend/ptf.cpp @@ -15,6 +15,8 @@ namespace Test { +using namespace P4::literals; + using ::testing::HasSubstr; TableConfig PTFTest::getForwardTableConfig() { @@ -22,13 +24,13 @@ TableConfig PTFTest::getForwardTableConfig() { IR::Constant::get(IR::Type_Bits::get(9), big_int("0x2"))); std::vector args({port}); const auto hit = ActionCall( - "SwitchIngress.hit", + "SwitchIngress.hit"_cs, new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), args); auto const *exactMatch = new Exact( new IR::KeyElement(new IR::PathExpression("key"), new IR::PathExpression("exact")), IR::Constant::get(IR::Type_Bits::get(48), big_int("0x222222222222"))); - auto matches = TableMatchMap({{"hdr.ethernet.dst_addr", exactMatch}}); + auto matches = TableMatchMap({{"hdr.ethernet.dst_addr"_cs, exactMatch}}); return TableConfig(new IR::P4Table("table", new IR::TableProperties()), {TableRule(matches, TestSpec::NO_PRIORITY, hit, 0)}); @@ -46,7 +48,7 @@ TableConfig PTFTest::getIPRouteTableConfig() { IR::Constant::get(IR::Type_Bits::get(9), big_int("0x2"))); const auto args = std::vector({srcAddr, dstAddr, dstPort}); const auto nat = ActionCall( - "SwitchIngress.nat", + "SwitchIngress.nat"_cs, new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), args); const auto *dipExactMatch = new Exact( @@ -57,7 +59,7 @@ TableConfig PTFTest::getIPRouteTableConfig() { new IR::KeyElement(new IR::PathExpression("key"), new IR::PathExpression("exact")), IR::Constant::get(IR::Type_Bits::get(16), big_int("0x0"))); - TableMatchMap matches({{"vrf", vrfExactMatch}, {"hdr.ipv4.dst_addr", dipExactMatch}}); + TableMatchMap matches({{"vrf"_cs, vrfExactMatch}, {"hdr.ipv4.dst_addr"_cs, dipExactMatch}}); return TableConfig(new IR::P4Table("table", new IR::TableProperties()), {TableRule(matches, TestSpec::NO_PRIORITY, nat, 0)}); @@ -80,11 +82,11 @@ TEST_F(PTFTest, Ptf01) { const auto fwdConfig = getForwardTableConfig(); auto testSpec = TestSpec(ingressPacket, egressPacket, {}); - testSpec.addTestObject("tables", "SwitchIngress.forward", &fwdConfig); + testSpec.addTestObject("tables"_cs, "SwitchIngress.forward"_cs, &fwdConfig); - TestBackendConfiguration testBackendConfiguration{"test01", 1, "test01", 1}; + TestBackendConfiguration testBackendConfiguration{"test01"_cs, 1, "test01", 1}; auto testWriter = PTF(testBackendConfiguration); - testWriter.writeTestToFile(&testSpec, "", 1, 0); + testWriter.writeTestToFile(&testSpec, cstring::empty, 1, 0); } /// Create a test spec with two Exact matches and print an ptf test. @@ -110,12 +112,12 @@ TEST_F(PTFTest, Ptf02) { const auto ipRouteConfig = getIPRouteTableConfig(); auto testSpec = TestSpec(ingressPacket, egressPacket, {}); - testSpec.addTestObject("tables", "SwitchIngress.forward", &fwdConfig); - testSpec.addTestObject("tables", "SwitchIngress.ipRoute", &ipRouteConfig); + testSpec.addTestObject("tables"_cs, "SwitchIngress.forward"_cs, &fwdConfig); + testSpec.addTestObject("tables"_cs, "SwitchIngress.ipRoute"_cs, &ipRouteConfig); - TestBackendConfiguration testBackendConfiguration{"test02", 1, "test02", 2}; + TestBackendConfiguration testBackendConfiguration{"test02"_cs, 1, "test02", 2}; auto testWriter = PTF(testBackendConfiguration); - testWriter.writeTestToFile(&testSpec, "", 2, 0); + testWriter.writeTestToFile(&testSpec, cstring::empty, 2, 0); } TableConfig PTFTest::gettest1TableConfig() { @@ -126,15 +128,15 @@ TableConfig PTFTest::gettest1TableConfig() { IR::Constant::get(IR::Type_Bits::get(9), big_int("0x2"))); const auto args = std::vector({val, port}); const auto setb1 = ActionCall( - "setb1", new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), - args); + "setb1"_cs, + new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), args); const auto *f1TernaryMatch = new Ternary( new IR::KeyElement(new IR::PathExpression("key"), new IR::PathExpression("ternary")), IR::Constant::get(IR::Type_Bits::get(32), big_int("0xABCD0101")), IR::Constant::get(IR::Type_Bits::get(32), big_int("0xFFFF0000"))); - TableMatchMap matches({{"data.f1", f1TernaryMatch}}); + TableMatchMap matches({{"data.f1"_cs, f1TernaryMatch}}); return TableConfig(new IR::P4Table("table", new IR::TableProperties()), {TableRule(matches, TestSpec::LOW_PRIORITY, setb1, 0)}); @@ -157,12 +159,12 @@ TEST_F(PTFTest, Ptf03) { const auto test1Config = gettest1TableConfig(); auto testSpec = TestSpec(ingressPacket, egressPacket, {}); - testSpec.addTestObject("tables", "test1", &test1Config); + testSpec.addTestObject("tables"_cs, "test1"_cs, &test1Config); - TestBackendConfiguration testBackendConfiguration{"test03", 1, "test03", 3}; + TestBackendConfiguration testBackendConfiguration{"test03"_cs, 1, "test03", 3}; auto testWriter = PTF(testBackendConfiguration); try { - testWriter.writeTestToFile(&testSpec, "", 3, 0); + testWriter.writeTestToFile(&testSpec, cstring::empty, 3, 0); } catch (const Util::CompilerBug &e) { EXPECT_THAT(e.what(), HasSubstr("Unimplemented for Ternary FieldMatch")); } @@ -176,8 +178,8 @@ TableConfig PTFTest::gettest1TableConfig2() { IR::Constant::get(IR::Type_Bits::get(9), big_int("0x2"))); const auto args = std::vector({val, port}); const auto setb1 = ActionCall( - "setb1", new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), - args); + "setb1"_cs, + new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), args); const auto *h1ExactMatch = new Exact( new IR::KeyElement(new IR::PathExpression("key"), new IR::PathExpression("exact")), @@ -197,12 +199,12 @@ TableConfig PTFTest::gettest1TableConfig2() { IR::Constant::get(IR::Type_Bits::get(32), big_int("0xABCDD00D")), IR::Constant::get(IR::Type_Bits::get(32), big_int("0x0000FFFF"))); - TableMatchMap matches1({{"data.f1", f1TernaryMatch}}); + TableMatchMap matches1({{"data.f1"_cs, f1TernaryMatch}}); - TableMatchMap matches2({{"data.h1", h1ExactMatch}, - {"data.f1", f1TernaryMatch}, - {"data.b1", b1ExactMatch}, - {"data.f2", f2TernaryMatch}}); + TableMatchMap matches2({{"data.h1"_cs, h1ExactMatch}, + {"data.f1"_cs, f1TernaryMatch}, + {"data.b1"_cs, b1ExactMatch}, + {"data.f2"_cs, f2TernaryMatch}}); return TableConfig(new IR::P4Table("table", new IR::TableProperties()), {TableRule(matches1, TestSpec::LOW_PRIORITY, setb1, 0), @@ -226,12 +228,12 @@ TEST_F(PTFTest, Ptf04) { const auto test1Config = gettest1TableConfig2(); auto testSpec = TestSpec(ingressPacket, egressPacket, {}); - testSpec.addTestObject("tables", "test1", &test1Config); + testSpec.addTestObject("tables"_cs, "test1"_cs, &test1Config); - TestBackendConfiguration testBackendConfiguration{"test04", 1, "test04", 4}; + TestBackendConfiguration testBackendConfiguration{"test04"_cs, 1, "test04", 4}; auto testWriter = PTF(testBackendConfiguration); try { - testWriter.writeTestToFile(&testSpec, "", 4, 0); + testWriter.writeTestToFile(&testSpec, cstring::empty, 4, 0); } catch (const Util::CompilerBug &e) { EXPECT_THAT(e.what(), HasSubstr("Unimplemented for Ternary FieldMatch")); } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/test_backend/stf.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/test_backend/stf.cpp index 4fce0fcc60..5ead04c78a 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/test_backend/stf.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/test_backend/stf.cpp @@ -15,6 +15,8 @@ namespace Test { +using namespace P4::literals; + using ::testing::HasSubstr; TableConfig STFTest::getForwardTableConfig() { @@ -22,13 +24,13 @@ TableConfig STFTest::getForwardTableConfig() { IR::Constant::get(IR::Type_Bits::get(9), big_int("0x2"))); std::vector args({port}); const auto hit = ActionCall( - "SwitchIngress.hit", + "SwitchIngress.hit"_cs, new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), args); auto const *exactMatch = new Exact( new IR::KeyElement(new IR::PathExpression("key"), new IR::PathExpression("exact")), IR::Constant::get(IR::Type_Bits::get(48), big_int("0x222222222222"))); - auto matches = TableMatchMap({{"hdr.ethernet.dst_addr", exactMatch}}); + auto matches = TableMatchMap({{"hdr.ethernet.dst_addr"_cs, exactMatch}}); return TableConfig(new IR::P4Table("table", new IR::TableProperties()), {TableRule(matches, TestSpec::NO_PRIORITY, hit, 0)}); @@ -46,7 +48,7 @@ TableConfig STFTest::getIPRouteTableConfig() { IR::Constant::get(IR::Type_Bits::get(9), big_int("0x2"))); const auto args = std::vector({srcAddr, dstAddr, dstPort}); const auto nat = ActionCall( - "SwitchIngress.nat", + "SwitchIngress.nat"_cs, new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), args); const auto *dipExactMatch = new Exact( @@ -57,7 +59,7 @@ TableConfig STFTest::getIPRouteTableConfig() { new IR::KeyElement(new IR::PathExpression("key"), new IR::PathExpression("exact")), IR::Constant::get(IR::Type_Bits::get(16), big_int("0x0"))); - TableMatchMap matches({{"vrf", vrfExactMatch}, {"hdr.ipv4.dst_addr", dipExactMatch}}); + TableMatchMap matches({{"vrf"_cs, vrfExactMatch}, {"hdr.ipv4.dst_addr"_cs, dipExactMatch}}); return TableConfig(new IR::P4Table("table", new IR::TableProperties()), {TableRule(matches, TestSpec::NO_PRIORITY, nat, 0)}); @@ -80,11 +82,11 @@ TEST_F(STFTest, Stf01) { const auto fwdConfig = getForwardTableConfig(); auto testSpec = TestSpec(ingressPacket, egressPacket, {}); - testSpec.addTestObject("tables", "SwitchIngress.forward", &fwdConfig); + testSpec.addTestObject("tables"_cs, "SwitchIngress.forward"_cs, &fwdConfig); - TestBackendConfiguration testBackendConfiguration{"test01", 1, "test01", 1}; + TestBackendConfiguration testBackendConfiguration{"test01"_cs, 1, "test01", 1}; auto testWriter = STF(testBackendConfiguration); - testWriter.writeTestToFile(&testSpec, "", 1, 0); + testWriter.writeTestToFile(&testSpec, cstring::empty, 1, 0); } /// Create a test spec with two Exact matches and print an stf test. @@ -110,12 +112,12 @@ TEST_F(STFTest, Stf02) { const auto ipRouteConfig = getIPRouteTableConfig(); auto testSpec = TestSpec(ingressPacket, egressPacket, {}); - testSpec.addTestObject("tables", "SwitchIngress.forward", &fwdConfig); - testSpec.addTestObject("tables", "SwitchIngress.ipRoute", &ipRouteConfig); + testSpec.addTestObject("tables"_cs, "SwitchIngress.forward"_cs, &fwdConfig); + testSpec.addTestObject("tables"_cs, "SwitchIngress.ipRoute"_cs, &ipRouteConfig); - TestBackendConfiguration testBackendConfiguration{"test02", 1, "test02", 2}; + TestBackendConfiguration testBackendConfiguration{"test02"_cs, 1, "test02", 2}; auto testWriter = STF(testBackendConfiguration); - testWriter.writeTestToFile(&testSpec, "", 2, 0); + testWriter.writeTestToFile(&testSpec, cstring::empty, 2, 0); } TableConfig STFTest::gettest1TableConfig() { @@ -126,15 +128,15 @@ TableConfig STFTest::gettest1TableConfig() { IR::Constant::get(IR::Type_Bits::get(9), big_int("0x2"))); const auto args = std::vector({val, port}); const auto setb1 = ActionCall( - "setb1", new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), - args); + "setb1"_cs, + new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), args); const auto *f1TernaryMatch = new Ternary( new IR::KeyElement(new IR::PathExpression("key"), new IR::PathExpression("ternary")), IR::Constant::get(IR::Type_Bits::get(32), big_int("0xABCD0101")), IR::Constant::get(IR::Type_Bits::get(32), big_int("0xFFFF0000"))); - TableMatchMap matches({{"data.f1", f1TernaryMatch}}); + TableMatchMap matches({{"data.f1"_cs, f1TernaryMatch}}); return TableConfig(new IR::P4Table("table", new IR::TableProperties()), {TableRule(matches, TestSpec::LOW_PRIORITY, setb1, 0)}); @@ -157,12 +159,12 @@ TEST_F(STFTest, Stf03) { const auto test1Config = gettest1TableConfig(); auto testSpec = TestSpec(ingressPacket, egressPacket, {}); - testSpec.addTestObject("tables", "test1", &test1Config); + testSpec.addTestObject("tables"_cs, "test1"_cs, &test1Config); - TestBackendConfiguration testBackendConfiguration{"test03", 1, "test03", 3}; + TestBackendConfiguration testBackendConfiguration{"test03"_cs, 1, "test03", 3}; auto testWriter = STF(testBackendConfiguration); try { - testWriter.writeTestToFile(&testSpec, "", 3, 0); + testWriter.writeTestToFile(&testSpec, cstring::empty, 3, 0); } catch (const Util::CompilerBug &e) { EXPECT_THAT(e.what(), HasSubstr("Unimplemented for Ternary FieldMatch")); } @@ -176,8 +178,8 @@ TableConfig STFTest::gettest1TableConfig2() { IR::Constant::get(IR::Type_Bits::get(9), big_int("0x2"))); const auto args = std::vector({val, port}); const auto setb1 = ActionCall( - "setb1", new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), - args); + "setb1"_cs, + new IR::P4Action("dummy", new IR::ParameterList({}, {}), new IR::BlockStatement()), args); const auto *h1ExactMatch = new Exact( new IR::KeyElement(new IR::PathExpression("key"), new IR::PathExpression("exact")), @@ -197,12 +199,12 @@ TableConfig STFTest::gettest1TableConfig2() { IR::Constant::get(IR::Type_Bits::get(32), big_int("0xABCDD00D")), IR::Constant::get(IR::Type_Bits::get(32), big_int("0x0000FFFF"))); - TableMatchMap matches1({{"data.f1", f1TernaryMatch}}); + TableMatchMap matches1({{"data.f1"_cs, f1TernaryMatch}}); - TableMatchMap matches2({{"data.h1", h1ExactMatch}, - {"data.f1", f1TernaryMatch}, - {"data.b1", b1ExactMatch}, - {"data.f2", f2TernaryMatch}}); + TableMatchMap matches2({{"data.h1"_cs, h1ExactMatch}, + {"data.f1"_cs, f1TernaryMatch}, + {"data.b1"_cs, b1ExactMatch}, + {"data.f2"_cs, f2TernaryMatch}}); return TableConfig(new IR::P4Table("table", new IR::TableProperties()), {TableRule(matches1, TestSpec::LOW_PRIORITY, setb1, 0), @@ -226,12 +228,12 @@ TEST_F(STFTest, Stf04) { const auto test1Config = gettest1TableConfig2(); auto testSpec = TestSpec(ingressPacket, egressPacket, {}); - testSpec.addTestObject("tables", "test1", &test1Config); + testSpec.addTestObject("tables"_cs, "test1"_cs, &test1Config); - TestBackendConfiguration testBackendConfiguration{"test04", 1, "test04", 4}; + TestBackendConfiguration testBackendConfiguration{"test04"_cs, 1, "test04", 4}; auto testWriter = STF(testBackendConfiguration); try { - testWriter.writeTestToFile(&testSpec, "", 4, 0); + testWriter.writeTestToFile(&testSpec, cstring::empty, 4, 0); } catch (const Util::CompilerBug &e) { EXPECT_THAT(e.what(), HasSubstr("Unimplemented for Ternary FieldMatch")); } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/api_test.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/api_test.cpp index af9def86b1..e8cc38ff6b 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/api_test.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/api_test.cpp @@ -10,6 +10,8 @@ namespace Test { +using namespace P4::literals; + TEST(P4TestgenLibrary, GeneratesCorrectProtobufIrTest) { std::stringstream streamTest; streamTest << R"p4( @@ -56,11 +58,11 @@ V1Switch(parse(), verifyChecksum(), ingress(), egress(), computeChecksum(), depa auto source = P4_SOURCE(P4Headers::V1MODEL, streamTest.str().c_str()); auto compilerOptions = P4CContextWithOptions::get().options(); - compilerOptions.target = "bmv2"; - compilerOptions.arch = "v1model"; + compilerOptions.target = "bmv2"_cs; + compilerOptions.arch = "v1model"_cs; auto &testgenOptions = P4Tools::P4Testgen::TestgenOptions::get(); - testgenOptions.testBackend = "PROTOBUF_IR"; - testgenOptions.testBaseName = "dummy"; + testgenOptions.testBackend = "PROTOBUF_IR"_cs; + testgenOptions.testBaseName = "dummy"_cs; // Create a bespoke packet for the Ethernet extract call. testgenOptions.minPktSize = 112; testgenOptions.maxPktSize = 112; @@ -79,7 +81,7 @@ V1Switch(parse(), verifyChecksum(), ingress(), egress(), computeChecksum(), depa EXPECT_THAT(protobufIrTest->getFormattedTest(), ::testing::HasSubstr(R"(input_packet)")); } /// Now try running again with the test back end set to Protobuf. The result should be the same. - testgenOptions.testBackend = "PROTOBUF"; + testgenOptions.testBackend = "PROTOBUF"_cs; auto testListOpt = P4Tools::P4Testgen::Testgen::generateTests(source, compilerOptions, testgenOptions); diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/benchmark.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/benchmark.cpp index aa48f41825..d726364f1f 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/benchmark.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/benchmark.cpp @@ -10,18 +10,20 @@ namespace Test { +using namespace P4::literals; + TEST(P4TestgenBenchmark, SuccessfullyGenerate1000Tests) { auto compilerOptions = P4CContextWithOptions::get().options(); - compilerOptions.target = "bmv2"; - compilerOptions.arch = "v1model"; + compilerOptions.target = "bmv2"_cs; + compilerOptions.arch = "v1model"_cs; auto includePath = P4CTestEnvironment::getProjectRoot() / "p4include"; compilerOptions.preprocessor_options = "-I" + includePath.string(); auto fabricFile = P4CTestEnvironment::getProjectRoot() / "testdata/p4_16_samples/fabric_20190420/fabric.p4"; compilerOptions.file = fabricFile.string(); auto &testgenOptions = P4Tools::P4Testgen::TestgenOptions::get(); - testgenOptions.testBackend = "PROTOBUF_IR"; - testgenOptions.testBaseName = "dummy"; + testgenOptions.testBackend = "PROTOBUF_IR"_cs; + testgenOptions.testBaseName = "dummy"_cs; testgenOptions.seed = 1; // Fix the packet size. testgenOptions.minPktSize = 512; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/control_plane_filter_test.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/control_plane_filter_test.cpp index 2444ffc7d9..114ae02d47 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/control_plane_filter_test.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/control_plane_filter_test.cpp @@ -13,6 +13,8 @@ namespace Test { +using namespace P4::literals; + using testing::Contains; using testing::HasSubstr; using testing::Not; @@ -63,15 +65,15 @@ V1Switch(parse(), verifyChecksum(), ingress(), egress(), computeChecksum(), depa CompilerOptions generateDefaultApiTestCompilerOptions() { auto compilerOptions = P4CContextWithOptions::get().options(); - compilerOptions.target = "bmv2"; - compilerOptions.arch = "v1model"; + compilerOptions.target = "bmv2"_cs; + compilerOptions.arch = "v1model"_cs; return compilerOptions; } P4Tools::P4Testgen::TestgenOptions &generateDefaultApiTestTestgenOptions() { auto &testgenOptions = P4Tools::P4Testgen::TestgenOptions::get(); - testgenOptions.testBackend = "PROTOBUF_IR"; - testgenOptions.testBaseName = "dummy"; + testgenOptions.testBackend = "PROTOBUF_IR"_cs; + testgenOptions.testBaseName = "dummy"_cs; testgenOptions.seed = 1; testgenOptions.maxTests = 0; // Create a bespoke packet for the Ethernet extract call. @@ -156,7 +158,7 @@ TEST(P4TestgenControlPlaneFilterTest, FiltersControlPlaneEntities) { // We install a filter. // Since we can not generate a config for the table we should only generate one test. - testgenOptions.skippedControlPlaneEntities = {"ingress.drop_table"}; + testgenOptions.skippedControlPlaneEntities = {"ingress.drop_table"_cs}; auto testListOpt = P4Tools::P4Testgen::Testgen::generateTests(source, compilerOptions, testgenOptions); @@ -196,7 +198,7 @@ TEST(P4TestgenControlPlaneFilterTest, IgnoresBogusControlPlaneEntities) { // This is a bogus control plane element, which is ignored. We expect two tests. // One which exercises action acl_drop and one which exercises the default action, NoAction. - testgenOptions.skippedControlPlaneEntities = {"ingress.bogus_table"}; + testgenOptions.skippedControlPlaneEntities = {"ingress.bogus_table"_cs}; auto testListOpt = P4Tools::P4Testgen::Testgen::generateTests(source, compilerOptions, testgenOptions); @@ -262,7 +264,8 @@ TEST(P4TestgenControlPlaneFilterTest, FiltersMultipleControlPlaneEntities) { // We install a filter. // Since we can not generate a config for the table we should only generate one test. - testgenOptions.skippedControlPlaneEntities = {"ingress.drop_table", "ingress.set_eth_table"}; + testgenOptions.skippedControlPlaneEntities = {"ingress.drop_table"_cs, + "ingress.set_eth_table"_cs}; auto testListOpt = P4Tools::P4Testgen::Testgen::generateTests(source, compilerOptions, testgenOptions); diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/output_option_test.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/output_option_test.cpp index 7e22f2fadc..1a1c0ba609 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/output_option_test.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/testgen_api/output_option_test.cpp @@ -9,6 +9,8 @@ namespace Test { +using namespace P4::literals; + TEST(P4TestgenOutputOptionTest, GenerateOuputsCorrectly) { std::stringstream streamTest; streamTest << R"p4( @@ -55,11 +57,11 @@ V1Switch(parse(), verifyChecksum(), ingress(), egress(), computeChecksum(), depa auto source = P4_SOURCE(P4Headers::V1MODEL, streamTest.str().c_str()); auto compilerOptions = P4CContextWithOptions::get().options(); - compilerOptions.target = "bmv2"; - compilerOptions.arch = "v1model"; + compilerOptions.target = "bmv2"_cs; + compilerOptions.arch = "v1model"_cs; auto &testgenOptions = P4Tools::P4Testgen::TestgenOptions::get(); - testgenOptions.testBackend = "PROTOBUF_IR"; - testgenOptions.testBaseName = "dummy"; + testgenOptions.testBackend = "PROTOBUF_IR"_cs; + testgenOptions.testBaseName = "dummy"_cs; testgenOptions.seed = 1; testgenOptions.maxTests = 0; // Create a bespoke packet for the Ethernet extract call. diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/transformations/saturation_arithm.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/transformations/saturation_arithm.cpp index 91501e9768..20a0725f1a 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/transformations/saturation_arithm.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/transformations/saturation_arithm.cpp @@ -22,6 +22,8 @@ namespace Test { +using namespace P4::literals; + using P4::SaturationElim; using P4Tools::Model; using P4Tools::Z3Solver; @@ -88,7 +90,7 @@ class Z3SolverSatTests : public ::testing::Test { } // Extract the binary operation from the P4Program - const auto *decl = test->getProgram().getDeclsByName("mau")->single(); + const auto *decl = test->getProgram().getDeclsByName("mau"_cs)->single(); const auto *control = decl->to(); for (const auto *st : control->body->components) { if (const auto *as = st->to()) { diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/asrt_model.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/asrt_model.cpp index ad7d91ae03..60d4027359 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/asrt_model.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/asrt_model.cpp @@ -25,6 +25,8 @@ namespace Test { +using namespace P4::literals; + using P4Tools::Model; using P4Tools::Z3Solver; using P4Tools::Z3SolverAccessor; @@ -93,7 +95,7 @@ class Z3SolverTest : public P4ToolsTest { } // Extract the binary operation from the P4Program - const auto *decl = test->getProgram().getDeclsByName("mau")->single(); + const auto *decl = test->getProgram().getDeclsByName("mau"_cs)->single(); const auto *control = decl->to(); SymbolicConverter converter; for (const auto *st : control->body->components) { diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/expressions.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/expressions.cpp index f806bee922..b94f8dff11 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/expressions.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/expressions.cpp @@ -17,6 +17,8 @@ namespace Test { +using namespace P4::literals; + using P4Tools::Z3Solver; using P4Tools::P4Testgen::TestgenTarget; using Value = IR::Literal; @@ -87,7 +89,7 @@ class Z3SolverTests : public ::testing::Test { } // Extract the binary operation from the P4Program - const auto *decl = test->getProgram().getDeclsByName("mau")->single(); + const auto *decl = test->getProgram().getDeclsByName("mau"_cs)->single(); const auto *control = decl->to(); for (const auto *st : control->body->components) { if (const auto *as = st->to()) { diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_backend.cpp index 7dc9ddc825..c9fd78b3d7 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend.cpp @@ -103,7 +103,7 @@ const TestSpec *Bmv2TestBackend::createTestSpec(const ExecutionState *executionS if (TestgenOptions::get().testBackend == "METADATA") { auto *metadataCollection = new MetadataCollection(); const auto *bmv2ProgInfo = getProgramInfo().checkedTo(); - const auto *localMetadataVar = bmv2ProgInfo->getBlockParam("Parser", 2); + const auto *localMetadataVar = bmv2ProgInfo->getBlockParam("Parser"_cs, 2); const auto &flatFields = executionState->getFlatFields(localMetadataVar, {}); for (const auto &fieldRef : flatFields) { const auto *fieldVal = finalModel->evaluate(executionState->get(fieldRef), true); @@ -113,51 +113,52 @@ const TestSpec *Bmv2TestBackend::createTestSpec(const ExecutionState *executionS fieldString = fieldString.substr(fieldString.find('.') - fieldString.begin() + 1); metadataCollection->addMetaDataField(fieldString, fieldVal); } - testSpec->addTestObject("metadata_collection", "metadata_collection", metadataCollection); + testSpec->addTestObject("metadata_collection"_cs, "metadata_collection"_cs, + metadataCollection); return testSpec; } // We retrieve the individual table configurations from the execution state. - const auto uninterpretedTableConfigs = executionState->getTestObjectCategory("tableconfigs"); + const auto uninterpretedTableConfigs = executionState->getTestObjectCategory("tableconfigs"_cs); // Since these configurations are uninterpreted we need to convert them. We launch a // helper function to solve the variables involved in each table configuration. for (const auto &tablePair : uninterpretedTableConfigs) { const auto tableName = tablePair.first; const auto *uninterpretedTableConfig = tablePair.second->checkedTo(); const auto *tableConfig = uninterpretedTableConfig->evaluate(*finalModel, true); - testSpec->addTestObject("tables", tableName, tableConfig); + testSpec->addTestObject("tables"_cs, tableName, tableConfig); } - const auto actionProfiles = executionState->getTestObjectCategory("action_profile"); + const auto actionProfiles = executionState->getTestObjectCategory("action_profile"_cs); for (const auto &testObject : actionProfiles) { const auto profileName = testObject.first; const auto *actionProfile = testObject.second->checkedTo(); const auto *evaluatedProfile = actionProfile->evaluate(*finalModel, true); - testSpec->addTestObject("action_profiles", profileName, evaluatedProfile); + testSpec->addTestObject("action_profiles"_cs, profileName, evaluatedProfile); } - const auto actionSelectors = executionState->getTestObjectCategory("action_selector"); + const auto actionSelectors = executionState->getTestObjectCategory("action_selector"_cs); for (const auto &testObject : actionSelectors) { const auto selectorName = testObject.first; const auto *actionSelector = testObject.second->checkedTo(); const auto *evaluatedSelector = actionSelector->evaluate(*finalModel, true); - testSpec->addTestObject("action_selectors", selectorName, evaluatedSelector); + testSpec->addTestObject("action_selectors"_cs, selectorName, evaluatedSelector); } - const auto cloneSpecs = executionState->getTestObjectCategory("clone_specs"); + const auto cloneSpecs = executionState->getTestObjectCategory("clone_specs"_cs); for (const auto &testObject : cloneSpecs) { const auto sessionId = testObject.first; const auto *cloneSpec = testObject.second->checkedTo(); const auto *evaluatedInfo = cloneSpec->evaluate(*finalModel, true); - testSpec->addTestObject("clone_specs", sessionId, evaluatedInfo); + testSpec->addTestObject("clone_specs"_cs, sessionId, evaluatedInfo); } - const auto meterInfos = executionState->getTestObjectCategory("meter_values"); + const auto meterInfos = executionState->getTestObjectCategory("meter_values"_cs); for (const auto &testObject : meterInfos) { const auto meterName = testObject.first; const auto *meterInfo = testObject.second->checkedTo(); const auto *evaluateMeterValue = meterInfo->evaluate(*finalModel, true); - testSpec->addTestObject("meter_values", meterName, evaluateMeterValue); + testSpec->addTestObject("meter_values"_cs, meterName, evaluateMeterValue); } return testSpec; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.cpp index fb51b6d39a..0208ffad5b 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.cpp @@ -90,7 +90,7 @@ inja::json Bmv2TestFramework::getControlPlane(const TestSpec *testSpec) const { // Map of actionProfiles and actionSelectors for easy reference. std::map apAsMap; - auto tables = testSpec->getTestObjectCategory("tables"); + auto tables = testSpec->getTestObjectCategory("tables"_cs); if (!tables.empty()) { controlPlaneJson["tables"] = inja::json::array(); } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/metadata.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/metadata.cpp index c1aa5f6857..d0f8e764e4 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/metadata.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/metadata.cpp @@ -110,7 +110,7 @@ void Metadata::emitTestcase(const TestSpec *testSpec, cstring selectedBranches, dataJson["coverage"] = coverageStr.str(); dataJson["metadata_fields"] = inja::json::array(); const auto *metadataCollection = - testSpec->getTestObject("metadata_collection", "metadata_collection", true) + testSpec->getTestObject("metadata_collection"_cs, "metadata_collection"_cs, true) ->checkedTo(); auto offset = 0; for (auto const &metadataField : metadataCollection->getMetadataFields()) { diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf.cpp index cb5fc574d0..2597cf846b 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf.cpp @@ -40,7 +40,7 @@ inja::json Protobuf::getControlPlane(const TestSpec *testSpec) const { // Map of actionProfiles and actionSelectors for easy reference. std::map apAsMap; - auto tables = testSpec->getTestObjectCategory("tables"); + auto tables = testSpec->getTestObjectCategory("tables"_cs); if (!tables.empty()) { controlPlaneJson["tables"] = inja::json::array(); } @@ -335,11 +335,11 @@ inja::json Protobuf::produceTestCase(const TestSpec *testSpec, cstring selectedB // Check whether this test has a clone configuration. // These are special because they require additional instrumentation and produce two output // packets. - auto cloneSpecs = testSpec->getTestObjectCategory("clone_specs"); + auto cloneSpecs = testSpec->getTestObjectCategory("clone_specs"_cs); if (!cloneSpecs.empty()) { dataJson["clone_specs"] = getClone(cloneSpecs); } - auto meterValues = testSpec->getTestObjectCategory("meter_values"); + auto meterValues = testSpec->getTestObjectCategory("meter_values"_cs); dataJson["meter_values"] = getMeter(meterValues); return dataJson; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.cpp index 67f3d32302..5793de6f5c 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.cpp @@ -26,7 +26,7 @@ ProtobufIr::ProtobufIr(const TestBackendConfiguration &testBackendConfiguration, std::optional ProtobufIr::checkForP4RuntimeTranslationAnnotation( const IR::IAnnotated *node) { - const auto *p4RuntimeTranslationAnnotation = node->getAnnotation("p4runtime_translation"); + const auto *p4RuntimeTranslationAnnotation = node->getAnnotation("p4runtime_translation"_cs); if (p4RuntimeTranslationAnnotation == nullptr) { return std::nullopt; } @@ -46,7 +46,7 @@ std::optional ProtobufIr::checkForP4RuntimeTranslationAnnotation( std::map ProtobufIr::getP4RuntimeTranslationMappings(const IR::IAnnotated *node) { std::map p4RuntimeTranslationMappings; const auto *p4RuntimeTranslationMappingAnnotation = - node->getAnnotation("p4runtime_translation_mappings"); + node->getAnnotation("p4runtime_translation_mappings"_cs); if (p4RuntimeTranslationMappingAnnotation == nullptr) { return p4RuntimeTranslationMappings; } @@ -72,7 +72,7 @@ std::string ProtobufIr::getFormatOfNode(const IR::IAnnotated *node) { return p4RuntimeTranslationFormat.value(); } - const auto *formatAnnotation = node->getAnnotation("format"); + const auto *formatAnnotation = node->getAnnotation("format"_cs); if (formatAnnotation == nullptr) { return "hex_str"; } @@ -428,11 +428,11 @@ inja::json ProtobufIr::produceTestCase(const TestSpec *testSpec, cstring selecte // Check whether this test has a clone configuration. // These are special because they require additional instrumentation and produce two output // packets. - auto cloneSpecs = testSpec->getTestObjectCategory("clone_specs"); + auto cloneSpecs = testSpec->getTestObjectCategory("clone_specs"_cs); if (!cloneSpecs.empty()) { dataJson["clone_specs"] = getClone(cloneSpecs); } - auto meterValues = testSpec->getTestObjectCategory("meter_values"); + auto meterValues = testSpec->getTestObjectCategory("meter_values"_cs); dataJson["meter_values"] = getMeter(meterValues); return dataJson; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/ptf.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/ptf.cpp index c78334acf4..3f462a5867 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/ptf.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/ptf.cpp @@ -283,11 +283,11 @@ void PTF::emitTestcase(const TestSpec *testSpec, cstring selectedBranches, size_ // Check whether this test has a clone configuration. // These are special because they require additional instrumentation and produce two output // packets. - auto cloneSpecs = testSpec->getTestObjectCategory("clone_specs"); + auto cloneSpecs = testSpec->getTestObjectCategory("clone_specs"_cs); if (!cloneSpecs.empty()) { dataJson["clone_specs"] = getClone(cloneSpecs); } - auto meterValues = testSpec->getTestObjectCategory("meter_values"); + auto meterValues = testSpec->getTestObjectCategory("meter_values"_cs); dataJson["meter_values"] = getMeter(meterValues); LOG5("PTF backend: emitting testcase:" << std::setw(4) << dataJson); diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/stf.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/stf.cpp index 11e0773d30..480ea22258 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/stf.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/stf.cpp @@ -226,7 +226,7 @@ void STF::emitTestcase(const TestSpec *testSpec, cstring selectedBranches, size_ // Check whether this test has a clone configuration. // These are special because they require additional instrumentation and produce two output // packets. - auto cloneSpecs = testSpec->getTestObjectCategory("clone_specs"); + auto cloneSpecs = testSpec->getTestObjectCategory("clone_specs"_cs); if (!cloneSpecs.empty()) { dataJson["clone_specs"] = getClone(cloneSpecs); } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_spec.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_spec.cpp index d493a7dde5..4acdc5703e 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_spec.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_spec.cpp @@ -7,6 +7,8 @@ namespace P4Tools::P4Testgen::Bmv2 { +using namespace P4::literals; + /* ========================================================================================= * IndexExpression * ========================================================================================= */ @@ -32,7 +34,7 @@ const IR::Expression *IndexExpression::getIndex() const { return index; } const IR::Expression *IndexExpression::getValue() const { return value; } -cstring IndexExpression::getObjectName() const { return "IndexExpression"; } +cstring IndexExpression::getObjectName() const { return "IndexExpression"_cs; } const IndexExpression *IndexExpression::evaluate(const Model &model, bool doComplete) const { const auto *evaluatedIndex = model.evaluate(index, doComplete); @@ -89,7 +91,7 @@ const IR::Constant *IndexMap::getEvaluatedInitialValue() const { Bmv2V1ModelRegisterValue::Bmv2V1ModelRegisterValue(const IR::Expression *initialValue) : IndexMap(initialValue) {} -cstring Bmv2V1ModelRegisterValue::getObjectName() const { return "Bmv2V1ModelRegisterValue"; } +cstring Bmv2V1ModelRegisterValue::getObjectName() const { return "Bmv2V1ModelRegisterValue"_cs; } const Bmv2V1ModelRegisterValue *Bmv2V1ModelRegisterValue::evaluate(const Model &model, bool doComplete) const { @@ -110,7 +112,7 @@ const Bmv2V1ModelRegisterValue *Bmv2V1ModelRegisterValue::evaluate(const Model & Bmv2V1ModelMeterValue::Bmv2V1ModelMeterValue(const IR::Expression *initialValue, bool isDirect) : IndexMap(initialValue), isDirect(isDirect) {} -cstring Bmv2V1ModelMeterValue::getObjectName() const { return "Bmv2V1ModelMeterValue"; } +cstring Bmv2V1ModelMeterValue::getObjectName() const { return "Bmv2V1ModelMeterValue"_cs; } const Bmv2V1ModelMeterValue *Bmv2V1ModelMeterValue::evaluate(const Model &model, bool doComplete) const { @@ -171,7 +173,7 @@ Bmv2V1ModelActionSelector::Bmv2V1ModelActionSelector(const IR::IDeclaration *sel const Bmv2V1ModelActionProfile *actionProfile) : selectorDecl(selectorDecl), actionProfile(actionProfile) {} -cstring Bmv2V1ModelActionSelector::getObjectName() const { return "Bmv2V1ModelActionSelector"; } +cstring Bmv2V1ModelActionSelector::getObjectName() const { return "Bmv2V1ModelActionSelector"_cs; } const IR::IDeclaration *Bmv2V1ModelActionSelector::getSelectorDecl() const { return selectorDecl; } @@ -198,7 +200,7 @@ Bmv2V1ModelCloneInfo::Bmv2V1ModelCloneInfo(const IR::Expression *sessionId, clonedState(clonedState), preserveIndex(preserveIndex) {} -cstring Bmv2V1ModelCloneInfo::getObjectName() const { return "Bmv2V1ModelCloneInfo"; } +cstring Bmv2V1ModelCloneInfo::getObjectName() const { return "Bmv2V1ModelCloneInfo"_cs; } BMv2Constants::CloneType Bmv2V1ModelCloneInfo::getCloneType() const { return cloneType; } @@ -221,7 +223,7 @@ Bmv2V1ModelCloneSpec::Bmv2V1ModelCloneSpec(const IR::Expression *sessionId, const IR::Expression *clonePort, bool isClone) : sessionId(sessionId), clonePort(clonePort), isClone(isClone) {} -cstring Bmv2V1ModelCloneSpec::getObjectName() const { return "Bmv2V1ModelCloneSpec"; } +cstring Bmv2V1ModelCloneSpec::getObjectName() const { return "Bmv2V1ModelCloneSpec"_cs; } const IR::Expression *Bmv2V1ModelCloneSpec::getClonePort() const { return clonePort; } @@ -270,7 +272,7 @@ const Optional *Optional::evaluate(const Model &model, bool doComplete) const { return new Optional(getKey(), evaluatedValue, addMatch); } -cstring Optional::getObjectName() const { return "Optional"; } +cstring Optional::getObjectName() const { return "Optional"_cs; } bool Optional::addAsExactMatch() const { return addMatch; } @@ -307,7 +309,7 @@ const Range *Range::evaluate(const Model &model, bool doComplete) const { MetadataCollection::MetadataCollection() = default; -cstring MetadataCollection::getObjectName() const { return "MetadataCollection"; } +cstring MetadataCollection::getObjectName() const { return "MetadataCollection"_cs; } const MetadataCollection *MetadataCollection::evaluate(const Model & /*model*/, bool /*finalModel*/) const { @@ -326,6 +328,6 @@ void MetadataCollection::addMetaDataField(cstring name, const IR::Literal *metad metadataFields[name] = metadataField; } -cstring Range::getObjectName() const { return "Range"; } +cstring Range::getObjectName() const { return "Range"_cs; } } // namespace P4Tools::P4Testgen::Bmv2 diff --git a/backends/p4tools/modules/testgen/targets/ebpf/backend/stf/stf.cpp b/backends/p4tools/modules/testgen/targets/ebpf/backend/stf/stf.cpp index 7072e6ce3f..e2e82bf682 100644 --- a/backends/p4tools/modules/testgen/targets/ebpf/backend/stf/stf.cpp +++ b/backends/p4tools/modules/testgen/targets/ebpf/backend/stf/stf.cpp @@ -40,7 +40,7 @@ inja::json STF::getControlPlane(const TestSpec *testSpec) { // Map of actionProfiles and actionSelectors for easy reference. std::map apAsMap; - auto tables = testSpec->getTestObjectCategory("tables"); + auto tables = testSpec->getTestObjectCategory("tables"_cs); if (!tables.empty()) { controlPlaneJson["tables"] = inja::json::array(); } diff --git a/backends/p4tools/modules/testgen/targets/ebpf/expr_stepper.cpp b/backends/p4tools/modules/testgen/targets/ebpf/expr_stepper.cpp index 734eed8d7f..bc2bf4f800 100644 --- a/backends/p4tools/modules/testgen/targets/ebpf/expr_stepper.cpp +++ b/backends/p4tools/modules/testgen/targets/ebpf/expr_stepper.cpp @@ -45,8 +45,8 @@ void EBPFExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, * CounterArray.add: Add value to counter with specified index. * ====================================================================================== */ // TODO: Count currently has no effect in the symbolic interpreter. - {"CounterArray.add", - {"index", "value"}, + {"CounterArray.add"_cs, + {"index"_cs, "value"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -66,8 +66,8 @@ void EBPFExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, * CounterArray.increment: Add value to counter with specified index. * ====================================================================================== */ // TODO: Count currently has no effect in the symbolic interpreter. - {"CounterArray.increment", - {"index"}, + {"CounterArray.increment"_cs, + {"index"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -85,8 +85,8 @@ void EBPFExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, * @return True if checksum is correct. * Implemented in p4c/testdata/extern_modules/extern-checksum-ebpf.c * ====================================================================================== */ - {"*method.verify_ipv4_checksum", - {"iphdr"}, + {"*method.verify_ipv4_checksum"_cs, + {"iphdr"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -162,19 +162,19 @@ void EBPFExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call, * stateful packet processing. * Implemented in p4c/testdata/extern_modules/extern-conntrack-ebpf.c * ====================================================================================== */ - {"*method.tcp_conntrack", - {"hdrs"}, + {"*method.tcp_conntrack"_cs, + {"hdrs"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { // Input must be the headers struct. const auto *headers = args->at(0)->expression->checkedTo(); - const auto *tcpRef = headers->getField("tcp"); + const auto *tcpRef = headers->getField("tcp"_cs); CHECK_NULL(tcpRef); const auto *tcpHeader = tcpRef->expression->checkedTo(); - const auto *syn = tcpHeader->getField("syn"); + const auto *syn = tcpHeader->getField("syn"_cs); CHECK_NULL(syn); - const auto *ack = tcpHeader->getField("ack"); + const auto *ack = tcpHeader->getField("ack"_cs); CHECK_NULL(ack); const auto *synExpr = syn->expression; const auto *ackExpr = ack->expression; diff --git a/backends/p4tools/modules/testgen/targets/ebpf/program_info.cpp b/backends/p4tools/modules/testgen/targets/ebpf/program_info.cpp index 36147c7bb6..b42aec4427 100644 --- a/backends/p4tools/modules/testgen/targets/ebpf/program_info.cpp +++ b/backends/p4tools/modules/testgen/targets/ebpf/program_info.cpp @@ -26,6 +26,8 @@ namespace P4Tools::P4Testgen::EBPF { +using namespace P4::literals; + const IR::Type_Bits EBPFProgramInfo::PARSER_ERR_BITS = IR::Type_Bits(32, false); EBPFProgramInfo::EBPFProgramInfo(const TestgenCompilerResult &compilerResult, @@ -122,9 +124,9 @@ const IR::Expression *EBPFProgramInfo::dropIsActive() const { const IR::Type_Bits *EBPFProgramInfo::getParserErrorType() const { return &PARSER_ERR_BITS; } const ArchSpec EBPFProgramInfo::ARCH_SPEC = - ArchSpec("ebpfFilter", {// parser parse(packet_in packet, out H headers); - {"parse", {nullptr, "*hdr"}}, - // control filter(inout H headers, out bool accept); - {"filter", {"*hdr", "*accept"}}}); + ArchSpec("ebpfFilter"_cs, {// parser parse(packet_in packet, out H headers); + {"parse"_cs, {nullptr, "*hdr"_cs}}, + // control filter(inout H headers, out bool accept); + {"filter"_cs, {"*hdr"_cs, "*accept"_cs}}}); } // namespace P4Tools::P4Testgen::EBPF diff --git a/backends/p4tools/modules/testgen/targets/ebpf/test_backend.cpp b/backends/p4tools/modules/testgen/targets/ebpf/test_backend.cpp index 0dc5f96a52..6ae78c55f4 100644 --- a/backends/p4tools/modules/testgen/targets/ebpf/test_backend.cpp +++ b/backends/p4tools/modules/testgen/targets/ebpf/test_backend.cpp @@ -92,14 +92,14 @@ const TestSpec *EBPFTestBackend::createTestSpec(const ExecutionState *executionS } testSpec = new TestSpec(ingressPacket, egressPacket, testInfo.programTraces); // We retrieve the individual table configurations from the execution state. - const auto uninterpretedTableConfigs = executionState->getTestObjectCategory("tableconfigs"); + const auto uninterpretedTableConfigs = executionState->getTestObjectCategory("tableconfigs"_cs); // Since these configurations are uninterpreted we need to convert them. We launch a // helper function to solve the variables involved in each table configuration. for (const auto &tablePair : uninterpretedTableConfigs) { const auto tableName = tablePair.first; const auto *uninterpretedTableConfig = tablePair.second->checkedTo(); const auto *const tableConfig = uninterpretedTableConfig->evaluate(*finalModel, true); - testSpec->addTestObject("tables", tableName, tableConfig); + testSpec->addTestObject("tables"_cs, tableName, tableConfig); } return testSpec; } diff --git a/backends/p4tools/modules/testgen/targets/pna/backend/metadata/metadata.cpp b/backends/p4tools/modules/testgen/targets/pna/backend/metadata/metadata.cpp index 7f8b5cce2c..250c7c5669 100644 --- a/backends/p4tools/modules/testgen/targets/pna/backend/metadata/metadata.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/backend/metadata/metadata.cpp @@ -158,7 +158,7 @@ void Metadata::emitTestcase(const TestSpec *testSpec, cstring selectedBranches, dataJson["coverage"] = coverageStr.str(); dataJson["metadata_fields"] = inja::json::array(); const auto *metadataCollection = - testSpec->getTestObject("metadata_collection", "metadata_collection", true) + testSpec->getTestObject("metadata_collection"_cs, "metadata_collection"_cs, true) ->checkedTo(); auto offset = 0; for (auto const &metadataField : metadataCollection->getMetadataFields()) { diff --git a/backends/p4tools/modules/testgen/targets/pna/backend/ptf/ptf.cpp b/backends/p4tools/modules/testgen/targets/pna/backend/ptf/ptf.cpp index 685da61bda..8b1cb98b46 100644 --- a/backends/p4tools/modules/testgen/targets/pna/backend/ptf/ptf.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/backend/ptf/ptf.cpp @@ -58,7 +58,7 @@ inja::json PTF::getControlPlane(const TestSpec *testSpec) { // Map of actionProfiles and actionSelectors for easy reference. std::map apAsMap; - auto tables = testSpec->getTestObjectCategory("tables"); + auto tables = testSpec->getTestObjectCategory("tables"_cs); if (!tables.empty()) { controlPlaneJson["tables"] = inja::json::array(); } diff --git a/backends/p4tools/modules/testgen/targets/pna/constants.cpp b/backends/p4tools/modules/testgen/targets/pna/constants.cpp index 36786f893b..76cde9f0a2 100644 --- a/backends/p4tools/modules/testgen/targets/pna/constants.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/constants.cpp @@ -5,6 +5,8 @@ namespace P4Tools::P4Testgen::Pna { +using namespace P4::literals; + const IR::Member PnaConstants::DROP_VAR = IR::Member(IR::Type_Boolean::get(), new IR::PathExpression("*pna_internal"), "drop_var"); const IR::Member PnaConstants::OUTPUT_PORT_VAR = @@ -14,6 +16,6 @@ const IR::Member PnaConstants::PARSER_ERROR = // TODO: Make this a proper variables variable. // We can not use the utilities because of an issue related to the garbage collector. const IR::SymbolicVariable PnaSymbolicVars::DIRECTION = - IR::SymbolicVariable(IR::Type_Bits::get(32), "direction"); + IR::SymbolicVariable(IR::Type_Bits::get(32), "direction"_cs); } // namespace P4Tools::P4Testgen::Pna diff --git a/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.cpp b/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.cpp index 0560e38eda..b5c486b34f 100644 --- a/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.cpp @@ -20,6 +20,8 @@ namespace P4Tools::P4Testgen::Pna { +using namespace P4::literals; + PnaDpdkProgramInfo::PnaDpdkProgramInfo( const TestgenCompilerResult &compilerResult, ordered_map inputBlocks) @@ -111,33 +113,34 @@ std::vector PnaDpdkProgramInfo::processDeclaration( } const ArchSpec PnaDpdkProgramInfo::ARCH_SPEC = ArchSpec( - "PNA_NIC", { - // parser MainParserT( - // packet_in pkt, - // //in PM pre_user_meta, - // out MH main_hdr, - // inout MM main_user_meta, - // in pna_main_parser_input_metadata_t istd); - {"MainParserT", {nullptr, "*main_hdr", "*main_user_meta", "*parser_istd"}}, - // control PreControlT( - // in PH pre_hdr, - // inout PM pre_user_meta, - // in pna_pre_input_metadata_t istd, - // inout pna_pre_output_metadata_t ostd); - {"PreControlT", {"*main_hdr", "*main_user_meta", "*pre_istd", "*pre_ostd"}}, - // control MainControlT( - // //in PM pre_user_meta, - // inout MH main_hdr, - // inout MM main_user_meta, - // in pna_main_input_metadata_t istd, - // inout pna_main_output_metadata_t ostd); - {"MainControlT", {"*main_hdr", "*main_user_meta", "*main_istd", "*ostd"}}, - // control MainDeparserT( - // packet_out pkt, - // in MH main_hdr, - // in MM main_user_meta, - // in pna_main_output_metadata_t ostd); - {"MainDeparserT", {nullptr, "*main_hdr", "*main_user_meta", "*ostd"}}, - }); + "PNA_NIC"_cs, + { + // parser MainParserT( + // packet_in pkt, + // //in PM pre_user_meta, + // out MH main_hdr, + // inout MM main_user_meta, + // in pna_main_parser_input_metadata_t istd); + {"MainParserT"_cs, {nullptr, "*main_hdr"_cs, "*main_user_meta"_cs, "*parser_istd"_cs}}, + // control PreControlT( + // in PH pre_hdr, + // inout PM pre_user_meta, + // in pna_pre_input_metadata_t istd, + // inout pna_pre_output_metadata_t ostd); + {"PreControlT"_cs, {"*main_hdr"_cs, "*main_user_meta"_cs, "*pre_istd"_cs, "*pre_ostd"_cs}}, + // control MainControlT( + // //in PM pre_user_meta, + // inout MH main_hdr, + // inout MM main_user_meta, + // in pna_main_input_metadata_t istd, + // inout pna_main_output_metadata_t ostd); + {"MainControlT"_cs, {"*main_hdr"_cs, "*main_user_meta"_cs, "*main_istd"_cs, "*ostd"_cs}}, + // control MainDeparserT( + // packet_out pkt, + // in MH main_hdr, + // in MM main_user_meta, + // in pna_main_output_metadata_t ostd); + {"MainDeparserT"_cs, {nullptr, "*main_hdr"_cs, "*main_user_meta"_cs, "*ostd"_cs}}, + }); } // namespace P4Tools::P4Testgen::Pna diff --git a/backends/p4tools/modules/testgen/targets/pna/shared_expr_stepper.cpp b/backends/p4tools/modules/testgen/targets/pna/shared_expr_stepper.cpp index 1edfccca12..fc898c346b 100644 --- a/backends/p4tools/modules/testgen/targets/pna/shared_expr_stepper.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/shared_expr_stepper.cpp @@ -37,7 +37,7 @@ const ExternMethodImpls SharedPnaExprStepper::PNA_EXTERN_METHOD_IMPLS({ * drop_packet * drop_packet sets the PNA internal drop variable to true. * ====================================================================================== */ - {"*method.drop_packet", + {"*method.drop_packet"_cs, {}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, @@ -46,7 +46,7 @@ const ExternMethodImpls SharedPnaExprStepper::PNA_EXTERN_METHOD_IMPLS({ // Use an assignment to set drop variable to true. // This variable will be processed in the deparser. nextState.set(&PnaConstants::DROP_VAR, IR::BoolLiteral::get(true)); - nextState.add(*new TraceEvents::Generic("drop_packet executed")); + nextState.add(*new TraceEvents::Generic("drop_packet executed"_cs)); nextState.popBody(); result->emplace_back(nextState); }}, @@ -55,8 +55,8 @@ const ExternMethodImpls SharedPnaExprStepper::PNA_EXTERN_METHOD_IMPLS({ * send_to_port sets the PNA internal egress port variable to true. * ====================================================================================== */ // TODO: Implement extern path expression calls. - {"*method.send_to_port", - {"dest_port"}, + {"*method.send_to_port"_cs, + {"dest_port"_cs}, [](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -79,7 +79,7 @@ const ExternMethodImpls SharedPnaExprStepper::PNA_EXTERN_METHOD_IMPLS({ } // Use an assignment to set the output port to the input. nextState.set(&PnaConstants::OUTPUT_PORT_VAR, destPort); - nextState.add(*new TraceEvents::Generic("send_to_port executed")); + nextState.add(*new TraceEvents::Generic("send_to_port executed"_cs)); nextState.popBody(); result->emplace_back(nextState); }}, @@ -106,8 +106,8 @@ const ExternMethodImpls SharedPnaExprStepper::PNA_EXTERN_METHOD_IMPLS({ * } * } * ====================================================================================== */ - {"*method.SelectByDirection", - {"direction", "n2h_value", "h2n_value"}, + {"*method.SelectByDirection"_cs, + {"direction"_cs, "n2h_value"_cs, "h2n_value"_cs}, [](const IR::MethodCallExpression *call, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector *args, const ExecutionState &state, SmallStepEvaluator::Result &result) { @@ -161,13 +161,13 @@ const ExternMethodImpls SharedPnaExprStepper::PNA_EXTERN_METHOD_IMPLS({ * ====================================================================================== */ // TODO: Currently, this is a no-op. This is because we only test a single packet input. // Implement a way to test add_entry. - {"*method.add_entry", - {"action_name", "action_params", "expire_time_profile_id"}, + {"*method.add_entry"_cs, + {"action_name"_cs, "action_params"_cs, "expire_time_profile_id"_cs}, [](const IR::MethodCallExpression * /*call*/, const IR::Expression * /*receiver*/, IR::ID & /*methodName*/, const IR::Vector * /*args*/, const ExecutionState &state, SmallStepEvaluator::Result &result) { auto &nextState = state.clone(); - nextState.add(*new TraceEvents::Generic("add_entry executed. Currently a no-op.")); + nextState.add(*new TraceEvents::Generic("add_entry executed. Currently a no-op."_cs)); nextState.replaceTopBody(Continuation::Return(IR::BoolLiteral::get(true))); result->emplace_back(nextState); }}, diff --git a/backends/p4tools/modules/testgen/targets/pna/shared_table_stepper.cpp b/backends/p4tools/modules/testgen/targets/pna/shared_table_stepper.cpp index 22185b06a2..57f3d7a300 100644 --- a/backends/p4tools/modules/testgen/targets/pna/shared_table_stepper.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/shared_table_stepper.cpp @@ -32,6 +32,8 @@ namespace P4Tools::P4Testgen::Pna { +using namespace P4::literals; + const IR::Expression *SharedPnaTableStepper::computeTargetMatchType( const TableUtils::KeyProperties &keyProperties, TableMatchMap *matches, const IR::Expression *hitCondition) { @@ -119,7 +121,7 @@ void SharedPnaTableStepper::evalTableActionProfile( // TODO: Should we check if we exceed the maximum number of possible profile entries? actionProfile->addToActionMap(actionName, ctrlPlaneArgs); // Update the action profile in the execution state. - nextState.addTestObject("action_profile", actionProfile->getObjectName(), actionProfile); + nextState.addTestObject("action_profile"_cs, actionProfile->getObjectName(), actionProfile); // We add the arguments to our action call, effectively creating a const entry call. auto *synthesizedAction = tableAction->clone(); @@ -133,8 +135,8 @@ void SharedPnaTableStepper::evalTableActionProfile( // Add the action profile to the table. // This implies a slightly different implementation to usual control plane table behavior. - tableConfig->addTableProperty("action_profile", actionProfile); - nextState.addTestObject("tableconfigs", table->controlPlaneName(), tableConfig); + tableConfig->addTableProperty("action_profile"_cs, actionProfile); + nextState.addTestObject("tableconfigs"_cs, table->controlPlaneName(), tableConfig); // Update all the tracking variables for tables. std::vector replacements; @@ -202,9 +204,10 @@ void SharedPnaTableStepper::evalTableActionSelector( SharedPnaProperties.actionSelector->getSelectorDecl(), actionProfile); // Update the action profile in the execution state. - nextState.addTestObject("action_profile", actionProfile->getObjectName(), actionProfile); + nextState.addTestObject("action_profile"_cs, actionProfile->getObjectName(), actionProfile); // Update the action selector in the execution state. - nextState.addTestObject("action_selector", actionSelector->getObjectName(), actionSelector); + nextState.addTestObject("action_selector"_cs, actionSelector->getObjectName(), + actionSelector); // We add the arguments to our action call, effectively creating a const entry call. auto *synthesizedAction = tableAction->clone(); @@ -217,11 +220,11 @@ void SharedPnaTableStepper::evalTableActionSelector( auto *tableConfig = new TableConfig(table, {tableRule}); // Add the action profile to the table. This signifies a slightly different implementation. - tableConfig->addTableProperty("action_profile", actionProfile); + tableConfig->addTableProperty("action_profile"_cs, actionProfile); // Add the action selector to the table. This signifies a slightly different implementation. - tableConfig->addTableProperty("action_selector", actionSelector); + tableConfig->addTableProperty("action_selector"_cs, actionSelector); - nextState.addTestObject("tableconfigs", table->controlPlaneName(), tableConfig); + nextState.addTestObject("tableconfigs"_cs, table->controlPlaneName(), tableConfig); // Update all the tracking variables for tables. std::vector replacements; @@ -248,7 +251,7 @@ void SharedPnaTableStepper::evalTableActionSelector( } bool SharedPnaTableStepper::checkForActionProfile() { - const auto *impl = table->properties->getProperty("implementation"); + const auto *impl = table->properties->getProperty("implementation"_cs); if (impl == nullptr) { return false; } @@ -276,7 +279,7 @@ bool SharedPnaTableStepper::checkForActionProfile() { } const auto *testObject = - state->getTestObject("action_profile", implExtern->controlPlaneName(), false); + state->getTestObject("action_profile"_cs, implExtern->controlPlaneName(), false); if (testObject == nullptr) { // This means, for every possible control plane entry (and with that, new execution state) // add the generated action profile. @@ -290,7 +293,7 @@ bool SharedPnaTableStepper::checkForActionProfile() { } bool SharedPnaTableStepper::checkForActionSelector() { - const auto *impl = table->properties->getProperty("implementation"); + const auto *impl = table->properties->getProperty("implementation"_cs); if (impl == nullptr) { return false; } @@ -319,7 +322,7 @@ bool SharedPnaTableStepper::checkForActionSelector() { // Treat action selectors like action profiles for now. // The behavioral model P4Runtime is unclear how to configure action selectors. const auto *testObject = - state->getTestObject("action_profile", selectorExtern->controlPlaneName(), false); + state->getTestObject("action_profile"_cs, selectorExtern->controlPlaneName(), false); if (testObject == nullptr) { // This means, for every possible control plane entry (and with that, new execution state) // add the generated action profile. diff --git a/backends/p4tools/modules/testgen/targets/pna/test_backend.cpp b/backends/p4tools/modules/testgen/targets/pna/test_backend.cpp index 587d2ad3df..b138efdc57 100644 --- a/backends/p4tools/modules/testgen/targets/pna/test_backend.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/test_backend.cpp @@ -84,7 +84,7 @@ const TestSpec *PnaTestBackend::createTestSpec(const ExecutionState *executionSt if (TestgenOptions::get().testBackend == "METADATA") { auto *metadataCollection = new MetadataCollection(); const auto *pnaProgInfo = getProgramInfo().checkedTo(); - const auto *localMetadataVar = pnaProgInfo->getBlockParam("MainParserT", 2); + const auto *localMetadataVar = pnaProgInfo->getBlockParam("MainParserT"_cs, 2); const auto &flatFields = executionState->getFlatFields(localMetadataVar, {}); for (const auto &fieldRef : flatFields) { const auto *fieldVal = finalModel->evaluate(executionState->get(fieldRef), true); @@ -94,35 +94,36 @@ const TestSpec *PnaTestBackend::createTestSpec(const ExecutionState *executionSt fieldString = fieldString.substr(fieldString.find('.') - fieldString.begin() + 1); metadataCollection->addMetaDataField(fieldString, fieldVal); } - testSpec->addTestObject("metadata_collection", "metadata_collection", metadataCollection); + testSpec->addTestObject("metadata_collection"_cs, "metadata_collection"_cs, + metadataCollection); return testSpec; } // We retrieve the individual table configurations from the execution state. - const auto uninterpretedTableConfigs = executionState->getTestObjectCategory("tableconfigs"); + const auto uninterpretedTableConfigs = executionState->getTestObjectCategory("tableconfigs"_cs); // Since these configurations are uninterpreted we need to convert them. We launch a // helper function to solve the variables involved in each table configuration. for (const auto &tablePair : uninterpretedTableConfigs) { const auto tableName = tablePair.first; const auto *uninterpretedTableConfig = tablePair.second->checkedTo(); const auto *const tableConfig = uninterpretedTableConfig->evaluate(*finalModel, true); - testSpec->addTestObject("tables", tableName, tableConfig); + testSpec->addTestObject("tables"_cs, tableName, tableConfig); } - const auto actionProfiles = executionState->getTestObjectCategory("action_profile"); + const auto actionProfiles = executionState->getTestObjectCategory("action_profile"_cs); for (const auto &testObject : actionProfiles) { const auto profileName = testObject.first; const auto *actionProfile = testObject.second->checkedTo(); const auto *evaluatedProfile = actionProfile->evaluate(*finalModel, true); - testSpec->addTestObject("action_profiles", profileName, evaluatedProfile); + testSpec->addTestObject("action_profiles"_cs, profileName, evaluatedProfile); } - const auto actionSelectors = executionState->getTestObjectCategory("action_selector"); + const auto actionSelectors = executionState->getTestObjectCategory("action_selector"_cs); for (const auto &testObject : actionSelectors) { const auto selectorName = testObject.first; const auto *actionSelector = testObject.second->checkedTo(); const auto *evaluatedSelector = actionSelector->evaluate(*finalModel, true); - testSpec->addTestObject("action_selectors", selectorName, evaluatedSelector); + testSpec->addTestObject("action_selectors"_cs, selectorName, evaluatedSelector); } return testSpec; diff --git a/backends/p4tools/modules/testgen/targets/pna/test_spec.cpp b/backends/p4tools/modules/testgen/targets/pna/test_spec.cpp index aceaa180a0..e241ee98c4 100644 --- a/backends/p4tools/modules/testgen/targets/pna/test_spec.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/test_spec.cpp @@ -7,6 +7,8 @@ namespace P4Tools::P4Testgen::Pna { +using namespace P4::literals; + /* ========================================================================================= * PnaDpdkRegister * ========================================================================================= */ @@ -20,7 +22,7 @@ void PnaDpdkRegisterValue::addRegisterCondition(PnaDpdkRegisterCondition cond) { const IR::Expression *PnaDpdkRegisterValue::getInitialValue() const { return initialValue; } -cstring PnaDpdkRegisterValue::getObjectName() const { return "PnaDpdkRegisterValue"; } +cstring PnaDpdkRegisterValue::getObjectName() const { return "PnaDpdkRegisterValue"_cs; } const IR::Expression *PnaDpdkRegisterValue::getCurrentValue(const IR::Expression *index) const { const IR::Expression *baseExpr = initialValue; @@ -76,7 +78,7 @@ const PnaDpdkRegisterCondition *PnaDpdkRegisterCondition::evaluate(const Model & return new PnaDpdkRegisterCondition(evaluatedIndex, evaluatedValue); } -cstring PnaDpdkRegisterCondition::getObjectName() const { return "PnaDpdkRegisterCondition"; } +cstring PnaDpdkRegisterCondition::getObjectName() const { return "PnaDpdkRegisterCondition"_cs; } /* ========================================================================================= * PnaDpdkActionProfile @@ -122,7 +124,7 @@ PnaDpdkActionSelector::PnaDpdkActionSelector(const IR::IDeclaration *selectorDec const PnaDpdkActionProfile *actionProfile) : selectorDecl(selectorDecl), actionProfile(actionProfile) {} -cstring PnaDpdkActionSelector::getObjectName() const { return "PnaDpdkActionSelector"; } +cstring PnaDpdkActionSelector::getObjectName() const { return "PnaDpdkActionSelector"_cs; } const IR::IDeclaration *PnaDpdkActionSelector::getSelectorDecl() const { return selectorDecl; } @@ -157,7 +159,7 @@ const Optional *Optional::evaluate(const Model &model, bool doComplete) const { return new Optional(getKey(), evaluatedValue, addMatch); } -cstring Optional::getObjectName() const { return "Optional"; } +cstring Optional::getObjectName() const { return "Optional"_cs; } bool Optional::addAsExactMatch() const { return addMatch; } @@ -194,7 +196,7 @@ const Range *Range::evaluate(const Model &model, bool doComplete) const { MetadataCollection::MetadataCollection() = default; -cstring MetadataCollection::getObjectName() const { return "MetadataCollection"; } +cstring MetadataCollection::getObjectName() const { return "MetadataCollection"_cs; } const MetadataCollection *MetadataCollection::evaluate(const Model & /*model*/, bool /*finalModel*/) const { @@ -213,6 +215,6 @@ void MetadataCollection::addMetaDataField(cstring name, const IR::Literal *metad metadataFields[name] = metadataField; } -cstring Range::getObjectName() const { return "Range"; } +cstring Range::getObjectName() const { return "Range"_cs; } } // namespace P4Tools::P4Testgen::Pna diff --git a/backends/p4tools/modules/testgen/test/small-step/util.h b/backends/p4tools/modules/testgen/test/small-step/util.h index 5f985aab50..673c14cf5e 100644 --- a/backends/p4tools/modules/testgen/test/small-step/util.h +++ b/backends/p4tools/modules/testgen/test/small-step/util.h @@ -46,6 +46,8 @@ class SmallStepTest : public P4ToolsTest { namespace SmallStepUtil { +using namespace P4::literals; + /// Creates a test case with the given header fields for /// stepping on a given expression. std::optional createSmallStepExprTest(const std::string &, @@ -55,7 +57,7 @@ std::optional createSmallStepExprTest(const std::string & template const T *extractExpr(const IR::P4Program &program) { // Get the mau declarations in the P4Program. - auto *decl = program.getDeclsByName("mau")->single(); + auto *decl = program.getDeclsByName("mau"_cs)->single(); // Convert the mau declaration to a control and ensure that // there is a single statement in the body. @@ -86,7 +88,7 @@ void stepAndExamineValue(const T *value, const P4Tools::CompilerResult &compiler ASSERT_TRUE(progInfo); // Create a base state with a parameter continuation to apply the value on. - const auto *v = Continuation::genParameter(value->type, "v", NamespaceContext::Empty); + const auto *v = Continuation::genParameter(value->type, "v"_cs, NamespaceContext::Empty); Body bodyBase({Return(v->param)}); Continuation continuationBase(v, bodyBase); ExecutionState esBase = SmallStepTest::mkState(bodyBase); diff --git a/backends/p4tools/modules/testgen/test/z3-solver/constraints.cpp b/backends/p4tools/modules/testgen/test/z3-solver/constraints.cpp index 937600d849..8496172cdd 100644 --- a/backends/p4tools/modules/testgen/test/z3-solver/constraints.cpp +++ b/backends/p4tools/modules/testgen/test/z3-solver/constraints.cpp @@ -10,6 +10,7 @@ #include "lib/cstring.h" namespace Test { +using namespace P4::literals; using ConstraintVector = const std::vector; class Z3SolverSatisfiabilityChecks : public ::testing::Test { @@ -26,8 +27,8 @@ class Z3SolverSatisfiabilityChecks : public ::testing::Test { TEST_F(Z3SolverSatisfiabilityChecks, BitVectors) { const auto *eightBitType = IR::Type_Bits::get(8); - const auto *fooVar = P4Tools::ToolsVariables::getSymbolicVariable(eightBitType, "foo"); - const auto *barVar = P4Tools::ToolsVariables::getSymbolicVariable(eightBitType, "bar"); + const auto *fooVar = P4Tools::ToolsVariables::getSymbolicVariable(eightBitType, "foo"_cs); + const auto *barVar = P4Tools::ToolsVariables::getSymbolicVariable(eightBitType, "bar"_cs); { auto *expression = new IR::Equ(IR::Constant::get(eightBitType, 1), IR::Constant::get(eightBitType, 1)); @@ -81,54 +82,54 @@ TEST_F(Z3SolverSatisfiabilityChecks, BitVectors) { TEST_F(Z3SolverSatisfiabilityChecks, Strings) { const auto *stringType = IR::Type_String::get(); - const auto *fooVar = P4Tools::ToolsVariables::getSymbolicVariable(stringType, "foo"); - const auto *barVar = P4Tools::ToolsVariables::getSymbolicVariable(stringType, "bar"); + const auto *fooVar = P4Tools::ToolsVariables::getSymbolicVariable(stringType, "foo"_cs); + const auto *barVar = P4Tools::ToolsVariables::getSymbolicVariable(stringType, "bar"_cs); { auto *expression = - new IR::Equ(IR::StringLiteral::get("dead"), IR::StringLiteral::get("dead")); + new IR::Equ(IR::StringLiteral::get("dead"_cs), IR::StringLiteral::get("dead"_cs)); ConstraintVector inputExpression = {expression}; testCheckSat(inputExpression, true); } { auto *expression = - new IR::Equ(IR::StringLiteral::get("dead"), IR::StringLiteral::get("beef")); + new IR::Equ(IR::StringLiteral::get("dead"_cs), IR::StringLiteral::get("beef"_cs)); ConstraintVector inputExpression = {expression}; testCheckSat(inputExpression, false); } { - auto *expression = new IR::Equ(fooVar, IR::StringLiteral::get("dead")); + auto *expression = new IR::Equ(fooVar, IR::StringLiteral::get("dead"_cs)); ConstraintVector inputExpression = {expression}; testCheckSat(inputExpression, true); } { - auto *expression = new IR::Equ(fooVar, IR::StringLiteral::get("dead")); - auto *constraint1 = new IR::Equ(fooVar, IR::StringLiteral::get("dead")); + auto *expression = new IR::Equ(fooVar, IR::StringLiteral::get("dead"_cs)); + auto *constraint1 = new IR::Equ(fooVar, IR::StringLiteral::get("dead"_cs)); ConstraintVector inputExpression = {expression, constraint1}; testCheckSat(inputExpression, true); } { auto *expression = new IR::Equ(fooVar, barVar); - auto *constraint1 = new IR::Equ(fooVar, IR::StringLiteral::get("dead")); + auto *constraint1 = new IR::Equ(fooVar, IR::StringLiteral::get("dead"_cs)); ConstraintVector inputExpression = {expression, constraint1}; testCheckSat(inputExpression, true); } { auto *expression = new IR::Equ(fooVar, barVar); - auto *constraint1 = new IR::Equ(fooVar, IR::StringLiteral::get("dead")); - auto *constraint2 = new IR::Equ(barVar, IR::StringLiteral::get("dead")); + auto *constraint1 = new IR::Equ(fooVar, IR::StringLiteral::get("dead"_cs)); + auto *constraint2 = new IR::Equ(barVar, IR::StringLiteral::get("dead"_cs)); ConstraintVector inputExpression = {expression, constraint1, constraint2}; testCheckSat(inputExpression, true); } { - auto *expression = new IR::Equ(fooVar, IR::StringLiteral::get("dead")); - auto *constraint1 = new IR::Equ(fooVar, IR::StringLiteral::get("beef")); + auto *expression = new IR::Equ(fooVar, IR::StringLiteral::get("dead"_cs)); + auto *constraint1 = new IR::Equ(fooVar, IR::StringLiteral::get("beef"_cs)); ConstraintVector inputExpression = {expression, constraint1}; testCheckSat(inputExpression, false); } { auto *expression = new IR::Equ(fooVar, barVar); - auto *constraint1 = new IR::Equ(fooVar, IR::StringLiteral::get("dead")); - auto *constraint2 = new IR::Equ(barVar, IR::StringLiteral::get("beef")); + auto *constraint1 = new IR::Equ(fooVar, IR::StringLiteral::get("dead"_cs)); + auto *constraint2 = new IR::Equ(barVar, IR::StringLiteral::get("beef"_cs)); ConstraintVector inputExpression = {expression, constraint1, constraint2}; testCheckSat(inputExpression, false); } @@ -136,8 +137,8 @@ TEST_F(Z3SolverSatisfiabilityChecks, Strings) { TEST_F(Z3SolverSatisfiabilityChecks, Bools) { const auto *boolType = IR::Type_Boolean::get(); - const auto *fooVar = P4Tools::ToolsVariables::getSymbolicVariable(boolType, "foo"); - const auto *barVar = P4Tools::ToolsVariables::getSymbolicVariable(boolType, "bar"); + const auto *fooVar = P4Tools::ToolsVariables::getSymbolicVariable(boolType, "foo"_cs); + const auto *barVar = P4Tools::ToolsVariables::getSymbolicVariable(boolType, "bar"_cs); { auto *expression = new IR::Equ(IR::BoolLiteral::get(true), IR::BoolLiteral::get(true)); ConstraintVector inputExpression = {expression}; diff --git a/backends/p4tools/modules/testgen/testgen.cpp b/backends/p4tools/modules/testgen/testgen.cpp index e825727bf8..4dc92b80f7 100644 --- a/backends/p4tools/modules/testgen/testgen.cpp +++ b/backends/p4tools/modules/testgen/testgen.cpp @@ -124,8 +124,8 @@ int generateAndWriteAbstractTests(const TestgenOptions &testgenOptions, } // The test name is the stem of the output base path. - TestBackendConfiguration testBackendConfiguration{testPath.c_str(), testgenOptions.maxTests, - testPath, testgenOptions.seed}; + TestBackendConfiguration testBackendConfiguration{ + cstring(testPath.c_str()), testgenOptions.maxTests, testPath, testgenOptions.seed}; // Need to declare the solver here to ensure its lifetime. Z3Solver solver; diff --git a/backends/p4tools/p4tools.def b/backends/p4tools/p4tools.def index 56721564f2..44d55d1db6 100644 --- a/backends/p4tools/p4tools.def +++ b/backends/p4tools/p4tools.def @@ -173,11 +173,11 @@ class Extracted_Varbits : Type_Bits { return size == a.size; } - cstring baseName() const { return "SizedVarbit"; } + cstring baseName() const { return "SizedVarbit"_cs; } toString { - return baseName() + "<" + Util::toString(size) + ">" + "<" + Util::toString(assignedSize) + - ">"; + return baseName() + "<"_cs + Util::toString(size) + ">"_cs + "<"_cs + Util::toString(assignedSize) + + ">"_cs; } dbprint { out << toString(); } @@ -209,11 +209,11 @@ public: optional inline IndexedVector associatedNodes; /// The name of the concolic method that this variable targets. - inline cstring concolicMethodName = ""; + inline cstring concolicMethodName = cstring::empty; toString { - cstring argumentStr = ""; - cstring sep = ""; + std::string argumentStr = ""; + std::string sep = ""; for (const auto *arg : *arguments) { argumentStr += sep + arg->toString(); sep = ", "; @@ -290,7 +290,7 @@ class InOutReference : Expression { Expression(ref.type), ref(ref), resolvedRef(resolvedRef) { validate(); } - toString { return ref->toString() + "(" + resolvedRef->toString() + ")"; } + toString { return ref->toString() + "("_cs + resolvedRef->toString() + ")"_cs; } dbprint { out << ref << "(" << resolvedRef << ")"; } } diff --git a/backends/tc/backend.cpp b/backends/tc/backend.cpp index 662f3eae0f..8b8ac1dfef 100644 --- a/backends/tc/backend.cpp +++ b/backends/tc/backend.cpp @@ -23,19 +23,22 @@ and limitations under the License. namespace TC { -const cstring Extern::dropPacket = "drop_packet"; -const cstring Extern::sendToPort = "send_to_port"; +using namespace P4::literals; -cstring pnaMainParserInputMetaFields[TC::MAX_PNA_PARSER_META] = {"recirculated", "input_port"}; +const cstring Extern::dropPacket = "drop_packet"_cs; +const cstring Extern::sendToPort = "send_to_port"_cs; + +cstring pnaMainParserInputMetaFields[TC::MAX_PNA_PARSER_META] = {"recirculated"_cs, + "input_port"_cs}; cstring pnaMainInputMetaFields[TC::MAX_PNA_INPUT_META] = { - "recirculated", "timestamp", "parser_error", "class_of_service", "input_port"}; + "recirculated"_cs, "timestamp"_cs, "parser_error"_cs, "class_of_service"_cs, "input_port"_cs}; -cstring pnaMainOutputMetaFields[TC::MAX_PNA_OUTPUT_META] = {"class_of_service"}; +cstring pnaMainOutputMetaFields[TC::MAX_PNA_OUTPUT_META] = {"class_of_service"_cs}; -const cstring pnaParserMeta = "pna_main_parser_input_metadata_t"; -const cstring pnaInputMeta = "pna_main_input_metadata_t"; -const cstring pnaOutputMeta = "pna_main_output_metadata_t"; +const cstring pnaParserMeta = "pna_main_parser_input_metadata_t"_cs; +const cstring pnaInputMeta = "pna_main_input_metadata_t"_cs; +const cstring pnaOutputMeta = "pna_main_output_metadata_t"_cs; bool Backend::process() { CHECK_NULL(toplevel); @@ -188,11 +191,11 @@ void ConvertToBackendIR::setPipelineName() { } auto fileName = path.findlast('/'); if (fileName) { - pipelineName = fileName; - pipelineName = pipelineName.replace("/", ""); + pipelineName = cstring(fileName); + pipelineName = pipelineName.replace("/"_cs, ""_cs); } - auto fileext = pipelineName.find("."); - pipelineName = pipelineName.replace(fileext, ""); + auto fileext = cstring(pipelineName.find(".")); + pipelineName = pipelineName.replace(fileext, ""_cs); pipelineName = pipelineName.trim(); } @@ -222,8 +225,8 @@ void ConvertToBackendIR::postorder(const IR::P4Action *action) { if (isDuplicateAction(action)) return; auto actionName = externalName(action); if (actionName == P4::P4CoreLibrary::instance().noAction.name) { - tcPipeline->addNoActionDefinition(new IR::TCAction("NoAction")); - actions.emplace("NoAction", action); + tcPipeline->addNoActionDefinition(new IR::TCAction("NoAction"_cs)); + actions.emplace("NoAction"_cs, action); return; } actions.emplace(actionName, action); @@ -314,14 +317,14 @@ void ConvertToBackendIR::updateConstEntries(const IR::P4Table *t, IR::TCTable *t auto keyString = keyElement->expression->toString(); auto annotations = keyElement->getAnnotations(); if (annotations) { - if (auto anno = annotations->getSingle("name")) { + if (auto anno = annotations->getSingle("name"_cs)) { keyString = anno->expr.at(0)->to()->value; } } auto keySetElement = keyset->components.at(itr); auto key = keySetElement->toString(); if (keySetElement->is()) { - key = "default"; + key = "default"_cs; } else if (keySetElement->is()) { big_int kValue = keySetElement->to()->value; int kBase = keySetElement->to()->base; @@ -348,7 +351,7 @@ void ConvertToBackendIR::updateConstEntries(const IR::P4Table *t, IR::TCTable *t buf.push_front(Util::DigitToChar(digit)); } while (kValue > 0); for (auto ch : buf) value << ch; - key = value.str().c_str(); + key = value.str(); } else if (keySetElement->is()) { auto left = keySetElement->to()->left; auto right = keySetElement->to()->right; @@ -575,7 +578,7 @@ void ConvertToBackendIR::updateAddOnMissTable(const IR::P4Table *t) { } } -unsigned ConvertToBackendIR::GetAccessNumericValue(cstring access) { +unsigned ConvertToBackendIR::GetAccessNumericValue(std::string_view access) { unsigned value = 0; for (auto s : access) { unsigned mask = 0; @@ -626,12 +629,12 @@ cstring ConvertToBackendIR::HandleTableAccessPermission(const IR::P4Table *t) { } // Default access value of Control_path and Data_Path if (control_path.isNullOrEmpty()) { - control_path = IsTableAddOnMiss ? DEFAULT_ADD_ON_MISS_TABLE_CONTROL_PATH_ACCESS - : DEFAULT_TABLE_CONTROL_PATH_ACCESS; + control_path = cstring(IsTableAddOnMiss ? DEFAULT_ADD_ON_MISS_TABLE_CONTROL_PATH_ACCESS + : DEFAULT_TABLE_CONTROL_PATH_ACCESS); } if (data_path.isNullOrEmpty()) { - data_path = IsTableAddOnMiss ? DEFAULT_ADD_ON_MISS_TABLE_DATA_PATH_ACCESS - : DEFAULT_TABLE_DATA_PATH_ACCESS; + data_path = cstring(IsTableAddOnMiss ? DEFAULT_ADD_ON_MISS_TABLE_DATA_PATH_ACCESS + : DEFAULT_TABLE_DATA_PATH_ACCESS); } if (IsTableAddOnMiss) { @@ -643,12 +646,13 @@ cstring ConvertToBackendIR::HandleTableAccessPermission(const IR::P4Table *t) { t->name.originalName); } } - auto access_cp = GetAccessNumericValue(control_path); - auto access_dp = GetAccessNumericValue(data_path); + // FIXME: refactor not to require cstring + auto access_cp = GetAccessNumericValue(control_path.string_view()); + auto access_dp = GetAccessNumericValue(data_path.string_view()); auto access_permisson = (access_cp << 7) | access_dp; std::stringstream value; value << "0x" << std::hex << access_permisson; - return value.str().c_str(); + return value.str(); } std::pair *ConvertToBackendIR::GetAnnotatedAccessPath( @@ -771,17 +775,17 @@ cstring ConvertToBackendIR::processExternPermission(const IR::Type_Extern *ext) } // Default access value of Control_path and Data_Path if (control_path.isNullOrEmpty()) { - control_path = DEFAULT_EXTERN_CONTROL_PATH_ACCESS; + control_path = cstring(DEFAULT_EXTERN_CONTROL_PATH_ACCESS); } if (data_path.isNullOrEmpty()) { - data_path = DEFAULT_EXTERN_DATA_PATH_ACCESS; + data_path = cstring(DEFAULT_EXTERN_DATA_PATH_ACCESS); } - auto access_cp = GetAccessNumericValue(control_path); - auto access_dp = GetAccessNumericValue(data_path); + auto access_cp = GetAccessNumericValue(control_path.string_view()); + auto access_dp = GetAccessNumericValue(data_path.string_view()); auto access_permisson = (access_cp << 7) | access_dp; std::stringstream value; value << "0x" << std::hex << access_permisson; - return value.str().c_str(); + return value.str(); } void ConvertToBackendIR::processExternConstructorAnnotations(const IR::Type_Extern *extn, @@ -835,7 +839,7 @@ safe_vector ConvertToBackendIR::processExternControlPath( annotation->name == ParseTCAnnotations::tc_data_scalar) { annoName = annotation->name; } else if (annotation->name == ParseTCAnnotations::tc_data) { - annoName = "param"; + annoName = "param"_cs; } /* If the field is of Type_Name example 'T' and 'T' is of Type_Struct, extract all fields of structure*/ diff --git a/backends/tc/backend.h b/backends/tc/backend.h index 09722983f0..14b4a21118 100644 --- a/backends/tc/backend.h +++ b/backends/tc/backend.h @@ -99,7 +99,7 @@ class ConvertToBackendIR : public Inspector { safe_vector processExternControlPath(const IR::Type_SpecializedCanonical *ts, const IR::Type_Extern *extn, cstring eName); - unsigned GetAccessNumericValue(cstring access); + unsigned GetAccessNumericValue(std::string_view access); bool isDuplicateAction(const IR::P4Action *action); bool isDuplicateOrNoAction(const IR::P4Action *action); void updateDefaultHitAction(const IR::P4Table *t, IR::TCTable *tdef); diff --git a/backends/tc/ebpfCodeGen.cpp b/backends/tc/ebpfCodeGen.cpp index 6b387ca42f..c6459cb15c 100644 --- a/backends/tc/ebpfCodeGen.cpp +++ b/backends/tc/ebpfCodeGen.cpp @@ -28,7 +28,7 @@ void PNAEbpfGenerator::emitPNAIncludes(EBPF::CodeBuilder *builder) const { cstring PNAEbpfGenerator::getProgramName() const { auto progName = options.file; auto filename = progName.findlast('/'); - if (filename) progName = filename; + if (filename) progName = cstring(filename); progName = progName.exceptLast(3); progName = progName.trim("/\t\n\r"); return progName; @@ -76,13 +76,13 @@ void PNAEbpfGenerator::emitGlobalHeadersMetadata(EBPF::CodeBuilder *builder) con builder->blockStart(); builder->emitIndent(); - pipeline->parser->headerType->declare(builder, "cpumap_hdr", false); + pipeline->parser->headerType->declare(builder, "cpumap_hdr"_cs, false); builder->endOfStatement(true); builder->emitIndent(); auto user_md_type = pipeline->typeMap->getType(pipeline->control->user_metadata); BUG_CHECK(user_md_type != nullptr, "cannot declare user metadata"); auto userMetadataType = EBPF::EBPFTypeFactory::instance->create(user_md_type); - userMetadataType->declare(builder, "cpumap_usermeta", false); + userMetadataType->declare(builder, "cpumap_usermeta"_cs, false); builder->endOfStatement(true); builder->emitIndent(); @@ -169,8 +169,8 @@ void PNAEbpfGenerator::emitPipelineInstances(EBPF::CodeBuilder *builder) const { pipeline->parser->emitValueSetInstances(builder); pipeline->deparser->emitDigestInstances(builder); - builder->target->emitTableDecl(builder, "hdr_md_cpumap", EBPF::TablePerCPUArray, "u32", - "struct hdr_md", 2); + builder->target->emitTableDecl(builder, "hdr_md_cpumap"_cs, EBPF::TablePerCPUArray, "u32"_cs, + "struct hdr_md"_cs, 2); } // =====================PNAArchTC============================= @@ -211,8 +211,8 @@ void PNAArchTC::emitInstances(EBPF::CodeBuilder *builder) const { builder->appendLine("REGISTER_START()"); if (options.xdp2tcMode == XDP2TC_CPUMAP) { - builder->target->emitTableDecl(builder, "xdp2tc_cpumap", EBPF::TablePerCPUArray, "u32", - "u16", 1); + builder->target->emitTableDecl(builder, "xdp2tc_cpumap"_cs, EBPF::TablePerCPUArray, + "u32"_cs, "u16"_cs, 1); } emitPipelineInstances(builder); @@ -235,9 +235,9 @@ void PNAArchTC::emitParser(EBPF::CodeBuilder *builder) const { builder->newline(); builder->appendLine("struct p4tc_filter_fields p4tc_filter_fields;"); builder->newline(); - pipeline->name = "tc-parse"; - pipeline->sectionName = "p4tc/parse"; - pipeline->functionName = pipeline->name.replace("-", "_") + "_func"; + pipeline->name = "tc-parse"_cs; + pipeline->sectionName = "p4tc/parse"_cs; + pipeline->functionName = pipeline->name.replace('-', '_') + "_func"; pipeline->emit(builder); builder->target->emitLicense(builder, pipeline->license); } @@ -267,7 +267,7 @@ void TCIngressPipelinePNA::emit(EBPF::CodeBuilder *builder) { builder->append("static __always_inline"); builder->spc(); // FIXME: use Target to generate metadata type - cstring func_name = (name == "tc-parse") ? "run_parser" : "process"; + cstring func_name = (name == "tc-parse") ? "run_parser"_cs : "process"_cs; builder->appendFormat( "int %s(%s *%s, %s %s *%s, " "struct pna_global_metadata *%s", @@ -526,14 +526,14 @@ void TCIngressPipelinePNA::emitLocalVariables(EBPF::CodeBuilder *builder) { builder->newline(); builder->emitIndent(); builder->appendFormat("void* %s = %s;", packetStartVar.c_str(), - builder->target->dataOffset(model.CPacketName.str()).c_str()); + builder->target->dataOffset(model.CPacketName.toString()).c_str()); builder->newline(); builder->emitIndent(); builder->appendFormat("u8* %s = %s;", headerStartVar.c_str(), packetStartVar.c_str()); builder->newline(); builder->emitIndent(); builder->appendFormat("void* %s = %s;", packetEndVar.c_str(), - builder->target->dataEnd(model.CPacketName.str()).c_str()); + builder->target->dataEnd(model.CPacketName.toString()).c_str()); builder->newline(); builder->emitIndent(); builder->appendFormat("u32 %s = 0;", zeroKey.c_str()); @@ -737,7 +737,7 @@ void PnaStateTranslationVisitor::compileExtractField(const IR::Expression *expr, if (auto member = expr->to()) { if (auto pathExpr = member->expr->to()) { if (isPointerVariable(pathExpr->path->name.name)) { - exprStr = exprStr.replace(".", "->"); + exprStr = exprStr.replace("."_cs, "->"_cs); } } } @@ -1200,11 +1200,11 @@ void IngressDeparserPNA::emit(EBPF::CodeBuilder *builder) { emitBufferAdjusts(builder); builder->emitIndent(); builder->appendFormat("%s = %s;", program->packetStartVar, - builder->target->dataOffset(program->model.CPacketName.str())); + builder->target->dataOffset(program->model.CPacketName.toString())); builder->newline(); builder->emitIndent(); builder->appendFormat("%s = %s;", program->packetEndVar, - builder->target->dataEnd(program->model.CPacketName.str())); + builder->target->dataEnd(program->model.CPacketName.toString())); builder->newline(); builder->emitIndent(); @@ -1249,17 +1249,17 @@ const PNAEbpfGenerator *ConvertToEbpfPNA::build(const IR::ToplevelBlock *tlb) { * PIPELINE */ auto pipeline = tlb->getMain()->checkedTo(); - auto pipelineParser = pipeline->getParameterValue("main_parser"); + auto pipelineParser = pipeline->getParameterValue("main_parser"_cs); BUG_CHECK(pipelineParser != nullptr, "No parser block found"); - auto pipelineControl = pipeline->getParameterValue("main_control"); + auto pipelineControl = pipeline->getParameterValue("main_control"_cs); BUG_CHECK(pipelineControl != nullptr, "No control block found"); - auto pipelineDeparser = pipeline->getParameterValue("main_deparser"); + auto pipelineDeparser = pipeline->getParameterValue("main_deparser"_cs); BUG_CHECK(pipelineDeparser != nullptr, "No deparser block found"); auto xdp = new EBPF::XDPHelpProgram(options); auto pipeline_converter = new ConvertToEbpfPipelineTC( - "tc-ingress", EBPF::TC_INGRESS, options, pipelineParser->checkedTo(), + "tc-ingress"_cs, EBPF::TC_INGRESS, options, pipelineParser->checkedTo(), pipelineControl->checkedTo(), pipelineDeparser->checkedTo(), refmap, typemap, tcIR); pipeline->apply(*pipeline_converter); @@ -1280,7 +1280,7 @@ bool ConvertToEbpfPipelineTC::preorder(const IR::PackageBlock *block) { (void)block; pipeline = new TCIngressPipelinePNA(name, options, refmap, typemap); - pipeline->sectionName = "p4tc/main"; + pipeline->sectionName = "p4tc/main"_cs; auto parser_converter = new ConvertToEBPFParserPNA(pipeline, typemap); parserBlock->apply(*parser_converter); pipeline->parser = parser_converter->getEBPFParser(); @@ -1531,7 +1531,7 @@ cstring ControlBodyTranslatorPNA::getParamName(const IR::PathExpression *expr) { } bool ControlBodyTranslatorPNA::IsTableAddOnMiss(const IR::P4Table *table) { - auto property = table->getBooleanProperty("add_on_miss"); + auto property = table->getBooleanProperty("add_on_miss"_cs); if (property && property->value) { return true; } @@ -1544,7 +1544,7 @@ const IR::P4Action *ControlBodyTranslatorPNA::GetAddOnMissHitAction(cstring acti auto action = adecl->getNode()->to(); if (action->name.originalName == actionName) { auto annotations = a->getAnnotations(); - if (annotations && annotations->getSingle("defaultonly")) { + if (annotations && annotations->getSingle("defaultonly"_cs)) { ::error(ErrorType::ERR_UNEXPECTED, "add_entry hit action %1% cannot be annotated with defaultonly.", actionName); @@ -1766,7 +1766,7 @@ void ControlBodyTranslatorPNA::processApply(const P4::ApplyMethod *method) { builder->blockStart(); BUG_CHECK(method->expr->arguments->size() == 0, "%1%: table apply with arguments", method); - cstring keyname = "key"; + cstring keyname = "key"_cs; if (table->keyGenerator != nullptr) { builder->emitIndent(); builder->appendLine("/* construct key */"); @@ -1804,7 +1804,7 @@ void ControlBodyTranslatorPNA::processApply(const P4::ApplyMethod *method) { auto tcTarget = dynamic_cast(builder->target); cstring isKeyBigEndian = tcTarget->getByteOrderFromAnnotation(c->getAnnotations()->annotations); - cstring isDefnBigEndian = "HOST"; + cstring isDefnBigEndian = "HOST"_cs; if (auto mem = c->expression->to()) { auto type = typeMap->getType(mem->expr, true); if (type->is()) { @@ -1821,13 +1821,13 @@ void ControlBodyTranslatorPNA::processApply(const P4::ApplyMethod *method) { if (isKeyBigEndian == "NETWORK" && isDefnBigEndian == "HOST") { if (width <= 8) { - swap = ""; // single byte, nothing to swap + swap = ""_cs; // single byte, nothing to swap } else if (width <= 16) { - swap = "bpf_htons"; + swap = "bpf_htons"_cs; } else if (width <= 32) { - swap = "bpf_htonl"; + swap = "bpf_htonl"_cs; } else if (width <= 64) { - swap = "bpf_htonll"; + swap = "bpf_htonll"_cs; } /* For width greater than 64 bit, there is no need of conversion. and the value will be copied directly from memory.*/ @@ -1868,7 +1868,7 @@ void ControlBodyTranslatorPNA::processApply(const P4::ApplyMethod *method) { builder->emitIndent(); builder->appendLine("/* value */"); builder->emitIndent(); - cstring valueName = "value"; + cstring valueName = "value"_cs; builder->appendFormat("struct %s *%s = NULL", table->valueTypeName.c_str(), valueName.c_str()); builder->endOfStatement(true); @@ -2138,7 +2138,7 @@ void DeparserHdrEmitTranslatorPNA::emitField(EBPF::CodeBuilder *builder, cstring } unsigned widthToEmit = et->widthInBits(); unsigned emitSize = 0; - cstring swap = "", msgStr; + cstring swap = ""_cs, msgStr; if (widthToEmit <= 64) { if (program->options.emitTraceMessages) { @@ -2162,13 +2162,13 @@ void DeparserHdrEmitTranslatorPNA::emitField(EBPF::CodeBuilder *builder, cstring if (widthToEmit <= 8) { emitSize = 8; } else if (widthToEmit <= 16) { - swap = "bpf_htons"; + swap = "bpf_htons"_cs; emitSize = 16; } else if (widthToEmit <= 32) { - swap = "htonl"; + swap = "htonl"_cs; emitSize = 32; } else if (widthToEmit <= 64) { - swap = "htonll"; + swap = "htonll"_cs; emitSize = 64; } unsigned shift = @@ -2252,7 +2252,7 @@ void CRCChecksumAlgorithmPNA::emitUpdateMethod(EBPF::CodeBuilder *builder, int c // incremented. For data shorter than or equal 64 bits, bytes are processed in little endian // byte order - data pointer is decremented by outer loop in this case. // There is no need for lookup table. - cstring code = + const char *code = "static __always_inline\n" "void crc16_update(u16 * reg, const u8 * data, " "u16 data_size, const u16 poly) {\n" @@ -2284,7 +2284,7 @@ void CRCChecksumAlgorithmPNA::emitUpdateMethod(EBPF::CodeBuilder *builder, int c // 4. Data size more than 8 bytes and not multiply of 8 bytes - calculated using slice-by-8 // and Standard Implementation both in big endian byte order. // Lookup table is necessary for both algorithms. - cstring code = + const char *code = "static __always_inline\n" "void crc32_update(u32 * reg, const u8 * data, u16 data_size, const u32 poly) {\n" " u32* current = (u32*) data;\n" @@ -2369,7 +2369,7 @@ void CRCChecksumAlgorithmPNA::emitUpdateMethod(EBPF::CodeBuilder *builder, int c void CRC16ChecksumAlgorithmPNA::emitGlobals(EBPF::CodeBuilder *builder) { CRCChecksumAlgorithmPNA::emitUpdateMethod(builder, 16); - cstring code = + const char *code = "static __always_inline " "u16 crc16_finalize(u16 reg) {\n" " return reg;\n" @@ -2382,7 +2382,7 @@ void CRC16ChecksumAlgorithmPNA::emitGlobals(EBPF::CodeBuilder *builder) { void CRC32ChecksumAlgorithmPNA::emitGlobals(EBPF::CodeBuilder *builder) { CRCChecksumAlgorithmPNA::emitUpdateMethod(builder, 32); - cstring code = + const char *code = "static __always_inline " "u32 crc32_finalize(u32 reg) {\n" " return reg ^ 0xFFFFFFFF;\n" diff --git a/backends/tc/ebpfCodeGen.h b/backends/tc/ebpfCodeGen.h index e0975115a9..228741374f 100644 --- a/backends/tc/ebpfCodeGen.h +++ b/backends/tc/ebpfCodeGen.h @@ -17,11 +17,14 @@ and limitations under the License. #ifndef BACKENDS_TC_EBPFCODEGEN_H_ #define BACKENDS_TC_EBPFCODEGEN_H_ +// FIXME: these include each other and present file #include "backend.h" #include "tcExterns.h" namespace TC { +using namespace P4::literals; + class ConvertToBackendIR; class EBPFPnaParser; class EBPFRegisterPNA; @@ -402,12 +405,12 @@ class CRC16ChecksumAlgorithmPNA : public CRCChecksumAlgorithmPNA { public: CRC16ChecksumAlgorithmPNA(const EBPF::EBPFProgram *program, cstring name) : CRCChecksumAlgorithmPNA(program, name, 16) { - initialValue = "0"; + initialValue = "0"_cs; // We use a 0x8005 polynomial. // 0xA001 comes from 0x8005 value bits reflection. - polynomial = "0xA001"; - updateMethod = "crc16_update"; - finalizeMethod = "crc16_finalize"; + polynomial = "0xA001"_cs; + updateMethod = "crc16_update"_cs; + finalizeMethod = "crc16_finalize"_cs; } static void emitGlobals(EBPF::CodeBuilder *builder); @@ -417,12 +420,12 @@ class CRC32ChecksumAlgorithmPNA : public CRCChecksumAlgorithmPNA { public: CRC32ChecksumAlgorithmPNA(const EBPF::EBPFProgram *program, cstring name) : CRCChecksumAlgorithmPNA(program, name, 32) { - initialValue = "0xffffffff"; + initialValue = "0xffffffff"_cs; // We use a 0x04C11DB7 polynomial. // 0xEDB88320 comes from 0x04C11DB7 value bits reflection. - polynomial = "0xEDB88320"; - updateMethod = "crc32_update"; - finalizeMethod = "crc32_finalize"; + polynomial = "0xEDB88320"_cs; + updateMethod = "crc32_update"_cs; + finalizeMethod = "crc32_finalize"_cs; } static void emitGlobals(EBPF::CodeBuilder *builder); diff --git a/backends/tc/introspection.cpp b/backends/tc/introspection.cpp index 181b4d7c93..029395acc3 100644 --- a/backends/tc/introspection.cpp +++ b/backends/tc/introspection.cpp @@ -180,23 +180,23 @@ void IntrospectionGenerator::collectExternInfo() { Util::JsonObject *IntrospectionGenerator::genExternInfo(struct ExternAttributes *extn) { auto externJson = new Util::JsonObject(); - externJson->emplace("name", extn->name); - externJson->emplace("id", extn->id); - externJson->emplace("permissions", extn->permissions); + externJson->emplace("name"_cs, extn->name); + externJson->emplace("id"_cs, extn->id); + externJson->emplace("permissions"_cs, extn->permissions); auto instanceJson = new Util::JsonArray(); for (auto eInstance : extn->instances) { auto eInstanceJson = new Util::JsonObject(); - eInstanceJson->emplace("inst_name", eInstance->name); - eInstanceJson->emplace("inst_id", eInstance->id); + eInstanceJson->emplace("inst_name"_cs, eInstance->name); + eInstanceJson->emplace("inst_id"_cs, eInstance->id); auto paramArray = new Util::JsonArray(); for (auto param : eInstance->keyFields) { auto keyJson = genKeyInfo(param); paramArray->append(keyJson); } - eInstanceJson->emplace("params", paramArray); + eInstanceJson->emplace("params"_cs, paramArray); instanceJson->append(eInstanceJson); } - externJson->emplace("instances", instanceJson); + externJson->emplace("instances"_cs, instanceJson); return externJson; } @@ -216,95 +216,95 @@ void IntrospectionGenerator::genTableJson(Util::JsonArray *tablesJson) { Util::JsonObject *IntrospectionGenerator::genActionInfo(struct ActionAttributes *action) { auto actionJson = new Util::JsonObject(); - actionJson->emplace("id", action->id); - actionJson->emplace("name", action->name); - cstring actionScope = ""; + actionJson->emplace("id"_cs, action->id); + actionJson->emplace("name"_cs, action->name); + cstring actionScope; if (action->scope == TableOnly) { - actionScope = "TableOnly"; + actionScope = "TableOnly"_cs; } else if (action->scope == DefaultOnly) { - actionScope = "DefaultOnly"; + actionScope = "DefaultOnly"_cs; } else { - actionScope = "TableAndDefault"; + actionScope = "TableAndDefault"_cs; } - actionJson->emplace("action_scope", actionScope); + actionJson->emplace("action_scope"_cs, actionScope); auto annoArray = new Util::JsonArray(); for (auto anno : action->annotations) { annoArray->append(anno->name); } - actionJson->emplace("annotations", annoArray); + actionJson->emplace("annotations"_cs, annoArray); auto paramArray = new Util::JsonArray(); for (auto param : action->actionParams) { auto paramJson = new Util::JsonObject(); - paramJson->emplace("id", param->id); - paramJson->emplace("name", param->name); + paramJson->emplace("id"_cs, param->id); + paramJson->emplace("name"_cs, param->name); switch (param->dataType) { case TC::BIT_TYPE: { auto paramtype = "bit" + Util::toString(param->bitwidth); - paramJson->emplace("type", paramtype); + paramJson->emplace("type"_cs, paramtype); break; } case TC::DEV_TYPE: { - paramJson->emplace("type", "dev"); + paramJson->emplace("type"_cs, "dev"); break; } case TC::MACADDR_TYPE: { - paramJson->emplace("type", "macaddr"); + paramJson->emplace("type"_cs, "macaddr"); break; } case TC::IPV4_TYPE: { - paramJson->emplace("type", "ipv4"); + paramJson->emplace("type"_cs, "ipv4"); break; } case TC::IPV6_TYPE: { - paramJson->emplace("type", "ipv6"); + paramJson->emplace("type"_cs, "ipv6"); break; } case TC::BE16_TYPE: { - paramJson->emplace("type", "be16"); + paramJson->emplace("type"_cs, "be16"); break; } case TC::BE32_TYPE: { - paramJson->emplace("type", "be32"); + paramJson->emplace("type"_cs, "be32"); break; } case TC::BE64_TYPE: { - paramJson->emplace("type", "be64"); + paramJson->emplace("type"_cs, "be64"); break; } } - paramJson->emplace("bitwidth", param->bitwidth); + paramJson->emplace("bitwidth"_cs, param->bitwidth); paramArray->append(paramJson); } - actionJson->emplace("params", paramArray); - actionJson->emplace("default_hit_action", action->defaultHit); - actionJson->emplace("default_miss_action", action->defaultMiss); + actionJson->emplace("params"_cs, paramArray); + actionJson->emplace("default_hit_action"_cs, action->defaultHit); + actionJson->emplace("default_miss_action"_cs, action->defaultMiss); return actionJson; } Util::JsonObject *IntrospectionGenerator::genKeyInfo(struct KeyFieldAttributes *keyField) { auto keyJson = new Util::JsonObject(); - keyJson->emplace("id", keyField->id); - keyJson->emplace("name", keyField->name); - keyJson->emplace("type", keyField->type); + keyJson->emplace("id"_cs, keyField->id); + keyJson->emplace("name"_cs, keyField->name); + keyJson->emplace("type"_cs, keyField->type); if (keyField->attribute) { - keyJson->emplace("attr", keyField->attribute); + keyJson->emplace("attr"_cs, keyField->attribute); } if (keyField->matchType) { - keyJson->emplace("match_type", keyField->matchType); + keyJson->emplace("match_type"_cs, keyField->matchType); } - keyJson->emplace("bitwidth", keyField->bitwidth); + keyJson->emplace("bitwidth"_cs, keyField->bitwidth); return keyJson; } Util::JsonObject *IntrospectionGenerator::genTableInfo(struct TableAttributes *tbl) { auto tableJson = new Util::JsonObject(); - tableJson->emplace("name", tbl->name); - tableJson->emplace("id", tbl->id); - tableJson->emplace("tentries", tbl->tentries); - tableJson->emplace("permissions", tbl->permissions); - tableJson->emplace("nummask", tbl->numMask); + tableJson->emplace("name"_cs, tbl->name); + tableJson->emplace("id"_cs, tbl->id); + tableJson->emplace("tentries"_cs, tbl->tentries); + tableJson->emplace("permissions"_cs, tbl->permissions); + tableJson->emplace("nummask"_cs, tbl->numMask); if (tbl->keysize != 0) { - tableJson->emplace("keysize", tbl->keysize); + tableJson->emplace("keysize"_cs, tbl->keysize); } auto keysJson = new Util::JsonArray(); for (auto keyField : tbl->keyFields) { @@ -312,7 +312,7 @@ Util::JsonObject *IntrospectionGenerator::genTableInfo(struct TableAttributes *t keysJson->append(keyJson); } if (keysJson->size() != 0) { - tableJson->emplace("keyfields", keysJson); + tableJson->emplace("keyfields"_cs, keysJson); } auto actionsJson = new Util::JsonArray(); for (auto action : tbl->actions) { @@ -320,7 +320,7 @@ Util::JsonObject *IntrospectionGenerator::genTableInfo(struct TableAttributes *t actionsJson->append(actionJson); } if (actionsJson->size() != 0) { - tableJson->emplace("actions", actionsJson); + tableJson->emplace("actions"_cs, actionsJson); } return tableJson; } @@ -333,12 +333,12 @@ const Util::JsonObject *IntrospectionGenerator::genIntrospectionJson() { collectTableInfo(); collectExternInfo(); introspec.initIntrospectionInfo(tcPipeline); - json->emplace("schema_version", introspec.schemaVersion); - json->emplace("pipeline_name", introspec.pipelineName); + json->emplace("schema_version"_cs, introspec.schemaVersion); + json->emplace("pipeline_name"_cs, introspec.pipelineName); genExternJson(externJson); - json->emplace("externs", externJson); + json->emplace("externs"_cs, externJson); genTableJson(tablesJson); - json->emplace("tables", tablesJson); + json->emplace("tables"_cs, tablesJson); return json; } diff --git a/backends/tc/introspection.h b/backends/tc/introspection.h index 6608e743b9..1a2d72a308 100644 --- a/backends/tc/introspection.h +++ b/backends/tc/introspection.h @@ -30,6 +30,8 @@ and limitations under the License. /// control plane programming by P4TC in Linux kernel namespace TC { +using namespace P4::literals; + struct IntrospectionInfo { cstring schemaVersion; cstring pipelineName; @@ -38,7 +40,7 @@ struct IntrospectionInfo { pipelineName = nullptr; } void initIntrospectionInfo(IR::TCPipeline *tcPipeline) { - schemaVersion = "1.0.0"; + schemaVersion = "1.0.0"_cs; pipelineName = tcPipeline->pipelineName; } }; diff --git a/backends/tc/midend.cpp b/backends/tc/midend.cpp index 469a79dfe6..d7d52001b4 100644 --- a/backends/tc/midend.cpp +++ b/backends/tc/midend.cpp @@ -61,7 +61,7 @@ const IR::ToplevelBlock *MidEnd::run(TCOptions &options, const IR::P4Program *pr evaluator, new P4::MidEndLast()}); if (options.listMidendPasses) { - midEnd.listPasses(*outStream, "\n"); + midEnd.listPasses(*outStream, cstring::newline); *outStream << std::endl; } midEnd.setName("MidEnd"); diff --git a/backends/tc/options.h b/backends/tc/options.h index d3a20b7fad..2051f098ee 100644 --- a/backends/tc/options.h +++ b/backends/tc/options.h @@ -23,10 +23,12 @@ and limitations under the License. namespace TC { +using namespace P4::literals; + class TCOptions : public CompilerOptions { public: // file to output to - cstring outputFolder = nullptr; + cstring outputFolder = ""_cs; bool DebugOn = false; // tracing eBPF code execution bool emitTraceMessages = false; @@ -38,7 +40,7 @@ class TCOptions : public CompilerOptions { registerOption( "-o", "output Directory", [this](const char *arg) { - outputFolder = arg; + outputFolder = cstring(arg); return true; }, "Write pipeline template, introspection json and C output to given directory"); diff --git a/backends/tc/pnaProgramStructure.cpp b/backends/tc/pnaProgramStructure.cpp index bedbda2371..09da41c1c7 100644 --- a/backends/tc/pnaProgramStructure.cpp +++ b/backends/tc/pnaProgramStructure.cpp @@ -18,6 +18,8 @@ and limitations under the License. namespace TC { +using namespace P4::literals; + void InspectPnaProgram::postorder(const IR::Declaration_Instance *di) { if (!pinfo->resourceMap.count(di)) return; auto blk = pinfo->resourceMap.at(di); @@ -231,7 +233,7 @@ bool ParsePnaArchitecture::preorder(const IR::ExternBlock *block) { bool ParsePnaArchitecture::preorder(const IR::PackageBlock *block) { if (auto pna_nic = block->to()) { - auto p = pna_nic->findParameterValue("main_parser"); + auto p = pna_nic->findParameterValue("main_parser"_cs); if (p == nullptr) { modelError("'PNA_NIC' package %1% has no parameter named 'ip'", block); return false; @@ -242,7 +244,7 @@ bool ParsePnaArchitecture::preorder(const IR::PackageBlock *block) { block); return false; } - p = pna_nic->findParameterValue("main_control"); + p = pna_nic->findParameterValue("main_control"_cs); if (p == nullptr) { modelError("'PNA_NIC' package %1% has no parameter named 'main_control'", block); return false; @@ -253,7 +255,7 @@ bool ParsePnaArchitecture::preorder(const IR::PackageBlock *block) { block); return false; } - p = pna_nic->findParameterValue("main_deparser"); + p = pna_nic->findParameterValue("main_deparser"_cs); if (p == nullptr) { modelError("'PNA_NIC' package %1% has no parameter named 'main_deparser'", block); return false; diff --git a/backends/tc/tc.def b/backends/tc/tc.def index ab0752fbb3..58e25f7a5b 100644 --- a/backends/tc/tc.def +++ b/backends/tc/tc.def @@ -171,9 +171,9 @@ class TCAction { optional safe_vector actionParams; cstring getName() const { if (actionName == "NoAction") { - return "NoAction"; + return actionName; } - cstring tcAction = pipelineName; + std::string tcAction = pipelineName.string(); tcAction += "/" + actionName; return tcAction; } @@ -306,16 +306,16 @@ class TCTable { return tableName; } cstring printMatchType(unsigned matchType) const { - cstring matchTypeString = ""; + cstring matchTypeString = cstring::empty; switch(matchType) { case TC::EXACT_TYPE : - matchTypeString = "exact"; + matchTypeString = "exact"_cs; break; case TC::LPM_TYPE : - matchTypeString = "lpm"; + matchTypeString = "lpm"_cs; break; case TC::TERNARY_TYPE : - matchTypeString = "ternary"; + matchTypeString = "ternary"_cs; break; } return matchTypeString; diff --git a/backends/tc/tcAnnotations.cpp b/backends/tc/tcAnnotations.cpp index 9aeb91e760..4cc6b4fb00 100644 --- a/backends/tc/tcAnnotations.cpp +++ b/backends/tc/tcAnnotations.cpp @@ -18,20 +18,22 @@ and limitations under the License. namespace TC { -const cstring ParseTCAnnotations::defaultHit = "default_hit"; -const cstring ParseTCAnnotations::defaultHitConst = "default_hit_const"; -const cstring ParseTCAnnotations::tcType = "tc_type"; -const cstring ParseTCAnnotations::numMask = "nummask"; -const cstring ParseTCAnnotations::tcMayOverride = "tc_may_override"; -const cstring ParseTCAnnotations::tc_md_write = "tc_md_write"; -const cstring ParseTCAnnotations::tc_md_read = "tc_md_read"; -const cstring ParseTCAnnotations::tc_md_exec = "tc_md_exec"; -const cstring ParseTCAnnotations::tc_ControlPath = "tc_ControlPath"; -const cstring ParseTCAnnotations::tc_key = "tc_key"; -const cstring ParseTCAnnotations::tc_data = "tc_data"; -const cstring ParseTCAnnotations::tc_data_scalar = "tc_data_scalar"; -const cstring ParseTCAnnotations::tc_init_val = "tc_init_val"; -const cstring ParseTCAnnotations::tc_numel = "tc_numel"; -const cstring ParseTCAnnotations::tc_acl = "tc_acl"; +using namespace P4::literals; + +const cstring ParseTCAnnotations::defaultHit = "default_hit"_cs; +const cstring ParseTCAnnotations::defaultHitConst = "default_hit_const"_cs; +const cstring ParseTCAnnotations::tcType = "tc_type"_cs; +const cstring ParseTCAnnotations::numMask = "nummask"_cs; +const cstring ParseTCAnnotations::tcMayOverride = "tc_may_override"_cs; +const cstring ParseTCAnnotations::tc_md_write = "tc_md_write"_cs; +const cstring ParseTCAnnotations::tc_md_read = "tc_md_read"_cs; +const cstring ParseTCAnnotations::tc_md_exec = "tc_md_exec"_cs; +const cstring ParseTCAnnotations::tc_ControlPath = "tc_ControlPath"_cs; +const cstring ParseTCAnnotations::tc_key = "tc_key"_cs; +const cstring ParseTCAnnotations::tc_data = "tc_data"_cs; +const cstring ParseTCAnnotations::tc_data_scalar = "tc_data_scalar"_cs; +const cstring ParseTCAnnotations::tc_init_val = "tc_init_val"_cs; +const cstring ParseTCAnnotations::tc_numel = "tc_numel"_cs; +const cstring ParseTCAnnotations::tc_acl = "tc_acl"_cs; } // namespace TC diff --git a/backends/ubpf/midend.cpp b/backends/ubpf/midend.cpp index b0e6760b20..be84d08f31 100644 --- a/backends/ubpf/midend.cpp +++ b/backends/ubpf/midend.cpp @@ -101,7 +101,7 @@ const IR::ToplevelBlock *MidEnd::run(EbpfOptions &options, const IR::P4Program * new P4::RemoveLeftSlices(&refMap, &typeMap), new EBPF::Lower(&refMap, &typeMap), evaluator, new P4::MidEndLast()}); if (options.listMidendPasses) { - midEnd.listPasses(*outStream, "\n"); + midEnd.listPasses(*outStream, cstring::newline); *outStream << std::endl; return nullptr; } diff --git a/backends/ubpf/p4c-ubpf.cpp b/backends/ubpf/p4c-ubpf.cpp index d8e5ca1332..b92cfea7d6 100644 --- a/backends/ubpf/p4c-ubpf.cpp +++ b/backends/ubpf/p4c-ubpf.cpp @@ -70,7 +70,7 @@ int main(int argc, char *const argv[]) { AutoCompileContext autoEbpfContext(new EbpfContext); auto &options = EbpfContext::get().options(); - options.compilerVersion = P4C_UBPF_VERSION_STRING; + options.compilerVersion = cstring(P4C_UBPF_VERSION_STRING); if (options.process(argc, argv) != nullptr) { options.setInputFile(); diff --git a/backends/ubpf/target.cpp b/backends/ubpf/target.cpp index edbe5d5d06..0158efde30 100644 --- a/backends/ubpf/target.cpp +++ b/backends/ubpf/target.cpp @@ -59,11 +59,11 @@ void UbpfTarget::emitTableDecl(Util::SourceCodeBuilder *builder, cstring tblName cstring type; if (tableKind == EBPF::TableHash) { - type = "UBPF_MAP_TYPE_HASHMAP"; + type = "UBPF_MAP_TYPE_HASHMAP"_cs; } else if (tableKind == EBPF::TableArray) { - type = "UBPF_MAP_TYPE_ARRAY"; + type = "UBPF_MAP_TYPE_ARRAY"_cs; } else if (tableKind == EBPF::TableLPMTrie) { - type = "UBPF_MAP_TYPE_LPM_TRIE"; + type = "UBPF_MAP_TYPE_LPM_TRIE"_cs; } else { BUG("%1%: unsupported table kind", tableKind); } diff --git a/backends/ubpf/target.h b/backends/ubpf/target.h index 723f3f2b3f..596a23eac4 100644 --- a/backends/ubpf/target.h +++ b/backends/ubpf/target.h @@ -23,11 +23,13 @@ limitations under the License. namespace UBPF { +using namespace P4::literals; + class UBPFControlBodyTranslator; class UbpfTarget : public EBPF::Target { public: - UbpfTarget() : EBPF::Target("UBPF") {} + UbpfTarget() : EBPF::Target("UBPF"_cs) {} void emitLicense(Util::SourceCodeBuilder *, cstring) const override {}; void emitCodeSection(Util::SourceCodeBuilder *, cstring) const override {}; @@ -52,14 +54,14 @@ class UbpfTarget : public EBPF::Target { void emitUbpfHelpers(EBPF::CodeBuilder *builder) const; void emitChecksumHelpers(EBPF::CodeBuilder *builder) const; - cstring dataOffset(UNUSED cstring base) const override { return cstring(""); } - cstring dataEnd(UNUSED cstring base) const override { return cstring(""); } - cstring dataLength(UNUSED cstring base) const override { return cstring(""); } - cstring dropReturnCode() const override { return "0"; } - cstring abortReturnCode() const override { return "1"; } - cstring forwardReturnCode() const override { return "1"; } - cstring sysMapPath() const override { return ""; } - cstring packetDescriptorType() const override { return "void"; } + cstring dataOffset(UNUSED cstring base) const override { return ""_cs; } + cstring dataEnd(UNUSED cstring base) const override { return ""_cs; } + cstring dataLength(UNUSED cstring base) const override { return ""_cs; } + cstring dropReturnCode() const override { return "0"_cs; } + cstring abortReturnCode() const override { return "1"_cs; } + cstring forwardReturnCode() const override { return "1"_cs; } + cstring sysMapPath() const override { return ""_cs; } + cstring packetDescriptorType() const override { return "void"_cs; } }; } // namespace UBPF diff --git a/backends/ubpf/ubpfControl.cpp b/backends/ubpf/ubpfControl.cpp index 58784502ad..8698b39a8d 100644 --- a/backends/ubpf/ubpfControl.cpp +++ b/backends/ubpf/ubpfControl.cpp @@ -112,7 +112,7 @@ cstring UBPFControlBodyTranslator::createHashKeyInstance(const P4::ExternFunctio auto ubpfList = atype->to(); ubpfList->name = this->refMap->newName("tuple"); - atype->declare(builder, "", false); + atype->declare(builder, ""_cs, false); builder->blockStart(); atype->emit(builder); builder->blockEnd(false); @@ -182,7 +182,7 @@ void UBPFControlBodyTranslator::processApply(const P4::ApplyMethod *method) { builder->blockStart(); BUG_CHECK(method->expr->arguments->empty(), "%1%: table apply with arguments", method); - cstring keyname = "key"; + cstring keyname = "key"_cs; if (table->keyGenerator != nullptr) { builder->emitIndent(); builder->appendLine("/* construct key */"); @@ -194,7 +194,7 @@ void UBPFControlBodyTranslator::processApply(const P4::ApplyMethod *method) { builder->emitIndent(); builder->appendLine("/* value */"); builder->emitIndent(); - cstring valueName = "value"; + cstring valueName = "value"_cs; builder->appendFormat("struct %s *%s = NULL", table->valueTypeName.c_str(), valueName.c_str()); builder->endOfStatement(true); @@ -532,7 +532,7 @@ bool UBPFControlBodyTranslator::comparison(const IR::Operation_Relation *b) { } bool UBPFControlBodyTranslator::preorder(const IR::Member *expression) { - cstring name = ""; + cstring name = ""_cs; if (expression->expr->is()) { name = expression->expr->to()->path->name.name; } diff --git a/backends/ubpf/ubpfDeparser.cpp b/backends/ubpf/ubpfDeparser.cpp index cce0e1b405..057d028d10 100644 --- a/backends/ubpf/ubpfDeparser.cpp +++ b/backends/ubpf/ubpfDeparser.cpp @@ -120,17 +120,17 @@ void UBPFDeparserTranslationVisitor::compileEmitField(const IR::Expression *expr unsigned widthToEmit = et->widthInBits(); unsigned loadSize = 0; - cstring swap = ""; + cstring swap = ""_cs; if (widthToEmit <= 8) { loadSize = 8; } else if (widthToEmit <= 16) { - swap = "bpf_htons"; + swap = "bpf_htons"_cs; loadSize = 16; } else if (widthToEmit <= 32) { - swap = "htonl"; + swap = "htonl"_cs; loadSize = 32; } else if (widthToEmit <= 64) { - swap = "htonll"; + swap = "htonll"_cs; loadSize = 64; } unsigned bytes = ROUNDUP(widthToEmit, 8); diff --git a/backends/ubpf/ubpfModel.cpp b/backends/ubpf/ubpfModel.cpp index c2aeeb8c52..3986cd89fe 100644 --- a/backends/ubpf/ubpfModel.cpp +++ b/backends/ubpf/ubpfModel.cpp @@ -18,7 +18,7 @@ limitations under the License. namespace UBPF { -cstring UBPFModel::reservedPrefix = "ubpf_"; +cstring UBPFModel::reservedPrefix = "ubpf_"_cs; UBPFModel UBPFModel::instance; } // namespace UBPF diff --git a/backends/ubpf/ubpfModel.h b/backends/ubpf/ubpfModel.h index 7346fe9c68..dc65931ee8 100644 --- a/backends/ubpf/ubpfModel.h +++ b/backends/ubpf/ubpfModel.h @@ -25,8 +25,11 @@ limitations under the License. namespace UBPF { +using namespace P4::literals; + struct Pipeline_Model : public ::Model::Elem { - Pipeline_Model() : Elem("Pipeline"), parser("prs"), control("p"), deparser("dprs") {} + Pipeline_Model() + : Elem("Pipeline"_cs), parser("prs"_cs), control("p"_cs), deparser("dprs"_cs) {} ::Model::Elem parser; ::Model::Elem control; @@ -35,13 +38,13 @@ struct Pipeline_Model : public ::Model::Elem { struct Register_Model : public ::Model::Extern_Model { Register_Model() - : Extern_Model("Register"), - sizeParam("size"), - read("read"), - write("write"), - initial_value("initial_value"), - index("index"), - value("value") {} + : Extern_Model("Register"_cs), + sizeParam("size"_cs), + read("read"_cs), + write("write"_cs), + initial_value("initial_value"_cs), + index("index"_cs), + value("value"_cs) {} ::Model::Elem sizeParam; ::Model::Elem read; @@ -52,28 +55,28 @@ struct Register_Model : public ::Model::Extern_Model { }; struct Algorithm_Model : public ::Model::Enum_Model { - Algorithm_Model() : ::Model::Enum_Model("HashAlgorithm"), lookup3("lookup3") {} + Algorithm_Model() : ::Model::Enum_Model("HashAlgorithm"_cs), lookup3("lookup3"_cs) {} ::Model::Elem lookup3; }; struct Hash_Model : public ::Model::Elem { - Hash_Model() : ::Model::Elem("hash") {} + Hash_Model() : ::Model::Elem("hash"_cs) {} }; class UBPFModel : public ::Model::Model { protected: UBPFModel() - : CPacketName("pkt"), - packet("packet", P4::P4CoreLibrary::instance().packetIn, 0), + : CPacketName("pkt"_cs), + packet("packet"_cs, P4::P4CoreLibrary::instance().packetIn, 0), pipeline(), registerModel(), - drop("mark_to_drop"), - pass("mark_to_pass"), - ubpf_time_get_ns("ubpf_time_get_ns"), - truncate("truncate"), - csum_replace2("csum_replace2"), - csum_replace4("csum_replace4"), + drop("mark_to_drop"_cs), + pass("mark_to_pass"_cs), + ubpf_time_get_ns("ubpf_time_get_ns"_cs), + truncate("truncate"_cs), + csum_replace2("csum_replace2"_cs), + csum_replace4("csum_replace4"_cs), hashAlgorithm(), hash() {} diff --git a/backends/ubpf/ubpfParser.cpp b/backends/ubpf/ubpfParser.cpp index b9cd1137f8..1a4654af52 100644 --- a/backends/ubpf/ubpfParser.cpp +++ b/backends/ubpf/ubpfParser.cpp @@ -334,7 +334,7 @@ void UBPFStateTranslationVisitor::compileLookahead(const IR::Expression *destina builder->append(" "); visit(destination); builder->append(" = "); - compileExtractField(nullptr, "", 0, etype, false); + compileExtractField(nullptr, ""_cs, 0, etype, false); builder->endOfStatement(true); } diff --git a/backends/ubpf/ubpfProgram.cpp b/backends/ubpf/ubpfProgram.cpp index efc732ae12..590cdf8a6e 100644 --- a/backends/ubpf/ubpfProgram.cpp +++ b/backends/ubpf/ubpfProgram.cpp @@ -77,7 +77,7 @@ void UBPFProgram::emitC(UbpfCodeBuilder *builder, cstring headerFile) { builder->target->emitChecksumHelpers(builder); builder->emitIndent(); - builder->target->emitMain(builder, "entry", contextVar.c_str(), stdMetadataVar.c_str()); + builder->target->emitMain(builder, "entry"_cs, contextVar, stdMetadataVar); builder->blockStart(); emitPktVariable(builder); @@ -247,7 +247,7 @@ void UBPFProgram::emitPktVariable(UbpfCodeBuilder *builder) const { void UBPFProgram::emitPacketLengthVariable(UbpfCodeBuilder *builder) const { builder->emitIndent(); builder->appendFormat("uint32_t %s = ", lengthVar.c_str()); - builder->target->emitGetFromStandardMetadata(builder, stdMetadataVar, "packet_length"); + builder->target->emitGetFromStandardMetadata(builder, stdMetadataVar, "packet_length"_cs); builder->endOfStatement(true); } diff --git a/backends/ubpf/ubpfProgram.h b/backends/ubpf/ubpfProgram.h index 71e2b1eb78..82493e009b 100644 --- a/backends/ubpf/ubpfProgram.h +++ b/backends/ubpf/ubpfProgram.h @@ -44,7 +44,7 @@ class UBPFProgram : public EBPF::EBPFProgram { cstring contextVar, outerHdrOffsetVar, outerHdrLengthVar; cstring stdMetadataVar; cstring packetTruncatedSizeVar; - cstring arrayIndexType = "uint32_t"; + cstring arrayIndexType = "uint32_t"_cs; UBPFProgram(const EbpfOptions &options, const IR::P4Program *program, P4::ReferenceMap *refMap, P4::TypeMap *typeMap, const IR::ToplevelBlock *toplevel) @@ -76,8 +76,8 @@ class UBPFProgram : public EBPF::EBPFProgram { bool isLibraryMethod(cstring methodName) override { static std::set DEFAULT_METHODS = { - "mark_to_drop", "mark_to_pass", "ubpf_time_get_ns", "truncate", - "hash", "csum_replace2", "csum_replace4", + "mark_to_drop"_cs, "mark_to_pass"_cs, "ubpf_time_get_ns"_cs, "truncate"_cs, + "hash"_cs, "csum_replace2"_cs, "csum_replace4"_cs, }; return DEFAULT_METHODS.find(methodName) != DEFAULT_METHODS.end() || EBPFProgram::isLibraryMethod(methodName); diff --git a/backends/ubpf/ubpfRegister.cpp b/backends/ubpf/ubpfRegister.cpp index db241817e7..92db34f8a6 100644 --- a/backends/ubpf/ubpfRegister.cpp +++ b/backends/ubpf/ubpfRegister.cpp @@ -112,14 +112,14 @@ void UBPFRegister::emitRegisterRead(EBPF::CodeBuilder *builder, BUG_CHECK(expression->arguments->size() == 1, "Expected 1 argument for %1%", expression); auto target = builder->target; - target->emitTableLookup(builder, dataMapName, last_key_name, ""); + target->emitTableLookup(builder, dataMapName, last_key_name, ""_cs); } void UBPFRegister::emitKeyInstance(EBPF::CodeBuilder *builder, const IR::MethodCallExpression *expression) { auto arg_key = expression->arguments->at(0); - cstring keyName = ""; + cstring keyName = ""_cs; if (arg_key->expression->is()) { keyName = arg_key->expression->to()->path->name.name; diff --git a/backends/ubpf/ubpfTable.cpp b/backends/ubpf/ubpfTable.cpp index b262479b84..10c7454b66 100644 --- a/backends/ubpf/ubpfTable.cpp +++ b/backends/ubpf/ubpfTable.cpp @@ -44,7 +44,7 @@ class UbpfActionTranslationVisitor : public EBPF::CodeGenInspector { } bool preorder(const IR::Member *expression) override { - cstring name = ""; + cstring name = ""_cs; if (expression->expr->is()) { name = expression->expr->to()->path->name.name; } @@ -166,13 +166,13 @@ UBPFTable::UBPFTable(const UBPFProgram *program, const IR::TableBlock *table, EBPF::CodeGenInspector *codeGen) : UBPFTableBase(program, EBPFObject::externalName(table->container), codeGen), table(table) { cstring base = instanceName + "_defaultAction"; - defaultActionMapName = program->refMap->newName(base); + defaultActionMapName = program->refMap->newName(base.string_view()); base = table->container->name.name + "_actions"; - actionEnumName = program->refMap->newName(base); + actionEnumName = program->refMap->newName(base.string_view()); base = instanceName + "_NoAction"; - noActionName = program->refMap->newName(base); + noActionName = program->refMap->newName(base.string_view()); keyGenerator = table->container->getKey(); actionList = table->container->getActionList(); @@ -187,7 +187,7 @@ UBPFTable::UBPFTable(const UBPFProgram *program, const IR::TableBlock *table, void UBPFTable::emitInstance(EBPF::CodeBuilder *builder) { UBPFTableBase::emitInstance(builder, tableKind); builder->target->emitTableDecl(builder, defaultActionMapName, EBPF::TableArray, - program->arrayIndexType, cstring("struct ") + valueTypeName, 1); + program->arrayIndexType, "struct "_cs + valueTypeName, 1); } void UBPFTable::setTableKind() { diff --git a/backends/ubpf/ubpfType.cpp b/backends/ubpf/ubpfType.cpp index b5641d8ba3..cae6034877 100644 --- a/backends/ubpf/ubpfType.cpp +++ b/backends/ubpf/ubpfType.cpp @@ -20,6 +20,8 @@ limitations under the License. namespace UBPF { +using namespace P4::literals; + EBPF::EBPFTypeFactory *instance = UBPFTypeFactory::getInstance(); EBPF::EBPFType *UBPFTypeFactory::create(const IR::Type *type) { @@ -69,16 +71,12 @@ void UBPFScalarType::emit(EBPF::CodeBuilder *builder) { } cstring UBPFScalarType::getAsString() { - if (width <= 8) - return cstring("uint8_t"); - else if (width <= 16) - return cstring("uint16_t"); - else if (width <= 32) - return cstring("uint32_t"); - else if (width <= 64) - return cstring("uint64_t"); - else - return cstring("uint8_t*"); + if (width <= 8) return "uint8_t"_cs; + if (width <= 16) return "uint16_t"_cs; + if (width <= 32) return "uint32_t"_cs; + if (width <= 64) return "uint64_t"_cs; + + return "uint8_t*"_cs; } void UBPFScalarType::declare(EBPF::CodeBuilder *builder, cstring id, bool asPointer) { @@ -138,7 +136,7 @@ void UBPFStructType::emit(EBPF::CodeBuilder *builder) { builder->emitIndent(); auto type = UBPFTypeFactory::instance->create(IR::Type_Boolean::get()); if (type != nullptr) { - type->declare(builder, "ebpf_valid", false); + type->declare(builder, "ebpf_valid"_cs, false); builder->endOfStatement(true); } } @@ -191,7 +189,7 @@ void UBPFErrorType::emit(EBPF::CodeBuilder *builder) { ////////////////////////////////////////////////////////// UBPFListType::UBPFListType(const IR::Type_List *lst) : EBPFType(lst) { - kind = "struct"; + kind = "struct"_cs; width = 0; implWidth = 0; // The first iteration is to compute total width of Type_List. diff --git a/bazel/example/main.cc b/bazel/example/main.cc index 33ebffe57c..e8f8fa66ae 100644 --- a/bazel/example/main.cc +++ b/bazel/example/main.cc @@ -9,6 +9,8 @@ using ::google::protobuf::TextFormat; using ::p4::config::v1::P4Info; +using namespace P4::literals; + const char kP4InfoFile[] = "program.p4info.txt"; int main() { @@ -24,6 +26,6 @@ int main() { std::cout << p4info.DebugString(); // Demonstrate that IR extension is present. - IR::MyCustomStatement statement("Hello, P4 extension world!"); + IR::MyCustomStatement statement("Hello, P4 extension world!"_cs); std::cout << statement << std::endl; } diff --git a/control-plane/bfruntime.cpp b/control-plane/bfruntime.cpp index 1dd99b0d9d..ac3de53b12 100644 --- a/control-plane/bfruntime.cpp +++ b/control-plane/bfruntime.cpp @@ -249,14 +249,14 @@ Util::JsonObject *BFRuntimeGenerator::makeCommonDataField(P4Id id, cstring name, Util::JsonObject *type, bool repeated, Util::JsonArray *annotations) { auto *dataField = new Util::JsonObject(); - dataField->emplace("id", id); - dataField->emplace("name", name); - dataField->emplace("repeated", repeated); + dataField->emplace("id"_cs, id); + dataField->emplace("name"_cs, name); + dataField->emplace("repeated"_cs, repeated); if (annotations != nullptr) - dataField->emplace("annotations", annotations); + dataField->emplace("annotations"_cs, annotations); else - dataField->emplace("annotations", new Util::JsonArray()); - dataField->emplace("type", type); + dataField->emplace("annotations"_cs, new Util::JsonArray()); + dataField->emplace("type"_cs, type); return dataField; } @@ -264,14 +264,14 @@ Util::JsonObject *BFRuntimeGenerator::makeContainerDataField(P4Id id, cstring na Util::JsonArray *items, bool repeated, Util::JsonArray *annotations) { auto *dataField = new Util::JsonObject(); - dataField->emplace("id", id); - dataField->emplace("name", name); - dataField->emplace("repeated", repeated); + dataField->emplace("id"_cs, id); + dataField->emplace("name"_cs, name); + dataField->emplace("repeated"_cs, repeated); if (annotations != nullptr) - dataField->emplace("annotations", annotations); + dataField->emplace("annotations"_cs, annotations); else - dataField->emplace("annotations", new Util::JsonArray()); - dataField->emplace("container", items); + dataField->emplace("annotations"_cs, new Util::JsonArray()); + dataField->emplace("container"_cs, items); return dataField; } @@ -279,16 +279,16 @@ void BFRuntimeGenerator::addActionDataField(Util::JsonArray *dataJson, P4Id id, const std::string &name, bool mandatory, bool read_only, Util::JsonObject *type, Util::JsonArray *annotations) { auto *dataField = new Util::JsonObject(); - dataField->emplace("id", id); - dataField->emplace("name", name); - dataField->emplace("repeated", false); - dataField->emplace("mandatory", mandatory); - dataField->emplace("read_only", read_only); + dataField->emplace("id"_cs, id); + dataField->emplace("name"_cs, name); + dataField->emplace("repeated"_cs, false); + dataField->emplace("mandatory"_cs, mandatory); + dataField->emplace("read_only"_cs, read_only); if (annotations != nullptr) - dataField->emplace("annotations", annotations); + dataField->emplace("annotations"_cs, annotations); else - dataField->emplace("annotations", new Util::JsonArray()); - dataField->emplace("type", type); + dataField->emplace("annotations"_cs, new Util::JsonArray()); + dataField->emplace("type"_cs, type); dataJson->append(dataField); } @@ -296,16 +296,16 @@ void BFRuntimeGenerator::addKeyField(Util::JsonArray *dataJson, P4Id id, cstring bool mandatory, cstring matchType, Util::JsonObject *type, Util::JsonArray *annotations) { auto *dataField = new Util::JsonObject(); - dataField->emplace("id", id); - dataField->emplace("name", name); - dataField->emplace("repeated", false); + dataField->emplace("id"_cs, id); + dataField->emplace("name"_cs, name); + dataField->emplace("repeated"_cs, false); if (annotations != nullptr) - dataField->emplace("annotations", annotations); + dataField->emplace("annotations"_cs, annotations); else - dataField->emplace("annotations", new Util::JsonArray()); - dataField->emplace("mandatory", mandatory); - dataField->emplace("match_type", matchType); - dataField->emplace("type", type); + dataField->emplace("annotations"_cs, new Util::JsonArray()); + dataField->emplace("mandatory"_cs, mandatory); + dataField->emplace("match_type"_cs, matchType); + dataField->emplace("type"_cs, type); dataJson->append(dataField); } @@ -313,17 +313,17 @@ void BFRuntimeGenerator::addKeyField(Util::JsonArray *dataJson, P4Id id, cstring cstring tableType, int64_t size, Util::JsonArray *annotations) { auto *tableJson = new Util::JsonObject(); - tableJson->emplace("name", name); - tableJson->emplace("id", id); - tableJson->emplace("table_type", tableType); - tableJson->emplace("size", size); - if (annotations != nullptr) tableJson->emplace("annotations", annotations); - tableJson->emplace("depends_on", new Util::JsonArray()); + tableJson->emplace("name"_cs, name); + tableJson->emplace("id"_cs, id); + tableJson->emplace("table_type"_cs, tableType); + tableJson->emplace("size"_cs, size); + if (annotations != nullptr) tableJson->emplace("annotations"_cs, annotations); + tableJson->emplace("depends_on"_cs, new Util::JsonArray()); return tableJson; } /* static */ void BFRuntimeGenerator::addToDependsOn(Util::JsonObject *tableJson, P4Id id) { - auto *dependsOnJson = tableJson->get("depends_on")->to(); + auto *dependsOnJson = tableJson->get("depends_on"_cs)->to(); CHECK_NULL(dependsOnJson); // Skip duplicates for (auto *d : *dependsOnJson) { @@ -335,22 +335,22 @@ void BFRuntimeGenerator::addKeyField(Util::JsonArray *dataJson, P4Id id, cstring void BFRuntimeGenerator::addCounterCommon(Util::JsonArray *tablesJson, const Counter &counter) const { auto *tableJson = - initTableJson(counter.name, counter.id, "Counter", counter.size, counter.annotations); + initTableJson(counter.name, counter.id, "Counter"_cs, counter.size, counter.annotations); auto *keyJson = new Util::JsonArray(); - addKeyField(keyJson, TD_DATA_COUNTER_INDEX, "$COUNTER_INDEX", true /* mandatory */, "Exact", - makeType("uint32")); - tableJson->emplace("key", keyJson); + addKeyField(keyJson, TD_DATA_COUNTER_INDEX, "$COUNTER_INDEX"_cs, true /* mandatory */, + "Exact"_cs, makeType("uint32"_cs)); + tableJson->emplace("key"_cs, keyJson); auto *dataJson = new Util::JsonArray(); addCounterDataFields(dataJson, counter); - tableJson->emplace("data", dataJson); + tableJson->emplace("data"_cs, dataJson); auto *operationsJson = new Util::JsonArray(); - operationsJson->append("Sync"); - tableJson->emplace("supported_operations", operationsJson); + operationsJson->append("Sync"_cs); + tableJson->emplace("supported_operations"_cs, operationsJson); - tableJson->emplace("attributes", new Util::JsonArray()); + tableJson->emplace("attributes"_cs, new Util::JsonArray()); tablesJson->append(tableJson); } @@ -360,36 +360,36 @@ void BFRuntimeGenerator::addCounterDataFields(Util::JsonArray *dataJson, static const uint64_t defaultCounterValue = 0u; if (counter.unit == Counter::Unit::BYTES || counter.unit == Counter::Unit::BOTH) { auto *f = - makeCommonDataField(TD_DATA_COUNTER_SPEC_BYTES, "$COUNTER_SPEC_BYTES", - makeType("uint64", defaultCounterValue), false /* repeated */); + makeCommonDataField(TD_DATA_COUNTER_SPEC_BYTES, "$COUNTER_SPEC_BYTES"_cs, + makeType("uint64"_cs, defaultCounterValue), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } if (counter.unit == Counter::Unit::PACKETS || counter.unit == Counter::Unit::BOTH) { auto *f = - makeCommonDataField(TD_DATA_COUNTER_SPEC_PKTS, "$COUNTER_SPEC_PKTS", - makeType("uint64", defaultCounterValue), false /* repeated */); + makeCommonDataField(TD_DATA_COUNTER_SPEC_PKTS, "$COUNTER_SPEC_PKTS"_cs, + makeType("uint64"_cs, defaultCounterValue), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } } void BFRuntimeGenerator::addMeterCommon(Util::JsonArray *tablesJson, const BFRuntimeGenerator::Meter &meter) const { - auto *tableJson = initTableJson(meter.name, meter.id, "Meter", meter.size); + auto *tableJson = initTableJson(meter.name, meter.id, "Meter"_cs, meter.size); auto *keyJson = new Util::JsonArray(); - addKeyField(keyJson, TD_DATA_METER_INDEX, "$METER_INDEX", true /* mandatory */, "Exact", - makeType("uint32")); - tableJson->emplace("key", keyJson); + addKeyField(keyJson, TD_DATA_METER_INDEX, "$METER_INDEX"_cs, true /* mandatory */, "Exact"_cs, + makeType("uint32"_cs)); + tableJson->emplace("key"_cs, keyJson); auto *dataJson = new Util::JsonArray(); addMeterDataFields(dataJson, meter); - tableJson->emplace("data", dataJson); + tableJson->emplace("data"_cs, dataJson); - tableJson->emplace("supported_operations", new Util::JsonArray()); + tableJson->emplace("supported_operations"_cs, new Util::JsonArray()); auto *attributesJson = new Util::JsonArray(); attributesJson->append("MeterByteCountAdjust"); - tableJson->emplace("attributes", attributesJson); + tableJson->emplace("attributes"_cs, attributesJson); tablesJson->append(tableJson); } @@ -411,36 +411,36 @@ void BFRuntimeGenerator::transformTypeSpecToDataFields(Util::JsonArray *fieldsJs void BFRuntimeGenerator::addRegisterDataFields(Util::JsonArray *dataJson, const BFRuntimeGenerator::Register ®ister_, P4Id idOffset) const { - auto parser = TypeSpecParser::make(p4info, register_.typeSpec, "Register", register_.name, - nullptr, "", "", idOffset); + auto parser = TypeSpecParser::make(p4info, register_.typeSpec, "Register"_cs, register_.name, + nullptr, cstring::empty, cstring::empty, idOffset); BUG_CHECK(parser.size() == 1, "Expected only one data field for Register extern %1%", register_.name); for (const auto &f : parser) { auto *fJson = - makeCommonDataField(idOffset, "$REGISTER_INDEX", f.type, false /* repeated */); + makeCommonDataField(idOffset, "$REGISTER_INDEX"_cs, f.type, false /* repeated */); addSingleton(dataJson, fJson, false /* mandatory */, false /* read-only */); } } void BFRuntimeGenerator::addRegisterCommon(Util::JsonArray *tablesJson, const BFRuntimeGenerator::Register ®ister_) const { - auto *tableJson = initTableJson(register_.name, register_.id, "Register", register_.size, + auto *tableJson = initTableJson(register_.name, register_.id, "Register"_cs, register_.size, register_.annotations); auto *keyJson = new Util::JsonArray(); - addKeyField(keyJson, TD_DATA_REGISTER_INDEX, "$REGISTER_INDEX", true /* mandatory */, "Exact", - makeType("uint32")); - tableJson->emplace("key", keyJson); + addKeyField(keyJson, TD_DATA_REGISTER_INDEX, "$REGISTER_INDEX"_cs, true /* mandatory */, + "Exact"_cs, makeType("uint32"_cs)); + tableJson->emplace("key"_cs, keyJson); auto *dataJson = new Util::JsonArray(); addRegisterDataFields(dataJson, register_, TD_DATA_REGISTER_INDEX); - tableJson->emplace("data", dataJson); + tableJson->emplace("data"_cs, dataJson); auto *operationsJson = new Util::JsonArray(); operationsJson->append("Sync"); - tableJson->emplace("supported_operations", operationsJson); + tableJson->emplace("supported_operations"_cs, operationsJson); - tableJson->emplace("attributes", new Util::JsonArray()); + tableJson->emplace("attributes"_cs, new Util::JsonArray()); tablesJson->append(tableJson); } @@ -451,44 +451,44 @@ void BFRuntimeGenerator::addMeterDataFields(Util::JsonArray *dataJson, static const uint64_t maxUint64 = std::numeric_limits::max(); if (meter.unit == Meter::Unit::BYTES) { { - auto *f = makeCommonDataField(TD_DATA_METER_SPEC_CIR_KBPS, "$METER_SPEC_CIR_KBPS", - makeType("uint64", maxUint64), false /* repeated */); + auto *f = makeCommonDataField(TD_DATA_METER_SPEC_CIR_KBPS, "$METER_SPEC_CIR_KBPS"_cs, + makeType("uint64"_cs, maxUint64), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } { - auto *f = makeCommonDataField(TD_DATA_METER_SPEC_PIR_KBPS, "$METER_SPEC_PIR_KBPS", - makeType("uint64", maxUint64), false /* repeated */); + auto *f = makeCommonDataField(TD_DATA_METER_SPEC_PIR_KBPS, "$METER_SPEC_PIR_KBPS"_cs, + makeType("uint64"_cs, maxUint64), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } { - auto *f = makeCommonDataField(TD_DATA_METER_SPEC_CBS_KBITS, "$METER_SPEC_CBS_KBITS", - makeType("uint64", maxUint64), false /* repeated */); + auto *f = makeCommonDataField(TD_DATA_METER_SPEC_CBS_KBITS, "$METER_SPEC_CBS_KBITS"_cs, + makeType("uint64"_cs, maxUint64), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } { - auto *f = makeCommonDataField(TD_DATA_METER_SPEC_PBS_KBITS, "$METER_SPEC_PBS_KBITS", - makeType("uint64", maxUint64), false /* repeated */); + auto *f = makeCommonDataField(TD_DATA_METER_SPEC_PBS_KBITS, "$METER_SPEC_PBS_KBITS"_cs, + makeType("uint64"_cs, maxUint64), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } } else if (meter.unit == Meter::Unit::PACKETS) { { - auto *f = makeCommonDataField(TD_DATA_METER_SPEC_CIR_PPS, "$METER_SPEC_CIR_PPS", - makeType("uint64", maxUint64), false /* repeated */); + auto *f = makeCommonDataField(TD_DATA_METER_SPEC_CIR_PPS, "$METER_SPEC_CIR_PPS"_cs, + makeType("uint64"_cs, maxUint64), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } { - auto *f = makeCommonDataField(TD_DATA_METER_SPEC_PIR_PPS, "$METER_SPEC_PIR_PPS", - makeType("uint64", maxUint64), false /* repeated */); + auto *f = makeCommonDataField(TD_DATA_METER_SPEC_PIR_PPS, "$METER_SPEC_PIR_PPS"_cs, + makeType("uint64"_cs, maxUint64), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } { - auto *f = makeCommonDataField(TD_DATA_METER_SPEC_CBS_PKTS, "$METER_SPEC_CBS_PKTS", - makeType("uint64", maxUint64), false /* repeated */); + auto *f = makeCommonDataField(TD_DATA_METER_SPEC_CBS_PKTS, "$METER_SPEC_CBS_PKTS"_cs, + makeType("uint64"_cs, maxUint64), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } { - auto *f = makeCommonDataField(TD_DATA_METER_SPEC_PBS_PKTS, "$METER_SPEC_PBS_PKTS", - makeType("uint64", maxUint64), false /* repeated */); + auto *f = makeCommonDataField(TD_DATA_METER_SPEC_PBS_PKTS, "$METER_SPEC_PBS_PKTS"_cs, + makeType("uint64"_cs, maxUint64), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } } else { @@ -498,13 +498,13 @@ void BFRuntimeGenerator::addMeterDataFields(Util::JsonArray *dataJson, void BFRuntimeGenerator::addActionProfCommon( Util::JsonArray *tablesJson, const BFRuntimeGenerator::ActionProf &actionProf) const { - auto *tableJson = initTableJson(actionProf.name, actionProf.id, "Action", actionProf.size, + auto *tableJson = initTableJson(actionProf.name, actionProf.id, "Action"_cs, actionProf.size, actionProf.annotations); auto *keyJson = new Util::JsonArray(); - addKeyField(keyJson, TD_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID", true /* mandatory */, - "Exact", makeType("uint32")); - tableJson->emplace("key", keyJson); + addKeyField(keyJson, TD_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID"_cs, true /* mandatory */, + "Exact"_cs, makeType("uint32"_cs)); + tableJson->emplace("key"_cs, keyJson); if (actionProf.tableIds.empty()) { ::warning("Action profile '%1%' is not used by any table, skipping it", actionProf.name); @@ -518,12 +518,12 @@ void BFRuntimeGenerator::addActionProfCommon( auto oneTableJson = findJsonTable(tablesJson, oneTable->preamble().name()); addToDependsOn(oneTableJson, actionProf.id); - tableJson->emplace("action_specs", makeActionSpecs(*oneTable)); + tableJson->emplace("action_specs"_cs, makeActionSpecs(*oneTable)); - tableJson->emplace("data", new Util::JsonArray()); + tableJson->emplace("data"_cs, new Util::JsonArray()); - tableJson->emplace("supported_operations", new Util::JsonArray()); - tableJson->emplace("attributes", new Util::JsonArray()); + tableJson->emplace("supported_operations"_cs, new Util::JsonArray()); + tableJson->emplace("attributes"_cs, new Util::JsonArray()); tablesJson->append(tableJson); } @@ -549,17 +549,17 @@ Util::JsonArray *BFRuntimeGenerator::makeActionSpecs(const p4configv1::Table &ta } auto *spec = new Util::JsonObject(); const auto &pre = action->preamble(); - spec->emplace("id", pre.id()); - spec->emplace("name", pre.name()); + spec->emplace("id"_cs, pre.id()); + spec->emplace("name"_cs, pre.name()); switch (action_ref.scope()) { case p4configv1::ActionRef::TABLE_AND_DEFAULT: - spec->emplace("action_scope", "TableAndDefault"); + spec->emplace("action_scope"_cs, "TableAndDefault"); break; case p4configv1::ActionRef::TABLE_ONLY: - spec->emplace("action_scope", "TableOnly"); + spec->emplace("action_scope"_cs, "TableOnly"); break; case p4configv1::ActionRef::DEFAULT_ONLY: - spec->emplace("action_scope", "DefaultOnly"); + spec->emplace("action_scope"_cs, "DefaultOnly"); break; default: ::error(ErrorType::ERR_INVALID, "Invalid action ref scope '%1%' in P4Info", @@ -568,7 +568,7 @@ Util::JsonArray *BFRuntimeGenerator::makeActionSpecs(const p4configv1::Table &ta } auto *annotations = transformAnnotations(action_ref.annotations().begin(), action_ref.annotations().end()); - spec->emplace("annotations", annotations); + spec->emplace("annotations"_cs, annotations); auto *dataJson = new Util::JsonArray(); for (const auto ¶m : action->params()) { @@ -576,8 +576,8 @@ Util::JsonArray *BFRuntimeGenerator::makeActionSpecs(const p4configv1::Table &ta transformAnnotations(param.annotations().begin(), param.annotations().end()); if (param.type_name().name() == "PSA_MeterColor_t") { addActionDataField(dataJson, param.id(), param.name(), true /* mandatory */, - false /* read_only */, makeTypeEnum({"RED", "GREEN", "YELLOW"}), - annotations); + false /* read_only */, + makeTypeEnum({"RED"_cs, "GREEN"_cs, "YELLOW"_cs}), annotations); } else { addActionDataField(dataJson, param.id(), param.name(), true /* mandatory */, false /* read_only */, makeTypeBytes(param.bitwidth()), @@ -585,7 +585,7 @@ Util::JsonArray *BFRuntimeGenerator::makeActionSpecs(const p4configv1::Table &ta } if (param.id() > maxId) maxId = param.id(); } - spec->emplace("data", dataJson); + spec->emplace("data"_cs, dataJson); specs->append(spec); } if (maxActionParamId != nullptr) *maxActionParamId = maxId; @@ -595,13 +595,13 @@ Util::JsonArray *BFRuntimeGenerator::makeActionSpecs(const p4configv1::Table &ta void BFRuntimeGenerator::addLearnFilterCommon(Util::JsonArray *learnFiltersJson, const BFRuntimeGenerator::Digest &digest) const { auto *learnFilterJson = new Util::JsonObject(); - learnFilterJson->emplace("name", digest.name); - learnFilterJson->emplace("id", digest.id); - learnFilterJson->emplace("annotations", digest.annotations); + learnFilterJson->emplace("name"_cs, digest.name); + learnFilterJson->emplace("id"_cs, digest.id); + learnFilterJson->emplace("annotations"_cs, digest.annotations); auto *fieldsJson = new Util::JsonArray(); - transformTypeSpecToDataFields(fieldsJson, digest.typeSpec, "Digest", digest.name); - learnFilterJson->emplace("fields", fieldsJson); + transformTypeSpecToDataFields(fieldsJson, digest.typeSpec, "Digest"_cs, digest.name); + learnFilterJson->emplace("fields"_cs, fieldsJson); learnFiltersJson->append(learnFilterJson); } @@ -663,11 +663,11 @@ void BFRuntimeGenerator::addMatchTables(Util::JsonArray *tablesJson) const { transformAnnotations(pre.annotations().begin(), pre.annotations().end()); auto *tableJson = - initTableJson(pre.name(), pre.id(), "MatchAction_Direct", table.size(), annotations); + initTableJson(pre.name(), pre.id(), "MatchAction_Direct"_cs, table.size(), annotations); if (!addActionProfIds(table, tableJson)) continue; - tableJson->emplace("has_const_default_action", table.const_default_action_id() != 0); + tableJson->emplace("has_const_default_action"_cs, table.const_default_action_id() != 0); // will be set to true by the for loop if the match key includes a // ternary, range or optional match @@ -704,8 +704,8 @@ void BFRuntimeGenerator::addMatchTables(Util::JsonArray *tablesJson) const { std::regex_search(s, sm, sliceRegex); if (sm.size() == 3) { auto *isFieldSliceAnnot = new Util::JsonObject(); - isFieldSliceAnnot->emplace("name", "isFieldSlice"); - isFieldSliceAnnot->emplace("value", "true"); + isFieldSliceAnnot->emplace("name"_cs, "isFieldSlice"); + isFieldSliceAnnot->emplace("value"_cs, "true"); annotations->append(isFieldSliceAnnot); } @@ -741,33 +741,33 @@ void BFRuntimeGenerator::addMatchTables(Util::JsonArray *tablesJson) const { if (needsPriority) { // DRV-3112 - Make key fields not mandatory, this allows user to use a // driver initialized default value (0). - addKeyField(keyJson, TD_DATA_MATCH_PRIORITY, "$MATCH_PRIORITY", false /* mandatory */, - "Exact", makeType("uint32")); + addKeyField(keyJson, TD_DATA_MATCH_PRIORITY, "$MATCH_PRIORITY"_cs, + false /* mandatory */, "Exact"_cs, makeType("uint32"_cs)); } - tableJson->emplace("key", keyJson); + tableJson->emplace("key"_cs, keyJson); auto *dataJson = new Util::JsonArray(); // will be used as an offset for other P4-dependent fields (e.g. direct // register fields). P4Id maxActionParamId = 0; - cstring tableType = tableJson->get("table_type")->to()->getString(); + cstring tableType = tableJson->get("table_type"_cs)->to()->getString(); if (tableType == "MatchAction_Direct") { - tableJson->emplace("action_specs", makeActionSpecs(table, &maxActionParamId)); + tableJson->emplace("action_specs"_cs, makeActionSpecs(table, &maxActionParamId)); } else if (tableType == "MatchAction_Indirect") { - auto *f = makeCommonDataField(TD_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID", - makeType("uint32"), false /* repeated */); + auto *f = makeCommonDataField(TD_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID"_cs, + makeType("uint32"_cs), false /* repeated */); addSingleton(dataJson, f, true /* mandatory */, false /* read-only */); } else if (tableType == "MatchAction_Indirect_Selector") { // action member id and selector group id are mutually-exclusive, so // we use a "oneof" here. auto *choicesDataJson = new Util::JsonArray(); - choicesDataJson->append(makeCommonDataField(TD_DATA_ACTION_MEMBER_ID, - "$ACTION_MEMBER_ID", makeType("uint32"), - false /* repeated */)); - choicesDataJson->append(makeCommonDataField(TD_DATA_SELECTOR_GROUP_ID, - "$SELECTOR_GROUP_ID", makeType("uint32"), - false /* repeated */)); + choicesDataJson->append( + makeCommonDataField(TD_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID"_cs, + makeType("uint32"_cs), false /* repeated */)); + choicesDataJson->append( + makeCommonDataField(TD_DATA_SELECTOR_GROUP_ID, "$SELECTOR_GROUP_ID"_cs, + makeType("uint32"_cs), false /* repeated */)); addOneOf(dataJson, choicesDataJson, true /* mandatory */, false /* read-only */); } else { BUG("Invalid table type '%1%'", tableType); @@ -796,20 +796,21 @@ void BFRuntimeGenerator::addMatchTables(Util::JsonArray *tablesJson) const { operationsJson->append("UpdateHitState"); attributesJson->append("IdleTimeout"); - auto *fEntryTTL = makeCommonDataField( - TD_DATA_ENTRY_TTL, "$ENTRY_TTL", - makeType("uint32", 0 /* default TTL -> ageing disabled */), false /* repeated */); - auto *fEntryHitState = makeCommonDataField(TD_DATA_ENTRY_HIT_STATE, "$ENTRY_HIT_STATE", - makeTypeEnum({"ENTRY_IDLE", "ENTRY_ACTIVE"}), - false /* repeated */); + auto *fEntryTTL = + makeCommonDataField(TD_DATA_ENTRY_TTL, "$ENTRY_TTL"_cs, + makeType("uint32"_cs, 0 /* default TTL -> ageing disabled */), + false /* repeated */); + auto *fEntryHitState = makeCommonDataField( + TD_DATA_ENTRY_HIT_STATE, "$ENTRY_HIT_STATE"_cs, + makeTypeEnum({"ENTRY_IDLE"_cs, "ENTRY_ACTIVE"_cs}), false /* repeated */); addSingleton(dataJson, fEntryHitState, false /* mandatory */, false /* read-only */); if (!pollModeOnly) addSingleton(dataJson, fEntryTTL, false /* mandatory */, false /* read-only */); } - tableJson->emplace("data", dataJson); - tableJson->emplace("supported_operations", operationsJson); - tableJson->emplace("attributes", attributesJson); + tableJson->emplace("data"_cs, dataJson); + tableJson->emplace("supported_operations"_cs, operationsJson); + tableJson->emplace("attributes"_cs, attributesJson); tablesJson->append(tableJson); } @@ -850,10 +851,10 @@ void BFRuntimeGenerator::addRegisters(Util::JsonArray *tablesJson) const { const Util::JsonObject *BFRuntimeGenerator::genSchema() const { auto *json = new Util::JsonObject(); - json->emplace("schema_version", cstring("1.0.0")); + json->emplace("schema_version"_cs, "1.0.0"_cs); auto *tablesJson = new Util::JsonArray(); - json->emplace("tables", tablesJson); + json->emplace("tables"_cs, tablesJson); addMatchTables(tablesJson); addActionProfs(tablesJson); @@ -862,7 +863,7 @@ const Util::JsonObject *BFRuntimeGenerator::genSchema() const { addRegisters(tablesJson); auto *learnFiltersJson = new Util::JsonArray(); - json->emplace("learn_filters", learnFiltersJson); + json->emplace("learn_filters"_cs, learnFiltersJson); addLearnFilters(learnFiltersJson); return json; diff --git a/control-plane/bfruntime.h b/control-plane/bfruntime.h index c12c6ff4f0..79935e9b24 100644 --- a/control-plane/bfruntime.h +++ b/control-plane/bfruntime.h @@ -55,7 +55,7 @@ static inline constexpr P4Id getIdPrefix(P4Id id) { return ((id >> 24) & 0xff); static inline Util::JsonObject *findJsonTable(Util::JsonArray *tablesJson, cstring tblName) { for (auto *t : *tablesJson) { auto *tblObj = t->to(); - auto tName = tblObj->get("name")->to()->getString(); + auto tName = tblObj->get("name"_cs)->to()->getString(); if (tName == tblName) { return tblObj; } @@ -67,7 +67,7 @@ static inline Util::JsonObject *transformAnnotation(const cstring &annotation) { auto *annotationJson = new Util::JsonObject(); // TODO(antonin): annotation string will need to be parsed so we can have it // in key/value format here. - annotationJson->emplace("name", annotation.escapeJson()); + annotationJson->emplace("name"_cs, annotation.escapeJson()); return annotationJson; } @@ -133,60 +133,60 @@ static inline const p4configv1::DirectMeter *findDirectMeter(const p4configv1::P static inline Util::JsonObject *makeType(cstring type) { auto *typeObj = new Util::JsonObject(); - typeObj->emplace("type", type); + typeObj->emplace("type"_cs, type); return typeObj; } template ::value, int>::type = 0> static inline Util::JsonObject *makeType(cstring type, T defaultValue) { auto *typeObj = new Util::JsonObject(); - typeObj->emplace("type", type); - typeObj->emplace("default_value", defaultValue); + typeObj->emplace("type"_cs, type); + typeObj->emplace("default_value"_cs, defaultValue); return typeObj; } static inline Util::JsonObject *makeTypeBool(std::optional defaultValue = std::nullopt) { auto *typeObj = new Util::JsonObject(); - typeObj->emplace("type", "bool"); - if (defaultValue != std::nullopt) typeObj->emplace("default_value", *defaultValue); + typeObj->emplace("type"_cs, "bool"); + if (defaultValue != std::nullopt) typeObj->emplace("default_value"_cs, *defaultValue); return typeObj; } static inline Util::JsonObject *makeTypeBytes(int width, std::optional defaultValue = std::nullopt) { auto *typeObj = new Util::JsonObject(); - typeObj->emplace("type", "bytes"); - typeObj->emplace("width", width); - if (defaultValue != std::nullopt) typeObj->emplace("default_value", *defaultValue); + typeObj->emplace("type"_cs, "bytes"); + typeObj->emplace("width"_cs, width); + if (defaultValue != std::nullopt) typeObj->emplace("default_value"_cs, *defaultValue); return typeObj; } static inline Util::JsonObject *makeTypeEnum(const std::vector &choices, std::optional defaultValue = std::nullopt) { auto *typeObj = new Util::JsonObject(); - typeObj->emplace("type", "string"); + typeObj->emplace("type"_cs, "string"); auto *choicesArray = new Util::JsonArray(); for (auto choice : choices) choicesArray->append(choice); - typeObj->emplace("choices", choicesArray); - if (defaultValue != std::nullopt) typeObj->emplace("default_value", *defaultValue); + typeObj->emplace("choices"_cs, choicesArray); + if (defaultValue != std::nullopt) typeObj->emplace("default_value"_cs, *defaultValue); return typeObj; } static inline void addSingleton(Util::JsonArray *dataJson, Util::JsonObject *dataField, bool mandatory, bool readOnly) { auto *singletonJson = new Util::JsonObject(); - singletonJson->emplace("mandatory", mandatory); - singletonJson->emplace("read_only", readOnly); - singletonJson->emplace("singleton", dataField); + singletonJson->emplace("mandatory"_cs, mandatory); + singletonJson->emplace("read_only"_cs, readOnly); + singletonJson->emplace("singleton"_cs, dataField); dataJson->append(singletonJson); } static inline void addOneOf(Util::JsonArray *dataJson, Util::JsonArray *choicesJson, bool mandatory, bool readOnly) { auto *oneOfJson = new Util::JsonObject(); - oneOfJson->emplace("mandatory", mandatory); - oneOfJson->emplace("read_only", readOnly); - oneOfJson->emplace("oneof", choicesJson); + oneOfJson->emplace("mandatory"_cs, mandatory); + oneOfJson->emplace("read_only"_cs, readOnly); + oneOfJson->emplace("oneof"_cs, choicesJson); dataJson->append(oneOfJson); } @@ -196,27 +196,25 @@ static inline std::optional transformMatchType( case p4configv1::MatchField_MatchType_UNSPECIFIED: return std::nullopt; case p4configv1::MatchField_MatchType_EXACT: - return cstring("Exact"); + return "Exact"_cs; case p4configv1::MatchField_MatchType_LPM: - return cstring("LPM"); + return "LPM"_cs; case p4configv1::MatchField_MatchType_TERNARY: - return cstring("Ternary"); + return "Ternary"_cs; case p4configv1::MatchField_MatchType_RANGE: - return cstring("Range"); + return "Range"_cs; case p4configv1::MatchField_MatchType_OPTIONAL: - return cstring("Optional"); + return "Optional"_cs; default: return std::nullopt; } } static inline std::optional transformOtherMatchType(std::string matchType) { - if (matchType == "atcam_partition_index") - return cstring("ATCAM"); - else if (matchType == "dleft_hash") - return cstring("DLEFT_HASH"); - else - return std::nullopt; + if (matchType == "atcam_partition_index") return "ATCAM"_cs; + if (matchType == "dleft_hash") return "DLEFT_HASH"_cs; + + return std::nullopt; } template @@ -253,7 +251,8 @@ class TypeSpecParser { const p4configv1::P4DataTypeSpec &typeSpec, cstring instanceType, cstring instanceName, const std::vector *fieldNames = nullptr, - cstring prefix = "", cstring suffix = "", P4Id idOffset = 1); + cstring prefix = cstring::empty, cstring suffix = cstring::empty, + P4Id idOffset = 1); iterator begin() { return fields.begin(); } const_iterator cbegin() { return fields.cbegin(); } @@ -424,8 +423,8 @@ class BFRuntimeGenerator { const p4configv1::P4DataTypeSpec &typeSpec, cstring instanceType, cstring instanceName, const std::vector *fieldNames = nullptr, - cstring prefix = "", cstring suffix = "", - P4Id idOffset = 1) const; + cstring prefix = cstring::empty, + cstring suffix = cstring::empty, P4Id idOffset = 1) const; static void addMeterDataFields(Util::JsonArray *dataJson, const Meter &meter); static Util::JsonObject *makeCommonDataField(P4Id id, cstring name, Util::JsonObject *type, diff --git a/control-plane/flattenHeader.cpp b/control-plane/flattenHeader.cpp index 5713423263..8494fcf4b8 100644 --- a/control-plane/flattenHeader.cpp +++ b/control-plane/flattenHeader.cpp @@ -50,9 +50,12 @@ void FlattenHeader::doFlatten(const IR::Type *type) { } } -cstring FlattenHeader::makeName(cstring sep) const { - cstring name = ""; - for (auto n : nameSegments) name += sep + n; +cstring FlattenHeader::makeName(std::string_view sep) const { + std::string name; + for (auto n : nameSegments) { + name += sep; + name += n; + } return name; } diff --git a/control-plane/flattenHeader.h b/control-plane/flattenHeader.h index 568dddf3ba..9736453411 100644 --- a/control-plane/flattenHeader.h +++ b/control-plane/flattenHeader.h @@ -40,7 +40,7 @@ class FlattenHeader { void doFlatten(const IR::Type *type); - cstring makeName(cstring sep) const; + cstring makeName(std::string_view sep) const; const IR::Annotations *mergeAnnotations() const; public: diff --git a/control-plane/p4RuntimeAnnotations.h b/control-plane/p4RuntimeAnnotations.h index 1a1e223b2f..9c1efd80c4 100644 --- a/control-plane/p4RuntimeAnnotations.h +++ b/control-plane/p4RuntimeAnnotations.h @@ -31,12 +31,12 @@ class ParseP4RuntimeAnnotations : public ParseAnnotations { : ParseAnnotations( "P4Runtime", false, { - PARSE("controller_header", StringLiteral), - PARSE_EMPTY("hidden"), - PARSE("id", Constant), - PARSE("brief", StringLiteral), - PARSE("description", StringLiteral), - PARSE_KV_LIST("platform_property"), + PARSE("controller_header"_cs, StringLiteral), + PARSE_EMPTY("hidden"_cs), + PARSE("id"_cs, Constant), + PARSE("brief"_cs, StringLiteral), + PARSE("description"_cs, StringLiteral), + PARSE_KV_LIST("platform_property"_cs), // These annotations are architecture-specific in theory, but // given that they are "reserved" by the P4Runtime // specification, I don't really have any qualms about adding @@ -50,10 +50,10 @@ class ParseP4RuntimeAnnotations : public ParseAnnotations { // ParseAnnotations instance, or 2) run a ParseAnnotations // pass "locally" (in this case on action profile instances // since these annotations are for them). - PARSE("max_group_size", Constant), - PARSE("selector_size_semantics", StringLiteral), - PARSE("max_member_weight", Constant), - {"p4runtime_translation", &ParseAnnotations::parseP4rtTranslationAnnotation}, + PARSE("max_group_size"_cs, Constant), + PARSE("selector_size_semantics"_cs, StringLiteral), + PARSE("max_member_weight"_cs, Constant), + {"p4runtime_translation"_cs, &ParseAnnotations::parseP4rtTranslationAnnotation}, }) {} }; diff --git a/control-plane/p4RuntimeArchHandler.cpp b/control-plane/p4RuntimeArchHandler.cpp index 7b7104da19..8c8466acff 100644 --- a/control-plane/p4RuntimeArchHandler.cpp +++ b/control-plane/p4RuntimeArchHandler.cpp @@ -94,7 +94,7 @@ int64_t getTableSize(const IR::P4Table *table) { // default table size. const int64_t defaultTableSize = P4V1::V1Model::instance.tableAttributes.defaultTableSize; - auto sizeProperty = table->properties->getProperty("size"); + auto sizeProperty = table->properties->getProperty("size"_cs); if (sizeProperty == nullptr) { return defaultTableSize; } diff --git a/control-plane/p4RuntimeArchHandler.h b/control-plane/p4RuntimeArchHandler.h index 440e0cd264..8c000d7c80 100644 --- a/control-plane/p4RuntimeArchHandler.h +++ b/control-plane/p4RuntimeArchHandler.h @@ -38,11 +38,14 @@ limitations under the License. #include "frontends/p4/methodInstance.h" #include "frontends/p4/typeMap.h" #include "ir/ir.h" +#include "lib/cstring.h" #include "lib/ordered_set.h" #include "typeSpecConverter.h" namespace P4 { +using namespace literals; + /** \addtogroup control_plane * @{ */ @@ -139,7 +142,7 @@ class P4RuntimeArchHandlerIface { /// Get control plane name for @block virtual cstring getControlPlaneName(const IR::Block *block) { auto decl = block->getContainer(); - return decl ? decl->controlPlaneName() : ""; + return decl ? decl->controlPlaneName() : cstring::empty; } /// Collects architecture-specific properties for @tableBlock in @symbols /// table. @@ -396,7 +399,7 @@ struct Counterlike { // Counter and meter externs refer to their unit as a "type"; this is // (confusingly) unrelated to the "type" field of a counter or meter in // P4Info. - auto unit = instance->getParameterValue("type"); + auto unit = instance->getParameterValue("type"_cs); if (!unit->is()) { ::error(ErrorType::ERR_INVALID, "%1% '%2%' has a unit type which is not an enum constant: %3%", @@ -457,7 +460,7 @@ struct Counterlike { return std::nullopt; } - auto unitArgument = instance.substitution.lookupByName("type")->expression; + auto unitArgument = instance.substitution.lookupByName("type"_cs)->expression; if (unitArgument == nullptr) { ::error(ErrorType::ERR_EXPECTED, "Direct %1% instance %2% should take a constructor argument", @@ -477,7 +480,7 @@ struct Counterlike { unit, Helpers::getTableSize(table), table->controlPlaneName(), - ""}; + cstring::empty}; } }; diff --git a/control-plane/p4RuntimeArchStandard.h b/control-plane/p4RuntimeArchStandard.h index 470461db3e..4bd40bfdd3 100644 --- a/control-plane/p4RuntimeArchStandard.h +++ b/control-plane/p4RuntimeArchStandard.h @@ -72,13 +72,13 @@ namespace Helpers { /// @ref CounterlikeTraits<> specialization for @ref CounterExtern for v1model template <> struct CounterlikeTraits> { - static const cstring name() { return "counter"; } + static const cstring name() { return "counter"_cs; } static const cstring directPropertyName() { return P4V1::V1Model::instance.tableAttributes.counters.name; } static const cstring typeName() { return P4V1::V1Model::instance.counter.name; } static const cstring directTypeName() { return P4V1::V1Model::instance.directCounter.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } static p4configv1::CounterSpec::Unit mapUnitName(const cstring name) { using p4configv1::CounterSpec; if (name == "packets") @@ -94,13 +94,13 @@ struct CounterlikeTraits> { template <> struct CounterlikeTraits> { - static const cstring name() { return "counter"; } + static const cstring name() { return "counter"_cs; } static const cstring directPropertyName() { return P4V1::V1Model::instance.tableAttributes.counters.name; } static const cstring typeName() { return P4V1::V1Model::instance.counter.name; } static const cstring directTypeName() { return P4V1::V1Model::instance.directCounter.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } static p4configv1::CounterSpec::Unit mapUnitName(const cstring name) { using p4configv1::CounterSpec; if (name == "packets") @@ -117,11 +117,11 @@ struct CounterlikeTraits> { /// @ref CounterlikeTraits<> specialization for @ref CounterExtern for PSA template <> struct CounterlikeTraits> { - static const cstring name() { return "counter"; } - static const cstring directPropertyName() { return "psa_direct_counter"; } - static const cstring typeName() { return "Counter"; } - static const cstring directTypeName() { return "DirectCounter"; } - static const cstring sizeParamName() { return "n_counters"; } + static const cstring name() { return "counter"_cs; } + static const cstring directPropertyName() { return "psa_direct_counter"_cs; } + static const cstring typeName() { return "Counter"_cs; } + static const cstring directTypeName() { return "DirectCounter"_cs; } + static const cstring sizeParamName() { return "n_counters"_cs; } static p4configv1::CounterSpec::Unit mapUnitName(const cstring name) { using p4configv1::CounterSpec; if (name == "PACKETS") @@ -140,11 +140,11 @@ struct CounterlikeTraits> { /// @ref CounterlikeTraits<> specialization for @ref CounterExtern for PNA template <> struct CounterlikeTraits> { - static const cstring name() { return "counter"; } - static const cstring directPropertyName() { return "pna_direct_counter"; } - static const cstring typeName() { return "Counter"; } - static const cstring directTypeName() { return "DirectCounter"; } - static const cstring sizeParamName() { return "n_counters"; } + static const cstring name() { return "counter"_cs; } + static const cstring directPropertyName() { return "pna_direct_counter"_cs; } + static const cstring typeName() { return "Counter"_cs; } + static const cstring directTypeName() { return "DirectCounter"_cs; } + static const cstring sizeParamName() { return "n_counters"_cs; } static p4configv1::CounterSpec::Unit mapUnitName(const cstring name) { using p4configv1::CounterSpec; if (name == "PACKETS") @@ -163,13 +163,13 @@ struct CounterlikeTraits> { /// @ref CounterlikeTraits<> specialization for @ref MeterExtern for v1model template <> struct CounterlikeTraits> { - static const cstring name() { return "meter"; } + static const cstring name() { return "meter"_cs; } static const cstring directPropertyName() { return P4V1::V1Model::instance.tableAttributes.meters.name; } static const cstring typeName() { return P4V1::V1Model::instance.meter.name; } static const cstring directTypeName() { return P4V1::V1Model::instance.directMeter.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } static p4configv1::MeterSpec::Unit mapUnitName(const cstring name) { using p4configv1::MeterSpec; if (name == "packets") @@ -183,13 +183,13 @@ struct CounterlikeTraits> { template <> struct CounterlikeTraits> { - static const cstring name() { return "meter"; } + static const cstring name() { return "meter"_cs; } static const cstring directPropertyName() { return P4V1::V1Model::instance.tableAttributes.meters.name; } static const cstring typeName() { return P4V1::V1Model::instance.meter.name; } static const cstring directTypeName() { return P4V1::V1Model::instance.directMeter.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } static p4configv1::MeterSpec::Unit mapUnitName(const cstring name) { using p4configv1::MeterSpec; if (name == "packets") @@ -204,11 +204,11 @@ struct CounterlikeTraits> { /// @ref CounterlikeTraits<> specialization for @ref MeterExtern for PSA template <> struct CounterlikeTraits> { - static const cstring name() { return "meter"; } - static const cstring directPropertyName() { return "psa_direct_meter"; } - static const cstring typeName() { return "Meter"; } - static const cstring directTypeName() { return "DirectMeter"; } - static const cstring sizeParamName() { return "n_meters"; } + static const cstring name() { return "meter"_cs; } + static const cstring directPropertyName() { return "psa_direct_meter"_cs; } + static const cstring typeName() { return "Meter"_cs; } + static const cstring directTypeName() { return "DirectMeter"_cs; } + static const cstring sizeParamName() { return "n_meters"_cs; } static p4configv1::MeterSpec::Unit mapUnitName(const cstring name) { using p4configv1::MeterSpec; if (name == "PACKETS") @@ -225,11 +225,11 @@ struct CounterlikeTraits> { /// @ref CounterlikeTraits<> specialization for @ref MeterExtern for PNA template <> struct CounterlikeTraits> { - static const cstring name() { return "meter"; } - static const cstring directPropertyName() { return "pna_direct_meter"; } - static const cstring typeName() { return "Meter"; } - static const cstring directTypeName() { return "DirectMeter"; } - static const cstring sizeParamName() { return "n_meters"; } + static const cstring name() { return "meter"_cs; } + static const cstring directPropertyName() { return "pna_direct_meter"_cs; } + static const cstring typeName() { return "Meter"_cs; } + static const cstring directTypeName() { return "DirectMeter"_cs; } + static const cstring sizeParamName() { return "n_meters"_cs; } static p4configv1::MeterSpec::Unit mapUnitName(const cstring name) { using p4configv1::MeterSpec; if (name == "PACKETS") @@ -308,38 +308,38 @@ struct ActionProfileTraits; template <> struct ActionProfileTraits { - static const cstring name() { return "action profile"; } + static const cstring name() { return "action profile"_cs; } static const cstring propertyName() { return P4V1::V1Model::instance.tableAttributes.tableImplementation.name; } static const cstring typeName() { return P4V1::V1Model::instance.action_profile.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } }; template <> struct ActionProfileTraits { - static const cstring name() { return "action profile"; } + static const cstring name() { return "action profile"_cs; } static const cstring propertyName() { return P4V1::V1Model::instance.tableAttributes.tableImplementation.name; } static const cstring typeName() { return P4V1::V1Model::instance.action_profile.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } }; template <> struct ActionProfileTraits { - static const cstring name() { return "action profile"; } - static const cstring propertyName() { return "psa_implementation"; } - static const cstring typeName() { return "ActionProfile"; } - static const cstring sizeParamName() { return "size"; } + static const cstring name() { return "action profile"_cs; } + static const cstring propertyName() { return "psa_implementation"_cs; } + static const cstring typeName() { return "ActionProfile"_cs; } + static const cstring sizeParamName() { return "size"_cs; } }; template <> struct ActionProfileTraits { - static const cstring name() { return "action profile"; } - static const cstring propertyName() { return "pna_implementation"; } - static const cstring typeName() { return "ActionProfile"; } - static const cstring sizeParamName() { return "size"; } + static const cstring name() { return "action profile"_cs; } + static const cstring propertyName() { return "pna_implementation"_cs; } + static const cstring typeName() { return "ActionProfile"_cs; } + static const cstring sizeParamName() { return "size"_cs; } }; /// Traits for the action selector extern, must be specialized for v1model and @@ -349,26 +349,26 @@ struct ActionSelectorTraits; template <> struct ActionSelectorTraits : public ActionProfileTraits { - static const cstring name() { return "action selector"; } + static const cstring name() { return "action selector"_cs; } static const cstring typeName() { return P4V1::V1Model::instance.action_selector.name; } }; template <> struct ActionSelectorTraits : public ActionProfileTraits { - static const cstring name() { return "action selector"; } + static const cstring name() { return "action selector"_cs; } static const cstring typeName() { return P4V1::V1Model::instance.action_selector.name; } }; template <> struct ActionSelectorTraits : public ActionProfileTraits { - static const cstring name() { return "action selector"; } - static const cstring typeName() { return "ActionSelector"; } + static const cstring name() { return "action selector"_cs; } + static const cstring typeName() { return "ActionSelector"_cs; } }; template <> struct ActionSelectorTraits : public ActionProfileTraits { - static const cstring name() { return "action selector"; } - static const cstring typeName() { return "ActionSelector"; } + static const cstring name() { return "action selector"_cs; } + static const cstring typeName() { return "ActionSelector"_cs; } }; /// Traits for the register extern, must be specialized for v1model and PSA. @@ -377,9 +377,9 @@ struct RegisterTraits; template <> struct RegisterTraits { - static const cstring name() { return "register"; } + static const cstring name() { return "register"_cs; } static const cstring typeName() { return P4V1::V1Model::instance.registers.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } // the index of the type parameter for the data stored in the register, in // the type parameter list of the extern type declaration static size_t dataTypeParamIdx() { return 0; } @@ -388,9 +388,9 @@ struct RegisterTraits { template <> struct RegisterTraits { - static const cstring name() { return "register"; } + static const cstring name() { return "register"_cs; } static const cstring typeName() { return P4V1::V1Model::instance.registers.name; } - static const cstring sizeParamName() { return "size"; } + static const cstring sizeParamName() { return "size"_cs; } // the index of the type parameter for the data stored in the register, in // the type parameter list of the extern type declaration static size_t dataTypeParamIdx() { return 0; } @@ -399,9 +399,9 @@ struct RegisterTraits { template <> struct RegisterTraits { - static const cstring name() { return "register"; } - static const cstring typeName() { return "Register"; } - static const cstring sizeParamName() { return "size"; } + static const cstring name() { return "register"_cs; } + static const cstring typeName() { return "Register"_cs; } + static const cstring sizeParamName() { return "size"_cs; } static size_t dataTypeParamIdx() { return 0; } // the index of the type parameter for the register index, in the type // parameter list of the extern type declaration. @@ -410,9 +410,9 @@ struct RegisterTraits { template <> struct RegisterTraits { - static const cstring name() { return "register"; } - static const cstring typeName() { return "Register"; } - static const cstring sizeParamName() { return "size"; } + static const cstring name() { return "register"_cs; } + static const cstring typeName() { return "Register"_cs; } + static const cstring sizeParamName() { return "size"_cs; } static size_t dataTypeParamIdx() { return 0; } // the index of the type parameter for the register index, in the type // parameter list of the extern type declaration. @@ -448,7 +448,7 @@ struct Register { CHECK_NULL(instance); auto declaration = instance->node->to(); - auto size = instance->getParameterValue("size")->to(); + auto size = instance->getParameterValue("size"_cs)->to(); if (!size->is()) { ::error(ErrorType::ERR_UNSUPPORTED, "Register '%1%' has a non-constant size: %2%", declaration, size); @@ -776,7 +776,7 @@ class P4RuntimeArchHandlerCommon : public P4RuntimeArchHandlerIface { }); profile->set_with_selector(actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR); profile->set_size(actionProfile.size); - auto maxGroupSizeAnnotation = actionProfile.annotations->getAnnotation("max_group_size"); + auto maxGroupSizeAnnotation = actionProfile.annotations->getAnnotation("max_group_size"_cs); if (maxGroupSizeAnnotation) { if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR) { auto maxGroupSizeConstant = @@ -793,7 +793,7 @@ class P4RuntimeArchHandlerCommon : public P4RuntimeArchHandlerIface { // By default, an action profile uses the SumOfWeights semantics. auto selectorSizeSemanticsAnnotation = - actionProfile.annotations->getAnnotation("selector_size_semantics"); + actionProfile.annotations->getAnnotation("selector_size_semantics"_cs); if (selectorSizeSemanticsAnnotation) { if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR) { auto selectorSizeSemantics = @@ -821,7 +821,7 @@ class P4RuntimeArchHandlerCommon : public P4RuntimeArchHandlerIface { // By default, an action profile uses the SumOfWeights semantics. auto maxMemberWeightAnnotation = - actionProfile.annotations->getAnnotation("max_member_weight"); + actionProfile.annotations->getAnnotation("max_member_weight"_cs); if (maxMemberWeightAnnotation) { if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR && profile->has_sum_of_members()) { @@ -1058,7 +1058,7 @@ class P4RuntimeArchHandlerPSAPNA : public P4RuntimeArchHandlerCommon { /// @return true if @table's 'psa_idle_timeout' property exists and is true. This /// indicates that @table supports entry ageing. static bool getSupportsTimeout(const IR::P4Table *table) { - auto timeout = table->properties->getProperty("psa_idle_timeout"); + auto timeout = table->properties->getProperty("psa_idle_timeout"_cs); if (timeout == nullptr) return false; diff --git a/control-plane/p4RuntimeSerializer.cpp b/control-plane/p4RuntimeSerializer.cpp index bf6d264521..32aef714f0 100644 --- a/control-plane/p4RuntimeSerializer.cpp +++ b/control-plane/p4RuntimeSerializer.cpp @@ -479,18 +479,20 @@ class P4RuntimeAnalyzer { // I considered using Protobuf reflection, but it didn't really make the // code less verbose, and it certainly didn't make it easier to read. - dupCnt += checkForDuplicatesOfSameType(p4Info->tables(), "table", &ids); - dupCnt += checkForDuplicatesOfSameType(p4Info->actions(), "action", &ids); - dupCnt += checkForDuplicatesOfSameType(p4Info->action_profiles(), "action profile", &ids); - dupCnt += checkForDuplicatesOfSameType(p4Info->counters(), "counter", &ids); - dupCnt += checkForDuplicatesOfSameType(p4Info->direct_counters(), "direct counter", &ids); - dupCnt += checkForDuplicatesOfSameType(p4Info->meters(), "meter", &ids); - dupCnt += checkForDuplicatesOfSameType(p4Info->direct_meters(), "direct meter", &ids); + dupCnt += checkForDuplicatesOfSameType(p4Info->tables(), "table"_cs, &ids); + dupCnt += checkForDuplicatesOfSameType(p4Info->actions(), "action"_cs, &ids); + dupCnt += + checkForDuplicatesOfSameType(p4Info->action_profiles(), "action profile"_cs, &ids); + dupCnt += checkForDuplicatesOfSameType(p4Info->counters(), "counter"_cs, &ids); + dupCnt += + checkForDuplicatesOfSameType(p4Info->direct_counters(), "direct counter"_cs, &ids); + dupCnt += checkForDuplicatesOfSameType(p4Info->meters(), "meter"_cs, &ids); + dupCnt += checkForDuplicatesOfSameType(p4Info->direct_meters(), "direct meter"_cs, &ids); dupCnt += checkForDuplicatesOfSameType(p4Info->controller_packet_metadata(), - "controller packet metadata", &ids); - dupCnt += checkForDuplicatesOfSameType(p4Info->value_sets(), "value set", &ids); - dupCnt += checkForDuplicatesOfSameType(p4Info->registers(), "register", &ids); - dupCnt += checkForDuplicatesOfSameType(p4Info->digests(), "digest", &ids); + "controller packet metadata"_cs, &ids); + dupCnt += checkForDuplicatesOfSameType(p4Info->value_sets(), "value set"_cs, &ids); + dupCnt += checkForDuplicatesOfSameType(p4Info->registers(), "register"_cs, &ids); + dupCnt += checkForDuplicatesOfSameType(p4Info->digests(), "digest"_cs, &ids); for (const auto &externType : p4Info->externs()) { dupCnt += checkForDuplicatesOfSameType(externType.instances(), @@ -601,7 +603,7 @@ class P4RuntimeAnalyzer { auto id = symbols.getId(P4RuntimeSymbolType::P4RT_CONTROLLER_HEADER(), name); auto annotations = type->to(); - auto controllerAnnotation = type->getAnnotation("controller_header"); + auto controllerAnnotation = type->getAnnotation("controller_header"_cs); CHECK_NULL(controllerAnnotation); auto nameConstant = controllerAnnotation->expr[0]->to(); @@ -683,8 +685,8 @@ class P4RuntimeAnalyzer { action_ref->set_id(id); addAnnotations(action_ref, action.annotations); // set action ref scope - auto isTableOnly = (action.annotations->getAnnotation("tableonly") != nullptr); - auto isDefaultOnly = (action.annotations->getAnnotation("defaultonly") != nullptr); + auto isTableOnly = (action.annotations->getAnnotation("tableonly"_cs) != nullptr); + auto isDefaultOnly = (action.annotations->getAnnotation("defaultonly"_cs) != nullptr); if (isTableOnly && isDefaultOnly) { ::error(ErrorType::ERR_INVALID, "Table '%1%' has an action reference ('%2%') which is annotated " @@ -1080,7 +1082,7 @@ class P4RuntimeEntriesConverter { } } - auto priorityAnnotation = e->getAnnotation("priority"); + auto priorityAnnotation = e->getAnnotation("priority"_cs); if (priorityAnnotation != nullptr) { ::warning(ErrorType::WARN_DEPRECATED, "The @priority annotation on %1% is not part of the P4 specification, " @@ -1527,34 +1529,28 @@ void P4RuntimeAPI::serializeEntriesTo(std::ostream *destination, P4RuntimeFormat static bool parseFileNames(cstring fileNameVector, std::vector &files, std::vector &formats) { - for (auto current = fileNameVector; current;) { + // FIXME: Logic here shoule be refactored. Lots of cstring copies everywhere. + for (auto current = fileNameVector; !current.isNullOrEmpty();) { cstring name = current; const char *comma = current.find(','); if (comma != nullptr) { name = current.before(comma); - current = comma + 1; + current = cstring(comma + 1); } else { - current = cstring(); + current = cstring::empty; } files.push_back(name); - if (cstring suffix = name.findlast('.')) { - if (suffix == ".json") { - formats.push_back(P4::P4RuntimeFormat::JSON); - } else if (suffix == ".bin") { - formats.push_back(P4::P4RuntimeFormat::BINARY); - } else if (suffix == ".txtpb") { - formats.push_back(P4::P4RuntimeFormat::TEXT_PROTOBUF); - } else if (suffix == ".txt") { - ::warning(ErrorType::WARN_DEPRECATED, - ".txt format is being deprecated; use .txtpb instead"); - formats.push_back(P4::P4RuntimeFormat::TEXT); - } else { - ::error(ErrorType::ERR_UNKNOWN, - "%1%: Could not detect p4runtime info file format from file suffix %2%", - name, suffix); - return false; - } + if (name.endsWith(".json")) { + formats.push_back(P4::P4RuntimeFormat::JSON); + } else if (name.endsWith(".bin")) { + formats.push_back(P4::P4RuntimeFormat::BINARY); + } else if (name.endsWith(".txtpb")) { + formats.push_back(P4::P4RuntimeFormat::TEXT_PROTOBUF); + } else if (name.endsWith(".txt")) { + ::warning(ErrorType::WARN_DEPRECATED, + ".txt format is being deprecated; use .txtpb instead"); + formats.push_back(P4::P4RuntimeFormat::TEXT); } else { ::error(ErrorType::ERR_UNKNOWN, "%1%: unknown file kind; known suffixes are .bin, .txt, .json, and .txtpb", @@ -1632,10 +1628,10 @@ void P4RuntimeSerializer::serializeP4RuntimeIfRequired(const P4RuntimeAPI &p4Run } P4RuntimeSerializer::P4RuntimeSerializer() { - registerArch("v1model", new ControlPlaneAPI::Standard::V1ModelArchHandlerBuilder()); - registerArch("psa", new ControlPlaneAPI::Standard::PSAArchHandlerBuilder()); - registerArch("pna", new ControlPlaneAPI::Standard::PNAArchHandlerBuilder()); - registerArch("ubpf", new ControlPlaneAPI::Standard::UBPFArchHandlerBuilder()); + registerArch("v1model"_cs, new ControlPlaneAPI::Standard::V1ModelArchHandlerBuilder()); + registerArch("psa"_cs, new ControlPlaneAPI::Standard::PSAArchHandlerBuilder()); + registerArch("pna"_cs, new ControlPlaneAPI::Standard::PNAArchHandlerBuilder()); + registerArch("ubpf"_cs, new ControlPlaneAPI::Standard::UBPFArchHandlerBuilder()); } P4RuntimeSerializer *P4RuntimeSerializer::get() { @@ -1649,7 +1645,7 @@ cstring P4RuntimeSerializer::resolveArch(const CompilerOptions &options) { } else if (options.arch != nullptr) { return options.arch; } else { - return "v1model"; + return "v1model"_cs; } } diff --git a/control-plane/p4RuntimeSerializer.h b/control-plane/p4RuntimeSerializer.h index e78040dfb2..a50fc42d28 100644 --- a/control-plane/p4RuntimeSerializer.h +++ b/control-plane/p4RuntimeSerializer.h @@ -48,6 +48,8 @@ class CompilerOptions; namespace P4 { +using namespace literals; + /// A P4 program's control-plane API, represented in terms of P4Runtime's data /// structures. Can be inspected or serialized. struct P4RuntimeAPI { @@ -139,7 +141,7 @@ class P4RuntimeSerializer { /// Calls @ref P4RuntimeSerializer::generateP4Runtime on the @ref /// P4RuntimeSerializer singleton. -P4RuntimeAPI generateP4Runtime(const IR::P4Program *program, cstring arch = "v1model"); +P4RuntimeAPI generateP4Runtime(const IR::P4Program *program, cstring arch = "v1model"_cs); /// Calls @ref P4RuntimeSerializer::serializeP4RuntimeIfRequired on the @ref /// P4RuntimeSerializer singleton. diff --git a/control-plane/p4RuntimeSymbolTable.cpp b/control-plane/p4RuntimeSymbolTable.cpp index 555ca6dd30..3249c80c26 100644 --- a/control-plane/p4RuntimeSymbolTable.cpp +++ b/control-plane/p4RuntimeSymbolTable.cpp @@ -26,13 +26,13 @@ namespace P4 { namespace ControlPlaneAPI { bool isControllerHeader(const IR::Type_Header *type) { - return type->getAnnotation("controller_header") != nullptr; + return type->getAnnotation("controller_header"_cs) != nullptr; } -bool isHidden(const IR::Node *node) { return node->getAnnotation("hidden") != nullptr; } +bool isHidden(const IR::Node *node) { return node->getAnnotation("hidden"_cs) != nullptr; } std::optional getIdAnnotation(const IR::IAnnotated *node) { - const auto *idAnnotation = node->getAnnotation("id"); + const auto *idAnnotation = node->getAnnotation("id"_cs); if (idAnnotation == nullptr) { return std::nullopt; } diff --git a/control-plane/typeSpecConverter.cpp b/control-plane/typeSpecConverter.cpp index d771f22a2c..875953bcd0 100644 --- a/control-plane/typeSpecConverter.cpp +++ b/control-plane/typeSpecConverter.cpp @@ -41,7 +41,7 @@ namespace P4 { namespace ControlPlaneAPI { bool hasTranslationAnnotation(const IR::Type *type, TranslationAnnotation *payload) { - auto ann = type->getAnnotation("p4runtime_translation"); + auto ann = type->getAnnotation("p4runtime_translation"_cs); if (!ann) return false; // Syntax: @pruntime_translation(, ). diff --git a/frontends/common/applyOptionsPragmas.cpp b/frontends/common/applyOptionsPragmas.cpp index dc67166067..1ea9288c92 100644 --- a/frontends/common/applyOptionsPragmas.cpp +++ b/frontends/common/applyOptionsPragmas.cpp @@ -86,11 +86,11 @@ std::optional P4COptionPragmaParser::pa cstring diagnosticOption; if (diagnosticAction->value == "disable") { - diagnosticOption = "--Wdisable="; + diagnosticOption = "--Wdisable="_cs; } else if (diagnosticAction->value == "warn") { - diagnosticOption = "--Wwarn="; + diagnosticOption = "--Wwarn="_cs; } else if (diagnosticAction->value == "error") { - diagnosticOption = "--Werror="; + diagnosticOption = "--Werror="_cs; } else { ::warning(ErrorType::WARN_MISMATCH, "@diagnostic's second argument must be 'disable', " diff --git a/frontends/common/constantFolding.h b/frontends/common/constantFolding.h index 832d4be2ff..8a53623926 100644 --- a/frontends/common/constantFolding.h +++ b/frontends/common/constantFolding.h @@ -23,6 +23,8 @@ limitations under the License. namespace P4 { +using namespace literals; + /// A policy for constant folding that allows customization of the folding. /// Currently we only have hook for customizing IR::PathExpression, but more can be added. /// Each hook takes a visitor and a node and is called from the visitor's preorder function on that @@ -163,7 +165,7 @@ class DoConstantFolding : public Transform { const IR::Node *preorder(IR::ArrayIndex *e) override; const IR::Node *preorder(IR::SwitchCase *c) override; const IR::BlockStatement *preorder(IR::BlockStatement *bs) override { - if (bs->annotations->getSingle("disable_optimization")) prune(); + if (bs->annotations->getSingle("disable_optimization"_cs)) prune(); return bs; } }; diff --git a/frontends/common/options.cpp b/frontends/common/options.cpp index b6edfade15..85efbe60c5 100644 --- a/frontends/common/options.cpp +++ b/frontends/common/options.cpp @@ -23,8 +23,9 @@ CompilerOptions::CompilerOptions() : ParserOptions() { "--excludeFrontendPasses", "pass1[,pass2]", [this](const char *arg) { excludeFrontendPasses = true; + // FIXME: just split into string_view's auto copy = strdup(arg); - while (auto pass = strsep(©, ",")) passesToExcludeFrontend.push_back(pass); + while (auto pass = strsep(©, ",")) passesToExcludeFrontend.push_back(cstring(pass)); return true; }, "Exclude passes from frontend passes whose name is equal\n" @@ -44,7 +45,7 @@ CompilerOptions::CompilerOptions() : ParserOptions() { [this](const char *arg) { excludeMidendPasses = true; auto copy = strdup(arg); - while (auto pass = strsep(©, ",")) passesToExcludeMidend.push_back(pass); + while (auto pass = strsep(©, ",")) passesToExcludeMidend.push_back(cstring(pass)); return true; }, "Exclude passes from midend passes whose name is equal\n" @@ -52,7 +53,7 @@ CompilerOptions::CompilerOptions() : ParserOptions() { registerOption( "--toJSON", "file", [this](const char *arg) { - dumpJsonFile = arg; + dumpJsonFile = cstring(arg); return true; }, "Dump the compiler IR after the midend as JSON in the specified file."); @@ -73,14 +74,14 @@ CompilerOptions::CompilerOptions() : ParserOptions() { registerOption( "--pp", "file", [this](const char *arg) { - prettyPrintFile = arg; + prettyPrintFile = cstring(arg); return true; }, "Pretty-print the program in the specified file."); registerOption( "--p4runtime-file", "file", [this](const char *arg) { - p4RuntimeFile = arg; + p4RuntimeFile = cstring(arg); return true; }, "Write a P4Runtime control plane API description to the specified " @@ -89,7 +90,7 @@ CompilerOptions::CompilerOptions() : ParserOptions() { registerOption( "--p4runtime-entries-file", "file", [this](const char *arg) { - p4RuntimeEntriesFile = arg; + p4RuntimeEntriesFile = cstring(arg); return true; }, "Write static table entries as a P4Runtime WriteRequest message" @@ -98,7 +99,7 @@ CompilerOptions::CompilerOptions() : ParserOptions() { registerOption( "--p4runtime-files", "filelist", [this](const char *arg) { - p4RuntimeFiles = arg; + p4RuntimeFiles = cstring(arg); return true; }, "Write the P4Runtime control plane API description to the specified\n" @@ -107,7 +108,7 @@ CompilerOptions::CompilerOptions() : ParserOptions() { registerOption( "--p4runtime-entries-files", "files", [this](const char *arg) { - p4RuntimeEntriesFiles = arg; + p4RuntimeEntriesFiles = cstring(arg); return true; }, "Write static table entries as a P4Runtime WriteRequest message\n" @@ -134,14 +135,14 @@ CompilerOptions::CompilerOptions() : ParserOptions() { registerOption( "--target", "target", [this](const char *arg) { - target = arg; + target = cstring(arg); return true; }, "Compile for the specified target device."); registerOption( "--arch", "arch", [this](const char *arg) { - arch = arg; + arch = cstring(arg); return true; }, "Compile for the specified architecture."); diff --git a/frontends/common/parser_options.cpp b/frontends/common/parser_options.cpp index fe451240e9..1d5e502a52 100644 --- a/frontends/common/parser_options.cpp +++ b/frontends/common/parser_options.cpp @@ -44,6 +44,8 @@ const char *p4_14includePath = CONFIG_PKGDATADIR "/p4_14include"; const char *ParserOptions::defaultMessage = "Compile a P4 program"; +using namespace P4::literals; + ParserOptions::ParserOptions() : Util::Options(defaultMessage) { registerOption( "--help", nullptr, @@ -180,7 +182,7 @@ ParserOptions::ParserOptions() : Util::Options(defaultMessage) { "--disable-annotations", "annotations", [this](const char *arg) { auto copy = strdup(arg); - while (auto name = strsep(©, ",")) disabledAnnotations.insert(name); + while (auto name = strsep(©, ",")) disabledAnnotations.insert(cstring(name)); return true; }, "Specify a (comma separated) list of annotations that should be " @@ -277,7 +279,7 @@ ParserOptions::ParserOptions() : Util::Options(defaultMessage) { "--top4", "pass1[,pass2]", [this](const char *arg) { auto copy = strdup(arg); - while (auto pass = strsep(©, ",")) top4.push_back(pass); + while (auto pass = strsep(©, ",")) top4.push_back(cstring(pass)); return true; }, "[Compiler debugging] Dump the P4 representation after\n" @@ -286,7 +288,7 @@ ParserOptions::ParserOptions() : Util::Options(defaultMessage) { registerOption( "--dump", "folder", [this](const char *arg) { - dumpFolder = arg; + dumpFolder = cstring(arg); return true; }, "[Compiler debugging] Folder where P4 programs are dumped\n"); @@ -308,7 +310,7 @@ ParserOptions::ParserOptions() : Util::Options(defaultMessage) { registerOption( "--doNotEmitIncludes", "condition", [this](const char *arg) { - noIncludes = arg; + noIncludes = cstring(arg); return true; }, "[Compiler debugging] If true do not generate #include statements\n"); @@ -329,7 +331,7 @@ void ParserOptions::setInputFile() { usage(); exit(1); } else { - file = remainingOptions.at(0); + file = cstring(remainingOptions.at(0)); } } @@ -358,7 +360,7 @@ bool ParserOptions::searchForIncludePath(const char *&includePathOut, snprintf(buffer, sizeof(buffer), "%s", exename); if (char *p = strrchr(buffer, '/')) { ++p; - exe_name = p; + exe_name = cstring(p); for (auto path : userSpecifiedPaths) { snprintf(p, buffer + sizeof(buffer) - p, "%s", path.c_str()); @@ -373,10 +375,10 @@ bool ParserOptions::searchForIncludePath(const char *&includePathOut, } std::vector *ParserOptions::process(int argc, char *const argv[]) { - searchForIncludePath(p4includePath, {"p4include", "../p4include", "../../p4include"}, + searchForIncludePath(p4includePath, {"p4include"_cs, "../p4include"_cs, "../../p4include"_cs}, exename(argv[0])); searchForIncludePath(p4_14includePath, - {"p4_14include", "../p4_14include", "../../p4_14include"}, + {"p4_14include"_cs, "../p4_14include"_cs, "../../p4_14include"_cs}, exename(argv[0])); auto remainingOptions = Util::Options::process(argc, argv); @@ -387,15 +389,15 @@ std::vector *ParserOptions::process(int argc, char *const argv[]) void ParserOptions::validateOptions() const {} const char *ParserOptions::getIncludePath() { - cstring path = ""; + cstring path = cstring::empty; // the p4c driver sets environment variables for include // paths. check the environment and add these to the command // line for the preprocessor char *driverP4IncludePath = isv1() ? getenv("P4C_14_INCLUDE_PATH") : getenv("P4C_16_INCLUDE_PATH"); - if (driverP4IncludePath != nullptr) path += (cstring(" -I") + cstring(driverP4IncludePath)); - path += cstring(" -I") + (isv1() ? p4_14includePath : p4includePath); - if (!isv1()) path += cstring(" -I") + p4includePath + cstring("/bmv2"); + if (driverP4IncludePath != nullptr) path += (" -I"_cs + cstring(driverP4IncludePath)); + path += " -I"_cs + (isv1() ? p4_14includePath : p4includePath); + if (!isv1()) path += " -I"_cs + p4includePath + "/bmv2"_cs; return path.c_str(); } @@ -403,7 +405,7 @@ FILE *ParserOptions::preprocess() { FILE *in = nullptr; if (file == "-") { - file = ""; + file = ""_cs; in = stdin; } else { #ifdef __clang__ @@ -412,10 +414,10 @@ FILE *ParserOptions::preprocess() { std::string cmd("cpp"); #endif - if (file == nullptr) file = ""; - if (file.find(' ')) file = cstring("\"") + file + "\""; - cmd += cstring(" -C -undef -nostdinc -x assembler-with-cpp") + " " + preprocessor_options + - getIncludePath() + " " + file; + if (file == nullptr) file = cstring::empty; + if (file.find(' ')) file = "\""_cs + file + "\""_cs; + cmd += " -C -undef -nostdinc -x assembler-with-cpp " + preprocessor_options.string() + + getIncludePath() + " " + file.string(); if (Log::verbose()) std::cerr << "Invoking preprocessor " << std::endl << cmd << std::endl; in = popen(cmd.c_str(), "r"); @@ -483,11 +485,12 @@ void ParserOptions::dumpPass(const char *manager, unsigned seq, const char *pass exit(1); } if (match) { + // FIXME: switch to sane printing via abseil char buf[16]; snprintf(buf, sizeof(buf), "-%04zu-", ++dump_uid); cstring suffix = cstring(buf) + name; cstring filename = file; - if (filename == "-") filename = "tmp.p4"; + if (filename == "-") filename = "tmp.p4"_cs; cstring fileName = makeFileName(dumpFolder, filename, suffix); std::unique_ptr stream{openFile(fileName, true)}; @@ -531,7 +534,7 @@ const P4CConfiguration &P4CContext::getConfig() { bool P4CContext::isRecognizedDiagnostic(cstring diagnostic) { static const std::unordered_set recognizedDiagnostics = { - "uninitialized_out_param", "uninitialized_use", "unknown_diagnostic"}; + "uninitialized_out_param"_cs, "uninitialized_use"_cs, "unknown_diagnostic"_cs}; return recognizedDiagnostics.count(diagnostic); } diff --git a/frontends/common/parser_options.h b/frontends/common/parser_options.h index 893a63933c..1da48b0dee 100644 --- a/frontends/common/parser_options.h +++ b/frontends/common/parser_options.h @@ -61,7 +61,7 @@ class ParserOptions : public Util::Options { // Which language to compile FrontendVersion langVersion = FrontendVersion::P4_16; // options to pass to preprocessor - cstring preprocessor_options = ""; + cstring preprocessor_options = cstring::empty; // file to compile (- for stdin) cstring file = nullptr; // if true preprocess only @@ -73,7 +73,7 @@ class ParserOptions : public Util::Options { // substrings matched against pass names std::vector top4; // debugging dumps of programs written in this folder - cstring dumpFolder = "."; + cstring dumpFolder = cstring::literal("."); // If false, optimization of callee parsers (subparsers) inlining is disabled. bool optimizeParserInlining = false; // Expect that the only remaining argument is the input file. @@ -145,7 +145,7 @@ class P4CContext : public BaseCompileContext { } /// Set the action to take for the given diagnostic. - void setDiagnosticAction(cstring diagnostic, DiagnosticAction action) { + void setDiagnosticAction(std::string_view diagnostic, DiagnosticAction action) { errorReporter().setDiagnosticAction(diagnostic, action); } diff --git a/frontends/common/programMap.h b/frontends/common/programMap.h index 4f3e661538..85ea0a2835 100644 --- a/frontends/common/programMap.h +++ b/frontends/common/programMap.h @@ -30,7 +30,7 @@ class ProgramMap : public IHasDbPrint { const IR::P4Program *fake = new IR::P4Program(); const IR::P4Program *program = nullptr; cstring mapKind; - explicit ProgramMap(cstring kind) : mapKind(kind) {} + explicit ProgramMap(std::string_view kind) : mapKind(kind) {} virtual ~ProgramMap() {} public: diff --git a/frontends/common/resolveReferences/referenceMap.cpp b/frontends/common/resolveReferences/referenceMap.cpp index 68469ce9b3..a9ab45663f 100644 --- a/frontends/common/resolveReferences/referenceMap.cpp +++ b/frontends/common/resolveReferences/referenceMap.cpp @@ -93,7 +93,7 @@ void ReferenceMap::dbprint(std::ostream &out) const { for (auto e : pathToDeclaration) out << dbp(e.first) << "->" << dbp(e.second) << std::endl; } -cstring ReferenceMap::newName(cstring base) { +cstring ReferenceMap::newName(std::string_view base) { // Maybe in the future we'll maintain information with per-scope identifiers, // but today we are content to generate globally-unique identifiers. @@ -102,17 +102,20 @@ cstring ReferenceMap::newName(cstring base) { // This will not impact correctness. unsigned len = base.size(); const char digits[] = "0123456789"; - const char *s = base.c_str(); + const char *s = base.data(); while (len > 0 && strchr(digits, s[len - 1])) len--; if (len > 0 && base[len - 1] == '_') base = base.substr(0, len - 1); - cstring name = base; - if (usedNames.count(name)) name = cstring::make_unique(usedNames, name, usedNames[base], '_'); - usedNames.emplace(name, 0); + cstring name(base); + auto [it, inserted] = usedNames.emplace(name, 0); + if (!inserted) { + name = cstring::make_unique(usedNames, name, it->second, '_'); + usedNames.emplace(name, 0); + } return name; } -cstring MinimalNameGenerator::newName(cstring base) { +cstring MinimalNameGenerator::newName(std::string_view base) { // Maybe in the future we'll maintain information with per-scope identifiers, // but today we are content to generate globally-unique identifiers. @@ -121,13 +124,16 @@ cstring MinimalNameGenerator::newName(cstring base) { // This will not impact correctness. unsigned len = base.size(); const char digits[] = "0123456789"; - const char *s = base.c_str(); + const char *s = base.data(); while (len > 0 && strchr(digits, s[len - 1])) len--; if (len > 0 && base[len - 1] == '_') base = base.substr(0, len - 1); - cstring name = base; - if (usedNames.count(name)) name = cstring::make_unique(usedNames, name, usedNames[base], '_'); - usedNames.emplace(name, 0); + cstring name(base); + auto [it, inserted] = usedNames.emplace(name, 0); + if (!inserted) { + name = cstring::make_unique(usedNames, name, it->second, '_'); + usedNames.emplace(name, 0); + } return name; } diff --git a/frontends/common/resolveReferences/referenceMap.h b/frontends/common/resolveReferences/referenceMap.h index c07e2afeab..3c462d5c66 100644 --- a/frontends/common/resolveReferences/referenceMap.h +++ b/frontends/common/resolveReferences/referenceMap.h @@ -28,7 +28,7 @@ namespace P4 { class NameGenerator { public: - virtual cstring newName(cstring base) = 0; + virtual cstring newName(std::string_view base) = 0; }; // replacement for ReferenceMap NameGenerator to make it easier to remove uses of refMap @@ -48,7 +48,7 @@ class MinimalNameGenerator : public NameGenerator, public Inspector { } /// Generate a name from @p base that does not appear in usedNames. - cstring newName(cstring base) override; + cstring newName(std::string_view base) override; }; // FIXME -- temp common base class to allow use of ReferenceMap or ResolutionContext @@ -105,7 +105,7 @@ class ReferenceMap final : public ProgramMap, public NameGenerator, public Decla void setAnyOrder(bool anyOrder) { this->isv1 = anyOrder; } /// Generate a name from @p base that fresh for the program. - cstring newName(cstring base) override; + cstring newName(std::string_view base) override; /// Clear the reference map void clear(); diff --git a/frontends/p4-14/header_type.cpp b/frontends/p4-14/header_type.cpp index fb96a129ff..d2d57e8d67 100644 --- a/frontends/p4-14/header_type.cpp +++ b/frontends/p4-14/header_type.cpp @@ -16,20 +16,22 @@ limitations under the License. #include "header_type.h" +using namespace P4::literals; + bool HeaderTypeMaxLengthCalculator::preorder(IR::Type_StructLike *hdr_type) { IR::Annotations *annot = nullptr; - auto *max_length = hdr_type->getAnnotation("max_length"); + auto *max_length = hdr_type->getAnnotation("max_length"_cs); if (!max_length) { unsigned len = 0; for (auto field : hdr_type->fields) len += field->type->width_bits(); - max_length = new IR::Annotation("max_length", len); + max_length = new IR::Annotation("max_length"_cs, len); if (!annot) annot = hdr_type->annotations->clone(); annot->annotations.push_back(max_length); } - auto *length = hdr_type->getAnnotation("length"); + auto *length = hdr_type->getAnnotation("length"_cs); if (!length) { if (!annot) annot = hdr_type->annotations->clone(); - length = new IR::Annotation("length", max_length->expr); + length = new IR::Annotation("length"_cs, max_length->expr); annot->annotations.push_back(length); } if (annot) hdr_type->annotations = annot; diff --git a/frontends/p4-14/typecheck.cpp b/frontends/p4-14/typecheck.cpp index 6cdac075e1..c7226f56b8 100644 --- a/frontends/p4-14/typecheck.cpp +++ b/frontends/p4-14/typecheck.cpp @@ -19,6 +19,8 @@ limitations under the License. #include "ir/dump.h" #include "lib/log.h" +using namespace P4::literals; + /// P4-14 (v1.0 and v1.1) type checking algorithm /// Initial type setting based on immediate context: /// - replace named reference to ActionParams in the bodies of ActionFunctions with the @@ -181,8 +183,8 @@ class TypeCheck::AssignInitialTypes : public Transform { auto prim = getParent(); // context is a primitive call static const std::set header_prims = { // primitives that operate on headers or header stacks - "add_header", "copy_header", "emit", "extract", - "push", "pop", "remove_header", "valid"}; + "add_header"_cs, "copy_header"_cs, "emit"_cs, "extract"_cs, + "push"_cs, "pop"_cs, "remove_header"_cs, "valid"_cs}; if (hdr && (!obj || preferHdr || (prim && header_prims.count(prim->name)))) { // prefer header to object only if in a simple member reference or in a // header stack reference or a primitive that is valid on headers. diff --git a/frontends/p4/actionsInlining.cpp b/frontends/p4/actionsInlining.cpp index 5dca99a45a..d54f5e5983 100644 --- a/frontends/p4/actionsInlining.cpp +++ b/frontends/p4/actionsInlining.cpp @@ -86,7 +86,7 @@ const IR::Node *ActionsInliner::preorder(IR::MethodCallStatement *statement) { // evaluate in and inout parameters in order for (auto param : callee->parameters->parameters) { auto argument = substitution.lookup(param); - cstring newName = refMap->newName(param->name); + cstring newName = refMap->newName(param->name.name.string_view()); paramRename.emplace(param, newName); if (param->direction == IR::Direction::In || param->direction == IR::Direction::InOut) { auto vardecl = new IR::Declaration_Variable(newName, param->annotations, param->type, diff --git a/frontends/p4/alias.h b/frontends/p4/alias.h index 7c87ac4dea..bdd25c729a 100644 --- a/frontends/p4/alias.h +++ b/frontends/p4/alias.h @@ -33,6 +33,8 @@ limitations under the License. namespace P4 { +using namespace literals; + /// This class represents the path to a location. /// Given a struct S { bit a; bit b; } and a variable S x; /// a path can be x.a, or just x. An array index is represented as a @@ -157,7 +159,7 @@ class ReadsWrites : public Inspector { result = e->append(Util::toString(index)); } else { auto index = ::get(rw, expression->right); - result = e->append("*")->join(index); + result = e->append("*"_cs)->join(index); } rw.emplace(expression, result); } diff --git a/frontends/p4/callGraph.cpp b/frontends/p4/callGraph.cpp index 2e5983c996..1800b9da76 100644 --- a/frontends/p4/callGraph.cpp +++ b/frontends/p4/callGraph.cpp @@ -1,9 +1,10 @@ #include "callGraph.h" namespace P4 { +using namespace literals; cstring cgMakeString(cstring s) { return s; } -cstring cgMakeString(char c) { return cstring("") + c; } +cstring cgMakeString(char c) { return ""_cs + c; } cstring cgMakeString(const IR::Node *node) { return node->toString(); } cstring cgMakeString(const IR::INode *node) { return node->toString(); } diff --git a/frontends/p4/callGraph.h b/frontends/p4/callGraph.h index 0da754f633..d457622ce5 100644 --- a/frontends/p4/callGraph.h +++ b/frontends/p4/callGraph.h @@ -49,7 +49,7 @@ class CallGraph { ordered_set nodes; // all nodes; do not modify this directly typedef typename ordered_map *>::const_iterator const_iterator; - explicit CallGraph(cstring name) : name(name) {} + explicit CallGraph(std::string_view name) : name(name) {} const cstring &getName() const { return name; } diff --git a/frontends/p4/commonInlining.h b/frontends/p4/commonInlining.h index a8623e4d77..69cb16f29b 100644 --- a/frontends/p4/commonInlining.h +++ b/frontends/p4/commonInlining.h @@ -32,6 +32,8 @@ limitations under the License. namespace P4 { +using namespace literals; + template class SimpleCallInfo : public IHasDbPrint { // Callable can be P4Action, Function, P4Control, P4Parser @@ -164,7 +166,7 @@ class InlineDriver : public Visitor { : toInline(toInline), inliner(inliner) { CHECK_NULL(toInline); CHECK_NULL(inliner); - setName((cstring("InlineDriver_") + cstring(inliner->name())).c_str()); + setName(("InlineDriver_"_cs + cstring(inliner->name())).c_str()); } const IR::Node *apply_visitor(const IR::Node *program, const char * = 0) override { LOG2("InlineDriver"); diff --git a/frontends/p4/coreLibrary.h b/frontends/p4/coreLibrary.h index 7ab5126d39..43a99bf310 100644 --- a/frontends/p4/coreLibrary.h +++ b/frontends/p4/coreLibrary.h @@ -64,14 +64,16 @@ inline std::ostream &operator<<(std::ostream &out, P4::StandardExceptions e) { namespace P4 { +using namespace literals; + class PacketIn : public Model::Extern_Model { public: PacketIn() - : Extern_Model("packet_in"), - extract("extract"), - lookahead("lookahead"), - advance("advance"), - length("length") {} + : Extern_Model("packet_in"_cs), + extract("extract"_cs), + lookahead("lookahead"_cs), + advance("advance"_cs), + length("length"_cs) {} Model::Elem extract; Model::Elem lookahead; Model::Elem advance; @@ -81,14 +83,14 @@ class PacketIn : public Model::Extern_Model { class PacketOut : public Model::Extern_Model { public: - PacketOut() : Extern_Model("packet_out"), emit("emit") {} + PacketOut() : Extern_Model("packet_out"_cs), emit("emit"_cs) {} Model::Elem emit; }; class P4Exception_Model : public ::Model::Elem { public: const StandardExceptions exc; - explicit P4Exception_Model(StandardExceptions exc) : ::Model::Elem(""), exc(exc) { + explicit P4Exception_Model(StandardExceptions exc) : ::Model::Elem(cstring::empty), exc(exc) { std::stringstream str; str << exc; name = str.str(); @@ -101,10 +103,10 @@ class P4CoreLibrary : public ::Model::Model { protected: // NOLINTBEGIN(bugprone-throw-keyword-missing) P4CoreLibrary() - : noAction("NoAction"), - exactMatch("exact"), - ternaryMatch("ternary"), - lpmMatch("lpm"), + : noAction("NoAction"_cs), + exactMatch("exact"_cs), + ternaryMatch("ternary"_cs), + lpmMatch("lpm"_cs), noError(StandardExceptions::NoError), packetTooShort(StandardExceptions::PacketTooShort), noMatch(StandardExceptions::NoMatch), diff --git a/frontends/p4/createBuiltins.cpp b/frontends/p4/createBuiltins.cpp index 16bac04341..47360fd7e5 100644 --- a/frontends/p4/createBuiltins.cpp +++ b/frontends/p4/createBuiltins.cpp @@ -23,7 +23,7 @@ limitations under the License. namespace P4 { const IR::Node *CreateBuiltins::preorder(IR::P4Program *program) { - auto decls = program->getDeclsByName(P4::P4CoreLibrary::instance().noAction.str()); + auto decls = program->getDeclsByName(P4::P4CoreLibrary::instance().noAction.toString()); auto vec = decls->toVector(); if (vec.empty()) return program; if (vec.size() > 1) { @@ -118,7 +118,7 @@ const IR::Node *CreateBuiltins::postorder(IR::ParserState *state) { const IR::Node *CreateBuiltins::postorder(IR::ActionList *actions) { if (!addNoAction) return actions; - auto decl = actions->getDeclaration(P4::P4CoreLibrary::instance().noAction.str()); + auto decl = actions->getDeclaration(P4::P4CoreLibrary::instance().noAction.toString()); if (decl != nullptr) return actions; checkGlobalAction(); actions->push_back(new IR::ActionListElement( diff --git a/frontends/p4/def_use.cpp b/frontends/p4/def_use.cpp index 8163202fca..f4d1842c18 100644 --- a/frontends/p4/def_use.cpp +++ b/frontends/p4/def_use.cpp @@ -23,9 +23,11 @@ limitations under the License. namespace P4 { +using namespace literals; + // internal name for header valid bit; used only locally -const cstring StorageFactory::validFieldName = "$valid"; -const cstring StorageFactory::indexFieldName = "$lastIndex"; +const cstring StorageFactory::validFieldName = "$valid"_cs; +const cstring StorageFactory::indexFieldName = "$lastIndex"_cs; const LocationSet *LocationSet::empty = new LocationSet(); ProgramPoint ProgramPoint::beforeStart; diff --git a/frontends/p4/deprecated.cpp b/frontends/p4/deprecated.cpp index 432a531e27..2f8636b2d8 100644 --- a/frontends/p4/deprecated.cpp +++ b/frontends/p4/deprecated.cpp @@ -25,9 +25,9 @@ void CheckDeprecated::warnIfDeprecated(const IR::IAnnotated *annotated, const IR auto anno = annotated->getAnnotations()->getSingle(IR::Annotation::deprecatedAnnotation); if (anno == nullptr) return; - cstring message = ""; - for (auto a : anno->expr) { - if (auto str = a->to()) message += str->value; + std::string message; + for (const auto *a : anno->expr) { + if (const auto *str = a->to()) message += str->value; } ::warning(ErrorType::WARN_DEPRECATED, "%1%: Using deprecated feature %2%. %3%", errorNode, annotated->getNode(), message); diff --git a/frontends/p4/entryPriorities.cpp b/frontends/p4/entryPriorities.cpp index 17bcb238ec..6188376f2c 100644 --- a/frontends/p4/entryPriorities.cpp +++ b/frontends/p4/entryPriorities.cpp @@ -56,9 +56,9 @@ const IR::Node *DoEntryPriorities::preorder(IR::EntriesList *entries) { bool largestWins = true; // default value size_t priorityDelta = 1; // default value - auto largestProp = table->getBooleanProperty("largest_priority_wins"); + auto largestProp = table->getBooleanProperty("largest_priority_wins"_cs); if (largestProp) largestWins = largestProp->value; - auto deltaProp = table->getConstantProperty("priority_delta"); + auto deltaProp = table->getConstantProperty("priority_delta"_cs); if (deltaProp) { if (!deltaProp->fitsUint()) { ::error(ErrorType::ERR_INVALID, "%1% must be a positive value", deltaProp); diff --git a/frontends/p4/fromv1.0/converters.cpp b/frontends/p4/fromv1.0/converters.cpp index def4f61051..a14d730a3c 100644 --- a/frontends/p4/fromv1.0/converters.cpp +++ b/frontends/p4/fromv1.0/converters.cpp @@ -68,7 +68,8 @@ const IR::Node *ExpressionConverter::postorder(IR::Constant *expression) { const IR::Node *ExpressionConverter::postorder(IR::FieldList *fl) { // Field lists may contain other field lists - if (auto func = get(std::type_index(typeid(*fl)).name())) { + cstring name(std::type_index(typeid(*fl)).name()); + if (auto func = get(name)) { return func(fl); } return new IR::ListExpression(fl->srcInfo, fl->fields); @@ -409,7 +410,7 @@ const IR::Statement *StatementConverter::convert(const IR::Vectorsize == 0) { if (auto type = findContext()) { - if (auto max = type->getAnnotation("max_length")) { + if (auto max = type->getAnnotation("max_length"_cs)) { if (max->expr.size() != 1 || !max->expr[0]->is()) error(ErrorType::ERR_UNSUPPORTED, "%s: max_length must be a constant", max); else @@ -458,7 +459,7 @@ const IR::StructField *TypeConverter::postorder(IR::StructField *field) { // given a struct with length and max_length, the // varbit field size is max_length * 8 - struct_size if (field->type->is()) { - if (auto len = type->getAnnotation("length")) { + if (auto len = type->getAnnotation("length"_cs)) { if (len->expr.size() == 1) { auto lenexpr = len->expr[0]; ValidateLenExpr vle(type, field); @@ -468,12 +469,12 @@ const IR::StructField *TypeConverter::postorder(IR::StructField *field) { auto fieldlen = new IR::Sub(scale->srcInfo, scale, new IR::Constant(type->width_bits())); field->annotations = - field->annotations->add(new IR::Annotation("length", {fieldlen})); + field->annotations->add(new IR::Annotation("length"_cs, {fieldlen})); } } } if (auto vec = structure->listIndexes(type->name.name, field->name.name)) - field->annotations = field->annotations->add(new IR::Annotation("field_list", *vec)); + field->annotations = field->annotations->add(new IR::Annotation("field_list"_cs, *vec)); return field; } @@ -522,7 +523,7 @@ class FixupExtern : public Modifier { bool preorder(IR::Parameter *param) override { BUG_CHECK(typeParams, "recursion failure"); if (param->type->is()) { - auto n = new IR::Type_Var(structure->makeUniqueName("FL")); + auto n = new IR::Type_Var(structure->makeUniqueName("FL"_cs)); param->type = n; typeParams->push_back(n); } @@ -592,10 +593,11 @@ ExternConverter *ExternConverter::get(cstring type) { std::map> *PrimitiveConverter::all_converters; -PrimitiveConverter::PrimitiveConverter(cstring name, int prio) : prim_name(name), priority(prio) { +PrimitiveConverter::PrimitiveConverter(std::string_view name, int prio) + : prim_name(name), priority(prio) { static std::map> converters; all_converters = &converters; - auto &vec = converters[name]; + auto &vec = converters[prim_name]; auto it = vec.begin(); while (it != vec.end() && (*it)->priority > prio) ++it; if (it != vec.end() && (*it)->priority == prio) diff --git a/frontends/p4/fromv1.0/converters.h b/frontends/p4/fromv1.0/converters.h index 2b65d65011..400e412c69 100644 --- a/frontends/p4/fromv1.0/converters.h +++ b/frontends/p4/fromv1.0/converters.h @@ -143,7 +143,7 @@ class PrimitiveConverter { int priority; protected: - PrimitiveConverter(cstring name, int prio); + PrimitiveConverter(std::string_view name, int prio); virtual ~PrimitiveConverter(); // helper functions @@ -178,8 +178,9 @@ class DiscoverStructure : public Inspector { ProgramStructure *structure; // These names can only be used for very specific purposes - std::map reserved_names = { - {"standard_metadata_t", "type"}, {"standard_metadata", "metadata"}, {"egress", "control"}}; + std::map reserved_names = {{"standard_metadata_t"_cs, "type"_cs}, + {"standard_metadata"_cs, "metadata"_cs}, + {"egress"_cs, "control"_cs}}; void checkReserved(const IR::Node *node, cstring nodeName, cstring kind) const { auto it = reserved_names.find(nodeName); @@ -203,7 +204,7 @@ class DiscoverStructure : public Inspector { } void postorder(const IR::Metadata *md) override { structure->metadata.emplace(md); - checkReserved(md, md->name, "metadata"); + checkReserved(md, md->name, "metadata"_cs); } void postorder(const IR::Header *hd) override { structure->headers.emplace(hd); @@ -211,11 +212,11 @@ class DiscoverStructure : public Inspector { } void postorder(const IR::Type_StructLike *t) override { structure->types.emplace(t); - checkReserved(t, t->name, "type"); + checkReserved(t, t->name, "type"_cs); } void postorder(const IR::V1Control *control) override { structure->controls.emplace(control); - checkReserved(control, control->name, "control"); + checkReserved(control, control->name, "control"_cs); } void postorder(const IR::V1Parser *parser) override { structure->parserStates.emplace(parser); @@ -537,7 +538,7 @@ class FixExtracts final : public Transform { for (auto f : type->fields) { if (f->type->is()) { - cstring hname = structure->makeUniqueName(type->name); + cstring hname = structure->makeUniqueName(type->name.name); if (fixedHeaderType != nullptr) { ::error(ErrorType::ERR_INVALID, "%1%: header types with multiple varbit fields are not supported", @@ -637,7 +638,7 @@ class FixExtracts final : public Transform { CHECK_NULL(fixed->fixedHeaderType); auto result = new IR::IndexedVector(); - cstring varName = structure->makeUniqueName("tmp_hdr"); + cstring varName = structure->makeUniqueName("tmp_hdr"_cs); auto var = new IR::Declaration_Variable(IR::ID(varName), fixed->fixedHeaderType->to()); varDecls.push_back(var); @@ -796,9 +797,9 @@ class InsertCompilerGeneratedStartState : public Transform { explicit InsertCompilerGeneratedStartState(ProgramStructure *structure) : structure(structure) { setName("InsertCompilerGeneratedStartState"); structure->allNames.insert({IR::ParserState::start, 0}); - structure->allNames.insert({"InstanceType", 0}); + structure->allNames.insert({"InstanceType"_cs, 0}); newStartState = structure->makeUniqueName(IR::ParserState::start); - newInstanceType = structure->makeUniqueName("InstanceType"); + newInstanceType = structure->makeUniqueName("InstanceType"_cs); } const IR::Node *postorder(IR::P4Program *program) override { @@ -841,7 +842,8 @@ class InsertCompilerGeneratedStartState : public Transform { // transition to original start state members.push_back(new IR::SerEnumMember("START", new IR::Constant(0))); selCases.push_back(new IR::SelectCase( - new IR::Member(new IR::TypeNameExpression(new IR::Type_Name(newInstanceType)), "START"), + new IR::Member(new IR::TypeNameExpression(new IR::Type_Name(newInstanceType)), + "START"_cs), new IR::PathExpression(new IR::Path(newStartState)))); // transition to addtional entry points @@ -854,19 +856,19 @@ class InsertCompilerGeneratedStartState : public Transform { new IR::PathExpression(new IR::Path(p.second->name)))); } auto instAnnos = new IR::Annotations(); - instAnnos->add(new IR::Annotation(IR::Annotation::nameAnnotation, ".$InstanceType")); + instAnnos->add(new IR::Annotation(IR::Annotation::nameAnnotation, ".$InstanceType"_cs)); auto instEnum = new IR::Type_SerEnum(newInstanceType, instAnnos, IR::Type_Bits::get(32), members); allTypeDecls.push_back(instEnum); IR::Vector selExpr; - selExpr.push_back( - new IR::Cast(new IR::Type_Name(newInstanceType), - new IR::Member(new IR::PathExpression(new IR::Path("standard_metadata")), - "instance_type"))); + selExpr.push_back(new IR::Cast( + new IR::Type_Name(newInstanceType), + new IR::Member(new IR::PathExpression(new IR::Path("standard_metadata"_cs)), + "instance_type"_cs))); auto selects = new IR::SelectExpression(new IR::ListExpression(selExpr), selCases); auto annos = new IR::Annotations(); - annos->add(new IR::Annotation(IR::Annotation::nameAnnotation, ".$start")); + annos->add(new IR::Annotation(IR::Annotation::nameAnnotation, ".$start"_cs)); auto startState = new IR::ParserState(IR::ParserState::start, annos, selects); parserStates.push_back(startState); diff --git a/frontends/p4/fromv1.0/programStructure.cpp b/frontends/p4/fromv1.0/programStructure.cpp index 1f7542c9be..385aa233d9 100644 --- a/frontends/p4/fromv1.0/programStructure.cpp +++ b/frontends/p4/fromv1.0/programStructure.cpp @@ -31,6 +31,7 @@ limitations under the License. #include "lib/path.h" namespace P4V1 { +using namespace P4::literals; static const IR::IDeclaration *getFirstDeclaration(const IR::Vector *nodes, cstring name) { @@ -90,7 +91,7 @@ const IR::Annotations *ProgramStructure::addNameAnnotation(cstring name, const IR::Annotations *ProgramStructure::addGlobalNameAnnotation(cstring name, const IR::Annotations *annos) { - return addNameAnnotation(cstring(".") + name, annos); + return addNameAnnotation("."_cs + name, annos); } cstring ProgramStructure::makeUniqueName(cstring base) { @@ -199,7 +200,7 @@ cstring ProgramStructure::createType(const IR::Type_StructLike *type, bool heade void ProgramStructure::createTypes() { if (allFieldLists.size()) { // An enum containing the recirculated/cloned/resubmitted field lists - fieldListsEnum = makeUniqueName("FieldLists"); + fieldListsEnum = makeUniqueName("FieldLists"_cs); auto members = new IR::IndexedVector(); unsigned index = 0; P4::MinimalNameGenerator mng; @@ -239,7 +240,7 @@ void ProgramStructure::createTypes() { BUG_CHECK(type->is(), "%1%: unexpected type", type); // Must convert to a struct type - cstring type_name = makeUniqueName(st->name); + cstring type_name = makeUniqueName(st->name.name); // Registers always use struct types auto annos = addNameAnnotation(layoutTypeName, type->annotations); auto newType = new IR::Type_Struct(type->srcInfo, type_name, annos, st->fields); @@ -278,7 +279,7 @@ const IR::Type_Struct *ProgramStructure::createFieldListType(const IR::Expressio return nullptr; } - auto name = makeUniqueName(nr->path->name); + auto name = makeUniqueName(nr->path->name.name); auto annos = addNameAnnotation(nr->path->name); auto result = new IR::Type_Struct(expression->srcInfo, name, annos); std::set fieldNames; @@ -555,7 +556,7 @@ const IR::ParserState *ProgramStructure::convertParser( value_sets_implemented.emplace(first->path->name); auto type = explodeType(fieldTypes); - auto sizeAnnotation = value_set->annotations->getSingle("parser_value_set_size"); + auto sizeAnnotation = value_set->annotations->getSingle("parser_value_set_size"_cs); const IR::Constant *sizeConstant; if (sizeAnnotation) { if (sizeAnnotation->expr.size() != 1) { @@ -896,9 +897,9 @@ const IR::Declaration_Instance *ProgramStructure::convertActionProfile( auto width = new IR::Constant(v1model.action_selector.widthType, flc->output_width); args->push_back(new IR::Argument(width)); if (action_selector->mode) - annos = annos->addAnnotation("mode", new IR::StringLiteral(action_selector->mode)); + annos = annos->addAnnotation("mode"_cs, new IR::StringLiteral(action_selector->mode)); if (action_selector->type) - annos = annos->addAnnotation("type", new IR::StringLiteral(action_selector->type)); + annos = annos->addAnnotation("type"_cs, new IR::StringLiteral(action_selector->type)); auto fl = getFieldLists(flc); for (auto annot : fl->annotations->annotations) { annos = annos->add(annot); @@ -936,7 +937,7 @@ const IR::P4Table *ProgramStructure::convertTable(const IR::V1Table *table, cstr if (mtr != nullptr || ctr != nullptr) { // we must synthesize a new action, which has a writeback to // the meter/counter - newname = makeUniqueName(a); + newname = makeUniqueName(a.name); auto actCont = convertAction(action, newname, mtr, ctr); stateful.push_back(actCont); mapNames[table->name + '.' + a] = newname; @@ -1139,7 +1140,7 @@ static bool isSaturatedField(const IR::Expression *expr) { auto header_type = member->expr->type->to(); if (!header_type) return false; auto field = header_type->getField(member->member.name); - if (field && field->getAnnotation("saturating")) { + if (field && field->getAnnotation("saturating"_cs)) { return true; } return false; @@ -1573,7 +1574,7 @@ CONVERT_PRIMITIVE( auto block = new IR::BlockStatement; if (primitive->operands.size() == 3) { mask = conv.convert(primitive->operands.at(2)); - cstring tmpvar = structure->makeUniqueName("tmp"); + cstring tmpvar = structure->makeUniqueName("tmp"_cs); auto decl = new IR::Declaration_Variable(tmpvar, field->type); block->push_back(decl); dest = new IR::PathExpression(field->type, new IR::Path(tmpvar)); @@ -2089,9 +2090,9 @@ const IR::Declaration_Instance *ProgramStructure::convert(const IR::CounterOrMet auto annos = addGlobalNameAnnotation(cm->name, cm->annotations); if (auto *c = cm->to()) { if (c->min_width >= 0) - annos = annos->addAnnotation("min_width", new IR::Constant(c->min_width)); + annos = annos->addAnnotation("min_width"_cs, new IR::Constant(c->min_width)); if (c->max_width >= 0) - annos = annos->addAnnotation("max_width", new IR::Constant(c->max_width)); + annos = annos->addAnnotation("max_width"_cs, new IR::Constant(c->max_width)); } auto decl = new IR::Declaration_Instance(newName, annos, type, args, nullptr); return decl; @@ -2120,7 +2121,7 @@ const IR::Declaration_Instance *ProgramStructure::convertDirectMeter(const IR::M auto annos = addGlobalNameAnnotation(m->name, m->annotations); if (m->pre_color != nullptr) { auto meterPreColor = ExpressionConverter(this).convert(m->pre_color); - if (meterPreColor != nullptr) annos = annos->addAnnotation("pre_color", meterPreColor); + if (meterPreColor != nullptr) annos = annos->addAnnotation("pre_color"_cs, meterPreColor); } auto decl = new IR::Declaration_Instance(newName, annos, specType, args, nullptr); return decl; @@ -2138,9 +2139,9 @@ const IR::Declaration_Instance *ProgramStructure::convertDirectCounter(const IR: args->push_back(new IR::Argument(kindarg)); auto annos = addGlobalNameAnnotation(c->name, c->annotations); if (c->min_width >= 0) - annos = annos->addAnnotation("min_width", new IR::Constant(c->min_width)); + annos = annos->addAnnotation("min_width"_cs, new IR::Constant(c->min_width)); if (c->max_width >= 0) - annos = annos->addAnnotation("max_width", new IR::Constant(c->max_width)); + annos = annos->addAnnotation("max_width"_cs, new IR::Constant(c->max_width)); auto decl = new IR::Declaration_Instance(newName, annos, type, args, nullptr); return decl; } @@ -2626,6 +2627,7 @@ void ProgramStructure::tablesReferred(const IR::V1Control *control, } void ProgramStructure::populateOutputNames() { + // FIXME: modernize static const char *used_names[] = { // core.p4 "packet_in", "packet_out", "NoAction", "exact", "ternary", "lpm", @@ -2643,7 +2645,7 @@ void ProgramStructure::populateOutputNames() { "DeparserImpl", // parameters "packet", "hdr", "meta", nullptr}; - for (const char **c = used_names; *c != nullptr; ++c) allNames.insert({*c, 0}); + for (const char **c = used_names; *c != nullptr; ++c) allNames.emplace(cstring(*c), 0); ; } diff --git a/frontends/p4/fromv1.0/v1model.h b/frontends/p4/fromv1.0/v1model.h index ed84632738..667d7fdd2b 100644 --- a/frontends/p4/fromv1.0/v1model.h +++ b/frontends/p4/fromv1.0/v1model.h @@ -26,6 +26,8 @@ limitations under the License. namespace P4V1 { +using namespace P4::literals; + // This should be kept in sync with p4includes/v1model.p4 // In a perfect world this would be generated automatically from // p4includes/v1model.p4 @@ -33,11 +35,11 @@ namespace P4V1 { struct Parser_Model : public ::Model::Elem { Parser_Model(Model::Type_Model headersType, Model::Type_Model userMetaType, Model::Type_Model standardMetadataType) - : Model::Elem("ParserImpl"), - packetParam("packet", P4::P4CoreLibrary::instance().packetIn, 0), - headersParam("hdr", headersType, 1), - metadataParam("meta", userMetaType, 2), - standardMetadataParam("standard_metadata", standardMetadataType, 3) {} + : Model::Elem("ParserImpl"_cs), + packetParam("packet"_cs, P4::P4CoreLibrary::instance().packetIn, 0), + headersParam("hdr"_cs, headersType, 1), + metadataParam("meta"_cs, userMetaType, 2), + standardMetadataParam("standard_metadata"_cs, standardMetadataType, 3) {} ::Model::Param_Model packetParam; ::Model::Param_Model headersParam; ::Model::Param_Model metadataParam; @@ -46,9 +48,9 @@ struct Parser_Model : public ::Model::Elem { struct Deparser_Model : public ::Model::Elem { explicit Deparser_Model(Model::Type_Model headersType) - : Model::Elem("DeparserImpl"), - packetParam("packet", P4::P4CoreLibrary::instance().packetOut, 0), - headersParam("hdr", headersType, 1) {} + : Model::Elem("DeparserImpl"_cs), + packetParam("packet"_cs, P4::P4CoreLibrary::instance().packetOut, 0), + headersParam("hdr"_cs, headersType, 1) {} ::Model::Param_Model packetParam; ::Model::Param_Model headersParam; }; @@ -58,9 +60,9 @@ struct Control_Model : public ::Model::Elem { Control_Model(cstring name, Model::Type_Model headersType, Model::Type_Model metadataType, Model::Type_Model standardMetadataType) : Model::Elem(name), - headersParam("hdr", headersType, 0), - metadataParam("meta", metadataType, 1), - standardMetadataParam("standard_metadata", standardMetadataType, 2) {} + headersParam("hdr"_cs, headersType, 0), + metadataParam("meta"_cs, metadataType, 1), + standardMetadataParam("standard_metadata"_cs, standardMetadataType, 2) {} ::Model::Param_Model headersParam; ::Model::Param_Model metadataParam; ::Model::Param_Model standardMetadataParam; @@ -68,41 +70,44 @@ struct Control_Model : public ::Model::Elem { struct VerifyUpdate_Model : public ::Model::Elem { VerifyUpdate_Model(cstring name, Model::Type_Model headersType) - : Model::Elem(name), headersParam("hdr", headersType, 0) {} + : Model::Elem(name), headersParam("hdr"_cs, headersType, 0) {} ::Model::Param_Model headersParam; }; struct CounterType_Model : public ::Model::Enum_Model { CounterType_Model() - : ::Model::Enum_Model("CounterType"), - packets("packets"), - bytes("bytes"), - both("packets_and_bytes") {} + : ::Model::Enum_Model("CounterType"_cs), + packets("packets"_cs), + bytes("bytes"_cs), + both("packets_and_bytes"_cs) {} ::Model::Elem packets; ::Model::Elem bytes; ::Model::Elem both; }; struct MeterType_Model : public ::Model::Enum_Model { - MeterType_Model() : ::Model::Enum_Model("MeterType"), packets("packets"), bytes("bytes") {} + MeterType_Model() + : ::Model::Enum_Model("MeterType"_cs), packets("packets"_cs), bytes("bytes"_cs) {} ::Model::Elem packets; ::Model::Elem bytes; }; struct ActionProfile_Model : public ::Model::Extern_Model { ActionProfile_Model() - : Extern_Model("action_profile"), sizeType(IR::Type_Bits::get(32)), sizeParam("size") {} + : Extern_Model("action_profile"_cs), + sizeType(IR::Type_Bits::get(32)), + sizeParam("size"_cs) {} const IR::Type *sizeType; ::Model::Elem sizeParam; }; struct ActionSelector_Model : public ::Model::Extern_Model { ActionSelector_Model() - : Extern_Model("action_selector"), + : Extern_Model("action_selector"_cs), sizeType(IR::Type_Bits::get(32)), - sizeParam("size"), + sizeParam("size"_cs), widthType(IR::Type_Bits::get(32)), - algorithmParam("algorithm") {} + algorithmParam("algorithm"_cs) {} const IR::Type *sizeType; ::Model::Elem sizeParam; const IR::Type *widthType; @@ -110,21 +115,21 @@ struct ActionSelector_Model : public ::Model::Extern_Model { }; struct Random_Model : public ::Model::Elem { - Random_Model() : Elem("random"), modify_field_rng_uniform("modify_field_rng_uniform") {} + Random_Model() : Elem("random"_cs), modify_field_rng_uniform("modify_field_rng_uniform"_cs) {} ::Model::Elem modify_field_rng_uniform; }; class Truncate : public Model::Extern_Model { public: - Truncate() : Extern_Model("truncate"), length_type(IR::Type::Bits::get(32)) {} + Truncate() : Extern_Model("truncate"_cs), length_type(IR::Type::Bits::get(32)) {} const IR::Type *length_type; }; struct CounterOrMeter_Model : public ::Model::Extern_Model { explicit CounterOrMeter_Model(cstring name) : Extern_Model(name), - sizeParam("size"), - typeParam("type"), + sizeParam("size"_cs), + typeParam("type"_cs), size_type(IR::Type_Bits::get(32)) {} ::Model::Elem sizeParam; ::Model::Elem typeParam; @@ -135,10 +140,10 @@ struct CounterOrMeter_Model : public ::Model::Extern_Model { struct Register_Model : public ::Model::Extern_Model { Register_Model() - : Extern_Model("register"), - sizeParam("size"), - read("read"), - write("write"), + : Extern_Model("register"_cs), + sizeParam("size"_cs), + read("read"_cs), + write("write"_cs), size_type(IR::Type_Bits::get(32)) {} ::Model::Elem sizeParam; ::Model::Elem read; @@ -147,58 +152,58 @@ struct Register_Model : public ::Model::Extern_Model { }; struct DigestReceiver_Model : public ::Model::Elem { - DigestReceiver_Model() : Elem("digest"), receiverType(IR::Type_Bits::get(32)) {} + DigestReceiver_Model() : Elem("digest"_cs), receiverType(IR::Type_Bits::get(32)) {} const IR::Type *receiverType; }; struct Counter_Model : public CounterOrMeter_Model { - Counter_Model() : CounterOrMeter_Model("counter"), increment("count") {} + Counter_Model() : CounterOrMeter_Model("counter"_cs), increment("count"_cs) {} ::Model::Elem increment; }; struct Meter_Model : public CounterOrMeter_Model { - Meter_Model() : CounterOrMeter_Model("meter"), executeMeter("execute_meter") {} + Meter_Model() : CounterOrMeter_Model("meter"_cs), executeMeter("execute_meter"_cs) {} ::Model::Elem executeMeter; }; struct DirectMeter_Model : public CounterOrMeter_Model { - DirectMeter_Model() : CounterOrMeter_Model("direct_meter"), read("read") {} + DirectMeter_Model() : CounterOrMeter_Model("direct_meter"_cs), read("read"_cs) {} ::Model::Elem read; }; struct DirectCounter_Model : public CounterOrMeter_Model { - DirectCounter_Model() : CounterOrMeter_Model("direct_counter"), count("count") {} + DirectCounter_Model() : CounterOrMeter_Model("direct_counter"_cs), count("count"_cs) {} ::Model::Elem count; }; struct StandardMetadataType_Model : public ::Model::Type_Model { explicit StandardMetadataType_Model(cstring name) : ::Model::Type_Model(name), - dropBit("drop"), - recirculate("recirculate_port"), - egress_spec("egress_spec") {} + dropBit("drop"_cs), + recirculate("recirculate_port"_cs), + egress_spec("egress_spec"_cs) {} ::Model::Elem dropBit; ::Model::Elem recirculate; ::Model::Elem egress_spec; }; struct CloneType_Model : public ::Model::Enum_Model { - CloneType_Model() : ::Model::Enum_Model("CloneType"), i2e("I2E"), e2e("E2E") {} + CloneType_Model() : ::Model::Enum_Model("CloneType"_cs), i2e("I2E"_cs), e2e("E2E"_cs) {} ::Model::Elem i2e; ::Model::Elem e2e; }; struct Algorithm_Model : public ::Model::Enum_Model { Algorithm_Model() - : ::Model::Enum_Model("HashAlgorithm"), - crc32("crc32"), - crc32_custom("crc32_custom"), - crc16("crc16"), - crc16_custom("crc16_custom"), - random("random"), - identity("identity"), - csum16("csum16"), - xor16("xor16") {} + : ::Model::Enum_Model("HashAlgorithm"_cs), + crc32("crc32"_cs), + crc32_custom("crc32_custom"_cs), + crc16("crc16"_cs), + crc16_custom("crc16_custom"_cs), + random("random"_cs), + identity("identity"_cs), + csum16("csum16"_cs), + xor16("xor16"_cs) {} ::Model::Elem crc32; ::Model::Elem crc32_custom; ::Model::Elem crc16; @@ -210,13 +215,13 @@ struct Algorithm_Model : public ::Model::Enum_Model { }; struct Hash_Model : public ::Model::Elem { - Hash_Model() : ::Model::Elem("hash") {} + Hash_Model() : ::Model::Elem("hash"_cs) {} }; struct Cloner_Model : public ::Model::Extern_Model { Cloner_Model() - : Extern_Model("clone"), - clone3("clone_preserving_field_list"), + : Extern_Model("clone"_cs), + clone3("clone_preserving_field_list"_cs), sessionType(IR::Type_Bits::get(32)) {} ::Model::Elem clone3; @@ -226,13 +231,13 @@ struct Cloner_Model : public ::Model::Extern_Model { struct Switch_Model : public ::Model::Elem { Switch_Model() - : Model::Elem("V1Switch"), - parser("p"), - verify("vr"), - ingress("ig"), - egress("eg"), - compute("ck"), - deparser("dep") {} + : Model::Elem("V1Switch"_cs), + parser("p"_cs), + verify("vr"_cs), + ingress("ig"_cs), + egress("eg"_cs), + compute("ck"_cs), + deparser("dep"_cs) {} ::Model::Elem parser; // names of the package arguments ::Model::Elem verify; ::Model::Elem ingress; @@ -243,11 +248,11 @@ struct Switch_Model : public ::Model::Elem { struct TableAttributes_Model { TableAttributes_Model() - : tableImplementation("implementation"), - counters("counters"), - meters("meters"), - size("size"), - supportTimeout("support_timeout") {} + : tableImplementation("implementation"_cs), + counters("counters"_cs), + meters("meters"_cs), + size("size"_cs), + supportTimeout("support_timeout"_cs) {} ::Model::Elem tableImplementation; ::Model::Elem counters; ::Model::Elem meters; @@ -259,44 +264,44 @@ struct TableAttributes_Model { class V1Model : public ::Model::Model { protected: V1Model() - : file("v1model.p4"), - standardMetadata("standard_metadata"), + : file("v1model.p4"_cs), + standardMetadata("standard_metadata"_cs), // The following 2 are not really docmented in the P4-14 spec. - intrinsicMetadata("intrinsic_metadata"), - queueingMetadata("queueing_metadata"), - headersType("headers"), - metadataType("metadata"), - standardMetadataType("standard_metadata_t"), + intrinsicMetadata("intrinsic_metadata"_cs), + queueingMetadata("queueing_metadata"_cs), + headersType("headers"_cs), + metadataType("metadata"_cs), + standardMetadataType("standard_metadata_t"_cs), parser(headersType, metadataType, standardMetadataType), deparser(headersType), - egress("egress", headersType, metadataType, standardMetadataType), - ingress("ingress", headersType, metadataType, standardMetadataType), + egress("egress"_cs, headersType, metadataType, standardMetadataType), + ingress("ingress"_cs, headersType, metadataType, standardMetadataType), sw(), - counterOrMeter("$"), + counterOrMeter("$"_cs), counter(), meter(), random(), action_profile(), action_selector(), clone(), - resubmit("resubmit_preserving_field_list"), + resubmit("resubmit_preserving_field_list"_cs), tableAttributes(), - rangeMatchType("range"), - optionalMatchType("optional"), - selectorMatchType("selector"), - verify("verifyChecksum", headersType), - compute("computeChecksum", headersType), + rangeMatchType("range"_cs), + optionalMatchType("optional"_cs), + selectorMatchType("selector"_cs), + verify("verifyChecksum"_cs, headersType), + compute("computeChecksum"_cs, headersType), digest_receiver(), hash(), algorithm(), registers(), - drop("mark_to_drop"), - recirculate("recirculate_preserving_field_list"), - verify_checksum("verify_checksum"), - update_checksum("update_checksum"), - verify_checksum_with_payload("verify_checksum_with_payload"), - update_checksum_with_payload("update_checksum_with_payload"), - log_msg("log_msg"), + drop("mark_to_drop"_cs), + recirculate("recirculate_preserving_field_list"_cs), + verify_checksum("verify_checksum"_cs), + update_checksum("update_checksum"_cs), + verify_checksum_with_payload("verify_checksum_with_payload"_cs), + update_checksum_with_payload("update_checksum_with_payload"_cs), + log_msg("log_msg"_cs), directMeter(), directCounter() {} diff --git a/frontends/p4/frontend.cpp b/frontends/p4/frontend.cpp index ca978fafe2..69e1e508e3 100644 --- a/frontends/p4/frontend.cpp +++ b/frontends/p4/frontend.cpp @@ -269,7 +269,7 @@ const IR::P4Program *FrontEnd::run(const CompilerOptions &options, const IR::P4P new FrontEndLast(), }); if (options.listFrontendPasses) { - passes.listPasses(*outStream, "\n"); + passes.listPasses(*outStream, cstring::newline); *outStream << std::endl; return nullptr; } diff --git a/frontends/p4/functionsInlining.cpp b/frontends/p4/functionsInlining.cpp index e25a84ef60..ceaf818ae5 100644 --- a/frontends/p4/functionsInlining.cpp +++ b/frontends/p4/functionsInlining.cpp @@ -177,7 +177,7 @@ const IR::Node *FunctionsInliner::inlineBefore(const IR::Node *calleeNode, // evaluate in and inout parameters in order for (auto param : callee->type->parameters->parameters) { auto argument = substitution.lookup(param); - cstring newName = refMap->newName(param->name); + cstring newName = refMap->newName(param->name.name.string_view()); paramRename.emplace(param, newName); if (param->direction == IR::Direction::In || param->direction == IR::Direction::InOut) { auto vardecl = new IR::Declaration_Variable(newName, param->annotations, param->type, diff --git a/frontends/p4/hierarchicalNames.cpp b/frontends/p4/hierarchicalNames.cpp index 5eb26664f5..fd8ad42ea8 100644 --- a/frontends/p4/hierarchicalNames.cpp +++ b/frontends/p4/hierarchicalNames.cpp @@ -27,7 +27,7 @@ const IR::Node *HierarchicalNames::postorder(IR::Annotation *annotation) { cstring name = annotation->getName(); if (name.startsWith(".")) return annotation; - cstring newName = ""; + std::string newName = ""; for (cstring s : stack) newName += s + "."; newName += name; LOG2("Changing " << name << " to " << newName); diff --git a/frontends/p4/inlining.cpp b/frontends/p4/inlining.cpp index 135dd5d54c..43e25a8f52 100644 --- a/frontends/p4/inlining.cpp +++ b/frontends/p4/inlining.cpp @@ -29,6 +29,8 @@ limitations under the License. namespace P4 { +using namespace literals; + namespace { class FindLocationSets : public Inspector { @@ -570,7 +572,7 @@ void GeneralInliner::inline_subst(P4Block *caller, substs->paramSubst.add(param, initializer); } else { // use a temporary variable - cstring newName = refMap->newName(param->name); + cstring newName = refMap->newName(param->name.name.string_view()); auto path = new IR::PathExpression( param->srcInfo, new IR::Path(param->srcInfo, IR::ID(newName))); substs->paramSubst.add(param, new IR::Argument(path)); @@ -705,7 +707,7 @@ class ComputeNewStateNames : public Inspector { } else if (state->name.name == IR::ParserState::accept) { newName = acceptName; } else { - cstring base = prefix + "_" + state->name.name; + std::string base = prefix + "_" + state->name.name; newName = refMap->newName(base); } stateRenameMap->emplace(state->name.name, newName); @@ -850,7 +852,7 @@ const IR::Node *GeneralInliner::preorder(IR::ParserState *state) { callee = substs->rename(refMap, callee); - cstring nextState = refMap->newName(state->name); + cstring nextState = refMap->newName(state->name.name.string_view()); std::map renameMap; ComputeNewStateNames cnn(refMap, callee->name.name, nextState, &renameMap); cnn.setCalledBy(this); @@ -935,6 +937,6 @@ const IR::Node *GeneralInliner::preorder(IR::P4Parser *caller) { } // set of annotations to _not_ propagate during inlining -std::set Inline::noPropagateAnnotations = {"name"}; +std::set Inline::noPropagateAnnotations = {"name"_cs}; } // namespace P4 diff --git a/frontends/p4/localizeActions.cpp b/frontends/p4/localizeActions.cpp index a95bc8be4a..c7ea68eae5 100644 --- a/frontends/p4/localizeActions.cpp +++ b/frontends/p4/localizeActions.cpp @@ -20,6 +20,8 @@ limitations under the License. namespace P4 { +using namespace literals; + namespace { class ParamCloner : public CloneExpressions { @@ -41,7 +43,7 @@ const IR::Node *TagGlobalActions::preorder(IR::P4Action *action) { if (findContext() == nullptr) { auto annos = action->annotations; if (annos == nullptr) annos = IR::Annotations::empty; - cstring name = cstring(".") + action->name; + cstring name = "."_cs + action->name; annos = annos->addAnnotationIfNew(IR::Annotation::nameAnnotation, new IR::StringLiteral(name), false); action->annotations = annos; @@ -64,7 +66,7 @@ bool FindGlobalActionUses::preorder(const IR::PathExpression *path) { auto control = findContext(); if (control != nullptr) { if (repl->getReplacement(action, control) != nullptr) return false; - auto newName = refMap->newName(action->name); + auto newName = refMap->newName(action->name.name.string_view()); ParamCloner cloner; auto replBody = cloner.clone(action->body); auto params = cloner.clone(action->parameters); @@ -147,7 +149,7 @@ bool FindRepeatedActionUses::preorder(const IR::PathExpression *expression) { LOG1(dbp(expression) << " used by " << dbp(actionUser)); auto replacement = repl->getActionUser(action, actionUser); if (replacement == nullptr) { - auto newName = refMap->newName(action->name); + auto newName = refMap->newName(action->name.name.string_view()); ParamCloner cloner; auto replBody = cloner.clone(action->body); auto annos = action->annotations; diff --git a/frontends/p4/moveDeclarations.cpp b/frontends/p4/moveDeclarations.cpp index dfa9148c1f..12d802893f 100644 --- a/frontends/p4/moveDeclarations.cpp +++ b/frontends/p4/moveDeclarations.cpp @@ -110,7 +110,7 @@ const IR::Node *MoveInitializers::preorder(IR::P4Parser *parser) { } } if (someInitializers) { - newStartName = refMap->newName(IR::ParserState::start); + newStartName = refMap->newName(IR::ParserState::start.string_view()); oldStart = parser->states.getDeclaration(IR::ParserState::start)->to(); CHECK_NULL(oldStart); } diff --git a/frontends/p4/parseAnnotations.cpp b/frontends/p4/parseAnnotations.cpp index e4a5e73301..95e36253db 100644 --- a/frontends/p4/parseAnnotations.cpp +++ b/frontends/p4/parseAnnotations.cpp @@ -28,7 +28,7 @@ ParseAnnotations::HandlerMap ParseAnnotations::standardHandlers() { PARSE_EMPTY(IR::Annotation::optionalAnnotation), PARSE_EMPTY(IR::Annotation::pureAnnotation), PARSE_EMPTY(IR::Annotation::noSideEffectsAnnotation), - PARSE_EMPTY("disable_optimization"), + PARSE_EMPTY("disable_optimization"_cs), // string literal argument. PARSE(IR::Annotation::nameAnnotation, StringLiteral), diff --git a/frontends/p4/reassociation.h b/frontends/p4/reassociation.h index 34b3670f75..c4ae466ad7 100644 --- a/frontends/p4/reassociation.h +++ b/frontends/p4/reassociation.h @@ -22,6 +22,8 @@ limitations under the License. namespace P4 { +using namespace literals; + /** Implements a pass that reorders associative operations when beneficial. * For example, (a + c0) + c1 is rewritten as a + (c0 + c1) when cs are constants. */ @@ -41,7 +43,7 @@ class Reassociation final : public Transform { const IR::Node *postorder(IR::BAnd *expr) override { return reassociate(expr); } const IR::Node *postorder(IR::BXor *expr) override { return reassociate(expr); } const IR::BlockStatement *preorder(IR::BlockStatement *bs) override { - if (bs->annotations->getSingle("disable_optimization")) prune(); + if (bs->annotations->getSingle("disable_optimization"_cs)) prune(); return bs; } }; diff --git a/frontends/p4/removeReturns.cpp b/frontends/p4/removeReturns.cpp index d1fde2a731..5b34c68604 100644 --- a/frontends/p4/removeReturns.cpp +++ b/frontends/p4/removeReturns.cpp @@ -30,7 +30,7 @@ const IR::Node *DoRemoveReturns::preorder(IR::P4Action *action) { return action; } LOG3("Processing " << dbp(action)); - cstring var = refMap->newName(variableName); + cstring var = refMap->newName(variableName.string_view()); returnVar = IR::ID(var, nullptr); auto f = new IR::BoolLiteral(false); auto decl = new IR::Declaration_Variable(returnVar, IR::Type_Boolean::get(), f); @@ -67,11 +67,11 @@ const IR::Node *DoRemoveReturns::preorder(IR::Function *function) { bool returnsVal = function->type->returnType != nullptr && !function->type->returnType->is(); - cstring var = refMap->newName(variableName); + cstring var = refMap->newName(variableName.string_view()); returnVar = IR::ID(var, nullptr); IR::Declaration_Variable *retvalDecl = nullptr; if (returnsVal) { - var = refMap->newName(retValName); + var = refMap->newName(retValName.string_view()); returnedValue = IR::ID(var, nullptr); retvalDecl = new IR::Declaration_Variable(returnedValue, function->type->returnType); } @@ -105,7 +105,7 @@ const IR::Node *DoRemoveReturns::preorder(IR::P4Control *control) { return control; } - cstring var = refMap->newName(variableName); + cstring var = refMap->newName(variableName.string_view()); returnVar = IR::ID(var, nullptr); auto f = new IR::BoolLiteral(false); auto decl = new IR::Declaration_Variable(returnVar, IR::Type_Boolean::get(), f); diff --git a/frontends/p4/removeReturns.h b/frontends/p4/removeReturns.h index 70e949f9b0..9cd8e10b6d 100644 --- a/frontends/p4/removeReturns.h +++ b/frontends/p4/removeReturns.h @@ -23,6 +23,7 @@ limitations under the License. #include "ir/ir.h" namespace P4 { +using namespace literals; /** This inspector detects whether an IR tree contains @@ -77,8 +78,8 @@ class DoRemoveReturns : public Transform { } public: - explicit DoRemoveReturns(P4::ReferenceMap *refMap, cstring varName = "hasReturned", - cstring retValName = "retval") + explicit DoRemoveReturns(P4::ReferenceMap *refMap, cstring varName = "hasReturned"_cs, + cstring retValName = "retval"_cs) : refMap(refMap), variableName(varName), retValName(retValName) { visitDagOnce = false; CHECK_NULL(refMap); diff --git a/frontends/p4/reservedWords.cpp b/frontends/p4/reservedWords.cpp index 9078c1924e..3ef6a7286c 100644 --- a/frontends/p4/reservedWords.cpp +++ b/frontends/p4/reservedWords.cpp @@ -18,16 +18,21 @@ limitations under the License. namespace P4 { +using namespace literals; + // Keep this in sync with the lexer -std::set reservedWords = { - "abstract", // experimental - "action", "actions", "apply", "bool", "bit", "const", "control", "default", - "else", "enum", "error", "exit", "extern", "false", "header", "header_union", - "if", "in", "inout", "int", "key", "match_kind", "out", "parser", - "package", "return", "select", "set", "state", "struct", "switch", "table", - "this", // experimental - "transition", "true", "tuple", "typedef", "varbit", "verify", "void", "_", - "NoAction" // core.p4 +const std::set reservedWords = { + "abstract"_cs, // experimental + "action"_cs, "actions"_cs, "apply"_cs, "bool"_cs, "bit"_cs, "const"_cs, + "control"_cs, "default"_cs, "else"_cs, "enum"_cs, "error"_cs, "exit"_cs, + "extern"_cs, "false"_cs, "header"_cs, "header_union"_cs, "if"_cs, "in"_cs, + "inout"_cs, "int"_cs, "key"_cs, "match_kind"_cs, "out"_cs, "parser"_cs, + "package"_cs, "return"_cs, "select"_cs, "set"_cs, "state"_cs, "struct"_cs, + "switch"_cs, "table"_cs, + "this"_cs, // experimental + "transition"_cs, "true"_cs, "tuple"_cs, "typedef"_cs, "varbit"_cs, "verify"_cs, + "void"_cs, "_"_cs, + "NoAction"_cs // core.p4 }; } // namespace P4 diff --git a/frontends/p4/reservedWords.h b/frontends/p4/reservedWords.h index 5c52724cf3..be4a4c85e2 100644 --- a/frontends/p4/reservedWords.h +++ b/frontends/p4/reservedWords.h @@ -23,7 +23,7 @@ limitations under the License. namespace P4 { -extern std::set reservedWords; +extern const std::set reservedWords; } // namespace P4 diff --git a/frontends/p4/simplifyDefUse.cpp b/frontends/p4/simplifyDefUse.cpp index 85eb04d1ee..579d206093 100644 --- a/frontends/p4/simplifyDefUse.cpp +++ b/frontends/p4/simplifyDefUse.cpp @@ -1035,12 +1035,10 @@ class FindUninitialized : public Inspector { // This could happen if we are writing to an array element // with an unknown index. auto type = typeMap->getType(expression, true); - cstring message; - if (type->is()) - message = "%1% may be uninitialized"; - else - message = "%1% may not be completely initialized"; - warn(ErrorType::WARN_UNINITIALIZED_USE, message, expression); + warn(ErrorType::WARN_UNINITIALIZED_USE, + type->is() ? "%1% may be uninitialized" + : "%1% may not be completely initialized", + expression); } hasUses->add(points); diff --git a/frontends/p4/specialize.cpp b/frontends/p4/specialize.cpp index 7200d9fe31..41643c5e34 100644 --- a/frontends/p4/specialize.cpp +++ b/frontends/p4/specialize.cpp @@ -64,7 +64,7 @@ const IR::Argument *SpecializationMap::convertArgument(const IR::Argument *arg, const IR::Parameter *param) { if (arg->expression->is()) { auto cce = arg->expression->to(); - cstring nName = refMap->newName(param->name); + cstring nName = refMap->newName(param->name.name.string_view()); IR::ID id(param->srcInfo, nName, param->name); auto decl = new IR::Declaration_Instance(param->srcInfo, id, cce->constructedType, cce->arguments); @@ -84,7 +84,7 @@ void SpecializationMap::addSpecialization(const IR::ConstructorCallExpression *i auto spec = new SpecializationInfo(invocation, cont, insertion); auto declaration = cont->to(); CHECK_NULL(declaration); - spec->name = refMap->newName(declaration->getName()); + spec->name = refMap->newName(declaration->getName().name.string_view()); auto cc = ConstructorCall::resolve(invocation, refMap, typeMap); auto ccc = cc->to(); CHECK_NULL(ccc); @@ -107,7 +107,7 @@ void SpecializationMap::addSpecialization(const IR::Declaration_Instance *invoca auto spec = new SpecializationInfo(invocation, cont, insertion); auto declaration = cont->to(); CHECK_NULL(declaration); - spec->name = refMap->newName(declaration->getName()); + spec->name = refMap->newName(declaration->getName().name.string_view()); const IR::Type_Name *type; const IR::Vector *typeArgs; if (invocation->type->is()) { diff --git a/frontends/p4/specializeGenericFunctions.h b/frontends/p4/specializeGenericFunctions.h index 76d321aee9..107342dc77 100644 --- a/frontends/p4/specializeGenericFunctions.h +++ b/frontends/p4/specializeGenericFunctions.h @@ -59,7 +59,7 @@ struct FunctionSpecializationMap { void add(const IR::MethodCallExpression *mce, const IR::Function *func, const IR::Node *insert) { - cstring name = refMap->newName(func->name); + cstring name = refMap->newName(func->name.name.string_view()); FunctionSpecialization *fs = new FunctionSpecialization(name, mce, func, insert); map.emplace(mce, fs); } diff --git a/frontends/p4/specializeGenericTypes.cpp b/frontends/p4/specializeGenericTypes.cpp index 109e99d06a..9ae94c8865 100644 --- a/frontends/p4/specializeGenericTypes.cpp +++ b/frontends/p4/specializeGenericTypes.cpp @@ -49,7 +49,7 @@ void TypeSpecializationMap::add(const IR::Type_Specialized *t, const IR::Type_St } } - cstring name = refMap->newName(decl->getName()); + cstring name = refMap->newName(decl->getName().name.string_view()); LOG3("Found to specialize: " << dbp(t) << "(" << t << ") with name " << name << " insert before " << dbp(insertion)); auto argTypes = new IR::Vector(); diff --git a/frontends/p4/staticAssert.h b/frontends/p4/staticAssert.h index 5bc3424e40..6f00a3dd23 100644 --- a/frontends/p4/staticAssert.h +++ b/frontends/p4/staticAssert.h @@ -23,6 +23,8 @@ limitations under the License. namespace P4 { +using namespace literals; + /** * Evaluates static_assert invocations. * A successful assertion is constant-folded to 'true'. @@ -32,6 +34,9 @@ class DoStaticAssert : public Transform { TypeMap *typeMap; bool removeStatement; + // Cannot go static here as cstring is not constexpr + const cstring staticAssertMethodName = "static_assert"_cs; + public: DoStaticAssert(ReferenceMap *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap), removeStatement(false) { @@ -42,7 +47,7 @@ class DoStaticAssert : public Transform { const IR::Node *postorder(IR::MethodCallExpression *method) override { MethodInstance *mi = MethodInstance::resolve(method, refMap, typeMap); if (auto ef = mi->to()) { - if (ef->method->name == "static_assert") { + if (ef->method->name == staticAssertMethodName) { auto subst = ef->substitution; auto params = subst.getParametersInOrder(); if (!params->moveNext()) { @@ -56,7 +61,7 @@ class DoStaticAssert : public Transform { CHECK_NULL(arg); if (auto bl = arg->expression->to()) { if (!bl->value) { - cstring message = "static_assert failed"; + cstring message = "static_assert failed"_cs; if (params->moveNext()) { param = params->getCurrent(); CHECK_NULL(param); diff --git a/frontends/p4/strengthReduction.h b/frontends/p4/strengthReduction.h index 0acee86a8e..896c188fe2 100644 --- a/frontends/p4/strengthReduction.h +++ b/frontends/p4/strengthReduction.h @@ -25,6 +25,8 @@ limitations under the License. namespace P4 { +using namespace literals; + /** Implements a pass that replaces expensive arithmetic and boolean * operations with cheaper ones -- i.e., strength reduction * @@ -107,7 +109,7 @@ class DoStrengthReduction final : public Transform { const IR::Node *postorder(IR::ArrayIndex *expr) override; const IR::BlockStatement *preorder(IR::BlockStatement *bs) override { - if (bs->annotations->getSingle("disable_optimization")) prune(); + if (bs->annotations->getSingle("disable_optimization"_cs)) prune(); return bs; } }; diff --git a/frontends/p4/symbol_table.cpp b/frontends/p4/symbol_table.cpp index 86fe3351de..5d64425f07 100644 --- a/frontends/p4/symbol_table.cpp +++ b/frontends/p4/symbol_table.cpp @@ -18,12 +18,15 @@ limitations under the License. #include +#include "lib/cstring.h" #include "lib/error.h" #include "lib/exceptions.h" #include "lib/log.h" namespace Util { +using namespace P4::literals; + class NamedSymbol : public ICastable { protected: Util::SourceInfo sourceInfo; @@ -93,7 +96,7 @@ class Namespace : public NamedSymbol { if (it == contents.end()) return nullptr; return it->second; } - cstring toString() const override { return cstring("Namespace ") + getName(); } + cstring toString() const override { return "Namespace "_cs + getName(); } void dump(std::stringstream &into, unsigned indent) const override { std::string s(indent, ' '); into << s; @@ -108,7 +111,7 @@ class Namespace : public NamedSymbol { DECLARE_TYPEINFO(Namespace, NamedSymbol); }; -const Namespace Namespace::empty("", Util::SourceInfo(), false); +const Namespace Namespace::empty(""_cs, Util::SourceInfo(), false); const Namespace *NamedSymbol::symNamespace() const { return &Namespace::empty; } class Object : public NamedSymbol { @@ -116,7 +119,7 @@ class Object : public NamedSymbol { public: Object(cstring name, Util::SourceInfo si) : NamedSymbol(name, si) {} - cstring toString() const override { return cstring("Object ") + getName(); } + cstring toString() const override { return "Object "_cs + getName(); } const Namespace *symNamespace() const override { return typeNamespace; } void setNamespace(const Namespace *ns) { typeNamespace = ns; } @@ -126,7 +129,7 @@ class Object : public NamedSymbol { class SimpleType : public NamedSymbol { public: SimpleType(cstring name, Util::SourceInfo si) : NamedSymbol(name, si) {} - cstring toString() const override { return cstring("SimpleType ") + getName(); } + cstring toString() const override { return "SimpleType "_cs + getName(); } DECLARE_TYPEINFO(SimpleType, NamedSymbol); }; @@ -136,7 +139,7 @@ class ContainerType : public Namespace { public: ContainerType(cstring name, Util::SourceInfo si, bool allowDuplicates) : Namespace(name, si, allowDuplicates) {} - cstring toString() const override { return cstring("ContainerType ") + getName(); } + cstring toString() const override { return "ContainerType "_cs + getName(); } DECLARE_TYPEINFO(ContainerType, Namespace); }; @@ -145,7 +148,7 @@ class ContainerType : public Namespace { ProgramStructure::ProgramStructure() : debug(false), debugStream(nullptr), rootNamespace(nullptr), currentNamespace(nullptr) { - rootNamespace = new Namespace("", Util::SourceInfo(), true); + rootNamespace = new Namespace(cstring::empty, Util::SourceInfo(), true); currentNamespace = rootNamespace; // We use stderr because we want debugging output // to be the same as the bison debugging output. @@ -164,7 +167,7 @@ void ProgramStructure::push(Namespace *ns) { void ProgramStructure::pushNamespace(SourceInfo si, bool allowDuplicates) { // Today we don't have named namespaces - auto ns = new Util::Namespace("", si, allowDuplicates); + auto ns = new Util::Namespace(cstring::empty, si, allowDuplicates); push(ns); } diff --git a/frontends/p4/tableKeyNames.cpp b/frontends/p4/tableKeyNames.cpp index b5db5ac866..6be5f23fcf 100644 --- a/frontends/p4/tableKeyNames.cpp +++ b/frontends/p4/tableKeyNames.cpp @@ -18,6 +18,8 @@ limitations under the License. namespace P4 { +using namespace literals; + void KeyNameGenerator::error(const IR::Expression *expression) { ::error(ErrorType::ERR_EXPECTED, "%1%: Complex key expression requires a @name annotation", expression); @@ -31,6 +33,11 @@ void KeyNameGenerator::postorder(const IR::PathExpression *expression) { namespace { +// The constants are used below. We use `$valid$` to represent `isValid()` calls +// on headers and header unions; this is what P4Runtime expects. +static const cstring isValid = "isValid"_cs; +static const cstring isValidKey = "$valid$"_cs; + /// @return a canonicalized string representation of the given Member /// expression's right-hand side, suitable for use as part of a key name. cstring keyComponentNameForMember(const IR::Member *expression, const P4::TypeMap *typeMap) { @@ -46,7 +53,7 @@ cstring keyComponentNameForMember(const IR::Member *expression, const P4::TypeMa // SynthesizeValidField, which leaves `isValid()` as-is for header unions, // but that's a BMV2-specific thing. if (type->is() || type->is()) - if (expression->member == "isValid") return "$valid$"; + if (expression->member == isValid) return isValidKey; // If this Member represents a field which has an @name annotation, use it. if (type->is()) { @@ -73,7 +80,7 @@ void KeyNameGenerator::postorder(const IR::Member *expression) { // We can generate a name for the overall Member expression only if we were // able to generate a name for its left-hand side. - if (cstring n = getName(expression->expr)) name.emplace(expression, n + "." + fname); + if (cstring n = getName(expression->expr)) name.emplace(expression, n + "."_cs + fname); } void KeyNameGenerator::postorder(const IR::ArrayIndex *expression) { diff --git a/frontends/p4/ternaryBool.cpp b/frontends/p4/ternaryBool.cpp index c7283c8a4a..0aa136fa91 100644 --- a/frontends/p4/ternaryBool.cpp +++ b/frontends/p4/ternaryBool.cpp @@ -16,19 +16,23 @@ limitations under the License. #include "ternaryBool.h" +#include "lib/cstring.h" + namespace P4 { +using namespace literals; + cstring toString(const TernaryBool &c) { switch (c) { case TernaryBool::Yes: - return "Yes"; + return "Yes"_cs; case TernaryBool::No: - return "No"; + return "No"_cs; ; case TernaryBool::Maybe: - return "Maybe"; + return "Maybe"_cs; } - return ""; + return cstring::empty; } } // namespace P4 diff --git a/frontends/p4/toP4/toP4.cpp b/frontends/p4/toP4/toP4.cpp index a6d312571a..96ddcdcb9a 100644 --- a/frontends/p4/toP4/toP4.cpp +++ b/frontends/p4/toP4/toP4.cpp @@ -173,15 +173,17 @@ bool ToP4::preorder(const IR::P4Program *program) { program->apply(g); builder.append("#define V1MODEL_VERSION "); builder.append(g.version); - builder.appendLine(""); + builder.newline(); } builder.append("#include <"); builder.append(p); - builder.appendLine(">"); + builder.append(">"); + builder.newline(); } else { builder.append("#include \""); builder.append(sourceFile); - builder.appendLine("\""); + builder.append("\""); + builder.newline(); } includesEmitted.emplace(sourceFile); } @@ -872,8 +874,8 @@ bool ToP4::preorder(const IR::SelectExpression *e) { bool ToP4::preorder(const IR::ListExpression *e) { cstring start, end; if (listTerminators.empty()) { - start = "{ "; - end = " }"; + start = "{ "_cs; + end = " }"_cs; } else { start = listTerminators.back().start; end = listTerminators.back().end; diff --git a/frontends/p4/typeChecking/typeChecker.cpp b/frontends/p4/typeChecking/typeChecker.cpp index 0b04393d3f..530570768c 100644 --- a/frontends/p4/typeChecking/typeChecker.cpp +++ b/frontends/p4/typeChecking/typeChecker.cpp @@ -25,6 +25,7 @@ limitations under the License. #include "frontends/p4/methodInstance.h" #include "frontends/p4/toP4/toP4.h" #include "lib/algorithm.h" +#include "lib/cstring.h" #include "lib/log.h" #include "syntacticEquivalence.h" #include "typeConstraints.h" @@ -220,7 +221,7 @@ void TypeInference::addSubstitutions(const TypeVariableSubstitution *tvs) { TypeVariableSubstitution *TypeInference::unifyBase( bool allowCasts, const IR::Node *errorPosition, const IR::Type *destType, - const IR::Type *srcType, cstring errorFormat, + const IR::Type *srcType, std::string_view errorFormat, std::initializer_list errorArgs) { CHECK_NULL(destType); CHECK_NULL(srcType); @@ -232,7 +233,7 @@ TypeVariableSubstitution *TypeInference::unifyBase( constraint = new CanBeImplicitlyCastConstraint(destType, srcType, errorPosition); else constraint = new EqualityConstraint(destType, srcType, errorPosition); - if (!errorFormat.isNullOrEmpty()) constraint->setError(errorFormat, errorArgs); + if (!errorFormat.empty()) constraint->setError(errorFormat, errorArgs); constraints.add(constraint); auto tvs = constraints.solve(); addSubstitutions(tvs); @@ -788,7 +789,7 @@ const IR::Expression *TypeInference::assignment(const IR::Node *errorPosition, if (src != compI->expression) changes = true; vec.push_back(new IR::NamedExpression(fieldI->name, src)); } - if (hasDots) vec.push_back(si->getField("...")); + if (hasDots) vec.push_back(si->getField("..."_cs)); if (!changes) vec = si->components; if (initType->is() || changes) { sourceExpression = new IR::StructExpression(type, type, vec); @@ -979,7 +980,7 @@ std::pair *> TypeInference::che } // will always be bound to Type_Void. - auto rettype = new IR::Type_Var(IR::ID(refMap->newName("R"), "")); + auto rettype = new IR::Type_Var(IR::ID(refMap->newName("R"), ""_cs)); auto callType = new IR::Type_MethodCall(errorPosition->srcInfo, new IR::Vector(), rettype, args); auto tvs = unify(errorPosition, methodType, callType, @@ -1087,7 +1088,7 @@ bool TypeInference::checkAbstractMethods(const IR::Declaration_Instance *inst, } bool rv = true; for (auto &vm : virt) { - if (!vm.second->annotations->getSingle("optional")) { + if (!vm.second->annotations->getSingle("optional"_cs)) { typeError("%1%: %2% abstract method not implemented", inst, vm.second); rv = false; } @@ -3276,7 +3277,7 @@ const IR::Node *TypeInference::postorder(IR::Member *expression) { } if (type->is()) { - cstring typeStr = "structure "; + std::string typeStr = "structure "; if (type->is() || type->is()) { typeStr = ""; if (inMethod && (member == IR::Type_Header::isValid)) { @@ -3380,7 +3381,7 @@ const IR::Node *TypeInference::postorder(IR::Member *expression) { if (!isLeftValue(expression->expr)) typeError("%1%: must be applied to a left-value", expression); auto params = new IR::IndexedVector(); - auto param = new IR::Parameter(IR::ID("count", nullptr), IR::Direction::None, + auto param = new IR::Parameter(IR::ID("count"_cs, nullptr), IR::Direction::None, IR::Type_InfInt::get()); auto tt = new IR::Type_Type(param->type); setType(param->type, tt); @@ -3700,7 +3701,7 @@ const IR::Node *TypeInference::postorder(IR::MethodCallExpression *expression) { // We build a type for the callExpression and unify it with the method expression // Allocate a fresh variable for the return type; it will be hopefully bound in the process. - auto rettype = new IR::Type_Var(IR::ID(refMap->newName("R"), "")); + auto rettype = new IR::Type_Var(IR::ID(refMap->newName("R"), ""_cs)); auto args = new IR::Vector(); bool constArgs = true; for (auto aarg : *expression->arguments) { diff --git a/frontends/p4/typeChecking/typeChecker.h b/frontends/p4/typeChecking/typeChecker.h index c146284283..d620793a67 100644 --- a/frontends/p4/typeChecking/typeChecker.h +++ b/frontends/p4/typeChecking/typeChecker.h @@ -117,20 +117,20 @@ class TypeInference : public Transform { TypeVariableSubstitution *unifyBase(bool allowCasts, const IR::Node *errorPosition, const IR::Type *destType, const IR::Type *srcType, - cstring errorFormat, + std::string_view errorFormat, std::initializer_list errorArgs); /// Unifies two types. Returns nullptr if unification fails. /// Populates the typeMap with values for the type variables. /// This allows an implicit cast from the right type to the left type. TypeVariableSubstitution *unifyCast(const IR::Node *errorPosition, const IR::Type *destType, - const IR::Type *srcType, cstring errorFormat = nullptr, + const IR::Type *srcType, std::string_view errorFormat = {}, std::initializer_list errorArgs = {}) { return unifyBase(true, errorPosition, destType, srcType, errorFormat, errorArgs); } /// Same as above, not allowing casts TypeVariableSubstitution *unify(const IR::Node *errorPosition, const IR::Type *destType, - const IR::Type *srcType, cstring errorFormat = nullptr, + const IR::Type *srcType, std::string_view errorFormat = {}, std::initializer_list errorArgs = {}) { return unifyBase(false, errorPosition, destType, srcType, errorFormat, errorArgs); } diff --git a/frontends/p4/typeChecking/typeConstraints.h b/frontends/p4/typeChecking/typeConstraints.h index dbafff929f..74319040f0 100644 --- a/frontends/p4/typeChecking/typeConstraints.h +++ b/frontends/p4/typeChecking/typeConstraints.h @@ -80,8 +80,8 @@ class TypeConstraint : public IHasDbPrint, public ICastable { std::string localError(Explain *explainer) const; public: - void setError(cstring format, std::initializer_list nodes) { - errFormat = format; + void setError(std::string_view format, std::initializer_list nodes) { + errFormat = cstring(format); errArguments = nodes; } template diff --git a/frontends/p4/typeChecking/typeSubstitution.cpp b/frontends/p4/typeChecking/typeSubstitution.cpp index e6fd139978..75d3009602 100644 --- a/frontends/p4/typeChecking/typeSubstitution.cpp +++ b/frontends/p4/typeChecking/typeSubstitution.cpp @@ -17,14 +17,18 @@ limitations under the License. #include "typeSubstitution.h" #include "frontends/p4/typeMap.h" +#include "lib/cstring.h" #include "typeConstraints.h" #include "typeSubstitutionVisitor.h" namespace P4 { +using namespace literals; + +// FIXME: see if we can not return format string as cstring here cstring TypeVariableSubstitution::compose(const IR::ITypeVar *var, const IR::Type *substitution) { LOG3("Adding " << var << "->" << dbp(substitution) << "=" << substitution << " to substitution"); - if (substitution->is()) return ""; + if (substitution->is()) return cstring::empty; // Type variables that represent Type_InfInt can only be unified to bit<> types // or to other Type_InfInt types. @@ -35,7 +39,7 @@ cstring TypeVariableSubstitution::compose(const IR::ITypeVar *var, const IR::Typ if (!substitution->is() && !substitution->is() && !substitution->is()) { return "'%1%' type can only be unified with 'int', 'bit<>', or 'signed<>' types, " - "not with '%2%'"; + "not with '%2%'"_cs; } } @@ -43,7 +47,7 @@ cstring TypeVariableSubstitution::compose(const IR::ITypeVar *var, const IR::Typ // It is not if var occurs in substitution TypeOccursVisitor occurs(var); substitution->apply(occurs); - if (occurs.occurs) return "'%1%' cannot be replaced with '%2%' which already contains it"; + if (occurs.occurs) return "'%1%' cannot be replaced with '%2%' which already contains it"_cs; // Check to see whether we already have a binding for this variable if (containsKey(var)) { @@ -62,7 +66,7 @@ cstring TypeVariableSubstitution::compose(const IR::ITypeVar *var, const IR::Typ for (auto &bound : binding) { const IR::Type *type = bound.second; const IR::Node *newType = type->apply(visitor); - if (newType == nullptr) return "Could not replace '%1%' with '%2%'"; + if (newType == nullptr) return "Could not replace '%1%' with '%2%'"_cs; if (newType == type) continue; if (bound.first->asType() == newType) { @@ -81,7 +85,7 @@ cstring TypeVariableSubstitution::compose(const IR::ITypeVar *var, const IR::Typ success = setBinding(var, substitution); if (!success) BUG("Failed to insert binding"); } - return ""; + return cstring::empty; } void TypeVariableSubstitution::simpleCompose(const TypeVariableSubstitution *other) { diff --git a/frontends/p4/typeChecking/typeUnification.cpp b/frontends/p4/typeChecking/typeUnification.cpp index a0d11510e0..fcbe426cd9 100644 --- a/frontends/p4/typeChecking/typeUnification.cpp +++ b/frontends/p4/typeChecking/typeUnification.cpp @@ -22,6 +22,8 @@ limitations under the License. namespace P4 { +using namespace literals; + /// Unifies a call with a prototype. bool TypeUnification::unifyCall(const BinaryConstraint *constraint) { // These are canonical types. @@ -408,7 +410,7 @@ bool TypeUnification::unify(const BinaryConstraint *constraint) { } if (stHasDots) { auto dotsType = new IR::Type_UnknownStruct(st->name, *missingFields); - auto dotsField = st->getField("..."); + auto dotsField = st->getField("..."_cs); CHECK_NULL(dotsField); auto partial = new IR::Type_Fragment(dotsType); constraints->add(new EqualityConstraint(dotsField->type, partial, constraint)); diff --git a/frontends/p4/uniqueNames.h b/frontends/p4/uniqueNames.h index 039c4b5511..4c5a5bc5f7 100644 --- a/frontends/p4/uniqueNames.h +++ b/frontends/p4/uniqueNames.h @@ -90,7 +90,7 @@ class FindSymbols : public Inspector { setName("FindSymbols"); } void doDecl(const IR::Declaration *decl) { - cstring newName = refMap->newName(decl->getName()); + cstring newName = refMap->newName(decl->getName().name.string_view()); renameMap->setNewName(decl, newName); } void postorder(const IR::Declaration_Variable *decl) override { doDecl(decl); } @@ -166,7 +166,7 @@ class FindParameters : public Inspector { void doParameters(const IR::ParameterList *pl) { for (auto p : pl->parameters) { - cstring newName = refMap->newName(p->name); + cstring newName = refMap->newName(p->name.name.string_view()); renameMap->setNewName(p, newName); } } diff --git a/frontends/p4/validateParsedProgram.h b/frontends/p4/validateParsedProgram.h index 22f8955869..62d1ac41be 100644 --- a/frontends/p4/validateParsedProgram.h +++ b/frontends/p4/validateParsedProgram.h @@ -22,6 +22,8 @@ limitations under the License. namespace P4 { +using namespace literals; + /** This pass performs some simple semantic checks on the program; since the grammar accepts many programs that are actually illegal, @@ -81,7 +83,7 @@ class ValidateParsedProgram final : public Inspector { control->getConstructorParameters()); } void postorder(const IR::P4Parser *parser) override { - auto start = parser->states.getDeclaration("start"); + auto start = parser->states.getDeclaration(IR::ParserState::start); if (!start) { ::error(ErrorType::ERR_INVALID, "Parser %1% has no 'start' state", parser); } diff --git a/frontends/parsers/p4/p4lexer.ll b/frontends/parsers/p4/p4lexer.ll index 78bad60e35..c4143540b6 100644 --- a/frontends/parsers/p4/p4lexer.ll +++ b/frontends/parsers/p4/p4lexer.ll @@ -204,7 +204,7 @@ using Parser = P4::P4Parser; [A-Za-z_][A-Za-z0-9_]* { BEGIN(driver.saveState); driver.template_args = false; - cstring name = yytext; + cstring name = cstring(yytext); Util::ProgramStructure::SymbolKind kind = driver.structure->lookupIdentifier(name); switch (kind) @@ -229,44 +229,44 @@ using Parser = P4::P4Parser; 0[xX][0-9a-fA-F_]+ { BEGIN(driver.saveState); driver.template_args = false; - UnparsedConstant constant{yytext, 2, 16, false}; + UnparsedConstant constant{cstring(yytext), 2, 16, false}; return Parser::make_INTEGER(constant, driver.yylloc); } 0[dD][0-9_]+ { BEGIN(driver.saveState); driver.template_args = false; - UnparsedConstant constant{yytext, 2, 10, false}; + UnparsedConstant constant{cstring(yytext), 2, 10, false}; return Parser::make_INTEGER(constant, driver.yylloc); } 0[oO][0-7_]+ { BEGIN(driver.saveState); driver.template_args = false; - UnparsedConstant constant{yytext, 2, 8, false}; + UnparsedConstant constant{cstring(yytext), 2, 8, false}; return Parser::make_INTEGER(constant, driver.yylloc); } 0[bB][01_]+ { BEGIN(driver.saveState); driver.template_args = false; - UnparsedConstant constant{yytext, 2, 2, false}; + UnparsedConstant constant{cstring(yytext), 2, 2, false}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9][0-9_]* { BEGIN(driver.saveState); driver.template_args = false; - UnparsedConstant constant{yytext, 0, 10, false}; + UnparsedConstant constant{cstring(yytext), 0, 10, false}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ws]0[xX][0-9a-fA-F_]+ { BEGIN(driver.saveState); driver.template_args = false; - UnparsedConstant constant{yytext, 2, 16, true}; + UnparsedConstant constant{cstring(yytext), 2, 16, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ws]0[dD][0-9_]+ { BEGIN(driver.saveState); driver.template_args = false; - UnparsedConstant constant{yytext, 2, 10, true}; + UnparsedConstant constant{cstring(yytext), 2, 10, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ws]0[oO][0-7_]+ { BEGIN(driver.saveState); driver.template_args = false; - UnparsedConstant constant{yytext, 2, 8, true}; + UnparsedConstant constant{cstring(yytext), 2, 8, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ws]0[bB][01_]+ { BEGIN(driver.saveState); driver.template_args = false; - UnparsedConstant constant{yytext, 2, 2, true}; + UnparsedConstant constant{cstring(yytext), 2, 2, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ws][0-9_]+ { BEGIN(driver.saveState); driver.template_args = false; - UnparsedConstant constant{yytext, 0, 10, true}; + UnparsedConstant constant{cstring(yytext), 0, 10, true}; return Parser::make_INTEGER(constant, driver.yylloc); } "&&&" { BEGIN(driver.saveState); driver.template_args = false; return makeToken(MASK); } diff --git a/frontends/parsers/p4/p4parser.ypp b/frontends/parsers/p4/p4parser.ypp index b3d9857aa3..85e7b9a287 100644 --- a/frontends/parsers/p4/p4parser.ypp +++ b/frontends/parsers/p4/p4parser.ypp @@ -94,14 +94,17 @@ typedef const IR::Type ConstType; #define YY_NULLPTR nullptr namespace P4 { +using namespace literals; + class Token { public: int type; cstring text; UnparsedConstant* unparsedConstant; - Token() : Token(0, "", nullptr) { } + Token() : Token(0, cstring::empty, nullptr) { } Token(int type, cstring text) : Token(type, text, nullptr) { } + Token(int type, const char* text) : Token(type, cstring(text), nullptr) { } Token(int type, UnparsedConstant unparsedConstant) : Token(type, unparsedConstant.text, new UnparsedConstant(unparsedConstant)) { } @@ -440,7 +443,7 @@ fragment // TODO: Could this be redesigned to avoid this hack? p4rtControllerType : STRING - { $$ = new IR::StringLiteral(@1, ""); } + { $$ = new IR::StringLiteral(@1, ""_cs); } | BIT l_angle INTEGER r_angle { $$ = new IR::Constant(parseConstantChecked(@3, $3)); } // Legacy syntax; to be removed in P4RT 2.0 @@ -471,28 +474,28 @@ declaration nonTypeName : IDENTIFIER { $$ = new IR::ID(@1, $1); } - | APPLY { $$ = new IR::ID(@1, "apply"); } - | KEY { $$ = new IR::ID(@1, "key"); } - | ACTIONS { $$ = new IR::ID(@1, "actions"); } - | STATE { $$ = new IR::ID(@1, "state"); } - | ENTRIES { $$ = new IR::ID(@1, "entries"); } - | TYPE { $$ = new IR::ID(@1, "type"); } - | PRIORITY { $$ = new IR::ID(@1, "priority"); } + | APPLY { $$ = new IR::ID(@1, "apply"_cs); } + | KEY { $$ = new IR::ID(@1, "key"_cs); } + | ACTIONS { $$ = new IR::ID(@1, "actions"_cs); } + | STATE { $$ = new IR::ID(@1, "state"_cs); } + | ENTRIES { $$ = new IR::ID(@1, "entries"_cs); } + | TYPE { $$ = new IR::ID(@1, "type"_cs); } + | PRIORITY { $$ = new IR::ID(@1, "priority"_cs); } ; name : nonTypeName { $$ = $1; } - | LIST { $$ = new IR::ID(@1, "list"); } + | LIST { $$ = new IR::ID(@1, "list"_cs); } | TYPE_IDENTIFIER { $$ = new IR::ID(@1, $1); } ; nonTableKwName : IDENTIFIER { $$ = new IR::ID(@1, $1); } | TYPE_IDENTIFIER { $$ = new IR::ID(@1, $1); } - | APPLY { $$ = new IR::ID(@1, "apply"); } - | STATE { $$ = new IR::ID(@1, "state"); } - | TYPE { $$ = new IR::ID(@1, "type"); } - | PRIORITY { $$ = new IR::ID(@1, "priority"); } + | APPLY { $$ = new IR::ID(@1, "apply"_cs); } + | STATE { $$ = new IR::ID(@1, "state"_cs); } + | TYPE { $$ = new IR::ID(@1, "type"_cs); } + | PRIORITY { $$ = new IR::ID(@1, "priority"_cs); } ; optCONST @@ -1021,7 +1024,7 @@ specializedType baseType : BOOL { $$ = IR::Type_Boolean::get(@1); } | MATCH_KIND { $$ = IR::Type_MatchKind::get(@1); } - | ERROR { $$ = new IR::Type_Name(@1, new IR::Path(IR::ID(@1, "error"))); } + | ERROR { $$ = new IR::Type_Name(@1, new IR::Path(IR::ID(@1, "error"_cs))); } | BIT { $$ = IR::Type::Bits::get(@1, 1); } | STRING { $$ = IR::Type::String::get(@1); } | INT { $$ = IR::Type_InfInt::get(@1); } @@ -1160,7 +1163,7 @@ specifiedIdentifier errorDeclaration : ERROR "{" identifierList "}" - { $$ = new IR::Type_Error(@1 + @4, IR::ID(@1, "error"), *$3); } + { $$ = new IR::Type_Error(@1 + @4, IR::ID(@1, "error"_cs), *$3); } ; matchKindDeclaration @@ -1239,12 +1242,12 @@ continueStatement directApplication : typeName "." APPLY "(" argumentList ")" ";" { auto method = new IR::Member( - @1 + @3, new IR::TypeNameExpression($1), IR::ID(@3, "apply")); + @1 + @3, new IR::TypeNameExpression($1), IR::ID(@3, "apply"_cs)); auto mce = new IR::MethodCallExpression(@1 + @6, method, $5); $$ = new IR::MethodCallStatement(@1 + @6, mce); } | specializedType "." APPLY "(" argumentList ")" ";" { auto method = new IR::Member( - @1 + @3, new IR::TypeNameExpression($1), IR::ID(@3, "apply")); + @1 + @3, new IR::TypeNameExpression($1), IR::ID(@3, "apply"_cs)); auto mce = new IR::MethodCallExpression(@1 + @6, method, $5); $$ = new IR::MethodCallStatement(@1 + @6, mce); } ; @@ -1369,15 +1372,15 @@ tablePropertyList tableProperty : KEY "=" "{" keyElementList "}" { auto v = new IR::Key(@4, *$4); - auto id = IR::ID(@1, "key"); + auto id = IR::ID(@1, "key"_cs); $$ = new IR::Property( @1 + @5, id, v, false); } | ACTIONS "=" "{" actionList "}" { auto v = new IR::ActionList(@4, *$4); - auto id = IR::ID(@1, "actions"); + auto id = IR::ID(@1, "actions"_cs); $$ = new IR::Property(@1 + @5, id, v, false); } | optAnnotations optCONST ENTRIES "=" "{" entriesList "}" { auto l = new IR::EntriesList(@3, *$6); - auto id = IR::ID(@3+@7, "entries"); + auto id = IR::ID(@3+@7, "entries"_cs); $$ = new IR::Property(@3, id, $1, l, $2.isConst); } | optAnnotations optCONST nonTableKwName "=" initializer ";" { auto v = new IR::ExpressionValue(@5, $5); @@ -1569,7 +1572,7 @@ expression | typeName dot_name %prec DOT { $$ = new IR::Member(@1 + @2, new IR::TypeNameExpression(@1, $1), *$2); } | ERROR "." name - { auto typeName = new IR::Type_Name(@1, new IR::Path(IR::ID(@1, "error"))); + { auto typeName = new IR::Type_Name(@1, new IR::Path(IR::ID(@1, "error"_cs))); $$ = new IR::Member(@1+@3, new IR::TypeNameExpression(@1+@3, typeName), *$3); } | expression dot_name %prec DOT { $$ = new IR::Member(@1 + @2, $1, *$2); } | expression "*" expression { $$ = new IR::Mul(@1 + @3, $1, $3); } @@ -1622,7 +1625,7 @@ nonBraceExpression | typeName dot_name %prec DOT { $$ = new IR::Member(@1 + @2, new IR::TypeNameExpression(@1, $1), *$2); } | ERROR "." name - { auto typeName = new IR::Type_Name(@1, new IR::Path(IR::ID(@1, "error"))); + { auto typeName = new IR::Type_Name(@1, new IR::Path(IR::ID(@1, "error"_cs))); $$ = new IR::Member(@1+@3, new IR::TypeNameExpression(@1+@3, typeName), *$3); } | nonBraceExpression dot_name %prec DOT { $$ = new IR::Member(@1 + @2, $1, *$2); } | nonBraceExpression "*" expression { $$ = new IR::Mul(@1 + @3, $1, $3); } diff --git a/frontends/parsers/parserDriver.cpp b/frontends/parsers/parserDriver.cpp index 01a2f622a3..0734b0c85a 100644 --- a/frontends/parsers/parserDriver.cpp +++ b/frontends/parsers/parserDriver.cpp @@ -88,12 +88,12 @@ void AbstractParserDriver::onReadLineNumber(const char *text) { } void AbstractParserDriver::onReadComment(const char *text, bool lineComment) { - sources->addComment(yylloc, lineComment, text); + sources->addComment(yylloc, lineComment, cstring(text)); } void AbstractParserDriver::onReadFileName(const char *text) { lineDirectiveFile = cstring(text); - sources->mapLine(lineDirectiveFile, lineDirectiveLine); + sources->mapLine(text, lineDirectiveLine); } void AbstractParserDriver::onReadIdentifier(cstring id) { lastIdentifier = id; } diff --git a/frontends/parsers/v1/v1lexer.ll b/frontends/parsers/v1/v1lexer.ll index 564f8bcb0d..7688281df0 100644 --- a/frontends/parsers/v1/v1lexer.ll +++ b/frontends/parsers/v1/v1lexer.ll @@ -70,7 +70,7 @@ using Parser = V1::V1Parser; BEGIN((driver.saveState = PRAGMA_LINE)); return Parser::make_PRAGMA(cstring(V1Lexer::trim(yytext+7)), driver.yylloc); } "@pragma"[ \t]* { BEGIN((driver.saveState = PRAGMA_LINE)); - return Parser::make_PRAGMA("pragma", driver.yylloc); } + return Parser::make_PRAGMA(cstring::literal("pragma"), driver.yylloc); } "action" { BEGIN(driver.saveState); return Parser::make_ACTION(cstring(yytext), driver.yylloc); } @@ -253,65 +253,65 @@ using Parser = V1::V1Parser; return Parser::make_WRITES(cstring(yytext), driver.yylloc); } [A-Za-z_][A-Za-z0-9_]* { BEGIN(driver.saveState); - cstring name = yytext; + cstring name = cstring(yytext); driver.onReadIdentifier(name); return Parser::make_IDENTIFIER(name, driver.yylloc); } 0[xX][0-9a-fA-F_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 16, false}; + UnparsedConstant constant{cstring(yytext), 2, 16, false}; return Parser::make_INTEGER(constant, driver.yylloc); } 0[dD][0-9_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 10, false}; + UnparsedConstant constant{cstring(yytext), 2, 10, false}; return Parser::make_INTEGER(constant, driver.yylloc); } 0[oO][0-7_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 8, false}; + UnparsedConstant constant{cstring(yytext), 2, 8, false}; return Parser::make_INTEGER(constant, driver.yylloc); } 0[bB][01_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 2, false}; + UnparsedConstant constant{cstring(yytext), 2, 2, false}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 0, 10, false}; + UnparsedConstant constant{cstring(yytext), 0, 10, false}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ws']0[xX][0-9a-fA-F_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 16, true}; + UnparsedConstant constant{cstring(yytext), 2, 16, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ws']0[dD][0-9_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 10, true}; + UnparsedConstant constant{cstring(yytext), 2, 10, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ws']0[oO][0-7_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 8, true}; + UnparsedConstant constant{cstring(yytext), 2, 8, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ws']0[bB][01_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 2, true}; + UnparsedConstant constant{cstring(yytext), 2, 2, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ws'][0-9]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 0, 10, true}; + UnparsedConstant constant{cstring(yytext), 0, 10, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ \t\r]*['][ \t\r]*0[xX][0-9a-fA-F_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 16, true}; + UnparsedConstant constant{cstring(yytext), 2, 16, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ \t\r]*['][ \t\r]*0[dD][0-9_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 10, true}; + UnparsedConstant constant{cstring(yytext), 2, 10, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ \t\r]*['][ \t\r]*0[oO][0-7_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 8, true}; + UnparsedConstant constant{cstring(yytext), 2, 8, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ \t\r]*['][ \t\r]*0[bB][01_]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 2, 2, true}; + UnparsedConstant constant{cstring(yytext), 2, 2, true}; return Parser::make_INTEGER(constant, driver.yylloc); } [0-9]+[ \t\r]*['][ \t\r]*[0-9]+ { BEGIN(driver.saveState); - UnparsedConstant constant{yytext, 0, 10, true}; + UnparsedConstant constant{cstring(yytext), 0, 10, true}; return Parser::make_INTEGER(constant, driver.yylloc); } -[^ \t\r\n,][^ \t\r\n,]* { return Parser::make_STRING_LITERAL(yytext, driver.yylloc); } +[^ \t\r\n,][^ \t\r\n,]* { return Parser::make_STRING_LITERAL(cstring(yytext), driver.yylloc); } "<<" { BEGIN(driver.saveState); return Parser::make_SHL(driver.yylloc); } ">>" { BEGIN(driver.saveState); return Parser::make_SHR(driver.yylloc); } diff --git a/frontends/parsers/v1/v1parser.ypp b/frontends/parsers/v1/v1parser.ypp index 415050c832..189ed441e4 100644 --- a/frontends/parsers/v1/v1parser.ypp +++ b/frontends/parsers/v1/v1parser.ypp @@ -42,6 +42,8 @@ namespace V1 { class V1Lexer; class V1ParserDriver; +using namespace P4::literals; + struct BBoxType { IR::Vector* methods; IR::NameMap* attribs; @@ -500,7 +502,7 @@ parser_statement_list: /* epsilon */ | parser_statement_list SET_METADATA "(" expression "," expression ")" ";" { ($$=$1)->stmts.push_back(new IR::Primitive(@2+@7, $2, $4, $6)); } | parser_statement_list expression "=" expression ";" - { ($$=$1)->stmts.push_back(new IR::Primitive(@3, "set_metadata", $2, $4)); } + { ($$=$1)->stmts.push_back(new IR::Primitive(@3, "set_metadata"_cs, $2, $4)); } | parser_statement_list RETURN name ";" { ($$=$1)->default_return = IR::ID(@3, $3); } | parser_statement_list RETURN SELECT "(" expression_list ")" "{" case_entry_list "}" @@ -698,7 +700,7 @@ action_statement_list: /* epsilon */ | action_statement_list name "(" opt_expression_list ")" ";" { ($$ = $1)->action.push_back(new IR::Primitive(@2+@5, $2, $4)); } | action_statement_list field_ref "=" expression ";" - { ($$ = $1)->action.push_back(new IR::Primitive(@3, "modify_field", $2, $4)); } + { ($$ = $1)->action.push_back(new IR::Primitive(@3, "modify_field"_cs, $2, $4)); } | action_statement_list field_ref "(" opt_expression_list ")" ";" { ($$ = $1)->action.push_back(new IR::Primitive(@2+@5, $2->member, $2->expr, $4)); } | action_statement_list error ";" @@ -855,7 +857,7 @@ apply_case_list: /* epsilon */ { $$ = new IR::Apply; } } $$ = $1; } | apply_case_list DEFAULT control_statement - { ($$=$1)->actions["default"] = $3; } + { ($$=$1)->actions["default"_cs] = $3; } ; /************/ diff --git a/ir/base.cpp b/ir/base.cpp index 1e5b46d5a2..1511224024 100644 --- a/ir/base.cpp +++ b/ir/base.cpp @@ -37,12 +37,12 @@ cstring Annotation::getName() const { cstring Annotation::getSingleString() const { if (expr.size() != 1) { ::error(ErrorType::ERR_INVALID, "%1%: should contain a string", this); - return ""; + return cstring::empty; } auto str = expr[0]->to(); if (str == nullptr) { ::error(ErrorType::ERR_INVALID, "%1%: should contain a string", this); - return ""; + return cstring::empty; } return str->value; } diff --git a/ir/base.def b/ir/base.def index 02c3f49a31..68500cb97b 100644 --- a/ir/base.def +++ b/ir/base.def @@ -121,7 +121,7 @@ class Type_Unknown : Type_Base { #nodbprint static Type_Unknown get(); static Type_Unknown get(const Util::SourceInfo &si); - toString{ return "Unknown type"; } + toString{ return "Unknown type"_cs; } } /// A statement or a declaration @@ -191,13 +191,13 @@ class Path { toString{ // This is the ORIGINAL name the user used if (absolute) - return cstring(".") + name.toString(); + return "."_cs + name.toString(); return name.toString(); } cstring asString() const { // The CURRENT internal name if (absolute) - return cstring(".") + name; + return "."_cs + name; return name; } dbprint { out << name; } @@ -289,7 +289,7 @@ class Annotation { static const cstring matchAnnotation; /// Match annotation (for value sets). static const cstring fieldListAnnotation; /// Used for recirculate, etc. static const cstring debugLoggingAnnotation; /// Used by compiler implementer to limit debug log to the annotated IR context. - toString{ return cstring("@") + name; } + toString{ return "@"_cs + name; } validate{ BUG_CHECK(!name.name.isNullOrEmpty(), "empty annotation name"); BUG_CHECK(!(needsParsing && !expr.empty()), @@ -394,7 +394,7 @@ class Argument { dbprint { out << (name.name.isNullOrEmpty() ? "" : name.name + " = ") << expression; } validate { CHECK_NULL(expression); } toString{ - cstring result = ""; + std::string result = ""; if (!name.name.isNullOrEmpty()) result = name.toString() + " = "; return result + expression->toString(); diff --git a/ir/dump.cpp b/ir/dump.cpp index 7510d55cea..e161ea29a4 100644 --- a/ir/dump.cpp +++ b/ir/dump.cpp @@ -25,6 +25,8 @@ limitations under the License. #include "lib/indent.h" #include "lib/source_file.h" +using namespace P4::literals; + namespace { class IRDumper : public Inspector { std::ostream &out; @@ -81,19 +83,19 @@ void dump(const IR::Node *n) { dump(n, ~0U); } void dump(const IR::INode *n, unsigned maxdepth) { dump(std::cout, n->getNode(), maxdepth); } void dump(const IR::INode *n) { dump(n, ~0U); } void dump_notype(const IR::Node *n, unsigned maxdepth) { - n->apply(IRDumper(std::cout, maxdepth, "type", false)); + n->apply(IRDumper(std::cout, maxdepth, "type"_cs, false)); } void dump_notype(const IR::Node *n) { dump_notype(n, ~0U); } void dump_notype(const IR::INode *n, unsigned maxdepth) { - n->getNode()->apply(IRDumper(std::cout, maxdepth, "type", false)); + n->getNode()->apply(IRDumper(std::cout, maxdepth, "type"_cs, false)); } void dump_notype(const IR::INode *n) { dump_notype(n, ~0U); } void dump_src(const IR::Node *n, unsigned maxdepth) { - n->apply(IRDumper(std::cout, maxdepth, "type", true)); + n->apply(IRDumper(std::cout, maxdepth, "type"_cs, true)); } void dump_src(const IR::Node *n) { dump_src(n, ~0U); } void dump_src(const IR::INode *n, unsigned maxdepth) { - n->getNode()->apply(IRDumper(std::cout, maxdepth, "type", true)); + n->getNode()->apply(IRDumper(std::cout, maxdepth, "type"_cs, true)); } void dump_src(const IR::INode *n) { dump_src(n, ~0U); } diff --git a/ir/expression.def b/ir/expression.def index b3559a1fc0..c6b61cd17a 100644 --- a/ir/expression.def +++ b/ir/expression.def @@ -166,17 +166,17 @@ class LOr : Operation_Binary { /// Represents the ... default initializer expression class Dots : Expression { dbprint { out << "..."; } - toString { return "..."; } + toString { return "..."_cs; } } /// Represents the ... default initializer expression /// when used in a StructExpression. class NamedDots : NamedExpression { NamedDots() : NamedExpression("...", new Dots()) {} - NamedDots(Util::SourceInfo srcInfo, Dots dots) : NamedExpression(srcInfo, "...", dots) { CHECK_NULL(dots); } + NamedDots(Util::SourceInfo srcInfo, Dots dots) : NamedExpression(srcInfo, "..."_cs, dots) { CHECK_NULL(dots); } NamedDots(Util::SourceInfo srcInfo) : NamedExpression(srcInfo, "...", new Dots()) {} dbprint { out << "..."; } - toString { return "..."; } + toString { return "..."_cs; } } abstract Literal : Expression, CompileTimeValue {} @@ -283,7 +283,7 @@ class Constant : Literal { class BoolLiteral : Literal { bool value; - toString{ return value ? "true" : "false"; } + toString{ return value ? "true"_cs : "false"_cs; } /// @return a bool literal. Both booleans are interned. static const BoolLiteral *get(bool value, const Util::SourceInfo &si = {}); @@ -292,7 +292,7 @@ class BoolLiteral : Literal { class StringLiteral : Literal { cstring value; validate{ if (value.isNull()) BUG("null StringLiteral"); } - toString{ return cstring("\"") + value.escapeJson() + "\""; } + toString{ return "\""_cs + value.escapeJson() + "\""_cs; } StringLiteral(ID v) : Literal(v.srcInfo), value(v.name) {} #emit operator IR::ID() const { return IR::ID(srcInfo, value); } @@ -327,7 +327,7 @@ class TypeNameExpression : Expression { class Slice : Operation_Ternary { precedence = DBPrint::Prec_Postfix; stringOp = "[:]"; - toString{ return e0->toString() + "[" + e1->toString() + ":" + e2->toString() + "]"; } + toString{ return e0->toString() + "["_cs + e1->toString() + ":"_cs + e2->toString() + "]"_cs; } // After type checking e1 and e2 will be constants unsigned getH() const { return e1->to()->asUnsigned(); } unsigned getL() const { return e2->to()->asUnsigned(); } @@ -349,7 +349,7 @@ class Member : Operation_Unary { int lsb() const; int msb() const; stringOp = "."; - toString{ return expr->toString() + "." + member; } + toString{ return expr->toString() + "."_cs + member; } } class Concat : Operation_Binary { @@ -369,7 +369,7 @@ class ArrayIndex : Operation_Binary { ArrayIndex { if (auto st = left ? left->type->to() : nullptr) type = st->elementType; } - toString{ return left->toString() + "[" + right->toString() + "]"; } + toString{ return left->toString() + "["_cs + right->toString() + "]"_cs; } } class Range : Operation_Binary { @@ -401,7 +401,7 @@ class DefaultExpression : Expression {} // That's why we use a hidden id field to distinguish them. class This : Expression { long id = nextId++; - toString { return "this"; } + toString { return "this"_cs; } private: static long nextId; } @@ -413,7 +413,7 @@ class Cast : Operation_Unary { /// type, and 'type' will only be updated later when type inferencing occurs precedence = DBPrint::Prec_Prefix; stringOp = "(cast)"; - toString{ return "(" + destType->toString() + ")" + expr->toString(); } + toString{ return "("_cs + destType->toString() + ")"_cs + expr->toString(); } validate{ BUG_CHECK(!destType->is(), "%1%: Cannot cast to unknown type", this); } } @@ -436,7 +436,7 @@ class MethodCallExpression : Expression { optional Vector typeArguments = new Vector; optional Vector arguments = new Vector; toString { - cstring str = method->toString() + "("; + std::string str = method->toString() + "("; if (!arguments->empty()) { str += arguments->at(0)->toString(); } @@ -480,7 +480,7 @@ class BaseListExpression : Expression { return components.at(size - 1)->is(); } toString { - cstring str = "{"; + std::string str = "{"; if (!components.empty()) { str += " " + components.at(0)->toString(); } @@ -535,7 +535,7 @@ class StructExpression : Expression { return components.at(size - 1)->is(); } toString { - cstring str = "{"; + std::string str = "{"; if (!components.empty()) { cstring exprStr = components.at(0)->expression->toString(); str += " " + components.at(0)->toString() + " = " + exprStr; diff --git a/ir/id.h b/ir/id.h index 9f66ceb9d1..c1d6ee578a 100644 --- a/ir/id.h +++ b/ir/id.h @@ -37,9 +37,9 @@ struct ID : Util::IHasSourceInfo { ID(Util::SourceInfo si, cstring n) : srcInfo(si), name(n), originalName(n) { if (n.isNullOrEmpty()) BUG("Identifier with no name"); } - ID(const char *n) : ID(Util::SourceInfo(), n) {} // NOLINT(runtime/explicit) - ID(cstring n) : ID(Util::SourceInfo(), n) {} // NOLINT(runtime/explicit) - ID(std::string n) : ID(Util::SourceInfo(), n) {} // NOLINT(runtime/explicit) + ID(const char *n) : ID(Util::SourceInfo(), cstring(n)) {} // NOLINT(runtime/explicit) + ID(cstring n) : ID(Util::SourceInfo(), n) {} // NOLINT(runtime/explicit) + ID(std::string n) : ID(Util::SourceInfo(), n) {} // NOLINT(runtime/explicit) ID(cstring n, cstring old) : ID(Util::SourceInfo(), n, old) {} void dbprint(std::ostream &out) const { out << name; diff --git a/ir/ir.cpp b/ir/ir.cpp index 93cab1f2f6..2322377438 100644 --- a/ir/ir.cpp +++ b/ir/ir.cpp @@ -41,19 +41,19 @@ limitations under the License. namespace IR { -const cstring ParserState::accept = "accept"; -const cstring ParserState::reject = "reject"; -const cstring ParserState::start = "start"; -const cstring ParserState::verify = "verify"; - -const cstring TableProperties::actionsPropertyName = "actions"; -const cstring TableProperties::keyPropertyName = "key"; -const cstring TableProperties::defaultActionPropertyName = "default_action"; -const cstring TableProperties::entriesPropertyName = "entries"; -const cstring TableProperties::sizePropertyName = "size"; -const cstring IApply::applyMethodName = "apply"; -const cstring P4Program::main = "main"; -const cstring Type_Error::error = "error"; +const cstring ParserState::accept = "accept"_cs; +const cstring ParserState::reject = "reject"_cs; +const cstring ParserState::start = "start"_cs; +const cstring ParserState::verify = "verify"_cs; + +const cstring TableProperties::actionsPropertyName = "actions"_cs; +const cstring TableProperties::keyPropertyName = "key"_cs; +const cstring TableProperties::defaultActionPropertyName = "default_action"_cs; +const cstring TableProperties::entriesPropertyName = "entries"_cs; +const cstring TableProperties::sizePropertyName = "size"_cs; +const cstring IApply::applyMethodName = "apply"_cs; +const cstring P4Program::main = "main"_cs; +const cstring Type_Error::error = "error"_cs; long IR::Declaration::nextId = 0; long IR::This::nextId = 0; diff --git a/ir/ir.def b/ir/ir.def index bc24cc504a..ee7cd96552 100644 --- a/ir/ir.def +++ b/ir/ir.def @@ -112,7 +112,7 @@ class P4Parser : Type_Declaration, INestedNamespace, ISimpleNamespace, IApply, I for (auto d : parserLocals) BUG_CHECK(!d->is(), "%1%: state in locals", d); } - toString { return cstring("parser ") + externalName(); } + toString { return "parser "_cs + externalName(); } } class P4Control : Type_Declaration, INestedNamespace, ISimpleNamespace, IApply, IContainer, IAnnotated { @@ -140,7 +140,7 @@ class P4Control : Type_Declaration, INestedNamespace, ISimpleNamespace, IApply, BUG("Name mismatch for %1%: %2% != %3%", this, name, type->name); controlLocals.check_null(); } - toString { return cstring("control ") + externalName(); } + toString { return "control "_cs + externalName(); } } /// A P4-16 action @@ -283,7 +283,7 @@ class Property : Declaration, IAnnotated { class TableProperties : ISimpleNamespace { optional inline IndexedVector properties; - toString{ return "TableProperties(" + Util::toString(properties.size()) + ")"; } + toString{ return "TableProperties("_cs + Util::toString(properties.size()) + ")"_cs; } Util::Enumerator* getDeclarations() const override { return properties.getDeclarations(); } Property getProperty(cstring name) const { @@ -427,14 +427,14 @@ abstract Statement : StatOrDecl { } class ExitStatement : Statement { - toString{ return "exit"; } + toString{ return "exit"_cs; } dbprint { out << "exit"; } } class ReturnStatement : Statement { NullOK Expression expression; - toString{ return cstring("return ") + - (expression != nullptr ? expression->toString() : cstring("")); } + toString{ return "return "_cs + + (expression != nullptr ? expression->toString() : ""_cs); } } class EmptyStatement : Statement { @@ -444,7 +444,7 @@ class EmptyStatement : Statement { class AssignmentStatement : Statement { Expression left; Expression right; - toString{ return left->toString() + " = " + right->toString(); } + toString{ return left->toString() + " = "_cs + right->toString(); } } class IfStatement : Statement { @@ -457,13 +457,13 @@ class IfStatement : Statement { } class BreakStatement : Statement { - toString{ return "break"; } + toString{ return "break"_cs; } dbprint { out << "break"; } visit_children; // in loop-visitor.cpp } class ContinueStatement : Statement { - toString{ return "continue"; } + toString{ return "continue"_cs; } dbprint { out << "continue"; } visit_children; // in loop-visitor.cpp } diff --git a/ir/irutils.cpp b/ir/irutils.cpp index a7f268ab1a..19fbddd5bd 100644 --- a/ir/irutils.cpp +++ b/ir/irutils.cpp @@ -11,6 +11,8 @@ namespace IR { +using namespace P4::literals; + /* ============================================================================================= * Types * ============================================================================================= */ @@ -61,7 +63,7 @@ const IR::Expression *getDefaultValue(const IR::Type *type, const Util::SourceIn return new IR::Member(srcInfo, new IR::TypeNameExpression(te->name), "NoError"); } if (type->is()) { - return new IR::StringLiteral(srcInfo, cstring("")); + return new IR::StringLiteral(srcInfo, ""_cs); } if (type->is()) { if (valueRequired) { diff --git a/ir/loop-visitor.cpp b/ir/loop-visitor.cpp index 261f578e02..79c49215ac 100644 --- a/ir/loop-visitor.cpp +++ b/ir/loop-visitor.cpp @@ -20,20 +20,20 @@ void IR::ForStatement::visit_children(THIS *self, Visitor &v) { v.visit(self->annotations, "annotations"); v.visit(self->init, "init"); if (auto *cfv = v.controlFlowVisitor()) { - ControlFlowVisitor::SaveGlobal outer(*cfv, "-BREAK-", "-CONTINUE-"); + ControlFlowVisitor::SaveGlobal outer(*cfv, "-BREAK-"_cs, "-CONTINUE-"_cs); ControlFlowVisitor *top = nullptr; while (true) { top = &cfv->flow_clone(); cfv->visit(self->condition, "condition", 1000); auto &inloop = cfv->flow_clone(); inloop.visit(self->body, "body"); - inloop.flow_merge_global_from("-CONTINUE-"); + inloop.flow_merge_global_from("-CONTINUE-"_cs); inloop.visit(self->updates, "updates"); inloop.flow_merge(*top); if (inloop == *top) break; cfv->flow_copy(inloop); } - cfv->flow_merge_global_from("-BREAK-"); + cfv->flow_merge_global_from("-BREAK-"_cs); } else { /* Since there is a variable number of init statements (0 or more), we * don't know what the child index of subsequent children will be. So we @@ -57,15 +57,15 @@ void IR::ForInStatement::visit_children(THIS *self, Visitor &v) { v.visit(self->decl, "decl", 0); v.visit(self->collection, "collection", 2); if (auto *cfv = v.controlFlowVisitor()) { - ControlFlowVisitor::SaveGlobal outer(*cfv, "-BREAK-", "-CONTINUE-"); + ControlFlowVisitor::SaveGlobal outer(*cfv, "-BREAK-"_cs, "-CONTINUE-"_cs); ControlFlowVisitor *top = nullptr; do { top = &cfv->flow_clone(); cfv->visit(self->ref, "ref", 1); cfv->visit(self->body, "body", 3); - cfv->flow_merge_global_from("-CONTINUE-"); + cfv->flow_merge_global_from("-CONTINUE-"_cs); } while (*cfv != *top); - cfv->flow_merge_global_from("-BREAK-"); + cfv->flow_merge_global_from("-BREAK-"_cs); } else { v.visit(self->ref, "ref", 1); v.visit(self->body, "body", 3); @@ -76,7 +76,7 @@ void IR::ForInStatement::visit_children(Visitor &v) const { visit_children(this, void IR::BreakStatement::visit_children(Visitor &v) const { if (auto *cfv = v.controlFlowVisitor()) { - cfv->flow_merge_global_to("-BREAK-"); + cfv->flow_merge_global_to("-BREAK-"_cs); cfv->setUnreachable(); } } @@ -86,7 +86,7 @@ void IR::BreakStatement::visit_children(Visitor &v) { void IR::ContinueStatement::visit_children(Visitor &v) const { if (auto *cfv = v.controlFlowVisitor()) { - cfv->flow_merge_global_to("-CONTINUE-"); + cfv->flow_merge_global_to("-CONTINUE-"_cs); cfv->setUnreachable(); } } diff --git a/ir/namemap.h b/ir/namemap.h index 7256000291..8463b8b1f7 100644 --- a/ir/namemap.h +++ b/ir/namemap.h @@ -46,7 +46,7 @@ class NameMap : public Node { auto obj_name(const U *obj) -> decltype(obj->name) { return obj->name; } - cstring obj_name(const void *) { return cstring(0); } + cstring obj_name(const void *) { return nullptr; } public: NameMap() = default; diff --git a/ir/node.cpp b/ir/node.cpp index 13498216f0..da7d521ce0 100644 --- a/ir/node.cpp +++ b/ir/node.cpp @@ -120,18 +120,18 @@ Util::JsonObject *IR::Node::sourceInfoJsonObj() const { // Added source_info for jsonObject when "--fromJSON" flag is used // which parameters are saved in srcInfo fileds(filename, line, column and srcBrief) auto json1 = new Util::JsonObject(); - json1->emplace("filename", srcInfo.filename); - json1->emplace("line", srcInfo.line); - json1->emplace("column", srcInfo.column); - json1->emplace("source_fragment", srcInfo.srcBrief); + json1->emplace("filename"_cs, srcInfo.filename); + json1->emplace("line"_cs, srcInfo.line); + json1->emplace("column"_cs, srcInfo.column); + json1->emplace("source_fragment"_cs, srcInfo.srcBrief); return json1; } } else { auto json = new Util::JsonObject(); - json->emplace("filename", fName); - json->emplace("line", lineNumber); - json->emplace("column", columnNumber); - json->emplace("source_fragment", si.toBriefSourceFragment().escapeJson()); + json->emplace("filename"_cs, fName); + json->emplace("line"_cs, lineNumber); + json->emplace("column"_cs, columnNumber); + json->emplace("source_fragment"_cs, si.toBriefSourceFragment().escapeJson()); return json; } } diff --git a/ir/node.h b/ir/node.h index 5c51bfebf9..93b1ebb1da 100644 --- a/ir/node.h +++ b/ir/node.h @@ -40,6 +40,8 @@ class JsonObject; namespace IR { +using namespace P4::literals; + class Node; class Annotation; // IWYU pragma: keep template @@ -138,8 +140,8 @@ class Node : public virtual INode { const Node *getNode() const final { return this; } Node *getNode() final { return this; } Util::SourceInfo getSourceInfo() const override { return srcInfo; } - cstring node_type_name() const override { return "Node"; } - static cstring static_type_name() { return "Node"; } + cstring node_type_name() const override { return "Node"_cs; } + static cstring static_type_name() { return "Node"_cs; } virtual int num_children() { return 0; } explicit Node(JSONLoader &json); cstring toString() const override { return node_type_name(); } diff --git a/ir/type.cpp b/ir/type.cpp index 6f85230930..f6ed7e4391 100644 --- a/ir/type.cpp +++ b/ir/type.cpp @@ -32,40 +32,40 @@ limitations under the License. namespace IR { -const cstring IR::Type_Stack::next = "next"; -const cstring IR::Type_Stack::last = "last"; -const cstring IR::Type_Stack::arraySize = "size"; -const cstring IR::Type_Stack::lastIndex = "lastIndex"; -const cstring IR::Type_Stack::push_front = "push_front"; -const cstring IR::Type_Stack::pop_front = "pop_front"; -const cstring IR::Type_Header::isValid = "isValid"; -const cstring IR::Type_Header::setValid = "setValid"; -const cstring IR::Type_Header::setInvalid = "setInvalid"; -const cstring IR::Type::minSizeInBits = "minSizeInBits"; -const cstring IR::Type::minSizeInBytes = "minSizeInBytes"; -const cstring IR::Type::maxSizeInBits = "maxSizeInBits"; -const cstring IR::Type::maxSizeInBytes = "maxSizeInBytes"; +const cstring IR::Type_Stack::next = "next"_cs; +const cstring IR::Type_Stack::last = "last"_cs; +const cstring IR::Type_Stack::arraySize = "size"_cs; +const cstring IR::Type_Stack::lastIndex = "lastIndex"_cs; +const cstring IR::Type_Stack::push_front = "push_front"_cs; +const cstring IR::Type_Stack::pop_front = "pop_front"_cs; +const cstring IR::Type_Header::isValid = "isValid"_cs; +const cstring IR::Type_Header::setValid = "setValid"_cs; +const cstring IR::Type_Header::setInvalid = "setInvalid"_cs; +const cstring IR::Type::minSizeInBits = "minSizeInBits"_cs; +const cstring IR::Type::minSizeInBytes = "minSizeInBytes"_cs; +const cstring IR::Type::maxSizeInBits = "maxSizeInBits"_cs; +const cstring IR::Type::maxSizeInBytes = "maxSizeInBytes"_cs; const IR::ID IR::Type_Table::hit = ID("hit"); const IR::ID IR::Type_Table::miss = ID("miss"); const IR::ID IR::Type_Table::action_run = ID("action_run"); -const cstring IR::Annotation::nameAnnotation = "name"; -const cstring IR::Annotation::tableOnlyAnnotation = "tableonly"; -const cstring IR::Annotation::defaultOnlyAnnotation = "defaultonly"; -const cstring IR::Annotation::atomicAnnotation = "atomic"; -const cstring IR::Annotation::hiddenAnnotation = "hidden"; -const cstring IR::Annotation::lengthAnnotation = "length"; -const cstring IR::Annotation::optionalAnnotation = "optional"; -const cstring IR::Annotation::pkginfoAnnotation = "pkginfo"; -const cstring IR::Annotation::deprecatedAnnotation = "deprecated"; -const cstring IR::Annotation::synchronousAnnotation = "synchronous"; -const cstring IR::Annotation::pureAnnotation = "pure"; -const cstring IR::Annotation::noSideEffectsAnnotation = "noSideEffects"; -const cstring IR::Annotation::noWarnAnnotation = "noWarn"; -const cstring IR::Annotation::matchAnnotation = "match"; -const cstring IR::Annotation::fieldListAnnotation = "field_list"; -const cstring IR::Annotation::debugLoggingAnnotation = "__debug"; +const cstring IR::Annotation::nameAnnotation = "name"_cs; +const cstring IR::Annotation::tableOnlyAnnotation = "tableonly"_cs; +const cstring IR::Annotation::defaultOnlyAnnotation = "defaultonly"_cs; +const cstring IR::Annotation::atomicAnnotation = "atomic"_cs; +const cstring IR::Annotation::hiddenAnnotation = "hidden"_cs; +const cstring IR::Annotation::lengthAnnotation = "length"_cs; +const cstring IR::Annotation::optionalAnnotation = "optional"_cs; +const cstring IR::Annotation::pkginfoAnnotation = "pkginfo"_cs; +const cstring IR::Annotation::deprecatedAnnotation = "deprecated"_cs; +const cstring IR::Annotation::synchronousAnnotation = "synchronous"_cs; +const cstring IR::Annotation::pureAnnotation = "pure"_cs; +const cstring IR::Annotation::noSideEffectsAnnotation = "noSideEffects"_cs; +const cstring IR::Annotation::noWarnAnnotation = "noWarn"_cs; +const cstring IR::Annotation::matchAnnotation = "match"_cs; +const cstring IR::Annotation::fieldListAnnotation = "field_list"_cs; +const cstring IR::Annotation::debugLoggingAnnotation = "__debug"_cs; long Type_Declaration::nextId = 0; long Type_InfInt::nextId = 0; diff --git a/ir/type.def b/ir/type.def index e06481cf67..e4a547fd0d 100644 --- a/ir/type.def +++ b/ir/type.def @@ -20,13 +20,13 @@ enum class Direction { inline cstring directionToString(IR::Direction direction) { switch (direction) { case IR::Direction::None: - return ""; + return ""_cs; case IR::Direction::In: - return "in"; + return "in"_cs; case IR::Direction::Out: - return "out"; + return "out"_cs; case IR::Direction::InOut: - return "inout"; + return "inout"_cs; default: BUG("Unhandled case"); } @@ -52,8 +52,9 @@ inline std::ostream& operator<<(std::ostream &out, IR::Direction d) { return out; } +// FIXME: should accept string_view inline bool operator>>(cstring s, IR::Direction &d) { - if (!s || s == "") d = IR::Direction::None; + if (!s || s == cstring::empty) d = IR::Direction::None; else if (s == "in") d = IR::Direction::In; else if (s == "out") d = IR::Direction::Out; else if (s == "inout") d = IR::Direction::InOut; @@ -74,10 +75,10 @@ class Type_Any : Type, ITypeVar { static long nextId; public: long declid = nextId++; - cstring getVarName() const override { return "int_" + Util::toString(declid); } + cstring getVarName() const override { return "int_"_cs + Util::toString(declid); } int getDeclId() const override { return declid; } dbprint { out << "ANYTYPE/" << declid; } - toString { return "ANYTYPE"; } + toString { return "ANYTYPE"_cs; } operator== { return declid == a.declid; } static Type_Any get(); static Type_Any get(const Util::SourceInfo &si); @@ -102,7 +103,7 @@ class Type_Any : Type, ITypeVar { class Type_Fragment : Type { Type type; dbprint { out << "FRAGMENT(" << type << ")"; } - toString { return "FRAGMENT(" + type->toString() + ")"; } + toString { return "FRAGMENT("_cs + type->toString() + ")"_cs; } const Type* getP4Type() const override { return nullptr; } } @@ -115,7 +116,7 @@ class Type_Fragment : Type { /// by type-checking. class Type_Type : Type { Type type; - toString { return "Type(" + type->toString() + ")"; } + toString { return "Type("_cs + type->toString() + ")"_cs; } dbprint { out << "Type(" << type << ")"; } const Type* getP4Type() const override { return type; } validate { BUG_CHECK(!type->is(), "%1%: nested Type_Type", type); } @@ -130,7 +131,7 @@ class Type_Boolean : Type_Base { static Type_Boolean get(); static Type_Boolean get(const Util::SourceInfo &si); int width_bits() const override { return 1; } - toString{ return "bool"; } + toString{ return "bool"_cs; } dbprint { out << "bool"; } } @@ -143,7 +144,7 @@ class Type_State : Type_Base { public: static Type_State get(); static Type_State get(const Util::SourceInfo &si); - toString{ return "state"; } + toString{ return "state"_cs; } dbprint { out << "state"; } } @@ -160,10 +161,10 @@ class Type_Bits : Type_Base { static Type_Bits get(const Util::SourceInfo &si, Expression expression, bool isSigned = false); static Type_Bits get(const Util::SourceInfo &si, int sz, bool isSigned = false); static Type_Bits get(int sz, bool isSigned = false); - cstring baseName() const { return isSigned ? "int" : "bit"; } + cstring baseName() const { return isSigned ? "int"_cs : "bit"_cs; } int width_bits() const override { return size; } - toString{ return baseName() + "<" + Util::toString(size) + ">"; } + toString{ return baseName() + "<"_cs + Util::toString(size) + ">"_cs; } dbprint { out << toString(); } } @@ -179,7 +180,7 @@ class Type_Varbits : Type_Base { static Type_Varbits get(const Util::SourceInfo &si, int size); static Type_Varbits get(int size); static Type_Varbits get(); - toString{ return cstring("varbit<") + Util::toString(size) + ">"; } + toString{ return "varbit<"_cs + Util::toString(size) + ">"_cs; } dbprint { out << "varbit<" << size << ">"; } } @@ -215,7 +216,7 @@ class ParameterList : ISimpleNamespace { IR::IDeclaration getDeclByName(cstring name) const override { return getParameter(name); } void push_back(const Parameter *p) { parameters.push_back(p); } toString { - cstring result = ""; + std::string result = ""; bool first = true; for (auto p : parameters) { if (!first) @@ -255,7 +256,7 @@ class Type_InfInt : Type, ITypeVar { cstring getVarName() const override { return "int_" + Util::toString(declid); } int getDeclId() const override { return declid; } dbprint { out << "int/" << declid; } - toString { return "int"; } + toString { return "int"_cs; } operator== { return declid == a.declid; } static Type_InfInt get(); static Type_InfInt get(const Util::SourceInfo &si); @@ -272,7 +273,7 @@ class Type_Dontcare : Type_Base { void *operator new(size_t size) { return ::operator new(size); } #end public: - toString{ return "_"; } + toString{ return "_"_cs; } static Type_Dontcare get(); static Type_Dontcare get(const Util::SourceInfo &si); dbprint { out << "_"; } @@ -284,7 +285,7 @@ class Type_Void : Type_Base { void *operator new(size_t size) { return ::operator new(size); } #end public: - toString{ return "void"; } + toString{ return "void"_cs; } static Type_Void get(); static Type_Void get(const Util::SourceInfo &si); dbprint { out << "void"; } @@ -296,7 +297,7 @@ class Type_MatchKind : Type_Base { void *operator new(size_t size) { return ::operator new(size); } #end public: - toString{ return "match_kind"; } + toString{ return "match_kind"_cs; } static Type_MatchKind get(); static Type_MatchKind get(const Util::SourceInfo &si); dbprint { out << "match_kind"; } @@ -314,8 +315,8 @@ class TypeParameters : ISimpleNamespace { validate{ parameters.check_null(); } toString { if (parameters.size() == 0) - return ""; - cstring result = "<"; + return ""_cs; + std::string result = "<"; bool first = true; for (auto p : parameters) { if (!first) @@ -385,7 +386,7 @@ abstract Type_StructLike : Type_Declaration, INestedNamespace, ISimpleNamespace, class Type_Struct : Type_StructLike { #nodbprint - toString{ return cstring("struct ") + externalName(); } + toString{ return "struct "_cs + externalName(); } } /// This is the type of a struct-valued expression whose @@ -397,7 +398,7 @@ class Type_UnknownStruct : Type_StructLike { class Type_HeaderUnion : Type_StructLike { #nodbprint - toString{ return cstring("header_union ") + externalName(); } + toString{ return "header_union "_cs + externalName(); } // this makes some assumptions on padding int width_bits() const override { int rv = 0; @@ -419,13 +420,13 @@ class Type_Header : Type_StructLike { static const cstring setInvalid; static const cstring isValid; #nodbprint - toString{ return cstring("header ") + externalName(); } + toString{ return "header "_cs + externalName(); } } class Type_Set : Type { Type elementType; dbprint{ Node::dbprint(out); out << "<" << elementType << ">"; } - toString { return cstring("set<") + elementType->toString() + ">"; } + toString { return "set<"_cs + elementType->toString() + ">"_cs; } const Type* getP4Type() const override { return nullptr; } int width_bits() const override { /// returning the width of the set elements, not the set itself, which doesn't @@ -454,6 +455,7 @@ abstract Type_BaseList : Type, Type_Indexed { } return rv; } cstring asString(const char* name) const { + // FIXME: simplify concatenation std::string result = name; result += "<"; bool first = true; @@ -492,8 +494,7 @@ class Type_P4List : Type { Type elementType; const Type* getP4Type() const override; toString{ - std::string result = "list<" + elementType->toString() + ">"; - return result; + return "list<"_cs + elementType->toString() + ">"_cs; } } @@ -515,7 +516,7 @@ class Type_Package : Type_ArchBlock, IContainer, ISimpleNamespace { ParameterList constructorParams; Type_Method getConstructorMethodType() const override; ParameterList getConstructorParameters() const override { return constructorParams; } - toString{ return cstring("package ") + externalName(); } + toString{ return "package "_cs + externalName(); } Util::Enumerator* getDeclarations() const override { return typeParameters->getDeclarations()->concat(constructorParams->getDeclarations()); } IDeclaration getDeclByName(cstring name) const override { @@ -528,14 +529,14 @@ class Type_Parser : Type_ArchBlock, IApply { ParameterList applyParams; Type_Method getApplyMethodType() const override; ParameterList getApplyParameters() const override { return applyParams; } - toString { return cstring("parser ") + externalName(); } + toString { return "parser "_cs + externalName(); } } class Type_Control : Type_ArchBlock, IApply { ParameterList applyParams; Type_Method getApplyMethodType() const override; ParameterList getApplyParameters() const override { return applyParams; } - toString { return cstring("control ") + externalName(); } + toString { return "control "_cs + externalName(); } } /// A type referred by name @@ -554,8 +555,9 @@ class Type_Name : Type { class Type_Stack : Type_Indexed, Type { Type elementType; Expression size; - toString{ return elementType->toString() + "[" + - (sizeKnown() ? Util::toString(getSize()) : "?") + "]"; } + // FIXME: do not create all these intermediate cstring's + toString{ return elementType->toString() + "["_cs + + (sizeKnown() ? Util::toString(getSize()) : "?"_cs) + "]"_cs; } dbprint{ out << elementType << "[" << size << "]"; } bool sizeKnown() const; size_t getSize() const override; @@ -581,8 +583,8 @@ class Type_Specialized : Type { validate{ arguments->check_null(); } const Type* getP4Type() const override; toString{ - cstring result = baseType->toString() + "<"; - cstring sep = ""; + std::string result = baseType->toString() + "<"; + std::string sep = ""; for (auto t : *arguments) { result += sep + t->toString(); sep = ", "; @@ -609,7 +611,7 @@ class Type_SpecializedCanonical : Type { BUG_CHECK(substituted->is(), "substituted %1% is not generic", substituted); } const Type* getP4Type() const override; - toString{ return baseType->toString() + "<...>"; } + toString{ return baseType->toString() + "<...>"_cs; } } /// A declaration that consists of just an identifier, e.g., an enum member @@ -627,7 +629,7 @@ class Type_String : Type_Base { public: static Type_String get(); static Type_String get(const Util::SourceInfo &si); - toString{ return "string"; } + toString{ return "string"_cs; } } class Type_Enum : Type_Declaration, ISimpleNamespace, IAnnotated { @@ -696,7 +698,7 @@ abstract Type_MethodBase : Type, IMayBeGenericType, ISimpleNamespace { size_t minParameterCount() const; virtual TypeParameters getTypeParameters() const override { return typeParameters; } void dbprint(std::ostream& out) const override; - toString { return ""; } + toString { return ""_cs; } const IR::Type* getP4Type() const override { return nullptr; } Util::Enumerator* getDeclarations() const override { return typeParameters->getDeclarations()->concat(parameters->getDeclarations()); } @@ -734,7 +736,7 @@ class Type_MethodCall : Type { Vector arguments; validate{ typeArguments->check_null(); arguments->check_null(); } const Type* getP4Type() const override { return nullptr; } - toString { return ""; } + toString { return ""_cs; } } /// Actions look a lot like methods in many respects. diff --git a/ir/v1.cpp b/ir/v1.cpp index 394d018eb1..47a66782b2 100644 --- a/ir/v1.cpp +++ b/ir/v1.cpp @@ -47,7 +47,7 @@ cstring IR::NamedCond::unique_name() { static int unique_counter = 0; char buf[16]; snprintf(buf, sizeof(buf), "cond-%d", unique_counter++); - return buf; + return cstring(buf); } struct primitive_info_t { @@ -56,62 +56,64 @@ struct primitive_info_t { unsigned type_match_operands; // bitset -- 1 bit per operand }; +using namespace P4::literals; + static const std::map prim_info = { - {"add", {3, 3, 0x1, 0x7}}, - {"add_header", {1, 1, 0x1, 0x0}}, - {"add_to_field", {2, 2, 0x1, 0x3}}, - {"bit_and", {3, 3, 0x1, 0x7}}, - {"bit_andca", {3, 3, 0x1, 0x7}}, - {"bit_andcb", {3, 3, 0x1, 0x7}}, - {"bit_nand", {3, 3, 0x1, 0x7}}, - {"bit_nor", {3, 3, 0x1, 0x7}}, - {"bit_not", {2, 2, 0x1, 0x3}}, - {"bit_or", {3, 3, 0x1, 0x7}}, - {"bit_orca", {3, 3, 0x1, 0x7}}, - {"bit_orcb", {3, 3, 0x1, 0x7}}, - {"bit_xnor", {3, 3, 0x1, 0x7}}, - {"bit_xor", {3, 3, 0x1, 0x7}}, - {"bypass_egress", {0, 0, 0x0, 0x0}}, - {"clone_egress_pkt_to_egress", {1, 2, 0x0, 0x0}}, - {"clone_ingress_pkt_to_egress", {1, 2, 0x0, 0x0}}, - {"copy_header", {2, 2, 0x1, 0x3}}, - {"copy_to_cpu", {1, 1, 0x0, 0x0}}, - {"count", {2, 2, 0x1, 0x0}}, - {"drop", {0, 0, 0x0, 0x0}}, - {"emit", {1, 1, 0x0, 0x0}}, - {"execute_meter", {3, 4, 0x5, 0x0}}, - {"execute_stateful_alu", {1, 2, 0x0, 0x0}}, - {"execute_stateful_alu_from_hash", {1, 2, 0x0, 0x0}}, - {"execute_stateful_log", {1, 1, 0x0, 0x0}}, - {"exit", {0, 0, 0x0, 0x0}}, - {"extract", {1, 1, 0x1, 0x0}}, - {"funnel_shift_right", {4, 4, 0x1, 0x0}}, - {"generate_digest", {2, 2, 0x0, 0x0}}, - {"invalidate", {1, 1, 0x0, 0x0}}, - {"mark_for_drop", {0, 0, 0x0, 0x0}}, - {"max", {3, 3, 0x1, 0x7}}, - {"min", {3, 3, 0x1, 0x7}}, - {"modify_field", {2, 3, 0x1, 0x7}}, - {"modify_field_conditionally", {3, 3, 0x1, 0x5}}, - {"modify_field_from_rng", {2, 3, 0x1, 0x5}}, - {"modify_field_rng_uniform", {3, 3, 0x1, 0x5}}, - {"modify_field_with_hash_based_offset", {4, 4, 0x1, 0x0}}, - {"no_op", {0, 0, 0x0, 0x0}}, - {"pop", {1, 2, 0x1, 0x0}}, - {"push", {1, 2, 0x1, 0x0}}, - {"recirculate", {1, 1, 0x0, 0x0}}, - {"register_read", {3, 3, 0x1, 0x0}}, - {"register_write", {3, 3, 0x0, 0x0}}, - {"remove_header", {1, 1, 0x1, 0x0}}, - {"resubmit", {0, 1, 0x0, 0x0}}, - {"sample_e2e", {2, 3, 0x0, 0x0}}, - {"set_metadata", {2, 2, 0x1, 0x3}}, - {"shift_left", {3, 3, 0x1, 0x0}}, - {"shift_right", {3, 3, 0x1, 0x0}}, - {"subtract", {3, 3, 0x1, 0x7}}, - {"subtract_from_field", {2, 2, 0x1, 0x3}}, - {"truncate", {1, 1, 0x0, 0x0}}, - {"valid", {1, 1, 0x0, 0x0}}, + {"add"_cs, {3, 3, 0x1, 0x7}}, + {"add_header"_cs, {1, 1, 0x1, 0x0}}, + {"add_to_field"_cs, {2, 2, 0x1, 0x3}}, + {"bit_and"_cs, {3, 3, 0x1, 0x7}}, + {"bit_andca"_cs, {3, 3, 0x1, 0x7}}, + {"bit_andcb"_cs, {3, 3, 0x1, 0x7}}, + {"bit_nand"_cs, {3, 3, 0x1, 0x7}}, + {"bit_nor"_cs, {3, 3, 0x1, 0x7}}, + {"bit_not"_cs, {2, 2, 0x1, 0x3}}, + {"bit_or"_cs, {3, 3, 0x1, 0x7}}, + {"bit_orca"_cs, {3, 3, 0x1, 0x7}}, + {"bit_orcb"_cs, {3, 3, 0x1, 0x7}}, + {"bit_xnor"_cs, {3, 3, 0x1, 0x7}}, + {"bit_xor"_cs, {3, 3, 0x1, 0x7}}, + {"bypass_egress"_cs, {0, 0, 0x0, 0x0}}, + {"clone_egress_pkt_to_egress"_cs, {1, 2, 0x0, 0x0}}, + {"clone_ingress_pkt_to_egress"_cs, {1, 2, 0x0, 0x0}}, + {"copy_header"_cs, {2, 2, 0x1, 0x3}}, + {"copy_to_cpu"_cs, {1, 1, 0x0, 0x0}}, + {"count"_cs, {2, 2, 0x1, 0x0}}, + {"drop"_cs, {0, 0, 0x0, 0x0}}, + {"emit"_cs, {1, 1, 0x0, 0x0}}, + {"execute_meter"_cs, {3, 4, 0x5, 0x0}}, + {"execute_stateful_alu"_cs, {1, 2, 0x0, 0x0}}, + {"execute_stateful_alu_from_hash"_cs, {1, 2, 0x0, 0x0}}, + {"execute_stateful_log"_cs, {1, 1, 0x0, 0x0}}, + {"exit"_cs, {0, 0, 0x0, 0x0}}, + {"extract"_cs, {1, 1, 0x1, 0x0}}, + {"funnel_shift_right"_cs, {4, 4, 0x1, 0x0}}, + {"generate_digest"_cs, {2, 2, 0x0, 0x0}}, + {"invalidate"_cs, {1, 1, 0x0, 0x0}}, + {"mark_for_drop"_cs, {0, 0, 0x0, 0x0}}, + {"max"_cs, {3, 3, 0x1, 0x7}}, + {"min"_cs, {3, 3, 0x1, 0x7}}, + {"modify_field"_cs, {2, 3, 0x1, 0x7}}, + {"modify_field_conditionally"_cs, {3, 3, 0x1, 0x5}}, + {"modify_field_from_rng"_cs, {2, 3, 0x1, 0x5}}, + {"modify_field_rng_uniform"_cs, {3, 3, 0x1, 0x5}}, + {"modify_field_with_hash_based_offset"_cs, {4, 4, 0x1, 0x0}}, + {"no_op"_cs, {0, 0, 0x0, 0x0}}, + {"pop"_cs, {1, 2, 0x1, 0x0}}, + {"push"_cs, {1, 2, 0x1, 0x0}}, + {"recirculate"_cs, {1, 1, 0x0, 0x0}}, + {"register_read"_cs, {3, 3, 0x1, 0x0}}, + {"register_write"_cs, {3, 3, 0x0, 0x0}}, + {"remove_header"_cs, {1, 1, 0x1, 0x0}}, + {"resubmit"_cs, {0, 1, 0x0, 0x0}}, + {"sample_e2e"_cs, {2, 3, 0x0, 0x0}}, + {"set_metadata"_cs, {2, 2, 0x1, 0x3}}, + {"shift_left"_cs, {3, 3, 0x1, 0x0}}, + {"shift_right"_cs, {3, 3, 0x1, 0x0}}, + {"subtract"_cs, {3, 3, 0x1, 0x7}}, + {"subtract_from_field"_cs, {2, 2, 0x1, 0x3}}, + {"truncate"_cs, {1, 1, 0x0, 0x0}}, + {"valid"_cs, {1, 1, 0x0, 0x0}}, }; void IR::Primitive::typecheck() const { @@ -206,6 +208,6 @@ IR::V1Program::V1Program() { new IR::StructField("instance_type", IR::Type::Bits::get(32)), new IR::StructField("parser_status", IR::Type::Bits::get(8)), new IR::StructField("parser_error_location", IR::Type::Bits::get(8))}); - scope.add("standard_metadata_t", new IR::v1HeaderType(standard_metadata_t)); - scope.add("standard_metadata", new IR::Metadata("standard_metadata", standard_metadata_t)); + scope.add("standard_metadata_t"_cs, new IR::v1HeaderType(standard_metadata_t)); + scope.add("standard_metadata"_cs, new IR::Metadata("standard_metadata", standard_metadata_t)); } diff --git a/ir/v1.def b/ir/v1.def index ec3f380e79..4edff84727 100644 --- a/ir/v1.def +++ b/ir/v1.def @@ -43,37 +43,37 @@ inline bool operator>>(cstring s, IR::CounterType &ctr) { #end class Type_Block : Type_Base { - toString { return "block"; } + toString { return "block"_cs; } static Type_Block get(); dbprint { out << "block"; } } class Type_Counter : Type_Base { - toString { return "counter"; } + toString { return "counter"_cs; } static Type_Counter get(); dbprint { out << "counter"; } } class Type_Expression : Type_Base { - toString { return "expression"; } + toString { return "expression"_cs; } static Type_Expression get(); dbprint { out << "expression"; } } class Type_FieldListCalculation : Type_Base { - toString { return "field_list_calculation"; } + toString { return "field_list_calculation"_cs; } static Type_FieldListCalculation get(); dbprint { out << "field_list_calculation"; } } class Type_Meter : Type_Base { - toString { return "meter"; } + toString { return "meter"_cs; } static Type_Meter get(); dbprint { out << "meter"; } } class Type_Register : Type_Base { - toString { return "register"; } + toString { return "register"_cs; } static Type_Register get(); dbprint { out << "register"; } } class Type_AnyTable : Type_Base { - toString { return "table"; } + toString { return "table"_cs; } static Type_AnyTable get(); dbprint { out << "table"; } } @@ -368,9 +368,9 @@ class ActionFunction : IAnnotated { v.visit(annotations, "annotations"); } toString { - return cstring("action ") + name + " {\n" + + return "action "_cs + name + " {\n"_cs + cstring::join(action.begin(), action.end(), ";\n") + - " }"; } + " }"_cs; } } class ActionProfile : Attached { diff --git a/ir/visitor.cpp b/ir/visitor.cpp index c4af4c42eb..043fcf65be 100644 --- a/ir/visitor.cpp +++ b/ir/visitor.cpp @@ -789,10 +789,10 @@ cstring Visitor::demangle(const char *str) { int status; cstring rv; if (char *n = abi::__cxa_demangle(str, 0, 0, &status)) { - rv = n; + rv = cstring(n); free(n); } else { - rv = str; + rv = cstring(str); } return rv; } diff --git a/ir/visitor.h b/ir/visitor.h index 1321312cfa..512eba1670 100644 --- a/ir/visitor.h +++ b/ir/visitor.h @@ -221,7 +221,7 @@ class Visitor { if (!internalName) internalName = demangle(typeid(*this).name()); return internalName.c_str(); } - void setName(const char *name) { internalName = name; } + void setName(const char *name) { internalName = cstring(name); } void print_context() const; // for debugging; can be called from debugger // Context access/search functions. getContext returns the context diff --git a/lib/cstring.cpp b/lib/cstring.cpp index d58ae1bf39..99daa6ed41 100644 --- a/lib/cstring.cpp +++ b/lib/cstring.cpp @@ -16,6 +16,13 @@ limitations under the License. #include "cstring.h" +#if HAVE_LIBGC +#include +#define IF_HAVE_LIBGC(X) X +#else +#define IF_HAVE_LIBGC(X) +#endif /* HAVE_LIBGC */ + #include #include #include @@ -75,8 +82,8 @@ class table_entry { m_inplace_string[length] = '\0'; m_flags = table_entry_flags::inplace; } else { - // Make copy of string elseware - auto copy = new char[length + 1]; + // Make copy of string elsewhere + auto copy = new IF_HAVE_LIBGC((NoGC)) char[length + 1]; std::memcpy(copy, string, length); copy[length] = '\0'; m_string = copy; @@ -185,18 +192,18 @@ size_t cstring::cache_size(size_t &count) { return rv; } -cstring cstring::newline = cstring("\n"); -cstring cstring::empty = cstring(""); +cstring cstring::newline = cstring::literal("\n"); +cstring cstring::empty = cstring::literal(""); -bool cstring::startsWith(const cstring &prefix) const { - if (prefix.isNullOrEmpty()) return true; - return size() >= prefix.size() && memcmp(str, prefix.str, prefix.size()) == 0; +bool cstring::startsWith(std::string_view prefix) const { + if (prefix.empty()) return true; + return size() >= prefix.size() && memcmp(str, prefix.data(), prefix.size()) == 0; } -bool cstring::endsWith(const cstring &suffix) const { - if (suffix.isNullOrEmpty()) return true; +bool cstring::endsWith(std::string_view suffix) const { + if (suffix.empty()) return true; return size() >= suffix.size() && - memcmp(str + size() - suffix.size(), suffix.str, suffix.size()) == 0; + memcmp(str + size() - suffix.size(), suffix.data(), suffix.size()) == 0; } cstring cstring::before(const char *at) const { return substr(0, at - str); } @@ -231,8 +238,8 @@ cstring cstring::replace(cstring search, cstring replace) const { cstring cstring::indent(size_t amount) const { std::string spaces = ""; for (size_t i = 0; i < amount; i++) spaces += " "; - cstring spc = cstring("\n") + spaces; - return cstring(spaces) + replace("\n", spc); + cstring spc = newline + spaces; + return cstring(spaces) + replace(newline, spc); } // See https://stackoverflow.com/a/33799784/4538702 diff --git a/lib/cstring.h b/lib/cstring.h index 60d92d63ce..1a1a089aba 100644 --- a/lib/cstring.h +++ b/lib/cstring.h @@ -70,13 +70,20 @@ limitations under the License. * This is convenient, but in performance-sensitive code it's good to be aware * that mixing the two types of strings can trigger a lot of implicit copies. */ + +class cstring; + +namespace P4::literals { +inline cstring operator""_cs(const char *str, std::size_t len); +} + class cstring { const char *str = nullptr; public: cstring() = default; - // TODO (DanilLutsenko): Enable when initialization with 0 will be eliminated - // cstring(std::nullptr_t) {} // NOLINT(runtime/explicit) + + cstring(std::nullptr_t) {} // NOLINT(runtime/explicit) // Copy and assignment from other kinds of strings @@ -92,7 +99,7 @@ class cstring { // Owner of string is someone else, we do not know size of string. // Do not use if possible, this is linear time operation if string // not exists in table, because the underlying string must be copied. - cstring(const char *string) { // NOLINT(runtime/explicit) + explicit cstring(const char *string) { if (string != nullptr) { construct_from_shared(string, std::strlen(string)); } @@ -151,6 +158,8 @@ class cstring { // string is literal void construct_from_literal(const char *string, std::size_t length); + friend cstring P4::literals::operator""_cs(const char *str, std::size_t len); + public: /// @return a version of the string where all necessary characters /// are properly escaped to make this into a json string (without @@ -166,10 +175,12 @@ class cstring { const char *c_str() const { return str; } operator const char *() const { return str; } - std::string string() const { return std::string(str); } + std::string string() const { return str ? std::string(str) : std::string(""); } explicit operator std::string() const { return string(); } - std::string_view string_view() const { return std::string_view(str); } + std::string_view string_view() const { + return str ? std::string_view(str) : std::string_view(""); + } explicit operator std::string_view() const { return string_view(); } // Size tests. Constant time except for size(), which is linear time. @@ -211,6 +222,8 @@ class cstring { bool operator>(const char *a) const { return str ? !a || strcmp(str, a) > 0 : false; } bool operator>=(cstring a) const { return *this >= a.str; } bool operator>=(const char *a) const { return str ? !a || strcmp(str, a) >= 0 : !a; } + bool operator==(std::string_view a) const { return str ? a.compare(str) == 0 : a.empty(); } + bool operator!=(std::string_view a) const { return str ? a.compare(str) != 0 : !a.empty(); } bool operator==(const std::string &a) const { return *this == a.c_str(); } bool operator!=(const std::string &a) const { return *this != a.c_str(); } @@ -219,8 +232,8 @@ class cstring { bool operator>(const std::string &a) const { return *this > a.c_str(); } bool operator>=(const std::string &a) const { return *this >= a.c_str(); } - bool startsWith(const cstring &prefix) const; - bool endsWith(const cstring &suffix) const; + bool startsWith(std::string_view prefix) const; + bool endsWith(std::string_view suffix) const; // FIXME (DanilLutsenko): We really need mutations for immutable string? // Probably better do transformation in std::string-like containter and @@ -237,7 +250,7 @@ class cstring { cstring before(const char *at) const; cstring substr(size_t start) const { - return (start >= size()) ? "" : substr(start, size() - start); + return (start >= size()) ? cstring::literal("") : substr(start, size() - start); } cstring substr(size_t start, size_t length) const; cstring replace(char find, char replace) const; @@ -384,7 +397,11 @@ namespace P4::literals { /// A user-provided literal suffix to allow creation of cstring from literals: "foo"_cs. /// Note that the C++ standard mandates that all user-defined literal suffixes defined outside of /// the standard library must start with underscore. -inline cstring operator""_cs(const char *str, std::size_t len) { return cstring(str, len); } +inline cstring operator""_cs(const char *str, std::size_t len) { + cstring result; + result.construct_from_literal(str, len); + return result; +} } // namespace P4::literals namespace std { diff --git a/lib/error.h b/lib/error.h index 6fed143305..f5f82b2aae 100644 --- a/lib/error.h +++ b/lib/error.h @@ -176,7 +176,7 @@ template inline void diagnose(DiagnosticAction defaultAction, const char *diagnosticName, const char *format, const char *suffix, Args &&...args) { auto &context = BaseCompileContext::get(); - auto action = context.getDiagnosticAction(diagnosticName, defaultAction); + auto action = context.getDiagnosticAction(cstring(diagnosticName), defaultAction); context.errorReporter().diagnose(action, diagnosticName, format, suffix, std::forward(args)...); } diff --git a/lib/error_catalog.cpp b/lib/error_catalog.cpp index 5e0cb4c0ca..cc8e2f80e6 100644 --- a/lib/error_catalog.cpp +++ b/lib/error_catalog.cpp @@ -17,7 +17,10 @@ limitations under the License. #include "error_catalog.h" #include -#include + +#include "lib/cstring.h" + +using namespace P4::literals; // -------- Errors ------------- const int ErrorType::LEGACY_ERROR = 0; @@ -71,49 +74,49 @@ const int ErrorType::INFO_PROGRESS = 2143; // map from errorCode to ErrorSig std::map ErrorCatalog::errorCatalog = { // Errors - {ErrorType::LEGACY_ERROR, "legacy"}, - {ErrorType::ERR_UNKNOWN, "unknown"}, - {ErrorType::ERR_UNSUPPORTED, "unsupported"}, - {ErrorType::ERR_UNEXPECTED, "unexpected"}, - {ErrorType::ERR_EXPECTED, "expected"}, - {ErrorType::ERR_NOT_FOUND, "not-found"}, - {ErrorType::ERR_INVALID, "invalid"}, - {ErrorType::ERR_EXPRESSION, "expr"}, - {ErrorType::ERR_OVERLIMIT, "overlimit"}, - {ErrorType::ERR_INSUFFICIENT, "insufficient"}, - {ErrorType::ERR_UNINITIALIZED, "uninitialized"}, - {ErrorType::ERR_TYPE_ERROR, "type-error"}, - {ErrorType::ERR_UNSUPPORTED_ON_TARGET, "target-error"}, - {ErrorType::ERR_DUPLICATE, "duplicate"}, - {ErrorType::ERR_IO, "I/O error"}, - {ErrorType::ERR_MODEL, "Target model error"}, - {ErrorType::ERR_RESERVED, "reserved"}, + {ErrorType::LEGACY_ERROR, "legacy"_cs}, + {ErrorType::ERR_UNKNOWN, "unknown"_cs}, + {ErrorType::ERR_UNSUPPORTED, "unsupported"_cs}, + {ErrorType::ERR_UNEXPECTED, "unexpected"_cs}, + {ErrorType::ERR_EXPECTED, "expected"_cs}, + {ErrorType::ERR_NOT_FOUND, "not-found"_cs}, + {ErrorType::ERR_INVALID, "invalid"_cs}, + {ErrorType::ERR_EXPRESSION, "expr"_cs}, + {ErrorType::ERR_OVERLIMIT, "overlimit"_cs}, + {ErrorType::ERR_INSUFFICIENT, "insufficient"_cs}, + {ErrorType::ERR_UNINITIALIZED, "uninitialized"_cs}, + {ErrorType::ERR_TYPE_ERROR, "type-error"_cs}, + {ErrorType::ERR_UNSUPPORTED_ON_TARGET, "target-error"_cs}, + {ErrorType::ERR_DUPLICATE, "duplicate"_cs}, + {ErrorType::ERR_IO, "I/O error"_cs}, + {ErrorType::ERR_MODEL, "Target model error"_cs}, + {ErrorType::ERR_RESERVED, "reserved"_cs}, // Warnings - {ErrorType::LEGACY_WARNING, "legacy"}, - {ErrorType::WARN_FAILED, "failed"}, - {ErrorType::WARN_UNKNOWN, "unknown"}, - {ErrorType::WARN_INVALID, "invalid"}, - {ErrorType::WARN_UNSUPPORTED, "unsupported"}, - {ErrorType::WARN_DEPRECATED, "deprecated"}, - {ErrorType::WARN_UNINITIALIZED, "uninitialized"}, - {ErrorType::WARN_UNUSED, "unused"}, - {ErrorType::WARN_MISSING, "missing"}, - {ErrorType::WARN_ORDERING, "ordering"}, - {ErrorType::WARN_MISMATCH, "mismatch"}, - {ErrorType::WARN_OVERFLOW, "overflow"}, - {ErrorType::WARN_IGNORE_PROPERTY, "ignore-prop"}, - {ErrorType::WARN_TYPE_INFERENCE, "type-inference"}, - {ErrorType::WARN_PARSER_TRANSITION, "parser-transition"}, - {ErrorType::WARN_UNREACHABLE, "parser-transition"}, - {ErrorType::WARN_SHADOWING, "shadow"}, - {ErrorType::WARN_UNINITIALIZED_USE, "uninitialized_use"}, - {ErrorType::WARN_UNINITIALIZED_OUT_PARAM, "uninitialized_out_param"}, - {ErrorType::WARN_IGNORE, "ignore"}, - {ErrorType::WARN_INVALID_HEADER, "invalid_header"}, - {ErrorType::WARN_DUPLICATE_PRIORITIES, "duplicate_priorities"}, - {ErrorType::WARN_ENTRIES_OUT_OF_ORDER, "entries_out_of_priority_order"}, + {ErrorType::LEGACY_WARNING, "legacy"_cs}, + {ErrorType::WARN_FAILED, "failed"_cs}, + {ErrorType::WARN_UNKNOWN, "unknown"_cs}, + {ErrorType::WARN_INVALID, "invalid"_cs}, + {ErrorType::WARN_UNSUPPORTED, "unsupported"_cs}, + {ErrorType::WARN_DEPRECATED, "deprecated"_cs}, + {ErrorType::WARN_UNINITIALIZED, "uninitialized"_cs}, + {ErrorType::WARN_UNUSED, "unused"_cs}, + {ErrorType::WARN_MISSING, "missing"_cs}, + {ErrorType::WARN_ORDERING, "ordering"_cs}, + {ErrorType::WARN_MISMATCH, "mismatch"_cs}, + {ErrorType::WARN_OVERFLOW, "overflow"_cs}, + {ErrorType::WARN_IGNORE_PROPERTY, "ignore-prop"_cs}, + {ErrorType::WARN_TYPE_INFERENCE, "type-inference"_cs}, + {ErrorType::WARN_PARSER_TRANSITION, "parser-transition"_cs}, + {ErrorType::WARN_UNREACHABLE, "parser-transition"_cs}, + {ErrorType::WARN_SHADOWING, "shadow"_cs}, + {ErrorType::WARN_UNINITIALIZED_USE, "uninitialized_use"_cs}, + {ErrorType::WARN_UNINITIALIZED_OUT_PARAM, "uninitialized_out_param"_cs}, + {ErrorType::WARN_IGNORE, "ignore"_cs}, + {ErrorType::WARN_INVALID_HEADER, "invalid_header"_cs}, + {ErrorType::WARN_DUPLICATE_PRIORITIES, "duplicate_priorities"_cs}, + {ErrorType::WARN_ENTRIES_OUT_OF_ORDER, "entries_out_of_priority_order"_cs}, // Info messages - {ErrorType::INFO_INFERRED, "inferred"}, - {ErrorType::INFO_PROGRESS, "progress"}}; + {ErrorType::INFO_INFERRED, "inferred"_cs}, + {ErrorType::INFO_PROGRESS, "progress"_cs}}; diff --git a/lib/error_catalog.h b/lib/error_catalog.h index 122a0539fa..ce8eaa8493 100644 --- a/lib/error_catalog.h +++ b/lib/error_catalog.h @@ -32,6 +32,7 @@ class ErrorType { public: // -------- Errors ------------- // errors as initially defined with a format string + // FIXME: make these constexpr static const int LEGACY_ERROR; static const int ERR_UNKNOWN; // unknown construct (in context) static const int ERR_UNSUPPORTED; // unsupported construct @@ -123,17 +124,20 @@ class ErrorCatalog { /// retrieve the name for errorCode cstring getName(int errorCode) { + using namespace P4::literals; + if (errorCatalog.count(errorCode)) return errorCatalog.at(errorCode); - return "--unknown--"; + return "--unknown--"_cs; } /// return true if the given diagnostic can _only_ be an error; false otherwise - bool isError(cstring name) { + bool isError(std::string_view name) { + cstring lookup(name); // Some diagnostics might be both errors and warning/info // (e.g. "invalid" -> both ERR_INVALID and WARN_INVALID). bool error = false; for (const auto &pair : errorCatalog) { - if (pair.second == name) { + if (pair.second == lookup) { if (pair.first < ErrorType::LEGACY_ERROR || pair.first > ErrorType::ERR_MAX) return false; error = true; diff --git a/lib/error_reporter.h b/lib/error_reporter.h index 1affede912..8fe7151a12 100644 --- a/lib/error_reporter.h +++ b/lib/error_reporter.h @@ -78,9 +78,7 @@ class ErrorReporter { } /// retrieve the format from the error catalog - const char *get_error_name(int errorCode) { - return ErrorCatalog::getCatalog().getName(errorCode); - } + cstring get_error_name(int errorCode) { return ErrorCatalog::getCatalog().getName(errorCode); } public: ErrorReporter() @@ -112,7 +110,7 @@ class ErrorReporter { void diagnose(DiagnosticAction action, const int errorCode, const char *format, const char *suffix, const T *node, Args &&...args) { if (node && !error_reported(errorCode, node->getSourceInfo())) { - const char *name = get_error_name(errorCode); + cstring name = get_error_name(errorCode); auto da = getDiagnosticAction(name, action); if (name) diagnose(da, name, format, suffix, node, std::forward(args)...); @@ -130,7 +128,7 @@ class ErrorReporter { template void diagnose(DiagnosticAction action, const int errorCode, const char *format, const char *suffix, Args &&...args) { - const char *name = get_error_name(errorCode); + cstring name = get_error_name(errorCode); auto da = getDiagnosticAction(name, action); if (name) diagnose(da, name, format, suffix, std::forward(args)...); @@ -245,8 +243,8 @@ class ErrorReporter { } /// Set the action to take for the given diagnostic. - void setDiagnosticAction(cstring diagnostic, DiagnosticAction action) { - diagnosticActions[diagnostic] = action; + void setDiagnosticAction(std::string_view diagnostic, DiagnosticAction action) { + diagnosticActions[cstring(diagnostic)] = action; } /// @return the default diagnostic action for calls to `::warning()`. diff --git a/lib/json.cpp b/lib/json.cpp index 782f5aa7f0..7620ab07c1 100644 --- a/lib/json.cpp +++ b/lib/json.cpp @@ -163,9 +163,9 @@ JsonObject *JsonObject::emplace(cstring label, IJson *value) { auto j = get(label); if (j != nullptr) { cstring s = value->toString(); - throw std::logic_error(cstring("Attempt to add to json object a value " - "for a label which already exists ") + - label.c_str() + " " + s.c_str()); + throw std::logic_error(std::string("Attempt to add to json object a value " + "for a label which already exists ") + + label.string() + " " + s.string()); } ordered_map::emplace(label, value); return this; diff --git a/lib/json.h b/lib/json.h index 93a52994b5..5b0f53c873 100644 --- a/lib/json.h +++ b/lib/json.h @@ -103,7 +103,7 @@ class JsonValue final : public IJson { const Kind tag; const big_int value = 0; - const cstring str = nullptr; + const cstring str = ""_cs; DECLARE_TYPEINFO(JsonValue, IJson); }; diff --git a/lib/nullstream.cpp b/lib/nullstream.cpp index c3f6ee11b8..31a82ebd64 100644 --- a/lib/nullstream.cpp +++ b/lib/nullstream.cpp @@ -18,6 +18,7 @@ limitations under the License. #include // IWYU pragma: keep +// FIXME: this should accept string_view instead std::ostream *openFile(cstring name, bool nullOnError) { if (name.isNullOrEmpty()) { if (nullOnError) return new nullstream(); diff --git a/lib/options.cpp b/lib/options.cpp index 64273abca1..c6451eae75 100644 --- a/lib/options.cpp +++ b/lib/options.cpp @@ -27,15 +27,15 @@ void Util::Options::registerOption(const char *option, const char *argName, if (option[0] != '-') throw std::logic_error(std::string("Expected option to start with -: ") + option); auto o = new Option(); - o->option = option; + o->option = cstring(option); o->argName = argName; o->processor = processor; o->description = description; o->flags = flags; - auto opt = get(options, option); + auto opt = get(options, cstring(option)); if (opt != nullptr) throw std::logic_error(std::string("Option already registered: ") + option); options.emplace(option, o); - optionOrder.push_back(option); + optionOrder.push_back(cstring(option)); } // Process options; return list of remaining options. @@ -57,7 +57,7 @@ std::vector *Util::Options::process(int argc, char *const argv[]) strftime(build_date, 50, "%c", localtime(&now)); buildDate = cstring(build_date); for (int i = 1; i < argc; i++) { - cstring opt = argv[i]; + cstring opt = cstring(argv[i]); const char *arg = nullptr; const Option *option = nullptr; diff --git a/lib/options.h b/lib/options.h index 03ba0adcc4..6437b13943 100644 --- a/lib/options.h +++ b/lib/options.h @@ -82,7 +82,8 @@ class Options { const char *description, // option help message OptionFlags flags = OptionFlags::Default); // additional flags - explicit Options(cstring message) : binaryName(nullptr), message(message), compileCommand("") {} + explicit Options(std::string_view message) + : binaryName(nullptr), message(message), compileCommand("") {} public: /** diff --git a/lib/path.cpp b/lib/path.cpp index c7f01188fa..7bcfc206bf 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -54,7 +54,7 @@ cstring PathName::getExtension() const { const char *dot = filename.str.findlast('.'); if (dot == nullptr) return cstring::empty; - return dot + 1; + return cstring(dot + 1); } PathName PathName::getFolder() const { diff --git a/lib/path.h b/lib/path.h index 969726f3fe..9e28369236 100644 --- a/lib/path.h +++ b/lib/path.h @@ -25,7 +25,10 @@ limitations under the License. #include "cstring.h" namespace Util { +using namespace P4::literals; + // Represents a filename path, e.g., /usr/local/bin/file.exe +// FIXME: Can we replace with std::filesystem? class PathName final { private: static const char pathSeparators[2]; @@ -36,9 +39,9 @@ class PathName final { public: static inline cstring separator() { #ifdef _WIN32 - return "\\"; + return "\\"_cs; #else - return "/"; + return "/"_cs; #endif } diff --git a/lib/sourceCodeBuilder.h b/lib/sourceCodeBuilder.h index f5c9545d7c..10f770fc6d 100644 --- a/lib/sourceCodeBuilder.h +++ b/lib/sourceCodeBuilder.h @@ -53,6 +53,10 @@ class SourceCodeBuilder { } void append(cstring str) { append(str.c_str()); } + void appendLine(const char *str) { + append(str); + newline(); + } void appendLine(cstring str) { append(str); newline(); diff --git a/lib/source_file.cpp b/lib/source_file.cpp index e34e6a00fd..f23c877212 100644 --- a/lib/source_file.cpp +++ b/lib/source_file.cpp @@ -56,7 +56,7 @@ cstring SourceInfo::toString() const { ////////////////////////////////////////////////////////////////////////////////////////// InputSources::InputSources() : sealed(false) { - mapLine(nullptr, 1); // the first line read will be line 1 of stdin + mapLine("", 1); // the first line read will be line 1 of stdin contents.push_back(""); } @@ -137,7 +137,7 @@ void InputSources::appendText(const char *text) { cstring InputSources::getLine(unsigned lineNumber) const { if (lineNumber == 0) { - return ""; + return ""_cs; // BUG("Lines are numbered starting at 1"); // don't throw: this code may be called by exceptions // reporting on elements that have no source position @@ -145,7 +145,7 @@ cstring InputSources::getLine(unsigned lineNumber) const { return contents.at(lineNumber - 1); } -void InputSources::mapLine(cstring file, unsigned originalSourceLineNo) { +void InputSources::mapLine(std::string_view file, unsigned originalSourceLineNo) { if (sealed) BUG("Changing mapping to sealed InputSources"); unsigned lineno = getCurrentLineNumber(); line_file_map.emplace(lineno, SourceFileLine(file, originalSourceLineNo)); @@ -169,7 +169,7 @@ SourceFileLine InputSources::getSourceLine(unsigned line) const { // So we have to subtract one to get the real line number. const auto nominalLine = line - it->first + it->second.sourceLine; const auto realLine = nominalLine > 0 ? nominalLine - 1 : 0; - return SourceFileLine(it->second.fileName, realLine); + return SourceFileLine(it->second.fileName.string_view(), realLine); } unsigned InputSources::getCurrentLineNumber() const { return contents.size(); } @@ -204,7 +204,7 @@ cstring carets(cstring source, unsigned start, unsigned end) { } cstring InputSources::getSourceFragment(const SourceInfo &position, bool useMarker) const { - if (!position.isValid()) return ""; + if (!position.isValid()) return ""_cs; // If the position spans multiple lines, truncate to just the first line if (position.getEnd().getLineNumber() > position.getStart().getLineNumber()) @@ -213,7 +213,7 @@ cstring InputSources::getSourceFragment(const SourceInfo &position, bool useMark cstring result = getLine(position.getStart().getLineNumber()); // Normally result has a newline, but if not // then we have to add a newline - cstring toadd = ""; + cstring toadd = ""_cs; if (result.find('\n') == nullptr) toadd = cstring::newline; cstring marker = carets(result, position.getStart().getColumnNumber(), position.getEnd().getColumnNumber()); @@ -225,12 +225,12 @@ cstring InputSources::getSourceFragment(const SourceInfo &position, bool useMark } cstring InputSources::getBriefSourceFragment(const SourceInfo &position) const { - if (!position.isValid()) return ""; + if (!position.isValid()) return ""_cs; cstring result = getLine(position.getStart().getLineNumber()); unsigned int start = position.getStart().getColumnNumber(); unsigned int end; - cstring toadd = ""; + cstring toadd = ""_cs; // If the position spans multiple lines, truncate to just the first line if (position.getEnd().getLineNumber() > position.getStart().getLineNumber()) { @@ -239,7 +239,7 @@ cstring InputSources::getBriefSourceFragment(const SourceInfo &position) const { if (result.find('\n') != nullptr) { --end; } - toadd = " ..."; + toadd = " ..."_cs; } else { end = position.getEnd().getColumnNumber(); } @@ -247,7 +247,7 @@ cstring InputSources::getBriefSourceFragment(const SourceInfo &position) const { // Adding escape character in front of '"' character to properly store // quote marks as part of JSON properties, they must be escaped. if (result.find('"') != nullptr) { - cstring out = result.replace("\"", "\\\""); + cstring out = result.replace("\""_cs, "\\\""_cs); return out.substr(0, out.size() - 1); } @@ -265,17 +265,17 @@ cstring InputSources::toDebugString() const { /////////////////////////////////////////////////// cstring SourceInfo::toSourceFragment(bool useMarker) const { - if (!isValid()) return ""; + if (!isValid()) return ""_cs; return sources->getSourceFragment(*this, useMarker); } cstring SourceInfo::toBriefSourceFragment() const { - if (!isValid()) return ""; + if (!isValid()) return ""_cs; return sources->getBriefSourceFragment(*this); } cstring SourceInfo::toPositionString() const { - if (!isValid()) return ""; + if (!isValid()) return ""_cs; SourceFileLine position = sources->getSourceLine(start.getLineNumber()); return position.toString(); } @@ -288,7 +288,7 @@ cstring SourceInfo::toSourcePositionData(unsigned *outLineNumber, unsigned *outC if (outColumnNumber != nullptr) { *outColumnNumber = start.getColumnNumber(); } - return position.fileName.c_str(); + return position.fileName; } SourceFileLine SourceInfo::toPosition() const { diff --git a/lib/source_file.h b/lib/source_file.h index 8d26306b0d..198db41c13 100644 --- a/lib/source_file.h +++ b/lib/source_file.h @@ -37,6 +37,8 @@ class UtilSourceFile; } namespace Util { +using namespace P4::literals; + struct SourceFileLine; /** A character position within some InputSources: a pair of @@ -119,10 +121,10 @@ SourceInfo can also be "invalid" */ class SourceInfo final { public: - cstring filename = ""; + cstring filename = ""_cs; int line = -1; int column = -1; - cstring srcBrief = ""; + cstring srcBrief = ""_cs; SourceInfo(cstring filename, int line, int column, cstring srcBrief) { this->filename = filename; this->line = line; @@ -220,7 +222,7 @@ struct SourceFileLine { cstring fileName; unsigned sourceLine; - SourceFileLine(cstring file, unsigned line) : fileName(file), sourceLine(line) {} + SourceFileLine(std::string_view file, unsigned line) : fileName(file), sourceLine(line) {} cstring toString() const; }; @@ -282,7 +284,7 @@ class InputSources final { /** Map the next line in the file to the line with number 'originalSourceLine' from file 'file'. */ - void mapLine(cstring file, unsigned originalSourceLineNo); + void mapLine(std::string_view file, unsigned originalSourceLineNo); /** The following return a nice (multi-line, newline-terminated) diff --git a/midend/actionSynthesis.cpp b/midend/actionSynthesis.cpp index 502c40f995..1138988ccf 100644 --- a/midend/actionSynthesis.cpp +++ b/midend/actionSynthesis.cpp @@ -21,6 +21,8 @@ limitations under the License. namespace P4 { +using namespace literals; + const IR::Node *DoMoveActionsToTables::postorder(IR::MethodCallStatement *statement) { auto mi = MethodInstance::resolve(statement, refMap, typeMap); if (!mi->is()) return statement; @@ -66,7 +68,7 @@ const IR::Node *DoMoveActionsToTables::postorder(IR::MethodCallStatement *statem // List of table properties auto props = new IR::TableProperties({prop, defprop}); // Synthesize a new table - cstring tblName = IR::ID(refMap->newName(cstring("tbl_") + ac->action->name.name), nullptr); + cstring tblName = IR::ID(refMap->newName("tbl_"_cs + ac->action->name.name), nullptr); auto annos = new IR::Annotations(); annos->add(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); @@ -167,9 +169,9 @@ const IR::Node *DoSynthesizeActions::preorder(IR::BlockStatement *statement) { } static cstring createName(const Util::SourceInfo &si) { - if (!si.isValid()) return "act"; + if (!si.isValid()) return "act"_cs; auto pos = si.toPosition(); - if (pos.fileName.isNullOrEmpty() || pos.sourceLine == 0) return "act"; + if (pos.fileName.isNullOrEmpty() || pos.sourceLine == 0) return "act"_cs; std::string name; const char *p = pos.fileName.findlast('/'); p = p ? p + 1 : pos.fileName.c_str(); @@ -178,14 +180,14 @@ static cstring createName(const Util::SourceInfo &si) { if (isalnum(*p) || *p == '_') name += *p; ++p; } - if (name.empty()) return "act"; + if (name.empty()) return "act"_cs; if (isdigit(name.back())) name += 'l'; return name + std::to_string(pos.sourceLine); } const IR::Statement *DoSynthesizeActions::createAction(const IR::Statement *toAdd) { changes = true; - auto name = refMap->newName(createName(toAdd->srcInfo)); + cstring name = refMap->newName(createName(toAdd->srcInfo).string_view()); const IR::BlockStatement *body; if (toAdd->is()) { body = toAdd->to(); diff --git a/midend/def_use.cpp b/midend/def_use.cpp index b941a9ca2f..9ce1728d1b 100644 --- a/midend/def_use.cpp +++ b/midend/def_use.cpp @@ -20,6 +20,8 @@ limitations under the License. namespace P4 { +using namespace literals; + const ordered_set ComputeDefUse::empty = {}; void ComputeDefUse::flow_merge(Visitor &a_) { @@ -143,7 +145,8 @@ class ComputeDefUse::SetupJoinPoints : public ControlFlowVisitor::SetupJoinPoint IndentCtl::TempIndent indent; LOG6("SetupJoinPoints(P4Parser " << p->name << ")" << indent); LOG8(" " << Log::indent << Log::indent << *p << Log::unindent << Log::unindent); - if (auto start = p->states.getDeclaration("start")) visit(start, "start"); + if (auto start = p->states.getDeclaration("start"_cs)) + visit(start, "start"); return false; } bool preorder(const IR::P4Control *) override { return false; } @@ -317,7 +320,7 @@ bool ComputeDefUse::preorder(const IR::P4Parser *p) { if (a->direction == IR::Direction::In || a->direction == IR::Direction::InOut) def_info[a].defs.insert(getLoc(a)); state = NORMAL; - if (auto start = p->states.getDeclaration("start")) { + if (auto start = p->states.getDeclaration("start"_cs)) { visit(start, "start"); } else { BUG("No start state in %s", p); diff --git a/midend/eliminateTuples.cpp b/midend/eliminateTuples.cpp index 8c4ecb4b39..6a15239122 100644 --- a/midend/eliminateTuples.cpp +++ b/midend/eliminateTuples.cpp @@ -4,6 +4,8 @@ namespace P4 { +using namespace literals; + const IR::Type *ReplacementMap::convertType(const IR::Type *type) { auto it = replacement.find(type); if (it != replacement.end()) return it->second; @@ -31,7 +33,7 @@ const IR::Type *ReplacementMap::convertType(const IR::Type *type) { size_t index = 0; for (auto t : bl->components) { auto ftype = convertType(t); - auto fname = cstring("f") + cstring(std::to_string(index)); + auto fname = "f"_cs + Util::toString(index); auto field = new IR::StructField(IR::ID(fname), ftype->getP4Type()); fields.push_back(field); index++; @@ -92,7 +94,7 @@ const IR::Node *DoReplaceTuples::postorder(IR::ArrayIndex *expression) { if (type->is()) { auto cst = expression->right->to(); BUG_CHECK(cst, "%1%: Expected a constant", expression->right); - cstring field = cstring("f") + Util::toString(cst->asInt()); + cstring field = "f"_cs + Util::toString(cst->asInt()); auto src = expression->right->srcInfo; return new IR::Member(src, expression->left, IR::ID(src, field)); } diff --git a/midend/expr_uses.h b/midend/expr_uses.h index 9205683820..25908667a4 100644 --- a/midend/expr_uses.h +++ b/midend/expr_uses.h @@ -29,7 +29,7 @@ class exprUses : public Inspector { const char *search_tail = nullptr; // pointer into look_for for partial match bool result = false; bool preorder(const IR::Path *p) override { - if (look_for.startsWith(p->name)) { + if (look_for.startsWith(p->name.name.string_view())) { search_tail = look_for.c_str() + p->name.name.size(); if (*search_tail == 0 || *search_tail == '.' || *search_tail == '[') result = true; } @@ -44,7 +44,7 @@ class exprUses : public Inspector { void postorder(const IR::Member *m) override { if (result && search_tail && *search_tail) { if (*search_tail == '.') search_tail++; - if (cstring(search_tail).startsWith(m->member)) { + if (cstring(search_tail).startsWith(m->member.name.string_view())) { search_tail += m->member.name.size(); if (*search_tail == 0 || *search_tail == '.' || *search_tail == '[') return; } diff --git a/midend/flattenHeaders.cpp b/midend/flattenHeaders.cpp index 4f386182c4..e67fdda2fe 100644 --- a/midend/flattenHeaders.cpp +++ b/midend/flattenHeaders.cpp @@ -18,6 +18,7 @@ limitations under the License. #include "flattenHeaders.h" namespace P4 { +using namespace literals; void FindHeaderTypesToReplace::createReplacement(const IR::Type_Header *type, AnnotationSelectionPolicy *policy) { @@ -63,11 +64,11 @@ const IR::Node *ReplaceHeaders::postorder(IR::Type_Header *type) { const IR::Node *ReplaceHeaders::postorder(IR::Member *expression) { // Find out if this applies to one of the parameters that are being replaced. const IR::Expression *e = expression; - cstring prefix = ""; + std::string prefix; const IR::Type_Header *h = nullptr; while (auto mem = e->to()) { e = mem->expr; - prefix = cstring(".") + mem->member + prefix; + prefix = "." + mem->member + prefix; auto type = typeMap->getType(e, true); if ((h = type->to())) break; } diff --git a/midend/flattenInterfaceStructs.cpp b/midend/flattenInterfaceStructs.cpp index a6eae9641e..cd854ce3bf 100644 --- a/midend/flattenInterfaceStructs.cpp +++ b/midend/flattenInterfaceStructs.cpp @@ -17,6 +17,7 @@ limitations under the License. #include "flattenInterfaceStructs.h" namespace P4 { +using namespace literals; namespace { static const IR::Type_Struct *isNestedStruct(const P4::TypeMap *typeMap, const IR::Type *type) { @@ -70,10 +71,10 @@ const IR::Node *ReplaceStructs::postorder(IR::Type_Struct *type) { const IR::Node *ReplaceStructs::postorder(IR::Member *expression) { // Find out if this applies to one of the parameters that are being replaced. const IR::Expression *e = expression; - cstring prefix = ""; + std::string prefix; while (auto mem = e->to()) { e = mem->expr; - prefix = cstring(".") + mem->member + prefix; + prefix = "." + mem->member + prefix; } auto pe = e->to(); if (pe == nullptr) return expression; diff --git a/midend/flattenInterfaceStructs.h b/midend/flattenInterfaceStructs.h index dbe39a22a5..22aa15664b 100644 --- a/midend/flattenInterfaceStructs.h +++ b/midend/flattenInterfaceStructs.h @@ -19,6 +19,7 @@ limitations under the License. #include "frontends/p4/typeChecking/typeChecker.h" #include "ir/ir.h" +#include "lib/cstring.h" namespace P4 { @@ -67,7 +68,7 @@ struct StructTypeReplacement : public IHasDbPrint { StructTypeReplacement(const P4::TypeMap *typeMap, const IR::Type_StructLike *type, AnnotationSelectionPolicy *policy) { auto vec = new IR::IndexedVector(); - flatten(typeMap, "", type, type->annotations, vec, policy); + flatten(typeMap, cstring::empty, type, type->annotations, vec, policy); if (type->is()) { replacementType = new IR::Type_Struct(type->srcInfo, type->name, IR::Annotations::empty, *vec); @@ -123,7 +124,7 @@ struct StructTypeReplacement : public IHasDbPrint { } return; } - cstring fieldName = prefix.replace(".", "_") + cstring::to_cstring(fieldNameRemap.size()); + cstring fieldName = prefix.replace('.', '_') + std::to_string(fieldNameRemap.size()); fieldNameRemap.emplace(prefix, fieldName); fields->push_back(new IR::StructField(IR::ID(fieldName), annotations, type->getP4Type())); LOG3("Flatten: " << type << " | " << prefix); diff --git a/midend/global_copyprop.cpp b/midend/global_copyprop.cpp index 2d816f17ef..5c1a0f6679 100644 --- a/midend/global_copyprop.cpp +++ b/midend/global_copyprop.cpp @@ -26,8 +26,8 @@ static cstring lValueName(const IR::Expression *exp) { /// Test to see if names denote overlapping locations. bool names_overlap(cstring name1, cstring name2) { if (name1 == name2) return true; - if (name1.startsWith(name2) && strchr(".[", name1.get(name2.size()))) return true; - if (name2.startsWith(name1) && strchr(".[", name2.get(name1.size()))) return true; + if (name1.startsWith(name2.string_view()) && strchr(".[", name1.get(name2.size()))) return true; + if (name2.startsWith(name1.string_view()) && strchr(".[", name2.get(name1.size()))) return true; return false; } diff --git a/midend/interpreter.h b/midend/interpreter.h index 35755f32a0..669e25f675 100644 --- a/midend/interpreter.h +++ b/midend/interpreter.h @@ -212,8 +212,8 @@ class SymbolicException : public SymbolicError { class SymbolicStaticError : public SymbolicError { public: - const cstring msg; - SymbolicStaticError(const IR::Node *errorPosition, cstring message) + const std::string msg; + SymbolicStaticError(const IR::Node *errorPosition, std::string_view message) : SymbolicError(errorPosition), msg(message) {} SymbolicValue *clone() const override { return new SymbolicStaticError(errorPosition, msg); } void dbprint(std::ostream &out) const override { out << "Error: " << msg; } diff --git a/midend/local_copyprop.cpp b/midend/local_copyprop.cpp index 9bbe021d67..b6e97bf47a 100644 --- a/midend/local_copyprop.cpp +++ b/midend/local_copyprop.cpp @@ -26,6 +26,8 @@ limitations under the License. namespace P4 { +using namespace literals; + /* helper function to get the 'outermost' containing expression in an lvalue */ static const IR::Expression *lvalue_out(const IR::Expression *exp) { if (auto ai = exp->to()) return lvalue_out(ai->left); @@ -231,8 +233,8 @@ bool DoLocalCopyPropagation::operator==(const ControlFlowVisitor &a_) const { /// test to see if names denote overlapping locations bool DoLocalCopyPropagation::name_overlap(cstring name1, cstring name2) { if (name1 == name2) return true; - if (name1.startsWith(name2) && strchr(".[", name1.get(name2.size()))) return true; - if (name2.startsWith(name1) && strchr(".[", name2.get(name1.size()))) return true; + if (name1.startsWith(name2.string_view()) && strchr(".[", name1.get(name2.size()))) return true; + if (name2.startsWith(name1.string_view()) && strchr(".[", name2.get(name1.size()))) return true; return false; } @@ -256,7 +258,8 @@ void DoLocalCopyPropagation::forOverlapAvail(cstring name, if (it != available.end()) fn(it->first, &it->second); } for (auto it = available.upper_bound(name); it != available.end(); ++it) { - if (!it->first.startsWith(name) || !strchr(".[", it->first.get(name.size()))) break; + if (!it->first.startsWith(name.string_view()) || !strchr(".[", it->first.get(name.size()))) + break; fn(it->first, &it->second); } } @@ -463,12 +466,12 @@ IR::IfStatement *DoLocalCopyPropagation::postorder(IR::IfStatement *s) { IR::ForStatement *DoLocalCopyPropagation::preorder(IR::ForStatement *s) { visit(s->init, "init"); s->apply(LoopPrepass(*this), getContext()); - ControlFlowVisitor::SaveGlobal outer(*this, "-BREAK-", "-CONTINUE-"); + ControlFlowVisitor::SaveGlobal outer(*this, "-BREAK-"_cs, "-CONTINUE-"_cs); visit(s->condition, "condition"); visit(s->body, "body"); - flow_merge_global_from("-CONTINUE-"); + flow_merge_global_from("-CONTINUE-"_cs); visit(s->updates, "updates"); - flow_merge_global_from("-BREAK-"); + flow_merge_global_from("-BREAK-"_cs); prune(); return s; } @@ -477,11 +480,11 @@ IR::ForInStatement *DoLocalCopyPropagation::preorder(IR::ForInStatement *s) { visit(s->decl, "decl", 0); visit(s->collection, "collection", 2); s->apply(LoopPrepass(*this), getContext()); - ControlFlowVisitor::SaveGlobal outer(*this, "-BREAK-", "-CONTINUE-"); + ControlFlowVisitor::SaveGlobal outer(*this, "-BREAK-"_cs, "-CONTINUE-"_cs); visit(s->ref, "ref", 1); visit(s->body, "body", 3); - flow_merge_global_from("-CONTINUE-"); - flow_merge_global_from("-BREAK-"); + flow_merge_global_from("-CONTINUE-"_cs); + flow_merge_global_from("-BREAK-"_cs); prune(); return s; } diff --git a/midend/nestedStructs.cpp b/midend/nestedStructs.cpp index dffe405278..be38559252 100644 --- a/midend/nestedStructs.cpp +++ b/midend/nestedStructs.cpp @@ -4,6 +4,8 @@ namespace P4 { +using namespace literals; + bool ComplexValues::isNestedStruct(const IR::Type *type) { if (!type->is()) return false; auto st = type->to(); @@ -30,7 +32,7 @@ void ComplexValues::explode(cstring prefix, const IR::Type_Struct *type, FieldsM map->members.emplace(f->name.name, submap); explode(fname, ftype->to(), submap, result); } else { - cstring newName = refMap->newName(fname); + cstring newName = refMap->newName(fname.string_view()); auto comp = new FinalName(newName); map->members.emplace(f->name.name, comp); auto clone = new IR::Declaration_Variable(IR::ID(newName), ftype->getP4Type()); @@ -45,9 +47,10 @@ const IR::Node *RemoveNestedStructs::postorder(IR::Declaration_Variable *decl) { if (!values->isNestedStruct(type)) return decl; BUG_CHECK(decl->initializer == nullptr, "%1%: did not expect an initializer", decl); - BUG_CHECK(decl->annotations->size() == 0 || (decl->annotations->size() == 1 && - decl->annotations->getSingle("name") != nullptr), - "%1%: don't know how to handle variable annotations other than @name", decl); + BUG_CHECK( + decl->annotations->size() == 0 || + (decl->annotations->size() == 1 && decl->annotations->getSingle("name"_cs) != nullptr), + "%1%: don't know how to handle variable annotations other than @name", decl); auto map = new ComplexValues::FieldsMap(type); values->values.emplace(getOriginal(), map); if (findContext()) { diff --git a/midend/parserUnroll.h b/midend/parserUnroll.h index f2024aa2a3..5246c391e9 100644 --- a/midend/parserUnroll.h +++ b/midend/parserUnroll.h @@ -151,7 +151,7 @@ class ParserStructure { std::map callsIndexes; // map for curent calls of state insite current one void setParser(const IR::P4Parser *parser) { CHECK_NULL(parser); - callGraph = new StateCallGraph(parser->name); + callGraph = new StateCallGraph(parser->name.name.string_view()); this->parser = parser; start = nullptr; } @@ -268,7 +268,7 @@ class RewriteAllParsers : public Transform { IR::Type::Void::get(), new IR::PathExpression( new IR::Type_Method(IR::Type::Void::get(), new IR::ParameterList(parameters), - "*method"), + "*method"_cs), new IR::Path(IR::ID("verify"))), arguments))); auto *outOfBoundsState = new IR::ParserState( diff --git a/midend/removeExits.cpp b/midend/removeExits.cpp index a150d2d21b..c559ae36d0 100644 --- a/midend/removeExits.cpp +++ b/midend/removeExits.cpp @@ -100,7 +100,7 @@ const IR::Node *DoRemoveExits::preorder(IR::P4Control *control) { return control; } - cstring var = refMap->newName(variableName); + cstring var = refMap->newName(variableName.string_view()); returnVar = IR::ID(var, nullptr); visit(control->controlLocals, "controlLocals"); diff --git a/midend/removeExits.h b/midend/removeExits.h index e1b99f113b..e6d1e34971 100644 --- a/midend/removeExits.h +++ b/midend/removeExits.h @@ -39,7 +39,7 @@ class DoRemoveExits : public DoRemoveReturns { public: DoRemoveExits(ReferenceMap *refMap, TypeMap *typeMap) - : DoRemoveReturns(refMap, "hasExited"), typeMap(typeMap) { + : DoRemoveReturns(refMap, "hasExited"_cs), typeMap(typeMap) { visitDagOnce = false; CHECK_NULL(typeMap); setName("DoRemoveExits"); diff --git a/midend/simplifySelectList.cpp b/midend/simplifySelectList.cpp index 908de03d40..a7cf69474f 100644 --- a/midend/simplifySelectList.cpp +++ b/midend/simplifySelectList.cpp @@ -16,6 +16,8 @@ limitations under the License. #include "simplifySelectList.h" +#include "lib/cstring.h" + namespace P4 { void SubstituteStructures::explode(const IR::Expression *expression, const IR::Type *type, @@ -89,7 +91,7 @@ void UnnestSelectList::flatten(const IR::Expression *expression, unsigned *nesti const IR::Node *UnnestSelectList::preorder(IR::SelectExpression *expression) { IR::Vector vec; - nesting = ""; + nesting = cstring::empty; flatten(expression->select, &vec); if (nesting.findlast(']') == nesting.c_str()) // no nested lists found diff --git a/midend/simplifySelectList.h b/midend/simplifySelectList.h index 7361c54ef2..d32596f98d 100644 --- a/midend/simplifySelectList.h +++ b/midend/simplifySelectList.h @@ -64,6 +64,7 @@ transition select(a, b, c, d) { class UnnestSelectList : public Transform { // Represent the nesting of lists inside of a selectExpression. // E.g.: [__[__]_] for two nested lists. + // FIXME: Lots of terrible concatenations here, must be std::string cstring nesting; void flatten(const IR::Expression *expression, IR::Vector *output); diff --git a/test/gtest/constant_folding.cpp b/test/gtest/constant_folding.cpp index e839646e50..e722ce086d 100644 --- a/test/gtest/constant_folding.cpp +++ b/test/gtest/constant_folding.cpp @@ -100,13 +100,13 @@ TEST_F(P4CConstantFoldingValidation, no_filter) { ASSERT_TRUE(program); // my_hdr_stack_1_t.hdr should be a Constant - auto *sf_1 = getStructField(program, "my_hdr_stack_1_t", "hdr"); + auto *sf_1 = getStructField(program, "my_hdr_stack_1_t"_cs, "hdr"_cs); ASSERT_TRUE(sf_1); auto *ts_1 = sf_1->type->to(); ASSERT_TRUE(ts_1->size->is()); // my_hdr_stack_2_t.hdr should be a Constant - auto *sf_2 = getStructField(program, "my_hdr_stack_2_t", "hdr"); + auto *sf_2 = getStructField(program, "my_hdr_stack_2_t"_cs, "hdr"_cs); ASSERT_TRUE(sf_2); auto *ts_2 = sf_2->type->to(); ASSERT_TRUE(ts_2->size->is()); @@ -121,13 +121,13 @@ TEST_F(P4CConstantFoldingValidation, filter) { ASSERT_TRUE(program); // my_hdr_stack_1_t.hdr should be a Constant - auto *sf_1 = getStructField(program, "my_hdr_stack_1_t", "hdr"); + auto *sf_1 = getStructField(program, "my_hdr_stack_1_t"_cs, "hdr"_cs); ASSERT_TRUE(sf_1); auto *ts_1 = sf_1->type->to(); EXPECT_TRUE(ts_1->size->is()); // my_hdr_stack_2_t.hdr should be a Constant - auto *sf_2 = getStructField(program, "my_hdr_stack_2_t", "hdr"); + auto *sf_2 = getStructField(program, "my_hdr_stack_2_t"_cs, "hdr"_cs); ASSERT_TRUE(sf_2); auto *ts_2 = sf_2->type->to(); EXPECT_TRUE(ts_2->size->is()); diff --git a/test/gtest/cstring.cpp b/test/gtest/cstring.cpp index 54c7d5dd1f..0484dbd1e0 100644 --- a/test/gtest/cstring.cpp +++ b/test/gtest/cstring.cpp @@ -20,6 +20,8 @@ limitations under the License. namespace Test { +using namespace P4::literals; + TEST(cstring, construct) { cstring c(nullptr); EXPECT_TRUE(c.isNullOrEmpty()); @@ -37,7 +39,7 @@ TEST(cstring, construct) { EXPECT_TRUE(c.isNullOrEmpty()); EXPECT_TRUE(c.isNull()); - c = ""; + c = ""_cs; EXPECT_TRUE(c.isNullOrEmpty()); EXPECT_FALSE(c.isNull()); @@ -52,32 +54,32 @@ TEST(cstring, construct) { } TEST(cstring, toupper) { - cstring c = "simple tEst"; - cstring c1 = ""; + cstring c = "simple tEst"_cs; + cstring c1 = ""_cs; EXPECT_EQ(c.toUpper(), "SIMPLE TEST"); EXPECT_EQ(c1.toUpper(), ""); } TEST(cstring, capitalize) { - cstring c = "simple tEst"; - cstring c1 = ""; + cstring c = "simple tEst"_cs; + cstring c1 = ""_cs; EXPECT_EQ(c.capitalize(), "Simple tEst"); EXPECT_EQ(c1.capitalize(), ""); } TEST(cstring, tolower) { - cstring c = "SIMple tEsT"; - cstring c1 = ""; + cstring c = "SIMple tEsT"_cs; + cstring c1 = ""_cs; EXPECT_EQ(c.toLower(), "simple test"); EXPECT_EQ(c1.toLower(), ""); } TEST(cstring, compare) { - cstring c = "simple"; - cstring c1 = ""; + cstring c = "simple"_cs; + cstring c1 = ""_cs; EXPECT_EQ(c, "simple"); EXPECT_EQ(c, c); @@ -110,7 +112,7 @@ TEST(cstring, compare) { } TEST(cstring, find) { - cstring c = "simplest"; + cstring c = "simplest"_cs; EXPECT_EQ(c.find('s'), c.c_str()); EXPECT_EQ(c.find('z'), nullptr); EXPECT_NE(c.findlast('s'), c.c_str()); @@ -119,7 +121,7 @@ TEST(cstring, find) { } TEST(cstring, substr) { - cstring c = "simplest"; + cstring c = "simplest"_cs; EXPECT_EQ(c.substr(3), "plest"); EXPECT_EQ(c.substr(3, 2), "pl"); EXPECT_EQ(c.substr(10), ""); @@ -128,16 +130,15 @@ TEST(cstring, substr) { } TEST(cstring, replace) { - cstring c = "Original"; - EXPECT_EQ(c.replace("in", "out"), "Origoutal"); - EXPECT_EQ(c.replace("", "out"), c); - EXPECT_EQ(c.replace("i", "o"), "Orogonal"); - EXPECT_EQ(c.replace("i", ""), "Orgnal"); + cstring c = "Original"_cs; + EXPECT_EQ(c.replace("in"_cs, "out"_cs), "Origoutal"); + EXPECT_EQ(c.replace(""_cs, "out"_cs), c); + EXPECT_EQ(c.replace("i"_cs, "o"_cs), "Orogonal"); + EXPECT_EQ(c.replace("i"_cs, ""_cs), "Orgnal"); } TEST(cstring, literalSuffix) { - using namespace P4::literals; - cstring c = "test"; + cstring c("test"); EXPECT_EQ(c, "test"_cs); EXPECT_TRUE((std::is_same_v)); } diff --git a/test/gtest/equiv_test.cpp b/test/gtest/equiv_test.cpp index 0d1b74c306..abcbafc51a 100644 --- a/test/gtest/equiv_test.cpp +++ b/test/gtest/equiv_test.cpp @@ -17,8 +17,8 @@ limitations under the License. #include #include "ir/ir.h" -#include "ir/visitor.h" -#include "lib/exceptions.h" + +using namespace P4::literals; TEST(IR, Equiv) { auto *t = IR::Type::Bits::get(16); @@ -60,14 +60,14 @@ TEST(IR, Equiv) { auto *pr1 = new IR::V1Program; auto *pr2 = pr1->clone(); - pr1->add("a", a1); - pr1->add("b", b); - pr1->add("call", call1); - pr2->add("a", a2); - pr2->add("b", b); - pr2->add("call", call2); + pr1->add("a"_cs, a1); + pr1->add("b"_cs, b); + pr1->add("call"_cs, call1); + pr2->add("a"_cs, a2); + pr2->add("b"_cs, b); + pr2->add("call"_cs, call2); EXPECT_TRUE(pr1->equiv(*pr2)); - pr1->add("lista", list1); - pr2->add("listb", list1); + pr1->add("lista"_cs, list1); + pr2->add("listb"_cs, list1); EXPECT_FALSE(pr1->equiv(*pr2)); } diff --git a/test/gtest/expr_uses_test.cpp b/test/gtest/expr_uses_test.cpp index 276ced83a5..ece56884c4 100644 --- a/test/gtest/expr_uses_test.cpp +++ b/test/gtest/expr_uses_test.cpp @@ -19,8 +19,8 @@ limitations under the License. #include #include "ir/ir.h" -#include "ir/visitor.h" -#include "lib/exceptions.h" + +using namespace P4::literals; TEST(expr_uses, expr_uses) { auto obj1 = new IR::PathExpression("obj1"); @@ -33,16 +33,16 @@ TEST(expr_uses, expr_uses) { auto sub = new IR::Sub(obj1_f11, obj2_f1); auto add2 = new IR::Add(obj1_f1, obj1_f11); - EXPECT_TRUE(exprUses(add, "obj1")); - EXPECT_TRUE(exprUses(add, "obj2")); - EXPECT_TRUE(exprUses(add, "obj1.f1")); - EXPECT_TRUE(exprUses(add, "obj1.f1[0]")); - EXPECT_FALSE(exprUses(add, "obj1.f11")); - EXPECT_FALSE(exprUses(add, "obj1.f11[1]")); - EXPECT_FALSE(exprUses(add, "obj2.f1")); - EXPECT_TRUE(exprUses(add, "obj2.f11")); - EXPECT_TRUE(exprUses(sub, "obj1")); - EXPECT_TRUE(exprUses(sub, "obj2")); - EXPECT_TRUE(exprUses(add2, "obj1.f1")); - EXPECT_TRUE(exprUses(add2, "obj1.f11")); + EXPECT_TRUE(exprUses(add, "obj1"_cs)); + EXPECT_TRUE(exprUses(add, "obj2"_cs)); + EXPECT_TRUE(exprUses(add, "obj1.f1"_cs)); + EXPECT_TRUE(exprUses(add, "obj1.f1[0]"_cs)); + EXPECT_FALSE(exprUses(add, "obj1.f11"_cs)); + EXPECT_FALSE(exprUses(add, "obj1.f11[1]"_cs)); + EXPECT_FALSE(exprUses(add, "obj2.f1"_cs)); + EXPECT_TRUE(exprUses(add, "obj2.f11"_cs)); + EXPECT_TRUE(exprUses(sub, "obj1"_cs)); + EXPECT_TRUE(exprUses(sub, "obj2"_cs)); + EXPECT_TRUE(exprUses(add2, "obj1.f1"_cs)); + EXPECT_TRUE(exprUses(add2, "obj1.f11"_cs)); } diff --git a/test/gtest/format_test.cpp b/test/gtest/format_test.cpp index 9208b3c106..6c32863c15 100644 --- a/test/gtest/format_test.cpp +++ b/test/gtest/format_test.cpp @@ -37,8 +37,8 @@ TEST(Util, Format) { int a, b, c; cstring toString() const { - return cstring("(") + Util::toString(this->a) + "," + Util::toString(this->b) + "," + - Util::toString(this->c) + ")"; + return "("_cs + Util::toString(this->a) + ","_cs + Util::toString(this->b) + ","_cs + + Util::toString(this->c) + ")"_cs; } }; @@ -46,8 +46,8 @@ TEST(Util, Format) { message = context.errorReporter().format_message("Nice=%1%", nf); EXPECT_EQ("Nice=(1,2,3)\n", message); - cstring x = "x"; - cstring y = "y"; + cstring x = "x"_cs; + cstring y = "y"_cs; message = context.errorReporter().format_message("%1% %2%", x, y); EXPECT_EQ("x y\n", message); diff --git a/test/gtest/indexed_vector.cpp b/test/gtest/indexed_vector.cpp index 191720a382..7417c57ed5 100644 --- a/test/gtest/indexed_vector.cpp +++ b/test/gtest/indexed_vector.cpp @@ -23,15 +23,15 @@ TEST(IndexedVector, basics) { EXPECT_EQ(vec.size(), 1u); EXPECT_EQ(vec[0]->name.name, "foo"); - vec.push_back(testItem("bar")); + vec.push_back(testItem("bar"_cs)); EXPECT_FALSE(vec.empty()); EXPECT_EQ(vec.size(), 2u); EXPECT_EQ(vec[1]->name.name, "bar"); - cstring check = "foo"; - for (auto *dec : vec) { + cstring check = "foo"_cs; + for (const auto *dec : vec) { EXPECT_EQ(dec->name.name, check); - check = "bar"; + check = "bar"_cs; } vec.pop_back(); @@ -39,7 +39,7 @@ TEST(IndexedVector, basics) { EXPECT_EQ(vec.size(), 1u); EXPECT_EQ(vec[0]->name.name, "foo"); - vec.removeByName("foo"); + vec.removeByName("foo"_cs); EXPECT_TRUE(vec.empty()); EXPECT_EQ(vec.size(), 0u); } @@ -64,7 +64,7 @@ TEST(IndexedVector, move_ctor) { TestVector vec2(std::move(vec)); EXPECT_TRUE(vec.empty()); EXPECT_TRUE(vec2.empty()); - vec2.push_back(testItem("foo")); + vec2.push_back(testItem("foo"_cs)); EXPECT_TRUE(vec.empty()); EXPECT_FALSE(vec2.empty()); @@ -75,21 +75,21 @@ TEST(IndexedVector, move_ctor) { } TEST(IndexedVector, ilist_ctor) { - TestVector vec{testItem("foo"), testItem("bar")}; + TestVector vec{testItem("foo"_cs), testItem("bar"_cs)}; EXPECT_EQ(vec.size(), 2u); EXPECT_EQ(vec[0]->name.name, "foo"); EXPECT_EQ(vec[1]->name.name, "bar"); } TEST(IndexedVector, save_vector_ctor) { - TestVector vec(safe_vector{testItem("foo"), testItem("bar")}); + TestVector vec(safe_vector{testItem("foo"_cs), testItem("bar"_cs)}); EXPECT_EQ(vec.size(), 2u); EXPECT_EQ(vec[0]->name.name, "foo"); EXPECT_EQ(vec[1]->name.name, "bar"); } TEST(IndexedVector, Vector_ctor) { - TestVector vec(Vector{testItem("foo"), testItem("bar")}); + TestVector vec(Vector{testItem("foo"_cs), testItem("bar"_cs)}); EXPECT_EQ(vec.size(), 2u); EXPECT_EQ(vec[0]->name.name, "foo"); EXPECT_EQ(vec[1]->name.name, "bar"); diff --git a/test/gtest/json_test.cpp b/test/gtest/json_test.cpp index 0d4a5629b6..0f9e80a9f7 100644 --- a/test/gtest/json_test.cpp +++ b/test/gtest/json_test.cpp @@ -65,9 +65,9 @@ TEST(Util, Json) { auto obj = new JsonObject(); EXPECT_EQ("{\n}", obj->toString()); - obj->emplace("x", "x"); + obj->emplace("x"_cs, "x"); EXPECT_EQ("{\n \"x\" : \"x\"\n}", obj->toString()); - obj->emplace("y", arr); + obj->emplace("y"_cs, arr); EXPECT_EQ("{\n \"x\" : \"x\",\n \"y\" : [\n 5,\n \"5\",\n [true]\n ]\n}", obj->toString()); } diff --git a/test/gtest/midend_pass.cpp b/test/gtest/midend_pass.cpp index 800e854da0..ef13f3c0c5 100644 --- a/test/gtest/midend_pass.cpp +++ b/test/gtest/midend_pass.cpp @@ -136,7 +136,7 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { [this, evaluator]() { toplevel = evaluator->getToplevelBlock(); }, new P4::MidEndLast()}); if (options.listMidendPasses) { - listPasses(*outStream, "\n"); + listPasses(*outStream, cstring::newline); *outStream << std::endl; return; } diff --git a/test/gtest/p4runtime.cpp b/test/gtest/p4runtime.cpp index 0d706500cb..e562f1e59a 100644 --- a/test/gtest/p4runtime.cpp +++ b/test/gtest/p4runtime.cpp @@ -46,6 +46,8 @@ limitations under the License. namespace p4v1 = ::p4::v1; namespace p4configv1 = ::p4::config::v1; +using namespace P4::literals; + namespace Test { namespace { @@ -63,12 +65,12 @@ using P4::ControlPlaneAPI::findP4RuntimeValueSet; using google::protobuf::util::MessageDifferencer; -const cstring defaultArch = "v1model"; +const cstring defaultArch = "v1model"_cs; class ParseAnnotations : public P4::ParseAnnotations { public: ParseAnnotations() - : P4::ParseAnnotations("FrontendTest", true, {PARSE("my_anno", StringLiteral)}) {} + : P4::ParseAnnotations("FrontendTest", true, {PARSE("my_anno"_cs, StringLiteral)}) {} }; struct AnnotationParsingPolicy : P4::FrontEndPolicy { @@ -199,7 +201,7 @@ TEST_F(P4Runtime, IdAssignment) { { // Check that 'igTable' ended up in the P4Info output. - const auto *igTable = findP4RuntimeTable(*test->p4Info, "ingress.igTable"); + const auto *igTable = findP4RuntimeTable(*test->p4Info, "ingress.igTable"_cs); ASSERT_TRUE(igTable != nullptr); // Check that the id indicates the correct resource type. @@ -215,8 +217,9 @@ TEST_F(P4Runtime, IdAssignment) { // Check that 'igTableWithName' ended up in the P4Info output under that // name, which is determined by its @name annotation, and *not* under // 'igTableWithoutName'. - EXPECT_TRUE(findP4RuntimeTable(*test->p4Info, "ingress.igTableWithoutName") == nullptr); - const auto *igTableWithName = findP4RuntimeTable(*test->p4Info, "ingress.igTableWithName"); + EXPECT_TRUE(findP4RuntimeTable(*test->p4Info, "ingress.igTableWithoutName"_cs) == nullptr); + const auto *igTableWithName = + findP4RuntimeTable(*test->p4Info, "ingress.igTableWithName"_cs); ASSERT_TRUE(igTableWithName != nullptr); // Check that the id of 'igTableWithName' was computed based on its @@ -229,7 +232,7 @@ TEST_F(P4Runtime, IdAssignment) { // Check that 'igTableWithId' ended up in the P4Info output, and that // its id matches the one set by its @id annotation, with the required // 8-bit type prefix (which is 0x2 for tables). - const auto *igTableWithId = findP4RuntimeTable(*test->p4Info, "ingress.igTableWithId"); + const auto *igTableWithId = findP4RuntimeTable(*test->p4Info, "ingress.igTableWithId"_cs); ASSERT_TRUE(igTableWithId != nullptr); auto expectedId = 1234U | (unsigned(P4Ids::TABLE) << 24); EXPECT_EQ(expectedId, igTableWithId->preamble().id()); @@ -238,7 +241,7 @@ TEST_F(P4Runtime, IdAssignment) { { // Same as above, but with the largest possible id (0xffffff). const auto *igTableWithLargestId = - findP4RuntimeTable(*test->p4Info, "ingress.igTableWithLargestId"); + findP4RuntimeTable(*test->p4Info, "ingress.igTableWithLargestId"_cs); ASSERT_TRUE(igTableWithLargestId != nullptr); auto expectedId = 0xffffffU | (static_cast(P4Ids::TABLE) << 24); EXPECT_EQ(expectedId, igTableWithLargestId->preamble().id()); @@ -248,7 +251,7 @@ TEST_F(P4Runtime, IdAssignment) { // Check that 'igTableWithPrefixedId' ended up in the P4Info output, and // that its id matches the one set by its @id annotation. const auto *igTableWithPrefixedId = - findP4RuntimeTable(*test->p4Info, "ingress.igTableWithPrefixedId"); + findP4RuntimeTable(*test->p4Info, "ingress.igTableWithPrefixedId"_cs); ASSERT_TRUE(igTableWithPrefixedId != nullptr); auto expectedId = 0x02000133U; EXPECT_EQ(expectedId, igTableWithPrefixedId->preamble().id()); @@ -258,10 +261,10 @@ TEST_F(P4Runtime, IdAssignment) { // Check that 'igTableWithNameAndId' ended up in the P4Info output under // that name, and that its id matches the one set by its @id annotation // - in other words, that @id takes precedence over @name. - EXPECT_TRUE(findP4RuntimeTable(*test->p4Info, "ingress.igTableWithoutNameAndId") == + EXPECT_TRUE(findP4RuntimeTable(*test->p4Info, "ingress.igTableWithoutNameAndId"_cs) == nullptr); const auto *igTableWithNameAndId = - findP4RuntimeTable(*test->p4Info, "ingress.igTableWithNameAndId"); + findP4RuntimeTable(*test->p4Info, "ingress.igTableWithNameAndId"_cs); ASSERT_TRUE(igTableWithNameAndId != nullptr); auto expectedId = 5678U | (static_cast(P4Ids::TABLE) << 24); EXPECT_EQ(expectedId, igTableWithNameAndId->preamble().id()); @@ -271,10 +274,10 @@ TEST_F(P4Runtime, IdAssignment) { // Check that the two tables with conflicting ids are both present, and // that they didn't end up with the same id in the P4Info output. const auto *conflictingTableA = - findP4RuntimeTable(*test->p4Info, "ingress.conflictingTableA"); + findP4RuntimeTable(*test->p4Info, "ingress.conflictingTableA"_cs); ASSERT_TRUE(conflictingTableA != nullptr); const p4::config::v1::Table *conflictingTableB = - findP4RuntimeTable(*test->p4Info, "ingress.conflictingTableB"); + findP4RuntimeTable(*test->p4Info, "ingress.conflictingTableB"_cs); ASSERT_TRUE(conflictingTableB != nullptr); EXPECT_TRUE(conflictingTableA->preamble().id() == 0x02000134 || conflictingTableB->preamble().id() == 0x02000134); @@ -372,7 +375,7 @@ TEST_F(P4Runtime, FieldIdAssignment) { { // Check the ids for igTable's match fields. - const auto *igTable = findP4RuntimeTable(*test->p4Info, "ingress.igTable"); + const auto *igTable = findP4RuntimeTable(*test->p4Info, "ingress.igTable"_cs); ASSERT_TRUE(igTable != nullptr); const auto &mf1 = igTable->match_fields(0); const auto &mf2 = igTable->match_fields(1); @@ -382,7 +385,7 @@ TEST_F(P4Runtime, FieldIdAssignment) { { // Check the ids for action a's parameters. - const auto *aAction = findP4RuntimeAction(*test->p4Info, "ingress.a"); + const auto *aAction = findP4RuntimeAction(*test->p4Info, "ingress.a"_cs); ASSERT_TRUE(aAction != nullptr); const auto &ap1 = aAction->params(0); const auto &ap2 = aAction->params(1); @@ -393,7 +396,7 @@ TEST_F(P4Runtime, FieldIdAssignment) { { // Check the ids for the packet-in header fields. const auto *packetInHeader = - findP4RuntimeControllerPacketMetadata(*test->p4Info, "packet_in"); + findP4RuntimeControllerPacketMetadata(*test->p4Info, "packet_in"_cs); ASSERT_TRUE(packetInHeader != nullptr); const auto &m1 = packetInHeader->metadata(0); const auto &m2 = packetInHeader->metadata(1); @@ -404,7 +407,7 @@ TEST_F(P4Runtime, FieldIdAssignment) { { // Check the ids for igTableNoAnno's match fields. Without @id // annotations, the ids should be assigned sequentially, starting at 1. - const auto *igTable = findP4RuntimeTable(*test->p4Info, "ingress.igTableNoAnno"); + const auto *igTable = findP4RuntimeTable(*test->p4Info, "ingress.igTableNoAnno"_cs); ASSERT_TRUE(igTable != nullptr); const auto &mf1 = igTable->match_fields(0); const auto &mf2 = igTable->match_fields(1); @@ -416,14 +419,14 @@ TEST_F(P4Runtime, FieldIdAssignment) { // Check the ids for igTableLargeId's match fields. The compiler should // be able to handle all unsigned 32-bit integers greater than 0, // including 0xffffffff. - const auto *igTable = findP4RuntimeTable(*test->p4Info, "ingress.igTableLargeId"); + const auto *igTable = findP4RuntimeTable(*test->p4Info, "ingress.igTableLargeId"_cs); ASSERT_TRUE(igTable != nullptr); const auto &mf1 = igTable->match_fields(0); EXPECT_EQ(0xffffffff, mf1.id()); } { - const auto *vset = findP4RuntimeValueSet(*test->p4Info, "parse.pvs"); + const auto *vset = findP4RuntimeValueSet(*test->p4Info, "parse.pvs"_cs); ASSERT_TRUE(vset != nullptr); const auto &mf1 = vset->match(0); const auto &mf2 = vset->match(1); @@ -485,27 +488,27 @@ TEST_F(P4Runtime, IdAssignmentCounters) { // checks that myDirectCounter1 with the right ID prefix { - const auto *myTable1 = findP4RuntimeTable(*test->p4Info, "myTable1"); + const auto *myTable1 = findP4RuntimeTable(*test->p4Info, "myTable1"_cs); ASSERT_TRUE(myTable1 != nullptr); const auto *myDirectCounter1 = - findP4RuntimeDirectCounter(*test->p4Info, "myDirectCounter1"); + findP4RuntimeDirectCounter(*test->p4Info, "myDirectCounter1"_cs); ASSERT_TRUE(myDirectCounter1 != nullptr); EXPECT_EQ(unsigned(P4Ids::DIRECT_COUNTER), myDirectCounter1->preamble().id() >> 24); EXPECT_EQ(myDirectCounter1->preamble().id(), myTable1->direct_resource_ids(0)); } // checks that myDirectCounter2 with the right ID prefix { - const auto *myTable2 = findP4RuntimeTable(*test->p4Info, "myTable2"); + const auto *myTable2 = findP4RuntimeTable(*test->p4Info, "myTable2"_cs); ASSERT_TRUE(myTable2 != nullptr); const auto *myDirectCounter2 = - findP4RuntimeDirectCounter(*test->p4Info, "myDirectCounter2"); + findP4RuntimeDirectCounter(*test->p4Info, "myDirectCounter2"_cs); ASSERT_TRUE(myDirectCounter2 != nullptr); EXPECT_EQ(unsigned(P4Ids::DIRECT_COUNTER), myDirectCounter2->preamble().id() >> 24); EXPECT_EQ(myDirectCounter2->preamble().id(), myTable2->direct_resource_ids(0)); } // checks that myCounter with the right ID prefix { - const auto *myCounter = findP4RuntimeCounter(*test->p4Info, "myCounter"); + const auto *myCounter = findP4RuntimeCounter(*test->p4Info, "myCounter"_cs); ASSERT_TRUE(myCounter != nullptr); EXPECT_EQ(unsigned(P4Ids::COUNTER), myCounter->preamble().id() >> 24); } @@ -633,7 +636,7 @@ TEST_F(P4Runtime, P416MatchFields) { ASSERT_TRUE(test); EXPECT_EQ(0u, ::diagnosticCount()); - const auto *igTable = findP4RuntimeTable(*test->p4Info, "ingress.igTable"); + const auto *igTable = findP4RuntimeTable(*test->p4Info, "ingress.igTable"_cs); ASSERT_TRUE(igTable != nullptr); EXPECT_EQ(39, igTable->match_fields_size()); @@ -746,7 +749,7 @@ TEST_F(P4Runtime, DISABLED_P414MatchFields) { ASSERT_TRUE(test); EXPECT_EQ(0U, ::diagnosticCount()); - const auto *igTable = findP4RuntimeTable(*test->p4Info, "igTable"); + const auto *igTable = findP4RuntimeTable(*test->p4Info, "igTable"_cs); ASSERT_TRUE(igTable != nullptr); EXPECT_EQ(18, igTable->match_fields_size()); @@ -825,7 +828,7 @@ TEST_F(P4Runtime, Digests) { // digest() where T is a header. { - const auto *digest = findP4RuntimeDigest(*test->p4Info, "Header"); + const auto *digest = findP4RuntimeDigest(*test->p4Info, "Header"_cs); ASSERT_TRUE(digest != nullptr); EXPECT_EQ(unsigned(P4Ids::DIGEST), digest->preamble().id() >> 24); ASSERT_TRUE(digest->type_spec().has_header()); @@ -835,7 +838,7 @@ TEST_F(P4Runtime, Digests) { // digest() where T is a struct. { - const auto *digest = findP4RuntimeDigest(*test->p4Info, "Metadata"); + const auto *digest = findP4RuntimeDigest(*test->p4Info, "Metadata"_cs); ASSERT_TRUE(digest != nullptr); EXPECT_EQ(unsigned(P4Ids::DIGEST), digest->preamble().id() >> 24); ASSERT_TRUE(digest->type_spec().has_struct_()); @@ -845,7 +848,7 @@ TEST_F(P4Runtime, Digests) { // digest() where T is a tuple. { - const auto *digest = findP4RuntimeDigest(*test->p4Info, "digest_0"); + const auto *digest = findP4RuntimeDigest(*test->p4Info, "digest_0"_cs); ASSERT_TRUE(digest != nullptr); EXPECT_EQ(unsigned(P4Ids::DIGEST), digest->preamble().id() >> 24); ASSERT_TRUE(digest->type_spec().has_tuple()); @@ -935,7 +938,7 @@ TEST_F(P4Runtime, PSADigests) { PSA_Switch(ip, PacketReplicationEngine(), ep, BufferingQueueingEngine()) main; )"), - CompilerOptions::FrontendVersion::P4_16, "psa"); + CompilerOptions::FrontendVersion::P4_16, "psa"_cs); ASSERT_TRUE(test); // 0 warnings @@ -947,7 +950,7 @@ TEST_F(P4Runtime, PSADigests) { // Digest where T is a header. { - const auto *digest = findP4RuntimeDigest(*test->p4Info, "MyIC.digest1"); + const auto *digest = findP4RuntimeDigest(*test->p4Info, "MyIC.digest1"_cs); ASSERT_TRUE(digest != nullptr); EXPECT_EQ(unsigned(P4Ids::DIGEST), digest->preamble().id() >> 24); ASSERT_TRUE(digest->type_spec().has_header()); @@ -957,7 +960,7 @@ TEST_F(P4Runtime, PSADigests) { // Digest where T is a struct. { - const auto *digest = findP4RuntimeDigest(*test->p4Info, "MyIC.digest2"); + const auto *digest = findP4RuntimeDigest(*test->p4Info, "MyIC.digest2"_cs); ASSERT_TRUE(digest != nullptr); EXPECT_EQ(unsigned(P4Ids::DIGEST), digest->preamble().id() >> 24); ASSERT_TRUE(digest->type_spec().has_struct_()); @@ -967,7 +970,7 @@ TEST_F(P4Runtime, PSADigests) { // Digest where T is a tuple. { - const auto *digest = findP4RuntimeDigest(*test->p4Info, "MyIC.digest3"); + const auto *digest = findP4RuntimeDigest(*test->p4Info, "MyIC.digest3"_cs); ASSERT_TRUE(digest != nullptr); EXPECT_EQ(unsigned(P4Ids::DIGEST), digest->preamble().id() >> 24); ASSERT_TRUE(digest->type_spec().has_tuple()); @@ -1034,13 +1037,13 @@ TEST_F(P4Runtime, StaticTableEntries) { ASSERT_EQ(6, updates.size()); { - const auto *table = findP4RuntimeTable(*test->p4Info, "ingress.t_exact_ternary"); + const auto *table = findP4RuntimeTable(*test->p4Info, "ingress.t_exact_ternary"_cs); ASSERT_TRUE(table != nullptr); EXPECT_TRUE(table->is_const_table()); unsigned int hfAId = 1; unsigned int hfBId = 2; unsigned int xId = 1; - const auto *action = findP4RuntimeAction(*test->p4Info, "ingress.a_with_control_params"); + const auto *action = findP4RuntimeAction(*test->p4Info, "ingress.a_with_control_params"_cs); ASSERT_TRUE(action != nullptr); int priority = 1000; @@ -1087,10 +1090,10 @@ TEST_F(P4Runtime, StaticTableEntries) { } { - const auto *table = findP4RuntimeTable(*test->p4Info, "ingress.t_exact_valid"); + const auto *table = findP4RuntimeTable(*test->p4Info, "ingress.t_exact_valid"_cs); ASSERT_TRUE(table != nullptr); EXPECT_TRUE(table->is_const_table()); - const auto *action = findP4RuntimeAction(*test->p4Info, "ingress.a_with_bool_param"); + const auto *action = findP4RuntimeAction(*test->p4Info, "ingress.a_with_bool_param"_cs); ASSERT_TRUE(action != nullptr); auto checkEntry = [&](const p4v1::Update &update, const std::string &exact_v, @@ -1158,10 +1161,10 @@ TEST_F(P4Runtime, IsConstTable) { ASSERT_TRUE(test); EXPECT_EQ(0U, ::diagnosticCount()); - const auto *tableConst = findP4RuntimeTable(*test->p4Info, "ingress.t_const"); + const auto *tableConst = findP4RuntimeTable(*test->p4Info, "ingress.t_const"_cs); ASSERT_TRUE(tableConst != nullptr); EXPECT_TRUE(tableConst->is_const_table()); - const auto *tableNonConst = findP4RuntimeTable(*test->p4Info, "ingress.t_non_const"); + const auto *tableNonConst = findP4RuntimeTable(*test->p4Info, "ingress.t_non_const"_cs); ASSERT_TRUE(tableNonConst != nullptr); EXPECT_FALSE(tableNonConst->is_const_table()); } @@ -1201,7 +1204,7 @@ TEST_F(P4Runtime, TableActionsAnnotations) { ASSERT_TRUE(test); EXPECT_EQ(0U, ::diagnosticCount()); - const auto *table = findP4RuntimeTable(*test->p4Info, "ingress.t"); + const auto *table = findP4RuntimeTable(*test->p4Info, "ingress.t"_cs); ASSERT_TRUE(table != nullptr); // finds action reference based on the action name @@ -1266,16 +1269,16 @@ TEST_F(P4Runtime, ValueSet) { ASSERT_TRUE(test); EXPECT_EQ(0U, ::diagnosticCount()); - const auto *vset = findP4RuntimeValueSet(*test->p4Info, "parse.pvs"); + const auto *vset = findP4RuntimeValueSet(*test->p4Info, "parse.pvs"_cs); ASSERT_TRUE(vset != nullptr); EXPECT_EQ(vset->preamble().id() >> 24, unsigned(P4Ids::VALUE_SET)); EXPECT_EQ(vset->size(), 16); ASSERT_EQ(vset->match_size(), 3); using MatchField = p4configv1::MatchField; - auto checkMatchField = [](const p4configv1::MatchField &mf, unsigned int id, cstring name, - const std::vector &annotations, int bitwidth, - std::optional matchType, + auto checkMatchField = [](const p4configv1::MatchField &mf, unsigned int id, + std::string_view name, const std::vector &annotations, + int bitwidth, std::optional matchType, std::optional otherMatchType) { EXPECT_EQ(mf.id(), id); EXPECT_EQ(mf.name(), name); @@ -1291,10 +1294,10 @@ TEST_F(P4Runtime, ValueSet) { EXPECT_EQ(mf.other_match_type(), *otherMatchType); } }; - checkMatchField(vset->match(0), 1, "f1", {"@my_anno(\"body\")"}, 8, MatchField::TERNARY, + checkMatchField(vset->match(0), 1, "f1", {"@my_anno(\"body\")"_cs}, 8, MatchField::TERNARY, std::nullopt); checkMatchField(vset->match(1), 2, "f2", {}, 8, MatchField::EXACT, std::nullopt); - checkMatchField(vset->match(2), 3, "f3", {}, 8, std::nullopt, cstring("custom")); + checkMatchField(vset->match(2), 3, "f3", {}, 8, std::nullopt, "custom"_cs); } TEST_F(P4Runtime, Register) { @@ -1328,7 +1331,7 @@ TEST_F(P4Runtime, Register) { EXPECT_EQ(0U, ::diagnosticCount()); { // type parameter is tuple - const auto *register_ = findP4RuntimeRegister(*test->p4Info, "ingress.my_register_1"); + const auto *register_ = findP4RuntimeRegister(*test->p4Info, "ingress.my_register_1"_cs); ASSERT_TRUE(register_ != nullptr); EXPECT_EQ(unsigned(P4Ids::REGISTER), register_->preamble().id() >> 24); const auto &annotations = register_->preamble().annotations(); @@ -1340,7 +1343,7 @@ TEST_F(P4Runtime, Register) { EXPECT_EQ(2, typeSpec.tuple().members_size()); } { // type parameter is header - const auto *register_ = findP4RuntimeRegister(*test->p4Info, "ingress.my_register_2"); + const auto *register_ = findP4RuntimeRegister(*test->p4Info, "ingress.my_register_2"_cs); ASSERT_TRUE(register_ != nullptr); EXPECT_EQ(unsigned(P4Ids::REGISTER), register_->preamble().id() >> 24); EXPECT_EQ(128, register_->size()); @@ -1392,7 +1395,7 @@ TEST_F(P4Runtime, Documentation) { EXPECT_EQ(0U, ::diagnosticCount()); { - const auto *table = findP4RuntimeTable(*test->p4Info, "ingress.t"); + const auto *table = findP4RuntimeTable(*test->p4Info, "ingress.t"_cs); ASSERT_TRUE(table != nullptr); const auto &tDocumentation = table->preamble().doc(); EXPECT_EQ(tDocumentation.brief(), ""); @@ -1408,7 +1411,7 @@ TEST_F(P4Runtime, Documentation) { } { - const auto *noop = findP4RuntimeAction(*test->p4Info, "ingress.noop"); + const auto *noop = findP4RuntimeAction(*test->p4Info, "ingress.noop"_cs); ASSERT_TRUE(noop != nullptr); const auto &aDocumentation = noop->preamble().doc(); EXPECT_EQ(aDocumentation.brief(), "This action does nothing duh!"); @@ -1416,7 +1419,7 @@ TEST_F(P4Runtime, Documentation) { } { - const auto *drop = findP4RuntimeAction(*test->p4Info, "ingress.drop"); + const auto *drop = findP4RuntimeAction(*test->p4Info, "ingress.drop"_cs); ASSERT_TRUE(drop != nullptr); EXPECT_FALSE(drop->preamble().has_doc()); } @@ -1652,7 +1655,7 @@ class P4RuntimeDataTypeSpec : public P4Runtime { PassManager passes( {new P4::ParseAnnotations("P4RuntimeDataTypeSpecTest", false, { - {"p4runtime_translation", + {"p4runtime_translation"_cs, &P4::ParseAnnotations::parseP4rtTranslationAnnotation}, }), new P4::ResolveReferences(&refMap), new P4::TypeInference(&refMap, &typeMap, false)}); @@ -1740,7 +1743,7 @@ TEST_F(P4RuntimeDataTypeSpec, Struct) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); const auto *typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -1766,7 +1769,7 @@ TEST_F(P4RuntimeDataTypeSpec, Header) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); const auto *typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -1792,7 +1795,7 @@ TEST_F(P4RuntimeDataTypeSpec, HeaderWithFlattening) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); const auto *typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -1821,7 +1824,7 @@ TEST_F(P4RuntimeDataTypeSpec, HeaderUnion) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); const auto *typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -1851,7 +1854,7 @@ TEST_F(P4RuntimeDataTypeSpec, HeaderStack) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); const auto *typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -1873,7 +1876,7 @@ TEST_F(P4RuntimeDataTypeSpec, HeaderUnionStack) { auto pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - auto type = findExternTypeParameterName(pgm, "my_extern_t"); + auto type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); auto typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -1895,7 +1898,7 @@ TEST_F(P4RuntimeDataTypeSpec, Enum) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); const auto *typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -1918,7 +1921,7 @@ TEST_F(P4RuntimeDataTypeSpec, SerEnum) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); const auto *typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -1943,7 +1946,7 @@ TEST_F(P4RuntimeDataTypeSpec, Error) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); const auto *typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -1965,7 +1968,7 @@ TEST_F(P4RuntimeDataTypeSpec, StructWithTypedef) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); const auto *typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -1975,7 +1978,7 @@ TEST_F(P4RuntimeDataTypeSpec, StructWithTypedef) { auto it = typeInfo.structs().find("my_struct"); ASSERT_TRUE(it != typeInfo.structs().end()); ASSERT_EQ(2, it->second.members_size()); - auto checkMember = [&](cstring name, int index) { + auto checkMember = [&](std::string_view name, int index) { EXPECT_EQ(name, it->second.members(index).name()); const auto &memberTypeSpec = it->second.members(index).type_spec(); ASSERT_TRUE(memberTypeSpec.has_bitstring()); @@ -1998,7 +2001,7 @@ TEST_F(P4RuntimeDataTypeSpec, NewType) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); const auto *typeSpec = P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); @@ -2009,7 +2012,7 @@ TEST_F(P4RuntimeDataTypeSpec, NewType) { ASSERT_TRUE(it != typeInfo.structs().end()); ASSERT_EQ(2, it->second.members_size()); - auto checkMember = [&](cstring memberName, int index, cstring newTypeName) { + auto checkMember = [&](std::string_view memberName, int index, std::string_view newTypeName) { EXPECT_EQ(memberName, it->second.members(index).name()); const auto &memberTypeSpec = it->second.members(index).type_spec(); ASSERT_TRUE(memberTypeSpec.has_new_type()); @@ -2073,7 +2076,7 @@ TEST_F(P4RuntimeDataTypeSpec, NewTypeIllegalTranslationAnnotations) { ASSERT_TRUE(pgm != nullptr); ASSERT_EQ(::errorCount(), 0U); // No syntax error. - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); EXPECT_EQ(1U, ::errorCount()); // But a type error. @@ -2098,7 +2101,7 @@ TEST_F(P4RuntimeDataTypeSpec, NewTypeValidTranslationAnnotations) { const auto *pgm = getProgram(program); ASSERT_TRUE(pgm != nullptr && ::errorCount() == 0); - const auto *type = findExternTypeParameterName(pgm, "my_extern_t"); + const auto *type = findExternTypeParameterName(pgm, "my_extern_t"_cs); ASSERT_TRUE(type != nullptr); P4::ControlPlaneAPI::TypeSpecConverter::convert(&refMap, &typeMap, type, &typeInfo); diff --git a/test/gtest/parser_unroll.cpp b/test/gtest/parser_unroll.cpp index d5c634818e..2c417572fe 100644 --- a/test/gtest/parser_unroll.cpp +++ b/test/gtest/parser_unroll.cpp @@ -66,7 +66,7 @@ const IR::P4Program *load_model(const char *curFile, CompilerOptions &options) { auto originalEnv = getenv("P4C_16_INCLUDE_PATH"); setenv("P4C_16_INCLUDE_PATH", includeDir.c_str(), 1); options.loopsUnrolling = true; - options.file = sourcePath; + options.file = cstring(sourcePath); options.file += "testdata/p4_16_samples/"; options.file += curFile; auto program = P4::parseP4File(options); diff --git a/test/gtest/path_test.cpp b/test/gtest/path_test.cpp index 1c887445e7..3c302db2e6 100644 --- a/test/gtest/path_test.cpp +++ b/test/gtest/path_test.cpp @@ -73,15 +73,15 @@ TEST(Util, PathName) { { PathName path = ""; EXPECT_TRUE(path.isNullOrEmpty()); - PathName grow = path.join("x"); + PathName grow = path.join("x"_cs); EXPECT_EQ("x", grow.toString()); EXPECT_FALSE(grow.isNullOrEmpty()); - grow = grow.join("y"); + grow = grow.join("y"_cs); EXPECT_EQ("x/y", grow.toString()); path = PathName("x/"); - grow = path.join("y"); + grow = path.join("y"_cs); EXPECT_EQ("x/y", grow.toString()); } } diff --git a/tools/ir-generator/generator.cpp b/tools/ir-generator/generator.cpp index d6fdb1f334..e2dc54c381 100644 --- a/tools/ir-generator/generator.cpp +++ b/tools/ir-generator/generator.cpp @@ -52,15 +52,15 @@ int main(int argc, char *argv[]) { usage(argv[0]); return 1; case 'o': - header = openFile(optarg, false); + header = openFile(cstring(optarg), false); if (header == nullptr) return 1; break; case 'i': - impl = openFile(optarg, false); + impl = openFile(cstring(optarg), false); if (impl == nullptr) return 1; break; case 't': - t = openFile(optarg, false); + t = openFile(cstring(optarg), false); if (t == nullptr) return 1; break; case 'P': diff --git a/tools/ir-generator/ir-generator-lex.l b/tools/ir-generator/ir-generator-lex.l index 7f5cc23a38..7643576018 100644 --- a/tools/ir-generator/ir-generator-lex.l +++ b/tools/ir-generator/ir-generator-lex.l @@ -50,19 +50,19 @@ static std::string comment_block; return EMITBLOCK; } .* { block_buffer += yytext; } -"#include".*[\n] { yylval.str = yytext; return INCLUDE; } +"#include".*[\n] { yylval.str = cstring(yytext); return INCLUDE; } "/*" { comment_block.clear(); comment_block += yytext; yy_push_state(COMMENT); } "*/" { yy_pop_state(); comment_block += yytext; - yylval.str = comment_block; + yylval.str = cstring(comment_block); return COMMENTBLOCK; } . { comment_block += yytext; } [\n] { comment_block += yytext; } -"//".* { yylval.str = yytext; return COMMENTBLOCK; } +"//".* { yylval.str = cstring(yytext); return COMMENTBLOCK; } "::" { return DBLCOL; } "abstract" { return ABSTRACT; } @@ -84,13 +84,13 @@ static std::string comment_block; "virtual" { return VIRTUAL; } "NullOK" { return NULLOK; } "#apply" { return APPLY; } -"#no"[a-zA-Z_]* { yylval.str = yytext+3; return NO; } -"#nooperator==" { yylval.str = yytext+3; return NO; } -"0" { yylval.str = yytext; return ZERO; } --?[0-9]+ { yylval.str = yytext; return INTEGER; } +"#no"[a-zA-Z_]* { yylval.str = cstring(yytext+3); return NO; } +"#nooperator==" { yylval.str = cstring(yytext+3); return NO; } +"0" { yylval.str = cstring(yytext); return ZERO; } +-?[0-9]+ { yylval.str = cstring(yytext); return INTEGER; } -[A-Za-z_][A-Za-z0-9_]* { yylval.str = yytext; return IDENTIFIER; } -\"(\\.|[^\\"])*\" { yylval.str = yytext; return STRING; } +[A-Za-z_][A-Za-z0-9_]* { yylval.str = cstring(yytext); return IDENTIFIER; } +\"(\\.|[^\\"])*\" { yylval.str = cstring(yytext); return STRING; } "{" { BEGIN(NORMAL); return *yytext; } "{" { block_buffer = yytext; @@ -104,7 +104,7 @@ static std::string comment_block; "}" { block_buffer += *yytext; if (--block_depth <= 0) { yy_pop_state(); - yylval.str = block_buffer; + yylval.str = cstring(block_buffer); yylloc = block_start + yylloc; return BLOCK; } } "{" { block_buffer += *yytext; ++block_depth; } diff --git a/tools/ir-generator/ir-generator.ypp b/tools/ir-generator/ir-generator.ypp index 4e62067948..eab98c240b 100644 --- a/tools/ir-generator/ir-generator.ypp +++ b/tools/ir-generator/ir-generator.ypp @@ -58,6 +58,7 @@ static IrNamespace *current_namespace = LookupScope().resolve(0); %union { YYSTYPE() {} int i; + // FIXME: decide if this is a good idea to store all tokens inside cstring cache cstring str; IrClass *irClass; IrElement *irElement; @@ -71,6 +72,7 @@ static IrNamespace *current_namespace = LookupScope().resolve(0); NodeKind kind; struct { bool impl; + // FIXME: decide if this is a good idea to store all code blocks inside cstring cache cstring block; } emit; } @@ -130,9 +132,10 @@ symbol_print(FILE* file, int type, YYSTYPE value) #include "ir-generator-lex.c" #pragma GCC diagnostic pop +// FIXME: should receive string_view static cstring canon_name(cstring name) { /* canonical method names for backwards compatibility */ - if (name == "visitchildren") return "visit_children"; + if (name == "visitchildren") return "visit_children"_cs; return name; } @@ -278,16 +281,16 @@ method methodName : IDENTIFIER - | OPERATOR '=' '=' { $$ = "operator=="; } - | OPERATOR '!' '=' { $$ = "operator!="; } - | OPERATOR '<' '=' { $$ = "operator<="; } - | OPERATOR '>' '=' { $$ = "operator>="; } - | OPERATOR '<' { $$ = "operator<"; } - | OPERATOR '<' '<' { $$ = "operator<<"; } - | OPERATOR '>' { $$ = "operator>"; } - | OPERATOR '>' '>' { $$ = "operator>>"; } - | OPERATOR '*' { $$ = "operator*"; } - | OPERATOR '-' '>' { $$ = "operator->"; } + | OPERATOR '=' '=' { $$ = "operator=="_cs; } + | OPERATOR '!' '=' { $$ = "operator!="_cs; } + | OPERATOR '<' '=' { $$ = "operator<="_cs; } + | OPERATOR '>' '=' { $$ = "operator>="_cs; } + | OPERATOR '<' { $$ = "operator<"_cs; } + | OPERATOR '<' '<' { $$ = "operator<<"_cs; } + | OPERATOR '>' { $$ = "operator>"_cs; } + | OPERATOR '>' '>' { $$ = "operator>>"_cs; } + | OPERATOR '*' { $$ = "operator*"_cs; } + | OPERATOR '-' '>' { $$ = "operator->"_cs; } ; optArgList : argList | ; @@ -311,10 +314,10 @@ optOverride yyerror("syntax error, expecting override or method body"); } body: BLOCK - | '=' ZERO ';' { $$ = "= 0;"; } - | '=' DEFAULT ';' { $$ = "= default;"; } - | '=' DELETE ';' { $$ = "= delete;"; } - | ';' { $$ = nullptr; } + | '=' ZERO ';' { $$ = "= 0;"_cs; } + | '=' DEFAULT ';' { $$ = "= default;"_cs; } + | '=' DELETE ';' { $$ = "= delete;"_cs; } + | ';' { $$ = {}; } ; irField @@ -338,10 +341,10 @@ modifier modifiers : { $$ = 0; } | modifiers modifier { $$ = $1 | $2; } -fieldName: IDENTIFIER | OPTIONAL { $$ = "optional"; } ; +fieldName: IDENTIFIER | OPTIONAL { $$ = "optional"_cs; } ; optInitializer - : /* empty */ { $$ = nullptr; } + : /* empty */ { $$ = {}; } | '=' expression { $$ = $2; } | '=' BLOCK { $$ = $2; } ; @@ -354,7 +357,7 @@ lookup_scope nonRefType : IDENTIFIER { $$ = new NamedType(@1, 0, $1); } | lookup_scope IDENTIFIER { $$ = new NamedType(@2, $1, $2); } - | lookup_scope OPTIONAL { $$ = new NamedType(@2, $1, "optional"); } + | lookup_scope OPTIONAL { $$ = new NamedType(@2, $1, "optional"_cs); } | nonRefType '<' type_args '>' { $$ = new TemplateInstantiation(@1+@4, $1, *$3); } | nonRefType '[' INTEGER ']' { $$ = new ArrayType(@1+@4, $1, atoi($3)); } ; diff --git a/tools/ir-generator/irclass.cpp b/tools/ir-generator/irclass.cpp index 191e840fa6..d3b8dd9027 100644 --- a/tools/ir-generator/irclass.cpp +++ b/tools/ir-generator/irclass.cpp @@ -21,40 +21,40 @@ limitations under the License. const char *IrClass::indent = " "; IrNamespace &IrNamespace::global() { - static IrNamespace irn(nullptr, nullptr); + static IrNamespace irn({}, {}); return irn; } -static const LookupScope utilScope(nullptr, "Util"); -static const NamedType srcInfoType(Util::SourceInfo(), &utilScope, "SourceInfo"); +static const LookupScope utilScope(nullptr, "Util"_cs); +static const NamedType srcInfoType(Util::SourceInfo(), &utilScope, "SourceInfo"_cs); IrField *IrField::srcInfoField() { - static IrField irf(Util::SourceInfo(), &srcInfoType, "srcInfo", nullptr, + static IrField irf(Util::SourceInfo(), &srcInfoType, "srcInfo"_cs, {}, IrField::Inline | IrField::Optional); return &irf; } IrClass *IrClass::nodeClass() { - static IrClass irc(NodeKind::Abstract, "Node", {IrField::srcInfoField()}); + static IrClass irc(NodeKind::Abstract, "Node"_cs, {IrField::srcInfoField()}); return &irc; } IrClass *IrClass::vectorClass() { - static IrClass irc(NodeKind::Template, "Vector"); + static IrClass irc(NodeKind::Template, "Vector"_cs); return &irc; } IrClass *IrClass::namemapClass() { - static IrClass irc(NodeKind::Template, "NameMap"); + static IrClass irc(NodeKind::Template, "NameMap"_cs); return &irc; } IrClass *IrClass::nodemapClass() { - static IrClass irc(NodeKind::Template, "NodeMap"); + static IrClass irc(NodeKind::Template, "NodeMap"_cs); return &irc; } IrClass *IrClass::ideclaration() { - static IrClass irc(NodeKind::Interface, "IDeclaration"); + static IrClass irc(NodeKind::Interface, "IDeclaration"_cs); return &irc; } IrClass *IrClass::indexedVectorClass() { - static IrClass irc(NodeKind::Template, "IndexedVector"); + static IrClass irc(NodeKind::Template, "IndexedVector"_cs); return &irc; } bool LineDirective::inhibit = false; @@ -134,6 +134,7 @@ void IrDefinitions::generate(std::ostream &t, std::ostream &out, std::ostream &i << std::endl << "namespace IR {\n" << "extern std::map unpacker_table;\n" + << "using namespace P4::literals;\n" << "}\n"; impl << "std::map IR::unpacker_table = {\n"; @@ -145,7 +146,7 @@ void IrDefinitions::generate(std::ostream &t, std::ostream &out, std::ostream &i first = false; else impl << ",\n"; - impl << "{\"" << cls->name << "\", NodeFactoryFn(&IR::"; + impl << "{\"" << cls->name << "\"_cs, NodeFactoryFn(&IR::"; if (cls->containedIn && cls->containedIn->name) impl << cls->containedIn->name << "::"; impl << cls->name << "::fromJSON)}"; } @@ -235,9 +236,9 @@ void IrDefinitions::generate(std::ostream &t, std::ostream &out, std::ostream &i << " Node = 2,\n"; unsigned nkId = 3; - auto *irNamespace = IrNamespace::get(nullptr, "IR"); + auto *irNamespace = IrNamespace::get(nullptr, "IR"_cs); for (auto *cls : *getClasses()) - t << " " << cls->qualified_name(irNamespace).replace("::", "_") << " = " << nkId++ + t << " " << cls->qualified_name(irNamespace).replace("::"_cs, "_"_cs) << " = " << nkId++ << ",\n"; // Add some specials: @@ -374,14 +375,14 @@ std::string IrClass::fullName() const { } cstring IrNamespace::qualified_name(const IrNamespace *in) const { - cstring rv = name ? name : "IR"; + cstring rv = name ? name : "IR"_cs; if (parent) { for (auto i = in; i; i = i->parent) { auto sym = i->lookupChild(name); if (sym && this != sym) break; if (parent == i) return rv; } - rv = parent->qualified_name(in) + "::" + rv; + rv = parent->qualified_name(in) + "::"_cs + rv; } return rv; } @@ -394,7 +395,7 @@ cstring IrClass::qualified_name(const IrNamespace *in) const { if (sym && this != sym) break; if (containedIn == i) return rv; } - rv = containedIn->qualified_name(in) + "::" + rv; + rv = containedIn->qualified_name(in) + "::"_cs + rv; } return rv; } @@ -439,10 +440,10 @@ void IrClass::generate_hdr(std::ostream &out) const { out << indent << "IRNODE" << (kind == NodeKind::Abstract ? "_ABSTRACT" : "") << "_SUBCLASS(" << name << ")" << std::endl; - auto *irNamespace = IrNamespace::get(nullptr, "IR"); + auto *irNamespace = IrNamespace::get(nullptr, "IR"_cs); if (kind != NodeKind::Nested) { out << indent << "DECLARE_TYPEINFO_WITH_TYPEID(" << name - << ", NodeKind::" << qualified_name(irNamespace).replace("::", "_"); + << ", NodeKind::" << qualified_name(irNamespace).replace("::"_cs, "_"_cs); if (!concreteParent) out << ", " << (kind != NodeKind::Interface ? "Node" : "INode"); for (const auto *p : parentClasses) out << ", " << p->qualified_name(containedIn); out << ");" << std::endl; @@ -494,9 +495,9 @@ int IrClass::generateConstructor(const ctor_args_t &arglist, const IrMethod *use if (arg.second == this) { body << end_parent; end_parent = ""; - } else if (parent) { + } else if (!parent.isNullOrEmpty()) { body << sep << parent; - parent = nullptr; + parent = ""_cs; sep = "("; end_parent = ")"; } @@ -651,10 +652,10 @@ void IrField::generate_impl(std::ostream &) const { void ConstFieldInitializer::generate_hdr(std::ostream &out) const { out << IrClass::indent; if (name == "precedence") - out << "int getPrecedence() const override { return "; + out << "int getPrecedence() const override { return " << initializer << "; }" << std::endl; else if (name == "stringOp") - out << "cstring getStringOp() const override { return "; + out << "cstring getStringOp() const override { return cstring(" << initializer << "); }" + << std::endl; else throw Util::CompilationError("Unexpected constant field %1%", this); - out << initializer << "; }" << std::endl; } diff --git a/tools/ir-generator/irclass.h b/tools/ir-generator/irclass.h index ddeb7ffc6d..214d04efa9 100644 --- a/tools/ir-generator/irclass.h +++ b/tools/ir-generator/irclass.h @@ -33,6 +33,8 @@ limitations under the License. class IrClass; class IrField; +using namespace P4::literals; + class IrNamespace { std::map classes; std::map children; @@ -190,7 +192,7 @@ class IrNo : public IrElement { IrNo(Util::SourceInfo info, cstring text) : IrElement(info), text(text) {} void generate_hdr(std::ostream &) const override {} void generate_impl(std::ostream &) const override {} - cstring toString() const override { return "#no" + text; } + cstring toString() const override { return "#no"_cs + text; } }; class IrApply : public IrElement { @@ -198,7 +200,7 @@ class IrApply : public IrElement { explicit IrApply(Util::SourceInfo info) : IrElement(info) {} void generate_hdr(std::ostream &out) const override; void generate_impl(std::ostream &out) const override; - cstring toString() const override { return "#apply"; } + cstring toString() const override { return "#apply"_cs; } }; enum class NodeKind { @@ -229,7 +231,7 @@ class CommentBlock : public IrElement { cstring toString() const override { // print only Doxygen comments if (body.startsWith("/**") || body.startsWith("///")) return body; - return ""; + return ""_cs; } void append(cstring comment) { body += "\n" + comment; } void generate_hdr(std::ostream &out) const override { out << toString() << std::endl; }; diff --git a/tools/ir-generator/methods.cpp b/tools/ir-generator/methods.cpp index 03a5c417c1..a75ad86b1a 100644 --- a/tools/ir-generator/methods.cpp +++ b/tools/ir-generator/methods.cpp @@ -34,7 +34,7 @@ enum flags { }; const ordered_map IrMethod::Generate = { - {"operator==", + {"operator=="_cs, {&NamedType::Bool(), {}, CONST + IN_IMPL + INCL_NESTED + OVERRIDE + CLASSREF, @@ -71,9 +71,9 @@ const ordered_map IrMethod::Generate = { buf << cl->indent << "}"; return buf.str(); }}}, - {"equiv", + {"equiv"_cs, {&NamedType::Bool(), - {new IrField(new ReferenceType(new NamedType(IrClass::nodeClass()), true), "a_")}, + {new IrField(new ReferenceType(new NamedType(IrClass::nodeClass()), true), "a_"_cs)}, EXTEND + CONST + IN_IMPL + OVERRIDE, [](IrClass *cl, Util::SourceInfo srcInfo, cstring body) -> cstring { std::stringstream buf; @@ -126,9 +126,9 @@ const ordered_map IrMethod::Generate = { buf << cl->indent << "}"; return buf.str(); }}}, - {"operator<<", + {"operator<<"_cs, {&ReferenceType::OstreamRef, - {new IrField(&ReferenceType::OstreamRef, "out")}, + {new IrField(&ReferenceType::OstreamRef, "out"_cs)}, EXTEND + IN_IMPL + NOT_DEFAULT + INCL_NESTED + CLASSREF + FRIEND, [](IrClass *cl, Util::SourceInfo srcInfo, cstring body) -> cstring { std::stringstream buf; @@ -137,9 +137,9 @@ const ordered_map IrMethod::Generate = { buf << LineDirective(true) << cl->indent << "return out; }"; return buf.str(); }}}, - {"visit_children", + {"visit_children"_cs, {&NamedType::Void(), - {new IrField(&ReferenceType::VisitorRef, "v")}, + {new IrField(&ReferenceType::VisitorRef, "v"_cs)}, IN_IMPL + OVERRIDE, [](IrClass *cl, Util::SourceInfo, cstring) -> cstring { bool needed = false; @@ -162,7 +162,7 @@ const ordered_map IrMethod::Generate = { buf << "}"; return needed ? buf.str() : cstring(); }}}, - {"validate", + {"validate"_cs, {&NamedType::Void(), {}, CONST + IN_IMPL + EXTEND + OVERRIDE, @@ -189,23 +189,23 @@ const ordered_map IrMethod::Generate = { buf << " }"; return needed ? buf.str() : cstring(); }}}, - {"node_type_name", + {"node_type_name"_cs, {&NamedType::Cstring(), {}, CONST + OVERRIDE, [](IrClass *cl, Util::SourceInfo, cstring) -> cstring { std::stringstream buf; - buf << "{ return \"" << cl->containedIn << cl->name << "\"; }"; + buf << "{ return \"" << cl->containedIn << cl->name << "\"_cs; }"; return buf.str(); }}}, - {"dbprint", + {"dbprint"_cs, {&NamedType::Void(), - {new IrField(&ReferenceType::OstreamRef, "out")}, + {new IrField(&ReferenceType::OstreamRef, "out"_cs)}, CONST + IN_IMPL + OVERRIDE + CONCRETE_ONLY, - [](IrClass *, Util::SourceInfo, cstring) -> cstring { return ""; }}}, - {"dump_fields", + [](IrClass *, Util::SourceInfo, cstring) -> cstring { return ""_cs; }}}, + {"dump_fields"_cs, {&NamedType::Void(), - {new IrField(&ReferenceType::OstreamRef, "out")}, + {new IrField(&ReferenceType::OstreamRef, "out"_cs)}, CONST + IN_IMPL + OVERRIDE, [](IrClass *cl, Util::SourceInfo, cstring) -> cstring { std::stringstream buf; @@ -227,9 +227,9 @@ const ordered_map IrMethod::Generate = { buf << "}"; return needed ? buf.str() : cstring(); }}}, - {"toJSON", + {"toJSON"_cs, {&NamedType::Void(), - {new IrField(new ReferenceType(&NamedType::JSONGenerator()), "json")}, + {new IrField(new ReferenceType(&NamedType::JSONGenerator()), "json"_cs)}, CONST + IN_IMPL + OVERRIDE + INCL_NESTED, [](IrClass *cl, Util::SourceInfo, cstring) -> cstring { std::stringstream buf; @@ -249,7 +249,7 @@ const ordered_map IrMethod::Generate = { }}}, {nullptr, {nullptr, - {new IrField(new ReferenceType(&NamedType::JSONLoader()), "json")}, + {new IrField(new ReferenceType(&NamedType::JSONLoader()), "json"_cs)}, IN_IMPL + CONSTRUCTOR + INCL_NESTED, [](IrClass *cl, Util::SourceInfo, cstring) -> cstring { std::stringstream buf; @@ -264,10 +264,10 @@ const ordered_map IrMethod::Generate = { buf << "}"; return buf.str(); }}}, - {"fromJSON", + {"fromJSON"_cs, {nullptr, { - new IrField(new ReferenceType(&NamedType::JSONLoader()), "json"), + new IrField(new ReferenceType(&NamedType::JSONLoader()), "json"_cs), }, FACTORY + IN_IMPL + CONCRETE_ONLY + INCL_NESTED, [](IrClass *cl, Util::SourceInfo, cstring) -> cstring { @@ -275,7 +275,7 @@ const ordered_map IrMethod::Generate = { buf << "{ return new " << cl->name << "(json); }"; return buf.str(); }}}, - {"toString", + {"toString"_cs, {&NamedType::Cstring(), {}, CONST + IN_IMPL + OVERRIDE + NOT_DEFAULT, @@ -314,19 +314,19 @@ void IrClass::generateMethods() { auto *m = new IrMethod(def.first, body); if (def.second.flags & FRIEND) m->isFriend = true; m->clss = this; - if (!(def.second.flags & CONSTRUCTOR) || !shouldSkip("method_constructor")) { + if (!(def.second.flags & CONSTRUCTOR) || !shouldSkip("method_constructor"_cs)) { elements.push_back(m); } } } } for (auto *parent = getParent(); parent; parent = parent->getParent()) { - auto eq_overload = new IrMethod("operator==", "{ return a == *this; }"); + auto eq_overload = new IrMethod("operator=="_cs, "{ return a == *this; }"_cs); eq_overload->clss = this; eq_overload->isOverride = true; eq_overload->rtype = &NamedType::Bool(); eq_overload->args.push_back( - new IrField(new ReferenceType(new NamedType(parent), true), "a")); + new IrField(new ReferenceType(new NamedType(parent), true), "a"_cs)); eq_overload->isConst = true; elements.push_back(eq_overload); } @@ -371,14 +371,14 @@ void IrClass::generateMethods() { } m->args = info.args; if (info.flags & CLASSREF) - m->args.push_back(new IrField(new ReferenceType(new NamedType(this), true), "a")); + m->args.push_back(new IrField(new ReferenceType(new NamedType(this), true), "a"_cs)); if (info.flags & IN_IMPL) m->inImpl = true; if (info.flags & CONST) m->isConst = true; if ((info.flags & OVERRIDE) && kind != NodeKind::Nested) m->isOverride = true; if (info.flags & FACTORY) m->isStatic = true; } if (ctor) elements.erase(find(elements, ctor)); - if (kind != NodeKind::Interface && !shouldSkip("constructor")) { + if (kind != NodeKind::Interface && !shouldSkip("constructor"_cs)) { ctor_args_t args; computeConstructorArguments(args); if (!user_defined_default_ctor || !args.empty()) { diff --git a/tools/ir-generator/type.cpp b/tools/ir-generator/type.cpp index 036ba9cee2..ec3fec9b38 100644 --- a/tools/ir-generator/type.cpp +++ b/tools/ir-generator/type.cpp @@ -71,63 +71,63 @@ const IrClass *NamedType::resolve(const IrNamespace *in) const { } NamedType &NamedType::Bool() { - static NamedType nt("bool"); + static NamedType nt("bool"_cs); return nt; } NamedType &NamedType::Int() { - static NamedType nt("int"); + static NamedType nt("int"_cs); return nt; } NamedType &NamedType::Void() { - static NamedType nt("void"); + static NamedType nt("void"_cs); return nt; } NamedType &NamedType::Cstring() { - static NamedType nt("cstring"); + static NamedType nt("cstring"_cs); return nt; } NamedType &NamedType::Ostream() { - static NamedType nt(new LookupScope("std"), "ostream"); + static NamedType nt(new LookupScope("std"_cs), "ostream"_cs); return nt; } NamedType &NamedType::Visitor() { - static NamedType nt("Visitor"); + static NamedType nt("Visitor"_cs); return nt; } NamedType &NamedType::Unordered_Set() { - static NamedType nt(new LookupScope("std"), "unordered_set"); + static NamedType nt(new LookupScope("std"_cs), "unordered_set"_cs); return nt; } NamedType &NamedType::JSONGenerator() { - static NamedType nt("JSONGenerator"); + static NamedType nt("JSONGenerator"_cs); return nt; } NamedType &NamedType::JSONLoader() { - static NamedType nt("JSONLoader"); + static NamedType nt("JSONLoader"_cs); return nt; } NamedType &NamedType::JSONObject() { - static NamedType nt("JSONObject"); + static NamedType nt("JSONObject"_cs); return nt; } NamedType &NamedType::SourceInfo() { - static NamedType nt(new LookupScope("Util"), "SourceInfo"); + static NamedType nt(new LookupScope("Util"_cs), "SourceInfo"_cs); return nt; } cstring NamedType::toString() const { if (resolved) return resolved->fullName(); - if (!lookup && name == "ID") return "IR::ID"; // hack -- ID is in namespace IR + if (!lookup && name == "ID") return "IR::ID"_cs; // hack -- ID is in namespace IR if (lookup) return lookup->toString() + name; if (foundin) return LookupScope(foundin).toString() + name; return name; @@ -137,7 +137,7 @@ cstring TemplateInstantiation::toString() const { std::string rv = base->toString().c_str(); rv += '<'; const char *sep = ""; - for (auto arg : args) { + for (const auto *arg : args) { rv += sep; if (arg->isResolved() && !base->isResolved()) rv += "const "; rv += arg->toString().c_str(); @@ -149,7 +149,7 @@ cstring TemplateInstantiation::toString() const { } cstring ReferenceType::toString() const { - cstring rv = base->toString(); + std::string rv = base->toString().c_str(); if (isConst) rv += " const"; rv += " &"; return rv; @@ -159,7 +159,7 @@ ReferenceType ReferenceType::OstreamRef(&NamedType::Ostream()), ReferenceType::V &NamedType::Visitor()); cstring PointerType::toString() const { - cstring rv = base->toString(); + std::string rv = base->toString().c_str(); if (isConst) rv += " const"; rv += " *"; return rv; @@ -168,7 +168,7 @@ cstring PointerType::toString() const { cstring ArrayType::declSuffix() const { char buf[16]; snprintf(buf, sizeof(buf), "[%d]", size); - return buf; + return cstring(buf); } const IrClass *FunctionType::resolve(const IrNamespace *ns) const { @@ -178,10 +178,10 @@ const IrClass *FunctionType::resolve(const IrNamespace *ns) const { } cstring FunctionType::toString() const { - cstring result = ret->toString(); + std::string result = ret->toString().c_str(); result += "("; const char *sep = ""; - for (auto arg : args) { + for (const auto *arg : args) { result += sep; if (arg->isResolved()) result += "const "; result += arg->toString().c_str(); diff --git a/tools/ir-generator/type.h b/tools/ir-generator/type.h index 7512040d73..58af07b429 100644 --- a/tools/ir-generator/type.h +++ b/tools/ir-generator/type.h @@ -25,6 +25,8 @@ limitations under the License. class IrClass; class IrNamespace; +using namespace P4::literals; + #define ALL_TYPES(M) \ M(NamedType) \ M(TemplateInstantiation) M(ReferenceType) M(PointerType) M(ArrayType) M(FunctionType) @@ -41,7 +43,7 @@ class Type : public Util::IHasSourceInfo { Util::SourceInfo getSourceInfo() const override { return srcInfo; } virtual const IrClass *resolve(const IrNamespace *) const = 0; virtual bool isResolved() const = 0; - virtual cstring declSuffix() const { return ""; } + virtual cstring declSuffix() const { return ""_cs; } virtual bool operator==(const Type &) const = 0; bool operator!=(const Type &t) const { return !operator==(t); } #define OP_EQUALS(T) \ @@ -62,8 +64,8 @@ struct LookupScope : public Util::IHasSourceInfo { Util::SourceInfo getSourceInfo() const override { return srcInfo; } cstring toString() const override { - if (global) return "IR::"; - return (in ? in->toString() + name : name) + "::"; + if (global) return "IR::"_cs; + return (in ? in->toString() + name : name) + "::"_cs; } IrNamespace *resolve(const IrNamespace *) const; bool operator==(const LookupScope &l) const {