From 274c5087f1224094665b86def416c0d1b1dfa4c9 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Fri, 28 Jun 2024 11:02:37 -0700 Subject: [PATCH] Remove ReferenceMap recalculation (almost) everywhere and switch to more fine-grained solutions (#4757) * Get rid of unused RefMap in ConstantTypeSubstitution Signed-off-by: Anton Korobeynikov * Convert ConstantFolding to DeclarationLookup Signed-off-by: Anton Korobeynikov * Convert SyntacticEquivalence to DeclarationLookup Signed-off-by: Anton Korobeynikov * Switch SubstituteParameters to DeclarationLookup. It stops populating refmap with cloned paths, but it seems it does not matter according to tests. In any way, the refmap was not fully correct after it. Signed-off-by: Anton Korobeynikov * Switch TypeInference to ResolutionContext Signed-off-by: Anton Korobeynikov * Remove refMap dependency from TypeChecking entirely. Clean up corresponding API around Signed-off-by: Anton Korobeynikov * Make DiscoverActionsInlining a ResolutionContext: no ReferenceMap is required Signed-off-by: Anton Korobeynikov * Switch action inliner not to use ReferenceMap Signed-off-by: Anton Korobeynikov * Update tests Signed-off-by: Anton Korobeynikov * Finally remove ReferenceMap recalculation from ActionsInliner Signed-off-by: Anton Korobeynikov * Switch to abseil time routines in time tracker Signed-off-by: Anton Korobeynikov * Ensure name generator is inherited for nested TypeInference calls Signed-off-by: Anton Korobeynikov * Ensure we always resolve to original declaration, not to the cloned one. This is particular important when mixing ResolveReferences with a Transform: various maps (e.g. TypeMap) are formulated in terms of original IR, not cloned. Signed-off-by: Anton Korobeynikov * Make DefaultArguments not to require ReferenceMap Signed-off-by: Anton Korobeynikov * Remove ReferenceMap from CheckCoreMethods Signed-off-by: Anton Korobeynikov * Move EntryPriorities to ResolutionContext Signed-off-by: Anton Korobeynikov * Remove RefMap from SpecializeGenericTypes Signed-off-by: Anton Korobeynikov * Remove RefMap from SpecializeGenericFunctions Signed-off-by: Anton Korobeynikov * Make StrengthReduce refmap-independent Signed-off-by: Anton Korobeynikov * Make DoConstantFolding a ResolutionContext, so it could resolve if necessary Signed-off-by: Anton Korobeynikov * Remove refmap from frontent ConstantFolding invocation Signed-off-by: Anton Korobeynikov * Make UniqueNames refmap-less Signed-off-by: Anton Korobeynikov * Remove RefMap from RemoveParserControlFlow Signed-off-by: Anton Korobeynikov * Switch TableApply to DeclarationLookup Signed-off-by: Anton Korobeynikov * Get rid of RefMap from DirectCalls Signed-off-by: Anton Korobeynikov * Switch Deprecated to ResolutionContext Signed-off-by: Anton Korobeynikov * DefaultValues does not use RefMap at all Signed-off-by: Anton Korobeynikov * No need for RefMap in BindVariables Signed-off-by: Anton Korobeynikov * Move StaticAsserts to ResolutionContext Signed-off-by: Anton Korobeynikov * Move StructInitializers to ResolutionContext Signed-off-by: Anton Korobeynikov * TableKeyNames does not need refMap Signed-off-by: Anton Korobeynikov * ResetHeaders do not need RefMap Signed-off-by: Anton Korobeynikov * Remove MoveDeclarations out of RefMap Signed-off-by: Anton Korobeynikov * No need for refMap in SimplifySwitch Signed-off-by: Anton Korobeynikov * Make UniqueParameters RefMap-less Signed-off-by: Anton Korobeynikov * Remove refMap from RemoveReturns / RemoveExits Signed-off-by: Anton Korobeynikov * Remove RefMap from DontcareArgs Signed-off-by: Anton Korobeynikov * Remove refmap from MoveConstructors Signed-off-by: Anton Korobeynikov * Move RemoveActionParameters out of RefMap Signed-off-by: Anton Korobeynikov * SetHeaders do not use RefMap Signed-off-by: Anton Korobeynikov * Remove RefMap from CheckConstants Signed-off-by: Anton Korobeynikov * Reduce RefMap proliferation in LocalizeActions Signed-off-by: Anton Korobeynikov * Remove much of refMap usage from functions inlining Signed-off-by: Anton Korobeynikov * Remove refMap from SimplifyControlFlow and around Signed-off-by: Anton Korobeynikov * Reduce refMap dependency inside Specialize Signed-off-by: Anton Korobeynikov * Reduce refMap usage around SimplifyExpressions Signed-off-by: Anton Korobeynikov * Silence a warning Signed-off-by: Anton Korobeynikov * Remove RefMap from DoSimplifyExpressions Signed-off-by: Anton Korobeynikov * Recognize nested TypeInference learners Signed-off-by: Anton Korobeynikov * Restore type checking instead of inference to emphasize read-only mode here Signed-off-by: Anton Korobeynikov * Restore old renaming scheme Signed-off-by: Anton Korobeynikov * Do not recalculate name generator contents on each inliner iteration Signed-off-by: Anton Korobeynikov * Reformat Signed-off-by: Anton Korobeynikov * Add fixme about declaration lookup caching Signed-off-by: Anton Korobeynikov * Make visitor context required for alias analysis routines Signed-off-by: Anton Korobeynikov * Get rid of PassManager for MoveConstructors Signed-off-by: Anton Korobeynikov * Get rid of EntryPriorities PassManager wrapper Signed-off-by: Anton Korobeynikov * Remove PassManager wrapper over InstantiateDirectCalls Signed-off-by: Anton Korobeynikov * Remove PassManager from Deprecated Signed-off-by: Anton Korobeynikov --------- Signed-off-by: Anton Korobeynikov --- backends/bmv2/psa_switch/midend.cpp | 22 +- backends/bmv2/psa_switch/psaSwitch.cpp | 10 +- backends/bmv2/simple_switch/midend.cpp | 21 +- backends/bmv2/simple_switch/simpleSwitch.cpp | 4 +- backends/dpdk/backend.cpp | 2 +- backends/dpdk/dpdkArch.cpp | 9 +- backends/dpdk/dpdkArch.h | 19 +- backends/dpdk/midend.cpp | 18 +- backends/ebpf/midend.cpp | 12 +- backends/p4test/midend.cpp | 14 +- backends/p4tools/common/compiler/midend.cpp | 10 +- backends/tc/midend.cpp | 18 +- backends/ubpf/midend.cpp | 67 +++--- frontends/common/constantFolding.cpp | 5 +- frontends/common/constantFolding.h | 32 ++- .../common/resolveReferences/referenceMap.h | 3 +- .../resolveReferences/resolveReferences.cpp | 62 +++-- .../resolveReferences/resolveReferences.h | 2 +- frontends/p4/actionsInlining.cpp | 37 +-- frontends/p4/actionsInlining.h | 21 +- frontends/p4/alias.h | 22 +- frontends/p4/checkConstants.cpp | 2 +- frontends/p4/checkConstants.h | 13 +- frontends/p4/checkCoreMethods.cpp | 2 +- frontends/p4/checkCoreMethods.h | 14 +- frontends/p4/commonInlining.h | 3 +- frontends/p4/defaultArguments.cpp | 6 +- frontends/p4/defaultArguments.h | 16 +- frontends/p4/defaultValues.h | 4 +- frontends/p4/deprecated.cpp | 14 +- frontends/p4/deprecated.h | 19 +- frontends/p4/directCalls.cpp | 10 +- frontends/p4/directCalls.h | 20 +- frontends/p4/dontcareArgs.cpp | 13 +- frontends/p4/dontcareArgs.h | 15 +- frontends/p4/entryPriorities.cpp | 6 +- frontends/p4/entryPriorities.h | 18 +- frontends/p4/evaluator/evaluator.cpp | 1 + .../p4/evaluator/substituteParameters.cpp | 8 +- frontends/p4/evaluator/substituteParameters.h | 12 +- frontends/p4/frontend.cpp | 94 ++++---- frontends/p4/functionsInlining.cpp | 28 ++- frontends/p4/functionsInlining.h | 25 +- frontends/p4/localizeActions.cpp | 26 ++- frontends/p4/localizeActions.h | 36 ++- frontends/p4/methodInstance.cpp | 14 +- frontends/p4/methodInstance.h | 27 ++- frontends/p4/moveConstructors.cpp | 189 +++++++-------- frontends/p4/moveConstructors.h | 37 ++- frontends/p4/moveDeclarations.cpp | 11 +- frontends/p4/moveDeclarations.h | 12 +- frontends/p4/optimizeExpressions.h | 2 +- frontends/p4/parserControlFlow.cpp | 12 +- frontends/p4/parserControlFlow.h | 28 +-- frontends/p4/removeParameters.cpp | 11 +- frontends/p4/removeParameters.h | 12 +- frontends/p4/removeReturns.cpp | 15 +- frontends/p4/removeReturns.h | 15 +- frontends/p4/resetHeaders.h | 4 +- frontends/p4/setHeaders.h | 10 +- frontends/p4/sideEffects.cpp | 88 ++++--- frontends/p4/sideEffects.h | 89 ++++---- frontends/p4/simplify.cpp | 7 +- frontends/p4/simplify.h | 14 +- frontends/p4/simplifySwitch.h | 4 +- frontends/p4/specialize.cpp | 68 +++--- frontends/p4/specialize.h | 38 ++-- frontends/p4/specializeGenericFunctions.cpp | 14 +- frontends/p4/specializeGenericFunctions.h | 20 +- frontends/p4/specializeGenericTypes.cpp | 14 +- frontends/p4/specializeGenericTypes.h | 13 +- frontends/p4/staticAssert.h | 24 +- frontends/p4/strengthReduction.h | 11 +- frontends/p4/structInitializers.cpp | 4 +- frontends/p4/structInitializers.h | 14 +- frontends/p4/tableApply.cpp | 11 +- frontends/p4/tableApply.h | 8 +- frontends/p4/tableKeyNames.h | 4 +- frontends/p4/typeChecking/bindVariables.h | 7 +- .../p4/typeChecking/syntacticEquivalence.h | 4 +- frontends/p4/typeChecking/typeChecker.cpp | 215 ++++++++++-------- frontends/p4/typeChecking/typeChecker.h | 25 +- frontends/p4/uniqueNames.cpp | 40 ++-- frontends/p4/uniqueNames.h | 35 +-- frontends/p4/uselessCasts.h | 4 +- ir/visitor.cpp | 37 ++- ir/visitor.h | 3 +- midend/copyStructures.cpp | 6 +- midend/eliminateTuples.h | 2 +- midend/expandEmit.cpp | 1 + midend/flattenUnions.h | 4 +- midend/global_copyprop.cpp | 2 + midend/has_side_effects.h | 2 +- midend/parserUnroll.h | 2 +- midend/removeExits.cpp | 25 +- midend/removeExits.h | 12 +- test/gtest/frontend_test.cpp | 8 +- test/gtest/midend_pass.cpp | 10 +- test/gtest/midend_test.cpp | 2 +- test/gtest/p4runtime.cpp | 2 +- 100 files changed, 1129 insertions(+), 978 deletions(-) diff --git a/backends/bmv2/psa_switch/midend.cpp b/backends/bmv2/psa_switch/midend.cpp index be044d82bb..8ae476dbf0 100644 --- a/backends/bmv2/psa_switch/midend.cpp +++ b/backends/bmv2/psa_switch/midend.cpp @@ -123,12 +123,12 @@ PsaSwitchMidEnd::PsaSwitchMidEnd(CompilerOptions &options, std::ostream *outStre &refMap, &typeMap, new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsMask())), new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::SimplifySelectCases(&refMap, &typeMap, true), // require constant keysets new P4::ExpandLookahead(&refMap, &typeMap), new P4::ExpandEmit(&refMap, &typeMap), new P4::SimplifyParsers(&refMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::EliminateTuples(&refMap, &typeMap), new P4::SimplifyComparisons(&refMap, &typeMap), new P4::CopyStructures(&refMap, &typeMap), @@ -142,13 +142,19 @@ PsaSwitchMidEnd::PsaSwitchMidEnd(CompilerOptions &options, std::ostream *outStre new P4::MoveDeclarations(), // more may have been introduced new P4::ConstantFolding(&refMap, &typeMap), new P4::LocalCopyPropagation(&refMap, &typeMap, nullptr, policy), - new PassRepeated({new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap)}), + new PassRepeated({ + new P4::ConstantFolding(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), + }), new P4::MoveDeclarations(), - 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::ValidateTableProperties({ + "psa_implementation"_cs, + "psa_direct_counter"_cs, + "psa_direct_meter"_cs, + "psa_idle_timeout"_cs, + "size"_cs, + }), + new P4::SimplifyControlFlow(&typeMap), new P4::CompileTimeOperations(), new P4::TableHit(&refMap, &typeMap), new P4::EliminateSwitch(&refMap, &typeMap), diff --git a/backends/bmv2/psa_switch/psaSwitch.cpp b/backends/bmv2/psa_switch/psaSwitch.cpp index 9f7d110395..7cd4454f7d 100644 --- a/backends/bmv2/psa_switch/psaSwitch.cpp +++ b/backends/bmv2/psa_switch/psaSwitch.cpp @@ -275,14 +275,16 @@ void PsaSwitchBackend::convert(const IR::ToplevelBlock *tlb) { new SkipControls(&structure.non_pipeline_controls)), new P4::MoveActionsToTables(refMap, typeMap), new P4::TypeChecking(refMap, typeMap), - new P4::SimplifyControlFlow(refMap, typeMap), + new P4::SimplifyControlFlow(typeMap), new LowerExpressions(typeMap), - new PassRepeated( - {new P4::ConstantFolding(refMap, typeMap), new P4::StrengthReduction(refMap, typeMap)}), + new PassRepeated({ + new P4::ConstantFolding(refMap, typeMap), + new P4::StrengthReduction(typeMap), + }), new P4::TypeChecking(refMap, typeMap), new P4::RemoveComplexExpressions(refMap, typeMap, new ProcessControls(&structure.pipeline_controls)), - new P4::SimplifyControlFlow(refMap, typeMap), + new P4::SimplifyControlFlow(typeMap), new P4::RemoveAllUnusedDeclarations(refMap, P4::RemoveUnusedPolicy()), // Converts the DAG into a TREE (at least for expressions) // This is important later for conversion to JSON. diff --git a/backends/bmv2/simple_switch/midend.cpp b/backends/bmv2/simple_switch/midend.cpp index 3b3035310b..78bb398574 100644 --- a/backends/bmv2/simple_switch/midend.cpp +++ b/backends/bmv2/simple_switch/midend.cpp @@ -92,12 +92,12 @@ SimpleSwitchMidEnd::SimpleSwitchMidEnd(CompilerOptions &options, std::ostream *o &refMap, &typeMap, new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsMask())), new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::SimplifySelectCases(&refMap, &typeMap, true), // require constant keysets new P4::ExpandLookahead(&refMap, &typeMap), new P4::ExpandEmit(&refMap, &typeMap), new P4::SimplifyParsers(&refMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::EliminateTuples(&refMap, &typeMap), new P4::SimplifyComparisons(&refMap, &typeMap), new P4::CopyStructures(&refMap, &typeMap), @@ -111,15 +111,22 @@ SimpleSwitchMidEnd::SimpleSwitchMidEnd(CompilerOptions &options, std::ostream *o new P4::MoveDeclarations(), // more may have been introduced new P4::ConstantFolding(&refMap, &typeMap), new P4::LocalCopyPropagation(&refMap, &typeMap), - new PassRepeated({new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap)}), + new PassRepeated({ + new P4::ConstantFolding(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), + }), new P4::SimplifyKey( &refMap, &typeMap, new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsMask())), new P4::MoveDeclarations(), - new P4::ValidateTableProperties({"implementation"_cs, "size"_cs, "counters"_cs, - "meters"_cs, "support_timeout"_cs}), - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::ValidateTableProperties({ + "implementation"_cs, + "size"_cs, + "counters"_cs, + "meters"_cs, + "support_timeout"_cs, + }), + new P4::SimplifyControlFlow(&typeMap), new P4::EliminateTypedef(&refMap, &typeMap), new P4::CompileTimeOperations(), new P4::TableHit(&refMap, &typeMap), diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index eb8abea291..6a4b4cc3b2 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -1175,13 +1175,13 @@ void SimpleSwitchBackend::convert(const IR::ToplevelBlock *tlb) { new SkipControls(&structure->non_pipeline_controls)), new P4::MoveActionsToTables(refMap, typeMap), new P4::TypeChecking(refMap, typeMap), - new P4::SimplifyControlFlow(refMap, typeMap), + new P4::SimplifyControlFlow(typeMap), new LowerExpressions(typeMap), new P4::ConstantFolding(refMap, typeMap, false), new P4::TypeChecking(refMap, typeMap), new RemoveComplexExpressions(refMap, typeMap, new ProcessControls(&structure->pipeline_controls)), - new P4::SimplifyControlFlow(refMap, typeMap), + new P4::SimplifyControlFlow(typeMap), new P4::RemoveAllUnusedDeclarations(refMap, P4::RemoveUnusedPolicy()), new P4::FlattenLogMsg(refMap, typeMap), // Converts the DAG into a TREE (at least for expressions) diff --git a/backends/dpdk/backend.cpp b/backends/dpdk/backend.cpp index 9d65a32980..7fdd13946e 100644 --- a/backends/dpdk/backend.cpp +++ b/backends/dpdk/backend.cpp @@ -93,7 +93,7 @@ void DpdkBackend::convert(const IR::ToplevelBlock *tlb) { new P4::TypeChecking(refMap, typeMap, true), new ConvertBinaryOperationTo2Params(refMap), new CollectProgramStructure(refMap, typeMap, &structure), - new CopyMatchKeysToSingleStruct(refMap, typeMap, &invokedInKey, &structure), + new CopyMatchKeysToSingleStruct(typeMap, &invokedInKey, &structure), new P4::ResolveReferences(refMap), new CollectLocalVariables(refMap, typeMap, &structure), new P4::ClearTypeMap(typeMap), diff --git a/backends/dpdk/dpdkArch.cpp b/backends/dpdk/dpdkArch.cpp index 3a155d6ca3..f414ecf0fc 100644 --- a/backends/dpdk/dpdkArch.cpp +++ b/backends/dpdk/dpdkArch.cpp @@ -1709,7 +1709,7 @@ const IR::Node *CopyMatchKeysToSingleStruct::postorder(IR::KeyElement *element) } if (isHeader || metaCopyNeeded) { - IR::ID keyNameId(refMap->newName(keyName.string_view())); + IR::ID keyNameId(nameGen.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. @@ -1724,11 +1724,12 @@ const IR::Node *CopyMatchKeysToSingleStruct::postorder(IR::KeyElement *element) } const IR::Node *CopyMatchKeysToSingleStruct::doStatement(const IR::Statement *statement, - const IR::Expression *expression) { + const IR::Expression *expression, + const Visitor::Context *ctxt) { LOG3("Visiting " << getOriginal()); - P4::HasTableApply hta(refMap, typeMap); + P4::HasTableApply hta(this, typeMap); hta.setCalledBy(this); - (void)expression->apply(hta); + (void)expression->apply(hta, ctxt); if (hta.table == nullptr) return statement; auto insertions = get(toInsert, hta.table); if (insertions == nullptr) return statement; diff --git a/backends/dpdk/dpdkArch.h b/backends/dpdk/dpdkArch.h index 8d4905915a..8a2ff90c34 100644 --- a/backends/dpdk/dpdkArch.h +++ b/backends/dpdk/dpdkArch.h @@ -831,17 +831,16 @@ class CopyMatchKeysToSingleStruct : public P4::KeySideEffect { bool metaCopyNeeded = false; public: - CopyMatchKeysToSingleStruct(P4::ReferenceMap *refMap, P4::TypeMap *typeMap, - std::set *invokedInKey, + CopyMatchKeysToSingleStruct(P4::TypeMap *typeMap, std::set *invokedInKey, DpdkProgramStructure *structure) - : P4::KeySideEffect(refMap, typeMap, invokedInKey), structure(structure) { + : P4::KeySideEffect(typeMap, invokedInKey), structure(structure) { setName("CopyMatchKeysToSingleStruct"); } const IR::Node *preorder(IR::Key *key) override; const IR::Node *postorder(IR::KeyElement *element) override; - const IR::Node *doStatement(const IR::Statement *statement, - const IR::Expression *expression) override; + const IR::Node *doStatement(const IR::Statement *statement, const IR::Expression *expression, + const Visitor::Context *ctxt) override; struct keyInfo *getKeyInfo(IR::Key *keys); cstring getTableKeyName(const IR::Expression *e); int getFieldSizeBits(const IR::Type *field_type); @@ -1184,7 +1183,7 @@ class EliminateHeaderCopy : public PassManager { EliminateHeaderCopy(P4::ReferenceMap *refMap, P4::TypeMap *typeMap) { passes.push_back(new P4::ClearTypeMap(typeMap)); passes.push_back(new P4::ResolveReferences(refMap)); - passes.push_back(new P4::TypeInference(refMap, typeMap, false)); + passes.push_back(new P4::TypeInference(typeMap, false)); passes.push_back(new P4::TypeChecking(refMap, typeMap, true)); passes.push_back(new ElimHeaderCopy(typeMap)); } @@ -1435,13 +1434,13 @@ class CollectLocalStructAndFlatten : public PassManager { CollectLocalStructAndFlatten(P4::ReferenceMap *refMap, P4::TypeMap *typeMap) { passes.push_back(new P4::ClearTypeMap(typeMap)); passes.push_back(new P4::ResolveReferences(refMap)); - passes.push_back(new P4::TypeInference(refMap, typeMap, false)); + passes.push_back(new P4::TypeInference(typeMap, false)); passes.push_back(new P4::TypeChecking(refMap, typeMap, true)); passes.push_back(new CollectStructLocalVariables(refMap, typeMap)); passes.push_back(new MoveCollectedStructLocalVariableToMetadata(typeMap)); passes.push_back(new P4::ClearTypeMap(typeMap)); passes.push_back(new P4::ResolveReferences(refMap)); - passes.push_back(new P4::TypeInference(refMap, typeMap, false)); + passes.push_back(new P4::TypeInference(typeMap, false)); passes.push_back(new P4::TypeChecking(refMap, typeMap, true)); passes.push_back(new P4::FlattenInterfaceStructs(refMap, typeMap)); } @@ -1464,7 +1463,7 @@ class CollectIPSecInfo : public Inspector { typeMap(typeMap), structure(structure) {} bool preorder(const IR::MethodCallStatement *mcs) override { - auto mi = P4::MethodInstance::resolve(mcs->methodCall, refMap, typeMap); + auto mi = P4::MethodInstance::resolve(mcs, refMap, typeMap); if (auto a = mi->to()) { if (a->originalExternType->getName().name == "ipsec_accelerator") { if (structure->isPSA()) { @@ -1542,7 +1541,7 @@ struct DpdkHandleIPSec : public PassManager { passes.push_back(new InsertReqDeclForIPSec(refMap, structure, is_ipsec_used, sa_id_width)); passes.push_back(new P4::ClearTypeMap(typeMap)); passes.push_back(new P4::ResolveReferences(refMap)); - passes.push_back(new P4::TypeInference(refMap, typeMap, false)); + passes.push_back(new P4::TypeInference(typeMap, false)); } }; diff --git a/backends/dpdk/midend.cpp b/backends/dpdk/midend.cpp index 39ff4cb4d2..a439e8c0dd 100644 --- a/backends/dpdk/midend.cpp +++ b/backends/dpdk/midend.cpp @@ -180,9 +180,9 @@ DpdkMidEnd::DpdkMidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::SimplifyKey( &refMap, &typeMap, new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsLikeLeftValue())), - new P4::RemoveExits(&refMap, &typeMap), + new P4::RemoveExits(&typeMap), new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::SimplifySelectCases(&refMap, &typeMap, true), // The lookahead implementation in DPDK target supports only a header instance as // an operand, we do not expand headers. @@ -192,7 +192,7 @@ DpdkMidEnd::DpdkMidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::ExpandEmit(&refMap, &typeMap), new P4::HandleNoMatch(&refMap), new P4::SimplifyParsers(&refMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::EliminateTuples(&refMap, &typeMap), new P4::SimplifyComparisons(&refMap, &typeMap), new P4::CopyStructures(&refMap, &typeMap, false /* errorOnMethodCall */), @@ -205,17 +205,19 @@ DpdkMidEnd::DpdkMidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::HSIndexSimplifier(&refMap, &typeMap), new P4::ParsersUnroll(true, &refMap, &typeMap), new P4::FlattenHeaderUnion(&refMap, &typeMap), - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), new P4::ReplaceSelectRange(&refMap, &typeMap), new P4::MoveDeclarations(), // more may have been introduced new P4::ConstantFolding(&refMap, &typeMap), new P4::LocalCopyPropagation(&refMap, &typeMap, nullptr, policy), - new PassRepeated({new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap)}), + new PassRepeated({ + new P4::ConstantFolding(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), + }), new P4::MoveDeclarations(), validateTableProperties(options.arch), - new P4::SimplifyControlFlow(&refMap, &typeMap), - new P4::SimplifySwitch(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), + new P4::SimplifySwitch(&typeMap), new P4::CompileTimeOperations(), new P4::TableHit(&refMap, &typeMap), new P4::RemoveLeftSlices(&refMap, &typeMap), diff --git a/backends/ebpf/midend.cpp b/backends/ebpf/midend.cpp index cef8eee8a8..8aed5a957c 100644 --- a/backends/ebpf/midend.cpp +++ b/backends/ebpf/midend.cpp @@ -84,18 +84,20 @@ const IR::ToplevelBlock *MidEnd::run(EbpfOptions &options, const IR::P4Program * new P4::RemoveMiss(&refMap, &typeMap), new P4::EliminateInvalidHeaders(&refMap, &typeMap), new P4::EliminateNewtype(&refMap, &typeMap), - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), new P4::SimplifyKey( &refMap, &typeMap, new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsLikeLeftValue())), - new P4::RemoveExits(&refMap, &typeMap), + new P4::RemoveExits(&typeMap), new P4::ConstantFolding(&refMap, &typeMap), new P4::SimplifySelectCases(&refMap, &typeMap, false), // accept non-constant keysets new P4::ExpandEmit(&refMap, &typeMap), new P4::HandleNoMatch(&refMap), new P4::SimplifyParsers(&refMap), - new PassRepeated({new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap)}), + new PassRepeated({ + new P4::ConstantFolding(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), + }), new P4::SimplifyComparisons(&refMap, &typeMap), new P4::EliminateTuples(&refMap, &typeMap), new P4::SimplifySelectList(&refMap, &typeMap), @@ -103,7 +105,7 @@ const IR::ToplevelBlock *MidEnd::run(EbpfOptions &options, const IR::P4Program * new P4::RemoveSelectBooleans(&refMap, &typeMap), new P4::SingleArgumentSelect(&refMap, &typeMap), new P4::ConstantFolding(&refMap, &typeMap), - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), new P4::TableHit(&refMap, &typeMap), new P4::RemoveLeftSlices(&refMap, &typeMap), new EBPF::Lower(&refMap, &typeMap), diff --git a/backends/p4test/midend.cpp b/backends/p4test/midend.cpp index 29ba7426c5..3281fd5d6b 100644 --- a/backends/p4test/midend.cpp +++ b/backends/p4test/midend.cpp @@ -93,19 +93,19 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::SimplifyKey( &refMap, &typeMap, new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsLikeLeftValue())), - new P4::RemoveExits(&refMap, &typeMap), + new P4::RemoveExits(&typeMap), new P4::ConstantFolding(&refMap, &typeMap), new P4::SimplifySelectCases(&refMap, &typeMap, false), // non-constant keysets new P4::ExpandLookahead(&refMap, &typeMap), new P4::ExpandEmit(&refMap, &typeMap), new P4::HandleNoMatch(&refMap), new P4::SimplifyParsers(&refMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::EliminateTuples(&refMap, &typeMap), new P4::SimplifyComparisons(&refMap, &typeMap), new P4::CopyStructures(&refMap, &typeMap, false), new P4::NestedStructs(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::SimplifySelectList(&refMap, &typeMap), new P4::RemoveSelectBooleans(&refMap, &typeMap), new P4::FlattenHeaders(&refMap, &typeMap), @@ -119,9 +119,9 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::LocalCopyPropagation(&refMap, &typeMap), new P4::ConstantFolding(&refMap, &typeMap), }), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::MoveDeclarations(), // more may have been introduced - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), new P4::CompileTimeOperations(), new P4::TableHit(&refMap, &typeMap), new P4::EliminateSwitch(&refMap, &typeMap), @@ -132,7 +132,7 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::UnrollLoops(refMap, defUse), new P4::LocalCopyPropagation(&refMap, &typeMap), new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), }), new P4::MoveDeclarations(), // more may have been introduced evaluator, @@ -166,7 +166,7 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { evaluator, [this, evaluator]() { toplevel = evaluator->getToplevelBlock(); }, new P4::FlattenHeaderUnion(&refMap, &typeMap, options.loopsUnrolling), - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), new P4::MidEndLast()}); if (options.listMidendPasses) { listPasses(*outStream, cstring::newline); diff --git a/backends/p4tools/common/compiler/midend.cpp b/backends/p4tools/common/compiler/midend.cpp index ba0e4be161..1b0fb7ca0f 100644 --- a/backends/p4tools/common/compiler/midend.cpp +++ b/backends/p4tools/common/compiler/midend.cpp @@ -103,14 +103,14 @@ void MidEnd::addDefaultPasses() { // Make sure that we have no TypeDef left in the program. new P4::EliminateTypedef(&refMap, &typeMap), // Remove in/inout/out action parameters. - new P4::RemoveActionParameters(&refMap, &typeMap), + new P4::RemoveActionParameters(&typeMap), // Sort call arguments according to the order of the function's parameters. new P4::OrderArguments(&refMap, &typeMap), new P4::TypeChecking(&refMap, &typeMap), mkConvertKeys(), mkConvertEnums(), new P4::ConstantFolding(&refMap, &typeMap), - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), // Eliminate extraneous cases in select statements. new P4::SimplifySelectCases(&refMap, &typeMap, false), // Expand lookahead assignments into sequences of field assignments. @@ -125,7 +125,7 @@ void MidEnd::addDefaultPasses() { new PassRepeated({ new P4::CopyStructures(&refMap, &typeMap, false, true, nullptr), }), - new P4::RemoveParserControlFlow(&refMap, &typeMap), + new P4::RemoveParserControlFlow(&typeMap), // Flatten nested list expressions. new P4::SimplifySelectList(&refMap, &typeMap), // Convert booleans in selects into bit<1>. @@ -147,7 +147,7 @@ void MidEnd::addDefaultPasses() { }), new P4::ConstantFolding(&refMap, &typeMap), new P4::MoveDeclarations(), - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), // Replace any slices in the left side of assignments and convert them to casts. new P4::RemoveLeftSlices(&refMap, &typeMap), // Remove loops from parsers by unrolling them as far as the stack indices allow. @@ -157,7 +157,7 @@ void MidEnd::addDefaultPasses() { // Convert tuples into structs. new P4::EliminateTuples(&refMap, &typeMap), new P4::ConstantFolding(&refMap, &typeMap), - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), // Simplify header stack assignments with runtime indices into conditional statements. new P4::HSIndexSimplifier(&refMap, &typeMap), // Convert Type_Varbits into a type that contains information about the assigned width. diff --git a/backends/tc/midend.cpp b/backends/tc/midend.cpp index d7d52001b4..a8b0ef567c 100644 --- a/backends/tc/midend.cpp +++ b/backends/tc/midend.cpp @@ -31,29 +31,33 @@ const IR::ToplevelBlock *MidEnd::run(TCOptions &options, const IR::P4Program *pr new P4::EliminateInvalidHeaders(&refMap, &typeMap), new P4::EliminateNewtype(&refMap, &typeMap), new P4::EliminateSerEnums(&refMap, &typeMap), - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), new P4::SimplifyKey( &refMap, &typeMap, new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsLikeLeftValue())), - new P4::RemoveExits(&refMap, &typeMap), + new P4::RemoveExits(&typeMap), new P4::ConstantFolding(&refMap, &typeMap), new P4::SimplifySelectCases(&refMap, &typeMap, false), // accept non-constant keysets new P4::ExpandEmit(&refMap, &typeMap), new P4::HandleNoMatch(&refMap), new P4::SimplifyParsers(&refMap), - new PassRepeated({new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap)}), + new PassRepeated({ + new P4::ConstantFolding(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), + }), new P4::SimplifyComparisons(&refMap, &typeMap), new P4::EliminateTuples(&refMap, &typeMap), new P4::SimplifySelectList(&refMap, &typeMap), new P4::MoveDeclarations(), // more may have been introduced new P4::LocalCopyPropagation(&refMap, &typeMap), - new PassRepeated({new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap)}), + new PassRepeated({ + new P4::ConstantFolding(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), + }), new P4::RemoveSelectBooleans(&refMap, &typeMap), new P4::SingleArgumentSelect(&refMap, &typeMap), new P4::ConstantFolding(&refMap, &typeMap), - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), new P4::TableHit(&refMap, &typeMap), new P4::RemoveLeftSlices(&refMap, &typeMap), new EBPF::Lower(&refMap, &typeMap), diff --git a/backends/ubpf/midend.cpp b/backends/ubpf/midend.cpp index be84d08f31..5515f8933c 100644 --- a/backends/ubpf/midend.cpp +++ b/backends/ubpf/midend.cpp @@ -74,32 +74,40 @@ const IR::ToplevelBlock *MidEnd::run(EbpfOptions &options, const IR::P4Program * PassManager midEnd; if (options.loadIRFromJson == false) { - midEnd.addPasses( - {new P4::ConvertEnums(&refMap, &typeMap, new EnumOn32Bits()), - new P4::RemoveMiss(&refMap, &typeMap), new P4::ClearTypeMap(&typeMap), - new P4::EliminateNewtype(&refMap, &typeMap), - new P4::EliminateInvalidHeaders(&refMap, &typeMap), - new P4::SimplifyControlFlow(&refMap, &typeMap), - new P4::SimplifyKey( - &refMap, &typeMap, - new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsLikeLeftValue())), - new P4::ConstantFolding(&refMap, &typeMap), - // accept non-constant keysets - new P4::SimplifySelectCases(&refMap, &typeMap, false), new P4::HandleNoMatch(&refMap), - new P4::SimplifyParsers(&refMap), - new PassRepeated({new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap)}), - new P4::SimplifyComparisons(&refMap, &typeMap), - new P4::CopyStructures(&refMap, &typeMap), - new P4::LocalCopyPropagation(&refMap, &typeMap), - new P4::SimplifySelectList(&refMap, &typeMap), - new P4::MoveDeclarations(), // more may have been introduced - new P4::RemoveSelectBooleans(&refMap, &typeMap), - new P4::SingleArgumentSelect(&refMap, &typeMap), - new P4::ConstantFolding(&refMap, &typeMap), - new P4::SimplifyControlFlow(&refMap, &typeMap), new P4::TableHit(&refMap, &typeMap), - new P4::RemoveLeftSlices(&refMap, &typeMap), new EBPF::Lower(&refMap, &typeMap), - evaluator, new P4::MidEndLast()}); + midEnd.addPasses({ + new P4::ConvertEnums(&refMap, &typeMap, new EnumOn32Bits()), + new P4::RemoveMiss(&refMap, &typeMap), + new P4::ClearTypeMap(&typeMap), + new P4::EliminateNewtype(&refMap, &typeMap), + new P4::EliminateInvalidHeaders(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), + new P4::SimplifyKey( + &refMap, &typeMap, + new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsLikeLeftValue())), + new P4::ConstantFolding(&refMap, &typeMap), + // accept non-constant keysets + new P4::SimplifySelectCases(&refMap, &typeMap, false), + new P4::HandleNoMatch(&refMap), + new P4::SimplifyParsers(&refMap), + new PassRepeated({ + new P4::ConstantFolding(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), + }), + new P4::SimplifyComparisons(&refMap, &typeMap), + new P4::CopyStructures(&refMap, &typeMap), + new P4::LocalCopyPropagation(&refMap, &typeMap), + new P4::SimplifySelectList(&refMap, &typeMap), + new P4::MoveDeclarations(), // more may have been introduced + new P4::RemoveSelectBooleans(&refMap, &typeMap), + new P4::SingleArgumentSelect(&refMap, &typeMap), + new P4::ConstantFolding(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), + new P4::TableHit(&refMap, &typeMap), + new P4::RemoveLeftSlices(&refMap, &typeMap), + new EBPF::Lower(&refMap, &typeMap), + evaluator, + new P4::MidEndLast(), + }); if (options.listMidendPasses) { midEnd.listPasses(*outStream, cstring::newline); *outStream << std::endl; @@ -109,8 +117,11 @@ const IR::ToplevelBlock *MidEnd::run(EbpfOptions &options, const IR::P4Program * midEnd.removePasses(options.passesToExcludeMidend); } } else { - midEnd.addPasses({new P4::ResolveReferences(&refMap), - new P4::TypeChecking(&refMap, &typeMap), evaluator}); + midEnd.addPasses({ + new P4::ResolveReferences(&refMap), + new P4::TypeChecking(&refMap, &typeMap), + evaluator, + }); } midEnd.setName("MidEnd"); midEnd.addDebugHooks(hooks); diff --git a/frontends/common/constantFolding.cpp b/frontends/common/constantFolding.cpp index 53ca77ac60..0d4c6da969 100644 --- a/frontends/common/constantFolding.cpp +++ b/frontends/common/constantFolding.cpp @@ -16,7 +16,8 @@ limitations under the License. #include "constantFolding.h" -#include "frontends/common/options.h" +#include "frontends/common/parser_options.h" +#include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/p4/enumInstance.h" #include "lib/big_int_util.h" #include "lib/log.h" @@ -240,7 +241,7 @@ const IR::Node *DoConstantFolding::preorder(IR::ArrayIndex *e) { namespace { // Returns true if the given expression is of the form "some_table.apply().action_run." -bool isActionRun(const IR::Expression *e, const ReferenceMap *refMap) { +bool isActionRun(const IR::Expression *e, const DeclarationLookup *refMap) { const auto *actionRunMem = e->to(); if (!actionRunMem) return false; if (actionRunMem->member.name != IR::Type_Table::action_run) return false; diff --git a/frontends/common/constantFolding.h b/frontends/common/constantFolding.h index 8a53623926..9d1f9a678f 100644 --- a/frontends/common/constantFolding.h +++ b/frontends/common/constantFolding.h @@ -17,9 +17,10 @@ limitations under the License. #ifndef COMMON_CONSTANTFOLDING_H_ #define COMMON_CONSTANTFOLDING_H_ +#include "frontends/common/resolveReferences/referenceMap.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "ir/ir.h" -#include "lib/big_int_util.h" namespace P4 { @@ -57,13 +58,13 @@ class ConstantFoldingPolicy { * `IR::Declaration_Constant` nodes are initialized with * compile-time known constants. */ -class DoConstantFolding : public Transform { +class DoConstantFolding : public Transform, public ResolutionContext { protected: ConstantFoldingPolicy *policy; /// Used to resolve IR nodes to declarations. /// If `nullptr`, then `const` values cannot be resolved. - const ReferenceMap *refMap; + const DeclarationLookup *refMap; /// Used to resolve nodes to their types. /// If `nullptr`, then type information is not available. @@ -113,7 +114,7 @@ class DoConstantFolding : public Transform { Result setContains(const IR::Expression *keySet, const IR::Expression *constant) const; public: - DoConstantFolding(const ReferenceMap *refMap, const TypeMap *typeMap, bool warnings = true, + DoConstantFolding(const DeclarationLookup *refMap, const TypeMap *typeMap, bool warnings = true, ConstantFoldingPolicy *policy = nullptr) : refMap(refMap), typeMap(typeMap), typesKnown(typeMap != nullptr), warnings(warnings) { if (policy) { @@ -126,6 +127,11 @@ class DoConstantFolding : public Transform { assignmentTarget = false; } + // If DeclarationLookup is not passed, then resolve by our own. + explicit DoConstantFolding(const TypeMap *typeMap, bool warnings = true, + ConstantFoldingPolicy *policy = nullptr) + : DoConstantFolding(this, typeMap, warnings, policy) {} + const IR::Node *postorder(IR::Declaration_Constant *d) override; const IR::Node *postorder(IR::PathExpression *e) override; const IR::Node *postorder(IR::Cmpl *e) override; @@ -189,6 +195,24 @@ class ConstantFolding : public PassManager { if (typeMap != nullptr) passes.push_back(new ClearTypeMap(typeMap)); setName("ConstantFolding"); } + + ConstantFolding(TypeMap *typeMap, ConstantFoldingPolicy *policy) + : ConstantFolding(typeMap, true, nullptr, policy) {} + + explicit ConstantFolding(ConstantFoldingPolicy *policy) + : ConstantFolding(nullptr, true, nullptr, policy) {} + + explicit ConstantFolding(TypeMap *typeMap, bool warnings = true, + TypeChecking *typeChecking = nullptr, + ConstantFoldingPolicy *policy = nullptr) { + if (typeMap != nullptr) { + if (!typeChecking) typeChecking = new TypeChecking(nullptr, typeMap); + passes.push_back(typeChecking); + } + passes.push_back(new DoConstantFolding(typeMap, warnings, policy)); + if (typeMap != nullptr) passes.push_back(new ClearTypeMap(typeMap)); + setName("ConstantFolding"); + } }; } // namespace P4 diff --git a/frontends/common/resolveReferences/referenceMap.h b/frontends/common/resolveReferences/referenceMap.h index 3c462d5c66..691475a722 100644 --- a/frontends/common/resolveReferences/referenceMap.h +++ b/frontends/common/resolveReferences/referenceMap.h @@ -29,6 +29,7 @@ namespace P4 { class NameGenerator { public: virtual cstring newName(std::string_view base) = 0; + virtual ~NameGenerator() = default; }; // replacement for ReferenceMap NameGenerator to make it easier to remove uses of refMap @@ -42,7 +43,7 @@ class MinimalNameGenerator : public NameGenerator, public Inspector { public: MinimalNameGenerator(); - void usedName(cstring name) { usedNames.insert({name, 0}); } + void usedName(cstring name) { usedNames.emplace(name, 0); } explicit MinimalNameGenerator(const IR::Node *root) : MinimalNameGenerator() { root->apply(*this); } diff --git a/frontends/common/resolveReferences/resolveReferences.cpp b/frontends/common/resolveReferences/resolveReferences.cpp index 937c7e9c12..c17f6606f6 100644 --- a/frontends/common/resolveReferences/resolveReferences.cpp +++ b/frontends/common/resolveReferences/resolveReferences.cpp @@ -48,7 +48,7 @@ std::unordered_multimap &ResolutionContext::m std::vector ResolutionContext::resolve(const IR::ID &name, P4::ResolutionType type) const { const Context *ctxt = nullptr; - while (auto scope = findContext(ctxt)) { + while (auto scope = findOrigCtxt(ctxt)) { auto rv = lookup(scope, name, type); if (!rv.empty()) return rv; } @@ -59,7 +59,7 @@ std::vector ResolutionContext::resolve(const IR::ID &n std::vector ResolutionContext::lookup(const IR::INamespace *current, const IR::ID &name, P4::ResolutionType type) const { - LOG2("Trying to resolve in " << current->toString()); + LOG2("Trying to resolve in " << dbp(current)); if (const auto *gen = current->to()) { // FIXME: implement range filtering without enumerator wrappers @@ -91,14 +91,14 @@ std::vector ResolutionContext::lookup(const IR::INames LOG3("\tPosition test:" << dsi << "<=" << nsi << "=" << before); if (type == ResolutionType::Type) { - if (auto *type_decl = findContext()) + if (auto *type_decl = findOrigCtxt()) if (type_decl->getNode() == d->getNode()) { ::error(ErrorType::ERR_UNSUPPORTED, "Self-referencing types not supported: '%1%' within '%2%'", name, d->getNode()); } } else if (type == ResolutionType::Any) { - if (auto *decl_ctxt = findContext()) + if (auto *decl_ctxt = findOrigCtxt()) if (decl_ctxt->getNode() == d->getNode()) before = false; } @@ -143,10 +143,8 @@ std::vector ResolutionContext::lookup(const IR::INames LOG3("\tPosition test:" << dsi << "<=" << nsi << "=" << before); if (type == ResolutionType::Any) - if (auto *ctxt = findContext()) { - if (ctxt->getNode() == decl->getNode()) { - before = false; - } + if (auto *ctxt = findOrigCtxt()) { + if (ctxt->getNode() == decl->getNode()) before = false; } if (!before) decl = nullptr; @@ -171,7 +169,7 @@ std::vector ResolutionContext::lookup(const IR::INames } std::vector ResolutionContext::lookupMatchKind(const IR::ID &name) const { - if (const auto *global = findContext()) { + if (const auto *global = findOrigCtxt()) { for (const auto *obj : global->objects) { if (const auto *match_kind = obj->to()) { auto rv = lookup(match_kind, name, ResolutionType::Any); @@ -185,21 +183,29 @@ std::vector ResolutionContext::lookupMatchKind(const I const IR::Vector *ResolutionContext::methodArguments(cstring name) const { const Context *ctxt = getChildContext(); while (ctxt) { - if (auto mc = ctxt->node->to()) { - if (auto mem = mc->method->to()) { + const auto *node = ctxt->node; + const IR::MethodCallExpression *mc = nullptr; + if (const auto *mcs = node->to()) + mc = mcs->methodCall; + else + mc = node->to(); + + if (mc) { + if (const auto *mem = mc->method->to()) { if (mem->member == name) return mc->arguments; } - if (auto path = mc->method->to()) { + if (const auto *path = mc->method->to()) { if (path->path->name == name) return mc->arguments; } break; } - if (auto decl = ctxt->node->to()) { + + if (const auto *decl = node->to()) { if (decl->name == name) return decl->arguments; - if (auto type = decl->type->to()) { + if (const auto *type = decl->type->to()) { if (type->path->name == name) return decl->arguments; } - if (auto ts = decl->type->to()) { + if (const auto *ts = decl->type->to()) { if (ts->baseType->path->name == name) return decl->arguments; } break; @@ -209,16 +215,24 @@ const IR::Vector *ResolutionContext::methodArguments(cstring name) else break; } + LOG4("No arguments found for calling " << name << " in " << ctxt->node); + return nullptr; } const IR::IDeclaration *ResolutionContext::resolveUnique(const IR::ID &name, P4::ResolutionType type, const IR::INamespace *ns) const { + LOG2("Resolving " << name << " " + << (type == ResolutionType::Type ? "as type" : "as identifier")); + auto decls = ns ? lookup(ns, name, type) : resolve(name, type); + LOG3("Lookup resulted in " << decls.size() << " declarations"); + // Check overloaded symbols. const IR::Vector *arguments; if (decls.size() > 1 && (arguments = methodArguments(name))) { + LOG4("Resolved arguments " << arguments << ". Performing additional overload check"); decls = Util::enumerate(decls) ->where([arguments](const IR::IDeclaration *d) { auto func = d->to(); @@ -232,7 +246,10 @@ const IR::IDeclaration *ResolutionContext::resolveUnique(const IR::ID &name, ::error(ErrorType::ERR_NOT_FOUND, "%1%: declaration not found", name); return nullptr; } - if (decls.size() == 1) return decls.front(); + if (decls.size() == 1) { + LOG2("Lookup result: " << dbp(decls.front())); + return decls.front(); + } ::error(ErrorType::ERR_DUPLICATE, "%1%: multiple matching declarations", name); for (const auto *a : decls) ::error(ErrorType::ERR_DUPLICATE, "Candidate: %1%", a); @@ -243,7 +260,7 @@ const IR::IDeclaration *ResolutionContext::getDeclaration(const IR::Path *path, bool notNull) const { const IR::IDeclaration *result = nullptr; const Context *ctxt = nullptr; - if (findContext(ctxt) && ctxt->child_index == 2) { + if (findOrigCtxt(ctxt) && ctxt->child_index == 2) { // looking up a matchType in a key, so need to do a special lookup auto decls = lookupMatchKind(path->name); if (decls.empty()) { @@ -259,7 +276,8 @@ const IR::IDeclaration *ResolutionContext::getDeclaration(const IR::Path *path, if (getParent() || getOriginal()->is()) rtype = ResolutionType::Type; const IR::INamespace *ns = nullptr; - if (path->absolute) ns = findContext(); + if (path->absolute) ns = findOrigCtxt(); + result = resolveUnique(path->name, rtype, ns); } if (notNull) BUG_CHECK(result != nullptr, "Cannot find declaration for %1%", path); @@ -268,8 +286,8 @@ const IR::IDeclaration *ResolutionContext::getDeclaration(const IR::Path *path, const IR::IDeclaration *ResolutionContext::getDeclaration(const IR::This *pointer, bool notNull) const { - auto result = findContext(); - if (findContext() == nullptr || result == nullptr) + auto result = findOrigCtxt(); + if (findOrigCtxt() == nullptr || result == nullptr) ::error(ErrorType::ERR_INVALID, "%1% can only be used in the definition of an abstract method", pointer); if (notNull) BUG_CHECK(result != nullptr, "Cannot find declaration for %1%", pointer); @@ -290,9 +308,9 @@ ResolveReferences::ResolveReferences(ReferenceMap *refMap, bool checkShadow) } const IR::IDeclaration *ResolutionContext::resolvePath(const IR::Path *path, bool isType) const { - LOG2("Resolving " << path << " " << (isType ? "as type" : "as identifier")); + LOG2("Resolving path " << path << " " << (isType ? "as type" : "as identifier")); const IR::INamespace *ctxt = nullptr; - if (path->absolute) ctxt = findContext(); + if (path->absolute) ctxt = findOrigCtxt(); ResolutionType k = isType ? ResolutionType::Type : ResolutionType::Any; return resolveUnique(path->name, k, ctxt); } diff --git a/frontends/common/resolveReferences/resolveReferences.h b/frontends/common/resolveReferences/resolveReferences.h index 55ece6e512..9d6ef4b1ae 100644 --- a/frontends/common/resolveReferences/resolveReferences.h +++ b/frontends/common/resolveReferences/resolveReferences.h @@ -64,7 +64,7 @@ class ResolutionContext : virtual public Visitor, public DeclarationLookup { // does not, so we will resolve names to things declared later only when translating // from P4_14 or Type_Vars or ParserStates, or after code transforms that may reorder // the code. - bool anyOrder; + bool anyOrder = false; ResolutionContext(); explicit ResolutionContext(bool ao) : anyOrder(ao) {} diff --git a/frontends/p4/actionsInlining.cpp b/frontends/p4/actionsInlining.cpp index d54f5e5983..f952e6129c 100644 --- a/frontends/p4/actionsInlining.cpp +++ b/frontends/p4/actionsInlining.cpp @@ -17,7 +17,6 @@ limitations under the License. #include "actionsInlining.h" #include "frontends/common/resolveReferences/resolveReferences.h" -#include "frontends/p4/callGraph.h" #include "frontends/p4/evaluator/substituteParameters.h" #include "frontends/p4/methodInstance.h" #include "frontends/p4/parameterSubstitution.h" @@ -25,7 +24,7 @@ limitations under the License. namespace P4 { void DiscoverActionsInlining::postorder(const IR::MethodCallStatement *mcs) { - auto mi = P4::MethodInstance::resolve(mcs, refMap, typeMap); + auto mi = P4::MethodInstance::resolve(mcs, this, typeMap); CHECK_NULL(mi); auto ac = mi->to(); if (ac == nullptr) return; @@ -45,11 +44,15 @@ void DiscoverActionsInlining::postorder(const IR::MethodCallStatement *mcs) { } Visitor::profile_t ActionsInliner::init_apply(const IR::Node *node) { - P4::ResolveReferences solver(refMap); - refMap->clear(); - node->apply(solver); + auto rv = Transform::init_apply(node); + LOG2("ActionsInliner " << toInline); - return Transform::init_apply(node); + if (!nameGen) { + // This would apply nameGen onto node + nameGen = std::make_unique(node); + } + + return rv; } const IR::Node *ActionsInliner::preorder(IR::P4Action *action) { @@ -84,13 +87,13 @@ const IR::Node *ActionsInliner::preorder(IR::MethodCallStatement *statement) { substitution.populate(callee->parameters, statement->methodCall->arguments); // evaluate in and inout parameters in order - for (auto param : callee->parameters->parameters) { - auto argument = substitution.lookup(param); - cstring newName = refMap->newName(param->name.name.string_view()); + for (const auto *param : callee->parameters->parameters) { + const auto *argument = substitution.lookup(param); + cstring newName = nameGen->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, - argument->expression); + const auto *vardecl = new IR::Declaration_Variable(newName, param->annotations, + param->type, argument->expression); body.push_back(vardecl); subst.add(param, new IR::Argument(argument->srcInfo, argument->name, new IR::PathExpression(newName))); @@ -105,16 +108,22 @@ const IR::Node *ActionsInliner::preorder(IR::MethodCallStatement *statement) { subst.add(param, argument); } else if (param->direction == IR::Direction::Out) { // uninitialized variable - auto vardecl = new IR::Declaration_Variable(newName, param->annotations, param->type); + const auto *vardecl = + new IR::Declaration_Variable(newName, param->annotations, param->type); subst.add(param, new IR::Argument(argument->srcInfo, argument->name, new IR::PathExpression(newName))); body.push_back(vardecl); } } - SubstituteParameters sp(refMap, &subst, &tvs); + // FIXME: SubstituteParameters is a ResolutionContext, but we are recreating + // it again and again killing lookup caches. We'd need to have instead some + // separate DeclarationLookup that would allow us to perform necessary + // lookups in the context of callee. We can probably pre-seed it first for + // all possible callees in replMap. + SubstituteParameters sp(nullptr, &subst, &tvs); sp.setCalledBy(this); - auto clone = callee->apply(sp); + auto clone = callee->apply(sp, getContext()); if (::errorCount() > 0) return statement; CHECK_NULL(clone); BUG_CHECK(clone->is(), "%1%: not an action", clone); diff --git a/frontends/p4/actionsInlining.h b/frontends/p4/actionsInlining.h index e66d3e699d..a4031589e9 100644 --- a/frontends/p4/actionsInlining.h +++ b/frontends/p4/actionsInlining.h @@ -18,6 +18,7 @@ limitations under the License. #define FRONTENDS_P4_ACTIONSINLINING_H_ #include "commonInlining.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "frontends/p4/unusedDeclarations.h" #include "ir/ir.h" @@ -28,16 +29,13 @@ typedef SimpleCallInfo ActionCallInfo; typedef SimpleInlineWorkList AInlineWorkList; typedef SimpleInlineList ActionsInlineList; -class DiscoverActionsInlining : public Inspector { +class DiscoverActionsInlining : public Inspector, public ResolutionContext { ActionsInlineList *toInline; // output - P4::ReferenceMap *refMap; // input P4::TypeMap *typeMap; // input public: - DiscoverActionsInlining(ActionsInlineList *toInline, P4::ReferenceMap *refMap, - P4::TypeMap *typeMap) - : toInline(toInline), refMap(refMap), typeMap(typeMap) { + DiscoverActionsInlining(ActionsInlineList *toInline, P4::TypeMap *typeMap) + : toInline(toInline), typeMap(typeMap) { CHECK_NULL(toInline); - CHECK_NULL(refMap); CHECK_NULL(typeMap); setName("DiscoverActionsInlining"); } @@ -47,11 +45,11 @@ class DiscoverActionsInlining : public Inspector { // General-purpose actions inliner. class ActionsInliner : public AbstractInliner { - P4::ReferenceMap *refMap; + std::unique_ptr nameGen; std::map *replMap; public: - explicit ActionsInliner(P4::ReferenceMap *refMap) : refMap(refMap), replMap(nullptr) {} + ActionsInliner() : replMap(nullptr) {} Visitor::profile_t init_apply(const IR::Node *node) override; const IR::Node *preorder(IR::P4Parser *cont) override { prune(); @@ -69,9 +67,10 @@ class InlineActions : public PassManager { public: InlineActions(ReferenceMap *refMap, TypeMap *typeMap, const RemoveUnusedPolicy &policy) { - passes.push_back(new TypeChecking(refMap, typeMap)); - passes.push_back(new DiscoverActionsInlining(&actionsToInline, refMap, typeMap)); - passes.push_back(new InlineActionsDriver(&actionsToInline, new ActionsInliner(refMap))); + passes.push_back(new TypeChecking(nullptr, typeMap)); + passes.push_back(new DiscoverActionsInlining(&actionsToInline, typeMap)); + passes.push_back(new InlineActionsDriver(&actionsToInline, new ActionsInliner())); + passes.push_back(new ResolveReferences(refMap)); passes.push_back(new RemoveAllUnusedDeclarations(refMap, policy)); setName("InlineActions"); } diff --git a/frontends/p4/alias.h b/frontends/p4/alias.h index 2bf72cd253..49007afee4 100644 --- a/frontends/p4/alias.h +++ b/frontends/p4/alias.h @@ -26,9 +26,7 @@ limitations under the License. * part of the *same statement*. */ -#include "frontends/common/resolveReferences/referenceMap.h" -#include "frontends/p4/methodInstance.h" -#include "frontends/p4/typeChecking/typeChecker.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "ir/ir.h" namespace P4 { @@ -115,12 +113,11 @@ class SetOfLocations : public IHasDbPrint { }; /// Computes the SetOfLocations read and written by an expression. -class ReadsWrites : public Inspector { - const ReferenceMap *refMap; +class ReadsWrites : public Inspector, public ResolutionContext { std::map rw; public: - explicit ReadsWrites(const ReferenceMap *refMap) : refMap(refMap) { setName("ReadsWrites"); } + ReadsWrites() { setName("ReadsWrites"); } void postorder(const IR::Operation_Binary *expression) override { auto left = ::get(rw, expression->left); @@ -131,7 +128,7 @@ class ReadsWrites : public Inspector { } void postorder(const IR::PathExpression *expression) override { - auto decl = refMap->getDeclaration(expression->path); + auto decl = getDeclaration(expression->path); auto path = new LocationPath(decl); auto locs = new SetOfLocations(path); rw.emplace(expression, locs); @@ -244,17 +241,18 @@ class ReadsWrites : public Inspector { rw.emplace(expression, new SetOfLocations()); } - const SetOfLocations *get(const IR::Expression *expression) { - expression->apply(*this); + const SetOfLocations *get(const IR::Expression *expression, const Visitor::Context *ctxt) { + expression->apply(*this, ctxt); auto result = ::get(rw, expression); CHECK_NULL(result); LOG3("SetOfLocations(" << expression << ")=" << result); return result; } - bool mayAlias(const IR::Expression *left, const IR::Expression *right) { - auto llocs = get(left); - auto rlocs = get(right); + bool mayAlias(const IR::Expression *left, const IR::Expression *right, + const Visitor::Context *ctxt) { + auto llocs = get(left, ctxt); + auto rlocs = get(right, ctxt); CHECK_NULL(llocs); CHECK_NULL(rlocs); LOG3("Checking overlap between " << llocs << " and " << rlocs); diff --git a/frontends/p4/checkConstants.cpp b/frontends/p4/checkConstants.cpp index 001344383d..3fa179f5c6 100644 --- a/frontends/p4/checkConstants.cpp +++ b/frontends/p4/checkConstants.cpp @@ -21,7 +21,7 @@ limitations under the License. namespace P4 { void DoCheckConstants::postorder(const IR::MethodCallExpression *expression) { - auto mi = MethodInstance::resolve(expression, refMap, typeMap); + auto mi = MethodInstance::resolve(expression, this, typeMap); if (auto bi = mi->to()) { if (bi->name == IR::Type_Stack::push_front || bi->name == IR::Type_Stack::pop_front) { BUG_CHECK(expression->arguments->size() == 1, "Expected 1 argument for %1%", diff --git a/frontends/p4/checkConstants.h b/frontends/p4/checkConstants.h index b19f2fbbde..0f905308e1 100644 --- a/frontends/p4/checkConstants.h +++ b/frontends/p4/checkConstants.h @@ -17,6 +17,7 @@ limitations under the License. #ifndef FRONTENDS_P4_CHECKCONSTANTS_H_ #define FRONTENDS_P4_CHECKCONSTANTS_H_ +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "ir/ir.h" @@ -25,13 +26,11 @@ namespace P4 { /// Makes sure that some methods that expect constant /// arguments have constant arguments (e.g., push_front). /// Checks that table sizes are constant integers. -class DoCheckConstants : public Inspector { - ReferenceMap *refMap; +class DoCheckConstants : public Inspector, public ResolutionContext { TypeMap *typeMap; public: - DoCheckConstants(ReferenceMap *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap) { - CHECK_NULL(refMap); + explicit DoCheckConstants(TypeMap *typeMap) : typeMap(typeMap) { CHECK_NULL(typeMap); setName("DoCheckConstants"); } @@ -43,9 +42,9 @@ class DoCheckConstants : public Inspector { class CheckConstants : public PassManager { public: - CheckConstants(ReferenceMap *refMap, TypeMap *typeMap) { - passes.push_back(new TypeChecking(refMap, typeMap)); - passes.push_back(new DoCheckConstants(refMap, typeMap)); + explicit CheckConstants(TypeMap *typeMap) { + passes.push_back(new TypeChecking(nullptr, typeMap)); + passes.push_back(new DoCheckConstants(typeMap)); setName("CheckConstants"); } }; diff --git a/frontends/p4/checkCoreMethods.cpp b/frontends/p4/checkCoreMethods.cpp index 23b3dd6007..92faf882f3 100644 --- a/frontends/p4/checkCoreMethods.cpp +++ b/frontends/p4/checkCoreMethods.cpp @@ -116,7 +116,7 @@ void DoCheckCoreMethods::checkCorelibMethods(const ExternMethod *em) const { } void DoCheckCoreMethods::postorder(const IR::MethodCallExpression *expression) { - auto mi = MethodInstance::resolve(expression, refMap, typeMap, nullptr, true); + auto mi = MethodInstance::resolve(expression, this, typeMap, nullptr, true); if (mi->is()) checkCorelibMethods(mi->to()); // Check that verify is only invoked from parsers. diff --git a/frontends/p4/checkCoreMethods.h b/frontends/p4/checkCoreMethods.h index 56db194106..ad3787a259 100644 --- a/frontends/p4/checkCoreMethods.h +++ b/frontends/p4/checkCoreMethods.h @@ -17,22 +17,22 @@ limitations under the License. #ifndef FRONTENDS_P4_CHECKCOREMETHODS_H_ #define FRONTENDS_P4_CHECKCOREMETHODS_H_ +#include "frontends/common/resolveReferences/resolveReferences.h" +#include "frontends/p4/methodInstance.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "ir/ir.h" namespace P4 { /// Check types for arguments of core.p4 methods -class DoCheckCoreMethods : public Inspector { - ReferenceMap *refMap; +class DoCheckCoreMethods : public Inspector, public ResolutionContext { TypeMap *typeMap; void checkEmitType(const IR::Expression *emit, const IR::Type *type) const; void checkCorelibMethods(const ExternMethod *em) const; public: - DoCheckCoreMethods(ReferenceMap *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap) { - CHECK_NULL(refMap); + explicit DoCheckCoreMethods(TypeMap *typeMap) : typeMap(typeMap) { CHECK_NULL(typeMap); setName("DoCheckCoreMethods"); } @@ -42,9 +42,9 @@ class DoCheckCoreMethods : public Inspector { class CheckCoreMethods : public PassManager { public: - CheckCoreMethods(ReferenceMap *refMap, TypeMap *typeMap) { - passes.push_back(new TypeChecking(refMap, typeMap)); - passes.push_back(new DoCheckCoreMethods(refMap, typeMap)); + explicit CheckCoreMethods(TypeMap *typeMap) { + passes.push_back(new TypeChecking(nullptr, typeMap)); + passes.push_back(new DoCheckCoreMethods(typeMap)); setName("CheckCoreMethods"); } }; diff --git a/frontends/p4/commonInlining.h b/frontends/p4/commonInlining.h index 69cb16f29b..bd33b5c49c 100644 --- a/frontends/p4/commonInlining.h +++ b/frontends/p4/commonInlining.h @@ -17,6 +17,7 @@ limitations under the License. #ifndef FRONTENDS_P4_COMMONINLINING_H_ #define FRONTENDS_P4_COMMONINLINING_H_ +#include "frontends/common/resolveReferences/resolveReferences.h" #define DEBUG_INLINER 0 #if DEBUG_INLINER @@ -136,7 +137,7 @@ class SimpleInlineList { // Base class for inliners template -class AbstractInliner : public Transform { +class AbstractInliner : public Transform, public ResolutionContext { protected: InlineList *list; InlineWorkList *toInline; diff --git a/frontends/p4/defaultArguments.cpp b/frontends/p4/defaultArguments.cpp index f64720b6b4..93ad1339bd 100644 --- a/frontends/p4/defaultArguments.cpp +++ b/frontends/p4/defaultArguments.cpp @@ -77,21 +77,21 @@ static const IR::Vector *fillDefaults(const TypeMap *typeMap, } const IR::Node *DoDefaultArguments::postorder(IR::MethodCallExpression *mce) { - auto mi = MethodInstance::resolve(mce, refMap, typeMap); + auto mi = MethodInstance::resolve(mce, this, typeMap); auto args = fillDefaults(typeMap, &mi->substitution, &mi->typeSubstitution); if (args != nullptr) mce->arguments = args; return mce; } const IR::Node *DoDefaultArguments::postorder(IR::ConstructorCallExpression *cce) { - auto cc = ConstructorCall::resolve(cce, refMap, typeMap); + auto cc = ConstructorCall::resolve(cce, this, typeMap); auto args = fillDefaults(typeMap, &cc->substitution, &cc->typeSubstitution); if (args != nullptr) cce->arguments = args; return cce; } const IR::Node *DoDefaultArguments::postorder(IR::Declaration_Instance *inst) { - auto ii = Instantiation::resolve(inst, refMap, typeMap); + auto ii = Instantiation::resolve(inst, this, typeMap); auto args = fillDefaults(typeMap, &ii->substitution, &ii->typeSubstitution); if (args != nullptr) inst->arguments = args; return inst; diff --git a/frontends/p4/defaultArguments.h b/frontends/p4/defaultArguments.h index 0fbc3ef475..d57a33111d 100644 --- a/frontends/p4/defaultArguments.h +++ b/frontends/p4/defaultArguments.h @@ -17,7 +17,6 @@ limitations under the License. #ifndef FRONTENDS_P4_DEFAULTARGUMENTS_H_ #define FRONTENDS_P4_DEFAULTARGUMENTS_H_ -#include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "frontends/p4/typeMap.h" @@ -34,14 +33,12 @@ namespace P4 { * to * f(a = 0); */ -class DoDefaultArguments : public Transform { - ReferenceMap *refMap; +class DoDefaultArguments : public Transform, public ResolutionContext { TypeMap *typeMap; public: - DoDefaultArguments(ReferenceMap *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap) { + explicit DoDefaultArguments(TypeMap *typeMap) : typeMap(typeMap) { setName("DoDefaultArguments"); - CHECK_NULL(refMap); CHECK_NULL(typeMap); } const IR::Node *postorder(IR::MethodCallExpression *expression) override; @@ -56,14 +53,13 @@ class DoDefaultArguments : public Transform { class DefaultArguments : public PassManager { public: - DefaultArguments(ReferenceMap *refMap, TypeMap *typeMap) { + explicit DefaultArguments(TypeMap *typeMap) { setName("DefaultArguments"); - passes.push_back(new TypeChecking(refMap, typeMap)); - passes.push_back(new DoDefaultArguments(refMap, typeMap)); + passes.push_back(new TypeChecking(nullptr, typeMap)); + passes.push_back(new DoDefaultArguments(typeMap)); passes.push_back(new ClearTypeMap(typeMap)); // this may insert casts into the new arguments - passes.push_back(new ResolveReferences(refMap)), - passes.push_back(new TypeInference(refMap, typeMap, false)); + passes.push_back(new TypeInference(typeMap, false)); } }; diff --git a/frontends/p4/defaultValues.h b/frontends/p4/defaultValues.h index 60decb2b3e..462d3b2aad 100644 --- a/frontends/p4/defaultValues.h +++ b/frontends/p4/defaultValues.h @@ -42,9 +42,9 @@ class DoDefaultValues final : public Transform { class DefaultValues : public PassManager { public: - DefaultValues(ReferenceMap *refMap, TypeMap *typeMap, TypeChecking *typeChecking = nullptr) { + explicit DefaultValues(TypeMap *typeMap, TypeChecking *typeChecking = nullptr) { if (typeMap != nullptr) { - if (!typeChecking) typeChecking = new TypeChecking(refMap, typeMap, true); + if (!typeChecking) typeChecking = new TypeChecking(nullptr, typeMap, true); passes.push_back(typeChecking); } passes.push_back(new DoDefaultValues(typeMap)); diff --git a/frontends/p4/deprecated.cpp b/frontends/p4/deprecated.cpp index 2f8636b2d8..3412c12ef9 100644 --- a/frontends/p4/deprecated.cpp +++ b/frontends/p4/deprecated.cpp @@ -16,11 +16,9 @@ limitations under the License. #include "deprecated.h" -#include "frontends/common/resolveReferences/resolveReferences.h" - namespace P4 { -void CheckDeprecated::warnIfDeprecated(const IR::IAnnotated *annotated, const IR::Node *errorNode) { +void Deprecated::warnIfDeprecated(const IR::IAnnotated *annotated, const IR::Node *errorNode) { if (annotated == nullptr) return; auto anno = annotated->getAnnotations()->getSingle(IR::Annotation::deprecatedAnnotation); if (anno == nullptr) return; @@ -33,16 +31,14 @@ void CheckDeprecated::warnIfDeprecated(const IR::IAnnotated *annotated, const IR annotated->getNode(), message); } -bool CheckDeprecated::preorder(const IR::PathExpression *expression) { - auto decl = refMap->getDeclaration(expression->path); - CHECK_NULL(decl); +bool Deprecated::preorder(const IR::PathExpression *expression) { + auto decl = getDeclaration(expression->path, true); warnIfDeprecated(decl->to(), expression); return false; } -bool CheckDeprecated::preorder(const IR::Type_Name *name) { - auto decl = refMap->getDeclaration(name->path); - CHECK_NULL(decl); +bool Deprecated::preorder(const IR::Type_Name *name) { + auto decl = getDeclaration(name->path, true); warnIfDeprecated(decl->to(), name); return false; } diff --git a/frontends/p4/deprecated.h b/frontends/p4/deprecated.h index 9c38fb2928..0a9afdefe1 100644 --- a/frontends/p4/deprecated.h +++ b/frontends/p4/deprecated.h @@ -19,7 +19,6 @@ limitations under the License. #include "frontends/common/resolveReferences/resolveReferences.h" #include "ir/ir.h" -#include "ir/pass_manager.h" namespace P4 { @@ -27,14 +26,9 @@ namespace P4 { * Checks for the use of symbols that are marked as @deprecated and * gives warnings. */ -class CheckDeprecated : public Inspector { - const ReferenceMap *refMap; - +class Deprecated : public Inspector, public ResolutionContext { public: - explicit CheckDeprecated(const ReferenceMap *refMap) : refMap(refMap) { - CHECK_NULL(refMap); - setName("CheckDeprecated"); - } + Deprecated() { setName("Deprecated"); } void warnIfDeprecated(const IR::IAnnotated *declaration, const IR::Node *errorNode); @@ -42,15 +36,6 @@ class CheckDeprecated : public Inspector { bool preorder(const IR::Type_Name *name) override; }; -class Deprecated : public PassManager { - public: - explicit Deprecated(ReferenceMap *refMap) { - passes.push_back(new ResolveReferences(refMap)); - passes.push_back(new CheckDeprecated(refMap)); - setName("Deprecated"); - } -}; - } // namespace P4 #endif /* FRONTENDS_P4_DEPRECATED_H_ */ diff --git a/frontends/p4/directCalls.cpp b/frontends/p4/directCalls.cpp index 126a6f2a58..ecb4bb8eff 100644 --- a/frontends/p4/directCalls.cpp +++ b/frontends/p4/directCalls.cpp @@ -2,19 +2,19 @@ namespace P4 { -const IR::Node *DoInstantiateCalls::postorder(IR::P4Parser *parser) { +const IR::Node *InstantiateDirectCalls::postorder(IR::P4Parser *parser) { parser->parserLocals.append(insert); insert.clear(); return parser; } -const IR::Node *DoInstantiateCalls::postorder(IR::P4Control *control) { +const IR::Node *InstantiateDirectCalls::postorder(IR::P4Control *control) { control->controlLocals.append(insert); insert.clear(); return control; } -const IR::Node *DoInstantiateCalls::postorder(IR::MethodCallExpression *expression) { +const IR::Node *InstantiateDirectCalls::postorder(IR::MethodCallExpression *expression) { // Identify type.apply(...) methods auto mem = expression->method->to(); if (mem == nullptr) return expression; @@ -28,10 +28,10 @@ const IR::Node *DoInstantiateCalls::postorder(IR::MethodCallExpression *expressi tname = tn->typeName->to(); } CHECK_NULL(tname); - auto ref = refMap->getDeclaration(tname->path, true); + auto ref = getDeclaration(tname->path, true); if (!ref->is() && !ref->is()) return expression; - auto name = refMap->newName(tname->path->name + "_inst"); + auto name = nameGen.newName(tname->path->name + "_inst"); LOG3("Inserting instance " << name); auto annos = new IR::Annotations(); annos->add(new IR::Annotation(IR::Annotation::nameAnnotation, tname->path->toString())); diff --git a/frontends/p4/directCalls.h b/frontends/p4/directCalls.h index cb6eca990b..5b90b517b8 100644 --- a/frontends/p4/directCalls.h +++ b/frontends/p4/directCalls.h @@ -35,27 +35,21 @@ is replaced with control c() { apply {} } control d() { @name("c") c() c_inst; { c_inst.apply(); }} */ -class DoInstantiateCalls : public Transform { - ReferenceMap *refMap; +class InstantiateDirectCalls : public Transform, public ResolutionContext { + MinimalNameGenerator nameGen; // used to generate new names IR::IndexedVector insert; public: - explicit DoInstantiateCalls(ReferenceMap *refMap) : refMap(refMap) { - CHECK_NULL(refMap); - setName("DoInstantiateCalls"); - } + InstantiateDirectCalls() { setName("InstantiateDirectCalls"); } const IR::Node *postorder(IR::P4Parser *parser) override; const IR::Node *postorder(IR::P4Control *control) override; const IR::Node *postorder(IR::MethodCallExpression *expression) override; -}; -class InstantiateDirectCalls : public PassManager { - public: - explicit InstantiateDirectCalls(ReferenceMap *refMap) { - passes.push_back(new ResolveReferences(refMap)); - passes.push_back(new DoInstantiateCalls(refMap)); - setName("InstantiateDirectCalls"); + profile_t init_apply(const IR::Node *node) override { + auto rv = Transform::init_apply(node); + node->apply(nameGen); + return rv; } }; diff --git a/frontends/p4/dontcareArgs.cpp b/frontends/p4/dontcareArgs.cpp index af1bc584b7..e9a3374735 100644 --- a/frontends/p4/dontcareArgs.cpp +++ b/frontends/p4/dontcareArgs.cpp @@ -16,17 +16,26 @@ limitations under the License. #include "dontcareArgs.h" +#include "frontends/p4/methodInstance.h" + namespace P4 { +Visitor::profile_t DontcareArgs::init_apply(const IR::Node *node) { + auto rv = Transform::init_apply(node); + node->apply(nameGen); + + return rv; +} + const IR::Node *DontcareArgs::postorder(IR::MethodCallExpression *expression) { bool changes = false; auto vec = new IR::Vector(); - auto mi = MethodInstance::resolve(expression, refMap, typeMap); + auto mi = MethodInstance::resolve(expression, this, typeMap); for (auto p : *mi->substitution.getParametersInArgumentOrder()) { auto a = mi->substitution.lookup(p); if (a->expression->is()) { - cstring name = refMap->newName("arg"); + cstring name = nameGen.newName("arg"); auto ptype = p->type; if (ptype->is()) { ::error(ErrorType::ERR_TYPE_ERROR, "Could not infer type for %1%", a); diff --git a/frontends/p4/dontcareArgs.h b/frontends/p4/dontcareArgs.h index b3321724d5..bc1697b002 100644 --- a/frontends/p4/dontcareArgs.h +++ b/frontends/p4/dontcareArgs.h @@ -17,6 +17,7 @@ limitations under the License. #ifndef FRONTENDS_P4_DONTCAREARGS_H_ #define FRONTENDS_P4_DONTCAREARGS_H_ +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "ir/ir.h" @@ -24,14 +25,13 @@ namespace P4 { /// This class replaces don't care arguments (_) with /// a temporary which is unused. -class DontcareArgs : public Transform { - ReferenceMap *refMap; +class DontcareArgs : public Transform, public ResolutionContext { + MinimalNameGenerator nameGen; TypeMap *typeMap; IR::IndexedVector toAdd; public: - DontcareArgs(ReferenceMap *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap) { - CHECK_NULL(refMap); + explicit DontcareArgs(TypeMap *typeMap) : typeMap(typeMap) { CHECK_NULL(typeMap); setName("DontcareArgs"); } @@ -56,13 +56,14 @@ class DontcareArgs : public Transform { toAdd.clear(); return control; } + profile_t init_apply(const IR::Node *node) override; }; class RemoveDontcareArgs : public PassManager { public: - RemoveDontcareArgs(ReferenceMap *refMap, TypeMap *typeMap) { - passes.push_back(new TypeChecking(refMap, typeMap)); - passes.push_back(new DontcareArgs(refMap, typeMap)); + explicit RemoveDontcareArgs(TypeMap *typeMap) { + passes.push_back(new TypeChecking(nullptr, typeMap)); + passes.push_back(new DontcareArgs(typeMap)); passes.push_back(new ClearTypeMap(typeMap)); setName("RemoveDontcareArgs"); } diff --git a/frontends/p4/entryPriorities.cpp b/frontends/p4/entryPriorities.cpp index 6188376f2c..eebff91370 100644 --- a/frontends/p4/entryPriorities.cpp +++ b/frontends/p4/entryPriorities.cpp @@ -20,20 +20,20 @@ limitations under the License. namespace P4 { -bool DoEntryPriorities::requiresPriority(const IR::KeyElement *ke) const { +bool EntryPriorities::requiresPriority(const IR::KeyElement *ke) const { // Check if the keys support priorities. Note: since match_kind // is extensible, we treat any non-standard match kind as if it // may require priorities. Back-ends should implement additional // checks if that's not true. auto path = ke->matchType->path; - auto mt = refMap->getDeclaration(path, true)->to(); + auto mt = getDeclaration(path, true)->to(); BUG_CHECK(mt != nullptr, "%1%: could not find declaration", ke->matchType); if (mt->name.name == corelib.exactMatch.name || mt->name.name == corelib.lpmMatch.name) return false; return true; } -const IR::Node *DoEntryPriorities::preorder(IR::EntriesList *entries) { +const IR::Node *EntryPriorities::preorder(IR::EntriesList *entries) { auto table = findContext(); CHECK_NULL(table); auto ep = table->properties->getProperty(IR::TableProperties::entriesPropertyName); diff --git a/frontends/p4/entryPriorities.h b/frontends/p4/entryPriorities.h index 2782a120f8..e53b6c56eb 100644 --- a/frontends/p4/entryPriorities.h +++ b/frontends/p4/entryPriorities.h @@ -25,30 +25,16 @@ limitations under the License. namespace P4 { /// Assigns priorities to table entries if they are not 'const' -class DoEntryPriorities : public Transform { - ReferenceMap *refMap; +class EntryPriorities : public Transform, public ResolutionContext { P4::P4CoreLibrary &corelib; bool requiresPriority(const IR::KeyElement *ke) const; public: - explicit DoEntryPriorities(ReferenceMap *refMap) - : refMap(refMap), corelib(P4::P4CoreLibrary::instance()) { - setName("DoEntryPriorities"); - CHECK_NULL(refMap); - } + EntryPriorities() : corelib(P4::P4CoreLibrary::instance()) { setName("EntryPriorities"); } const IR::Node *preorder(IR::EntriesList *entries) override; }; -class EntryPriorities : public PassManager { - public: - explicit EntryPriorities(ReferenceMap *refMap) { - setName("EntryPriorities"); - passes.emplace_back(new ResolveReferences(refMap)); - passes.emplace_back(new DoEntryPriorities(refMap)); - } -}; - } // namespace P4 #endif /* FRONTENDS_P4_ENTRYPRIORITIES_H_ */ diff --git a/frontends/p4/evaluator/evaluator.cpp b/frontends/p4/evaluator/evaluator.cpp index d154cf5c4b..a937e5e97a 100644 --- a/frontends/p4/evaluator/evaluator.cpp +++ b/frontends/p4/evaluator/evaluator.cpp @@ -17,6 +17,7 @@ limitations under the License. #include "evaluator.h" #include "frontends/common/constantFolding.h" +#include "frontends/p4/parameterSubstitution.h" #include "frontends/p4/typeChecking/typeChecker.h" namespace P4 { diff --git a/frontends/p4/evaluator/substituteParameters.cpp b/frontends/p4/evaluator/substituteParameters.cpp index 13237bc12e..ba48401c3a 100644 --- a/frontends/p4/evaluator/substituteParameters.cpp +++ b/frontends/p4/evaluator/substituteParameters.cpp @@ -25,7 +25,8 @@ const IR::Node *SubstituteParameters::postorder(IR::This *t) { } const IR::Node *SubstituteParameters::postorder(IR::PathExpression *expr) { - auto decl = refMap->getDeclaration(expr->path, true); + auto decl = + (refMap ? refMap->getDeclaration(expr->path, true) : getDeclaration(expr->path, true)); auto param = decl->to(); if (param != nullptr && subst->contains(param)) { auto value = subst->lookup(param)->expression; @@ -38,12 +39,12 @@ const IR::Node *SubstituteParameters::postorder(IR::PathExpression *expr) { auto path = new IR::Path(newid, expr->path->absolute); auto result = new IR::PathExpression(path); LOG1("Cloned " << dbp(expr) << " into " << dbp(result)); - refMap->setDeclaration(path, decl); return result; } const IR::Node *SubstituteParameters::postorder(IR::Type_Name *type) { - auto decl = refMap->getDeclaration(type->path, true); + auto decl = + (refMap ? refMap->getDeclaration(type->path, true) : getDeclaration(type->path, true)); auto var = decl->to(); if (var != nullptr && bindings->containsKey(var)) { auto repl = bindings->lookup(var); @@ -53,7 +54,6 @@ const IR::Node *SubstituteParameters::postorder(IR::Type_Name *type) { IR::ID newid = type->path->name; auto path = new IR::Path(newid, type->path->absolute); - refMap->setDeclaration(path, decl); auto result = new IR::Type_Name(type->srcInfo, path); LOG1("Cloned " << dbp(type) << " into " << dbp(result)); return result; diff --git a/frontends/p4/evaluator/substituteParameters.h b/frontends/p4/evaluator/substituteParameters.h index 888e94358b..6479f7d1aa 100644 --- a/frontends/p4/evaluator/substituteParameters.h +++ b/frontends/p4/evaluator/substituteParameters.h @@ -20,25 +20,21 @@ limitations under the License. #define EVALUATOR_SUBSTITUTEPARAMETERS_H_ #include "frontends/common/resolveReferences/referenceMap.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/parameterSubstitution.h" #include "frontends/p4/typeChecking/typeSubstitutionVisitor.h" #include "ir/ir.h" namespace P4 { -class SubstituteParameters : public TypeVariableSubstitutionVisitor { +class SubstituteParameters : public TypeVariableSubstitutionVisitor, public ResolutionContext { protected: - // When a PathExpression is cloned, it is added to the RefMap. - // It is set to point to the same declaration as the original path. - // But running this pass may change some declaration nodes - so - // in general the refMap won't be up-to-date at the end. - ReferenceMap *refMap; // input and output + const DeclarationLookup *refMap; // input const ParameterSubstitution *subst; // input public: - SubstituteParameters(ReferenceMap *refMap, const ParameterSubstitution *subst, + SubstituteParameters(const DeclarationLookup *refMap, const ParameterSubstitution *subst, const TypeVariableSubstitution *tvs) : TypeVariableSubstitutionVisitor(tvs), refMap(refMap), subst(subst) { - CHECK_NULL(refMap); CHECK_NULL(subst); CHECK_NULL(tvs); visitDagOnce = true; diff --git a/frontends/p4/frontend.cpp b/frontends/p4/frontend.cpp index bcacebaa11..c96fb9cd6a 100644 --- a/frontends/p4/frontend.cpp +++ b/frontends/p4/frontend.cpp @@ -173,64 +173,62 @@ const IR::P4Program *FrontEnd::run(const CompilerOptions &options, const IR::P4P new ResolveReferences(&refMap, /* checkShadow */ true), // First pass of constant folding, before types are known -- // may be needed to compute types. - new ConstantFolding(&refMap, nullptr, constantFoldingPolicy), + new ConstantFolding(constantFoldingPolicy), // Desugars direct parser and control applications // into instantiations followed by application - new InstantiateDirectCalls(&refMap), - new ResolveReferences(&refMap), - new Deprecated(&refMap), + new InstantiateDirectCalls(), + new Deprecated(), new CheckNamedArgs(), // Type checking and type inference. Also inserts // explicit casts where implicit casts exist. - new SetStrictStruct(&typeMap, true), // Next pass uses strict struct checking - new TypeInference(&refMap, &typeMap, false, false), // insert casts, don't check arrays + new SetStrictStruct(&typeMap, true), // Next pass uses strict struct checking + new TypeInference(&typeMap, false, false), // insert casts, don't check arrays new SetStrictStruct(&typeMap, false), new ValidateMatchAnnotations(&typeMap), new ValidateValueSets(), - new DefaultValues(&refMap, &typeMap), - new BindTypeVariables(&refMap, &typeMap), - new EntryPriorities(&refMap), + new DefaultValues(&typeMap), + new BindTypeVariables(&typeMap), + new EntryPriorities(), new PassRepeated({ - new SpecializeGenericTypes(&refMap, &typeMap), - new DefaultArguments(&refMap, &typeMap), // add default argument values to parameters - new ResolveReferences(&refMap), - new SetStrictStruct(&typeMap, true), // Next pass uses strict struct checking - new TypeInference(&refMap, &typeMap, false), // more casts may be needed + new SpecializeGenericTypes(&typeMap), + new DefaultArguments(&typeMap), // add default argument values to parameters + new SetStrictStruct(&typeMap, true), // Next pass uses strict struct checking + new TypeInference(&typeMap, false), // more casts may be needed new SetStrictStruct(&typeMap, false), - new SpecializeGenericFunctions(&refMap, &typeMap), + new SpecializeGenericFunctions(&typeMap), }), - new CheckCoreMethods(&refMap, &typeMap), - new StaticAssert(&refMap, &typeMap), - new RemoveParserIfs(&refMap, &typeMap), - new StructInitializers(&refMap, &typeMap), - new TableKeyNames(&refMap, &typeMap), + new CheckCoreMethods(&typeMap), + new StaticAssert(&typeMap), + new RemoveParserIfs(&typeMap), + new StructInitializers(&typeMap), + new TableKeyNames(&typeMap), new PassRepeated({ - new ConstantFolding(&refMap, &typeMap, constantFoldingPolicy), - new StrengthReduction(&refMap, &typeMap, policy->enableSubConstToAddTransform()), + new ConstantFolding(&typeMap, constantFoldingPolicy), + new StrengthReduction(&typeMap, policy->enableSubConstToAddTransform()), new Reassociation(), - new UselessCasts(&refMap, &typeMap), + new UselessCasts(&typeMap), }), - new SimplifyControlFlow(&refMap, &typeMap), + new SimplifyControlFlow(&typeMap), new SwitchAddDefault, new FrontEndDump(), // used for testing the program at this point new RemoveAllUnusedDeclarations(&refMap, *policy, true), new SimplifyParsers(&refMap), - new ResetHeaders(&refMap, &typeMap), - new UniqueNames(&refMap), // Give each local declaration a unique internal name - new MoveDeclarations(), // Move all local declarations to the beginning - new MoveInitializers(&refMap), - new SideEffectOrdering(&refMap, &typeMap, policy->skipSideEffectOrdering()), - new SimplifyControlFlow(&refMap, &typeMap), - new SimplifySwitch(&refMap, &typeMap), + new ResetHeaders(&typeMap), + new UniqueNames(), // Give each local declaration a unique internal name + new MoveDeclarations(), // Move all local declarations to the beginning + new MoveInitializers(), + new SideEffectOrdering(&typeMap, policy->skipSideEffectOrdering()), + new SimplifyControlFlow(&typeMap), + new SimplifySwitch(&typeMap), new MoveDeclarations(), // Move all local declarations to the beginning new SimplifyDefUse(&refMap, &typeMap), - new UniqueParameters(&refMap, &typeMap), - new SimplifyControlFlow(&refMap, &typeMap), + new UniqueParameters(&typeMap), + new SimplifyControlFlow(&typeMap), new SpecializeAll(&refMap, &typeMap, policy), - new RemoveParserControlFlow(&refMap, &typeMap), - new RemoveReturns(&refMap), - new RemoveDontcareArgs(&refMap, &typeMap), - new MoveConstructors(&refMap), + new RemoveParserControlFlow(&typeMap), + new RemoveReturns(), + new RemoveDontcareArgs(&typeMap), + new MoveConstructors(), new RemoveAllUnusedDeclarations(&refMap, *policy), new RemoveRedundantParsers(&refMap, &typeMap, *policy), new ClearTypeMap(&typeMap), @@ -241,25 +239,25 @@ const IR::P4Program *FrontEnd::run(const CompilerOptions &options, const IR::P4P new Inline(&refMap, &typeMap, evaluator, *policy, options.optimizeParserInlining), new InlineActions(&refMap, &typeMap, *policy), new LocalizeAllActions(&refMap, *policy), - new UniqueNames(&refMap), - new UniqueParameters(&refMap, &typeMap), + new UniqueNames(), + new UniqueParameters(&typeMap), // Must be done before inlining functions, to allow // function calls used as action arguments to be inlined // in the proper place. - new RemoveActionParameters(&refMap, &typeMap), + new RemoveActionParameters(&typeMap), new InlineFunctions(&refMap, &typeMap, *policy), - new SetHeaders(&refMap, &typeMap), + new SetHeaders(&typeMap), // Check for constants only after inlining - new CheckConstants(&refMap, &typeMap), - new ConstantFolding(&refMap, &typeMap, constantFoldingPolicy), - new SimplifyControlFlow(&refMap, &typeMap), + new CheckConstants(&typeMap), + new ConstantFolding(&typeMap, constantFoldingPolicy), + new SimplifyControlFlow(&typeMap), // more ifs may have been added to parsers - new RemoveParserControlFlow(&refMap, &typeMap), - new UniqueNames(&refMap), // needed again after inlining - new MoveDeclarations(), // needed again after inlining + new RemoveParserControlFlow(&typeMap), + new UniqueNames(), // needed again after inlining + new MoveDeclarations(), // needed again after inlining new SimplifyDefUse(&refMap, &typeMap), new RemoveAllUnusedDeclarations(&refMap, *policy), - new SimplifyControlFlow(&refMap, &typeMap), + new SimplifyControlFlow(&typeMap), }); passes.addPasses({ // Check for shadowing after all inlining passes. We disable this diff --git a/frontends/p4/functionsInlining.cpp b/frontends/p4/functionsInlining.cpp index ceaf818ae5..a48d2bcab4 100644 --- a/frontends/p4/functionsInlining.cpp +++ b/frontends/p4/functionsInlining.cpp @@ -16,8 +16,6 @@ limitations under the License. #include "functionsInlining.h" -#include "frontends/common/resolveReferences/resolveReferences.h" -#include "frontends/p4/callGraph.h" #include "frontends/p4/evaluator/substituteParameters.h" #include "frontends/p4/methodInstance.h" #include "frontends/p4/parameterSubstitution.h" @@ -25,7 +23,7 @@ limitations under the License. namespace P4 { void DiscoverFunctionsInlining::postorder(const IR::MethodCallExpression *mce) { - auto mi = P4::MethodInstance::resolve(mce, refMap, typeMap); + auto mi = P4::MethodInstance::resolve(mce, this, typeMap); CHECK_NULL(mi); auto ac = mi->to(); if (ac == nullptr) return; @@ -48,11 +46,16 @@ void FunctionsInliner::end_apply(const IR::Node *) { } Visitor::profile_t FunctionsInliner::init_apply(const IR::Node *node) { - P4::ResolveReferences solver(refMap); - refMap->clear(); - node->apply(solver); + auto rv = Transform::init_apply(node); + LOG2("FunctionsInliner " << toInline); - return Transform::init_apply(node); + + if (!nameGen) { + // This would apply nameGen onto node + nameGen = std::make_unique(node); + } + + return rv; } bool FunctionsInliner::preCaller() { @@ -177,7 +180,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.name.string_view()); + cstring newName = nameGen->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, @@ -198,8 +201,13 @@ const IR::Node *FunctionsInliner::inlineBefore(const IR::Node *calleeNode, } } - SubstituteParameters sp(refMap, &subst, &tvs); - auto clone = callee->apply(sp); + // FIXME: SubstituteParameters is a ResolutionContext, but we are recreating + // it again and again killing lookup caches. We'd need to have instead some + // separate DeclarationLookup that would allow us to perform necessary + // lookups in the context of callee. We can probably pre-seed it first for + // all possible callees in replMap. + SubstituteParameters sp(nullptr, &subst, &tvs); + auto clone = callee->apply(sp, getChildContext()); if (::errorCount() > 0) return statement; CHECK_NULL(clone); BUG_CHECK(clone->is(), "%1%: not an function", clone); diff --git a/frontends/p4/functionsInlining.h b/frontends/p4/functionsInlining.h index 6b470f9df8..50146af553 100644 --- a/frontends/p4/functionsInlining.h +++ b/frontends/p4/functionsInlining.h @@ -18,7 +18,8 @@ limitations under the License. #define FRONTENDS_P4_FUNCTIONSINLINING_H_ #include "commonInlining.h" -#include "frontends/p4/cloner.h" +#include "frontends/common/resolveReferences/referenceMap.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "frontends/p4/unusedDeclarations.h" #include "ir/ir.h" @@ -29,17 +30,14 @@ typedef SimpleCallInfo FunctionCallInfo; typedef SimpleInlineWorkList FunctionsInlineWorkList; typedef SimpleInlineList FunctionsInlineList; -class DiscoverFunctionsInlining : public Inspector { +class DiscoverFunctionsInlining : public Inspector, public ResolutionContext { FunctionsInlineList *toInline; // output - P4::ReferenceMap *refMap; // input P4::TypeMap *typeMap; // input public: - DiscoverFunctionsInlining(FunctionsInlineList *toInline, P4::ReferenceMap *refMap, - P4::TypeMap *typeMap) - : toInline(toInline), refMap(refMap), typeMap(typeMap) { + DiscoverFunctionsInlining(FunctionsInlineList *toInline, P4::TypeMap *typeMap) + : toInline(toInline), typeMap(typeMap) { CHECK_NULL(toInline); - CHECK_NULL(refMap); CHECK_NULL(typeMap); setName("DiscoverFunctionsInlining"); } @@ -51,7 +49,8 @@ class DiscoverFunctionsInlining : public Inspector { This must be executed after SideEffectOrdering and RemoveReturns. */ class FunctionsInliner : public AbstractInliner { - P4::ReferenceMap *refMap; + std::unique_ptr nameGen; + // All elements in the replacement map are actually IR::Function objects typedef std::map ReplacementMap; /// A stack of replacement maps @@ -72,7 +71,7 @@ class FunctionsInliner : public AbstractInlinersetIsV1(isv1); } + FunctionsInliner() = default; Visitor::profile_t init_apply(const IR::Node *node) override; void end_apply(const IR::Node *node) override; const IR::Node *preorder(IR::Function *function) override; @@ -109,10 +108,10 @@ class InlineFunctions : public PassManager { public: InlineFunctions(ReferenceMap *refMap, TypeMap *typeMap, const RemoveUnusedPolicy &policy) { passes.push_back(new PassRepeated( - {new TypeChecking(refMap, typeMap), - new DiscoverFunctionsInlining(&functionsToInline, refMap, typeMap), - new InlineFunctionsDriver(&functionsToInline, new FunctionsInliner(refMap->isV1())), - new RemoveAllUnusedDeclarations(refMap, policy)})); + {new TypeChecking(nullptr, typeMap), + new DiscoverFunctionsInlining(&functionsToInline, typeMap), + new InlineFunctionsDriver(&functionsToInline, new FunctionsInliner()), + new ResolveReferences(refMap), new RemoveAllUnusedDeclarations(refMap, policy)})); passes.push_back(new CloneVariableDeclarations()); setName("InlineFunctions"); } diff --git a/frontends/p4/localizeActions.cpp b/frontends/p4/localizeActions.cpp index c7ea68eae5..9ddb45d210 100644 --- a/frontends/p4/localizeActions.cpp +++ b/frontends/p4/localizeActions.cpp @@ -52,13 +52,20 @@ const IR::Node *TagGlobalActions::preorder(IR::P4Action *action) { return action; } +Visitor::profile_t FindGlobalActionUses::init_apply(const IR::Node *node) { + auto rv = Inspector::init_apply(node); + node->apply(nameGen); + + return rv; +} + bool FindGlobalActionUses::preorder(const IR::P4Action *action) { if (findContext() == nullptr) globalActions.emplace(action); return false; } bool FindGlobalActionUses::preorder(const IR::PathExpression *path) { - auto decl = refMap->getDeclaration(path->path, true); + auto decl = getDeclaration(path->path, true); if (!decl->is()) return false; auto action = decl->to(); @@ -66,7 +73,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.name.string_view()); + auto newName = nameGen.newName(action->name.name.string_view()); ParamCloner cloner; auto replBody = cloner.clone(action->body); auto params = cloner.clone(action->parameters); @@ -101,7 +108,7 @@ const IR::Node *LocalizeActions::postorder(IR::P4Control *control) { const IR::Node *LocalizeActions::postorder(IR::PathExpression *expression) { auto control = findOrigCtxt(); if (control == nullptr) return expression; - auto decl = refMap->getDeclaration(expression->path); + auto decl = getDeclaration(expression->path); if (!decl || !decl->is()) return expression; auto action = decl->to(); auto replacement = repl->getReplacement(action, control); @@ -113,8 +120,15 @@ const IR::Node *LocalizeActions::postorder(IR::PathExpression *expression) { return expression; } +Visitor::profile_t FindRepeatedActionUses::init_apply(const IR::Node *node) { + auto rv = Inspector::init_apply(node); + node->apply(nameGen); + + return rv; +} + bool FindRepeatedActionUses::preorder(const IR::PathExpression *expression) { - auto decl = refMap->getDeclaration(expression->path, true); + auto decl = getDeclaration(expression->path, true); if (!decl->is()) return false; auto action = decl->to(); auto control = findContext(); @@ -141,7 +155,7 @@ bool FindRepeatedActionUses::preorder(const IR::PathExpression *expression) { auto methmem = method->to(); BUG_CHECK(methmem->expr->is(), "Unexpected table %1%", methmem->expr); auto pathe = methmem->expr->to(); - auto tbl = refMap->getDeclaration(pathe->path, true); + auto tbl = getDeclaration(pathe->path, true); BUG_CHECK(tbl->is(), "%1%: expected a table", pathe); actionUser = tbl->to(); } @@ -149,7 +163,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.name.string_view()); + auto newName = nameGen.newName(action->name.name.string_view()); ParamCloner cloner; auto replBody = cloner.clone(action->body); auto annos = action->annotations; diff --git a/frontends/p4/localizeActions.h b/frontends/p4/localizeActions.h index 7cc15247e9..e74e090a5f 100644 --- a/frontends/p4/localizeActions.h +++ b/frontends/p4/localizeActions.h @@ -17,6 +17,8 @@ limitations under the License. #ifndef FRONTENDS_P4_LOCALIZEACTIONS_H_ #define FRONTENDS_P4_LOCALIZEACTIONS_H_ +#include "frontends/common/resolveReferences/referenceMap.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/callGraph.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "frontends/p4/unusedDeclarations.h" @@ -49,33 +51,29 @@ class GlobalActionReplacements { }; // Find global (i.e., declared at toplevel) actions and who uses them. -class FindGlobalActionUses : public Inspector { - ReferenceMap *refMap; +class FindGlobalActionUses : public Inspector, public ResolutionContext { + MinimalNameGenerator nameGen; GlobalActionReplacements *repl; std::set globalActions; public: - FindGlobalActionUses(ReferenceMap *refMap, GlobalActionReplacements *repl) - : refMap(refMap), repl(repl) { - CHECK_NULL(refMap); + explicit FindGlobalActionUses(GlobalActionReplacements *repl) : repl(repl) { CHECK_NULL(repl); setName("FindGlobalActionUses"); } bool preorder(const IR::PathExpression *path) override; bool preorder(const IR::P4Action *action) override; + profile_t init_apply(const IR::Node *node) override; }; // Global actions are cloned into actions local to the // control using them. One action can produce many copies. -class LocalizeActions : public Transform { - ReferenceMap *refMap; +class LocalizeActions : public Transform, public ResolutionContext { GlobalActionReplacements *repl; public: - LocalizeActions(ReferenceMap *refMap, GlobalActionReplacements *repl) - : refMap(refMap), repl(repl) { + explicit LocalizeActions(GlobalActionReplacements *repl) : repl(repl) { visitDagOnce = false; - CHECK_NULL(refMap); CHECK_NULL(repl); setName("LocalizeActions"); } @@ -117,18 +115,17 @@ class ActionReplacement { // Find actions that are invoked in multiple places; create a new // copy for each invocation and store it in the repl map. Ignores // actions that are not in a control. -class FindRepeatedActionUses : public Inspector { - ReferenceMap *refMap; +class FindRepeatedActionUses : public Inspector, public ResolutionContext { + MinimalNameGenerator nameGen; ActionReplacement *repl; public: - FindRepeatedActionUses(ReferenceMap *refMap, ActionReplacement *repl) - : refMap(refMap), repl(repl) { - CHECK_NULL(refMap); + explicit FindRepeatedActionUses(ActionReplacement *repl) : repl(repl) { CHECK_NULL(repl); setName("FindRepeatedActionUses"); } bool preorder(const IR::PathExpression *expression) override; + profile_t init_apply(const IR::Node *node) override; }; // Replicates actions for each different user. @@ -174,13 +171,12 @@ class LocalizeAllActions : public PassManager { explicit LocalizeAllActions(ReferenceMap *refMap, const RemoveUnusedPolicy &policy) { passes.emplace_back(new TagGlobalActions()); passes.emplace_back(new PassRepeated{ - new ResolveReferences(refMap), - new FindGlobalActionUses(refMap, &globalReplacements), - new LocalizeActions(refMap, &globalReplacements), + new FindGlobalActionUses(&globalReplacements), + new LocalizeActions(&globalReplacements), }); - passes.emplace_back(new ResolveReferences(refMap)); - passes.emplace_back(new FindRepeatedActionUses(refMap, &localReplacements)); + passes.emplace_back(new FindRepeatedActionUses(&localReplacements)); passes.emplace_back(new DuplicateActions(&localReplacements)); + passes.emplace_back(new ResolveReferences(refMap)); passes.emplace_back(new RemoveAllUnusedDeclarations(refMap, policy)); setName("LocalizeAllActions"); } diff --git a/frontends/p4/methodInstance.cpp b/frontends/p4/methodInstance.cpp index 1d96d7987f..ff924f9ae4 100644 --- a/frontends/p4/methodInstance.cpp +++ b/frontends/p4/methodInstance.cpp @@ -16,6 +16,7 @@ limitations under the License. #include "methodInstance.h" +#include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/p4/evaluator/substituteParameters.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "ir/ir.h" @@ -24,7 +25,7 @@ namespace P4 { // If useExpressionType is true trust the type in mce->type MethodInstance *MethodInstance::resolve(const IR::MethodCallExpression *mce, - DeclarationLookup *refMap, TypeMap *typeMap, + const DeclarationLookup *refMap, TypeMap *typeMap, bool useExpressionType, const Visitor::Context *ctxt, bool incomplete) { auto mt = typeMap ? typeMap->getType(mce->method) : nullptr; @@ -34,11 +35,10 @@ MethodInstance *MethodInstance::resolve(const IR::MethodCallExpression *mce, auto originalType = mt->to(); auto actualType = originalType; if (typeMap && !mce->typeArguments->empty()) { - auto t = TypeInference::specialize(originalType, mce->typeArguments); + auto t = TypeInference::specialize(originalType, mce->typeArguments, ctxt); CHECK_NULL(t); actualType = t->to(); - // FIXME -- currently refMap is always a ReferenceMap, but this arg should soon go away - TypeInference tc(dynamic_cast(refMap), typeMap, true); + TypeInference tc(typeMap, /* readOnly */ true); (void)actualType->apply(tc, ctxt); // may need to learn new type components CHECK_NULL(actualType); } @@ -73,7 +73,7 @@ MethodInstance *MethodInstance::resolve(const IR::MethodCallExpression *mce, decl = refMap->getDeclaration(th, true); } else if (auto pe = mem->expr->to()) { decl = refMap->getDeclaration(pe->path, true); - type = typeMap ? typeMap->getType(decl->getNode()) : pe->type; + type = typeMap ? typeMap->getType(decl->getNode(), true) : pe->type; } else if (auto mc = mem->expr->to()) { auto mi = resolve(mc, refMap, typeMap, useExpressionType); decl = mi->object; @@ -123,14 +123,14 @@ MethodInstance *MethodInstance::resolve(const IR::MethodCallExpression *mce, return nullptr; // unreachable } -const IR::P4Action *ActionCall::specialize(ReferenceMap *refMap) const { +const IR::P4Action *ActionCall::specialize(const DeclarationLookup *refMap) const { SubstituteParameters sp(refMap, &substitution, new TypeVariableSubstitution()); auto result = action->apply(sp); return result->to(); } ConstructorCall *ConstructorCall::resolve(const IR::ConstructorCallExpression *cce, - DeclarationLookup *refMap, TypeMap *typeMap) { + const DeclarationLookup *refMap, TypeMap *typeMap) { auto ct = typeMap ? typeMap->getTypeType(cce->constructedType, true) : cce->type; ConstructorCall *result; const IR::Vector *typeArguments; diff --git a/frontends/p4/methodInstance.h b/frontends/p4/methodInstance.h index 3d685d66fb..f330dad832 100644 --- a/frontends/p4/methodInstance.h +++ b/frontends/p4/methodInstance.h @@ -91,26 +91,31 @@ class MethodInstance : public InstanceBase { * @param incomplete If true we do not expect to have * all type arguments. */ - static MethodInstance *resolve(const IR::MethodCallExpression *mce, DeclarationLookup *refMap, - TypeMap *typeMap, bool useExpressionType = false, + static MethodInstance *resolve(const IR::MethodCallExpression *mce, + const DeclarationLookup *refMap, TypeMap *typeMap, + bool useExpressionType = false, const Visitor::Context *ctxt = nullptr, bool incomplete = false); - static MethodInstance *resolve(const IR::MethodCallExpression *mce, DeclarationLookup *refMap, - TypeMap *typeMap, const Visitor::Context *ctxt, - bool incomplete = false) { + static MethodInstance *resolve(const IR::MethodCallExpression *mce, + const DeclarationLookup *refMap, TypeMap *typeMap, + const Visitor::Context *ctxt, bool incomplete = false) { return resolve(mce, refMap, typeMap, false, ctxt, incomplete); } - static MethodInstance *resolve(const IR::MethodCallStatement *mcs, DeclarationLookup *refMap, - TypeMap *typeMap, const Visitor::Context *ctxt = nullptr) { + static MethodInstance *resolve(const IR::MethodCallStatement *mcs, + const DeclarationLookup *refMap, TypeMap *typeMap, + const Visitor::Context *ctxt = nullptr) { return resolve(mcs->methodCall, refMap, typeMap, false, ctxt, false); } - static MethodInstance *resolve(const IR::MethodCallExpression *mce, DeclarationLookup *refMap, + static MethodInstance *resolve(const IR::MethodCallExpression *mce, + const DeclarationLookup *refMap, const Visitor::Context *ctxt = nullptr) { return resolve(mce, refMap, nullptr, true, ctxt, false); } - static MethodInstance *resolve(const IR::MethodCallStatement *mcs, DeclarationLookup *refMap, + static MethodInstance *resolve(const IR::MethodCallStatement *mcs, + const DeclarationLookup *refMap, const Visitor::Context *ctxt = nullptr) { return resolve(mcs->methodCall, refMap, nullptr, true, ctxt, false); } + const IR::ParameterList *getOriginalParameters() const { return originalMethodType->parameters; } @@ -210,7 +215,7 @@ class ActionCall final : public MethodInstance { const IR::P4Action *action; /// Generate a version of the action where the parameters in the /// substitution have been replaced with the arguments. - const IR::P4Action *specialize(ReferenceMap *refMap) const; + const IR::P4Action *specialize(const DeclarationLookup *refMap) const; DECLARE_TYPEINFO(ActionCall, MethodInstance); }; @@ -282,7 +287,7 @@ class ConstructorCall : public InstanceBase { const IR::Vector *typeArguments = nullptr; const IR::ParameterList *constructorParameters = nullptr; static ConstructorCall *resolve(const IR::ConstructorCallExpression *cce, - DeclarationLookup *refMap, TypeMap *typeMap); + const DeclarationLookup *refMap, TypeMap *typeMap); DECLARE_TYPEINFO(ConstructorCall, InstanceBase); }; diff --git a/frontends/p4/moveConstructors.cpp b/frontends/p4/moveConstructors.cpp index 3176208182..1c8d2450f4 100644 --- a/frontends/p4/moveConstructors.cpp +++ b/frontends/p4/moveConstructors.cpp @@ -18,136 +18,111 @@ limitations under the License. namespace P4 { -struct ConstructorMap { - // Maps a constructor to the temporary used to hold its value. - ordered_map tmpName; - - void clear() { tmpName.clear(); } - void add(const IR::ConstructorCallExpression *expression, cstring name) { - CHECK_NULL(expression); - tmpName[expression] = name; - } - bool empty() const { return tmpName.empty(); } -}; - -namespace { - -class MoveConstructorsImpl : public Transform { - enum class Region { InParserStateful, InControlStateful, InBody, Outside }; +MoveConstructors::MoveConstructors() : convert(Region::Outside) { setName("MoveConstructors"); } - ReferenceMap *refMap; - ConstructorMap cmap; - Region convert; +Visitor::profile_t MoveConstructors::init_apply(const IR::Node *node) { + auto rv = Transform::init_apply(node); + node->apply(nameGen); - public: - explicit MoveConstructorsImpl(ReferenceMap *refMap) : refMap(refMap), convert(Region::Outside) { - setName("MoveConstructorsImpl"); - } + return rv; +} - const IR::Node *preorder(IR::P4Parser *parser) override { - cmap.clear(); - convert = Region::InParserStateful; - visit(parser->parserLocals, "parserLocals"); - convert = Region::InBody; - visit(parser->states, "states"); - convert = Region::Outside; - prune(); - return parser; - } +const IR::Node *MoveConstructors::preorder(IR::P4Parser *parser) { + cmap.clear(); + convert = Region::InParserStateful; + visit(parser->parserLocals, "parserLocals"); + convert = Region::InBody; + visit(parser->states, "states"); + convert = Region::Outside; + prune(); + return parser; +} - const IR::Node *preorder(IR::IndexedVector *declarations) override { - if (convert != Region::InParserStateful) return declarations; - - bool changes = false; - auto result = new IR::Vector(); - for (auto s : *declarations) { - visit(s); - for (auto e : cmap.tmpName) { - auto cce = e.first; - auto decl = new IR::Declaration_Instance(cce->srcInfo, e.second, - cce->constructedType, cce->arguments); - result->push_back(decl); - changes = true; - } - result->push_back(s); - cmap.clear(); - } - prune(); - if (changes) return result; - return declarations; - } +const IR::Node *MoveConstructors::preorder(IR::IndexedVector *declarations) { + if (convert != Region::InParserStateful) return declarations; - const IR::Node *postorder(IR::P4Parser *parser) override { - if (cmap.empty()) return parser; + bool changes = false; + auto result = new IR::Vector(); + for (auto s : *declarations) { + visit(s); for (auto e : cmap.tmpName) { auto cce = e.first; auto decl = new IR::Declaration_Instance(cce->srcInfo, e.second, cce->constructedType, cce->arguments); - parser->parserLocals.insert(parser->parserLocals.begin(), decl); + result->push_back(decl); + changes = true; } - return parser; + result->push_back(s); + cmap.clear(); } + prune(); + if (changes) return result; + return declarations; +} - const IR::Node *preorder(IR::P4Control *control) override { - cmap.clear(); - convert = Region::InControlStateful; - IR::IndexedVector newDecls; - bool changes = false; - for (auto decl : control->controlLocals) { - visit(decl); - for (auto e : cmap.tmpName) { - auto cce = e.first; - auto inst = new IR::Declaration_Instance(cce->srcInfo, e.second, - cce->constructedType, cce->arguments); - newDecls.push_back(inst); - changes = true; - } - newDecls.push_back(decl); - cmap.clear(); - } - convert = Region::InBody; - visit(control->body); - convert = Region::Outside; - prune(); - if (changes) { - control->controlLocals = newDecls; - } - return control; +const IR::Node *MoveConstructors::postorder(IR::P4Parser *parser) { + if (cmap.empty()) return parser; + for (auto e : cmap.tmpName) { + auto cce = e.first; + auto decl = new IR::Declaration_Instance(cce->srcInfo, e.second, cce->constructedType, + cce->arguments); + parser->parserLocals.insert(parser->parserLocals.begin(), decl); } + return parser; +} - const IR::Node *postorder(IR::P4Control *control) override { - if (cmap.empty()) return control; - IR::IndexedVector newDecls; +const IR::Node *MoveConstructors::preorder(IR::P4Control *control) { + cmap.clear(); + convert = Region::InControlStateful; + IR::IndexedVector newDecls; + bool changes = false; + for (auto decl : control->controlLocals) { + visit(decl); for (auto e : cmap.tmpName) { auto cce = e.first; - auto decl = new IR::Declaration_Instance(cce->srcInfo, e.second, cce->constructedType, + auto inst = new IR::Declaration_Instance(cce->srcInfo, e.second, cce->constructedType, cce->arguments); - newDecls.push_back(decl); + newDecls.push_back(inst); + changes = true; } - newDecls.append(control->controlLocals); + newDecls.push_back(decl); + cmap.clear(); + } + convert = Region::InBody; + visit(control->body); + convert = Region::Outside; + prune(); + if (changes) { control->controlLocals = newDecls; - return control; } + return control; +} - const IR::Node *preorder(IR::P4Table *table) override { - prune(); - return table; - } // skip - - const IR::Node *postorder(IR::ConstructorCallExpression *expression) override { - if (convert == Region::Outside) return expression; - auto tmpvar = refMap->newName("tmp"); - auto tmpref = new IR::PathExpression(IR::ID(expression->srcInfo, tmpvar)); - cmap.add(expression, tmpvar); - return tmpref; +const IR::Node *MoveConstructors::postorder(IR::P4Control *control) { + if (cmap.empty()) return control; + IR::IndexedVector newDecls; + for (auto e : cmap.tmpName) { + auto cce = e.first; + auto decl = new IR::Declaration_Instance(cce->srcInfo, e.second, cce->constructedType, + cce->arguments); + newDecls.push_back(decl); } -}; -} // namespace + newDecls.append(control->controlLocals); + control->controlLocals = newDecls; + return control; +} -MoveConstructors::MoveConstructors(ReferenceMap *refMap) { - setName("MoveConstructors"); - passes.emplace_back(new P4::ResolveReferences(refMap)); - passes.emplace_back(new MoveConstructorsImpl(refMap)); +const IR::Node *MoveConstructors::preorder(IR::P4Table *table) { + prune(); + return table; +} // skip + +const IR::Node *MoveConstructors::postorder(IR::ConstructorCallExpression *expression) { + if (convert == Region::Outside) return expression; + auto tmpvar = nameGen.newName("tmp"); + auto tmpref = new IR::PathExpression(IR::ID(expression->srcInfo, tmpvar)); + cmap.add(expression, tmpvar); + return tmpref; } } // namespace P4 diff --git a/frontends/p4/moveConstructors.h b/frontends/p4/moveConstructors.h index 7d8da4caf9..3162a57f0b 100644 --- a/frontends/p4/moveConstructors.h +++ b/frontends/p4/moveConstructors.h @@ -17,8 +17,10 @@ limitations under the License. #ifndef FRONTENDS_P4_MOVECONSTRUCTORS_H_ #define FRONTENDS_P4_MOVECONSTRUCTORS_H_ -#include "frontends/common/resolveReferences/resolveReferences.h" -#include "ir/pass_manager.h" +#include "frontends/common/resolveReferences/referenceMap.h" +#include "ir/ir.h" +#include "ir/visitor.h" +#include "lib/ordered_map.h" namespace P4 { @@ -50,9 +52,36 @@ namespace P4 { * constructor parameters. * */ -class MoveConstructors : public PassManager { +class MoveConstructors : public Transform { + struct ConstructorMap { + // Maps a constructor to the temporary used to hold its value. + ordered_map tmpName; + + void clear() { tmpName.clear(); } + void add(const IR::ConstructorCallExpression *expression, cstring name) { + CHECK_NULL(expression); + tmpName[expression] = name; + } + bool empty() const { return tmpName.empty(); } + }; + + enum class Region { InParserStateful, InControlStateful, InBody, Outside }; + + MinimalNameGenerator nameGen; + ConstructorMap cmap; + Region convert; + public: - explicit MoveConstructors(ReferenceMap *refMap); + MoveConstructors(); + + profile_t init_apply(const IR::Node *node) override; + const IR::Node *preorder(IR::P4Parser *parser) override; + const IR::Node *preorder(IR::IndexedVector *declarations) override; + const IR::Node *postorder(IR::P4Parser *parser) override; + const IR::Node *preorder(IR::P4Control *control) override; + const IR::Node *postorder(IR::P4Control *control) override; + const IR::Node *preorder(IR::P4Table *table) override; + const IR::Node *postorder(IR::ConstructorCallExpression *expression) override; }; } // namespace P4 diff --git a/frontends/p4/moveDeclarations.cpp b/frontends/p4/moveDeclarations.cpp index 12d802893f..a3ac88830e 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.string_view()); + newStartName = nameGen.newName(IR::ParserState::start.string_view()); oldStart = parser->states.getDeclaration(IR::ParserState::start)->to(); CHECK_NULL(oldStart); } @@ -159,9 +159,16 @@ const IR::Node *MoveInitializers::postorder(IR::P4Control *control) { const IR::Node *MoveInitializers::postorder(IR::Path *path) { if (oldStart == nullptr || path->name != IR::ParserState::start) return path; - auto decl = refMap->getDeclaration(getOriginal()->to()); + auto decl = getDeclaration(getOriginal()->to()); if (!decl->is()) return path; return new IR::Path(newStartName); } +Visitor::profile_t MoveInitializers::init_apply(const IR::Node *node) { + auto rv = Transform::init_apply(node); + node->apply(nameGen); + + return rv; +} + } // namespace P4 diff --git a/frontends/p4/moveDeclarations.h b/frontends/p4/moveDeclarations.h index b486772524..a2d566e9de 100644 --- a/frontends/p4/moveDeclarations.h +++ b/frontends/p4/moveDeclarations.h @@ -18,6 +18,7 @@ limitations under the License. #define FRONTENDS_P4_MOVEDECLARATIONS_H_ #include "frontends/common/resolveReferences/referenceMap.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "ir/ir.h" namespace P4 { @@ -98,19 +99,18 @@ class MoveDeclarations : public Transform { * * @pre Must be run after MoveDeclarations. */ -class MoveInitializers : public Transform { - ReferenceMap *refMap; +class MoveInitializers : public Transform, public ResolutionContext { + MinimalNameGenerator nameGen; IR::IndexedVector *toMove; // This contains just IR::AssignmentStatement const IR::ParserState *oldStart; // nullptr if we do not want to rename the start state cstring newStartName; // name allocated to the old start state public: - explicit MoveInitializers(ReferenceMap *refMap) - : refMap(refMap), oldStart(nullptr), newStartName("") { + MoveInitializers() + : toMove(new IR::IndexedVector()), oldStart(nullptr), newStartName("") { setName("MoveInitializers"); - CHECK_NULL(refMap); - toMove = new IR::IndexedVector(); } + profile_t init_apply(const IR::Node *node) override; const IR::Node *preorder(IR::P4Parser *parser) override; const IR::Node *postorder(IR::P4Parser *parser) override; const IR::Node *postorder(IR::Declaration_Variable *decl) override; diff --git a/frontends/p4/optimizeExpressions.h b/frontends/p4/optimizeExpressions.h index 7d1fa2c55b..980babd734 100644 --- a/frontends/p4/optimizeExpressions.h +++ b/frontends/p4/optimizeExpressions.h @@ -10,7 +10,7 @@ namespace P4 { /// Currently, performs constant folding and strength reduction. inline const IR::Expression *optimizeExpression(const IR::Expression *node) { auto pass = PassRepeated({ - new P4::StrengthReduction(nullptr, nullptr, nullptr), + new P4::StrengthReduction(nullptr, nullptr), new P4::ConstantFolding(nullptr, nullptr, false), }); node = node->apply(pass); diff --git a/frontends/p4/parserControlFlow.cpp b/frontends/p4/parserControlFlow.cpp index ad51b2e1a5..1d702843e0 100644 --- a/frontends/p4/parserControlFlow.cpp +++ b/frontends/p4/parserControlFlow.cpp @@ -38,10 +38,10 @@ const IR::Node *DoRemoveParserControlFlow::postorder(IR::ParserState *state) { states->push_back(currentState); auto ifstat = c->to(); - joinName = refMap->newName(state->name.name + "_join"); + joinName = nameGen.newName(state->name.name + "_join"); // s_true - cstring trueName = refMap->newName(state->name.name + "_true"); + cstring trueName = nameGen.newName(state->name.name + "_true"); auto trueComponents = new IR::IndexedVector(); trueComponents->push_back(ifstat->ifTrue); auto trueState = new IR::ParserState(trueName, *trueComponents, @@ -51,7 +51,7 @@ const IR::Node *DoRemoveParserControlFlow::postorder(IR::ParserState *state) { // s_false cstring falseName = joinName; if (ifstat->ifFalse != nullptr) { - falseName = refMap->newName(state->name.name + "_false"); + falseName = nameGen.newName(state->name.name + "_false"); auto falseComponents = new IR::IndexedVector(); falseComponents->push_back(ifstat->ifFalse); auto falseState = new IR::ParserState( @@ -88,7 +88,11 @@ const IR::Node *DoRemoveParserControlFlow::postorder(IR::ParserState *state) { Visitor::profile_t DoRemoveParserControlFlow::init_apply(const IR::Node *node) { LOG1("DoRemoveControlFlow"); - return Transform::init_apply(node); + auto rv = Transform::init_apply(node); + + node->apply(nameGen); + + return rv; } } // namespace P4 diff --git a/frontends/p4/parserControlFlow.h b/frontends/p4/parserControlFlow.h index 6ac2036a73..0b866f5d1f 100644 --- a/frontends/p4/parserControlFlow.h +++ b/frontends/p4/parserControlFlow.h @@ -77,13 +77,10 @@ state s_join { */ class DoRemoveParserControlFlow : public Transform { - ReferenceMap *refMap; + MinimalNameGenerator nameGen; public: - explicit DoRemoveParserControlFlow(ReferenceMap *refMap) : refMap(refMap) { - CHECK_NULL(refMap); - setName("DoRemoveParserControlFlow"); - } + DoRemoveParserControlFlow() { setName("DoRemoveParserControlFlow"); } const IR::Node *postorder(IR::ParserState *state) override; Visitor::profile_t init_apply(const IR::Node *node) override; }; @@ -92,9 +89,9 @@ class DoRemoveParserControlFlow : public Transform { /// convergence. class RemoveParserControlFlow : public PassRepeated { public: - RemoveParserControlFlow(ReferenceMap *refMap, TypeMap *typeMap) : PassRepeated({}) { - passes.emplace_back(new DoRemoveParserControlFlow(refMap)); - passes.emplace_back(new SimplifyControlFlow(refMap, typeMap)); + explicit RemoveParserControlFlow(TypeMap *typeMap) : PassRepeated({}) { + passes.emplace_back(new DoRemoveParserControlFlow()); + passes.emplace_back(new SimplifyControlFlow(typeMap)); setName("RemoveParserControlFlow"); } }; @@ -119,15 +116,14 @@ class RemoveParserIfs : public PassManager { bool found = false; public: - RemoveParserIfs(ReferenceMap *refMap, TypeMap *typeMap) { + explicit RemoveParserIfs(TypeMap *typeMap) { passes.push_back(new IfInParser(&found)); - passes.push_back(new PassIf( - [this] { return found; }, - {// only do this if we found an 'if' in a parser - new ResolveReferences(refMap), - new UniqueNames(refMap), // Give each local declaration a unique internal name - new MoveDeclarations(true), // Move all local declarations to the beginning - new ResolveReferences(refMap), new RemoveParserControlFlow(refMap, typeMap)})); + passes.push_back( + new PassIf([this] { return found; }, + { // only do this if we found an 'if' in a parser + new UniqueNames(), // Give each local declaration a unique internal name + new MoveDeclarations(true), // Move all local declarations to the beginning + new RemoveParserControlFlow(typeMap)})); } }; diff --git a/frontends/p4/removeParameters.cpp b/frontends/p4/removeParameters.cpp index ca557b587b..a6d2eb1d50 100644 --- a/frontends/p4/removeParameters.cpp +++ b/frontends/p4/removeParameters.cpp @@ -50,7 +50,7 @@ class RemoveMethodCallArguments : public Transform { void FindActionParameters::postorder(const IR::ActionListElement *element) { auto path = element->getPath(); - auto decl = refMap->getDeclaration(path, true); + auto decl = getDeclaration(path, true); BUG_CHECK(decl->is(), "%1%: not an action", element); BUG_CHECK(element->expression->is(), "%1%: expected a method call", element->expression); @@ -59,7 +59,7 @@ void FindActionParameters::postorder(const IR::ActionListElement *element) { } void FindActionParameters::postorder(const IR::MethodCallExpression *expression) { - auto mi = MethodInstance::resolve(expression, refMap, typeMap); + auto mi = MethodInstance::resolve(expression, this, typeMap); if (!mi->is()) return; auto ac = mi->to(); @@ -183,8 +183,7 @@ const IR::Node *DoRemoveActionParameters::postorder(IR::MethodCallExpression *ex return expression; } -RemoveActionParameters::RemoveActionParameters(ReferenceMap *refMap, TypeMap *typeMap, - TypeChecking *typeChecking) { +RemoveActionParameters::RemoveActionParameters(TypeMap *typeMap, TypeChecking *typeChecking) { setName("RemoveActionParameters"); auto ai = new ActionInvocation(); // MoveDeclarations() is needed because of this case: @@ -196,9 +195,9 @@ RemoveActionParameters::RemoveActionParameters(ReferenceMap *refMap, TypeMap *ty // bit<32> w; // table t() { actions = a(); ... } passes.emplace_back(new MoveDeclarations()); - if (!typeChecking) typeChecking = new TypeChecking(refMap, typeMap); + if (!typeChecking) typeChecking = new TypeChecking(nullptr, typeMap); passes.emplace_back(typeChecking); - passes.emplace_back(new FindActionParameters(refMap, typeMap, ai)); + passes.emplace_back(new FindActionParameters(typeMap, ai)); passes.emplace_back(new DoRemoveActionParameters(ai)); passes.emplace_back(new ClearTypeMap(typeMap)); } diff --git a/frontends/p4/removeParameters.h b/frontends/p4/removeParameters.h index 6c4a283e56..65a366f710 100644 --- a/frontends/p4/removeParameters.h +++ b/frontends/p4/removeParameters.h @@ -18,6 +18,7 @@ limitations under the License. #define FRONTENDS_P4_REMOVEPARAMETERS_H_ #include "frontends/common/resolveReferences/referenceMap.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "frontends/p4/typeMap.h" #include "ir/ir.h" @@ -70,15 +71,13 @@ class ActionInvocation { } }; -class FindActionParameters : public Inspector { - ReferenceMap *refMap; +class FindActionParameters : public Inspector, public ResolutionContext { TypeMap *typeMap; ActionInvocation *invocations; public: - FindActionParameters(ReferenceMap *refMap, TypeMap *typeMap, ActionInvocation *invocations) - : refMap(refMap), typeMap(typeMap), invocations(invocations) { - CHECK_NULL(refMap); + FindActionParameters(TypeMap *typeMap, ActionInvocation *invocations) + : typeMap(typeMap), invocations(invocations) { CHECK_NULL(invocations); CHECK_NULL(typeMap); setName("FindActionParameters"); @@ -131,8 +130,7 @@ class DoRemoveActionParameters : public Transform { class RemoveActionParameters : public PassManager { public: - RemoveActionParameters(ReferenceMap *refMap, TypeMap *typeMap, - TypeChecking *typeChecking = nullptr); + explicit RemoveActionParameters(TypeMap *typeMap, TypeChecking *typeChecking = nullptr); }; } // namespace P4 diff --git a/frontends/p4/removeReturns.cpp b/frontends/p4/removeReturns.cpp index 5b34c68604..c7ee8b7273 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.string_view()); + cstring var = nameGen.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.string_view()); + cstring var = nameGen.newName(variableName.string_view()); returnVar = IR::ID(var, nullptr); IR::Declaration_Variable *retvalDecl = nullptr; if (returnsVal) { - var = refMap->newName(retValName.string_view()); + var = nameGen.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.string_view()); + cstring var = nameGen.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); @@ -229,4 +229,11 @@ const IR::Node *DoRemoveReturns::postorder(IR::LoopStatement *loop) { return rv; } +Visitor::profile_t DoRemoveReturns::init_apply(const IR::Node *node) { + auto rv = Transform::init_apply(node); + node->apply(nameGen); + + return rv; +} + } // namespace P4 diff --git a/frontends/p4/removeReturns.h b/frontends/p4/removeReturns.h index 9cd8e10b6d..2cf043b258 100644 --- a/frontends/p4/removeReturns.h +++ b/frontends/p4/removeReturns.h @@ -17,6 +17,7 @@ limitations under the License. #ifndef FRONTENDS_P4_REMOVERETURNS_H_ #define FRONTENDS_P4_REMOVERETURNS_H_ +#include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/ternaryBool.h" #include "frontends/p4/typeChecking/typeChecker.h" @@ -59,7 +60,7 @@ control c(inout bit x) { */ class DoRemoveReturns : public Transform { protected: - P4::ReferenceMap *refMap; + MinimalNameGenerator nameGen; IR::ID returnVar; // one for each context IR::ID returnedValue; // only for functions that return expressions cstring variableName; @@ -78,11 +79,9 @@ class DoRemoveReturns : public Transform { } public: - explicit DoRemoveReturns(P4::ReferenceMap *refMap, cstring varName = "hasReturned"_cs, - cstring retValName = "retval"_cs) - : refMap(refMap), variableName(varName), retValName(retValName) { + explicit DoRemoveReturns(cstring varName = "hasReturned"_cs, cstring retValName = "retval"_cs) + : variableName(varName), retValName(retValName) { visitDagOnce = false; - CHECK_NULL(refMap); setName("DoRemoveReturns"); } @@ -101,13 +100,13 @@ class DoRemoveReturns : public Transform { } const IR::Node *postorder(IR::LoopStatement *loop) override; + profile_t init_apply(const IR::Node *node) override; }; class RemoveReturns : public PassManager { public: - explicit RemoveReturns(ReferenceMap *refMap) { - passes.push_back(new ResolveReferences(refMap)); - passes.push_back(new DoRemoveReturns(refMap)); + RemoveReturns() { + passes.push_back(new DoRemoveReturns()); setName("RemoveReturns"); } }; diff --git a/frontends/p4/resetHeaders.h b/frontends/p4/resetHeaders.h index 44654ee947..985cd4630a 100644 --- a/frontends/p4/resetHeaders.h +++ b/frontends/p4/resetHeaders.h @@ -72,8 +72,8 @@ class DoResetHeaders : public Transform { /// Invokes TypeChecking followed by DoResetHeaders. class ResetHeaders : public PassManager { public: - ResetHeaders(ReferenceMap *refMap, TypeMap *typeMap) { - passes.push_back(new P4::TypeChecking(refMap, typeMap)); + explicit ResetHeaders(TypeMap *typeMap) { + passes.push_back(new P4::TypeChecking(nullptr, typeMap)); passes.push_back(new P4::DoResetHeaders(typeMap)); setName("ResetHeaders"); } diff --git a/frontends/p4/setHeaders.h b/frontends/p4/setHeaders.h index ccf9fc4d6a..1b31894957 100644 --- a/frontends/p4/setHeaders.h +++ b/frontends/p4/setHeaders.h @@ -46,7 +46,6 @@ of tuples passed as arguments to functions expecting headers, reducing them to assignments. */ class DoSetHeaders final : public Transform { - ReferenceMap *refMap; TypeMap *typeMap; bool containsHeaderType(const IR::Type *type); @@ -54,8 +53,7 @@ class DoSetHeaders final : public Transform { const IR::Type *destType, IR::Vector *insert); public: - DoSetHeaders(ReferenceMap *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap) { - CHECK_NULL(refMap); + explicit DoSetHeaders(TypeMap *typeMap) : typeMap(typeMap) { CHECK_NULL(typeMap); setName("DoSetHeaders"); } @@ -64,9 +62,9 @@ class DoSetHeaders final : public Transform { class SetHeaders final : public PassManager { public: - SetHeaders(ReferenceMap *refMap, TypeMap *typeMap) { - passes.push_back(new P4::TypeChecking(refMap, typeMap)); - passes.push_back(new P4::DoSetHeaders(refMap, typeMap)); + explicit SetHeaders(TypeMap *typeMap) { + passes.push_back(new P4::TypeChecking(nullptr, typeMap)); + passes.push_back(new P4::DoSetHeaders(typeMap)); setName("SetHeaders"); } }; diff --git a/frontends/p4/sideEffects.cpp b/frontends/p4/sideEffects.cpp index be3a14b511..9555572ca7 100644 --- a/frontends/p4/sideEffects.cpp +++ b/frontends/p4/sideEffects.cpp @@ -16,16 +16,20 @@ limitations under the License. #include "frontends/p4/sideEffects.h" +#include "frontends/common/resolveReferences/referenceMap.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/alias.h" #include "frontends/p4/cloner.h" #include "frontends/p4/tableApply.h" +#include "ir/node.h" +#include "ir/visitor.h" namespace P4 { cstring DoSimplifyExpressions::createTemporary(const IR::Type *type) { type = type->getP4Type(); BUG_CHECK(type && !type->is(), "Can't create don't-care temps"); - auto tmp = refMap->newName("tmp"); + auto tmp = nameGen.newName("tmp"); auto decl = new IR::Declaration_Variable(IR::ID(tmp, nullptr), type); toInsert.push_back(decl); return tmp; @@ -66,7 +70,7 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::Literal *expression) { const IR::Node *DoSimplifyExpressions::preorder(IR::ArrayIndex *expression) { LOG3("Visiting " << dbp(expression)); auto type = typeMap->getType(getOriginal(), true); - if (SideEffects::check(getOriginal(), this, refMap, typeMap) || + if (SideEffects::check(getOriginal(), this, this, typeMap) || // if the expression appears as part of an argument also use a temporary for the index findContext() != nullptr) { visit(expression->left); @@ -100,7 +104,7 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::Member *expression) { LOG3("Visiting " << dbp(expression)); auto type = typeMap->getType(getOriginal(), true); const IR::Expression *rv = expression; - if (SideEffects::check(getOriginal(), this, refMap, typeMap) || + if (SideEffects::check(getOriginal(), this, this, typeMap) || // This may be part of a left-value that is passed as an out argument findContext() != nullptr) { visit(expression->expr); @@ -108,8 +112,8 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::Member *expression) { // Special case for table.apply().hit/miss, which is not dismantled by // the MethodCallExpression. - if (TableApplySolver::isHit(expression, refMap, typeMap) || - TableApplySolver::isMiss(expression, refMap, typeMap)) { + if (TableApplySolver::isHit(expression, this, typeMap) || + TableApplySolver::isMiss(expression, this, typeMap)) { if (isIfContext(getContext())) { /* if the hit/miss test is directly in an "if", don't bother cloning it * as that will just create a redundant table later */ @@ -154,7 +158,7 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::StructExpression *expression LOG3("Visiting " << dbp(expression)); bool foundEffect = false; for (auto v : expression->components) { - if (SideEffects::check(v->expression, this, refMap, typeMap)) { + if (SideEffects::check(v->expression, this, this, typeMap)) { foundEffect = true; break; } @@ -182,7 +186,7 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::ListExpression *expression) LOG3("Visiting " << dbp(expression)); bool foundEffect = false; for (auto v : expression->components) { - if (SideEffects::check(v, this, refMap, typeMap)) { + if (SideEffects::check(v, this, this, typeMap)) { foundEffect = true; break; } @@ -207,8 +211,8 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::Operation_Binary *expression LOG3("Visiting " << dbp(expression)); auto original = getOriginal(); auto type = typeMap->getType(original, true); - if (SideEffects::check(original, this, refMap, typeMap)) { - if (SideEffects::check(original->right, this, refMap, typeMap)) { + if (SideEffects::check(original, this, this, typeMap)) { + if (SideEffects::check(original->right, this, this, typeMap)) { // We are a bit conservative here. We handle this case: // T f(inout T val) { ... } // val + f(val); @@ -239,7 +243,7 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::Operation_Binary *expression const IR::Node *DoSimplifyExpressions::shortCircuit(IR::Operation_Binary *expression) { LOG3("Visiting " << dbp(expression)); auto type = typeMap->getType(getOriginal(), true); - if (SideEffects::check(getOriginal(), this, refMap, typeMap)) { + if (SideEffects::check(getOriginal(), this, this, typeMap)) { visit(expression->left); CHECK_NULL(expression->left); @@ -314,10 +318,11 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::LOr *expression) { return shortCircuit(expression); } -bool DoSimplifyExpressions::mayAlias(const IR::Expression *left, - const IR::Expression *right) const { - ReadsWrites rw(refMap); - return rw.mayAlias(left, right); +bool DoSimplifyExpressions::mayAlias(const IR::Expression *left, const IR::Expression *right, + const Visitor::Context *ctxt) const { + // FIXME: This recreates ReadWrites() over and over again, loosing all + // declaration lookup caching + return ReadsWrites().mayAlias(left, right, ctxt); } /// Returns true if type is a header or a struct containing a header. @@ -339,8 +344,7 @@ namespace { /// modified while evaluating the expression. This is a list of /// left-values. Also, a table application expression is /// assumed to modify everything. -class GetWrittenExpressions : public Inspector { - ReferenceMap *refMap; +class GetWrittenExpressions : public Inspector, public ResolutionContext { TypeMap *typeMap; public: @@ -353,14 +357,12 @@ class GetWrittenExpressions : public Inspector { static const IR::Expression *everything; std::set written; - GetWrittenExpressions(ReferenceMap *refMap, TypeMap *typeMap) - : refMap(refMap), typeMap(typeMap) { - CHECK_NULL(refMap); + explicit GetWrittenExpressions(TypeMap *typeMap) : typeMap(typeMap) { CHECK_NULL(typeMap); setName("GetWrittenExpressions"); } void postorder(const IR::MethodCallExpression *expression) override { - auto mi = MethodInstance::resolve(expression, refMap, typeMap); + auto mi = MethodInstance::resolve(expression, this, typeMap); if (auto a = mi->to()) { if (a->isTableApply()) { written.emplace(everything); @@ -389,13 +391,13 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::MethodCallExpression *mce) { LOG3("Visiting " << dbp(mce)); auto orig = getOriginal(); auto type = typeMap->getType(orig, true); - if (!SideEffects::check(orig, this, refMap, typeMap)) { + if (!SideEffects::check(orig, this, this, typeMap)) { return mce; } auto copyBack = new IR::IndexedVector(); auto args = new IR::Vector(); - auto mi = MethodInstance::resolve(orig, refMap, typeMap); + auto mi = MethodInstance::resolve(orig, this, typeMap); // If a parameter is in this set then we use a temporary to // copy the corresponding argument. We could always use @@ -406,9 +408,11 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::MethodCallExpression *mce) { std::set useTemporary; // Set of expressions modified while evaluating this method call. std::set modifies; - GetWrittenExpressions gwe(refMap, typeMap); + // FIXME: We need to be able to cache results here and not to recompute over + // and over again + GetWrittenExpressions gwe(typeMap); gwe.setCalledBy(this); - mce->apply(gwe); + mce->apply(gwe, getContext()); for (auto p : *mi->substitution.getParametersInArgumentOrder()) { if (p->direction == IR::Direction::None) continue; @@ -423,7 +427,7 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::MethodCallExpression *mce) { // If an argument evaluation has side-effects then // always use a temporary to hold the argument value. - if (SideEffects::check(arg->expression, this, refMap, typeMap)) { + if (SideEffects::check(arg->expression, this, this, typeMap)) { LOG3("Using temporary for " << dbp(mce) << " param " << dbp(p) << " arg side effect"); useTemporary.emplace(p); continue; @@ -463,7 +467,7 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::MethodCallExpression *mce) { for (auto e : modifies) { // Here we use just raw equality: equivalent but not equal expressions // should be compared. - if (e != arg->expression && mayAlias(arg->expression, e)) { + if (e != arg->expression && mayAlias(arg->expression, e, getContext())) { LOG3("Using temporary for " << dbp(mce) << " param " << dbp(p) << " aliasing" << dbp(e)); if (p->hasOut()) @@ -535,9 +539,9 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::MethodCallExpression *mce) { // dismantle these expressions. bool tbl_apply = false; if (auto mmbr = getParent()) { - auto tbl = TableApplySolver::isActionRun(mmbr, refMap, typeMap); - auto tbl1 = TableApplySolver::isHit(mmbr, refMap, typeMap); - auto tbl2 = TableApplySolver::isMiss(mmbr, refMap, typeMap); + auto tbl = TableApplySolver::isActionRun(mmbr, this, typeMap); + auto tbl1 = TableApplySolver::isHit(mmbr, this, typeMap); + auto tbl2 = TableApplySolver::isMiss(mmbr, this, typeMap); tbl_apply = tbl != nullptr || tbl1 != nullptr || tbl2 != nullptr; } // Simplified method call, with arguments substituted @@ -704,6 +708,13 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::ForInStatement *statement) { return rv; } +Visitor::profile_t DoSimplifyExpressions::init_apply(const IR::Node *node) { + auto rv = Transform::init_apply(node); + node->apply(nameGen); + + return rv; +} + void DoSimplifyExpressions::end_apply(const IR::Node *) { BUG_CHECK(toInsert.empty(), "DoSimplifyExpressions::end_apply orphaned declarations"); BUG_CHECK(statements.empty(), "DoSimplifyExpressions::end_apply orphaned statements"); @@ -711,13 +722,21 @@ void DoSimplifyExpressions::end_apply(const IR::Node *) { /////////////////////////////////////////////// +Visitor::profile_t KeySideEffect::init_apply(const IR::Node *node) { + auto rv = Transform::init_apply(node); + node->apply(nameGen); + + return rv; +} + const IR::Node *KeySideEffect::preorder(IR::Key *key) { // If any key field has side effects then pull out all // the key field values. LOG3("Visiting " << key); bool complex = false; for (auto k : key->keyElements) - complex = complex || P4::SideEffects::check(k->expression, this, refMap, typeMap); + complex = + complex || P4::SideEffects::check(k->expression, this, this, typeMap, getContext()); if (!complex) // This prune will prevent the postoder(IR::KeyElement*) below from executing prune(); @@ -740,7 +759,7 @@ const IR::Node *KeySideEffect::postorder(IR::KeyElement *element) { insertions = it->second; } - auto tmp = refMap->newName("key"); + auto tmp = nameGen.newName("key"); auto type = typeMap->getType(element->expression, true); auto decl = new IR::Declaration_Variable(tmp, type, nullptr); insertions->declarations.push_back(decl); @@ -778,11 +797,12 @@ const IR::Node *KeySideEffect::postorder(IR::P4Table *table) { } const IR::Node *KeySideEffect::doStatement(const IR::Statement *statement, - const IR::Expression *expression) { + const IR::Expression *expression, + const Visitor::Context *ctxt) { LOG3("Visiting " << getOriginal()); - HasTableApply hta(refMap, typeMap); + HasTableApply hta(this, typeMap); hta.setCalledBy(this); - (void)expression->apply(hta); + (void)expression->apply(hta, ctxt); if (hta.table == nullptr) return statement; auto insertions = get(toInsert, hta.table); if (insertions == nullptr) return statement; diff --git a/frontends/p4/sideEffects.h b/frontends/p4/sideEffects.h index f8832a1940..b04cdb1307 100644 --- a/frontends/p4/sideEffects.h +++ b/frontends/p4/sideEffects.h @@ -20,6 +20,7 @@ limitations under the License. /* makes explicit side effect ordering */ #include "frontends/common/resolveReferences/referenceMap.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/methodInstance.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "ir/ir.h" @@ -28,13 +29,13 @@ namespace P4 { /// Checks to see whether an IR node includes a table.apply() sub-expression class HasTableApply : public Inspector { - ReferenceMap *refMap; + DeclarationLookup *refMap; TypeMap *typeMap; public: const IR::P4Table *table; const IR::MethodCallExpression *call; - HasTableApply(ReferenceMap *refMap, TypeMap *typeMap) + HasTableApply(DeclarationLookup *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap), table(nullptr), call(nullptr) { CHECK_NULL(refMap); CHECK_NULL(typeMap); @@ -63,7 +64,7 @@ class HasTableApply : public Inspector { */ class SideEffects : public Inspector { private: - ReferenceMap *refMap; + DeclarationLookup *refMap; TypeMap *typeMap; public: @@ -100,20 +101,21 @@ class SideEffects : public Inspector { /// The @refMap and @typeMap arguments can be null, in which case the check /// will be more conservative. - SideEffects(ReferenceMap *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap) { + SideEffects(DeclarationLookup *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap) { setName("SideEffects"); } /// @return true if the expression may have side-effects. static bool check(const IR::Expression *expression, const Visitor *calledBy, - ReferenceMap *refMap, TypeMap *typeMap) { + DeclarationLookup *refMap, TypeMap *typeMap, + const Visitor::Context *ctxt = nullptr) { SideEffects se(refMap, typeMap); se.setCalledBy(calledBy); - expression->apply(se); + expression->apply(se, ctxt); return se.nodeWithSideEffect != nullptr; } /// @return true if the method call expression may have side-effects. - static bool hasSideEffect(const IR::MethodCallExpression *mce, ReferenceMap *refMap, + static bool hasSideEffect(const IR::MethodCallExpression *mce, DeclarationLookup *refMap, TypeMap *typeMap) { // mce does not produce a side effect in few cases: // * isValid() @@ -178,8 +180,8 @@ a[tmp1].x = tmp4; // assign result of call of f to actual left value * For assignment statements ```e = e1;``` the left hand side is evaluated * first. */ -class DoSimplifyExpressions : public Transform, P4WriteContext { - ReferenceMap *refMap; +class DoSimplifyExpressions : public Transform, P4WriteContext, public ResolutionContext { + MinimalNameGenerator nameGen; TypeMap *typeMap; // Expressions holding temporaries that are already added. std::set *added; @@ -193,14 +195,13 @@ class DoSimplifyExpressions : public Transform, P4WriteContext { cstring createTemporary(const IR::Type *type); const IR::Expression *addAssignment(Util::SourceInfo srcInfo, cstring varName, const IR::Expression *expression); - bool mayAlias(const IR::Expression *left, const IR::Expression *right) const; + bool mayAlias(const IR::Expression *left, const IR::Expression *right, + const Visitor::Context *ctxt) const; bool containsHeaderType(const IR::Type *type); public: - DoSimplifyExpressions(ReferenceMap *refMap, TypeMap *typeMap, - std::set *added) - : refMap(refMap), typeMap(typeMap), added(added) { - CHECK_NULL(refMap); + DoSimplifyExpressions(TypeMap *typeMap, std::set *added) + : typeMap(typeMap), added(added) { CHECK_NULL(typeMap); setName("DoSimplifyExpressions"); } @@ -246,6 +247,7 @@ class DoSimplifyExpressions : public Transform, P4WriteContext { const IR::Node *preorder(IR::ForStatement *statement) override; const IR::Node *preorder(IR::ForInStatement *statement) override; + profile_t init_apply(const IR::Node *node) override; void end_apply(const IR::Node *) override; }; @@ -293,40 +295,42 @@ class TableInsertions { * @pre none * @post all complex table key expressions are replaced with a simpler expression. */ -class KeySideEffect : public Transform { +class KeySideEffect : public Transform, public ResolutionContext { protected: - ReferenceMap *refMap; + MinimalNameGenerator nameGen; TypeMap *typeMap; std::map toInsert; std::set *invokedInKey; public: - KeySideEffect(ReferenceMap *refMap, TypeMap *typeMap, - std::set *invokedInKey) - : refMap(refMap), typeMap(typeMap), invokedInKey(invokedInKey) { - CHECK_NULL(refMap); + KeySideEffect(TypeMap *typeMap, std::set *invokedInKey) + : typeMap(typeMap), invokedInKey(invokedInKey) { CHECK_NULL(typeMap); CHECK_NULL(invokedInKey); setName("KeySideEffect"); } + + profile_t init_apply(const IR::Node *node) override; + virtual const IR::Node *doStatement(const IR::Statement *statement, - const IR::Expression *expression); + const IR::Expression *expression, + const Visitor::Context *ctxt); const IR::Node *preorder(IR::Key *key) override; // These should be all kinds of statements that may contain a table apply // after the program has been simplified const IR::Node *postorder(IR::MethodCallStatement *statement) override { - return doStatement(statement, statement->methodCall); + return doStatement(statement, statement->methodCall, getContext()); } const IR::Node *postorder(IR::IfStatement *statement) override { - return doStatement(statement, statement->condition); + return doStatement(statement, statement->condition, getContext()); } const IR::Node *postorder(IR::SwitchStatement *statement) override { - return doStatement(statement, statement->expression); + return doStatement(statement, statement->expression, getContext()); } const IR::Node *postorder(IR::AssignmentStatement *statement) override { - return doStatement(statement, statement->right); + return doStatement(statement, statement->right, getContext()); } const IR::Node *postorder(IR::KeyElement *element) override; const IR::Node *postorder(IR::P4Table *table) override; @@ -338,15 +342,13 @@ class KeySideEffect : public Transform { /// table Y { ... } /// table X { key = { ... Y.apply.hit() ... } } /// This inserts Y into the map invokedInKey; -class TablesInKeys : public Inspector { - ReferenceMap *refMap; +class TablesInKeys : public Inspector, ResolutionContext { TypeMap *typeMap; std::set *invokedInKey; public: - TablesInKeys(ReferenceMap *refMap, TypeMap *typeMap, - std::set *invokedInKey) - : refMap(refMap), typeMap(typeMap), invokedInKey(invokedInKey) { + TablesInKeys(TypeMap *typeMap, std::set *invokedInKey) + : typeMap(typeMap), invokedInKey(invokedInKey) { CHECK_NULL(invokedInKey); setName("TableInKeys"); } @@ -356,9 +358,9 @@ class TablesInKeys : public Inspector { } void postorder(const IR::MethodCallExpression *mce) override { if (!findContext()) return; - HasTableApply hta(refMap, typeMap); + HasTableApply hta(this, typeMap); hta.setCalledBy(this); - (void)mce->apply(hta); + (void)mce->apply(hta, getContext()); if (hta.table != nullptr) { LOG2("Table " << hta.table << " invoked in key of another table"); invokedInKey->emplace(hta.table); @@ -371,17 +373,16 @@ class TablesInKeys : public Inspector { /// table s { ... } /// table t { /// actions { a(s.apply().hit ? ... ); } -class TablesInActions : public Inspector { - ReferenceMap *refMap; +class TablesInActions : public Inspector, ResolutionContext { TypeMap *typeMap; public: - TablesInActions(ReferenceMap *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap) {} + explicit TablesInActions(TypeMap *typeMap) : typeMap(typeMap) {} void postorder(const IR::MethodCallExpression *expression) override { if (findContext()) { - HasTableApply hta(refMap, typeMap); + HasTableApply hta(this, typeMap); hta.setCalledBy(this); - (void)expression->apply(hta); + (void)expression->apply(hta, getContext()); if (hta.table != nullptr) { ::error(ErrorType::ERR_UNSUPPORTED, "%1%: table invocation in action argument", expression); @@ -400,16 +401,16 @@ class SideEffectOrdering : public PassRepeated { std::set added; public: - SideEffectOrdering(ReferenceMap *refMap, TypeMap *typeMap, bool skipSideEffectOrdering, + SideEffectOrdering(TypeMap *typeMap, bool skipSideEffectOrdering, TypeChecking *typeChecking = nullptr) { - if (!typeChecking) typeChecking = new TypeChecking(refMap, typeMap); + if (!typeChecking) typeChecking = new TypeChecking(nullptr, typeMap); if (!skipSideEffectOrdering) { - passes.push_back(new TypeChecking(refMap, typeMap)); - passes.push_back(new DoSimplifyExpressions(refMap, typeMap, &added)); + passes.push_back(new TypeChecking(nullptr, typeMap)); + passes.push_back(new DoSimplifyExpressions(typeMap, &added)); passes.push_back(typeChecking); - passes.push_back(new TablesInActions(refMap, typeMap)); - passes.push_back(new TablesInKeys(refMap, typeMap, &invokedInKey)); - passes.push_back(new KeySideEffect(refMap, typeMap, &invokedInKey)); + passes.push_back(new TablesInActions(typeMap)); + passes.push_back(new TablesInKeys(typeMap, &invokedInKey)); + passes.push_back(new KeySideEffect(typeMap, &invokedInKey)); } setName("SideEffectOrdering"); } diff --git a/frontends/p4/simplify.cpp b/frontends/p4/simplify.cpp index b092bf63f5..c035469d49 100644 --- a/frontends/p4/simplify.cpp +++ b/frontends/p4/simplify.cpp @@ -65,7 +65,8 @@ const IR::Node *DoSimplifyControlFlow::postorder(IR::IfStatement *statement) { statement->ifTrue = e; } - if (SideEffects::check(statement->condition, this, refMap, typeMap)) return statement; + if (SideEffects::check(statement->condition, this, this, typeMap, getChildContext())) + return statement; if (statement->ifTrue->is() && (statement->ifFalse == nullptr || statement->ifFalse->is())) return new IR::EmptyStatement(statement->srcInfo); @@ -87,13 +88,13 @@ const IR::Node *DoSimplifyControlFlow::postorder(IR::SwitchStatement *statement) if (statement->cases.empty()) { // If this is a table application remove the switch altogether but keep // the table application. Otherwise remove the switch altogether. - if (TableApplySolver::isActionRun(statement->expression, refMap, typeMap)) { + if (TableApplySolver::isActionRun(statement->expression, this, typeMap)) { auto mce = statement->expression->checkedTo() ->expr->checkedTo(); LOG2("Removing switch statement " << statement << " keeping " << mce); return new IR::MethodCallStatement(statement->srcInfo, mce); } - if (SideEffects::check(statement->expression, this, refMap, typeMap)) + if (SideEffects::check(statement->expression, this, this, typeMap, getChildContext())) // This can happen if this pass is run before SideEffectOrdering. return statement; LOG2("Removing switch statement " << statement); diff --git a/frontends/p4/simplify.h b/frontends/p4/simplify.h index 494e8b7ff1..620f3261f2 100644 --- a/frontends/p4/simplify.h +++ b/frontends/p4/simplify.h @@ -48,14 +48,11 @@ namespace P4 { * * @pre An up-to-date ReferenceMap and TypeMap. */ -class DoSimplifyControlFlow : public Transform { - ReferenceMap *refMap; +class DoSimplifyControlFlow : public Transform, public ResolutionContext { TypeMap *typeMap; public: - DoSimplifyControlFlow(ReferenceMap *refMap, TypeMap *typeMap) - : refMap(refMap), typeMap(typeMap) { - CHECK_NULL(refMap); + explicit DoSimplifyControlFlow(TypeMap *typeMap) : typeMap(typeMap) { CHECK_NULL(typeMap); setName("DoSimplifyControlFlow"); // We may want to replace the same statement with different things @@ -72,11 +69,10 @@ class DoSimplifyControlFlow : public Transform { /// steps enable further simplification. class SimplifyControlFlow : public PassRepeated { public: - SimplifyControlFlow(ReferenceMap *refMap, TypeMap *typeMap, - TypeChecking *typeChecking = nullptr) { - if (!typeChecking) typeChecking = new TypeChecking(refMap, typeMap); + explicit SimplifyControlFlow(TypeMap *typeMap, TypeChecking *typeChecking = nullptr) { + if (!typeChecking) typeChecking = new TypeChecking(nullptr, typeMap); passes.push_back(typeChecking); - passes.push_back(new DoSimplifyControlFlow(refMap, typeMap)); + passes.push_back(new DoSimplifyControlFlow(typeMap)); setName("SimplifyControlFlow"); } }; diff --git a/frontends/p4/simplifySwitch.h b/frontends/p4/simplifySwitch.h index f6e36ed209..bbb3bbe8e7 100644 --- a/frontends/p4/simplifySwitch.h +++ b/frontends/p4/simplifySwitch.h @@ -41,8 +41,8 @@ class DoSimplifySwitch : public Transform { class SimplifySwitch : public PassManager { public: - SimplifySwitch(ReferenceMap *refMap, TypeMap *typeMap) { - passes.push_back(new TypeChecking(refMap, typeMap)); + explicit SimplifySwitch(TypeMap *typeMap) { + passes.push_back(new TypeChecking(nullptr, typeMap)); passes.push_back(new DoSimplifySwitch(typeMap)); setName("SimplifySwitch"); } diff --git a/frontends/p4/specialize.cpp b/frontends/p4/specialize.cpp index 41643c5e34..a6edf0fcab 100644 --- a/frontends/p4/specialize.cpp +++ b/frontends/p4/specialize.cpp @@ -16,26 +16,31 @@ limitations under the License. #include "specialize.h" -#include - +#include "frontends/common/constantFolding.h" +#include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/p4/enumInstance.h" #include "frontends/p4/evaluator/substituteParameters.h" #include "frontends/p4/frontend.h" #include "frontends/p4/methodInstance.h" #include "frontends/p4/parameterSubstitution.h" -#include "frontends/p4/toP4/toP4.h" #include "frontends/p4/unusedDeclarations.h" +#include "ir/visitor.h" namespace P4 { -const IR::Type_Declaration *SpecializationInfo::synthesize(ReferenceMap *refMap) const { +const IR::Type_Declaration *SpecializationInfo::synthesize(const Visitor::Context *ctxt) const { TypeVariableSubstitution tvs; ParameterSubstitution subst; subst.populate(specialized->getConstructorParameters(), constructorArguments); tvs.setBindings(invocation, specialized->getTypeParameters(), typeArguments); - SubstituteParameters sp(refMap, &subst, &tvs); - auto clone = specialized->getNode()->apply(sp); + // FIXME: SubstituteParameters is a ResolutionContext, but we are recreating + // it again and again killing lookup caches. We'd need to have instead some + // separate DeclarationLookup that would allow us to perform necessary + // lookups in the context of callee. We can probably pre-seed it first for + // all possible callees in specMap. + SubstituteParameters sp(nullptr, &subst, &tvs); + auto clone = specialized->getNode()->apply(sp, ctxt); CHECK_NULL(clone); const IR::Type_Declaration *result = nullptr; if (auto parser = clone->to()) { @@ -59,12 +64,11 @@ const IR::Type_Declaration *SpecializationInfo::synthesize(ReferenceMap *refMap) return result; } -const IR::Argument *SpecializationMap::convertArgument(const IR::Argument *arg, - SpecializationInfo *spec, - const IR::Parameter *param) { +static const IR::Argument *convertArgument(const IR::Argument *arg, SpecializationInfo *spec, + const IR::Parameter *param, NameGenerator *nameGen) { if (arg->expression->is()) { auto cce = arg->expression->to(); - cstring nName = refMap->newName(param->name.name.string_view()); + cstring nName = nameGen->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); @@ -77,22 +81,23 @@ const IR::Argument *SpecializationMap::convertArgument(const IR::Argument *arg, } void SpecializationMap::addSpecialization(const IR::ConstructorCallExpression *invocation, - const IR::IContainer *cont, const IR::Node *insertion) { + const IR::IContainer *cont, const IR::Node *insertion, + DeclarationLookup *declLookup, NameGenerator *nameGen) { LOG2("Will specialize " << dbp(invocation) << " of " << dbp(cont->getNode()) << " " << cont->getNode() << " inserted after " << insertion); auto spec = new SpecializationInfo(invocation, cont, insertion); auto declaration = cont->to(); CHECK_NULL(declaration); - spec->name = refMap->newName(declaration->getName().name.string_view()); - auto cc = ConstructorCall::resolve(invocation, refMap, typeMap); + spec->name = nameGen->newName(declaration->getName().name.string_view()); + auto cc = ConstructorCall::resolve(invocation, declLookup, typeMap); auto ccc = cc->to(); CHECK_NULL(ccc); spec->constructorArguments = new IR::Vector(); for (auto ca : *invocation->arguments) { auto param = cc->substitution.findParameter(ca); CHECK_NULL(param); - auto arg = convertArgument(ca, spec, param); + auto arg = convertArgument(ca, spec, param, nameGen); spec->constructorArguments->push_back(arg); } spec->typeArguments = ccc->typeArguments; @@ -100,14 +105,15 @@ void SpecializationMap::addSpecialization(const IR::ConstructorCallExpression *i } void SpecializationMap::addSpecialization(const IR::Declaration_Instance *invocation, - const IR::IContainer *cont, const IR::Node *insertion) { + const IR::IContainer *cont, const IR::Node *insertion, + DeclarationLookup *declLookup, NameGenerator *nameGen) { LOG2("Will specialize " << dbp(invocation) << " of " << dbp(cont->getNode()) << " inserted after " << insertion); auto spec = new SpecializationInfo(invocation, cont, insertion); auto declaration = cont->to(); CHECK_NULL(declaration); - spec->name = refMap->newName(declaration->getName().name.string_view()); + spec->name = nameGen->newName(declaration->getName().name.string_view()); const IR::Type_Name *type; const IR::Vector *typeArgs; if (invocation->type->is()) { @@ -118,25 +124,26 @@ void SpecializationMap::addSpecialization(const IR::Declaration_Instance *invoca type = invocation->type->to(); typeArgs = new IR::Vector(); } - Instantiation *inst = Instantiation::resolve(invocation, refMap, typeMap); + Instantiation *inst = Instantiation::resolve(invocation, declLookup, typeMap); spec->typeArguments = typeArgs; CHECK_NULL(type); for (auto ca : *invocation->arguments) { auto param = inst->substitution.findParameter(ca); CHECK_NULL(param); - auto arg = convertArgument(ca, spec, param); + auto arg = convertArgument(ca, spec, param, nameGen); spec->constructorArguments->push_back(arg); } specializations.emplace(invocation, spec); } -IR::Vector *SpecializationMap::getSpecializations(const IR::Node *insertionPoint) const { +IR::Vector *SpecializationMap::getSpecializations(const IR::Node *insertionPoint, + const Visitor::Context *ctxt) const { IR::Vector *result = nullptr; for (auto s : specializations) { if (s.second->insertBefore == insertionPoint) { if (result == nullptr) result = new IR::Vector(); - auto node = s.second->synthesize(refMap); + auto node = s.second->synthesize(ctxt); LOG2("Will insert " << node << " before " << insertionPoint); result->push_back(node); } @@ -207,7 +214,7 @@ void FindSpecializations::postorder(const IR::ConstructorCallExpression *express !expression->constructedType->is()) return; // nothing to specialize - auto cc = ConstructorCall::resolve(expression, specMap->refMap, specMap->typeMap); + auto cc = ConstructorCall::resolve(expression, this, specMap->typeMap); if (!cc->is()) return; for (auto arg : *expression->arguments) { if (!isSimpleConstant(arg->expression)) return; @@ -216,7 +223,7 @@ void FindSpecializations::postorder(const IR::ConstructorCallExpression *express auto insert = findInsertionPoint(); auto decl = cc->to()->container; if (decl->is()) return; - specMap->addSpecialization(expression, decl, insert); + specMap->addSpecialization(expression, decl, insert, this, &nameGen); } void FindSpecializations::postorder(const IR::Declaration_Instance *decl) { @@ -241,15 +248,15 @@ void FindSpecializations::postorder(const IR::Declaration_Instance *decl) { BUG_CHECK(decl->type->is(), "%1%: unexpected type", decl->type); contDecl = decl->type->to()->baseType; } - auto cont = specMap->refMap->getDeclaration(contDecl->path, true); + auto cont = getDeclaration(contDecl->path, true); if (!cont->is() && !cont->is()) return; auto insert = findInsertionPoint(); if (insert == nullptr) insert = decl; - specMap->addSpecialization(decl, cont->to(), insert); + specMap->addSpecialization(decl, cont->to(), insert, this, &nameGen); } -const IR::Node *Specialize::instantiate(const IR::Node *node) { - auto specs = specMap->getSpecializations(getOriginal()); +const IR::Node *Specialize::instantiate(const IR::Node *node, const Visitor::Context *ctxt) { + auto specs = specMap->getSpecializations(getOriginal(), ctxt); if (specs == nullptr) return node; LOG2(specs->size() << " instantiations before " << node); specs->push_back(node); @@ -277,19 +284,18 @@ const IR::Node *Specialize::postorder(IR::Declaration_Instance *decl) { LOG2("Replaced " << decl << " with " << replacement); } - return instantiate(replacement); + return instantiate(replacement, getContext()); } SpecializeAll::SpecializeAll(ReferenceMap *refMap, TypeMap *typeMap, FrontEndPolicy *policy) : PassRepeated({}) { - passes.emplace_back(new ConstantFolding(refMap, typeMap, policy->getConstantFoldingPolicy())); - passes.emplace_back(new TypeChecking(refMap, typeMap)); + passes.emplace_back(new ConstantFolding(typeMap, policy->getConstantFoldingPolicy())); + passes.emplace_back(new TypeChecking(nullptr, typeMap)); passes.emplace_back(new FindSpecializations(&specMap)); passes.emplace_back(new Specialize(&specMap)); + passes.emplace_back(new TypeInference(typeMap, false)); // more casts may be needed passes.emplace_back(new ResolveReferences(refMap)); - passes.emplace_back(new TypeInference(refMap, typeMap, false)); // more casts may be needed passes.emplace_back(new RemoveAllUnusedDeclarations(refMap, *policy)); - specMap.refMap = refMap; specMap.typeMap = typeMap; setName("SpecializeAll"); } diff --git a/frontends/p4/specialize.h b/frontends/p4/specialize.h index c1aa58c08c..80b837dd3e 100644 --- a/frontends/p4/specialize.h +++ b/frontends/p4/specialize.h @@ -17,10 +17,11 @@ limitations under the License. #ifndef FRONTENDS_P4_SPECIALIZE_H_ #define FRONTENDS_P4_SPECIALIZE_H_ -#include "frontends/common/constantFolding.h" #include "frontends/common/resolveReferences/referenceMap.h" -#include "frontends/p4/typeChecking/typeChecker.h" +#include "frontends/common/resolveReferences/resolveReferences.h" +#include "frontends/p4/typeMap.h" #include "ir/ir.h" +#include "ir/pass_manager.h" namespace P4 { @@ -55,19 +56,16 @@ struct SpecializationInfo { CHECK_NULL(invocation); CHECK_NULL(insertion); } - const IR::Type_Declaration *synthesize(ReferenceMap *refMap) const; + const IR::Type_Declaration *synthesize(const Visitor::Context *ctxt) const; }; /// Maintains a map from invocation to a SpecializationInfo object. class SpecializationMap { /// Maps invocation to specialization info. ordered_map specializations; - const IR::Argument *convertArgument(const IR::Argument *arg, SpecializationInfo *info, - const IR::Parameter *param); public: TypeMap *typeMap = nullptr; - ReferenceMap *refMap = nullptr; /** Add a specialization instance. * * @param invocation The constructor invocation. @@ -75,7 +73,8 @@ class SpecializationMap { * @param insertion Where the specialization should be inserted. */ void addSpecialization(const IR::ConstructorCallExpression *invocation, - const IR::IContainer *container, const IR::Node *insertion); + const IR::IContainer *container, const IR::Node *insertion, + DeclarationLookup *declLookup, NameGenerator *nameGen); /** Add a specialization instance. * * @param invocation The constructor invocation. @@ -83,8 +82,10 @@ class SpecializationMap { * @param insertion Where the specialization should be inserted. */ void addSpecialization(const IR::Declaration_Instance *invocation, - const IR::IContainer *container, const IR::Node *insertion); - IR::Vector *getSpecializations(const IR::Node *insertion) const; + const IR::IContainer *container, const IR::Node *insertion, + DeclarationLookup *declLookup, NameGenerator *nameGen); + IR::Vector *getSpecializations(const IR::Node *insertion, + const Visitor::Context *ctxt) const; cstring getName(const IR::Node *insertion) const { auto s = ::get(specializations, insertion); if (s == nullptr) return nullptr; @@ -96,8 +97,9 @@ class SpecializationMap { /** Builds a SpecializationMap of instantiations with constant values for * type and constructor arguments. */ -class FindSpecializations : public Inspector { +class FindSpecializations : public Inspector, public ResolutionContext { SpecializationMap *specMap; + MinimalNameGenerator nameGen; public: explicit FindSpecializations(SpecializationMap *specMap) : specMap(specMap) { @@ -108,8 +110,12 @@ class FindSpecializations : public Inspector { const IR::Node *findInsertionPoint() const; bool isSimpleConstant(const IR::Expression *expression) const; Visitor::profile_t init_apply(const IR::Node *node) override { + auto rv = Inspector::init_apply(node); + specMap->clear(); - return Inspector::init_apply(node); + node->apply(nameGen); + + return rv; } /// True if this container does not have constructor or type /// parameters i.e., we can look inside for invocations to @@ -166,20 +172,24 @@ cspec() c_inst; */ class Specialize : public Transform { SpecializationMap *specMap; - const IR::Node *instantiate(const IR::Node *node); + const IR::Node *instantiate(const IR::Node *node, const Visitor::Context *ctxt); public: explicit Specialize(SpecializationMap *specMap) : specMap(specMap) { CHECK_NULL(specMap); setName("Specialize"); } - const IR::Node *postorder(IR::P4Parser *parser) override { return instantiate(parser); } + const IR::Node *postorder(IR::P4Parser *parser) override { + return instantiate(parser, getContext()); + } // skip packages const IR::Node *preorder(IR::Type_Package *package) override { prune(); return package; } - const IR::Node *postorder(IR::P4Control *control) override { return instantiate(control); } + const IR::Node *postorder(IR::P4Control *control) override { + return instantiate(control, getContext()); + } const IR::Node *postorder(IR::ConstructorCallExpression *expression) override; const IR::Node *postorder(IR::Declaration_Instance *) override; }; diff --git a/frontends/p4/specializeGenericFunctions.cpp b/frontends/p4/specializeGenericFunctions.cpp index c937bbb5e4..13cce7bd76 100644 --- a/frontends/p4/specializeGenericFunctions.cpp +++ b/frontends/p4/specializeGenericFunctions.cpp @@ -16,8 +16,18 @@ limitations under the License. #include "specializeGenericFunctions.h" +#include "frontends/p4/methodInstance.h" +#include "frontends/p4/typeChecking/typeSubstitutionVisitor.h" + namespace P4 { +Visitor::profile_t FindFunctionSpecializations::init_apply(const IR::Node *node) { + auto rv = Inspector::init_apply(node); + node->apply(nameGen); + + return rv; +} + bool FindFunctionSpecializations::preorder(const IR::MethodCallExpression *mce) { if (!mce->typeArguments->size()) return false; // We only specialize if the type arguments are not type variables @@ -33,10 +43,10 @@ bool FindFunctionSpecializations::preorder(const IR::MethodCallExpression *mce) if (!insert) insert = findContext(); if (!insert) insert = findContext(); CHECK_NULL(insert); - MethodInstance *mi = MethodInstance::resolve(mce, specMap->refMap, specMap->typeMap); + MethodInstance *mi = MethodInstance::resolve(mce, this, specMap->typeMap); if (auto func = mi->to()) { LOG3("Will specialize " << mce); - specMap->add(mce, func->function, insert); + specMap->add(mce, func->function, insert, &nameGen); } return false; } diff --git a/frontends/p4/specializeGenericFunctions.h b/frontends/p4/specializeGenericFunctions.h index 107342dc77..4f283f0bc4 100644 --- a/frontends/p4/specializeGenericFunctions.h +++ b/frontends/p4/specializeGenericFunctions.h @@ -18,6 +18,7 @@ limitations under the License. #define FRONTENDS_P4_SPECIALIZEGENERICFUNCTIONS_H_ #include "frontends/common/resolveReferences/referenceMap.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "ir/ir.h" @@ -50,18 +51,16 @@ struct FunctionSpecialization { }; struct FunctionSpecializationMap { - ReferenceMap *refMap; TypeMap *typeMap; ordered_map map; // Keep track of the values in the above map which are already // inserted in the program. std::set inserted; - void add(const IR::MethodCallExpression *mce, const IR::Function *func, - const IR::Node *insert) { - cstring name = refMap->newName(func->name.name.string_view()); - FunctionSpecialization *fs = new FunctionSpecialization(name, mce, func, insert); - map.emplace(mce, fs); + void add(const IR::MethodCallExpression *mce, const IR::Function *func, const IR::Node *insert, + NameGenerator *nameGen) { + cstring name = nameGen->newName(func->name.string_view()); + map.emplace(mce, new FunctionSpecialization(name, mce, func, insert)); } FunctionSpecialization *get(const IR::MethodCallExpression *mce) const { return ::get(map, mce); @@ -85,8 +84,9 @@ struct FunctionSpecializationMap { /** * Find all generic function invocations and their type arguments. */ -class FindFunctionSpecializations : public Inspector { +class FindFunctionSpecializations : public Inspector, public ResolutionContext { FunctionSpecializationMap *specMap; + MinimalNameGenerator nameGen; public: explicit FindFunctionSpecializations(FunctionSpecializationMap *specMap) : specMap(specMap) { @@ -95,6 +95,7 @@ class FindFunctionSpecializations : public Inspector { } bool preorder(const IR::MethodCallExpression *call) override; + profile_t init_apply(const IR::Node *node) override; }; /** @brief Specializes each generic function by substituting type parameters. @@ -136,11 +137,10 @@ class SpecializeGenericFunctions : public PassManager { FunctionSpecializationMap specMap; public: - SpecializeGenericFunctions(ReferenceMap *refMap, TypeMap *typeMap) { - passes.emplace_back(new TypeChecking(refMap, typeMap)); + explicit SpecializeGenericFunctions(TypeMap *typeMap) { + passes.emplace_back(new TypeChecking(nullptr, typeMap)); passes.emplace_back(new FindFunctionSpecializations(&specMap)); passes.emplace_back(new SpecializeFunctions(&specMap)); - specMap.refMap = refMap; specMap.typeMap = typeMap; setName("SpecializeGenericFunctions"); } diff --git a/frontends/p4/specializeGenericTypes.cpp b/frontends/p4/specializeGenericTypes.cpp index 9ae94c8865..a046f59c78 100644 --- a/frontends/p4/specializeGenericTypes.cpp +++ b/frontends/p4/specializeGenericTypes.cpp @@ -16,6 +16,7 @@ limitations under the License. #include "specializeGenericTypes.h" +#include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/p4/typeChecking/typeSubstitutionVisitor.h" namespace P4 { @@ -35,7 +36,7 @@ bool TypeSpecializationMap::same(const TypeSpecialization *spec, } void TypeSpecializationMap::add(const IR::Type_Specialized *t, const IR::Type_StructLike *decl, - const IR::Node *insertion) { + const IR::Node *insertion, NameGenerator *nameGen) { auto it = map.find(t); if (it != map.end()) return; @@ -49,7 +50,7 @@ void TypeSpecializationMap::add(const IR::Type_Specialized *t, const IR::Type_St } } - cstring name = refMap->newName(decl->getName().name.string_view()); + cstring name = nameGen->newName(decl->getName().string_view()); LOG3("Found to specialize: " << dbp(t) << "(" << t << ") with name " << name << " insert before " << dbp(insertion)); auto argTypes = new IR::Vector(); @@ -89,6 +90,13 @@ class ContainsTypeVariable : public Inspector { } // namespace +Visitor::profile_t FindTypeSpecializations::init_apply(const IR::Node *node) { + auto rv = Inspector::init_apply(node); + node->apply(nameGen); + + return rv; +} + void FindTypeSpecializations::postorder(const IR::Type_Specialized *type) { auto baseType = specMap->typeMap->getTypeType(type->baseType, true); auto st = baseType->to(); @@ -117,7 +125,7 @@ void FindTypeSpecializations::postorder(const IR::Type_Specialized *type) { if (!insert) insert = findContext(); if (!insert) insert = findContext(); CHECK_NULL(insert); - specMap->add(type, st, insert); + specMap->add(type, st, insert, &nameGen); } /////////////////////////////////////////////////////////////////////////////////////// diff --git a/frontends/p4/specializeGenericTypes.h b/frontends/p4/specializeGenericTypes.h index 33d0a1eccb..1c85dd5e51 100644 --- a/frontends/p4/specializeGenericTypes.h +++ b/frontends/p4/specializeGenericTypes.h @@ -59,7 +59,6 @@ struct TypeSpecialization : public IHasDbPrint { }; struct TypeSpecializationMap : public IHasDbPrint { - ReferenceMap *refMap; TypeMap *typeMap; // The map can have multiple keys pointing to the same value ordered_map map; @@ -68,7 +67,7 @@ struct TypeSpecializationMap : public IHasDbPrint { std::set inserted; void add(const IR::Type_Specialized *t, const IR::Type_StructLike *decl, - const IR::Node *insertion); + const IR::Node *insertion, NameGenerator *nameGen); TypeSpecialization *get(const IR::Type_Specialized *t) const; bool same(const TypeSpecialization *left, const IR::Type_Specialized *right) const; void dbprint(std::ostream &out) const override { @@ -97,6 +96,7 @@ struct TypeSpecializationMap : public IHasDbPrint { */ class FindTypeSpecializations : public Inspector { TypeSpecializationMap *specMap; + MinimalNameGenerator nameGen; public: explicit FindTypeSpecializations(TypeSpecializationMap *specMap) : specMap(specMap) { @@ -105,6 +105,7 @@ class FindTypeSpecializations : public Inspector { } void postorder(const IR::Type_Specialized *type) override; + profile_t init_apply(const IR::Node *node) override; }; /** @@ -162,21 +163,21 @@ class SpecializeGenericTypes : public PassRepeated { TypeSpecializationMap specMap; public: - SpecializeGenericTypes(ReferenceMap *refMap, TypeMap *typeMap) { + explicit SpecializeGenericTypes(TypeMap *typeMap) { passes.emplace_back(new PassRepeated({ - new TypeChecking(refMap, typeMap), + new TypeChecking(nullptr, typeMap), new FindTypeSpecializations(&specMap), new CreateSpecializedTypes(&specMap), // The previous pass has mutated some struct types new ClearTypeMap(typeMap, true), })); - passes.emplace_back(new TypeChecking(refMap, typeMap)); + passes.emplace_back(new TypeChecking(nullptr, typeMap)); passes.emplace_back(new ReplaceTypeUses(&specMap)); // The previous pass has invalidated the types of struct expressions passes.emplace_back(new ClearTypeMap(typeMap, true)); - specMap.refMap = refMap; specMap.typeMap = typeMap; setName("SpecializeGenericTypes"); + setStopOnError(true); } }; diff --git a/frontends/p4/staticAssert.h b/frontends/p4/staticAssert.h index 6f00a3dd23..5b89c5f61a 100644 --- a/frontends/p4/staticAssert.h +++ b/frontends/p4/staticAssert.h @@ -17,6 +17,7 @@ limitations under the License. #ifndef FRONTENDS_P4_STATICASSERT_H_ #define FRONTENDS_P4_STATICASSERT_H_ +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/methodInstance.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "ir/ir.h" @@ -29,23 +30,20 @@ using namespace literals; * Evaluates static_assert invocations. * A successful assertion is constant-folded to 'true'. */ -class DoStaticAssert : public Transform { - ReferenceMap *refMap; +class DoStaticAssert : public Transform, public ResolutionContext { TypeMap *typeMap; - bool removeStatement; + bool removeStatement = false; // 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) { - CHECK_NULL(refMap); + explicit DoStaticAssert(TypeMap *typeMap) : typeMap(typeMap) { CHECK_NULL(typeMap); setName("DoStaticAssert"); } const IR::Node *postorder(IR::MethodCallExpression *method) override { - MethodInstance *mi = MethodInstance::resolve(method, refMap, typeMap); + MethodInstance *mi = MethodInstance::resolve(method, this, typeMap); if (auto ef = mi->to()) { if (ef->method->name == staticAssertMethodName) { auto subst = ef->substitution; @@ -61,14 +59,14 @@ class DoStaticAssert : public Transform { CHECK_NULL(arg); if (auto bl = arg->expression->to()) { if (!bl->value) { - cstring message = "static_assert failed"_cs; + std::string_view message = "static_assert failed"; if (params->moveNext()) { param = params->getCurrent(); CHECK_NULL(param); auto msg = subst.lookup(param); CHECK_NULL(msg); - if (auto sl = msg->expression->to()) { - message = sl->value; + if (const auto *sl = msg->expression->to()) { + message = sl->value.string_view(); } } ::error(ErrorType::ERR_EXPECTED, "%1%: %2%", method, message); @@ -100,9 +98,9 @@ class DoStaticAssert : public Transform { class StaticAssert : public PassManager { public: - StaticAssert(ReferenceMap *refMap, TypeMap *typeMap) { - passes.push_back(new TypeInference(refMap, typeMap)); - passes.push_back(new DoStaticAssert(refMap, typeMap)); + explicit StaticAssert(TypeMap *typeMap) { + passes.push_back(new TypeInference(typeMap)); + passes.push_back(new DoStaticAssert(typeMap)); setName("StaticAssert"); } }; diff --git a/frontends/p4/strengthReduction.h b/frontends/p4/strengthReduction.h index 896c188fe2..242c60f043 100644 --- a/frontends/p4/strengthReduction.h +++ b/frontends/p4/strengthReduction.h @@ -79,6 +79,7 @@ class DoStrengthReduction final : public Transform { explicit DoStrengthReduction(bool enableSubConstToAddTransform) : enableSubConstToAddTransform(enableSubConstToAddTransform) { + // FIXME: This does not call a constructor DoStrengthReduction(); } @@ -116,19 +117,17 @@ class DoStrengthReduction final : public Transform { class StrengthReduction : public PassManager { public: - explicit StrengthReduction(ReferenceMap *refMap, TypeMap *typeMap, - TypeChecking *typeChecking = nullptr, + explicit StrengthReduction(TypeMap *typeMap, TypeChecking *typeChecking = nullptr, bool enableSubConstToAddTransform = true) { if (typeMap != nullptr) { - if (!typeChecking) typeChecking = new TypeChecking(refMap, typeMap, true); + if (!typeChecking) typeChecking = new TypeChecking(nullptr, typeMap, true); passes.push_back(typeChecking); } passes.push_back(new DoStrengthReduction(enableSubConstToAddTransform)); } - explicit StrengthReduction(ReferenceMap *refMap, TypeMap *typeMap, - bool enableSubConstToAddTransform) - : StrengthReduction(refMap, typeMap, nullptr, enableSubConstToAddTransform) {} + explicit StrengthReduction(TypeMap *typeMap, bool enableSubConstToAddTransform) + : StrengthReduction(typeMap, nullptr, enableSubConstToAddTransform) {} }; } // namespace P4 diff --git a/frontends/p4/structInitializers.cpp b/frontends/p4/structInitializers.cpp index fb6603f9ea..7da808d94e 100644 --- a/frontends/p4/structInitializers.cpp +++ b/frontends/p4/structInitializers.cpp @@ -16,6 +16,8 @@ limitations under the License. #include "structInitializers.h" +#include "frontends/p4/methodInstance.h" + namespace P4 { /// Given an expression and a destination type, convert ListExpressions @@ -106,7 +108,7 @@ const IR::Node *CreateStructInitializers::postorder(IR::Declaration_Variable *de } const IR::Node *CreateStructInitializers::postorder(IR::MethodCallExpression *expression) { - auto mi = MethodInstance::resolve(expression, refMap, typeMap); + auto mi = MethodInstance::resolve(expression, this, typeMap); auto result = expression; auto convertedArgs = new IR::Vector(); bool modified = false; diff --git a/frontends/p4/structInitializers.h b/frontends/p4/structInitializers.h index 5a8a7a49c8..de3be1b106 100644 --- a/frontends/p4/structInitializers.h +++ b/frontends/p4/structInitializers.h @@ -17,21 +17,19 @@ limitations under the License. #ifndef FRONTENDS_P4_STRUCTINITIALIZERS_H_ #define FRONTENDS_P4_STRUCTINITIALIZERS_H_ +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "ir/ir.h" namespace P4 { /// Converts some list expressions into struct initializers. -class CreateStructInitializers : public Transform { - ReferenceMap *refMap; +class CreateStructInitializers : public Transform, public ResolutionContext { TypeMap *typeMap; public: - CreateStructInitializers(ReferenceMap *refMap, TypeMap *typeMap) - : refMap(refMap), typeMap(typeMap) { + explicit CreateStructInitializers(TypeMap *typeMap) : typeMap(typeMap) { setName("CreateStructInitializers"); - CHECK_NULL(refMap); CHECK_NULL(typeMap); } @@ -44,10 +42,10 @@ class CreateStructInitializers : public Transform { class StructInitializers : public PassManager { public: - StructInitializers(ReferenceMap *refMap, TypeMap *typeMap) { + explicit StructInitializers(TypeMap *typeMap) { setName("StructInitializers"); - passes.push_back(new TypeChecking(refMap, typeMap)); - passes.push_back(new CreateStructInitializers(refMap, typeMap)); + passes.push_back(new TypeChecking(nullptr, typeMap)); + passes.push_back(new CreateStructInitializers(typeMap)); passes.push_back(new ClearTypeMap(typeMap)); } }; diff --git a/frontends/p4/tableApply.cpp b/frontends/p4/tableApply.cpp index 17d6632ac2..6de79e71a3 100644 --- a/frontends/p4/tableApply.cpp +++ b/frontends/p4/tableApply.cpp @@ -16,12 +16,13 @@ limitations under the License. #include "tableApply.h" +#include "frontends/common/resolveReferences/referenceMap.h" #include "methodInstance.h" namespace P4 { -const IR::P4Table *TableApplySolver::isHit(const IR::Expression *expression, ReferenceMap *refMap, - TypeMap *typeMap) { +const IR::P4Table *TableApplySolver::isHit(const IR::Expression *expression, + DeclarationLookup *refMap, TypeMap *typeMap) { if (!expression->is()) return nullptr; auto mem = expression->to(); if (!mem->expr->is()) return nullptr; @@ -35,8 +36,8 @@ const IR::P4Table *TableApplySolver::isHit(const IR::Expression *expression, Ref return am->object->to(); } -const IR::P4Table *TableApplySolver::isMiss(const IR::Expression *expression, ReferenceMap *refMap, - TypeMap *typeMap) { +const IR::P4Table *TableApplySolver::isMiss(const IR::Expression *expression, + DeclarationLookup *refMap, TypeMap *typeMap) { if (!expression->is()) return nullptr; auto mem = expression->to(); if (!mem->expr->is()) return nullptr; @@ -51,7 +52,7 @@ const IR::P4Table *TableApplySolver::isMiss(const IR::Expression *expression, Re } const IR::P4Table *TableApplySolver::isActionRun(const IR::Expression *expression, - ReferenceMap *refMap, TypeMap *typeMap) { + DeclarationLookup *refMap, TypeMap *typeMap) { auto mem = expression->to(); if (mem == nullptr) return nullptr; if (mem->member.name != IR::Type_Table::action_run) return nullptr; diff --git a/frontends/p4/tableApply.h b/frontends/p4/tableApply.h index 417b74fad8..15e86551ff 100644 --- a/frontends/p4/tableApply.h +++ b/frontends/p4/tableApply.h @@ -34,12 +34,12 @@ namespace P4 { // table.apply().action_run class TableApplySolver { public: - static const IR::P4Table *isHit(const IR::Expression *expression, ReferenceMap *refMap, + static const IR::P4Table *isHit(const IR::Expression *expression, DeclarationLookup *refMap, TypeMap *typeMap); - static const IR::P4Table *isMiss(const IR::Expression *expression, ReferenceMap *refMap, + static const IR::P4Table *isMiss(const IR::Expression *expression, DeclarationLookup *refMap, TypeMap *typeMap); - static const IR::P4Table *isActionRun(const IR::Expression *expression, ReferenceMap *refMap, - TypeMap *typeMap); + static const IR::P4Table *isActionRun(const IR::Expression *expression, + DeclarationLookup *refMap, TypeMap *typeMap); }; } // namespace P4 diff --git a/frontends/p4/tableKeyNames.h b/frontends/p4/tableKeyNames.h index e5def593dc..0a0627fb5d 100644 --- a/frontends/p4/tableKeyNames.h +++ b/frontends/p4/tableKeyNames.h @@ -89,8 +89,8 @@ class DoTableKeyNames final : public Transform { class TableKeyNames final : public PassManager { public: - TableKeyNames(ReferenceMap *refMap, TypeMap *typeMap) { - passes.push_back(new TypeChecking(refMap, typeMap)); + explicit TableKeyNames(TypeMap *typeMap) { + passes.push_back(new TypeChecking(nullptr, typeMap)); passes.push_back(new DoTableKeyNames(typeMap)); setName("TableKeyNames"); } diff --git a/frontends/p4/typeChecking/bindVariables.h b/frontends/p4/typeChecking/bindVariables.h index 1ffe35313e..f102ad22a3 100644 --- a/frontends/p4/typeChecking/bindVariables.h +++ b/frontends/p4/typeChecking/bindVariables.h @@ -1,7 +1,6 @@ #ifndef FRONTENDS_P4_TYPECHECKING_BINDVARIABLES_H_ #define FRONTENDS_P4_TYPECHECKING_BINDVARIABLES_H_ -#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" #include "frontends/p4/typeMap.h" #include "ir/ir.h" @@ -31,12 +30,10 @@ class DoBindTypeVariables : public Transform { class BindTypeVariables : public PassManager { public: - BindTypeVariables(ReferenceMap *refMap, TypeMap *typeMap) { - CHECK_NULL(refMap); + explicit BindTypeVariables(TypeMap *typeMap) { CHECK_NULL(typeMap); passes.push_back(new ClearTypeMap(typeMap)); - passes.push_back(new ResolveReferences(refMap)); - passes.push_back(new TypeInference(refMap, typeMap, false)); // may insert casts + passes.push_back(new TypeInference(typeMap, false)); // may insert casts passes.push_back(new DoBindTypeVariables(typeMap)); passes.push_back(new ClearTypeMap(typeMap, true)); setName("BindTypeVariables"); diff --git a/frontends/p4/typeChecking/syntacticEquivalence.h b/frontends/p4/typeChecking/syntacticEquivalence.h index 07cc2e9335..7254df9224 100644 --- a/frontends/p4/typeChecking/syntacticEquivalence.h +++ b/frontends/p4/typeChecking/syntacticEquivalence.h @@ -25,11 +25,11 @@ namespace P4 { // Check if two expressions are syntactically equivalent class SameExpression { - const ReferenceMap *refMap; + const DeclarationLookup *refMap; const TypeMap *typeMap; public: - explicit SameExpression(const ReferenceMap *refMap, const TypeMap *typeMap) + explicit SameExpression(const DeclarationLookup *refMap, const TypeMap *typeMap) : refMap(refMap), typeMap(typeMap) { CHECK_NULL(refMap); CHECK_NULL(typeMap); diff --git a/frontends/p4/typeChecking/typeChecker.cpp b/frontends/p4/typeChecking/typeChecker.cpp index 5664cfbea3..876c5a9b80 100644 --- a/frontends/p4/typeChecking/typeChecker.cpp +++ b/frontends/p4/typeChecking/typeChecker.cpp @@ -19,6 +19,7 @@ limitations under the License. #include #include "frontends/common/constantFolding.h" +#include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/coreLibrary.h" #include "frontends/p4/enumInstance.h" @@ -36,14 +37,13 @@ namespace P4 { namespace { // Used to set the type of Constants after type inference -class ConstantTypeSubstitution : public Transform { +class ConstantTypeSubstitution : public Transform, ResolutionContext { TypeVariableSubstitution *subst; TypeMap *typeMap; TypeInference *tc; public: - ConstantTypeSubstitution(TypeVariableSubstitution *subst, ReferenceMap *, TypeMap *typeMap, - TypeInference *tc) + ConstantTypeSubstitution(TypeVariableSubstitution *subst, TypeMap *typeMap, TypeInference *tc) : subst(subst), typeMap(typeMap), tc(tc) { CHECK_NULL(subst); CHECK_NULL(typeMap); @@ -71,38 +71,42 @@ class ConstantTypeSubstitution : public Transform { return cst; } - const IR::Expression *convert(const IR::Expression *expr) { - auto result = expr->apply(*this)->to(); - if (result != expr && (::errorCount() == 0)) tc->learn(result, this); + const IR::Expression *convert(const IR::Expression *expr, const Visitor::Context *ctxt) { + auto result = expr->apply(*this, ctxt)->to(); + if (result != expr && (::errorCount() == 0)) tc->learn(result, this, ctxt); return result; } - const IR::Vector *convert(const IR::Vector *vec) { - auto result = vec->apply(*this)->to>(); - if (result != vec) tc->learn(result, this); + const IR::Vector *convert(const IR::Vector *vec, + const Visitor::Context *ctxt) { + auto result = vec->apply(*this, ctxt)->to>(); + if (result != vec) tc->learn(result, this, ctxt); return result; } - const IR::Vector *convert(const IR::Vector *vec) { - auto result = vec->apply(*this)->to>(); - if (result != vec) tc->learn(result, this); + const IR::Vector *convert(const IR::Vector *vec, + const Visitor::Context *ctxt) { + auto result = vec->apply(*this, ctxt)->to>(); + if (result != vec) tc->learn(result, this, ctxt); return result; } }; } // namespace TypeChecking::TypeChecking(ReferenceMap *refMap, TypeMap *typeMap, bool updateExpressions) { - addPasses({new P4::ResolveReferences(refMap), new P4::TypeInference(refMap, typeMap, true), + addPasses({new P4::TypeInference(typeMap, /* readOnly */ true, /* checkArrays */ true, + /* errorOnNullDecls */ true), updateExpressions ? new ApplyTypesToExpressions(typeMap) : nullptr, - updateExpressions ? new P4::ResolveReferences(refMap) : nullptr}); + refMap ? new P4::ResolveReferences(refMap) : nullptr}); setStopOnError(true); } ////////////////////////////////////////////////////////////////////////// -bool TypeInference::learn(const IR::Node *node, Visitor *caller) { +bool TypeInference::learn(const IR::Node *node, Visitor *caller, const Visitor::Context *ctxt) { auto *learner = clone(); learner->setCalledBy(caller); + learner->setName("TypeInference learner"); unsigned previous = ::errorCount(); - (void)node->apply(*learner); + (void)node->apply(*learner, ctxt); unsigned errCount = ::errorCount(); bool result = errCount > previous; if (result) typeError("Error while analyzing %1%", node); @@ -111,9 +115,9 @@ bool TypeInference::learn(const IR::Node *node, Visitor *caller) { const IR::Expression *TypeInference::constantFold(const IR::Expression *expression) { if (readOnly) return expression; - DoConstantFolding cf(refMap, typeMap, false); - auto result = expression->apply(cf); - learn(result, this); + DoConstantFolding cf(this, typeMap, false); + auto result = expression->apply(cf, getChildContext()); + learn(result, this, getChildContext()); LOG3("Folded " << expression << " into " << result); return result; } @@ -131,34 +135,43 @@ const IR::Type *TypeInference::cloneWithFreshTypeVariables(const IR::IMayBeGener TypeVariableSubstitutionVisitor sv(&tvs, true); sv.setCalledBy(this); - auto cl = type->to()->apply(sv); + auto cl = type->to()->apply(sv, getChildContext()); CHECK_NULL(cl); - learn(cl, this); + learn(cl, this, getChildContext()); LOG3("Cloned for type variables " << type << " into " << cl); return cl->to(); } -TypeInference::TypeInference(ReferenceMap *refMap, TypeMap *typeMap, bool readOnly, - bool checkArrays) - : refMap(refMap), - typeMap(typeMap), +TypeInference::TypeInference(TypeMap *typeMap, bool readOnly, bool checkArrays, + bool errorOnNullDecls) + : typeMap(typeMap), initialNode(nullptr), readOnly(readOnly), checkArrays(checkArrays), + errorOnNullDecls(errorOnNullDecls), currentActionList(nullptr) { CHECK_NULL(typeMap); - CHECK_NULL(refMap); visitDagOnce = false; // the done() method will take care of this } +TypeInference::TypeInference(TypeMap *typeMap, + std::shared_ptr inheritedNameGen) + : TypeInference(typeMap, true) { + nameGen = inheritedNameGen; +} + Visitor::profile_t TypeInference::init_apply(const IR::Node *node) { + auto rv = Transform::init_apply(node); if (node->is()) { - LOG3("Reference map for type checker:" << std::endl << refMap); LOG2("TypeInference for " << dbp(node)); } initialNode = node; - refMap->validateMap(node); - return Transform::init_apply(node); + if (!nameGen) { + nameGen = std::make_shared(); + node->apply(*nameGen); + } + + return rv; } void TypeInference::end_apply(const IR::Node *node) { @@ -179,9 +192,7 @@ const IR::Node *TypeInference::apply_visitor(const IR::Node *orig, const char *n return transformed; } -TypeInference *TypeInference::clone() const { - return new TypeInference(this->refMap, this->typeMap, true); -} +TypeInference *TypeInference::clone() const { return new TypeInference(this->typeMap, nameGen); } bool TypeInference::done() const { auto orig = getOriginal(); @@ -315,7 +326,8 @@ bool TypeInference::checkParameters(const IR::ParameterList *paramList, bool for * void _>(int<32> data); */ const IR::Type *TypeInference::specialize(const IR::IMayBeGenericType *type, - const IR::Vector *arguments) { + const IR::Vector *arguments, + const Visitor::Context *ctxt) { TypeVariableSubstitution *bindings = new TypeVariableSubstitution(); bool success = bindings->setBindings(type->getNode(), type->getTypeParameters(), arguments); if (!success) return nullptr; @@ -323,7 +335,7 @@ const IR::Type *TypeInference::specialize(const IR::IMayBeGenericType *type, LOG2("Translation map\n" << bindings); TypeVariableSubstitutionVisitor tsv(bindings); - const IR::Node *result = type->getNode()->apply(tsv); + const IR::Node *result = type->getNode()->apply(tsv, ctxt); if (result == nullptr) return nullptr; LOG2("Specialized " << type << "\n\tinto " << result); @@ -564,12 +576,12 @@ const IR::Type *TypeInference::canonicalize(const IR::Type *type) { if (canon == nullptr) return nullptr; args->push_back(canon); } - auto specialized = specialize(gt, args); + auto specialized = specialize(gt, args, getChildContext()); auto result = new IR::Type_SpecializedCanonical(type->srcInfo, baseCanon, args, specialized); LOG2("Scanning the specialized type"); - learn(result, this); + learn(result, this, getChildContext()); return result; } else { BUG_CHECK(::errorCount(), "Unexpected type %1%", dbp(type)); @@ -742,8 +754,8 @@ const IR::Expression *TypeInference::assignment(const IR::Node *errorPosition, // error already signalled return sourceExpression; if (!tvs->isIdentity()) { - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - sourceExpression = cts.convert(sourceExpression); // sets type + ConstantTypeSubstitution cts(tvs, typeMap, this); + sourceExpression = cts.convert(sourceExpression, getChildContext()); // sets type } if (destType->is() && !typeMap->equivalent(destType, initType) && !initType->is()) { @@ -980,7 +992,7 @@ std::pair *> TypeInference::che } // will always be bound to Type_Void. - auto rettype = new IR::Type_Var(IR::ID(refMap->newName("R"), ""_cs)); + auto rettype = new IR::Type_Var(IR::ID(nameGen->newName("R"), ""_cs)); auto callType = new IR::Type_MethodCall(errorPosition->srcInfo, new IR::Vector(), rettype, args); auto tvs = unify(errorPosition, methodType, callType, @@ -992,9 +1004,9 @@ std::pair *> TypeInference::che LOG2("Constructor type before specialization " << methodType << " with " << tvs); TypeVariableSubstitutionVisitor substVisitor(tvs); substVisitor.setCalledBy(this); - auto specMethodType = methodType->apply(substVisitor); + auto specMethodType = methodType->apply(substVisitor, getChildContext()); LOG2("Constructor type after specialization " << specMethodType); - learn(specMethodType, this); + learn(specMethodType, this, getChildContext()); auto canon = getType(specMethodType); if (canon == nullptr) return none; @@ -1002,7 +1014,7 @@ std::pair *> TypeInference::che BUG_CHECK(functionType != nullptr, "Method type is %1%", specMethodType); if (!functionType->is()) BUG("Unexpected type for function %1%", functionType); - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); + ConstantTypeSubstitution cts(tvs, typeMap, this); // Arguments may need to be cast, e.g., list expression to a // header type. auto paramIt = functionType->parameters->begin(); @@ -1027,7 +1039,7 @@ std::pair *> TypeInference::che newExpr = assignment(arg, param->type, arg->expression); } else { // Insert casts for 'int' values. - newExpr = cts.convert(newExpr)->to(); + newExpr = cts.convert(newExpr, getChildContext())->to(); } if (::errorCount() > 0) return none; if (newExpr != arg->expression) { @@ -1042,7 +1054,7 @@ std::pair *> TypeInference::che if (changed) arguments = newArgs; auto objectType = new IR::Type_Extern(ext->srcInfo, ext->name, methodType->typeParameters, freshExtern->methods); - learn(objectType, this); + learn(objectType, this, getChildContext()); return {objectType, arguments}; } @@ -1155,7 +1167,7 @@ const IR::Node *TypeInference::preorder(IR::Declaration_Instance *decl) { prune(); return decl; } - learn(type, this); + learn(type, this, getChildContext()); if (args != decl->arguments) decl->arguments = args; setType(decl, type); setType(orig, type); @@ -1192,9 +1204,9 @@ std::pair *> TypeInference::con } TypeVariableSubstitutionVisitor sv(&tvs, true); sv.setCalledBy(this); - constructor = constructor->apply(sv)->to(); + constructor = constructor->apply(sv, getChildContext())->to(); CHECK_NULL(constructor); - learn(constructor, this); + learn(constructor, this, getChildContext()); LOG3("Cloned constructor arguments " << constructor); } @@ -1216,7 +1228,7 @@ std::pair *> TypeInference::con auto argInfo = new IR::ArgumentInfo(arg->srcInfo, arg, true, argType, aarg); args->push_back(argInfo); } - auto rettype = new IR::Type_Var(IR::ID(refMap->newName(""))); + auto rettype = new IR::Type_Var(IR::ID(nameGen->newName(""))); // There are never type arguments at this point; if they exist, they have been folded // into the constructor by type specialization. auto callType = @@ -1242,8 +1254,8 @@ std::pair *> TypeInference::con } addSubstitutions(dontCares); - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - auto newArgs = cts.convert(constructorArguments); + ConstantTypeSubstitution cts(tvs, typeMap, this); + auto newArgs = cts.convert(constructorArguments, getChildContext()); auto returnType = tvs->lookup(rettype); BUG_CHECK(returnType != nullptr, "Cannot infer constructor result type %1%", node); @@ -1304,7 +1316,7 @@ const IR::Type *TypeInference::setTypeType(const IR::Type *type, bool learn) { if (canon != nullptr) { // Learn the new type if (canon != typeToCanonicalize && learn) { - bool errs = this->learn(canon, this); + bool errs = this->learn(canon, this, getChildContext()); if (errs) return nullptr; } auto tt = new IR::Type_Type(canon); @@ -1418,7 +1430,11 @@ const IR::Node *TypeInference::postorder(IR::Type_Name *typeName) { auto t = IR::Type_Dontcare::get(); type = new IR::Type_Type(t); } else { - auto decl = refMap->getDeclaration(typeName->path, true); + auto decl = getDeclaration(typeName->path, !errorOnNullDecls); + if (errorOnNullDecls && decl == nullptr) { + typeError("%1%: Cannot resolve type", typeName); + return typeName; + } // Check for references of a control or parser within itself. auto ctrl = findContext(); if (ctrl != nullptr && ctrl->name == decl->getName()) { @@ -1586,8 +1602,8 @@ const IR::Node *TypeInference::postorder(IR::SerEnumMember *member) { return member; if (tvs->isIdentity()) return member; - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - member->value = cts.convert(member->value); // sets type + ConstantTypeSubstitution cts(tvs, typeMap, this); + member->value = cts.convert(member->value, getChildContext()); // sets type if (!typeMap->getType(member)) setType(member, getTypeType(serEnum)); return member; } @@ -1598,7 +1614,7 @@ const IR::Node *TypeInference::postorder(IR::P4ValueSet *decl) { auto canon = canonicalize(decl->elementType); if (canon != nullptr) { if (canon != decl->elementType) { - bool errs = learn(canon, this); + bool errs = learn(canon, this, getChildContext()); if (errs) return nullptr; } if (!canon->is() && !canon->is() && @@ -1888,9 +1904,9 @@ bool TypeInference::compare(const IR::Node *errorPosition, const IR::Type *ltype auto tvs = unify(errorPosition, ltype, rtype); if (tvs == nullptr) return false; if (!tvs->isIdentity()) { - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - compare->left = cts.convert(compare->left); - compare->right = cts.convert(compare->right); + ConstantTypeSubstitution cts(tvs, typeMap, this); + compare->left = cts.convert(compare->left, getChildContext()); + compare->right = cts.convert(compare->right, getChildContext()); } defined = true; } else if (auto se = rtype->to()) { @@ -1917,9 +1933,9 @@ bool TypeInference::compare(const IR::Node *errorPosition, const IR::Type *ltype } if (tvs == nullptr) return false; if (!tvs->isIdentity()) { - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - compare->left = cts.convert(compare->left); - compare->right = cts.convert(compare->right); + ConstantTypeSubstitution cts(tvs, typeMap, this); + compare->left = cts.convert(compare->left, getChildContext()); + compare->right = cts.convert(compare->right, getChildContext()); } if (ls != nullptr) { @@ -1959,9 +1975,9 @@ bool TypeInference::compare(const IR::Node *errorPosition, const IR::Type *ltype auto tvs = unify(errorPosition, ltype, rtype); if (tvs == nullptr) return false; if (!tvs->isIdentity()) { - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - compare->left = cts.convert(compare->left); - compare->right = cts.convert(compare->right); + ConstantTypeSubstitution cts(tvs, typeMap, this); + compare->left = cts.convert(compare->left, getChildContext()); + compare->right = cts.convert(compare->right, getChildContext()); } defined = true; } @@ -2208,8 +2224,8 @@ const IR::Node *TypeInference::postorder(IR::Entry *entry) { "Table entry has type '%1%' which is not the expected type '%2%'", {keyTuple, entryKeyType}); if (tvs == nullptr) return entry; - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - auto ks = cts.convert(keyset); + ConstantTypeSubstitution cts(tvs, typeMap, this); + auto ks = cts.convert(keyset, getChildContext()); if (::errorCount() > 0) return entry; if (ks != keyset) @@ -2309,8 +2325,8 @@ const IR::Node *TypeInference::postorder(IR::P4ListExpression *expression) { {type, elementType}); if (tvs == nullptr) return expression; if (!tvs->isIdentity()) { - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - auto converted = cts.convert(c); + ConstantTypeSubstitution cts(tvs, typeMap, this); + auto converted = cts.convert(c, getChildContext()); vec->push_back(converted); changed = changed || converted != c; } else { @@ -2352,8 +2368,8 @@ const IR::Node *TypeInference::postorder(IR::HeaderStackExpression *expression) {type, elementType}); if (tvs == nullptr) return expression; if (!tvs->isIdentity()) { - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - auto converted = cts.convert(c); + ConstantTypeSubstitution cts(tvs, typeMap, this); + auto converted = cts.convert(c, getChildContext()); vec->push_back(converted); changed = true; } else { @@ -2403,8 +2419,8 @@ const IR::Node *TypeInference::postorder(IR::StructExpression *expression) { {structType, desired}); if (tvs == nullptr) return expression; if (!tvs->isIdentity()) { - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - result = cts.convert(expression); + ConstantTypeSubstitution cts(tvs, typeMap, this); + result = cts.convert(expression, getChildContext()); } structType = desired; } @@ -2987,8 +3003,8 @@ const IR::Node *TypeInference::postorder(IR::Cast *expression) { if (tvs == nullptr) return expression; const IR::Expression *rhs = expression->expr; if (!tvs->isIdentity()) { - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - rhs = cts.convert(expression->expr); // sets type + ConstantTypeSubstitution cts(tvs, typeMap, this); + rhs = cts.convert(expression->expr, getChildContext()); // sets type } if (rhs != expression->expr) { // if we are here we have performed a substitution on the rhs @@ -3010,7 +3026,11 @@ const IR::Node *TypeInference::postorder(IR::Cast *expression) { const IR::Node *TypeInference::postorder(IR::PathExpression *expression) { if (done()) return expression; - auto decl = refMap->getDeclaration(expression->path, true); + auto decl = getDeclaration(expression->path, !errorOnNullDecls); + if (errorOnNullDecls && decl == nullptr) { + typeError("%1%: Cannot resolve declaration", expression); + return expression; + } const IR::Type *type = nullptr; if (auto tbl = decl->to()) { if (auto current = findContext()) { @@ -3199,9 +3219,9 @@ const IR::Node *TypeInference::postorder(IR::Mux *expression) { {secondType, thirdType}); if (tvs != nullptr) { if (!tvs->isIdentity()) { - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - auto e1 = cts.convert(expression->e1); - auto e2 = cts.convert(expression->e2); + ConstantTypeSubstitution cts(tvs, typeMap, this); + auto e1 = cts.convert(expression->e1, getChildContext()); + auto e2 = cts.convert(expression->e2, getChildContext()); if (::errorCount() > 0) return expression; expression->e1 = e1; expression->e2 = e2; @@ -3341,7 +3361,7 @@ const IR::Node *TypeInference::postorder(IR::Member *expression) { if (!canon) return expression; methodType = canon->to(); if (methodType == nullptr) return expression; - learn(methodType, this); + learn(methodType, this, getChildContext()); setType(getOriginal(), methodType); setType(expression, methodType); return expression; @@ -3569,8 +3589,9 @@ const IR::Expression *TypeInference::actionCall(bool inActionList, if (tvs == nullptr || errorCount() > 0) return actionCall; addSubstitutions(tvs); - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - actionCall = cts.convert(actionCall)->to(); // cast arguments + ConstantTypeSubstitution cts(tvs, typeMap, this); + actionCall = cts.convert(actionCall, getChildContext()) + ->to(); // cast arguments if (::errorCount() > 0) return actionCall; LOG2("Converted action " << actionCall); @@ -3701,7 +3722,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"), ""_cs)); + auto rettype = new IR::Type_Var(IR::ID(nameGen->newName("R"), ""_cs)); auto args = new IR::Vector(); bool constArgs = true; for (auto aarg : *expression->arguments) { @@ -3747,7 +3768,7 @@ const IR::Node *TypeInference::postorder(IR::MethodCallExpression *expression) { substVisitor.setCalledBy(this); auto specMethodType = methodType->apply(substVisitor); LOG2("Method type after specialization " << specMethodType); - learn(specMethodType, this); + learn(specMethodType, this, getChildContext()); auto canon = getType(specMethodType); if (canon == nullptr) return expression; @@ -3765,7 +3786,7 @@ const IR::Node *TypeInference::postorder(IR::MethodCallExpression *expression) { } // The return type may also contain type variables returnType = returnType->apply(substVisitor)->to(); - learn(returnType, this); + learn(returnType, this, getChildContext()); if (returnType->is() || returnType->is() || returnType->is() || returnType->is() || returnType->is() || @@ -3779,7 +3800,7 @@ const IR::Node *TypeInference::postorder(IR::MethodCallExpression *expression) { setType(getOriginal(), returnType); setType(expression, returnType); - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); + ConstantTypeSubstitution cts(tvs, typeMap, this); auto result = expression; // Arguments may need to be cast, e.g., list expression to a // header type. @@ -3817,7 +3838,7 @@ const IR::Node *TypeInference::postorder(IR::MethodCallExpression *expression) { newExpr = assignment(arg, param->type, arg->expression); } else { // Insert casts for 'int' values. - newExpr = cts.convert(newExpr)->to(); + newExpr = cts.convert(newExpr, getChildContext())->to(); } if (::errorCount() > 0) return expression; if (newExpr != arg->expression) { @@ -3835,7 +3856,7 @@ const IR::Node *TypeInference::postorder(IR::MethodCallExpression *expression) { result->typeArguments, newArgs); setType(result, returnType); - auto mi = MethodInstance::resolve(result, refMap, typeMap, nullptr, true); + auto mi = MethodInstance::resolve(result, this, typeMap, getChildContext(), true); if (mi->isApply() && findContext()) { typeError("%1%: apply cannot be called from actions", expression); return expression; @@ -3940,8 +3961,8 @@ const IR::SelectCase *TypeInference::matchCase(const IR::SelectExpression *selec "'match' case label '%1%' has type '%2%' which does not match the expected type '%3%'", {selectCase->keyset, caseType, useSelType}); if (tvs == nullptr) return nullptr; - ConstantTypeSubstitution cts(tvs, refMap, typeMap, this); - auto ks = cts.convert(selectCase->keyset); + ConstantTypeSubstitution cts(tvs, typeMap, this); + auto ks = cts.convert(selectCase->keyset, getChildContext()); if (::errorCount() > 0) return selectCase; if (ks != selectCase->keyset) @@ -4250,7 +4271,12 @@ const IR::ActionListElement *TypeInference::validateActionInitializer( auto method = call->method; if (!method->is()) BUG("%1%: unexpected expression", method); auto pe = method->to(); - auto decl = refMap->getDeclaration(pe->path, true); + auto decl = getDeclaration(pe->path, !errorOnNullDecls); + if (errorOnNullDecls && decl == nullptr) { + typeError("%1%: Cannot resolve declaration", pe); + return nullptr; + } + auto ale = al->actionList.getDeclaration(decl->getName()); if (ale == nullptr) { typeError("%1% not present in action list", call); @@ -4260,7 +4286,7 @@ const IR::ActionListElement *TypeInference::validateActionInitializer( BUG_CHECK(ale->is(), "%1%: expected an ActionListElement", ale); auto elem = ale->to(); auto entrypath = elem->getPath(); - auto entrydecl = refMap->getDeclaration(entrypath, true); + auto entrydecl = getDeclaration(entrypath, true); if (entrydecl != decl) { typeError("%1% and %2% refer to different actions", actionCall, elem); return nullptr; @@ -4282,9 +4308,10 @@ const IR::ActionListElement *TypeInference::validateActionInitializer( return nullptr; } - SameExpression se(refMap, typeMap); - auto callInstance = MethodInstance::resolve(call, refMap, typeMap, nullptr, true); - auto listInstance = MethodInstance::resolve(actionListCall, refMap, typeMap, nullptr, true); + SameExpression se(this, typeMap); + auto callInstance = MethodInstance::resolve(call, this, typeMap, getChildContext(), true); + auto listInstance = + MethodInstance::resolve(actionListCall, this, typeMap, getChildContext(), true); for (auto param : *listInstance->substitution.getParametersInArgumentOrder()) { auto aa = listInstance->substitution.lookup(param); diff --git a/frontends/p4/typeChecking/typeChecker.h b/frontends/p4/typeChecking/typeChecker.h index d620793a67..5665dbc26c 100644 --- a/frontends/p4/typeChecking/typeChecker.h +++ b/frontends/p4/typeChecking/typeChecker.h @@ -18,16 +18,12 @@ limitations under the License. #define TYPECHECKING_TYPECHECKER_H_ #include "frontends/common/resolveReferences/referenceMap.h" -#include "frontends/p4/methodInstance.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeSubstitution.h" -#include "frontends/p4/typeChecking/typeSubstitutionVisitor.h" #include "frontends/p4/typeMap.h" #include "ir/ir.h" #include "ir/pass_manager.h" #include "ir/visitor.h" -#include "lib/cstring.h" -#include "lib/exceptions.h" -#include "typeUnification.h" namespace P4 { @@ -80,23 +76,25 @@ bool hasVarbitsOrUnions(const TypeMap *typeMap, const IR::Type *type); // In fact, several passes do modify the program such that types are invalidated. // For example, enum elimination converts enum values into integers. After such // changes the typemap has to be cleared and types must be recomputed from scratch. -class TypeInference : public Transform { - // Input: reference map - ReferenceMap *refMap; +class TypeInference : public Transform, public ResolutionContext { // Output: type map TypeMap *typeMap; const IR::Node *initialNode; + std::shared_ptr nameGen; + + TypeInference(TypeMap *typeMap, std::shared_ptr nameGen); public: // @param readOnly If true it will assert that it behaves like // an Inspector. - TypeInference(ReferenceMap *refMap, TypeMap *typeMap, bool readOnly = false, - bool checkArrays = true); + explicit TypeInference(TypeMap *typeMap, bool readOnly = false, bool checkArrays = true, + bool errorOnNullDecls = false); protected: // If true we expect to leave the program unchanged - bool readOnly; + bool readOnly = false; bool checkArrays = true; + bool errorOnNullDecls = false; const IR::Type *getType(const IR::Node *element) const; const IR::Type *getTypeType(const IR::Node *element) const; void setType(const IR::Node *element, const IR::Type *type); @@ -205,7 +203,8 @@ class TypeInference : public Transform { using Transform::preorder; static const IR::Type *specialize(const IR::IMayBeGenericType *type, - const IR::Vector *arguments); + const IR::Vector *arguments, + const Visitor::Context *ctxt); const IR::Node *pruneIfDone(const IR::Node *node) { if (done()) { prune(); @@ -346,7 +345,7 @@ class TypeInference : public Transform { // Apply recursively the typechecker to the newly created node // to add all component subtypes in the typemap. // Return 'true' if errors were discovered in the learning process. - bool learn(const IR::Node *node, Visitor *caller); + bool learn(const IR::Node *node, Visitor *caller, const Visitor::Context *ctxt); }; // Copy types from the typeMap to expressions. Updates the typeMap with newly created nodes diff --git a/frontends/p4/uniqueNames.cpp b/frontends/p4/uniqueNames.cpp index b48c64ff68..f94317b42d 100644 --- a/frontends/p4/uniqueNames.cpp +++ b/frontends/p4/uniqueNames.cpp @@ -16,6 +16,7 @@ limitations under the License. #include "uniqueNames.h" +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/methodInstance.h" #include "frontends/p4/typeChecking/typeChecker.h" @@ -41,21 +42,19 @@ void RenameMap::markActionCall(const IR::P4Action *action, const IR::MethodCallE namespace { -class FindActionCalls : public Inspector { - ReferenceMap *refMap; +class FindActionCalls : public Inspector, public ResolutionContext { TypeMap *typeMap; RenameMap *renameMap; public: - explicit FindActionCalls(ReferenceMap *refMap, TypeMap *typeMap, RenameMap *renameMap) - : refMap(refMap), typeMap(typeMap), renameMap(renameMap) { - CHECK_NULL(refMap); + explicit FindActionCalls(TypeMap *typeMap, RenameMap *renameMap) + : typeMap(typeMap), renameMap(renameMap) { CHECK_NULL(typeMap); CHECK_NULL(renameMap); } void postorder(const IR::MethodCallExpression *expression) { - auto mi = MethodInstance::resolve(expression, refMap, typeMap); + auto mi = MethodInstance::resolve(expression, this, typeMap); if (!mi->is()) return; auto ac = mi->to(); renameMap->markActionCall(ac->action, getOriginal()); @@ -64,24 +63,27 @@ class FindActionCalls : public Inspector { } // namespace -UniqueNames::UniqueNames(ReferenceMap *refMap) : renameMap(new RenameMap) { +Visitor::profile_t FindParameters::init_apply(const IR::Node *node) { + auto rv = Inspector::init_apply(node); + node->apply(nameGen); + + return rv; +} + +UniqueNames::UniqueNames() : renameMap(new RenameMap) { setName("UniqueNames"); visitDagOnce = false; - CHECK_NULL(refMap); - passes.emplace_back(new ResolveReferences(refMap)); - passes.emplace_back(new FindSymbols(refMap, renameMap)); - passes.emplace_back(new RenameSymbols(refMap, renameMap)); + passes.emplace_back(new FindSymbols(renameMap)); + passes.emplace_back(new RenameSymbols(renameMap)); } -UniqueParameters::UniqueParameters(ReferenceMap *refMap, TypeMap *typeMap) - : renameMap(new RenameMap) { +UniqueParameters::UniqueParameters(TypeMap *typeMap) : renameMap(new RenameMap) { setName("UniqueParameters"); - CHECK_NULL(refMap); CHECK_NULL(typeMap); - passes.emplace_back(new TypeChecking(refMap, typeMap)); - passes.emplace_back(new FindActionCalls(refMap, typeMap, renameMap)); - passes.emplace_back(new FindParameters(refMap, renameMap)); - passes.emplace_back(new RenameSymbols(refMap, renameMap)); + passes.emplace_back(new TypeChecking(nullptr, typeMap)); + passes.emplace_back(new FindActionCalls(typeMap, renameMap)); + passes.emplace_back(new FindParameters(renameMap)); + passes.emplace_back(new RenameSymbols(renameMap)); passes.emplace_back(new ClearTypeMap(typeMap)); } @@ -118,7 +120,7 @@ const IR::Node *RenameSymbols::postorder(IR::Parameter *param) { } const IR::Node *RenameSymbols::postorder(IR::PathExpression *expression) { - auto decl = refMap->getDeclaration(expression->path, true); + auto decl = getDeclaration(expression->path, true); if (!renameMap->toRename(decl)) return expression; // This should be a local name. BUG_CHECK(!expression->path->absolute, "%1%: renaming absolute path", expression); diff --git a/frontends/p4/uniqueNames.h b/frontends/p4/uniqueNames.h index 4c5a5bc5f7..fd00b0a165 100644 --- a/frontends/p4/uniqueNames.h +++ b/frontends/p4/uniqueNames.h @@ -17,10 +17,12 @@ limitations under the License. #ifndef FRONTENDS_P4_UNIQUENAMES_H_ #define FRONTENDS_P4_UNIQUENAMES_H_ +#include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeMap.h" #include "ir/ir.h" #include "ir/pass_manager.h" +#include "ir/visitor.h" namespace P4 { @@ -70,27 +72,32 @@ class UniqueNames : public PassManager { RenameMap *renameMap; public: - explicit UniqueNames(ReferenceMap *refMap); + UniqueNames(); }; /// Finds and allocates new names for some symbols: /// Declaration_Variable, Declaration_Constant, Declaration_Instance, /// P4Table, P4Action. class FindSymbols : public Inspector { - ReferenceMap *refMap; // used to generate new names + MinimalNameGenerator nameGen; // used to generate new names RenameMap *renameMap; public: bool isTopLevel() const { return findContext() == nullptr && findContext() == nullptr; } - FindSymbols(ReferenceMap *refMap, RenameMap *renameMap) : refMap(refMap), renameMap(renameMap) { - CHECK_NULL(refMap); + explicit FindSymbols(RenameMap *renameMap) : renameMap(renameMap) { CHECK_NULL(renameMap); setName("FindSymbols"); } + profile_t init_apply(const IR::Node *node) override { + auto rv = Inspector::init_apply(node); + node->apply(nameGen); + return rv; + } + void doDecl(const IR::Declaration *decl) { - cstring newName = refMap->newName(decl->getName().name.string_view()); + cstring newName = nameGen.newName(decl->getName().name.string_view()); renameMap->setNewName(decl, newName); } void postorder(const IR::Declaration_Variable *decl) override { doDecl(decl); } @@ -113,9 +120,8 @@ class FindSymbols : public Inspector { } }; -class RenameSymbols : public Transform { +class RenameSymbols : public Transform, public ResolutionContext { protected: - ReferenceMap *refMap; RenameMap *renameMap; /// Get new name of the current declaration or nullptr if the declaration is not to be renamed. @@ -141,9 +147,7 @@ class RenameSymbols : public Transform { } public: - RenameSymbols(ReferenceMap *refMap, RenameMap *renameMap) - : refMap(refMap), renameMap(renameMap) { - CHECK_NULL(refMap); + explicit RenameSymbols(RenameMap *renameMap) : renameMap(renameMap) { CHECK_NULL(renameMap); visitDagOnce = false; setName("RenameSymbols"); @@ -161,24 +165,23 @@ class RenameSymbols : public Transform { /// Finds parameters for actions that will be given unique names class FindParameters : public Inspector { - ReferenceMap *refMap; // used to generate new names + MinimalNameGenerator nameGen; RenameMap *renameMap; void doParameters(const IR::ParameterList *pl) { for (auto p : pl->parameters) { - cstring newName = refMap->newName(p->name.name.string_view()); + cstring newName = nameGen.newName(p->name.name.string_view()); renameMap->setNewName(p, newName); } } public: - FindParameters(ReferenceMap *refMap, RenameMap *renameMap) - : refMap(refMap), renameMap(renameMap) { - CHECK_NULL(refMap); + explicit FindParameters(RenameMap *renameMap) : renameMap(renameMap) { CHECK_NULL(renameMap); setName("FindParameters"); } void postorder(const IR::P4Action *action) override { doParameters(action->parameters); } + profile_t init_apply(const IR::Node *node) override; }; /// Give each parameter of an action a new unique name @@ -188,7 +191,7 @@ class UniqueParameters : public PassManager { RenameMap *renameMap; public: - UniqueParameters(ReferenceMap *refMap, TypeMap *typeMap); + explicit UniqueParameters(TypeMap *typeMap); }; } // namespace P4 diff --git a/frontends/p4/uselessCasts.h b/frontends/p4/uselessCasts.h index f83a69874c..50aedff554 100644 --- a/frontends/p4/uselessCasts.h +++ b/frontends/p4/uselessCasts.h @@ -39,8 +39,8 @@ class RemoveUselessCasts : public Transform { class UselessCasts : public PassManager { public: - UselessCasts(ReferenceMap *refMap, TypeMap *typeMap) { - passes.push_back(new TypeChecking(refMap, typeMap)); + explicit UselessCasts(TypeMap *typeMap) { + passes.push_back(new TypeChecking(nullptr, typeMap)); passes.push_back(new RemoveUselessCasts(typeMap)); setName("UselessCasts"); } diff --git a/ir/visitor.cpp b/ir/visitor.cpp index 49a6a5b731..9545c98297 100644 --- a/ir/visitor.cpp +++ b/ir/visitor.cpp @@ -20,6 +20,8 @@ limitations under the License. #include #include "absl/container/flat_hash_map.h" +#include "absl/time/clock.h" +#include "absl/time/time.h" #include "ir/ir-generated.h" #include "lib/hash.h" @@ -370,37 +372,24 @@ void Visitor::end_apply() {} void Visitor::end_apply(const IR::Node *) {} static indent_t profile_indent; -static uint64_t first_start = 0; +static absl::Time first_start = absl::InfinitePast(); + Visitor::profile_t::profile_t(Visitor &v_) : v(v_) { - struct timespec ts; -#ifdef CLOCK_MONOTONIC - clock_gettime(CLOCK_MONOTONIC, &ts); -#else - // FIXME -- figure out how to do this on OSX/Mach - ts.tv_sec = ts.tv_nsec = 0; -#endif - start = ts.tv_sec * 1000000000UL + ts.tv_nsec + 1; - assert(start); + start = absl::Now(); LOG3(profile_indent << v.name() << " statrting at +" - << (first_start ? start - first_start : (first_start = start, 0UL)) / - 1000000.0 - << " msec"); + << (first_start != absl::InfinitePast() + ? start - first_start + : (first_start = start, start - first_start))); ++profile_indent; } -Visitor::profile_t::profile_t(profile_t &&a) : v(a.v), start(a.start) { a.start = 0; } +Visitor::profile_t::profile_t(profile_t &&a) : v(a.v), start(a.start) { + a.start = absl::InfinitePast(); +} Visitor::profile_t::~profile_t() { - if (start) { + if (start != absl::InfinitePast()) { v.end_apply(); --profile_indent; - struct timespec ts; -#ifdef CLOCK_MONOTONIC - clock_gettime(CLOCK_MONOTONIC, &ts); -#else - // FIXME -- figure out how to do this on OSX/Mach - ts.tv_sec = ts.tv_nsec = 0; -#endif - uint64_t end = ts.tv_sec * 1000000000UL + ts.tv_nsec + 1; - LOG1(profile_indent << v.name() << ' ' << (end - start) / 1000.0 << " usec"); + LOG1(profile_indent << v.name() << ' ' << (absl::Now() - start)); } } diff --git a/ir/visitor.h b/ir/visitor.h index 512eba1670..5d6f4e03a1 100644 --- a/ir/visitor.h +++ b/ir/visitor.h @@ -29,6 +29,7 @@ limitations under the License. #include #include +#include "absl/time/time.h" #include "ir/gen-tree-macro.h" #include "ir/ir-tree-macros.h" #include "ir/node.h" @@ -76,7 +77,7 @@ class Visitor { // for profiling -- a profile_t object is created when a pass // starts and destroyed when it ends. Moveable but not copyable. Visitor &v; - uint64_t start; + absl::Time start; explicit profile_t(Visitor &); friend class Visitor; diff --git a/midend/copyStructures.cpp b/midend/copyStructures.cpp index 88c0078735..3ec4ad169a 100644 --- a/midend/copyStructures.cpp +++ b/midend/copyStructures.cpp @@ -26,8 +26,10 @@ const IR::Node *RemoveAliases::postorder(IR::AssignmentStatement *statement) { return statement; } - ReadsWrites rw(refMap); - if (!rw.mayAlias(statement->left, statement->right)) { + // FIXME: This recreates ReadWrites() over and over again, loosing all + // declaration lookup caching + ReadsWrites rw; + if (!rw.mayAlias(statement->left, statement->right, getContext())) { return statement; } auto tmp = refMap->newName("tmp"); diff --git a/midend/eliminateTuples.h b/midend/eliminateTuples.h index 245e358c28..a7af2a5d31 100644 --- a/midend/eliminateTuples.h +++ b/midend/eliminateTuples.h @@ -124,7 +124,7 @@ class EliminateTuples final : public PassManager { // into StructExpression where tuples were converted // to structs. passes.push_back(new ResolveReferences(refMap)); - if (!typeInference) typeInference = new TypeInference(refMap, typeMap, false); + if (!typeInference) typeInference = new TypeInference(typeMap, false); passes.push_back(typeInference); setName("EliminateTuples"); } diff --git a/midend/expandEmit.cpp b/midend/expandEmit.cpp index 772c449594..41750e4e44 100644 --- a/midend/expandEmit.cpp +++ b/midend/expandEmit.cpp @@ -17,6 +17,7 @@ limitations under the License. #include "expandEmit.h" #include "frontends/p4/coreLibrary.h" +#include "frontends/p4/methodInstance.h" namespace P4 { diff --git a/midend/flattenUnions.h b/midend/flattenUnions.h index 26b2643bc3..637f2abb58 100644 --- a/midend/flattenUnions.h +++ b/midend/flattenUnions.h @@ -195,7 +195,7 @@ class FlattenHeaderUnion : public PassManager { passes.push_back(new DoFlattenHeaderUnionStack(refMap, typeMap)); passes.push_back(new P4::ClearTypeMap(typeMap)); passes.push_back(new P4::ResolveReferences(refMap)); - passes.push_back(new P4::TypeInference(refMap, typeMap, false)); + passes.push_back(new P4::TypeInference(typeMap, false)); passes.push_back(new P4::TypeChecking(refMap, typeMap)); passes.push_back(new P4::RemoveAllUnusedDeclarations(refMap, RemoveUnusedPolicy())); } @@ -204,7 +204,7 @@ class FlattenHeaderUnion : public PassManager { passes.push_back(new P4::TypeChecking(refMap, typeMap)); passes.push_back(new P4::RemoveAllUnusedDeclarations(refMap, RemoveUnusedPolicy())); passes.push_back(new P4::RemoveUnusedHUDeclarations(refMap)); - passes.push_back(new P4::RemoveParserIfs(refMap, typeMap)); + passes.push_back(new P4::RemoveParserIfs(typeMap)); } }; } // namespace P4 diff --git a/midend/global_copyprop.cpp b/midend/global_copyprop.cpp index 5c1a0f6679..eb4cb56c23 100644 --- a/midend/global_copyprop.cpp +++ b/midend/global_copyprop.cpp @@ -1,5 +1,7 @@ #include "global_copyprop.h" +#include "frontends/p4/methodInstance.h" + namespace P4 { namespace GlobalCopyProp { diff --git a/midend/has_side_effects.h b/midend/has_side_effects.h index 409f23747c..2d583c580b 100644 --- a/midend/has_side_effects.h +++ b/midend/has_side_effects.h @@ -18,7 +18,7 @@ limitations under the License. #define MIDEND_HAS_SIDE_EFFECTS_H_ #include "frontends/common/resolveReferences/referenceMap.h" -#include "frontends/p4/typeChecking/typeChecker.h" +#include "frontends/p4/methodInstance.h" #include "ir/ir.h" /* Should this be a method on IR::Expression? Maybe after the refMap/typeMap go away */ diff --git a/midend/parserUnroll.h b/midend/parserUnroll.h index 5246c391e9..7e3e718cda 100644 --- a/midend/parserUnroll.h +++ b/midend/parserUnroll.h @@ -298,7 +298,7 @@ class ParsersUnroll : public PassManager { public: ParsersUnroll(bool unroll, ReferenceMap *refMap, TypeMap *typeMap) { // remove block statements - passes.push_back(new SimplifyControlFlow(refMap, typeMap)); + passes.push_back(new SimplifyControlFlow(typeMap)); passes.push_back(new TypeChecking(refMap, typeMap)); passes.push_back(new RewriteAllParsers(refMap, typeMap, unroll)); setName("ParsersUnroll"); diff --git a/midend/removeExits.cpp b/midend/removeExits.cpp index c559ae36d0..e09e84c3ab 100644 --- a/midend/removeExits.cpp +++ b/midend/removeExits.cpp @@ -16,19 +16,20 @@ limitations under the License. #include "removeExits.h" +#include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/p4/methodInstance.h" namespace P4 { namespace { class CallsExit : public Inspector { - ReferenceMap *refMap; + DeclarationLookup *refMap; TypeMap *typeMap; std::set *callers; public: bool callsExit = false; - CallsExit(ReferenceMap *refMap, TypeMap *typeMap, std::set *callers) + CallsExit(DeclarationLookup *refMap, TypeMap *typeMap, std::set *callers) : refMap(refMap), typeMap(typeMap), callers(callers) {} void postorder(const IR::MethodCallExpression *expression) override { auto mi = MethodInstance::resolve(expression, refMap, typeMap); @@ -65,7 +66,7 @@ const IR::Node *DoRemoveExits::preorder(IR::ExitStatement *statement) { const IR::Node *DoRemoveExits::preorder(IR::P4Table *table) { for (auto a : table->getActionList()->actionList) { auto path = a->getPath(); - auto decl = refMap->getDeclaration(path, true); + auto decl = getDeclaration(path, true); BUG_CHECK(decl->is(), "%1% is not an action", decl); if (callsExit.find(decl->getNode()) != callsExit.end()) { callExit(getOriginal()); @@ -100,7 +101,7 @@ const IR::Node *DoRemoveExits::preorder(IR::P4Control *control) { return control; } - cstring var = refMap->newName(variableName.string_view()); + cstring var = nameGen.newName(variableName.string_view()); returnVar = IR::ID(var, nullptr); visit(control->controlLocals, "controlLocals"); @@ -161,9 +162,9 @@ const IR::Node *DoRemoveExits::preorder(IR::BlockStatement *statement) { const IR::Node *DoRemoveExits::preorder(IR::IfStatement *statement) { push(); - CallsExit ce(refMap, typeMap, &callsExit); + CallsExit ce(this, typeMap, &callsExit); ce.setCalledBy(this); - (void)statement->condition->apply(ce); + (void)statement->condition->apply(ce, getChildContext()); auto rcond = ce.callsExit ? TernaryBool::Maybe : TernaryBool::No; visit(statement->ifTrue); @@ -201,9 +202,9 @@ const IR::Node *DoRemoveExits::preorder(IR::IfStatement *statement) { const IR::Node *DoRemoveExits::preorder(IR::SwitchStatement *statement) { auto r = TernaryBool::No; - CallsExit ce(refMap, typeMap, &callsExit); + CallsExit ce(this, typeMap, &callsExit); ce.setCalledBy(this); - (void)statement->expression->apply(ce); + (void)statement->expression->apply(ce), getChildContext(); /* FIXME -- alter cases in place rather than allocating a new Vector */ IR::Vector *cases = nullptr; @@ -237,17 +238,17 @@ const IR::Node *DoRemoveExits::preorder(IR::SwitchStatement *statement) { } const IR::Node *DoRemoveExits::preorder(IR::AssignmentStatement *statement) { - CallsExit ce(refMap, typeMap, &callsExit); + CallsExit ce(this, typeMap, &callsExit); ce.setCalledBy(this); - (void)statement->apply(ce); + (void)statement->apply(ce, getChildContext()); if (ce.callsExit) set(TernaryBool::Maybe); return statement; } const IR::Node *DoRemoveExits::preorder(IR::MethodCallStatement *statement) { - CallsExit ce(refMap, typeMap, &callsExit); + CallsExit ce(this, typeMap, &callsExit); ce.setCalledBy(this); - (void)statement->apply(ce); + (void)statement->apply(ce, getChildContext()); if (ce.callsExit) set(TernaryBool::Maybe); return statement; } diff --git a/midend/removeExits.h b/midend/removeExits.h index e6d1e34971..6c62d2af4f 100644 --- a/midend/removeExits.h +++ b/midend/removeExits.h @@ -17,6 +17,7 @@ limitations under the License. #ifndef MIDEND_REMOVEEXITS_H_ #define MIDEND_REMOVEEXITS_H_ +#include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/removeReturns.h" namespace P4 { @@ -31,15 +32,14 @@ e.g., SideEffectOrdering. if (t1.apply().hit && t2.apply().hit) { ... } It also assumes that there are no global actions and that action calls have been inlined. */ -class DoRemoveExits : public DoRemoveReturns { +class DoRemoveExits : public DoRemoveReturns, public ResolutionContext { TypeMap *typeMap; // In this class "Return" (inherited from RemoveReturns) should be read as "Exit" std::set callsExit; // actions, tables void callExit(const IR::Node *node); public: - DoRemoveExits(ReferenceMap *refMap, TypeMap *typeMap) - : DoRemoveReturns(refMap, "hasExited"_cs), typeMap(typeMap) { + explicit DoRemoveExits(TypeMap *typeMap) : DoRemoveReturns("hasExited"_cs), typeMap(typeMap) { visitDagOnce = false; CHECK_NULL(typeMap); setName("DoRemoveExits"); @@ -60,10 +60,10 @@ class DoRemoveExits : public DoRemoveReturns { class RemoveExits : public PassManager { public: - RemoveExits(ReferenceMap *refMap, TypeMap *typeMap, TypeChecking *typeChecking = nullptr) { - if (!typeChecking) typeChecking = new TypeChecking(refMap, typeMap); + explicit RemoveExits(TypeMap *typeMap, TypeChecking *typeChecking = nullptr) { + if (!typeChecking) typeChecking = new TypeChecking(nullptr, typeMap); passes.push_back(typeChecking); - passes.push_back(new DoRemoveExits(refMap, typeMap)); + passes.push_back(new DoRemoveExits(typeMap)); setName("RemoveExits"); } }; diff --git a/test/gtest/frontend_test.cpp b/test/gtest/frontend_test.cpp index e0bbd17705..31daf6bb57 100644 --- a/test/gtest/frontend_test.cpp +++ b/test/gtest/frontend_test.cpp @@ -33,7 +33,7 @@ struct P4CFrontendEnumValidation : P4CFrontend { P4CFrontendEnumValidation() { addPasses({new P4::ResolveReferences(&refMap), new P4::ConstantFolding(&refMap, nullptr), new P4::ResolveReferences(&refMap), - new P4::TypeInference(&refMap, &typeMap, false, false)}); + new P4::TypeInference(&typeMap, false, false)}); } P4::ReferenceMap refMap; @@ -172,11 +172,7 @@ TEST_F(P4CFrontendEnumValidation, InvalidType) { // Tests for MoveInitializers struct P4CFrontendMoveInitializers : P4CFrontend { - P4CFrontendMoveInitializers() { - addPasses({new P4::ResolveReferences(&refMap), new P4::MoveInitializers(&refMap)}); - } - - P4::ReferenceMap refMap; + P4CFrontendMoveInitializers() { addPasses({new P4::MoveInitializers()}); } }; TEST_F(P4CFrontendMoveInitializers, P4ControlSrcInfo) { diff --git a/test/gtest/midend_pass.cpp b/test/gtest/midend_pass.cpp index ef13f3c0c5..407a521248 100644 --- a/test/gtest/midend_pass.cpp +++ b/test/gtest/midend_pass.cpp @@ -74,19 +74,19 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::SimplifyKey( &refMap, &typeMap, new P4::OrPolicy(new P4::IsValid(&refMap, &typeMap), new P4::IsLikeLeftValue())), - new P4::RemoveExits(&refMap, &typeMap), + new P4::RemoveExits(&typeMap), new P4::ConstantFolding(&refMap, &typeMap), new P4::SimplifySelectCases(&refMap, &typeMap, false), // non-constant keysets new P4::ExpandLookahead(&refMap, &typeMap), new P4::ExpandEmit(&refMap, &typeMap), new P4::HandleNoMatch(&refMap), new P4::SimplifyParsers(&refMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::EliminateTuples(&refMap, &typeMap), new P4::SimplifyComparisons(&refMap, &typeMap), new P4::CopyStructures(&refMap, &typeMap), new P4::NestedStructs(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::SimplifySelectList(&refMap, &typeMap), new P4::RemoveSelectBooleans(&refMap, &typeMap), new P4::FlattenHeaders(&refMap, &typeMap), @@ -98,9 +98,9 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::ConstantFolding(&refMap, &typeMap), new P4::LocalCopyPropagation(&refMap, &typeMap), new P4::ConstantFolding(&refMap, &typeMap), - new P4::StrengthReduction(&refMap, &typeMap), + new P4::StrengthReduction(&typeMap), new P4::MoveDeclarations(), // more may have been introduced - new P4::SimplifyControlFlow(&refMap, &typeMap), + new P4::SimplifyControlFlow(&typeMap), new P4::CompileTimeOperations(), new P4::TableHit(&refMap, &typeMap), new P4::EliminateSwitch(&refMap, &typeMap), diff --git a/test/gtest/midend_test.cpp b/test/gtest/midend_test.cpp index b752bbd066..88e5b3a8ca 100644 --- a/test/gtest/midend_test.cpp +++ b/test/gtest/midend_test.cpp @@ -160,7 +160,7 @@ static void testReplaceSelectRange(std::vector ranges, ExtraTests extraTe TypeMap typeMap; PassManager passes_ = {new P4::ResolveReferences(&refMap), - new P4::TypeInference(&refMap, &typeMap, false), + new P4::TypeInference(&typeMap, false), // properly set types for compound expressions new P4::TypeChecking(&refMap, &typeMap, true), new P4::ReplaceSelectRange(&refMap, &typeMap)}; diff --git a/test/gtest/p4runtime.cpp b/test/gtest/p4runtime.cpp index e562f1e59a..a45c71e2fa 100644 --- a/test/gtest/p4runtime.cpp +++ b/test/gtest/p4runtime.cpp @@ -1658,7 +1658,7 @@ class P4RuntimeDataTypeSpec : public P4Runtime { {"p4runtime_translation"_cs, &P4::ParseAnnotations::parseP4rtTranslationAnnotation}, }), - new P4::ResolveReferences(&refMap), new P4::TypeInference(&refMap, &typeMap, false)}); + new P4::ResolveReferences(&refMap), new P4::TypeInference(&typeMap, false)}); pgm = pgm->apply(passes); return pgm; }