Skip to content

Commit db7da5c

Browse files
committed
Add arrays of non-header types
Signed-off-by: Chris Dodd <[email protected]>
1 parent 72732bd commit db7da5c

File tree

2 files changed

+77
-41
lines changed

2 files changed

+77
-41
lines changed

p4-16/spec/P4-16-spec.adoc

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,7 @@ There are also built-in types for
13071307
representing constructs such as parsers, pipelines, actions, and
13081308
tables. Users can
13091309
construct new types based on these: structures, enumerations, headers,
1310-
header stacks, header unions, etc.
1310+
arrays, header stacks, header unions, etc.
13111311

13121312
In this document we adopt the following conventions:
13131313

@@ -1416,6 +1416,7 @@ include::grammar.adoc[tag=lvalue]
14161416
* Identifiers of a base or derived type.
14171417
* Structure, header, and header union field member access operations
14181418
(using the dot notation).
1419+
* References to elements within arrays (see <<sec-expr-array>>)
14191420
* References to elements within header stacks (see
14201421
<<sec-expr-hs>>): indexing, and references to `last` and `next`.
14211422
* The result of a bit-slice operator `[m:l]`.
@@ -1615,8 +1616,8 @@ There are additional benefits of using copy-in copy-out semantics:
16151616

16161617
* It enables P4 to be compiled for architectures that do not support
16171618
references (e.g., where all data is allocated to named
1618-
registers. Such architectures may require indices into header stacks that appear
1619-
in a program to be compile-time known values.)
1619+
registers. Such architectures may require indices into arrays and header
1620+
stacks that appear in a program to be compile-time known values.)
16201621
* It simplifies some compiler analyses, since function parameters can
16211622
never alias to each other within the function body.
16221623

@@ -2131,6 +2132,7 @@ additional types including:
21312132

21322133
* `enum`
21332134
* `header`
2135+
* arrays
21342136
* header stacks
21352137
* `struct`
21362138
* `header_union`
@@ -2398,22 +2400,30 @@ parsing steps.
23982400
Notice that the names `isValid`, `setValid`, `minSizeInBits`, etc. are all
23992401
valid header field names.
24002402

