Skip to content
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

Fixes for issue #818 and #819 #821

Merged
merged 1 commit into from
Aug 7, 2017
Merged
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
6 changes: 4 additions & 2 deletions frontends/p4/directCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
namespace P4 {

const IR::Node* DoInstantiateCalls::postorder(IR::P4Parser* parser) {
parser->parserLocals.append(insert);
insert.append(parser->parserLocals);
parser->parserLocals = insert;
insert.clear();
return parser;
}

const IR::Node* DoInstantiateCalls::postorder(IR::P4Control* control) {
control->controlLocals.append(insert);
insert.append(control->controlLocals);
control->controlLocals = insert;
insert.clear();
return control;
}
Expand Down
66 changes: 55 additions & 11 deletions frontends/p4/typeChecking/typeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,22 @@ bool TypeInference::done() const {
return done;
}

const IR::Type* TypeInference::getType(const IR::Node* element, bool verbose) const {
const IR::Type* TypeInference::getType(const IR::Node* element) const {
const IR::Type* result = typeMap->getType(element);
if (result == nullptr && verbose)
typeError("Could not find type of %1%", element);
// This should be happening only when type-checking already failed
// for some node; we are now just trying to typecheck a parent node.
// So an error should have already been signalled.
if ((result == nullptr) && (::errorCount() == 0))
BUG("Could not find type of %1%", element);
return result;
}

const IR::Type* TypeInference::getTypeType(const IR::Node* element) const {
const IR::Type* result = typeMap->getType(element);
// See comment in getType() above.
if (result == nullptr) {
typeError("Could not find type of %1%", element);
if (::errorCount() == 0)
BUG("Could not find type of %1%", element);
return nullptr;
}
BUG_CHECK(result->is<IR::Type_Type>(), "%1%: expected a TypeType", dbp(result));
Expand Down Expand Up @@ -274,6 +279,8 @@ const IR::Type* TypeInference::canonicalize(const IR::Type* type) {
type->is<IR::Type_Action>() ||
type->is<IR::Type_Error>()) {
return type;
} else if (type->is<IR::Type_Dontcare>()) {
return IR::Type_Dontcare::get();
} else if (type->is<IR::Type_Base>()) {
if (!type->is<IR::Type_Bits>())
// all other base types are singletons
Expand Down Expand Up @@ -492,7 +499,18 @@ const IR::Type* TypeInference::canonicalize(const IR::Type* type) {

IR::Vector<IR::Type> *args = new IR::Vector<IR::Type>();
for (const IR::Type* a : *st->arguments) {
const IR::Type* canon = canonicalize(a);
auto atype = getTypeType(a);
if (atype == nullptr)
return nullptr;
if (atype->is<IR::Type_Control>() ||
atype->is<IR::Type_Parser>() ||
atype->is<IR::Type_Package>() ||
atype->is<IR::P4Parser>() ||
atype->is<IR::P4Control>()) {
typeError("%1%: Cannot use %2% as a type parameter", type, atype);
return nullptr;
}
const IR::Type* canon = canonicalize(atype);
if (canon == nullptr)
return nullptr;
args->push_back(canon);
Expand Down Expand Up @@ -727,6 +745,13 @@ TypeInference::checkExternConstructor(const IR::Node* errorPosition,
if (argType == nullptr || paramType == nullptr)
return nullptr;

if (paramType->is<IR::Type_Control>() ||
paramType->is<IR::Type_Parser>() ||
paramType->is<IR::P4Control>() ||
paramType->is<IR::P4Parser>() ||
paramType->is<IR::Type_Package>())
typeError("%1%: parameter cannot have type %2%", pi, paramType);

auto tvs = unify(errorPosition, paramType, argType, true);
if (tvs == nullptr) {
// error already signalled
Expand Down Expand Up @@ -1012,6 +1037,18 @@ const IR::Node* TypeInference::postorder(IR::Type_Name* typeName) {
type = new IR::Type_Type(t);
} else {
auto decl = refMap->getDeclaration(typeName->path, true);
// Check for references of a control or parser within itself.
auto ctrl = findContext<IR::P4Control>();
if (ctrl != nullptr && ctrl->name == decl->getName()) {
typeError("%1%: Cannot refer to control inside itself", typeName);
return typeName;
}
auto parser = findContext<IR::P4Parser>();
if (parser != nullptr && parser->name == decl->getName()) {
typeError("%1%: Cannot refer parser inside itself", typeName);
return typeName;
}

type = getType(decl->getNode());
if (type == nullptr)
return typeName;
Expand Down Expand Up @@ -1377,14 +1414,21 @@ const IR::Node* TypeInference::preorder(IR::EntriesList* el) {
prune();
return el;
}
auto keyTuple = getType(key, false);
auto keyTuple = typeMap->getType(key); // direct typeMap call to skip checks
if (keyTuple == nullptr) {
typeError("Could not find type for table key %1%", key);
prune();
return el;
// The keys have to be before the entries list. If they are not,
// at this point they have not yet been type-checked.
if (key->srcInfo.isValid() && el->srcInfo.isValid() && key->srcInfo >= el->srcInfo) {
typeError("%1%: Entries list must be after table key %2%",
el, key);
prune();
return el;
}
// otherwise the type-checking of the keys must have failed
}
return el;
}

/**
* typecheck a table initializer entry
*
Expand All @@ -1408,9 +1452,9 @@ const IR::Node* TypeInference::postorder(IR::Entry* entry) {
if (key == nullptr)
return entry;
auto keyTuple = getType(key);
if (keyTuple == nullptr) {
if (keyTuple == nullptr)
return entry;
}

auto entryKeyType = getType(entry->keys);
if (entryKeyType == nullptr)
return entry;
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/typeChecking/typeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class TypeInference : public Transform {
bool readOnly = false);

protected:
const IR::Type* getType(const IR::Node* element, bool verbose = true) const;
const IR::Type* getType(const IR::Node* element) const;
const IR::Type* getTypeType(const IR::Node* element) const;
void setType(const IR::Node* element, const IR::Type* type);
void setLeftValue(const IR::Expression* expression)
Expand Down
2 changes: 1 addition & 1 deletion frontends/parsers/p4/p4parser.ypp
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ typeParameterList

typeArg
: typeRef { $$ = $1; }
| "_" { $$ = IR::Type_Dontcare::get(); }
| "_" { $$ = new IR::Type_Dontcare(@1); }
;

typeArgumentList
Expand Down
50 changes: 50 additions & 0 deletions testdata/p4_16_errors/issue818.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <core.p4>

// Architecture
parser P();
control C();
package S(P p);
extern BoolReg {
BoolReg();
bool get();
void flip();
}
extern WrapControl {
WrapControl(C c);
void execute();
}

// User Program
BoolReg() r;

parser Loop()(WrapControl c1, WrapControl c2) {
state start {
r.flip();
transition select(r.get()) {
true: q1;
false: q2;
default: accept;
}
}
state q1 {
c1.execute();
transition start;
}
state q2 {
c2.execute();
transition start;
}
}

control MyC1() {
apply {
// Code for Control 1
}
}
control MyC2() {
apply {
// Code for Control 2
}
}

S(Loop(WrapControl(MyC1()), WrapControl(MyC2()))) main;
33 changes: 33 additions & 0 deletions testdata/p4_16_errors/issue819-1.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <core.p4>

// Architecture
control C();
package S(C c);

extern WrapControls<T1,T2> {
WrapControls(T1 t1, T2 t2);
void execute1(); // invokes c1.apply on self
void execute2(); // invokes c2.apply on self
}

//User Program
control MyC1(WrapControls wc) {
apply {
wc.execute2();
}
}
control MyC2(WrapControls wc) {
apply {
wc.execute1();
}
}
control MyC3() {
MyC1() c1;
MyC2() c2;
WrapControls<MyC1,MyC2>(c1,c2) wc;
apply {
c1.apply(wc);
}
}

S(MyC3()) main;
33 changes: 33 additions & 0 deletions testdata/p4_16_errors/issue819.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <core.p4>

// Architecture
control C();
package S(C c);

extern WrapControls<T1,T2> {
WrapControls(T1 t1, T2 t2);
void execute1(); // invokes c1.apply on self
void execute2(); // invokes c2.apply on self
}

//User Program
control MyC1(WrapControls<_,_> wc) {
apply {
wc.execute2();
}
}
control MyC2(WrapControls<_,_> wc) {
apply {
wc.execute1();
}
}
control MyC3() {
MyC1() c1;
MyC2() c2;
WrapControls<MyC1,MyC2>(c1,c2) wc;
apply {
c1.apply(wc);
}
}

S(MyC3()) main;
1 change: 0 additions & 1 deletion testdata/p4_16_errors/table-entries-decl-order.p4
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ control ingress(inout Header_t h, inout Meta_t m, inout standard_metadata_t stan
action a() { standard_meta.egress_spec = 0; }
action a_with_control_params(bit<9> x) { standard_meta.egress_spec = x; }


table t_ternary {

#if ENABLE_NEGATIVE_TESTS
Expand Down
15 changes: 0 additions & 15 deletions testdata/p4_16_errors_outputs/binary_e.p4-stderr
Original file line number Diff line number Diff line change
@@ -1,30 +1,15 @@
binary_e.p4(32): error: Array indexing [] applied to non-array type int<2>
c = a[2]; // not an array
^^^^
binary_e.p4(32): error: Could not find type of []
c = a[2]; // not an array
^^^^
binary_e.p4(33): error: Array index d must be an integer, but it has type bool
c = stack[d]; // indexing with bool
^
binary_e.p4(33): error: Could not find type of []
c = stack[d]; // indexing with bool
^^^^^^^^
binary_e.p4(35): error: &: Cannot operate on values with different types bit<2> and bit<4>
f = e & f; // different width
^^^^^
binary_e.p4(35): error: Could not find type of &
f = e & f; // different width
^^^^^
binary_e.p4(38): error: <: not defined on bool and bool
d = d < d; // not defined on bool
^^^^^
binary_e.p4(38): error: Could not find type of <
d = d < d; // not defined on bool
^^^^^
binary_e.p4(39): error: >: not defined on int<2> and int<4>
d = a > c; // different width
^^^^^
binary_e.p4(39): error: Could not find type of >
d = a > c; // different width
^^^^^
9 changes: 0 additions & 9 deletions testdata/p4_16_errors_outputs/bitExtract_e.p4-stderr
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
bitExtract_e.p4(25): error: s[3:0]: bit extraction only defined for bit<> types
bit<4> x = s[3:0]; // wrong type for s
^^^^^^
bitExtract_e.p4(25): error: Could not find type of s[3:0]
bit<4> x = s[3:0]; // wrong type for s
^^^^^^
bitExtract_e.p4(26): error: Bit index 7 greater than width 4
bit<8> y = dt[7:0]; // too many bits
^
bitExtract_e.p4(26): error: Could not find type of dt[7:0]
bit<8> y = dt[7:0]; // too many bits
^^^^^^^
bitExtract_e.p4(27): error: Bit index 7 greater than width 4
bit<4> z = dt[7:4]; // too many bits
^
bitExtract_e.p4(27): error: Could not find type of dt[7:4]
bit<4> z = dt[7:4]; // too many bits
^^^^^^^
12 changes: 0 additions & 12 deletions testdata/p4_16_errors_outputs/div1.p4-stderr
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
: not defined on negative numbers
a = a / -1; // not defined for negative numbers
^^^^^^

a = a / -1; // not defined for negative numbers
^^^^^^
: not defined on negative numbers
a = -5 / a;
^^^^^^

a = -5 / a;
^^^^^^
div1.p4(20): error: %: not defined on negative numbers
a = a % -1;
^^^^^^
div1.p4(20): error: Could not find type of %
a = a % -1;
^^^^^^
div1.p4(21): error: %: not defined on negative numbers
a = -5 % a;
^^^^^^
div1.p4(21): error: Could not find type of %
a = -5 % a;
^^^^^^
24 changes: 0 additions & 24 deletions testdata/p4_16_errors_outputs/extern.p4-stderr
Original file line number Diff line number Diff line change
@@ -1,30 +1,6 @@
extern.p4(19): error: x: a parameter with an extern type cannot have a direction
control c(in X x) { // Cannot have externs with direction
^
extern.p4(19): error: Could not find type of control c
control c(in X x) { // Cannot have externs with direction
^
extern.p4(24): error: x: a parameter with an extern type cannot have a direction
control proto(in X x);
^
extern.p4(24): error: Could not find type of control proto
control proto(in X x);
^^^^^
extern.p4(25): error: Could not find type of proto
package top(proto _c);
^^^^^
extern.p4(25): error: Could not find type of _c
package top(proto _c);
^^
extern.p4(25): error: Could not find type of package top
package top(proto _c);
^^^
extern.p4(19): error: Could not find type of control c
control c(in X x) { // Cannot have externs with direction
^
extern.p4(27): error: Could not find type of c
top(c()) main;
^
extern.p4(27): error: Could not find type of top
top(c()) main;
^^^
Loading