Skip to content

Commit 61d3b70

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

File tree

2 files changed

+73
-41
lines changed

2 files changed

+73
-41
lines changed

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

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,7 +1289,7 @@ There are also built-in types for
12891289
representing constructs such as parsers, pipelines, actions, and
12901290
tables. Users can
12911291
construct new types based on these: structures, enumerations, headers,
1292-
header stacks, header unions, etc.
1292+
arrays, header stacks, header unions, etc.
12931293

12941294
In this document we adopt the following conventions:
12951295

@@ -1398,6 +1398,7 @@ include::grammar.adoc[tag=lvalue]
13981398
* Identifiers of a base or derived type.
13991399
* Structure, header, and header union field member access operations
14001400
(using the dot notation).
1401+
* References to elements within arrays (see <<sec-expr-array>>)
14011402
* References to elements within header stacks (see
14021403
<<sec-expr-hs>>): indexing, and references to `last` and `next`.
14031404
* The result of a bit-slice operator `[m:l]`.
@@ -1597,8 +1598,8 @@ There are additional benefits of using copy-in copy-out semantics:
15971598

15981599
* It enables P4 to be compiled for architectures that do not support
15991600
references (e.g., where all data is allocated to named
1600-
registers. Such architectures may require indices into header stacks that appear
1601-
in a program to be compile-time known values.)
1601+
registers. Such architectures may require indices into arrays and header
1602+
stacks that appear in a program to be compile-time known values.)
16021603
* It simplifies some compiler analyses, since function parameters can
16031604
never alias to each other within the function body.
16041605

@@ -2108,6 +2109,7 @@ additional types including:
21082109

21092110
* `enum`
21102111
* `header`
2112+
* arrays
21112113
* header stacks
21122114
* `struct`
21132115
* `header_union`
@@ -2375,22 +2377,30 @@ parsing steps.
23752377
Notice that the names `isValid`, `setValid`, `minSizeInBits`, etc. are all
23762378
valid header field names.
23772379

