-
Notifications
You must be signed in to change notification settings - Fork 82
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
standard annotations on extern functions/methods #802
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7200,6 +7200,63 @@ The `@match` annotation, described in Section [#sec-select], is used | |
to specify a `match_kind` value other than the default `match_kind` of | ||
`exact` for a field of a `value_set`. | ||
|
||
### Extern function/method annotations { #sec-extern-annotations } | ||
|
||
Various annotations may appear on extern function and method declarations | ||
to describe limitations on the behavior and interactions of those | ||
functions. By default extern functions might have any effect on the | ||
environment of the P4 program and might interact in non-trivial ways. | ||
Since externs are architecture-specific and their behavior is known to | ||
the architecture definition, these annotations are not strictly necessary | ||
(an implementation can have knowledge of how externs interact based | ||
on their names built into it), but these annotations provide a uniform | ||
way of describing certain well-defined interactions (or their absence), | ||
allowing architecture-indepedent analysis of P4 programs. | ||
|
||
- `@pure` - Describes a function that depends solely on its `in` argument | ||
values and has no effect other than its `out` argument values and return | ||
value. No hidden state is recorded between calls, and its value does | ||
not depend on any hidden state that may be changed by other calls. | ||
An example is the `hash` function which computes a deterministic | ||
hash of its arguments. A `@pure` function whose results are unused | ||
may be safely eliminated with no adverse effects, and multiple calls | ||
with identical arguments may be combined into a single call. `@pure` | ||
functions may also be reordered with respect to other computations | ||
that are not data dependent. | ||
|
||
- `@noSideEffects` - Weaker than `@pure` and describes a function that | ||
does not change any hidden state, but may depend on hidden state. | ||
Such a function may be dead code eliminated, and may be reordered | ||
or combined with other `@noSideEffects` or `@pure` calls, but not | ||
with other function calls that may have side effects that affect | ||
the function. | ||
|
||
- `@localState` - When applied to an extern method, the extern method | ||
implementation might read and/or write internal state, but all such | ||
accessed state is limited to state associated directly with the extern | ||
object instance on which the method is called. When applied to an extern | ||
function, the accessible state is restricted to state associated directly | ||
with this extern function. Method and function calls so annotated will | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suspect that for extern functions you imply that they operate on a "singleton" instance of an implicit built-in extern? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is the meaning I was trying to convey by the sentence "When applied to an extern function, the accessible state is restricted to state associated directly with this extern function." There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that is essentially what I was trying to say here. Not clear if introducing the concept of an implicit singleton makes it clearer or less clear though. |
||
never read, nor write, global state of the architecture, nor the state | ||
of any other extern object instance or function. | ||
|
||
- `@packetState` - Similar to `@localState`, except it is even more | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wrote this comment on the compiler PR: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not know if it ever makes sense to have only some methods of an extern be I can say that in v1model and PSA architectures, the only ones that exist where
Details are in this article, where you can look for yes's in the Again, before we try to make localState, localIndexedState, and packetState more precise in the spec, better to decide whether we should leave them out of the spec, at least for now, until and unless they are deemed useful for compiler optimization passes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't at the moment think of an extern where we might want different annotations on different methods, but I'm not sure moving it to the extern (requiring all methods of an extern to be the same) really buys us anything (and it makes the implementation a little more cumbersome.) |
||
restricted in the state that can be accessed. The internal state of the | ||
extern object instance or extern function is partitioned by packets being | ||
processed in the device. The extern method/function can only access the | ||
part of its internal state that is associated with the current packet | ||
being processed by the P4_16 code that made the method/function call. An | ||
annotation of `@packetState` implies an annotation of `@localState`. | ||
|
||
- `@localIndexedState` - Similar to `@localState`, except it is even | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that all these would benefit from at least an example. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before writing examples in the spec, I think it is better to consider leaving localState, localIndexedState, and packetState out of the spec, if they have no known use cases for enabling compiler optimizations. I do think the ideas behind them are useful for documentation purposes, whether they are annotations in the language or not. |
||
more restricted in the state that can be accessed. The internal state | ||
of the extern object instance or extern function is partitioned into an | ||
array of independently accessible sub-states, each with its own index or | ||
associated table entry. The extern method/function call can only access | ||
the internal state associated with that one index, or one table entry, | ||
and no others. An annotation of `@localIndexedState` implies an annotation | ||
of `@localState`. | ||
|
||
### Deprecated annotation { #sec-deprecated-anno } | ||
|
||
The `deprecated` annotation has a required string argument that is a | ||
|
@@ -7329,6 +7386,11 @@ The following table shows all P4 reserved annotations. | |
| `optional` | parameter is optional | [#sec-optional-parameter-annotations] | | ||
| `tableonly` | action cannot be a defalt_action | [#sec-table-action-anno] | | ||
| `deprecated` | Construct has been deprecated | [#sec-deprecated-anno] | | ||
| `pure` | pure function | [#sec-extern-annotations] | | ||
| `noSideEffects` | function with no side effects | [#sec-extern-annotations] | | ||
| `localState` | limited hidden state | [#sec-extern-annotations] | | ||
| `packetState` | limited hidden state | [#sec-extern-annotations] | | ||
| `localIndexedState`| limited hidden state | [#sec-extern-annotations] | | ||
|---------------|----------------------------------------------------|--------------------------| | ||
|
||
# Appendix: P4 core library { #sec-p4-core-lib } | ||
|
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 we do not know when the hidden state may be mutated this may make reordering difficult.
Perhaps we want to discuss also
@synchronous
and@asynchronous
annotations, because I suspect thatnoSideEffects
functions are only allowed to operate on state that is changed synchronously - by other operations invoked explicitly from the dataplane.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.
I am happy to discuss the meaning of synchronous and asynchronous annotations, as it isn't clear to me yet what they are intended to mean, at least not in a precise covers-all-cases kind of way.
I am assuming that a compiler can never really use one of these proposed annotations in isolation and assume it can do safe optimizations based only upon that, but most know globally about the effects of all possible methods on an extern.
Does that change the meaning of the proposed @nosideeffects annotation, though? Or is it a caution to compiler optimization pass writers, who are hopefully already a cautious group of folks? :-)