Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions frontends/p4/typeChecking/typeCheckExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1893,15 +1893,8 @@ const IR::Expression *TypeInferenceBase::actionCall(bool inActionList,
typeError("%1%: parameter %2% cannot be bound: it is set by the control plane", arg,
param);
} else if (inTable) {
// For actions None parameters are treated as IN
// parameters when the action is called directly. We
// don't require them to be bound to a compile-time
// constant. But if the action is instantiated in a
// table (as default_action or entries), then the
// arguments do have to be compile-time constants.
if (!isCompileTimeConstant(arg->expression))
typeError("%1%: action argument must be a compile-time constant",
arg->expression);
// Directionless action parameters behave like 'in'
// parameters even when used in tables (P4 Spec Section 6.8).
}
// This is like an assignment; may make additional conversions.
newExpr = assignment(arg, param->type, arg->expression);
Expand Down
74 changes: 74 additions & 0 deletions testdata/p4_16_errors_outputs/issue473-first.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <core.p4>
#define V1MODEL_VERSION 20180101
#include <v1model.p4>

typedef bit<48> EthernetAddress;
header Ethernet_h {
EthernetAddress dstAddr;
EthernetAddress srcAddr;
bit<16> etherType;
}

struct Parsed_packet {
Ethernet_h ethernet;
}

struct mystruct1 {
bit<4> a;
bit<4> b;
bit<32> c;
bit<32> d;
}

control DeparserI(packet_out packet, in Parsed_packet hdr) {
apply {
packet.emit<Ethernet_h>(hdr.ethernet);
}
}

parser parserI(packet_in pkt, out Parsed_packet hdr, inout mystruct1 meta, inout standard_metadata_t stdmeta) {
state start {
pkt.extract<Ethernet_h>(hdr.ethernet);
transition accept;
}
}

control cIngress(inout Parsed_packet hdr, inout mystruct1 meta, inout standard_metadata_t stdmeta) {
action a1(in bit<32> x) {
meta.b = meta.b + (bit<4>)x;
meta.b = (bit<4>)((bit<32>)meta.b + x);
}
action b(inout bit<32> x, bit<8> data) {
meta.a = meta.a ^ (bit<4>)x ^ (bit<4>)data;
}
table t1 {
key = {
hdr.ethernet.srcAddr: exact @name("hdr.ethernet.srcAddr");
}
actions = {
a1((bit<32>)meta.a);
b(meta.c);
}
default_action = b(meta.c, (bit<8>)meta.d);
}
apply {
t1.apply();
}
}

control cEgress(inout Parsed_packet hdr, inout mystruct1 meta, inout standard_metadata_t stdmeta) {
apply {
}
}

control vc(inout Parsed_packet hdr, inout mystruct1 meta) {
apply {
}
}

control uc(inout Parsed_packet hdr, inout mystruct1 meta) {
apply {
}
}

V1Switch<Parsed_packet, mystruct1>(parserI(), vc(), cIngress(), cEgress(), uc(), DeparserI()) main;
79 changes: 79 additions & 0 deletions testdata/p4_16_errors_outputs/issue473-frontend.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <core.p4>
#define V1MODEL_VERSION 20180101
#include <v1model.p4>

typedef bit<48> EthernetAddress;
header Ethernet_h {
EthernetAddress dstAddr;
EthernetAddress srcAddr;
bit<16> etherType;
}

struct Parsed_packet {
Ethernet_h ethernet;
}

struct mystruct1 {
bit<4> a;
bit<4> b;
bit<32> c;
bit<32> d;
}

control DeparserI(packet_out packet, in Parsed_packet hdr) {
apply {
packet.emit<Ethernet_h>(hdr.ethernet);
}
}

parser parserI(packet_in pkt, out Parsed_packet hdr, inout mystruct1 meta, inout standard_metadata_t stdmeta) {
state start {
pkt.extract<Ethernet_h>(hdr.ethernet);
transition accept;
}
}

control cIngress(inout Parsed_packet hdr, inout mystruct1 meta, inout standard_metadata_t stdmeta) {
@name("cIngress.x") bit<32> x_0;
@name("cIngress.x") bit<32> x_1;
@name("cIngress.a1") action a1() {
x_0 = (bit<32>)meta.a;
meta.b = meta.b + (bit<4>)x_0;
meta.b = (bit<4>)((bit<32>)meta.b + x_0);
}
@name("cIngress.b") action b_1(@name("data") bit<8> data_1) {
x_1 = meta.c;
meta.a = meta.a ^ (bit<4>)x_1 ^ (bit<4>)data_1;
meta.c = x_1;
}
@name("cIngress.t1") table t1_0 {
key = {
hdr.ethernet.srcAddr: exact @name("hdr.ethernet.srcAddr");
}
actions = {
a1();
b_1();
}
default_action = b_1((bit<8>)meta.d);
}
apply {
t1_0.apply();
}
}

control cEgress(inout Parsed_packet hdr, inout mystruct1 meta, inout standard_metadata_t stdmeta) {
apply {
}
}

control vc(inout Parsed_packet hdr, inout mystruct1 meta) {
apply {
}
}

control uc(inout Parsed_packet hdr, inout mystruct1 meta) {
apply {
}
}