2378-
[#sec-header-stacks]
2379-
==== Header stacks
2380+
[#sec-arrays]
2381+
==== Arrays
23802382

2381-
A header stack represents an array of headers or header unions. A header stack type is
2382-
defined as:
2383+
An array is a fixed-size vector of elements of the same type. It is defined as:
23832384

23842385
[source,bison]
23852386
----
2386-
include::grammar.adoc[tag=headerStackType]
2387+
include::grammar.adoc[tag=arrayType]
23872388
----
23882389

2389-
where `typeName` is the name of a header or header union type. For a
2390+
where `typeRef` refers to the element type and the expression is a compile-time
2391+
known value that is the size of the array. For an array type such as `arr[n]`,
2392+
`n-1` is the maximum defined index.
2393+
2394+
[#sec-header-stacks]
2395+
==== Header stacks
2396+
2397+
A header stack represents an array of headers or header unions. A header stack type is
2398+
defined as an array declaration
2399+
where `typeRef` is the name of a header or header union type. For a
23902400
header stack `hs[n]`, the term `n` is the maximum defined size, and
23912401
must be a local compile-time known value that is a positive
23922402
integer. Nested header stacks are not supported. At runtime a stack
2393-
contains `n` values with type `typeName`, only some of which may be
2403+
contains `n` values with type `typeRef`, only some of which may be
23942404
valid. Expressions on header stacks are discussed in Section
23952405
<<#sec-expr-hs>>.
23962406

@@ -2526,39 +2536,41 @@ arbitrary-precision integer, without a width specified.
25262536
|===
25272537
| Element type 5+^| Container kind
25282538

2529-
| | header | header_union | struct or tuple | list | header stack
2539+
| | header | header_union | struct or tuple | list | array [4] | header stack
25302540

2531-
| `bit<W>` | allowed | error | allowed | allowed | error
2541+
| `bit<W>` | allowed | error | allowed | allowed | allowed | error
25322542

2533-
| `int<W>` | allowed | error | allowed | allowed | error
2543+
| `int<W>` | allowed | error | allowed | allowed | allowed | error
25342544

2535-
| `varbit<W>` | allowed | error | allowed | allowed | error
2545+
| `varbit<W>` | allowed | error | allowed | allowed | allowed | error
25362546

2537-
| `int` | error | error | error | allowed | error
2547+
| `int` | error | error | error | allowed | error | error
25382548

2539-
| `void` | error | error | error | error | error
2549+
| `void` | error | error | error | error | error | error
25402550

2541-
| `string` | error | error | error | allowed | error
2551+
| `string` | error | error | error | allowed | error | error
25422552

2543-
| `error` | error | error | allowed | allowed | error
2553+
| `error` | error | error | allowed | allowed | error | error
25442554

2545-
| `match_kind` | error | error | error | allowed | error
2555+
| `match_kind` | error | error | error | allowed | error | error
25462556

2547-
| `bool` | allowed | error | allowed | allowed | error
2557+
| `bool` | allowed | error | allowed | allowed | allowed | error
25482558

2549-
| `enumeration types` | allowed [1] | error | allowed | allowed | error
2559+
| `enumeration types` | allowed [1] | error | allowed | allowed | allowed | error
25502560

2551-
| `header types` | error | allowed | allowed | allowed | allowed
2561+
| `header types` | error | allowed | allowed | allowed | NA [3] | allowed
25522562

2553-
| `header stacks` | error | error | allowed | allowed | error
2563+
| `array types` [4] | allowed | error | allowed | error? | allowed [5] | error
25542564

2555-
| `header_unions` | error | error | allowed | allowed | allowed
2565+
| `header stacks` | error | error | allowed | allowed | error | error
25562566

2557-
| `struct types` | allowed [2] | error | allowed | allowed | error
2567+
| `header_unions` | error | error | allowed | allowed | NA [3] | allowed
25582568

2559-
| `tuple types` | error | error | allowed | allowed | error
2569+
| `struct types` | allowed [2] | error | allowed | allowed | allowed | error
25602570

2561-
| `list types` | error | error | error | allowed | error
2571+
| `tuple types` | error | error | allowed | allowed | error? | error
2572+
2573+
| `list types` | error | error | error | allowed | error? | error
25622574

25632575
|===
25642576

@@ -2569,6 +2581,14 @@ underlying type and representation for `enum` elements.
25692581
used as a field in a `header` must contain only `bit<W>`, `int<W>`, a
25702582
serializable `enum`, or a `bool`.
25712583

2584+
[3] An array whose element type is a header or header union type is a
2585+
header stack.
2586+
2587+
[4] This is for array types that are not header stacks (the array element
2588+
type is not a header or header_union)
2589+
2590+
[5] Architectures may disallow arrays of arrays
2591+
25722592
Rationale: `int` does not have precise storage requirements,
25732593
unlike `bit<>` or `int<>` types. `match_kind`
25742594
values are not useful to store in a variable, as they
@@ -2609,6 +2629,8 @@ The table below lists all types that may appear as base types in a
26092629

26102630
| enumeration types | allowed | error
26112631

2632+
| array types | allowed | error
2633+
26122634
| header types | allowed | error
26132635

26142636
| header stacks | allowed | error
@@ -2980,6 +3002,7 @@ as follows:
29803002
even if 0 is actually not one of the named values in the enum.
29813003
* For `enum` values without an underlying type the default value is the
29823004
first value that appears in the `enum` type declaration.
3005+
* For arrays the default value is that all elements have their default value.
29833006
* For `header` types the default value is `invalid`.
29843007
* For header stacks the default value is that all elements are invalid and the
29853008
`nextIndex` is 0.
@@ -3879,7 +3902,7 @@ The following casts are legal in P4:
38793902
* casts between a type introduced by `type` and the original type.
38803903
* casts between an `enum` with an explicit type and its underlying type
38813904
* casts of a key-value list to a struct type or a header type (see <<sec-structure-expressions>>)
3882-
* casts of a tuple expression to a header stack type
3905+
* casts of a tuple expression to an array or header stack type
38833906
* casts of an invalid expression `+{#}+` to a header or a header union type
38843907
* casts where the destination type is the same as the source type
38853908
if the destination type appears in this list (this excludes
@@ -3896,7 +3919,7 @@ expression with a fixed-width type will implicitly cast the `int`
38963919
expression to the type of the other expression. For enums with an underlying
38973920
type, it can be implicitly cast to its underlying type whenever appropriate,
38983921
including but not limited to in shifts, concatenation, bit slicing indexes,
3899-
header stack indexes as well as other unary and binary operations.
3922+
array and header stack indexes as well as other unary and binary operations.
39003923

39013924
For example, given the following declarations,
39023925

@@ -4431,6 +4454,16 @@ for a description of the behavior if header fields are read without
44314454
being initialized, or header fields are written to a currently invalid
44324455
header.
44334456

4457+
[#sec-expr-array]
4458+
=== Operations on arrays
4459+
4460+
Arrays can be indexed with an expression to select one element of the
4461+
array. `arr[index]` refers to that element and is an l-value if `arr` is
4462+
an l-value.
4463+
4464+
Arrays can be assigned to another array with the same element type and
4465+
size.
4466+
44344467
[#sec-expr-hs]
44354468
=== Operations on header stacks
44364469

@@ -5321,7 +5354,7 @@ headers and other header-related types, which are initialized to invalid in the
53215354
same way as described for direction `out` parameters in <<sec-calling-convention>>). The language places few restrictions on
53225355
the types of the variables: most P4 types that can be written
53235356
explicitly can be used (e.g., base types, `struct`, `header`,
5324-
header stack, `tuple`). However, it is impossible to declare variables with type `int`,
5357+
array, header stack, `tuple`). However, it is impossible to declare variables with type `int`,
53255358
or with types that are only synthesized by the compiler (e.g., `set`)
53265359
In addition, variables of type `parser`, `control`, `package`,
53275360
or `extern` types must be declared using instantiations (see <<sec-instantiations>>).
@@ -5596,7 +5629,7 @@ following behavior after the expression evaluation is interrupted.
55965629
then neither expression `e2` nor `e3` are evaluated.
55975630
** If the expression is the right hand side of an assignment
55985631
statement, or part of the calculation of the L-value on the left
5599-
hand side (e.g. the index expression of a header stack reference),
5632+
hand side (e.g. the index expression of an array or header stack reference),
56005633
then no assignment occurs.
56015634
** If the expression is an argument passed to a function or method
56025635
call, then the function/method call does not occur.
@@ -5752,7 +5785,7 @@ The update statements will be executed after the loop body and before evaluating
57525785
condition again for the next iteration.
57535786

57545787
The `for`-`in` statement executes the body once for each value in a range or each
5755-
element in a list expression or header stack. The list or range expression itself
5788+
element in a list expression, array or header stack. The list or range expression itself
57565789
will only be evaluated once, before the first iteration of the loop. All side effects
57575790
in the list or range expression will occur before the first iteration of the loop body.
57585791

@@ -7837,11 +7870,11 @@ extern packet_out {
78377870
----
78387871

78397872
The `emit` method supports appending the data contained in a
7840-
header, header stack, `struct`, or header union to the output packet.
7873+
header, array, header stack, `struct`, or header union to the output packet.
78417874

78427875
- When applied to a header, `emit` appends the data in the header to
78437876
the packet if it is valid and otherwise behaves like a no-op.
7844-
- When applied to a header stack, `emit` recursively invokes itself to
7877+
- When applied to an array or header stack, `emit` recursively invokes itself to
78457878
each element of the stack.
78467879
- When applied to a `struct` or header union, `emit` recursively
78477880
invokes itself to each field. Note, a `struct` must not contain
@@ -9279,7 +9312,7 @@ error {
92799312
NoError, /// No error.
92809313
PacketTooShort, /// Not enough bits in packet for 'extract'.
92819314
NoMatch, /// 'select' expression has no matches.
9282-
StackOutOfBounds, /// Reference to invalid element of a header stack.
9315+
StackOutOfBounds, /// Reference to invalid element of an array or header stack.
92839316
HeaderTooShort, /// Extracting too many bits into a varbit field.
92849317
ParserTimeout, /// Parser execution time limit exceeded.
92859318
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
@@ -506,7 +506,7 @@ typeRef
506506
: baseType
507507
| typeName
508508
| specializedType
509-
| headerStackType
509+
| arrayType
510510
| p4listType
511511
| tupleType
512512
;
@@ -544,12 +544,11 @@ tupleType
544544
;
545545
// end::tupleType[]
546546

547-
// tag::headerStackType[]
548-
headerStackType
549-
: typeName "[" expression "]"
550-
| specializedType "[" expression "]"
547+
// tag::arrayType[]
548+
arrayType
549+
: typeRef "[" expression "]"
551550
;
552-
// end::headerStackType[]
551+
// end::arrayType[]
553552

554553
// tag::specializedType[]
555554
specializedType

0 commit comments

Comments
 (0)