diff --git a/frontends/p4-14/p4-14-parse.ypp b/frontends/p4-14/p4-14-parse.ypp index 51c2f43a5dc..371d602428b 100644 --- a/frontends/p4-14/p4-14-parse.ypp +++ b/frontends/p4-14/p4-14-parse.ypp @@ -36,7 +36,7 @@ limitations under the License. static map> 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 make_expr_list(const IR::NameList *); #define YYLTYPE Util::SourceInfo @@ -69,16 +69,16 @@ static const IR::Annotations *getPragmas() { IR::CalculatedField *CalculatedField; IR::CaseEntry *CaseEntry; IR::Vector *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 *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; @@ -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: @@ -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); } ; @@ -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(); - 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(); } static IR::Vector make_expr_list(const IR::NameList *list) { diff --git a/frontends/p4/fromv1.0/converters.cpp b/frontends/p4/fromv1.0/converters.cpp index 215ad58a31a..a6e95fd4a94 100644 --- a/frontends/p4/fromv1.0/converters.cpp +++ b/frontends/p4/fromv1.0/converters.cpp @@ -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(); typeargs->push_back(IR::Type_Bits::get(aval + bval)); - auto lookahead = new IR::MethodCallExpression( - Util::SourceInfo(), method, typeargs, new IR::Vector()); - 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(), - new IR::Vector()); + 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); @@ -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::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(); @@ -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; @@ -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(); 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? diff --git a/frontends/p4/fromv1.0/programStructure.cpp b/frontends/p4/fromv1.0/programStructure.cpp index 603c0e02f79..c02ad30934d 100644 --- a/frontends/p4/fromv1.0/programStructure.cpp +++ b/frontends/p4/fromv1.0/programStructure.cpp @@ -236,7 +236,7 @@ void ProgramStructure::createExterns() { } } -const IR::Expression* ProgramStructure::paramReference(const IR::Parameter* param) { +IR::ERef ProgramStructure::paramReference(const IR::Parameter* param) { auto result = new IR::PathExpression(param->name); auto tn = param->type->to(); cstring name = tn->path->toString(); @@ -264,13 +264,8 @@ const IR::Statement* ProgramStructure::convertParserStatement(const IR::Expressi conv.replaceNextWithLast = true; this->latest = conv.convert(dest); conv.replaceNextWithLast = false; - const IR::Expression* method = new IR::Member( - Util::SourceInfo(), - paramReference(parserPacketIn), - p4lib.packetIn.extract.Id()); - auto mce = new IR::MethodCallExpression(expr->srcInfo, method, - emptyTypeArguments, args); - auto result = new IR::MethodCallStatement(expr->srcInfo, mce); + IR::ERef method = paramReference(parserPacketIn).Member(p4lib.packetIn.extract.Id()); + auto result = new IR::MethodCallStatement(expr->srcInfo, method(args)); return result; } else if (primitive->name == "set_metadata") { BUG_CHECK(primitive->operands.size() == 2, "Expected 2 operands for %1%", primitive); @@ -465,7 +460,7 @@ class HeaderRepresentation { if (expression->is()) { cstring name = expression->to()->ref->name; if (header.find(name) == header.end()) - header[name] = new IR::Member(Util::SourceInfo(), hdrsParam, name); + header[name] = IR::ERef(hdrsParam).Member(name); return header[name]; } else if (expression->is()) { auto hsir = expression->to(); @@ -568,13 +563,8 @@ void ProgramStructure::createDeparser() { continue; auto args = new IR::Vector(); args->push_back(exp); - const IR::Expression* method = new IR::Member( - Util::SourceInfo(), - paramReference(packetOut), - p4lib.packetOut.emit.Id()); - auto mce = new IR::MethodCallExpression(Util::SourceInfo(), method, - emptyTypeArguments, args); - auto stat = new IR::MethodCallStatement(Util::SourceInfo(), mce); + IR::ERef method = paramReference(packetOut).Member(p4lib.packetOut.emit.Id()); + auto stat = new IR::MethodCallStatement(Util::SourceInfo(), method(args)); components->push_back(stat); } auto body = new IR::BlockStatement(Util::SourceInfo(), IR::Annotations::empty, components); @@ -696,11 +686,10 @@ ProgramStructure::convertTable(const IR::V1Table* table, cstring newName, else defaction = p4lib.noAction.Id(); { - auto act = new IR::PathExpression(defaction); + IR::ERef act = new IR::PathExpression(defaction); auto args = table->default_action_args != nullptr ? table->default_action_args : new IR::Vector(); - auto methodCall = new IR::MethodCallExpression(Util::SourceInfo(), act, - emptyTypeArguments, args); + auto methodCall = act(args); auto prop = new IR::Property( Util::SourceInfo(), IR::ID(IR::TableProperties::defaultActionPropertyName), IR::Annotations::empty, new IR::ExpressionValue(Util::SourceInfo(), methodCall), false); @@ -789,8 +778,8 @@ const IR::Expression* ProgramStructure::convertHashAlgorithm(IR::ID algorithm) { ::warning("%1%: unexpected algorithm", algorithm); result = algorithm; } - auto pe = new IR::TypeNameExpression(v1model.algorithm.Id()); - auto mem = new IR::Member(Util::SourceInfo(), pe, result); + IR::ERef pe = new IR::TypeNameExpression(v1model.algorithm.Id()); + auto mem = pe.Member(result); return mem; } @@ -804,20 +793,18 @@ static bool sameBitsType(const IR::Type* left, const IR::Type* right) { // Implement modify_field(left, right, mask) const IR::Statement* ProgramStructure::sliceAssign( - Util::SourceInfo srcInfo, const IR::Expression* left, - const IR::Expression* right, const IR::Expression* mask) { + Util::SourceInfo srcInfo, IR::ERef left, + IR::ERef right, IR::ERef mask) { if (mask->is()) { auto cst = mask->to(); if (cst->value < 0) { - ::error("%1%: Negative mask not supported", mask); + ::error("%1%: Negative mask not supported", &*mask); // FIXME -- error print of ERef return nullptr; } auto range = Util::findOnes(cst->value); if (cst->value == range.value) { - auto h = new IR::Constant(range.highIndex); - auto l = new IR::Constant(range.lowIndex); - left = new IR::Slice(left->srcInfo, left, h, l); - right = new IR::Slice(right->srcInfo, right, h, l); + left = left.Slice(range.highIndex, range.lowIndex); + right = right.Slice(range.highIndex, range.lowIndex); return new IR::AssignmentStatement(srcInfo, left, right); } // else value is too complex for a slice @@ -828,11 +815,7 @@ const IR::Statement* ProgramStructure::sliceAssign( mask = new IR::Cast(Util::SourceInfo(), type, mask); if (!sameBitsType(right->type, left->type)) right = new IR::Cast(Util::SourceInfo(), type, right); - auto op1 = new IR::BAnd(left->srcInfo, left, - new IR::Cmpl(Util::SourceInfo(), mask)); - auto op2 = new IR::BAnd(right->srcInfo, right, mask); - auto result = new IR::BOr(mask->srcInfo, op1, op2); - return new IR::AssignmentStatement(srcInfo, left, result); + return new IR::AssignmentStatement(srcInfo, left, (left & ~mask) | (right & mask)); } #define OPS_CK(primitive, n) BUG_CHECK((primitive)->operands.size() == n, \ @@ -861,14 +844,12 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri if (glob) extrn = glob->obj->to(); if (extrn) { - auto extref = new IR::PathExpression(externs.get(extrn)); - auto method = new IR::Member(primitive->srcInfo, extref, primitive->name); + IR::ERef extref = new IR::PathExpression(externs.get(extrn)); + IR::ERef method = extref.Member(primitive->name); auto args = new IR::Vector(); for (unsigned i = 1; i < primitive->operands.size(); ++i) args->push_back(conv.convert(primitive->operands.at(i))); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, - emptyTypeArguments, args); - return new IR::MethodCallStatement(primitive->srcInfo, mc); + return new IR::MethodCallStatement(primitive->srcInfo, method(args)); } else if (primitive->name == "modify_field") { if (primitive->operands.size() == 2) { auto left = conv.convert(primitive->operands.at(0)); @@ -892,9 +873,9 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri primitive->name == "max") { OPS_CK(primitive, 3); auto dest = conv.convert(primitive->operands.at(0)); - auto left = conv.convert(primitive->operands.at(1)); - auto right = conv.convert(primitive->operands.at(2)); - IR::Expression* op = nullptr; + IR::ERef left = conv.convert(primitive->operands.at(1)); + IR::ERef right = conv.convert(primitive->operands.at(2)); + IR::ERef op = nullptr; if (!sameBitsType(left->type, right->type) && !primitive->name.startsWith("shift")) { auto r = new IR::Cast(right->srcInfo, left->type, right); @@ -902,101 +883,90 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri right = r; } if (primitive->name == "bit_xor") - op = new IR::BXor(dest->srcInfo, left, right); + op = left ^ right; else if (primitive->name == "min") - op = new IR::Mux(dest->srcInfo, new IR::Leq(dest->srcInfo, left, right), - left, right); + op = (left <= right).Mux(left, right); else if (primitive->name == "max") - op = new IR::Mux(dest->srcInfo, new IR::Geq(dest->srcInfo, left, right), - left, right); + op = (left >= right).Mux(left, right); else if (primitive->name == "bit_or") - op = new IR::BOr(dest->srcInfo, left, right); + op = left | right; else if (primitive->name == "bit_xnor") - op = new IR::Cmpl(dest->srcInfo, new IR::BXor(dest->srcInfo, left, right)); + op = ~(left ^ right); else if (primitive->name == "add") - op = new IR::Add(dest->srcInfo, left, right); + op = left + right; else if (primitive->name == "bit_nor") - op = new IR::Cmpl(dest->srcInfo, new IR::BOr(dest->srcInfo, left, right)); + op = ~(left | right); else if (primitive->name == "bit_nand") - op = new IR::Cmpl(dest->srcInfo, new IR::BAnd(dest->srcInfo, left, right)); + op = ~(left & right); else if (primitive->name == "bit_orca") - op = new IR::BOr(dest->srcInfo, new IR::Cmpl(dest->srcInfo, left), right); + op = ~left | right; else if (primitive->name == "bit_orcb") - op = new IR::BOr(dest->srcInfo, left, new IR::Cmpl(dest->srcInfo, right)); + op = left | ~right; else if (primitive->name == "bit_andca") - op = new IR::BAnd(dest->srcInfo, new IR::Cmpl(dest->srcInfo, left), right); + op = ~left & right; else if (primitive->name == "bit_andcb") - op = new IR::BAnd(dest->srcInfo, left, new IR::Cmpl(dest->srcInfo, right)); + op = left & ~right; else if (primitive->name == "bit_and") - op = new IR::BAnd(dest->srcInfo, left, right); + op = left & right; else if (primitive->name == "subtract") - op = new IR::Sub(dest->srcInfo, left, right); + op = left - right; else if (primitive->name == "shift_left") - op = new IR::Shl(dest->srcInfo, left, right); + op = left << right; else if (primitive->name == "shift_right") - op = new IR::Shr(dest->srcInfo, left, right); + op = left >> right; + else + BUG("primitve %s not in containing if?", primitive->name); auto result = new IR::AssignmentStatement(primitive->srcInfo, dest, op); return result; } else if (primitive->name == "bit_not") { OPS_CK(primitive, 2); auto dest = conv.convert(primitive->operands.at(0)); - auto right = conv.convert(primitive->operands.at(1)); - IR::Expression* op = nullptr; + IR::ERef right = conv.convert(primitive->operands.at(1)); + IR::ERef op = nullptr; if (primitive->name == "bit_not") - op = new IR::Cmpl(Util::SourceInfo(), right); + op = ~right; auto result = new IR::AssignmentStatement(primitive->srcInfo, dest, op); return result; } else if (primitive->name == "no_op") { return new IR::EmptyStatement(Util::SourceInfo()); } else if (primitive->name == "add_to_field" || primitive->name == "subtract_from_field") { OPS_CK(primitive, 2); - auto left = conv.convert(primitive->operands.at(0)); - auto right = conv.convert(primitive->operands.at(1)); + IR::ERef left = conv.convert(primitive->operands.at(0)); + IR::ERef right = conv.convert(primitive->operands.at(1)); const IR::Expression* op; if (primitive->name == "add_to_field") - op = new IR::Add(primitive->srcInfo, left, right); + op = left + right; else - op = new IR::Sub(primitive->srcInfo, left, right); + op = left - right; return new IR::AssignmentStatement(primitive->srcInfo, left, op); } else if (primitive->name == "remove_header") { OPS_CK(primitive, 1); - auto hdr = conv.convert(primitive->operands.at(0)); - auto method = new IR::Member(Util::SourceInfo(), hdr, IR::ID(IR::Type_Header::setInvalid)); - auto args = new IR::Vector(); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, - emptyTypeArguments, args); - return new IR::MethodCallStatement(mc->srcInfo, mc); + IR::ERef hdr = conv.convert(primitive->operands.at(0)); + IR::ERef method = hdr.Member(IR::Type_Header::setInvalid); + return new IR::MethodCallStatement(primitive->srcInfo, method()); } else if (primitive->name == "add_header") { OPS_CK(primitive, 1); - auto hdr = conv.convert(primitive->operands.at(0)); - auto method = new IR::Member(Util::SourceInfo(), hdr, IR::ID(IR::Type_Header::setValid)); - auto args = new IR::Vector(); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, - emptyTypeArguments, args); - return new IR::MethodCallStatement(mc->srcInfo, mc); + IR::ERef hdr = conv.convert(primitive->operands.at(0)); + IR::ERef method = hdr.Member(IR::Type_Header::setValid); + return new IR::MethodCallStatement(primitive->srcInfo, method()); } else if (primitive->name == "copy_header") { OPS_CK(primitive, 2); auto left = conv.convert(primitive->operands.at(0)); auto right = conv.convert(primitive->operands.at(1)); return new IR::AssignmentStatement(primitive->srcInfo, left, right); } else if (primitive->name == "drop") { - auto method = new IR::PathExpression(v1model.drop.Id()); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, - emptyTypeArguments, - new IR::Vector()); - return new IR::MethodCallStatement(mc->srcInfo, mc); + IR::ERef method = new IR::PathExpression(v1model.drop.Id()); + return new IR::MethodCallStatement(primitive->srcInfo, method()); } else if (primitive->name == "push" || primitive->name == "pop") { OPS_CK(primitive, 2); - auto hdr = conv.convert(primitive->operands.at(0)); + IR::ERef hdr = conv.convert(primitive->operands.at(0)); auto count = conv.convert(primitive->operands.at(1)); auto methodName = primitive->name == "push" ? IR::Type_Stack::push_front : IR::Type_Stack::pop_front; - auto method = new IR::Member(Util::SourceInfo(), hdr, IR::ID(methodName)); + IR::ERef method = hdr.Member(methodName); auto args = new IR::Vector(); args->push_back(count); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, - emptyTypeArguments, args); - return new IR::MethodCallStatement(mc->srcInfo, mc); + return new IR::MethodCallStatement(primitive->srcInfo, method(args)); } else if (primitive->name == "count") { OPS_CK(primitive, 2); auto ref = primitive->operands.at(0); @@ -1009,16 +979,14 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri ::error("Expected a counter reference %1%", ref); return nullptr; } auto newname = counters.get(counter); - auto counterref = new IR::PathExpression(newname); + IR::ERef counterref = new IR::PathExpression(newname); auto methodName = v1model.counter.increment.Id(); - auto method = new IR::Member(Util::SourceInfo(), counterref, methodName); + IR::ERef method = counterref.Member(methodName); auto args = new IR::Vector(); auto arg = new IR::Cast(Util::SourceInfo(), v1model.counter.index_type, conv.convert(primitive->operands.at(1))); args->push_back(arg); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, - emptyTypeArguments, args); - return new IR::MethodCallStatement(mc->srcInfo, mc); + return new IR::MethodCallStatement(primitive->srcInfo, method(args)); } else if (primitive->name == "modify_field_from_rng") { BUG_CHECK(primitive->operands.size() == 2 || primitive->operands.size() == 3, "Expected 2 or 3 operands for %1%", primitive); @@ -1039,10 +1007,8 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri auto one = new IR::Constant(primitive->operands.at(1)->srcInfo, 1); args->push_back(new IR::Cast(primitive->operands.at(1)->srcInfo, v1model.random.resultType, new IR::Sub(new IR::Shl(one, logRange), one))); - auto random = new IR::PathExpression(v1model.random.Id()); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, random, - emptyTypeArguments, args); - auto call = new IR::MethodCallStatement(primitive->srcInfo, mc); + IR::ERef random = new IR::PathExpression(v1model.random.Id()); + auto call = new IR::MethodCallStatement(primitive->srcInfo, random(args)); auto components = new IR::IndexedVector(); const IR::Statement* assign; if (mask != nullptr) { @@ -1068,10 +1034,8 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri v1model.random.resultType, lo)); args->push_back(new IR::Cast(primitive->operands.at(1)->srcInfo, v1model.random.resultType, hi)); - auto random = new IR::PathExpression(v1model.random.Id()); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, random, - emptyTypeArguments, args); - auto call = new IR::MethodCallStatement(primitive->srcInfo, mc); + IR::ERef random = new IR::PathExpression(v1model.random.Id()); + auto call = new IR::MethodCallStatement(primitive->srcInfo, random(args)); return call; } else if (primitive->name == "recirculate") { OPS_CK(primitive, 1); @@ -1080,10 +1044,8 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri return nullptr; auto args = new IR::Vector(); args->push_back(right); - auto path = new IR::PathExpression(v1model.recirculate.Id()); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, path, - emptyTypeArguments, args); - return new IR::MethodCallStatement(mc->srcInfo, mc); + IR::ERef path = new IR::PathExpression(v1model.recirculate.Id()); + return new IR::MethodCallStatement(primitive->srcInfo, path(args)); } else if (primitive->name == "clone_egress_pkt_to_egress" || primitive->name == "clone_ingress_pkt_to_egress" || primitive->name == "clone_i2e" || primitive->name == "clone_e2e") { @@ -1096,10 +1058,9 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri auto session = conv.convert(primitive->operands.at(0)); auto args = new IR::Vector(); - auto enumref = new IR::TypeNameExpression( - Util::SourceInfo(), + IR::ERef enumref = new IR::TypeNameExpression( new IR::Type_Name(new IR::Path(v1model.clone.cloneType.Id()))); - auto kindarg = new IR::Member(Util::SourceInfo(), enumref, kind.Id()); + auto kindarg = enumref.Member(kind.Id()); args->push_back(kindarg); args->push_back(new IR::Cast(primitive->operands.at(0)->srcInfo, v1model.clone.sessionType, session)); @@ -1110,20 +1071,16 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri } auto id = primitive->operands.size() == 2 ? v1model.clone.clone3.Id() : v1model.clone.Id(); - auto clone = new IR::PathExpression(id); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, clone, - emptyTypeArguments, args); - return new IR::MethodCallStatement(mc->srcInfo, mc); + IR::ERef clone = new IR::PathExpression(id); + return new IR::MethodCallStatement(primitive->srcInfo, clone(args)); } else if (primitive->name == "resubmit") { OPS_CK(primitive, 1); auto args = new IR::Vector(); auto list = convertFieldList(primitive->operands.at(0)); if (list != nullptr) args->push_back(list); - auto resubmit = new IR::PathExpression(v1model.resubmit.Id()); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, resubmit, - emptyTypeArguments, args); - return new IR::MethodCallStatement(mc->srcInfo, mc); + IR::ERef resubmit = new IR::PathExpression(v1model.resubmit.Id()); + return new IR::MethodCallStatement(primitive->srcInfo, resubmit(args)); } else if (primitive->name == "execute_meter") { OPS_CK(primitive, 3); auto ref = primitive->operands.at(0); @@ -1138,18 +1095,15 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri if (!meter->implementation.name.isNullOrEmpty()) ::warning("Ignoring `implementation' field of meter %1%", meter); auto newname = meters.get(meter); - auto meterref = new IR::PathExpression(newname); - auto methodName = v1model.meter.executeMeter.Id(); - auto method = new IR::Member(Util::SourceInfo(), meterref, methodName); + IR::ERef meterref = new IR::PathExpression(newname); + IR::ERef method = meterref.Member(v1model.meter.executeMeter.Id()); auto args = new IR::Vector(); auto arg = new IR::Cast(Util::SourceInfo(), v1model.meter.index_type, conv.convert(primitive->operands.at(1))); args->push_back(arg); auto dest = conv.convert(primitive->operands.at(2)); args->push_back(dest); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, - emptyTypeArguments, args); - return new IR::MethodCallStatement(primitive->srcInfo, mc); + return new IR::MethodCallStatement(primitive->srcInfo, method(args)); } else if (primitive->name == "modify_field_with_hash_based_offset") { OPS_CK(primitive, 4); @@ -1175,10 +1129,8 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri args->push_back(list); args->push_back(new IR::Cast(Util::SourceInfo(), IR::Type_Bits::get(2 * flc->output_width), max)); - auto hash = new IR::PathExpression(v1model.hash.Id()); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, hash, - emptyTypeArguments, args); - auto result = new IR::MethodCallStatement(primitive->srcInfo, mc); + IR::ERef hash = new IR::PathExpression(v1model.hash.Id()); + auto result = new IR::MethodCallStatement(primitive->srcInfo, hash(args)); return result; } else if (primitive->name == "generate_digest") { OPS_CK(primitive, 2); @@ -1194,10 +1146,8 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri auto typeArgs = new IR::Vector(); auto typeName = new IR::Type_Name(Util::SourceInfo(), new IR::Path(type->name)); typeArgs->push_back(typeName); - auto random = new IR::PathExpression(v1model.digest_receiver.Id()); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, random, - typeArgs, args); - auto result = new IR::MethodCallStatement(mc->srcInfo, mc); + IR::ERef random = new IR::PathExpression(v1model.digest_receiver.Id()); + auto result = new IR::MethodCallStatement(primitive->srcInfo, random(typeArgs, args)); return result; } else if (primitive->name == "register_read") { OPS_CK(primitive, 3); @@ -1212,17 +1162,14 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri ::error("Expected a register reference %1%", ref); return nullptr; } auto newname = registers.get(reg); - auto registerref = new IR::PathExpression(newname); - auto methodName = v1model.registers.read.Id(); - auto method = new IR::Member(Util::SourceInfo(), registerref, methodName); + IR::ERef registerref = new IR::PathExpression(newname); + IR::ERef method = registerref.Member(v1model.registers.read.Id()); auto args = new IR::Vector(); auto arg = new IR::Cast(Util::SourceInfo(), v1model.registers.index_type, conv.convert(primitive->operands.at(2))); args->push_back(left); args->push_back(arg); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, - emptyTypeArguments, args); - return new IR::MethodCallStatement(mc->srcInfo, mc); + return new IR::MethodCallStatement(primitive->srcInfo, method(args)); } else if (primitive->name == "register_write") { OPS_CK(primitive, 3); auto ref = primitive->operands.at(0); @@ -1240,9 +1187,8 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri auto regElementType = IR::Type_Bits::get(width); auto newname = registers.get(reg); - auto registerref = new IR::PathExpression(newname); - auto methodName = v1model.registers.write.Id(); - auto method = new IR::Member(Util::SourceInfo(), registerref, methodName); + IR::ERef registerref = new IR::PathExpression(newname); + IR::ERef method = registerref.Member(v1model.registers.write.Id()); auto args = new IR::Vector(); auto arg0 = new IR::Cast(primitive->operands.at(1)->srcInfo, v1model.registers.index_type, conv.convert(primitive->operands.at(1))); @@ -1250,35 +1196,29 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri conv.convert(primitive->operands.at(2))); args->push_back(arg0); args->push_back(arg1); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, - emptyTypeArguments, args); - return new IR::MethodCallStatement(mc->srcInfo, mc); + return new IR::MethodCallStatement(primitive->srcInfo, method(args)); } else if (primitive->name == "truncate") { OPS_CK(primitive, 1); auto len = primitive->operands.at(0); auto methodName = v1model.truncate.Id(); - auto method = new IR::PathExpression(methodName); + IR::ERef method = new IR::PathExpression(methodName); auto args = new IR::Vector(); auto arg0 = new IR::Cast(len->srcInfo, v1model.truncate.length_type, conv.convert(len)); args->push_back(arg0); - auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, - emptyTypeArguments, args); - return new IR::MethodCallStatement(mc->srcInfo, mc); + return new IR::MethodCallStatement(primitive->srcInfo, method(args)); } // If everything else failed maybe we are invoking an action auto action = actions.get(primitive->name); if (action != nullptr) { auto newname = actions.get(action); - auto act = new IR::PathExpression(newname); + IR::ERef act = new IR::PathExpression(newname); auto args = new IR::Vector(); for (auto a : primitive->operands) { auto e = conv.convert(a); args->push_back(e); } - auto call = new IR::MethodCallExpression(primitive->srcInfo, act, - emptyTypeArguments, args); - auto stat = new IR::MethodCallStatement(primitive->srcInfo, call); + auto stat = new IR::MethodCallStatement(primitive->srcInfo, act(args)); return stat; } @@ -1323,15 +1263,13 @@ ProgramStructure::convertAction(const IR::ActionFunction* action, cstring newNam // add a writeback to the meter field auto decl = get(meterMap, meterToAccess); CHECK_NULL(decl); - auto extObj = new IR::PathExpression(decl->name); - auto method = new IR::Member(Util::SourceInfo(), extObj, v1model.directMeter.read.Id()); + IR::ERef extObj = new IR::PathExpression(decl->name); + IR::ERef method = extObj.Member(v1model.directMeter.read.Id()); auto args = new IR::Vector(); auto arg = conv.convert(meterToAccess->result); if (arg != nullptr) args->push_back(arg); - auto mc = new IR::MethodCallExpression(Util::SourceInfo(), method, - emptyTypeArguments, args); - auto stat = new IR::MethodCallStatement(mc->srcInfo, mc); + auto stat = new IR::MethodCallStatement(method(args)); body->push_back(stat); } @@ -1384,9 +1322,9 @@ const IR::Expression* ProgramStructure::counterType(const IR::CounterOrMeter* cm kind = v1model.counterOrMeter.counterType.both.Id(); else BUG("%1%: unsupported", cm); - auto enumref = new IR::TypeNameExpression(Util::SourceInfo(), + IR::ERef enumref = new IR::TypeNameExpression(Util::SourceInfo(), new IR::Type_Name(new IR::Path(v1model.counterOrMeter.counterType.Id()))); - return new IR::Member(Util::SourceInfo(), enumref, kind); + return enumref.Member(kind); } const IR::Declaration_Instance* @@ -1787,7 +1725,7 @@ void ProgramStructure::createChecksumVerifications() { auto components = new IR::IndexedVector(); for (auto cf : calculated_fields) { LOG1("Converting " << cf); - auto dest = conv.convert(cf->field); + IR::ERef dest = conv.convert(cf->field); for (auto uov : cf->specs) { if (uov.update) continue; @@ -1797,24 +1735,19 @@ void ProgramStructure::createChecksumVerifications() { auto fl = getFieldLists(flc); if (fl == nullptr) continue; auto le = conv.convert(fl); - auto extObj = new IR::PathExpression(inst->name); + IR::ERef extObj = new IR::PathExpression(inst->name); // The only method we currently know about is v1model.ck16.get - auto method = new IR::Member(Util::SourceInfo(), extObj, v1model.ck16.get.Id()); + IR::ERef method = extObj.Member(v1model.ck16.get.Id()); auto args = new IR::Vector(); args->push_back(le); - auto mc = new IR::MethodCallExpression(Util::SourceInfo(), method, - emptyTypeArguments, args); - const IR::Expression* cond = new IR::Equ(uov.srcInfo, dest, mc); + IR::ERef cond = dest == method(args); if (uov.cond != nullptr) { - auto cond2 = conv.convert(uov.cond); + IR::ERef cond2 = conv.convert(uov.cond); // cond2 is evaluated first - cond = new IR::LAnd(Util::SourceInfo(), cond2, cond); + cond = cond2 && cond; } - auto dropmethod = new IR::PathExpression(v1model.drop.Id()); - auto dropmc = new IR::MethodCallExpression(Util::SourceInfo(), dropmethod, - emptyTypeArguments, - new IR::Vector()); - auto drop = new IR::MethodCallStatement(mc->srcInfo, dropmc); + IR::ERef dropmethod = new IR::PathExpression(v1model.drop.Id()); + auto drop = new IR::MethodCallStatement(dropmethod()); auto ifstate = new IR::IfStatement(Util::SourceInfo(), cond, drop, nullptr); components->push_back(ifstate); LOG1("Converted " << flc); @@ -1885,14 +1818,13 @@ void ProgramStructure::createChecksumUpdates() { if (fl == nullptr) continue; auto le = conv.convert(fl); - auto extObj = new IR::PathExpression(inst->name); + IR::ERef extObj = new IR::PathExpression(inst->name); // The only method we currently know about is v1model.ck16.get - auto method = new IR::Member(Util::SourceInfo(), extObj, v1model.ck16.get.Id()); + IR::ERef method = extObj.Member(v1model.ck16.get.Id()); auto args = new IR::Vector(); args->push_back(le); - auto mc = new IR::MethodCallExpression(Util::SourceInfo(), method, - emptyTypeArguments, args); - const IR::Statement* set = new IR::AssignmentStatement(flc->srcInfo, dest, mc); + const IR::Statement *set = new IR::AssignmentStatement(flc->srcInfo, dest, + method(args)); if (uov.cond != nullptr) { auto cond = conv.convert(uov.cond); set = new IR::IfStatement(Util::SourceInfo(), cond, set, nullptr); diff --git a/frontends/p4/fromv1.0/programStructure.h b/frontends/p4/fromv1.0/programStructure.h index 561f5e09fd7..0d9a9d3eb3e 100644 --- a/frontends/p4/fromv1.0/programStructure.h +++ b/frontends/p4/fromv1.0/programStructure.h @@ -175,8 +175,8 @@ class ProgramStructure { const IR::Expression* convertFieldList(const IR::Expression* expression); const IR::Type_Struct* createFieldListType(const IR::Expression* expression); const IR::Expression* convertHashAlgorithm(IR::ID algorithm); - const IR::Statement* sliceAssign(Util::SourceInfo srcInfo, const IR::Expression* left, - const IR::Expression* right, const IR::Expression* mask); + const IR::Statement* sliceAssign(Util::SourceInfo srcInfo, IR::ERef left, + IR::ERef right, IR::ERef mask); const IR::Expression* counterType(const IR::CounterOrMeter* cm) const; cstring mapAlgorithm(IR::ID algorithm) const; void createChecksumVerifications(); @@ -190,7 +190,7 @@ class ProgramStructure { void createMain(); public: - const IR::Expression* paramReference(const IR::Parameter* param); + IR::ERef paramReference(const IR::Parameter* param); void tablesReferred(const IR::V1Control* control, std::vector &out); bool isHeader(const IR::ConcreteHeaderRef* nhr) const; diff --git a/frontends/p4/p4-parse.ypp b/frontends/p4/p4-parse.ypp index 43cd745fa95..c2c4fbb96f2 100644 --- a/frontends/p4/p4-parse.ypp +++ b/frontends/p4/p4-parse.ypp @@ -94,7 +94,7 @@ static int yylex(); IR::Constant *Constant; IR::Declaration *Declaration; IR::Direction dir; - IR::Expression *Expression; + IR::ERef Expression; IR::IDeclaration *decl; IR::KeyElement *KeyElement; IR::Method *Method; @@ -452,8 +452,8 @@ simpleExpressionList simpleKeysetExpression : expression { $$ = $1; } - | expression MASK expression { $$ = new IR::Mask(@1 + @3, $1, $3); } - | expression RANGE expression { $$ = new IR::Range(@1 + @3, $1, $3); } + | expression MASK expression { $$ = $1.Mask($3); } + | expression RANGE expression { $$ = $1.Range($3); } | DEFAULT { $$ = new IR::DefaultExpression(@1); } | DONTCARE { $$ = new IR::DefaultExpression(@1); } ; @@ -673,13 +673,9 @@ typedefDeclaration assignmentOrMethodCallStatement // These rules are overly permissive, but they avoid some conflicts - : lvalue '(' argumentList ')' ';' { auto mc = new IR::MethodCallExpression(@1 + @4, $1, - new IR::Vector(), $3); - $$ = new IR::MethodCallStatement(@1 + @4, mc); } + : lvalue '(' argumentList ')' ';' { $$ = new IR::MethodCallStatement(@1 + @4, $1($3)); } | lvalue '<' typeArgumentList '>' '(' argumentList ')' ';' - { auto mc = new IR::MethodCallExpression(@1 + @7, - $1, $3, $6); - $$ = new IR::MethodCallStatement(@1 + @7, mc); } + { $$ = new IR::MethodCallStatement(@1 + @7, $1($3, $6)); } | lvalue '=' expression ';' { $$ = new IR::AssignmentStatement(@2, $1, $3); } ; @@ -810,10 +806,8 @@ actionRef : optAnnotations name { auto expr = new IR::PathExpression(*$2); $$ = new IR::ActionListElement(@2, $1, expr);} | optAnnotations name '(' argumentList ')' - { auto method = new IR::PathExpression(*$2); - auto mce = new IR::MethodCallExpression( - @2+@4, method, new IR::Vector(), $4); - $$ = new IR::ActionListElement(@2, $1, mce); } + { IR::ERef method = new IR::PathExpression(*$2); + $$ = new IR::ActionListElement(@2, $1, method($4)); } ; /************************* ACTION ********************************/ @@ -888,26 +882,26 @@ prefixedNonTypeName lvalue : prefixedNonTypeName { $$ = new IR::PathExpression($1); } | THIS { $$ = new IR::This(@1); } // experimental - | lvalue '.' name { $$ = new IR::Member(@1 + @3, $1, *$3); } - | lvalue '[' expression ']' { $$ = new IR::ArrayIndex(@1 + @4, $1, $3); } - | lvalue '[' expression ':' expression ']' { $$ = new IR::Slice(@1 + @6, $1, $3, $5); } + | lvalue '.' name { $$ = $1.Member(*$3); } + | lvalue '[' expression ']' { $$ = $1[$3]; } + | lvalue '[' expression ':' expression ']' { $$ = $1.Slice($3, $5); } ; expression : INTEGER { $$ = $1; } | STRING_LITERAL { $$ = new IR::StringLiteral(@1, $1); } - | TRUE { $$ = new IR::BoolLiteral(@1, true); } - | FALSE { $$ = new IR::BoolLiteral(@1, false); } + | TRUE { $$ = true; } + | FALSE { $$ = false; } | THIS { $$ = new IR::This(@1); } // experimental | nonTypeName { $$ = new IR::PathExpression(*$1); } | '.' nonTypeName { $$ = new IR::PathExpression(new IR::Path(*$2, true)); } - | expression '[' expression ']' { $$ = new IR::ArrayIndex(@1 + @4, $1, $3); } - | expression '[' expression ':' expression ']' { $$ = new IR::Slice(@1 + @6, $1, $3, $5); } + | expression '[' expression ']' { $$ = $1[$3]; } + | expression '[' expression ':' expression ']' { $$ = $1.Slice($3, $5); } | '{' expressionList '}' { $$ = new IR::ListExpression(@1 + @3, $2); } | '(' expression ')' { $$ = $2; } - | '!' expression %prec PREFIX { $$ = new IR::LNot(@1 + @2, $2); } - | '~' expression %prec PREFIX { $$ = new IR::Cmpl(@1 + @2, $2); } - | '-' expression %prec PREFIX { $$ = new IR::Neg(@1 + @2, $2); } + | '!' expression %prec PREFIX { $$ = !$2; } + | '~' expression %prec PREFIX { $$ = ~$2; } + | '-' expression %prec PREFIX { $$ = -$2; } | '+' expression %prec PREFIX { $$ = $2; } | typeName '.' name { $$ = new IR::Member( @1 + @3, new IR::TypeNameExpression(@1, $1), *$3); } @@ -917,33 +911,31 @@ expression @1+@3, new IR::Type_Name( @1, new IR::Path(IR::ID(@1, "error")))), *$3); } - | expression '.' name { $$ = new IR::Member(@1 + @3, $1, *$3); } - | expression '*' expression { $$ = new IR::Mul(@1 + @3, $1, $3); } - | expression '/' expression { $$ = new IR::Div(@1 + @3, $1, $3); } - | expression '%' expression { $$ = new IR::Mod(@1 + @3, $1, $3); } - | expression '+' expression { $$ = new IR::Add(@1 + @3, $1, $3); } - | expression '-' expression { $$ = new IR::Sub(@1 + @3, $1, $3); } - | expression SHL expression { $$ = new IR::Shl(@1 + @3, $1, $3); } - | expression '>''>' expression { checkShift(@2, @3); $$ = new IR::Shr(@1 + @4, $1, $4); } - | expression LE expression { $$ = new IR::Leq(@1 + @3, $1, $3); } - | expression GE expression { $$ = new IR::Geq(@1 + @3, $1, $3); } - | expression '<' expression { $$ = new IR::Lss(@1 + @3, $1, $3); } - | expression '>' expression { $$ = new IR::Grt(@1 + @3, $1, $3); } - | expression NE expression { $$ = new IR::Neq(@1 + @3, $1, $3); } - | expression EQ expression { $$ = new IR::Equ(@1 + @3, $1, $3); } - | expression '&' expression { $$ = new IR::BAnd(@1 + @3, $1, $3); } - | expression '^' expression { $$ = new IR::BXor(@1 + @3, $1, $3); } - | expression '|' expression { $$ = new IR::BOr(@1 + @3, $1, $3); } - | expression PP expression { $$ = new IR::Concat(@1 + @3, $1, $3); } - | expression AND expression { $$ = new IR::LAnd(@1 + @2 + @3, $1, $3); } - | expression OR expression { $$ = new IR::LOr(@1 + @2 + @3, $1, $3); } - | expression '?' expression ':' expression { $$ = new IR::Mux(@1 + @5, $1, $3, $5); } - | expression '<' typeArgumentList '>' '(' argumentList ')' - { $$ = new IR::MethodCallExpression(@1 + @4, $1, $3, $6); } + | expression '.' name { $$ = $1.Member(*$3); } + | 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 '>''>' expression { checkShift(@2, @3); $$ = $1 >> $4; } + | 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 PP expression { $$ = $1.Concat($3); } + | expression AND expression { $$ = $1 && $3; } + | expression OR expression { $$ = $1 || $3; } + | expression '?' expression ':' expression { $$ = $1.Mux($3, $5); } + | expression '<' typeArgumentList '>' '(' argumentList ')' { $$ = $1($3, $6); } // FIXME: the previous rule has the wrong precedence, and parses with // precedence weaker than casts. There is no easy way to fix this in bison. - | expression '(' argumentList ')' { $$ = new IR::MethodCallExpression(@1 + @4, $1, - new IR::Vector(), $3); } + | expression '(' argumentList ')' { $$ = $1($3); } | typeRef '(' argumentList ')' { $$ = new IR::ConstructorCallExpression(@1 + @4, $1, $3); } | '(' typeRef ')' expression %prec PREFIX { $$ = new IR::Cast(@1 + @4, $2, $4); } diff --git a/ir/dump.cpp b/ir/dump.cpp index 1024678d504..1faf05f7b85 100644 --- a/ir/dump.cpp +++ b/ir/dump.cpp @@ -60,9 +60,14 @@ void dump(std::ostream &out, const IR::Node *n, unsigned maxdepth) { void dump(std::ostream &out, const IR::Node *n) { dump(out, n, ~0U); } void dump(const IR::Node *n, unsigned maxdepth) { dump(std::cout, n, maxdepth); } void dump(const IR::Node *n) { dump(n, ~0U); } +void dump(const IR::ERef &e, unsigned maxdepth) { dump(e->to(), maxdepth); } +void dump(const IR::ERef &e) { dump(e->to()); } + void dump_notype(const IR::Node *n, unsigned maxdepth) { n->apply(IRDumper(std::cout, maxdepth, "type")); } void dump_notype(const IR::Node *n) { dump_notype(n, ~0U); } +void dump_notype(const IR::ERef &e, unsigned maxdepth) { dump_notype(e->to(), maxdepth); } +void dump_notype(const IR::ERef &e) { dump_notype(e->to()); } void dump(uintptr_t p, unsigned maxdepth) { dump(reinterpret_cast(p), maxdepth); } diff --git a/ir/expression.def b/ir/expression.def index 96736d8a72e..f597f4ac2bd 100644 --- a/ir/expression.def +++ b/ir/expression.def @@ -66,10 +66,12 @@ class Sub : Operation_Binary { class Shl : Operation_Binary { stringOp = "<<"; precedence = DBPrint::Prec_Shl; + Shl { if (type->is() && left) type = left->type; } } class Shr : Operation_Binary { stringOp = ">>"; precedence = DBPrint::Prec_Shr; + Shr { if (type->is() && left) type = left->type; } } class Equ : Operation_Relation { stringOp = "=="; @@ -207,6 +209,12 @@ class Slice : Operation_Ternary { : Operation_Ternary(a, new Constant(hi), new Constant(lo)) {} Slice(Util::SourceInfo si, Expression a, int hi, int lo) : Operation_Ternary(si, a, new Constant(hi), new Constant(lo)) {} + Slice { + if (type->is() && e1 && e2) { + auto hi = e1->to(); + auto lo = e2->to(); + if (lo && hi) + type = IR::Type::Bits::get(hi->asInt() - lo->asInt() + 1); } } } class Member : Operation_Unary { @@ -221,11 +229,20 @@ class Member : Operation_Unary { class Concat : Operation_Binary { stringOp = "++"; precedence = DBPrint::Prec_Add; + Concat { + if (left && right) { + auto lt = left->type->to(); + auto rt = left->type->to(); + if (lt && rt) + type = IR::Type::Bits::get(lt->size + rt->size, lt->isSigned); } } } class ArrayIndex : Operation_Binary { stringOp = "[]"; precedence = DBPrint::Prec_Postfix; + ArrayIndex { + if (auto st = left ? left->type->to() : nullptr) + type = st->elementType; } } class Range : Operation_Binary { @@ -247,6 +264,7 @@ class Mux : Operation_Ternary { v.visit(e1, "e1"); clone.visit(e2, "e2"); v.flow_merge(clone); } + Mux { if (type->is() && e1 && e2 && e1->type == e2->type) type = e1->type; } } class DefaultExpression : Expression {} diff --git a/ir/expression_ref.h b/ir/expression_ref.h new file mode 100644 index 00000000000..165c489deb3 --- /dev/null +++ b/ir/expression_ref.h @@ -0,0 +1,82 @@ +#ifndef IR_EXPRESSION_REF_H_ +#define IR_EXPRESSION_REF_H_ + +#include "ir.h" + +namespace IR { + +class ERef { + const Expression *expr; + + template class ERef_specific { + const T *expr; + friend class ERef; + + public: + ERef_specific(const T *e) : expr(e) {} // NOLINT(runtime/explicit) + const T &operator*() const { return *expr; } + const T *operator->() const { return expr; } + operator const T *() const { return expr; } + }; + + public: + ERef(const Expression *e) : expr(e) {} // NOLINT(runtime/explicit) + ERef(const Expression &e) : expr(&e) {} // NOLINT(runtime/explicit) + template ERef(ERef_specific e) : expr(e) {} // NOLINT(runtime/explicit) + ERef(int v) : expr(new Constant(v)) {} // NOLINT(runtime/explicit) + ERef(unsigned v) : expr(new Constant(v)) {} // NOLINT(runtime/explicit) + ERef(long v) : expr(new Constant(v)) {} // NOLINT(runtime/explicit) + ERef(unsigned long v) : expr(new Constant(v)) {} // NOLINT(runtime/explicit) + ERef(bool v) : expr(new BoolLiteral(v)) {} // NOLINT(runtime/explicit) + operator const Expression *() const { return expr; } + const Expression &operator *() const { return *expr; } + const Expression *operator ->() const { return expr; } + ERef operator[](ERef idx) const { return new ArrayIndex(expr, idx); } + ERef operator-() const { return new Neg(expr); } + ERef operator~() const { return new Cmpl(expr); } + ERef operator!() const { return new LNot(expr); } + ERef operator+(ERef a) const { return new Add(expr, a); } + ERef operator-(ERef a) const { return new Sub(expr, a); } + ERef operator*(ERef a) const { return new Mul(expr, a); } + ERef operator/(ERef a) const { return new Div(expr, a); } + ERef operator%(ERef a) const { return new Mod(expr, a); } + ERef operator<<(ERef a) const { return new Shl(expr, a); } + ERef operator>>(ERef a) const { return new Shr(expr, a); } + ERef operator==(ERef a) const { return new Equ(expr, a); } + ERef operator!=(ERef a) const { return new Neq(expr, a); } + ERef operator<=(ERef a) const { return new Leq(expr, a); } + ERef operator>=(ERef a) const { return new Geq(expr, a); } + ERef operator<(ERef a) const { return new Lss(expr, a); } + ERef operator>(ERef a) const { return new Grt(expr, a); } + ERef operator&(ERef a) const { return new BAnd(expr, a); } + ERef operator|(ERef a) const { return new BOr(expr, a); } + ERef operator^(ERef a) const { return new BXor(expr, a); } + ERef operator&&(ERef a) const { return new LAnd(expr, a); } + ERef operator||(ERef a) const { return new LOr(expr, a); } + ERef Slice(ERef hi, ERef lo) const { return new IR::Slice(expr, hi, lo); } + ERef Range(ERef to) const { return new IR::Range(expr, to); } + ERef Concat(ERef a) const { return new IR::Concat(expr, a); } + ERef Mask(ERef mask) const { return new IR::Mask(expr, mask); } + ERef Mux(ERef t, ERef f) const { return new IR::Mux(expr, t, f); } + ERef_specific Member(Util::SourceInfo srcInfo, IR::ID name) const { + return new IR::Member(srcInfo + expr->srcInfo + name.srcInfo, expr, name); } + ERef_specific Member(IR::ID name) const { + return new IR::Member(expr->srcInfo + name.srcInfo, expr, name); } + ERef_specific operator()(const Vector *targs = nullptr, + const Vector *args = nullptr) const { + auto srcInfo = expr->srcInfo; + if (args) { + srcInfo += args->srcInfo; + if (!args->empty()) srcInfo += args->back()->srcInfo; + } else if (targs) { + srcInfo += targs->srcInfo; + if (!targs->empty()) srcInfo += targs->back()->srcInfo; } + return new MethodCallExpression(srcInfo, expr, targs ? targs : new Vector(), + args ? args : new Vector()); } + ERef_specific operator()(const Vector *args) const { + return (*this)(nullptr, args); } +}; + +} // end namespace IR + +#endif /* IR_EXPRESSION_REF_H_ */ diff --git a/ir/ir.h b/ir/ir.h index 66632d57c3b..51c556e426d 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -52,5 +52,6 @@ limitations under the License. #include "pass_manager.h" #include "ir-inline.h" #include "dump.h" +#include "expression_ref.h" #endif /* _IR_IR_H_*/