Skip to content

Commit

Permalink
Merge branch 'master' into issue583
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisDodd authored May 10, 2017
2 parents ffd5ed2 + b25ba2d commit 210a6d1
Show file tree
Hide file tree
Showing 25 changed files with 452 additions and 155 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ENV P4C_DEPS automake \
g++ \
libboost-dev \
libboost-iostreams1.58-dev \
libfl-dev \
libgc-dev \
libgmp-dev \
libtool \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ included with `p4c` are documented here:
Most dependencies can be installed using `apt-get install`:
`sudo apt-get install g++ git automake libtool libgc-dev bison flex libgmp-dev libboost-dev libboost-iostreams-dev pkg-config python python-scapy python-ipaddr tcpdump`
`sudo apt-get install g++ git automake libtool libgc-dev bison flex libfl-dev libgmp-dev libboost-dev libboost-iostreams-dev pkg-config python python-scapy python-ipaddr tcpdump`
For documentation building:
`sudo apt-get install -y doxygen graphviz texlive-full`
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ AC_SUBST([PROTOBUF_LIBS])
AC_PATH_PROG([PROTOC], [protoc], [])
AS_IF([test "x$PROTOC" = x], [AC_MSG_ERROR([protoc not found; is protobuf installed?])])

AC_CHECK_HEADERS([constraint_solver/constraint_solver.h])
AC_CHECK_HEADER([FlexLexer.h], [], [AC_MSG_ERROR([Missing FlexLexer.h; is flex and libfl-dev installed?])])
AC_CHECK_LIB([gc], [GC_malloc], [], [AC_MSG_ERROR([Missing GC library])])
AC_CHECK_LIB([rt], [clock_gettime], [], [])
AC_CHECK_LIB([gmp], [__gmpz_init], [], [AC_MSG_ERROR([GNU MP not found])])
Expand Down
133 changes: 37 additions & 96 deletions frontends/common/constantFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ namespace P4 {

const IR::Expression* DoConstantFolding::getConstant(const IR::Expression* expr) const {
CHECK_NULL(expr);
auto cst = get(constants, expr);
if (cst != nullptr)
return cst;
if (expr->is<IR::Constant>())
return expr;
if (expr->is<IR::BoolLiteral>())
Expand All @@ -35,38 +32,33 @@ const IR::Expression* DoConstantFolding::getConstant(const IR::Expression* expr)
for (auto e : list->components)
if (getConstant(e) == nullptr)
return nullptr;
return list;
return expr;
}
if (typesKnown) {
auto ei = EnumInstance::resolve(expr, typeMap);
if (ei != nullptr)
return expr;
}

return nullptr;
}

// This has to be called from a visitor method - it calls getOriginal()
void DoConstantFolding::setConstant(const IR::Node* node, const IR::Expression* result) {
LOG2("Folding " << node << " to " << result << " (" << result->id << ")");
auto orig = getOriginal();
constants.emplace(node, result);
constants.emplace(orig, result);
}

const IR::Node* DoConstantFolding::postorder(IR::PathExpression* e) {
if (refMap == nullptr)
return e;
auto decl = refMap->getDeclaration(e->path);
if (decl == nullptr)
return e;
auto v = get(constants, decl->getNode());
if (v == nullptr)
return e;
setConstant(e, v);
if (v->is<IR::ListExpression>())
return e;
return v;
if (auto dc = decl->to<IR::Declaration_Constant>()) {
auto cst = get(constants, dc);
if (cst == nullptr)
cst = getConstant(dc->initializer);
if (cst == nullptr)
return e;
if (!typesKnown && cst->is<IR::ListExpression>())
return e;
return cst;
}
return e;
}

