Skip to content

Commit

Permalink
Fix for issue #314 (#315)
Browse files Browse the repository at this point in the history
* Fixed bugs in EBPF back-end; made the 'builder' argument into a field

* cpplint fix

* Removed useless decl

* Support for ebpf control-plane: .h file

* Deleted one line by mistake

* Support for functions; control-plane table initialization

* Support for enum types in ebpf

* Fix for issue #314
  • Loading branch information
Mihai Budiu authored and ChrisDodd committed Feb 21, 2017
1 parent 6e2b06d commit 1e1a1e0
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 2 deletions.
39 changes: 38 additions & 1 deletion frontends/p4/def_use.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace P4 {

// name for header valid bit
const cstring StorageFactory::validFieldName = "$valid";
const cstring StorageFactory::indexFieldName = "$lastIndex";
const LocationSet* LocationSet::empty = new LocationSet();
ProgramPoint ProgramPoint::beforeStart;

Expand Down Expand Up @@ -62,6 +63,7 @@ StorageLocation* StorageFactory::create(const IR::Type* type, cstring name) cons
auto sl = create(st->elementType, name + "[" + Util::toString(i) + "]");
result->addElement(i, sl);
}
result->setLastIndexField(create(IR::Type_Bits::get(32), name + "." + indexFieldName));
return result;
}
return nullptr;
Expand All @@ -85,6 +87,11 @@ void StructLocation::addValidBits(LocationSet* result) const {
}
}

void StructLocation::addLastIndexField(LocationSet* result) const {
for (auto f : fields())
f->addLastIndexField(result);
}