2401-
[#sec-header-stacks]
2402-
==== Header stacks
2403+
[#sec-arrays]
2404+
==== Arrays
24032405

2404-
A header stack represents an array of headers or header unions. A header stack type is
2405-
defined as:
2406+
An array is a fixed-size vector of elements of the same type. It is defined as:
24062407

24072408
[source,bison]
24082409
----
2409-
include::grammar.adoc[tag=headerStackType]
2410+
include::grammar.adoc[tag=arrayType]
24102411
----
24112412

2412-
where `typeName` is the name of a header or header union type. For a
2413+
where `typeRef` refers to the element type and the expression is a compile-time
2414+
known value that is the size of the array. For an array type such as `arr[n]`,
2415+
`n-1` is the maximum defined index.
2416+
2417+
[#sec-header-stacks]
2418+
==== Header stacks
2419+
2420+
A header stack represents an array of headers or header unions. A header stack type is
2421+
defined as an array declaration
2422+
where `typeRef` is the name of a header or header union type. For a
24132423
header stack `hs[n]`, the term `n` is the maximum defined size, and
24142424
must be a local compile-time known value that is a positive
24152425
integer. Nested header stacks are not supported. At runtime a stack
2416-
contains `n` values with type `typeName`, only some of which may be
2426+
contains `n` values with type `typeRef`, only some of which may be
24172427
valid. Expressions on header stacks are discussed in Section
24182428
<<#sec-expr-hs>>.
24192429

@@ -2549,39 +2559,43 @@ arbitrary-precision integer, without a width specified.
25492559
|===
25502560
| Element type 5+^| Container kind
25512561

2552-
| | header | header_union | struct or tuple | list | header stack
2562+
| | header | header_union | struct or tuple | list | array [4] | header stack
2563+
2564+
| `bit<W>` | allowed | error | allowed | allowed | allowed | error
25532565

2554-
| `bit<W>` | allowed | error | allowed | allowed | error
2566+
| `int<W>` | allowed | error | allowed | allowed | allowed | error
25552567

2556-
| `int<W>` | allowed | error | allowed | allowed | error
2568+
| `varbit<W>` | allowed | error | allowed | allowed | allowed | error
25572569

2558-
| `varbit<W>` | allowed | error | allowed | allowed | error
2570+
| `int` | error | error | error | allowed | error | error
25592571

2560-
| `int` | error | error | error | allowed | error
2572+
| `void` | error | error | error | error | error | error
25612573

2562-
| `void` | error | error | error | error | error
2574+
| `string` | error | error | error | allowed | error | error
25632575

2564-
| `string` | error | error | error | allowed | error
2576+
| `error` | error | error | allowed | allowed | error | error
25652577

2566-
| `error` | error | error | allowed | allowed | error
2578+
| `match_kind` | error | error | error | allowed | error | error
25672579

2568-
| `match_kind` | error | error | error | allowed | error
2580+
| `bool` | allowed | error | allowed | allowed | allowed | error
25692581

2570-
| `bool` | allowed | error | allowed | allowed | error
2582+
| `enumeration types` | allowed [1] | error | allowed | allowed | allowed | error
25712583

2572-
| `enumeration types` | allowed [1] | error | allowed | allowed | error
2584+
| `header types` | error | allowed | allowed | allowed | NA [3] | allowed
25732585

2574-
| `header types` | error | allowed | allowed | allowed | allowed
2586+
| `array types` [4] | allowed | error | allowed | error? | allowed [5] | error
25752587

2576-
| `header stacks` | error | error | allowed | allowed | error
2588+
| `header stacks` | error | error | allowed | allowed | error | error
25772589

2578-
| `header_unions` | error | error | allowed | allowed | allowed
2590+
| `header_unions` | error | error | allowed | allowed | NA [3] | allowed
25792591

2580-
| `struct types` | allowed [2] | error | allowed | allowed | error
2592+
| `struct types` | allowed [2] | error | allowed | allowed | allowed | error
25812593

2582-
| `tuple types` | error | error | allowed | allowed | error
2594+
| `tuple types` | error | error | allowed | allowed | error? | error
25832595

2584-
| `list types` | error | error | error | allowed | error
2596+
| `list types` | error | error | error | allowed | error? | error
2597+
2598+
| `extern instances` | error | error | error | erroe | allowed [6] | error
25852599

25862600
|===
25872601

@@ -2592,6 +2606,16 @@ underlying type and representation for `enum` elements.
25922606
used as a field in a `header` must contain only `bit<W>`, `int<W>`, a
25932607
serializable `enum`, or a `bool`.
25942608

2609+
[3] An array whose element type is a header or header union type is a
2610+
header stack.
2611+
2612+
[4] This is for array types that are not header stacks (the array element
2613+
type is not a header or header_union)
2614+
2615+
[5] Architectures may disallow arrays of arrays
2616+
2617+
[6] Architectures may disallow arrays of extern instances
2618+
25952619
Rationale: `int` does not have precise storage requirements,
25962620
unlike `bit<>` or `int<>` types. `match_kind`
25972621
values are not useful to store in a variable, as they
@@ -2632,6 +2656,8 @@ The table below lists all types that may appear as base types in a
26322656

26332657
| enumeration types | allowed | error
26342658

2659+
| array types | allowed | error
2660+
26352661
| header types | allowed | error
26362662

26372663
| header stacks | allowed | error
@@ -2999,6 +3025,7 @@ as follows:
29993025
even if 0 is actually not one of the named values in the enum.
30003026
* For `enum` values without an underlying type the default value is the
30013027
first value that appears in the `enum` type declaration.
3028+
* For arrays the default value is that all elements have their default value.
30023029
* For `header` types the default value is `invalid`.
30033030
* For header stacks the default value is that all elements are invalid and the
30043031
`nextIndex` is 0.
@@ -3917,7 +3944,7 @@ The following casts are legal in P4:
39173944
* casts between a type introduced by `type` and the original type.
39183945
* casts between an `enum` with an explicit type and its underlying type
39193946
* casts of a key-value list to a struct type or a header type (see <<sec-structure-expressions>>)
3920-
* casts of a tuple expression to a header stack type
3947+
* casts of a tuple expression to an array or header stack type
39213948
* casts of an invalid expression `+{#}+` to a header or a header union type
39223949
* casts where the destination type is the same as the source type
39233950
if the destination type appears in this list (this excludes
@@ -3934,7 +3961,7 @@ expression with a fixed-width type will implicitly cast the `int`
39343961
expression to the type of the other expression. For enums with an underlying
39353962
type, it can be implicitly cast to its underlying type whenever appropriate,
39363963
including but not limited to in shifts, concatenation, bit slicing indexes,
3937-
header stack indexes as well as other unary and binary operations.
3964+
array and header stack indexes as well as other unary and binary operations.
39383965

39393966
For example, given the following declarations,
39403967

@@ -4469,6 +4496,16 @@ for a description of the behavior if header fields are read without
44694496
being initialized, or header fields are written to a currently invalid
44704497
header.
44714498

4499+
[#sec-expr-array]
4500+
=== Operations on arrays
4501+
4502+
Arrays can be indexed with an expression to select one element of the
4503+
array. `arr[index]` refers to that element and is an l-value if `arr` is
4504+
an l-value.
4505+
4506+
Arrays can be assigned to another array with the same element type and
4507+
size.
4508+
44724509
[#sec-expr-hs]
44734510
=== Operations on header stacks
44744511

@@ -5359,7 +5396,7 @@ headers and other header-related types, which are initialized to invalid in the
53595396
same way as described for direction `out` parameters in <<sec-calling-convention>>). The language places few restrictions on
53605397
the types of the variables: most P4 types that can be written
53615398
explicitly can be used (e.g., base types, `struct`, `header`,
5362-
header stack, `tuple`). However, it is impossible to declare variables with type `int`,
5399+
array, header stack, `tuple`). However, it is impossible to declare variables with type `int`,
53635400
or with types that are only synthesized by the compiler (e.g., `set`)
53645401
In addition, variables of type `parser`, `control`, `package`,
53655402
or `extern` types must be declared using instantiations (see <<sec-instantiations>>).
@@ -5645,7 +5682,7 @@ following behavior after the expression evaluation is interrupted.
56455682
then neither expression `e2` nor `e3` are evaluated.
56465683
** If the expression is the right hand side of an assignment
56475684
statement, or part of the calculation of the L-value on the left
5648-
hand side (e.g. the index expression of a header stack reference),
5685+
hand side (e.g. the index expression of an array or header stack reference),
56495686
then no assignment occurs.
56505687
** If the expression is an argument passed to a function or method
56515688
call, then the function/method call does not occur.
@@ -5813,7 +5850,7 @@ The update statements will be executed after the loop body and before evaluating
58135850
condition again for the next iteration.
58145851

58155852
The `for`-`in` statement executes the body once for each value in a range or each
5816-
element in a list expression or header stack. The list or range expression itself
5853+
element in a list expression, array or header stack. The list or range expression itself
58175854
will only be evaluated once, before the first iteration of the loop. All side effects
58185855
in the list or range expression will occur before the first iteration of the loop body.
58195856

@@ -7904,11 +7941,11 @@ extern packet_out {
79047941
----
79057942

79067943
The `emit` method supports appending the data contained in a
7907-
header, header stack, `struct`, or header union to the output packet.
7944+
header, array, header stack, `struct`, or header union to the output packet.
79087945

79097946
- When applied to a header, `emit` appends the data in the header to
79107947
the packet if it is valid and otherwise behaves like a no-op.
7911-
- When applied to a header stack, `emit` recursively invokes itself to
7948+
- When applied to an array or header stack, `emit` recursively invokes itself to
79127949
each element of the stack.
79137950
- When applied to a `struct` or header union, `emit` recursively
79147951
invokes itself to each field. Note, a `struct` must not contain
@@ -9386,7 +9423,7 @@ error {
93869423
NoError, /// No error.
93879424
PacketTooShort, /// Not enough bits in packet for 'extract'.
93889425
NoMatch, /// 'select' expression has no matches.
9389-
StackOutOfBounds, /// Reference to invalid element of a header stack.
9426+
StackOutOfBounds, /// Reference to invalid element of an array or header stack.
93909427
HeaderTooShort, /// Extracting too many bits into a varbit field.
93919428
ParserTimeout, /// Parser execution time limit exceeded.
93929429
ParserInvalidArgument /// Parser operation was called with a value

p4-16/spec/grammar.adoc

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ typeRef
516516
: baseType
517517
| typeName
518518
| specializedType
519-
| headerStackType
519+
| arrayType
520520
| p4listType
521521
| tupleType
522522
;
@@ -554,12 +554,11 @@ tupleType
554554
;
555555
// end::tupleType[]
556556

557-
// tag::headerStackType[]
558-
headerStackType
559-
: typeName "[" expression "]"
560-
| specializedType "[" expression "]"
557+
// tag::arrayType[]
558+
arrayType
559+
: typeRef "[" expression "]"
561560
;
562-
// end::headerStackType[]
561+
// end::arrayType[]
563562

564563
// tag::specializedType[]
565564
specializedType

0 commit comments

Comments
 (0)