diff --git a/PExpr.cc b/PExpr.cc index 8e22bd950..49a3971a2 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -139,31 +139,12 @@ bool PEBinary::has_aa_term(Design*des, NetScope*scope) const return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope); } -PECastSize::PECastSize(PExpr*si, PExpr*b) -: size_(si), base_(b) +PECast::PECast(PExpr *target, PExpr *base) +: target_(target), base_(base) { } -PECastSize::~PECastSize() -{ -} - -bool PECastSize::has_aa_term(Design *des, NetScope *scope) const -{ - return base_->has_aa_term(des, scope); -} - -PECastType::PECastType(data_type_t*t, PExpr*b) -: target_(t), base_(b) -{ - target_type_ = nullptr; -} - -PECastType::~PECastType() -{ -} - -bool PECastType::has_aa_term(Design *des, NetScope *scope) const +bool PECast::has_aa_term(Design *des, NetScope *scope) const { return base_->has_aa_term(des, scope); } diff --git a/PExpr.h b/PExpr.h index b934763f6..e1acb5ca4 100644 --- a/PExpr.h +++ b/PExpr.h @@ -51,6 +51,11 @@ class PExpr : public LineInfo { // Mode values used by test_width() (see below for description). enum width_mode_t { SIZED, UNSIZED, EXPAND, LOSSLESS, UPSIZE }; + enum class type_elaboration_context_t { + DEFAULT, + CAST_TARGET + }; + // Flag values that can be passed to elaborate_expr(). static const unsigned NO_FLAGS = 0x0; static const unsigned NEED_CONST = 0x1; @@ -132,8 +137,12 @@ class PExpr : public LineInfo { // may cache lookup state for a subsequent elaborate_type() call. virtual bool test_type(Design *des, NetScope *scope); - // Elaborate this expression as a type. Return null on failure. - virtual ivl_type_t elaborate_type(Design *des, NetScope *scope) const; + // Elaborate this expression as a type in a specific context. Return + // null if the expression is not a type or elaboration fails. + virtual ivl_type_t elaborate_type( + Design *des, NetScope *scope, + type_elaboration_context_t context = + type_elaboration_context_t::DEFAULT) const; // After the test_width method is complete, these methods // return valid results. @@ -385,7 +394,10 @@ class PEIdent : public PExpr { virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, ivl_type_t type, unsigned flags) const override; bool test_type(Design *des, NetScope *scope) override; - ivl_type_t elaborate_type(Design *des, NetScope *scope) const override; + ivl_type_t elaborate_type( + Design *des, NetScope *scope, + type_elaboration_context_t context = + type_elaboration_context_t::DEFAULT) const override; virtual NetExpr*elaborate_expr(Design*des, NetScope*, unsigned expr_wid, unsigned flags) const override; @@ -732,7 +744,10 @@ class PETypename : public PExpr { virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, ivl_type_t type, unsigned flags) const override; bool test_type(Design *des, NetScope *scope) override; - ivl_type_t elaborate_type(Design *des, NetScope *scope) const override; + ivl_type_t elaborate_type( + Design *des, NetScope *scope, + type_elaboration_context_t context = + type_elaboration_context_t::DEFAULT) const override; private: data_type_t*data_type_; @@ -1041,57 +1056,64 @@ class PECallFunction : public PExpr { unsigned test_width_chain_(Design*des, NetScope*scope, width_mode_t&mode); }; -/* - * Support the SystemVerilog cast to size. - */ -class PECastSize : public PExpr { +/* Support SystemVerilog size and type casts. */ +class PECast : public PExpr { public: - explicit PECastSize(PExpr*size, PExpr*base); - ~PECastSize() override; + explicit PECast(PExpr *target, PExpr *base); + ~PECast() override = default; void dump(std::ostream &out) const override; - virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, - unsigned expr_wid, - unsigned flags) const override; + NetExpr *elaborate_expr(Design *des, NetScope *scope, + ivl_type_t type, unsigned int flags) const override; - virtual bool has_aa_term(Design *des, NetScope *scope) const override; + NetExpr *elaborate_expr(Design *des, NetScope *scope, + unsigned int expr_wid, + unsigned int flags) const override; - virtual unsigned test_width(Design*des, NetScope*scope, - width_mode_t&mode) override; + bool has_aa_term(Design *des, NetScope *scope) const override; + + unsigned int test_width(Design *des, NetScope *scope, + width_mode_t &mode) override; private: - PExpr* size_; - PExpr* base_; -}; + NetExpr *elaborate_size_cast_(Design *des, NetScope *scope, + unsigned int expr_wid, + unsigned int target_width, + bool signed_flag, + unsigned int flags) const; + NetExpr *elaborate_type_cast_(Design *des, NetScope *scope, + unsigned int expr_wid, + ivl_type_t target_type, + unsigned int target_width, + bool signed_flag, + unsigned int flags) const; -/* - * Support the SystemVerilog cast to a different type. - */ -class PECastType : public PExpr { + enum class target_kind_t { + ERROR, + SIZE, + TYPE + }; - public: - explicit PECastType(data_type_t*target, PExpr*base); - ~PECastType() override; + struct target_info_t { + target_kind_t kind = target_kind_t::ERROR; + ivl_type_t type = nullptr; + unsigned int width = 0; + }; - void dump(std::ostream &out) const override; + target_info_t resolve_target_(Design *des, NetScope *scope) const; + target_info_t target_for_scope_(Design *des, NetScope *scope) const; - virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, - ivl_type_t type, unsigned flags) const override; + std::unique_ptr target_; + std::unique_ptr base_; - virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, - unsigned expr_wid, unsigned flags) const override; - - virtual bool has_aa_term(Design *des, NetScope *scope) const override; - - virtual unsigned test_width(Design*des, NetScope*scope, - width_mode_t&mode) override; - - private: - data_type_t* target_; - ivl_type_t target_type_; - PExpr* base_; + // Cast targets can depend on parameters in the instance scope. Width + // testing and expression elaboration run sequentially for one scope, so + // retain only the most recent result. + const NetScope *target_scope_ = nullptr; + target_info_t target_info_; + bool target_resolved_ = false; }; /* diff --git a/elab_expr.cc b/elab_expr.cc index 9b381394f..bd216ba1e 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -488,7 +488,8 @@ unsigned PExpr::test_width(Design*des, NetScope*, width_mode_t&) return 1; } -ivl_type_t PExpr::elaborate_type(Design *, NetScope *) const +ivl_type_t PExpr::elaborate_type( + Design *, NetScope *, type_elaboration_context_t) const { return nullptr; } @@ -4219,151 +4220,263 @@ NetExpr* PECallFunction::elaborate_expr_method_par_(Design*des, const NetScope*s return 0; } -unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&) +struct cast_type_info_t { + ivl_variable_type_t expr_type; + unsigned int width; +}; + +static cast_type_info_t cast_type_info(ivl_type_t type) { - ivl_assert(*this, size_); + if (auto darray = dynamic_cast(type)) { + return { darray->element_base_type(), + static_cast(darray->element_width()) }; + } + + if (auto string_type = dynamic_cast(type)) { + return { string_type->base_type(), 8 }; + } + + return { type->base_type(), + static_cast(type->packed_width()) }; +} + +static unsigned int evaluate_cast_size(Design *des, NetScope *scope, + PExpr *target, const LineInfo &loc) +{ + unsigned int width = 0; + auto size_expr = elab_and_eval(des, scope, target, -1, true); + auto size_const = dynamic_cast(size_expr); + if (size_const && !size_const->value().is_negative()) + width = size_const->value().as_ulong(); + delete size_expr; + + if (width == 0) { + cerr << loc.get_fileline() << ": error: Cast size expression " + << "must be constant and greater than zero." << endl; + des->errors += 1; + } + + return width; +} + +static bool test_size_cast_base(Design *des, NetScope *scope, PExpr *base, + const LineInfo &loc) +{ + PExpr::width_mode_t mode = PExpr::SIZED; + base->test_width(des, scope, mode); + + if (type_is_vectorable(base->expr_type())) + return true; + + cerr << loc.get_fileline() << ": error: Cast base expression " + << "must be a vector type." << endl; + des->errors += 1; + return false; +} + +PECast::target_info_t PECast::resolve_target_(Design *des, + NetScope *scope) const +{ + target_info_t target_info; + + if (target_->test_type(des, scope)) { + auto type = target_->elaborate_type( + des, scope, PExpr::type_elaboration_context_t::CAST_TARGET); + if (!type) + return target_info; + + target_info.kind = target_kind_t::TYPE; + target_info.type = type; + return target_info; + } + + target_info.width = evaluate_cast_size( + des, scope, target_.get(), *this); + if (target_info.width != 0) + target_info.kind = target_kind_t::SIZE; + + return target_info; +} + +PECast::target_info_t PECast::target_for_scope_(Design *des, + NetScope *scope) const +{ + if (target_resolved_ && target_scope_ == scope) + return target_info_; + + return resolve_target_(des, scope); +} + +unsigned int PECast::test_width(Design *des, NetScope *scope, width_mode_t &) +{ + ivl_assert(*this, target_); ivl_assert(*this, base_); - expr_width_ = 0; - - NetExpr*size_ex = elab_and_eval(des, scope, size_, -1, true); - const NetEConst*size_ce = dynamic_cast(size_ex); - if (size_ce && !size_ce->value().is_negative()) - expr_width_ = size_ce->value().as_ulong(); - delete size_ex; - if (expr_width_ == 0) { - cerr << get_fileline() << ": error: Cast size expression " - "must be constant and greater than zero." << endl; - des->errors += 1; - return 0; + if (!target_resolved_ || target_scope_ != scope) { + target_info_ = resolve_target_(des, scope); + target_scope_ = scope; + target_resolved_ = true; } - width_mode_t tmp_mode = PExpr::SIZED; - base_->test_width(des, scope, tmp_mode); - - if (!type_is_vectorable(base_->expr_type())) { - cerr << get_fileline() << ": error: Cast base expression " - "must be a vector type." << endl; - des->errors += 1; + const auto &target_info = target_info_; + if (target_info.kind == target_kind_t::ERROR) return 0; + + if (target_info.kind == target_kind_t::TYPE) { + width_mode_t mode = PExpr::SIZED; + base_->test_width(des, scope, mode); + + auto type_info = cast_type_info(target_info.type); + expr_type_ = type_info.expr_type; + expr_width_ = type_info.width; + min_width_ = expr_width_; + signed_flag_ = target_info.type->get_signed(); + return expr_width_; } - expr_type_ = base_->expr_type(); - min_width_ = expr_width_; + ivl_assert(*this, target_info.kind == target_kind_t::SIZE); + expr_width_ = target_info.width; + if (!test_size_cast_base(des, scope, base_.get(), *this)) + return 0; + + expr_type_ = base_->expr_type(); + min_width_ = expr_width_; signed_flag_ = base_->has_sign(); - return expr_width_; } -NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope, - unsigned expr_wid, unsigned flags) const +NetExpr *PECast::elaborate_expr(Design *des, NetScope *scope, ivl_type_t, + unsigned int flags) const { - flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag - - ivl_assert(*this, size_); + ivl_assert(*this, target_); ivl_assert(*this, base_); + auto target_info = target_for_scope_(des, scope); + if (target_info.kind == target_kind_t::ERROR) + return nullptr; + + if (target_info.kind == target_kind_t::TYPE) { + width_mode_t mode = PExpr::SIZED; + base_->test_width(des, scope, mode); + + auto type_info = cast_type_info(target_info.type); + return elaborate_type_cast_(des, scope, type_info.width, + target_info.type, type_info.width, + target_info.type->get_signed(), + flags); + } + + ivl_assert(*this, target_info.kind == target_kind_t::SIZE); + return elaborate_size_cast_(des, scope, target_info.width, + target_info.width, + base_->has_sign(), flags); +} + +NetExpr *PECast::elaborate_expr(Design *des, NetScope *scope, + unsigned int expr_wid, + unsigned int flags) const +{ + ivl_assert(*this, target_); + ivl_assert(*this, base_); + + auto target_info = target_for_scope_(des, scope); + if (target_info.kind == target_kind_t::ERROR) + return nullptr; + + if (target_info.kind == target_kind_t::TYPE) { + auto type_info = cast_type_info(target_info.type); + return elaborate_type_cast_(des, scope, expr_wid, target_info.type, + type_info.width, signed_flag_, + flags); + } + + ivl_assert(*this, target_info.kind == target_kind_t::SIZE); + return elaborate_size_cast_(des, scope, expr_wid, target_info.width, + signed_flag_, flags); +} + +NetExpr *PECast::elaborate_size_cast_(Design *des, NetScope *scope, + unsigned int expr_wid, + unsigned int target_width, + bool signed_flag, + unsigned int flags) const +{ + flags &= ~SYS_TASK_ARG; + // A cast behaves exactly like an assignment to a temporary variable, // so the temporary result size may affect the sub-expression width. - unsigned cast_width = base_->expr_width(); - if (cast_width < expr_width_) - cast_width = expr_width_; + unsigned int cast_width = base_->expr_width(); + if (cast_width < target_width) + cast_width = target_width; - NetExpr*sub = base_->elaborate_expr(des, scope, cast_width, flags); - if (sub == 0) - return 0; + auto sub = base_->elaborate_expr(des, scope, cast_width, flags); + if (!sub) + return nullptr; // Perform the cast. The extension method (zero/sign), if needed, // depends on the type of the base expression. - NetExpr*tmp = cast_to_width(sub, expr_width_, base_->has_sign(), *this); + auto tmp = cast_to_width(sub, target_width, base_->has_sign(), *this); // Pad up to the expression width. The extension method (zero/sign) // depends on the type of enclosing expression. - return pad_to_width(tmp, expr_wid, signed_flag_, *this); + return pad_to_width(tmp, expr_wid, signed_flag, *this); } -unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&) +NetExpr *PECast::elaborate_type_cast_(Design *des, NetScope *scope, + unsigned int expr_wid, + ivl_type_t target_type, + unsigned int target_width, + bool signed_flag, + unsigned int flags) const { - target_type_ = target_->elaborate_type(des, scope); + auto darray = dynamic_cast(target_type); + auto vector = darray + ? dynamic_cast(darray->element_type()) + : nullptr; + if (vector) { + unsigned int use_width = base_->expr_width(); + auto base_expr = base_->elaborate_expr(des, scope, use_width, + NO_FLAGS); + if (!base_expr) + return nullptr; - width_mode_t tmp_mode = PExpr::SIZED; - base_->test_width(des, scope, tmp_mode); + ivl_assert(*this, vector->packed_width() > 0); + ivl_assert(*this, base_expr->expr_width() > 0); - if (const netdarray_t*use_darray = dynamic_cast(target_type_)) { - expr_type_ = use_darray->element_base_type(); - expr_width_ = use_darray->element_width(); + // Find the number of elements needed to contain the source value. + int length = base_expr->expr_width() + vector->packed_width() - 1; + if (base_expr->expr_width() > + static_cast(vector->packed_width())) + length /= vector->packed_width(); + else + length /= base_expr->expr_width(); - } else if (const netstring_t*use_string = dynamic_cast(target_type_)) { - expr_type_ = use_string->base_type(); - expr_width_ = 8; - - } else { - expr_type_ = target_type_->base_type(); - expr_width_ = target_type_->packed_width(); + auto length_expr = new NetEConst(verinum(length)); + return new NetENew(target_type, length_expr, base_expr); } - min_width_ = expr_width_; - signed_flag_ = target_type_->get_signed(); - return expr_width_; -} - -NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, - ivl_type_t type, unsigned flags) const -{ - const netdarray_t*darray = NULL; - const netvector_t*vector = NULL; - - // Casting array of vectors to dynamic array type - if((darray = dynamic_cast(type)) && - (vector = dynamic_cast(darray->element_type()))) { - PExpr::width_mode_t mode = PExpr::SIZED; - unsigned use_wid = base_->test_width(des, scope, mode); - NetExpr*base = base_->elaborate_expr(des, scope, use_wid, NO_FLAGS); - - ivl_assert(*this, vector->packed_width() > 0); - ivl_assert(*this, base->expr_width() > 0); - - // Find rounded up length that can fit the whole casted array of vectors - int len = base->expr_width() + vector->packed_width() - 1; - if(base->expr_width() > (unsigned)vector->packed_width()) { - len /= vector->packed_width(); - } else { - len /= base->expr_width(); - } - - // Number of words in the created dynamic array - NetEConst*len_expr = new NetEConst(verinum(len)); - return new NetENew(type, len_expr, base); - } - - // Fallback - return elaborate_expr(des, scope, (unsigned) 0, flags); -} - -NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, - unsigned expr_wid, unsigned flags) const -{ - flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag + flags &= ~SYS_TASK_ARG; // A cast behaves exactly like an assignment to a temporary variable, // so the temporary result size may affect the sub-expression width. - unsigned cast_width = base_->expr_width(); - if (type_is_vectorable(base_->expr_type()) && (cast_width < expr_width_)) - cast_width = expr_width_; + unsigned int cast_width = base_->expr_width(); + if (type_is_vectorable(base_->expr_type()) && + cast_width < target_width) + cast_width = target_width; - NetExpr*sub = base_->elaborate_expr(des, scope, cast_width, flags); - if (sub == 0) - return 0; + auto sub = base_->elaborate_expr(des, scope, cast_width, flags); + if (!sub) + return nullptr; - NetExpr*tmp = 0; - if (dynamic_cast(target_type_)) { + NetExpr *tmp = nullptr; + if (dynamic_cast(target_type)) { switch (sub->expr_type()) { case IVL_VT_REAL: return sub; case IVL_VT_LOGIC: case IVL_VT_BOOL: return cast_to_real(sub); - default: + default: break; } cerr << get_fileline() << " error: Expression of type `" @@ -4371,40 +4484,42 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, << endl; des->errors++; return nullptr; - } else if (dynamic_cast(target_type_)) { + } + + if (dynamic_cast(target_type)) { if (base_->expr_type() == IVL_VT_STRING) - return sub; // no conversion + return sub; if (base_->expr_type() == IVL_VT_LOGIC || base_->expr_type() == IVL_VT_BOOL) - return sub; // handled by the target as special cases - } else if (target_type_ && target_type_->packed()) { - switch (target_type_->base_type()) { + return sub; + } else if (target_type->packed()) { + switch (target_type->base_type()) { case IVL_VT_BOOL: - tmp = cast_to_int2(sub, expr_width_); + tmp = cast_to_int2(sub, target_width); break; - case IVL_VT_LOGIC: - tmp = cast_to_int4(sub, expr_width_); + tmp = cast_to_int4(sub, target_width); break; - default: break; } } + if (tmp) { if (tmp == sub) { // We already had the correct base type, so we just need to // fix the size. Note that even if the size is already correct, - // we still need to isolate the sub-expression from changes in - // the signedness pushed down from the main expression. - tmp = cast_to_width(sub, expr_width_, sub->has_sign(), *this); + // we still need to isolate the sub-expression from changes in + // the signedness pushed down from the main expression. + tmp = cast_to_width(sub, target_width, sub->has_sign(), *this); } - return pad_to_width(tmp, expr_wid, signed_flag_, *this, target_type_); + return pad_to_width(tmp, expr_wid, signed_flag, *this, target_type); } - cerr << get_fileline() << ": sorry: This cast operation is not yet supported." << endl; + cerr << get_fileline() + << ": sorry: This cast operation is not yet supported." << endl; des->errors += 1; - return 0; + return nullptr; } unsigned PECastSign::test_width(Design *des, NetScope *scope, width_mode_t &mode) @@ -5078,7 +5193,9 @@ static bool elaborate_type_dimensions(Design *des, NetScope *scope, return dimensions_ok; } -ivl_type_t PEIdent::elaborate_type(Design *des, NetScope *scope) const +ivl_type_t PEIdent::elaborate_type( + Design *des, NetScope *scope, + type_elaboration_context_t context) const { symbol_search_results search_results; NetScope *declaration_scope; @@ -5110,11 +5227,21 @@ ivl_type_t PEIdent::elaborate_type(Design *des, NetScope *scope) const return nullptr; } + const auto &name = path_.name.front(); + if (context == type_elaboration_context_t::CAST_TARGET && + !name.index.empty()) { + cerr << get_fileline() << ": error: Dimensions after a type " + << "identifier are not allowed in a cast target." << endl; + cerr << type_def->get_fileline() + << ": : The type was declared here." << endl; + des->errors++; + return nullptr; + } + ivl_type_t base_type = type_def->elaborate_type(des, declaration_scope); if (!base_type) return nullptr; - const auto &name = path_.name.front(); netranges_t packed_dimensions; if (!elaborate_type_dimensions(des, scope, name.index, packed_dimensions)) @@ -8023,7 +8150,8 @@ NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope, * A typename expression is only legal in very narrow cases. This is * just a placeholder. */ -ivl_type_t PETypename::elaborate_type(Design *des, NetScope *scope) const +ivl_type_t PETypename::elaborate_type( + Design *des, NetScope *scope, type_elaboration_context_t) const { return data_type_->elaborate_type(des, scope); } diff --git a/parse.y b/parse.y index 3548977dd..3cb4be796 100644 --- a/parse.y +++ b/parse.y @@ -1235,7 +1235,7 @@ Module::port_t *module_declare_interface_port(const YYLTYPE&loc, char *type, %type data_type data_type_opt data_type_or_implicit data_type_or_implicit_or_void %type block_reg_data_type %type implicit_type -%type reg_prefixed_atomic_type simple_type_or_string let_formal_type +%type reg_prefixed_atomic_type let_formal_type %type packed_array_data_type atomic_type %type ps_type_identifier ps_type_identifier_dim @@ -2900,35 +2900,6 @@ simple_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */ } ; -simple_type_or_string /* IEEE1800-2005: A.2.2.1 */ - : integer_vector_type - { vector_type_t*tmp = new vector_type_t($1, false, 0); - FILE_NAME(tmp, @1); - $$ = tmp; - } - | non_integer_type - { real_type_t*tmp = new real_type_t($1); - FILE_NAME(tmp, @1); - $$ = tmp; - } - | atom_type - { atom_type_t*tmp = new atom_type_t($1, true); - FILE_NAME(tmp, @1); - $$ = tmp; - } - | K_time - { atom_type_t*tmp = new atom_type_t(atom_type_t::TIME, false); - FILE_NAME(tmp, @1); - $$ = tmp; - } - | K_string - { string_type_t*tmp = new string_type_t; - FILE_NAME(tmp, @1); - $$ = tmp; - } - | ps_type_identifier - ; - /* Many places where statements are allowed can actually take a statement or a null statement marked with a naked semi-colon. */ @@ -4983,24 +4954,14 @@ expr_primary /* Cast expressions are primaries */ - | expr_primary '\'' '(' expression ')' - { PExpr*base = $4; - if (pform_requires_sv(@1, "Size cast")) { - PECastSize*tmp = new PECastSize($1, base); - FILE_NAME(tmp, @1); - $$ = tmp; - } else { - $$ = base; - } - } - - | simple_type_or_string '\'' '(' expression ')' - { PExpr*base = $4; - if (pform_requires_sv(@1, "Type cast")) { - PECastType*tmp = new PECastType($1, base); + | expr_primary_or_typename '\'' '(' expression ')' + { auto base = $4; + if (pform_requires_sv(@1, "Cast expression")) { + auto tmp = new PECast($1, base); FILE_NAME(tmp, @1); $$ = tmp; } else { + delete $1; $$ = base; } } diff --git a/pform_dump.cc b/pform_dump.cc index fcba4b18a..4f3c062b4 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -431,16 +431,9 @@ void PECallFunction::dump(ostream &out) const } } -void PECastSize::dump(ostream &out) const +void PECast::dump(ostream &out) const { - out << *size_ << "'("; - base_->dump(out); - out << ")"; -} - -void PECastType::dump(ostream &out) const -{ - target_->pform_dump(out, 0); + target_->dump(out); out << "'("; base_->dump(out); out << ")"; @@ -533,7 +526,7 @@ void PETernary::dump(ostream&out) const void PETypename::dump(ostream&fd) const { - fd << ""; + data_type_->pform_dump(fd, 0); } void PEUnary::dump(ostream&out) const