void StructLocation::addField(cstring field, LocationSet* result) const {
auto f = ::get(fieldLocations, field);
CHECK_NULL(f);
Expand All @@ -102,6 +109,11 @@ void ArrayLocation::addValidBits(LocationSet* result) const {
e->addValidBits(result);
}

void ArrayLocation::addLastIndexField(LocationSet* result) const {
result->add(getLastIndexField());
}


void ArrayLocation::addElement(unsigned index, LocationSet* result) const {
BUG_CHECK(index < elements.size(), "%1%: out of bounds index", index);
result->add(elements.at(index));
Expand All @@ -113,6 +125,12 @@ const LocationSet* StorageLocation::getValidBits() const {
return result;
}

const LocationSet* StorageLocation::getLastIndexField() const {
auto result = new LocationSet();
addLastIndexField(result);
return result;
}

const LocationSet* LocationSet::join(const LocationSet* other) const {
CHECK_NULL(other);
if (this == LocationSet::empty)
Expand All @@ -125,6 +143,18 @@ const LocationSet* LocationSet::join(const LocationSet* other) const {
return result;
}

const LocationSet* LocationSet::getArrayLastIndex() const {
auto result = new LocationSet();
for (auto l : locations) {
if (l->is<ArrayLocation>()) {
auto array = l->to<ArrayLocation>();
result->add(array->getLastIndexField());
}
}
return result;
}


const LocationSet* LocationSet::getField(cstring field) const {
auto result = new LocationSet();
for (auto l : locations) {
Expand Down Expand Up @@ -338,6 +368,8 @@ void ComputeWriteSet::enterScope(const IR::ParameterList* parameters,
defs->set(loc, uninit);
auto valid = loc->getValidBits();
defs->set(valid, startPoints);
auto lastIndex = loc->getLastIndexField();
defs->set(lastIndex, startPoints);
}
if (locals != nullptr) {
for (auto d : *locals) {
Expand All @@ -347,6 +379,8 @@ void ComputeWriteSet::enterScope(const IR::ParameterList* parameters,
defs->set(loc, uninit);
auto valid = loc->getValidBits();
defs->set(valid, startPoints);
auto lastIndex = loc->getLastIndexField();
defs->set(lastIndex, startPoints);
}
}
}
Expand All @@ -357,7 +391,7 @@ void ComputeWriteSet::enterScope(const IR::ParameterList* parameters,
}

void ComputeWriteSet::exitScope(const IR::ParameterList* parameters,
const IR::IndexedVector<IR::Declaration>* locals) {
const IR::IndexedVector<IR::Declaration>* locals) {
currentDefinitions = currentDefinitions->clone();
for (auto p : *parameters->parameters) {
StorageLocation* loc = definitions->storageMap->getStorage(p);
Expand Down Expand Up @@ -475,6 +509,9 @@ bool ComputeWriteSet::preorder(const IR::Member* expression) {
expression->member.name == IR::Type_Stack::last) {
set(expression, storage);
return false;
} else if (expression->member.name == IR::Type_Stack::lastIndex) {
set(expression, LocationSet::empty);
return false;
}
}

Expand Down
16 changes: 15 additions & 1 deletion frontends/p4/def_use.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class StorageLocation : public IHasDbPrint {
// set of locations if we exclude all headers
const LocationSet* removeHeaders() const;
virtual void removeHeaders(LocationSet* result) const = 0;
// all locations inside that represent the last index of an array
const LocationSet* getLastIndexField() const;
virtual void addLastIndexField(LocationSet* result) const = 0;
};

/* Represents a storage location with a simple type.
Expand All @@ -68,6 +71,7 @@ class BaseLocation : public StorageLocation {
|| type-is<IR::Type_Error>() || type->is<IR::Type_Var>(),
"%1%: unexpected type", type); }
void addValidBits(LocationSet*) const override {}
void addLastIndexField(LocationSet* result) const override {}
void removeHeaders(LocationSet* result) const override;
};

Expand All @@ -92,22 +96,28 @@ class StructLocation : public StorageLocation {
void addField(cstring field, LocationSet* addTo) const;
void addValidBits(LocationSet* result) const override;
void removeHeaders(LocationSet* result) const override;
void addLastIndexField(LocationSet* result) const override;
};

class ArrayLocation : public StorageLocation {
std::vector<const StorageLocation*> elements;
const StorageLocation* lastIndexField; // accessed by lastIndex
friend class StorageFactory;

void addElement(unsigned index, StorageLocation* element)
{ elements[index] = element; CHECK_NULL(element); }

public:
ArrayLocation(const IR::Type* type, cstring name) :
StorageLocation(type, name) {
StorageLocation(type, name), lastIndexField(nullptr) {
BUG_CHECK(type->is<IR::Type_Stack>(), "%1%: unexpected type", type);
auto stack = type->to<IR::Type_Stack>();
elements.resize(stack->getSize());
}
void setLastIndexField(const StorageLocation* location)
{ lastIndexField = location; }
const StorageLocation* getLastIndexField() const
{ return lastIndexField; }
std::vector<const StorageLocation*>::const_iterator begin() const
{ return elements.cbegin(); }
std::vector<const StorageLocation*>::const_iterator end() const
Expand All @@ -119,6 +129,7 @@ class ArrayLocation : public StorageLocation {
void addElement(unsigned index, LocationSet* result) const;
void addValidBits(LocationSet* result) const override;
void removeHeaders(LocationSet*) const override {} // no results added
void addLastIndexField(LocationSet* result) const override;
};

class StorageFactory {
Expand All @@ -129,6 +140,7 @@ class StorageFactory {
StorageLocation* create(const IR::Type* type, cstring name) const;

static const cstring validFieldName;
static const cstring indexFieldName;
};

// A set of locations that may be read or written by a computation.
Expand All @@ -146,6 +158,8 @@ class LocationSet : public IHasDbPrint {
const LocationSet* getValidField() const;
const LocationSet* getIndex(unsigned index) const;
const LocationSet* allElements() const;
const LocationSet* getArrayLastIndex() const;

void add(const StorageLocation* location)
{ locations.emplace(location); }
const LocationSet* join(const LocationSet* other) const;
Expand Down
5 changes: 5 additions & 0 deletions frontends/p4/simplifyDefUse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,11 @@ class FindUninitialized : public Inspector {
reads(expression, storage);
registerUses(expression, false);
return;
} else if (expression->member.name == IR::Type_Stack::lastIndex) {
auto index = storage->getArrayLastIndex();
reads(expression, index);
registerUses(expression, false);
return;
}
}

Expand Down
36 changes: 36 additions & 0 deletions testdata/p4_16_samples/issue314.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Copyright 2017 VMware, Inc.
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.
*/

#include <core.p4>

header header_h {
bit<8> field;
}

struct struct_t {
header_h[4] stack;
}

parser Parser(inout struct_t input) {
state start {
input.stack[input.stack.lastIndex].field = 8w1;
transition accept;
}
}

parser MyParser<S>(inout S input);
package MyPackage<S>(MyParser<S> p);
MyPackage(Parser()) main;
22 changes: 22 additions & 0 deletions testdata/p4_16_samples_outputs/issue314-frontend.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <core.p4>

header header_h {
bit<8> field;
}

struct struct_t {
header_h[4] stack;
}

parser Parser(inout struct_t input) {
int<32> tmp;
state start {
tmp = input.stack.lastIndex;
input.stack[tmp].field = 8w1;
transition accept;
}
}

parser MyParser<S>(inout S input);
package MyPackage<S>(MyParser<S> p);
MyPackage<struct_t>(Parser()) main;
22 changes: 22 additions & 0 deletions testdata/p4_16_samples_outputs/issue314-midend.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <core.p4>

header header_h {
bit<8> field;
}

struct struct_t {
header_h[4] stack;
}

parser Parser(inout struct_t input) {
int<32> tmp_0;
state start {
tmp_0 = input.stack.lastIndex;
input.stack[tmp_0].field = 8w1;
transition accept;
}
}

parser MyParser<S>(inout S input);
package MyPackage<S>(MyParser<S> p);
MyPackage<struct_t>(Parser()) main;
20 changes: 20 additions & 0 deletions testdata/p4_16_samples_outputs/issue314.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <core.p4>

header header_h {
bit<8> field;
}

struct struct_t {
header_h[4] stack;
}

parser Parser(inout struct_t input) {
state start {
input.stack[input.stack.lastIndex].field = 8w1;
transition accept;
}
}

parser MyParser<S>(inout S input);
package MyPackage<S>(MyParser<S> p);
MyPackage(Parser()) main;
Empty file.

0 comments on commit 1e1a1e0

Please sign in to comment.