const IR::Node* DoConstantFolding::postorder(IR::Declaration_Constant* d) {
Expand All @@ -76,27 +68,24 @@ const IR::Node* DoConstantFolding::postorder(IR::Declaration_Constant* d) {
::error("%1%: Cannot evaluate initializer for constant", d->initializer);
return d;
}

if (typesKnown) {
// If we typechecked we're safe
setConstant(d, init);
} else {
// In fact, this declaration may imply a cast, so the actual value of
// d is not init, but (d->type)init. The typechecker inserts casts,
// but if we run this before typechecking we have to be more conservative.
if (!typesKnown) {
// This declaration may imply a cast, so the actual value of d
// is not init, but (d->type)init. The typechecker inserts
// casts, but if we run this before typechecking we have to be
// more conservative.
if (init->is<IR::Constant>()) {
auto cst = init->to<IR::Constant>();
if (d->type->is<IR::Type_Bits>()) {
if (cst->type->is<IR::Type_InfInt>() ||
(cst->type->is<IR::Type_Bits>() &&
!(*d->type->to<IR::Type_Bits>() == *cst->type->to<IR::Type_Bits>())))
init = new IR::Constant(init->srcInfo, d->type, cst->value, cst->base);
setConstant(d, init);
}
}
if (init != d->initializer)
d = new IR::Declaration_Constant(d->srcInfo, d->name, d->annotations, d->type, init);
}
if (init != d->initializer)
d = new IR::Declaration_Constant(d->srcInfo, d->name, d->annotations, d->type, init);
constants.emplace(getOriginal<IR::Declaration_Constant>(), init);
return d;
}

Expand Down Expand Up @@ -124,9 +113,7 @@ const IR::Node* DoConstantFolding::postorder(IR::Cmpl* e) {
}

mpz_class value = ~cst->value;
auto result = new IR::Constant(cst->srcInfo, t, value, cst->base, true);
setConstant(e, result);
return result;
return new IR::Constant(cst->srcInfo, t, value, cst->base, true);
}

const IR::Node* DoConstantFolding::postorder(IR::Neg* e) {
Expand All @@ -151,9 +138,7 @@ const IR::Node* DoConstantFolding::postorder(IR::Neg* e) {
}

mpz_class value = -cst->value;
auto result = new IR::Constant(cst->srcInfo, t, value, cst->base, true);
setConstant(e, result);
return result;
return new IR::Constant(cst->srcInfo, t, value, cst->base, true);
}

const IR::Constant*
Expand Down Expand Up @@ -260,19 +245,15 @@ DoConstantFolding::compare(const IR::Operation_Binary* e) {
return e;
}
bool bresult = (left->value == right->value) == eqTest;
auto result = new IR::BoolLiteral(e->srcInfo, bresult);
setConstant(e, result);
return result;
return new IR::BoolLiteral(e->srcInfo, bresult);
} else if (typesKnown) {
auto le = EnumInstance::resolve(eleft, typeMap);
auto re = EnumInstance::resolve(eright, typeMap);
if (le != nullptr && re != nullptr) {
BUG_CHECK(le->type == re->type,
"%1%: different enum types in comparison", e);
bool bresult = (le->name == re->name) == eqTest;
auto result = new IR::BoolLiteral(e->srcInfo, bresult);
setConstant(e, result);
return result;
return new IR::BoolLiteral(e->srcInfo, bresult);
}
}

Expand Down Expand Up @@ -349,13 +330,10 @@ DoConstantFolding::binary(const IR::Operation_Binary* e,
}
}

const IR::Expression* result;
if (e->is<IR::Operation_Relation>())
result = new IR::BoolLiteral(e->srcInfo, value != 0);
return new IR::BoolLiteral(e->srcInfo, value != 0);
else
result = new IR::Constant(e->srcInfo, resultType, value, left->base, true);
setConstant(e, result);
return result;
return new IR::Constant(e->srcInfo, resultType, value, left->base, true);
}

const IR::Node* DoConstantFolding::postorder(IR::LAnd* e) {
Expand All @@ -368,16 +346,10 @@ const IR::Node* DoConstantFolding::postorder(IR::LAnd* e) {
::error("%1%: Expected a boolean value", left);
return e;
}

if (lcst->value) {
setConstant(e, e->right);
return e->right;
}

// Short-circuit folding
auto result = new IR::BoolLiteral(left->srcInfo, false);
setConstant(e, result);
return result;
return new IR::BoolLiteral(left->srcInfo, false);
}

const IR::Node* DoConstantFolding::postorder(IR::LOr* e) {
Expand All @@ -390,16 +362,10 @@ const IR::Node* DoConstantFolding::postorder(IR::LOr* e) {
::error("%1%: Expected a boolean value", left);
return e;
}

if (!lcst->value) {
setConstant(e, e->right);
return e->right;
}

// Short-circuit folding
auto result = new IR::BoolLiteral(left->srcInfo, true);
setConstant(e, result);
return result;
return new IR::BoolLiteral(left->srcInfo, true);
}

