-
Notifications
You must be signed in to change notification settings - Fork 447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make HasTableApply a resolution context, so it could resolve declarations on its own if desired #4781
Conversation
@ChrisDodd So, this is one case where The problem is as follows:
As a result, we cannot pass Any ideas how to solve this in generic and non error-prone way are welcome :) |
For something like |
@@ -28,7 +28,7 @@ limitations under the License. | |||
namespace P4 { | |||
|
|||
/// Checks to see whether an IR node includes a table.apply() sub-expression | |||
class HasTableApply : public Inspector { | |||
class HasTableApply : public Inspector, public ResolutionContext { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you make HasTableApply
a ResolutionContext
, you don't need the refMap
field in it any more -- you just use this
. However, as HasTableApply
is only ever called on expressions, there won't be any additional scopes to look things up in within it's visit traversal -- the innermost scope will be the same as the caller. So I don't see how this affects anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is still called with refmap somewhere in the midend. And I do not want to trigger set of changes there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it does affect exactly due to outlined case, see
const IR::Vector<IR::Argument> *ResolutionContext::methodArguments(cstring name) const { |
So, KeySideEffects
cannot resolve overload, it it "further down".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment here that this needs to be ResolutionContext
so that if we are working without a P4::ReferenceMap
we have the call in context for the sake of MethodInstance::resolve
.
I mean literally, where const IR::Node *postorder(IR::AssignmentStatement *statement) override {
return doStatement(statement, statement->right, getContext());
} Note that LOG3("Visiting " << getOriginal());
HasTableApply hta(typeMap);
hta.setCalledBy(this);
(void)expression->apply(hta, ctxt); So, we cannot have |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, this is quite tricky. But I absolutely see why the call itself needs to be on the context.
We should at least add some bug check that allows catching these problems in MethodInstance
. Possibly to ResolutionContext::resolveUnique
(something like !decls[0]->is<IR::IFunction>() || argumets
after more than one decl
is found). Or possibly to MethodInstance
to check somehow that the mce
is in context of the refMap
, but that seems both more complex to do and less general.
@@ -28,7 +28,7 @@ limitations under the License. | |||
namespace P4 { | |||
|
|||
/// Checks to see whether an IR node includes a table.apply() sub-expression | |||
class HasTableApply : public Inspector { | |||
class HasTableApply : public Inspector, public ResolutionContext { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment here that this needs to be ResolutionContext
so that if we are working without a P4::ReferenceMap
we have the call in context for the sake of MethodInstance::resolve
.
Yes, I was thinking to |
94cae53
to
3d02b37
Compare
The problem here could be that |
I don't see this at all. The only issue with using In fact, if you look at this example (issue4775) it has no problem finding the definition of |
It is not problem of finding const IR::Vector<IR::Argument> *ResolutionContext::methodArguments(cstring name) const {
const Context *ctxt = getChildContext();
while (ctxt) {
const auto *node = ctxt->original;
const IR::MethodCallExpression *mc = nullptr;
if (const auto *mcs = node->to<IR::MethodCallStatement>())
mc = mcs->methodCall;
else
mc = node->to<IR::MethodCallExpression>();
if (mc) {
if (const auto *mem = mc->method->to<IR::Member>()) {
if (mem->member == name) return mc->arguments;
}
if (const auto *path = mc->method->to<IR::PathExpression>()) {
if (path->path->name == name) return mc->arguments;
}
break;
}
if (const auto *decl = node->to<IR::Declaration_Instance>()) {
if (decl->name == name) return decl->arguments;
if (const auto *type = decl->type->to<IR::Type_Name>()) {
if (type->path->name == name) return decl->arguments;
}
if (const auto *ts = decl->type->to<IR::Type_Specialized>()) {
if (ts->baseType->path->name == name) return decl->arguments;
}
break;
}
if (ctxt->node->is<IR::Expression>() || ctxt->node->is<IR::Type>())
ctxt = ctxt->parent;
else
break;
}
LOG4("No arguments found for calling " << name << " in " << ctxt->node);
return nullptr;
} In the issue4775 case, the
|
Oh, I see what you mean. In fact, |
Ah, ok, now I understand what you were talking about -- the problem being that methodArguments could not find the MethodCallExpression to get the arguments, as the wrong Visitor::Context was being used for the lookup (an earlier one that doesn't include the MethodCall). Longer term, it might help to merge ResolutionContext into the Visitor class directly -- that way every visitor is automatically a ResolutionContext. There's no real cost to this -- Visitor already maintains the Visitor::Context chain, which is what is being used for the lookup. The main (remaining) error foot-gun is calling |
I suggest also modifying midend/simplifyKey.cpp as:
which allows getting rid of the |
Exactly.
I was also thinking of always providing context to Still, there are few interesting cases (like in Evaluator or Inliner) where we are have, say, call, but we'd need to resolve something in the callee context... |
That could work -- basically, getDeclaration becomes a free function and takes a
The tricky thing here is that if you want to recurse into the callee in the same visitor, you should NOT use the context of MethodCall doing the call -- the context should be the scope where the method was found. Otherwise you would accidentally do dynamic scoping, and symbols in the callee scope would be visible and might shadow globals. This won't happen if you call UniqueNames first (which will rename things so there is no shadowing), so maybe it is not necessary to worry about this too much -- UniqueNames gets called in the frontend before we ever call the Evaluator or Inliner for precisely this purpose (mostly for Inlining, since that actually rewrites the code, and would have problems if locals could shadow globals, regardless of what happens with the Visitor::Context) |
BTW, if you do include the mod to midend/simplifyKey.cpp above, you'll also need:
There's that foot-gun of calling |
Yes. Alternatively – we do have |
Possible, but I don't thing setCalledBy is called reliably either. However, using that when ctxt == nullptr could cover more cases. |
...or we could put in BUG_CHECKs for when the setCalledBy parent context and the apply context are inconsistent. Make all the code call both properly. |
cbf84a2
to
309a8ad
Compare
I removed As for |
I think there are a number of ways we could try to make the use of ResolutionContext safer and/or clearer
If we ever do manage to completely eliminate the reference maps, then some of the cost could be reduced. |
frontends/p4/sideEffects.h
Outdated
/// | ||
/// Note: when working without refMap, we need to have a call on the context, | ||
/// so ResolutionContext could find the original declaration (invoked inside | ||
/// MethodInstance::resolve). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update the comment as there is no longer an option to work with refMap
…ions on its own if desired Fixes p4lang#4775 Signed-off-by: Anton Korobeynikov <[email protected]>
Signed-off-by: Anton Korobeynikov <[email protected]>
Fixes #4775