P4C
The P4 Compiler
Loading...
Searching...
No Matches
resolveReferences.h
1/*
2 * SPDX-FileCopyrightText: 2013 Barefoot Networks, Inc.
3 * Copyright 2013-present Barefoot Networks, Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef FRONTENDS_COMMON_RESOLVEREFERENCES_RESOLVEREFERENCES_H_
9#define FRONTENDS_COMMON_RESOLVEREFERENCES_RESOLVEREFERENCES_H_
10
11#include "absl/container/flat_hash_map.h"
12#include "absl/container/inlined_vector.h"
13#include "frontends/common/parser_options.h"
14#include "ir/ir.h"
15#include "ir/pass_manager.h"
16#include "lib/cstring.h"
17#include "lib/iterator_range.h"
18#include "referenceMap.h"
19
20namespace P4 {
21
23enum class ResolutionType { Any, Type, TypeVariable };
24
26class ResolutionContext : virtual public Visitor, public DeclarationLookup {
27 private:
28 // Returns a vector of the decls that exist in the given namespace, and caches the result
29 // for future lookups.
30 const std::vector<const IR::IDeclaration *> &memoizeDeclarations(
31 const IR::INamespace *ns) const;
32
33 using DeclsVector = absl::InlinedVector<const IR::IDeclaration *, 2>;
34 using NamespaceDeclsByName = absl::flat_hash_map<cstring, DeclsVector, Util::Hash>;
35
36 // Returns a mapping from name -> decl for the given namespace, and caches the result for
37 // future lookups.
38 NamespaceDeclsByName &memoizeDeclsByName(const IR::INamespace *ns) const;
39
40 mutable absl::flat_hash_map<const IR::INamespace *, std::vector<const IR::IDeclaration *>,
42 namespaceDecls;
43 mutable absl::flat_hash_map<const IR::INamespace *, NamespaceDeclsByName, Util::Hash>
44 namespaceDeclNames;
45
46 protected:
47 // Note that all errors have been merged by the parser into
48 // a single error { } namespace.
49 std::vector<const IR::IDeclaration *> lookup(const IR::INamespace *ns, const IR::ID &name,
50 ResolutionType type) const;
51
52 // match kinds exist in their own special namespace, made from all the match_kind
53 // declarations in the global scope. Unlike errors, we don't merge those scopes in
54 // the parser, so we have to find them and scan them here.
55 std::vector<const IR::IDeclaration *> lookupMatchKind(const IR::ID &name) const;
56
57 // P4_14 allows things to be used before their declaration while P4_16 (generally)
58 // does not, so we will resolve names to things declared later only when translating
59 // from P4_14 or Type_Vars or ParserStates, or after code transforms that may reorder
60 // the code.
61 bool anyOrder = false;
62
63 ResolutionContext();
64 explicit ResolutionContext(bool ao) : anyOrder(ao) {}
65
68
69 public:
71 std::vector<const IR::IDeclaration *> resolve(const IR::ID &name, ResolutionType type) const;
72
74 const IR::IDeclaration *resolveUnique(const IR::ID &name, ResolutionType type,
75 const IR::INamespace * = nullptr) const;
76
79 virtual const IR::IDeclaration *resolvePath(const IR::Path *path, bool isType) const;
80
82 const IR::Type *resolveType(const IR::Type *type) const;
83
84 const IR::IDeclaration *getDeclaration(const IR::Path *path,
85 bool notNull = false) const override;
86 const IR::IDeclaration *getDeclaration(const IR::This *, bool notNull = false) const override;
87
89 auto getDeclarations(const IR::INamespace *ns) const {
90 auto nsIt = namespaceDecls.find(ns);
91 const auto &decls = nsIt != namespaceDecls.end() ? nsIt->second : memoizeDeclarations(ns);
92 return Util::iterator_range(decls);
93 }
94
96 auto getDeclsByName(const IR::INamespace *ns, cstring name) const {
97 auto nsIt = namespaceDeclNames.find(ns);
98 const auto &namesToDecls =
99 nsIt != namespaceDeclNames.end() ? nsIt->second : memoizeDeclsByName(ns);
100
101 auto decls = namesToDecls.find(name);
102 if (decls == namesToDecls.end())
103 return Util::Enumerator<const IR::IDeclaration *>::emptyEnumerator();
104 return Util::enumerate(decls->second);
105 }
106};
107
115class ResolveReferences : public Inspector, private ResolutionContext {
117 ReferenceMap *refMap;
118
120 bool checkShadow;
121
122 private:
125 const IR::IDeclaration *resolvePath(const IR::Path *path, bool isType) const override;
126
127 public:
128 explicit ResolveReferences(/* out */ P4::ReferenceMap *refMap, bool checkShadow = false);
129
130 Visitor::profile_t init_apply(const IR::Node *node) override;
131 void end_apply(const IR::Node *node) override;
132
133 bool preorder(const IR::Type_Name *type) override;
134 bool preorder(const IR::PathExpression *path) override;
135 bool preorder(const IR::KeyElement *path) override;
136 bool preorder(const IR::This *pointer) override;
137 bool preorder(const IR::Declaration_Instance *decl) override;
138
139 bool preorder(const IR::P4Program *t) override;
140 void postorder(const IR::P4Program *t) override;
141 bool preorder(const IR::P4Control *t) override;
142 bool preorder(const IR::P4Parser *t) override;
143 bool preorder(const IR::P4Action *t) override;
144 bool preorder(const IR::Function *t) override;
145 bool preorder(const IR::TableProperties *t) override;
146 bool preorder(const IR::Type_Method *t) override;
147 bool preorder(const IR::ParserState *t) override;
148 bool preorder(const IR::Type_Extern *t) override;
149 bool preorder(const IR::Type_ArchBlock *t) override;
150 void postorder(const IR::Type_ArchBlock *t) override;
151 bool preorder(const IR::Type_StructLike *t) override;
152 bool preorder(const IR::BlockStatement *t) override;
153
154 bool preorder(const IR::P4Table *table) override;
155 bool preorder(const IR::Declaration *d) override {
156 refMap->usedName(d->getName().name);
157 return true;
158 }
159 bool preorder(const IR::Type_Declaration *d) override {
160 refMap->usedName(d->getName().name);
161 return true;
162 }
163
164 void checkShadowing(const IR::INamespace *ns) const;
165};
166
167class CheckShadowing : public PassManager {
168 ReferenceMap refMap;
169
170 public:
171 CheckShadowing() {
172 refMap.setIsV1(P4CContext::get().options().isv1());
173
174 addPasses({new ResolveReferences(&refMap, /* checkShadow */ true)});
175 setName("CheckShadowing");
176 }
177};
178
179} // namespace P4
180
181#endif /* FRONTENDS_COMMON_RESOLVEREFERENCES_RESOLVEREFERENCES_H_ */
Definition referenceMap.h:48
The Declaration interface, representing objects with names.
Definition declaration.h:17
Definition node.h:44
Definition ir/vector.h:50
Definition visitor.h:409
static P4CContext & get()
Definition parser_options.cpp:523
Class used to encode maps from paths to declarations.
Definition referenceMap.h:58
void setIsV1(bool isv1)
Set boolean indicating whether map is for a P4_14 program to isV1.
Definition referenceMap.h:97
std::vector< const IR::IDeclaration * > resolve(const IR::ID &name, ResolutionType type) const
Resolve references for name, restricted to type declarations.
Definition resolveReferences.cpp:37
auto getDeclsByName(const IR::INamespace *ns, cstring name) const
Returns the set of decls with the given name that exist in the given namespace.
Definition resolveReferences.h:96
auto getDeclarations(const IR::INamespace *ns) const
Returns the set of decls that exist in the given namespace.
Definition resolveReferences.h:89
virtual const IR::IDeclaration * resolvePath(const IR::Path *path, bool isType) const
Definition resolveReferences.cpp:301
const IR::Vector< IR::Argument > * methodArguments(cstring name) const
We are resolving a method call. Find the arguments from the context.
Definition resolveReferences.cpp:173
const IR::Type * resolveType(const IR::Type *type) const
Resolve a refrence to a type type.
Definition resolveReferences.cpp:288
const IR::IDeclaration * resolveUnique(const IR::ID &name, ResolutionType type, const IR::INamespace *=nullptr) const
Resolve reference for name, restricted to type declarations, and expect one result.
Definition resolveReferences.cpp:213
Definition resolveReferences.h:115
Definition iterator_range.h:44
Definition visitor.h:69
Definition cstring.h:76
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:13
ResolutionType
Helper class to indicate types of nodes that may be returned during resolution.
Definition resolveReferences.h:23
Definition id.h:19
Definition hash.h:125