From 8a4d769b3d50953117b6a5a99070e5c3db6fbc61 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 16 Dec 2013 03:49:57 +0200 Subject: [PATCH] Type name expressions down to elaboration. --- PExpr.cc | 9 +++++++++ PExpr.h | 15 ++++++++++++++ elab_expr.cc | 54 ++++++++++++++++++++++++++++++++++++++++++--------- parse.y | 8 ++++++++ pform_dump.cc | 5 +++++ 5 files changed, 82 insertions(+), 9 deletions(-) diff --git a/PExpr.cc b/PExpr.cc index 538f4f37f..4c7f303f6 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -540,6 +540,15 @@ bool PETernary::has_aa_term(Design*des, NetScope*scope) const || fal_->has_aa_term(des, scope); } +PETypename::PETypename(data_type_t*dt) +: data_type_(dt) +{ +} + +PETypename::~PETypename() +{ +} + PEUnary::PEUnary(char op, PExpr*ex) : op_(op), expr_(ex) { diff --git a/PExpr.h b/PExpr.h index 714778994..910f8a1b8 100644 --- a/PExpr.h +++ b/PExpr.h @@ -660,6 +660,21 @@ class PEString : public PExpr { char*text_; }; +class PETypename : public PExpr { + public: + explicit PETypename(data_type_t*data_type); + ~PETypename(); + + virtual void dump(ostream&) const; + virtual unsigned test_width(Design*des, NetScope*scope, + width_mode_t&mode); + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, + ivl_type_t type, unsigned flags) const; + + private: + data_type_t*data_type_; +}; + class PEUnary : public PExpr { public: diff --git a/elab_expr.cc b/elab_expr.cc index dc0d8de69..67397c26e 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -188,7 +188,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const * supported, can assign to packed arrays and structs, unpacked arrays * and dynamic arrays. */ -unsigned PEAssignPattern::test_width(Design*des, NetScope*scope, width_mode_t&mode) +unsigned PEAssignPattern::test_width(Design*, NetScope*, width_mode_t&) { expr_type_ = IVL_VT_DARRAY; expr_width_ = 1; @@ -1078,10 +1078,14 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope, if (expr == 0) return 0; - // The argument type/width is self-determined and doesn't - // affect the result type/width. - width_mode_t arg_mode = SIZED; - expr->test_width(des, scope, arg_mode); + if (! dynamic_cast(expr)) { + // The argument type/width is self-determined and doesn't + // affect the result type/width. Note that if the + // argument is a type name (a special case) then + // don't bother with this step. + width_mode_t arg_mode = SIZED; + expr->test_width(des, scope, arg_mode); + } expr_type_ = IVL_VT_BOOL; expr_width_ = integer_width; @@ -1393,11 +1397,18 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, PExpr*expr = parms_[0]; - verinum val ( (uint64_t)expr->expr_width(), integer_width); - NetEConst*sub = new NetEConst(val); - sub->set_line(*this); + if (PETypename*type_expr = dynamic_cast(expr)) { + cerr << get_fileline() << ": sorry: " + << "I don't yet support typename argumets to $bits." << endl; + des->errors += 1; + return 0; + } else { + verinum val ( (uint64_t)expr->expr_width(), integer_width); + NetEConst*sub = new NetEConst(val); + sub->set_line(*this); - return cast_to_width_(sub, expr_wid); + return cast_to_width_(sub, expr_wid); + } } /* Interpret the internal $is_signed system function to return @@ -5158,6 +5169,31 @@ NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope, return tmp; } +/* + * A typename expression is only legal in very narrow cases. This is + * just a placeholder. + */ +unsigned PETypename::test_width(Design*des, NetScope*, width_mode_t&) +{ + cerr << get_fileline() << ": error: " + << "Type names are not valid expressions here." << endl; + des->errors += 1; + + expr_type_ = IVL_VT_NO_TYPE; + expr_width_ = 1; + min_width_ = 1; + signed_flag_ = false; + return expr_width_; +} + +NetExpr*PETypename::elaborate_expr(Design*des, NetScope*, + ivl_type_t, unsigned) const +{ + cerr << get_fileline() << ": error: Type name not a valid expression here." << endl; + des->errors += 1; + return 0; +} + unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode) { switch (op_) { diff --git a/parse.y b/parse.y index d5c352583..15e4a9814 100644 --- a/parse.y +++ b/parse.y @@ -3097,6 +3097,14 @@ expr_primary delete[]$1; } + /* There are a few special cases (notably $bits argument) where the + expression may be a type name. Let the elaborator sort this out. */ + | TYPE_IDENTIFIER + { PETypename*tmp = new PETypename($1); + FILE_NAME(tmp,@1); + $$ = tmp; + } + /* The hierarchy_identifier rule matches simple identifiers as well as indexed arrays and part selects */ diff --git a/pform_dump.cc b/pform_dump.cc index b5ab2b348..a8b08c04b 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -385,6 +385,11 @@ void PETernary::dump(ostream&out) const out << "(" << *expr_ << ")?(" << *tru_ << "):(" << *fal_ << ")"; } +void PETypename::dump(ostream&fd) const +{ + fd << ""; +} + void PEUnary::dump(ostream&out) const { switch (op_) {