V1Switch<Parsed_packet, mystruct1>(parserI(), vc(), cIngress(), cEgress(), uc(), DeparserI()) main;
73 changes: 73 additions & 0 deletions testdata/p4_16_errors_outputs/issue473-midend.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <core.p4>
#define V1MODEL_VERSION 20180101
#include <v1model.p4>

header Ethernet_h {
bit<48> dstAddr;
bit<48> srcAddr;
bit<16> etherType;
}

struct Parsed_packet {
Ethernet_h ethernet;
}

struct mystruct1 {
bit<4> a;
bit<4> b;
bit<32> c;
bit<32> d;
}

control DeparserI(packet_out packet, in Parsed_packet hdr) {
apply {
packet.emit<Ethernet_h>(hdr.ethernet);
}
}

parser parserI(packet_in pkt, out Parsed_packet hdr, inout mystruct1 meta, inout standard_metadata_t stdmeta) {
state start {
pkt.extract<Ethernet_h>(hdr.ethernet);
transition accept;
}
}

control cIngress(inout Parsed_packet hdr, inout mystruct1 meta, inout standard_metadata_t stdmeta) {
@name("cIngress.a1") action a1() {
meta.b = meta.b + (bit<4>)(bit<32>)meta.a;
meta.b = (bit<4>)((bit<32>)meta.b + (bit<32>)meta.a);
}
@name("cIngress.b") action b_1(@name("data") bit<8> data_1) {
meta.a = meta.a ^ (bit<4>)meta.c ^ (bit<4>)data_1;
}
@name("cIngress.t1") table t1_0 {
key = {
hdr.ethernet.srcAddr: exact @name("hdr.ethernet.srcAddr");
}
actions = {
a1();
b_1();
}
default_action = b_1((bit<8>)meta.d);
}
apply {
t1_0.apply();
}
}

control cEgress(inout Parsed_packet hdr, inout mystruct1 meta, inout standard_metadata_t stdmeta) {
apply {
}
}

control vc(inout Parsed_packet hdr, inout mystruct1 meta) {
apply {
}
}

control uc(inout Parsed_packet hdr, inout mystruct1 meta) {
apply {
}
}

V1Switch<Parsed_packet, mystruct1>(parserI(), vc(), cIngress(), cEgress(), uc(), DeparserI()) main;
4 changes: 2 additions & 2 deletions testdata/p4_16_errors_outputs/issue473.p4-stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
issue473.p4(70): [--Werror=type-error] error: (bit<8>)meta.d: action argument must be a compile-time constant
issue473.p4(70): [--Werror=unsupported] error: meta.d unsupported argument expression of type Type_Bits
default_action = b(meta.c, (bit<8>) meta.d);
^^^^^^^^^^^^^^^
^^^^^^
3 changes: 3 additions & 0 deletions testdata/p4_16_errors_outputs/issue473.p4.entries.txtpb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# proto-file: p4/v1/p4runtime.proto
# proto-message: p4.v1.WriteRequest

50 changes: 50 additions & 0 deletions testdata/p4_16_errors_outputs/issue473.p4.p4info.txtpb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# proto-file: p4/config/v1/p4info.proto
# proto-message: p4.config.v1.P4Info

pkg_info {
arch: "v1model"
}
tables {
preamble {
id: 39254368
name: "cIngress.t1"
alias: "t1"
}
match_fields {
id: 1
name: "hdr.ethernet.srcAddr"
bitwidth: 48
match_type: EXACT
}
action_refs {
id: 21211318
}
action_refs {
id: 26584255
}
initial_default_action {
action_id: 26584255
}
size: 1024
}
actions {
preamble {
id: 21211318
name: "cIngress.a1"
alias: "a1"
}
}
actions {
preamble {
id: 26584255
name: "cIngress.b"
alias: "b"
}
params {
id: 1
name: "data"
bitwidth: 8
}
}
type_info {
}
83 changes: 83 additions & 0 deletions testdata/p4_16_samples/issue5042.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
Copyright 2026 Deval Gupta

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
* Test for issue #5042: Directionless action parameters should accept
* non-compile-time-known values when provided by the P4 program.
* Per P4 Spec Section 6.8, such parameters behave as 'in' direction.
*/

#include <core.p4>
#include <v1model.p4>

header h_t {
bit<8> f;
}

struct metadata_t {
bit<8> x;
}

struct headers_t {
h_t h;
}

parser p(packet_in pkt, out headers_t hdr, inout metadata_t meta,
inout standard_metadata_t std_meta) {
state start {
pkt.extract(hdr.h);
meta.x = hdr.h.f;
transition accept;
}
}

control ingress(inout headers_t hdr, inout metadata_t meta,
inout standard_metadata_t std_meta) {
// Action with directionless parameter 'data'
action a(bit<8> data) {
hdr.h.f = data;
}

table t {
key = { hdr.h.f : exact; }
actions = { a; }
}

apply {
a(meta.x);
t.apply();
}
}

control egress(inout headers_t hdr, inout metadata_t meta,
inout standard_metadata_t std_meta) {
apply { }
}

control deparser(packet_out pkt, in headers_t hdr) {
apply { pkt.emit(hdr.h); }
}

control verifyChecksum(inout headers_t hdr, inout metadata_t meta) {
apply { }
}

control computeChecksum(inout headers_t hdr, inout metadata_t meta) {
apply { }
}

V1Switch(p(), verifyChecksum(), ingress(), egress(),
computeChecksum(), deparser()) main;
Loading
Loading