Skip to content

Commit

Permalink
Syntax sugar for creating IR::Expressions
Browse files Browse the repository at this point in the history
- IR::ERef type encapsulating a `const IR::Expression *` for overloading
- overloaded operators and methods for creating new expressions
- set types & srcInfo of newly created expressions based on operands
  • Loading branch information
Chris Dodd committed Dec 20, 2016
1 parent 640a429 commit ed0e282
Show file tree
Hide file tree
Showing 9 changed files with 302 additions and 288 deletions.
67 changes: 32 additions & 35 deletions frontends/p4-14/p4-14-parse.ypp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ limitations under the License.
static map<int, std::pair<std::string, int>> line_file_map;
static IR::V1Program *global;
static void yyerror(const char *fmt);
static IR::Constant *constantFold(IR::Expression *);
static const IR::Constant *constantFold(const IR::Expression *);
static IR::Vector<IR::Expression> make_expr_list(const IR::NameList *);

#define YYLTYPE Util::SourceInfo
Expand Down Expand Up @@ -69,16 +69,16 @@ static const IR::Annotations *getPragmas() {
IR::CalculatedField *CalculatedField;
IR::CaseEntry *CaseEntry;
IR::Vector<IR::CaseEntry> *CaseEntryList;
IR::Constant *Constant;
const IR::Constant *Constant;
IR::Counter *Counter;
IR::Declaration_Instance *BBox;
IR::Direction Direction;
IR::Expression *Expression;
IR::ERef Expression;
IR::Vector<IR::Expression> *ExpressionList;
IR::FieldList *FieldList;
IR::FieldListCalculation *FieldListCalculation;
IR::NameList *NameList;
IR::Member *Member;
const IR::Member *Member;
IR::Meter *Meter;
IR::Parameter *Parameter;
IR::ParameterList *ParameterList;
Expand Down Expand Up @@ -825,31 +825,31 @@ expression:
new IR::PathExpression(IR::ID(@1, $1)), IR::ID(@3, $3)); }
| INTEGER { $$ = $1; }
| '(' expression ')' { $$ = $2; }
| NOT expression %prec PREFIX { $$ = new IR::LNot(@1, $2); }
| '!' expression %prec PREFIX { $$ = new IR::LNot(@1, $2); }
| '~' expression %prec PREFIX { $$ = new IR::Cmpl(@1, $2); }
| '-' expression %prec PREFIX { $$ = new IR::Neg(@1, $2); }
| NOT expression %prec PREFIX { $$ = !$2; }
| '!' expression %prec PREFIX { $$ = !$2; }
| '~' expression %prec PREFIX { $$ = ~$2; }
| '-' expression %prec PREFIX { $$ = -$2; }
| '+' expression %prec PREFIX { $$ = $2; }
| expression '*' expression { $$ = new IR::Mul(@2, $1, $3); }
| expression '/' expression { $$ = new IR::Div(@2, $1, $3); }
| expression '%' expression { $$ = new IR::Mod(@2, $1, $3); }
| expression '+' expression { $$ = new IR::Add(@2, $1, $3); }
| expression '-' expression { $$ = new IR::Sub(@2, $1, $3); }
| expression SHL expression { $$ = new IR::Shl(@2, $1, $3); }
| expression SHR expression { $$ = new IR::Shr(@2, $1, $3); }
| expression LE expression { $$ = new IR::Leq(@2, $1, $3); }
| expression GE expression { $$ = new IR::Geq(@2, $1, $3); }
| expression '<' expression { $$ = new IR::Lss(@2, $1, $3); }
| expression '>' expression { $$ = new IR::Grt(@2, $1, $3); }
| expression NE expression { $$ = new IR::Neq(@2, $1, $3); }
| expression EQ expression { $$ = new IR::Equ(@2, $1, $3); }
| expression '&' expression { $$ = new IR::BAnd(@2, $1, $3); }
| expression '^' expression { $$ = new IR::BXor(@2, $1, $3); }
| expression '|' expression { $$ = new IR::BOr(@2, $1, $3); }
| expression AND expression { $$ = new IR::LAnd(@2, $1, $3); }
| expression OR expression { $$ = new IR::LOr(@2, $1, $3); }
| TRUE { $$ = new IR::BoolLiteral(@1, true); }
| FALSE { $$ = new IR::BoolLiteral(@1, false); }
| expression '*' expression { $$ = $1 * $3; }
| expression '/' expression { $$ = $1 / $3; }
| expression '%' expression { $$ = $1 % $3; }
| expression '+' expression { $$ = $1 + $3; }
| expression '-' expression { $$ = $1 - $3; }
| expression SHL expression { $$ = $1 << $3; }
| expression SHR expression { $$ = $1 >> $3; }
| expression LE expression { $$ = $1 <= $3; }
| expression GE expression { $$ = $1 >= $3; }
| expression '<' expression { $$ = $1 < $3; }
| expression '>' expression { $$ = $1 > $3; }
| expression NE expression { $$ = $1 != $3; }
| expression EQ expression { $$ = $1 == $3; }
| expression '&' expression { $$ = $1 & $3; }
| expression '^' expression { $$ = $1 ^ $3; }
| expression '|' expression { $$ = $1 | $3; }
| expression AND expression { $$ = $1 && $3; }
| expression OR expression { $$ = $1 || $3; }
| TRUE { $$ = true; }
| FALSE { $$ = false; }
;

header_or_field_ref:
Expand All @@ -862,13 +862,12 @@ header_ref:
| header_ref '[' expression ']' { $$ = new IR::HeaderStackItemRef(@1+@4, $1, $3); }
;

field_ref: header_ref '.' name
{ $$ = new IR::Member(@1+@3, $1, IR::ID(@3, $3)); }
field_ref: header_ref '.' name { $$ = $1.Member(IR::ID(@3, $3)); }
;