const IR::Node* DoConstantFolding::postorder(IR::Slice* e) {
Expand Down Expand Up @@ -451,9 +417,7 @@ const IR::Node* DoConstantFolding::postorder(IR::Slice* e) {
auto resultType = typeMap->getType(getOriginal(), true);
if (!resultType->is<IR::Type_Bits>())
BUG("Type of slice is not Type_Bits, but %1%", resultType);
auto result = new IR::Constant(e->srcInfo, resultType, value, cbase->base, true);
setConstant(e, result);
return result;
return new IR::Constant(e->srcInfo, resultType, value, cbase->base, true);
}

const IR::Node* DoConstantFolding::postorder(IR::Member* e) {
Expand All @@ -467,7 +431,7 @@ const IR::Node* DoConstantFolding::postorder(IR::Member* e) {
if (type->is<IR::Type_Stack>() && e->member == IR::Type_Stack::arraySize) {
auto st = type->to<IR::Type_Stack>();
auto size = st->getSize();
result = new IR::Constant(st->size->srcInfo, size);
result = new IR::Constant(st->size->srcInfo, origtype, size);
} else {
auto expr = getConstant(e->expr);
if (expr == nullptr)
Expand All @@ -494,9 +458,6 @@ const IR::Node* DoConstantFolding::postorder(IR::Member* e) {
BUG("Could not find field %1% in type %2%", e->member, type);
result = list->components.at(index)->clone();
}
typeMap->setType(result, origtype);
typeMap->setCompileTimeConstant(result);
setConstant(e, result);
return result;
}

Expand Down Expand Up @@ -526,9 +487,7 @@ const IR::Node* DoConstantFolding::postorder(IR::Concat* e) {

auto resultType = IR::Type_Bits::get(lt->size + rt->size, lt->isSigned);
mpz_class value = Util::shift_left(left->value, static_cast<unsigned>(rt->size)) + right->value;
auto result = new IR::Constant(e->srcInfo, resultType, value, left->base);
setConstant(e, result);
return result;
return new IR::Constant(e->srcInfo, resultType, value, left->base);
}

const IR::Node* DoConstantFolding::postorder(IR::LNot* e) {
Expand All @@ -541,10 +500,7 @@ const IR::Node* DoConstantFolding::postorder(IR::LNot* e) {
::error("%1%: Expected a boolean value", op);
return e;
}

auto result = new IR::BoolLiteral(cst->srcInfo, !cst->value);
setConstant(e, result);
return result;
return new IR::BoolLiteral(cst->srcInfo, !cst->value);
}

const IR::Node* DoConstantFolding::postorder(IR::Mux* e) {
Expand Down Expand Up @@ -577,7 +533,6 @@ const IR::Node* DoConstantFolding::shift(const IR::Operation_Binary* e) {

if (sgn(cr->value) == 0) {
// ::warning("%1% with zero", e);
setConstant(e, e->left);
return e->left;
}

Expand All @@ -604,9 +559,7 @@ const IR::Node* DoConstantFolding::shift(const IR::Operation_Binary* e) {
value = Util::shift_left(value, shift);
else
value = Util::shift_right(value, shift);
auto result = new IR::Constant(e->srcInfo, left->type, value, cl->base);
setConstant(e, result);
return result;
return new IR::Constant(e->srcInfo, left->type, value, cl->base);
}

const IR::Node *DoConstantFolding::postorder(IR::Cast *e) {
Expand All @@ -624,15 +577,11 @@ const IR::Node *DoConstantFolding::postorder(IR::Cast *e) {
auto type = etype->to<IR::Type_Bits>();
if (expr->is<IR::Constant>()) {
auto arg = expr->to<IR::Constant>();
auto result = cast(arg, arg->base, type);
setConstant(e, result);
return result;
return cast(arg, arg->base, type);
} else if (expr -> is<IR::BoolLiteral>()) {
auto arg = expr->to<IR::BoolLiteral>();
int v = arg->value ? 1 : 0;
auto result = new IR::Constant(e->srcInfo, type, v, 10);
setConstant(e, result);
return result;
return new IR::Constant(e->srcInfo, type, v, 10);
} else {
return e;
}
Expand Down Expand Up @@ -662,19 +611,11 @@ const IR::Node *DoConstantFolding::postorder(IR::Cast *e) {
::error("%1%: Only 0 and 1 can be cast to booleans", e);
return e;
}
auto lit = new IR::BoolLiteral(e->srcInfo, v == 1);
setConstant(e, lit);
return lit;
return new IR::BoolLiteral(e->srcInfo, v == 1);
}
} else if (etype->is<IR::Type_StructLike>()) {
auto result = expr->clone();
auto origtype = typeMap->getType(getOriginal());
typeMap->setType(result, origtype);
typeMap->setCompileTimeConstant(result);
setConstant(e, result);
return result;
return expr->clone();
}

return e;
}

Expand Down
Loading

0 comments on commit 210a6d1

Please sign in to comment.