const_expression: expression
{ if (!($$ = constantFold(&*$1)))
{ if (!($$ = constantFold($1)))
error("%s: Non constant expression", @1); }
;

Expand Down Expand Up @@ -930,10 +929,8 @@ const IR::V1Program *parse_P4_14_file(const CompilerOptions &options, FILE *in)

#include "frontends/common/constantFolding.h"

static IR::Constant *constantFold(IR::Expression *a) {
IR::Node *exp(a);
auto rv = exp->apply(P4::DoConstantFolding(nullptr, nullptr))->to<IR::Constant>();
return rv ? new IR::Constant(rv->type, rv->value, rv->base) : nullptr;
static const IR::Constant *constantFold(const IR::Expression *a) {
return a->apply(P4::DoConstantFolding(nullptr, nullptr))->to<IR::Constant>();
}

static IR::Vector<IR::Expression> make_expr_list(const IR::NameList *list) {
Expand Down
41 changes: 14 additions & 27 deletions frontends/p4/fromv1.0/converters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,26 +94,18 @@ const IR::Node* ExpressionConverter::postorder(IR::Primitive* primitive) {
return primitive;
}

const IR::Expression* method = new IR::Member(
Util::SourceInfo(),
structure->paramReference(structure->parserPacketIn),
P4::P4CoreLibrary::instance.packetIn.lookahead.Id());
IR::ERef method = structure->paramReference(structure->parserPacketIn)
.Member(P4::P4CoreLibrary::instance.packetIn.lookahead.Id());
auto typeargs = new IR::Vector<IR::Type>();
typeargs->push_back(IR::Type_Bits::get(aval + bval));
auto lookahead = new IR::MethodCallExpression(
Util::SourceInfo(), method, typeargs, new IR::Vector<IR::Expression>());
auto result = new IR::Slice(primitive->srcInfo, lookahead,
new IR::Constant(aval + bval - 1),
new IR::Constant(aval));
result->type = IR::Type_Bits::get(bval);
IR::ERef lookahead = method(typeargs);
IR::ERef result = lookahead.Slice(aval + bval - 1, aval);
return result;
} else if (primitive->name == "valid") {
BUG_CHECK(primitive->operands.size() == 1, "Expected 1 operand for %1%", primitive);
auto base = primitive->operands.at(0);
auto method = new IR::Member(primitive->srcInfo, base, IR::ID(IR::Type_Header::isValid));
auto result = new IR::MethodCallExpression(
primitive->srcInfo, method, new IR::Vector<IR::Type>(),
new IR::Vector<IR::Expression>());
IR::ERef base = primitive->operands.at(0);
IR::ERef method = base.Member(primitive->srcInfo, IR::Type_Header::isValid);
IR::ERef result = method();
return result;
}
BUG("Unexpected primitive %1%", primitive);
Expand Down Expand Up @@ -172,12 +164,9 @@ const IR::Node* ExpressionConverter::postorder(IR::HeaderStackItemRef* ref) {
const IR::Node* StatementConverter::preorder(IR::Apply* apply) {
auto table = structure->tables.get(apply->name);
auto newname = structure->tables.get(table);
auto tbl = new IR::PathExpression(newname);
auto method = new IR::Member(Util::SourceInfo(), tbl,
IR::ID(IR::IApply::applyMethodName));
auto call = new IR::MethodCallExpression(apply->srcInfo, method,
structure->emptyTypeArguments,
new IR::Vector<IR::Expression>());
IR::ERef tbl = new IR::PathExpression(newname);
IR::ERef method = tbl.Member(IR::IApply::applyMethodName);
auto call = method();
if (apply->actions.size() == 0) {
auto stat = new IR::MethodCallStatement(apply->srcInfo, call);
prune();
Expand Down Expand Up @@ -207,7 +196,7 @@ const IR::Node* StatementConverter::preorder(IR::Apply* apply) {
StatementConverter conv(structure, renameMap);
auto hitcase = hit ? conv.convert(hit) : new IR::EmptyStatement(Util::SourceInfo());
auto misscase = miss ? conv.convert(miss) : nullptr;
auto check = new IR::Member(Util::SourceInfo(), call, IR::Type_Table::hit);
IR::ERef check = IR::ERef(call).Member(IR::Type_Table::hit);
auto ifstat = new IR::IfStatement(apply->srcInfo, check, hitcase, misscase);
prune();
return ifstat;
Expand Down Expand Up @@ -242,15 +231,13 @@ const IR::Node* StatementConverter::preorder(IR::Primitive* primitive) {
auto control = structure->controls.get(primitive->name);
if (control != nullptr) {
auto instanceName = get(renameMap, control->name);
auto ctrl = new IR::PathExpression(IR::ID(instanceName));
auto method = new IR::Member(Util::SourceInfo(), ctrl, IR::ID(IR::IApply::applyMethodName));
IR::ERef ctrl = new IR::PathExpression(IR::ID(instanceName));
IR::ERef method = ctrl.Member(IR::IApply::applyMethodName);
auto args = new IR::Vector<IR::Expression>();
args->push_back(structure->conversionContext.header->clone());
args->push_back(structure->conversionContext.userMetadata->clone());
args->push_back(structure->conversionContext.standardMetadata->clone());
auto call = new IR::MethodCallExpression(primitive->srcInfo, method,
structure->emptyTypeArguments, args);
auto stat = new IR::MethodCallStatement(primitive->srcInfo, call);
auto stat = new IR::MethodCallStatement(primitive->srcInfo, method(args));
return stat;
}
// FIXME -- always a noop as ExpressionConverter has only postorder methods?
Expand Down
Loading

0 comments on commit ed0e282

Please sign in to comment.