From patchwork Fri Dec 10 04:28:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 48747 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E03013858022 for ; Fri, 10 Dec 2021 04:31:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E03013858022 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1639110697; bh=HhWe2CYltjZCDWkhpaKFms8hf5myoJ2bG72mS2+i+b0=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=qeyp94xm9KBsBGeRvynuXDCJS9aZO+ZVs2y5BT7sha3kvuJN0RAkQ+REtL8FhxxgN BZSc5dqaWIBpz/4PSjKPIo2PS/acavUkfiJQ67C8vvLL1j6M/AGRUYxTe0qo+ND36g bQg3xpEvixp67XjZJqr6l+HevhPOb/cHC1Xsw/Zo= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-202.mailbox.org (mout-p-202.mailbox.org [80.241.56.172]) by sourceware.org (Postfix) with ESMTPS id F33DA3858036 for ; Fri, 10 Dec 2021 04:28:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org F33DA3858036 Received: from smtp202.mailbox.org (smtp202.mailbox.org [IPv6:2001:67c:2050:105:465:1:4:0]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-202.mailbox.org (Postfix) with ESMTPS id 4J9Hw32czzzQjmg; Fri, 10 Dec 2021 05:28:35 +0100 (CET) X-Virus-Scanned: amavisd-new at heinlein-support.de To: gcc-patches@gcc.gnu.org Subject: [committed 2/3] d: Update for new front-end interface. Date: Fri, 10 Dec 2021 05:28:25 +0100 Message-Id: <20211210042825.532141-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch updates the gdc codegen interface for the new front-end. Bootstrapped and regression tested on x86_64-linux-gnu, committed to mainline. Regards, Iain. --- gcc/d/ChangeLog: * Make-lang.in (D_FRONTEND_OBJS): Add d/root-optional.o. * d-attribs.cc (build_attributes): Update for new front-end interface. * d-codegen.cc (d_build_call): Likewise. * d-compiler.cc (Compiler::paintAsType): Likewise. * d-lang.cc (d_handle_option): Remove OPT_fpreview_intpromote, add handling of OPT_frevert_intpromote. * d-port.cc (Port::valcpy): Assert buffer is aligned. * d-target.cc (Target::isVectorOpSupported): Update for new front-end interface. * decl.cc (layout_class_initializer): Likewise. * expr.cc (lvalue_p): Likewise. (binop_assignment): Likewise. (ExprVisitor::visit): Likewise. (ExprVisitor::visit (AssignExp *)): Remove generation of _d_arrayctor and _d_arraysetctor library helpers. (ExprVisitor::visit (VarExp *)): Support __traits(initSymbol). * intrinsics.cc (expand_intrinsic_rotate): Update for new front-end interface. * lang.opt (fpreview=intpromote): Remove. (frevert=intpromote): New. * runtime.def (ARRAYCTOR): Remove. (ARRAYSETCTOR): Remove. * toir.cc (IRVisitor::visit): Update for new front-end interface. * types.cc (layout_aggregate_members): Likewise. --- gcc/d/Make-lang.in | 1 + gcc/d/d-attribs.cc | 6 +- gcc/d/d-codegen.cc | 6 +- gcc/d/d-compiler.cc | 4 +- gcc/d/d-lang.cc | 11 +- gcc/d/d-port.cc | 2 + gcc/d/d-target.cc | 30 +- gcc/d/decl.cc | 2 +- gcc/d/expr.cc | 259 +-- gcc/d/intrinsics.cc | 2 +- gcc/d/lang.opt | 8 +- gcc/d/runtime.def | 7 - gcc/d/toir.cc | 3 +- gcc/d/types.cc | 2 +- 14 files changed, 178 insertions(+), 165 deletions(-) diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in index d7f714760f7..00169a743a1 100644 --- a/gcc/d/Make-lang.in +++ b/gcc/d/Make-lang.in @@ -162,6 +162,7 @@ D_FRONTEND_OBJS = \ d/root-filename.o \ d/root-hash.o \ d/root-longdouble.o \ + d/root-optional.o \ d/root-port.o \ d/root-region.o \ d/root-rmem.o \ diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc index 04b9791ab1b..5c9f569d1c4 100644 --- a/gcc/d/d-attribs.cc +++ b/gcc/d/d-attribs.cc @@ -337,10 +337,10 @@ build_attributes (Expressions *eattrs) continue; /* Get the result of the attribute if it hasn't already been folded. */ - if (attr->op == TOKcall) + if (attr->op == EXP::call) attr = attr->ctfeInterpret (); - if (attr->op != TOKstructliteral) + if (attr->op != EXP::structLiteral) { warning_at (make_location_t (attr->loc), OPT_Wattributes, "%qE attribute has no effect", @@ -353,7 +353,7 @@ build_attributes (Expressions *eattrs) Expressions *elems = attr->isStructLiteralExp ()->elements; Expression *e0 = (*elems)[0]; - if (e0->op != TOKstring) + if (e0->op != EXP::string_) { warning_at (make_location_t (attr->loc), OPT_Wattributes, "unknown attribute %qs", e0->toChars()); diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index c082ac5ab80..39c3c6ce987 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -2154,9 +2154,9 @@ d_build_call (TypeFunction *tf, tree callable, tree object, { Lagain: Expression *arg = (*arguments)[i]; - gcc_assert (arg->op != TOKtuple); + gcc_assert (arg->op != EXP::tuple); - if (arg->op == TOKcomma) + if (arg->op == EXP::comma) { CommaExp *ce = arg->isCommaExp (); tree tce = build_expr (ce->e1); @@ -2200,7 +2200,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object, /* Nested structs also have ADDRESSABLE set, but if the type has neither a copy constructor nor a destructor available, then we need to take care of copying its value before passing it. */ - if (arg->op == TOKstructliteral || (!sd->postblit && !sd->dtor)) + if (arg->op == EXP::structLiteral || (!sd->postblit && !sd->dtor)) targ = force_target_expr (targ); targ = convert (build_reference_type (TREE_TYPE (targ)), diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc index 3df40073ac5..c1e78c0a5de 100644 --- a/gcc/d/d-compiler.cc +++ b/gcc/d/d-compiler.cc @@ -50,7 +50,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type) cst = build_integer_cst (expr->toInteger (), build_ctype (expr->type)); else if (expr->type->isfloating ()) cst = build_float_cst (expr->toReal (), expr->type); - else if (expr->op == TOKarrayliteral) + else if (expr->op == EXP::arrayLiteral) { /* Build array as VECTOR_CST, assumes EXPR is constant. */ Expressions *elements = expr->isArrayLiteralExp ()->elements; @@ -99,7 +99,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type) cst = native_interpret_expr (vectype, buffer, len); Expression *e = d_eval_constant_expression (expr->loc, cst); - gcc_assert (e != NULL && e->op == TOKvector); + gcc_assert (e != NULL && e->op == EXP::vector); return e->isVectorExp ()->e1; } diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index 576eefcc01f..2c5d206a95f 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -620,10 +620,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, global.params.inclusiveInContracts = value; break; - case OPT_fpreview_intpromote: - global.params.fix16997 = value; - break; - case OPT_fpreview_nosharedaccess: global.params.noSharedAccess = value; break; @@ -642,8 +638,9 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, case OPT_frevert_all: global.params.useDIP25 = FeatureState::disabled; - global.params.markdown = !value; global.params.dtorFields = FeatureState::disabled; + global.params.fix16997 = !value; + global.params.markdown = !value; break; case OPT_frevert_dip25: @@ -654,6 +651,10 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, global.params.dtorFields = FeatureState::disabled; break; + case OPT_frevert_intpromote: + global.params.fix16997 = !value; + break; + case OPT_frevert_markdown: global.params.markdown = !value; break; diff --git a/gcc/d/d-port.cc b/gcc/d/d-port.cc index 58b3fe138b2..4e867a7db4a 100644 --- a/gcc/d/d-port.cc +++ b/gcc/d/d-port.cc @@ -145,6 +145,8 @@ Port::readlongBE (const void *buffer) void Port::valcpy (void *buffer, uint64_t value, size_t sz) { + gcc_assert (((size_t) buffer) % sz == 0); + switch (sz) { case 1: diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index 21417dddf78..dd244f12119 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -287,7 +287,7 @@ Target::isVectorTypeSupported (int sz, Type *type) Returns true if the operation is supported or type is not a vector. */ bool -Target::isVectorOpSupported (Type *type, unsigned op, Type *) +Target::isVectorOpSupported (Type *type, EXP op, Type *) { if (type->ty != TY::Tvector) return true; @@ -299,31 +299,31 @@ Target::isVectorOpSupported (Type *type, unsigned op, Type *) /* Don't support if expression cannot be represented. */ switch (op) { - case TOKpow: - case TOKpowass: + case EXP::pow: + case EXP::powAssign: /* pow() is lowered as a function call. */ return false; - case TOKmod: - case TOKmodass: + case EXP::mod: + case EXP::modAssign: /* fmod() is lowered as a function call. */ if (type->isfloating ()) return false; break; - case TOKandand: - case TOKoror: + case EXP::andAnd: + case EXP::orOr: /* Logical operators must have a result type of bool. */ return false; - case TOKle: - case TOKlt: - case TOKge: - case TOKgt: - case TOKequal: - case TOKnotequal: - case TOKidentity: - case TOKnotidentity: + case EXP::lessOrEqual: + case EXP::lessThan: + case EXP::greaterOrEqual: + case EXP::greaterThan: + case EXP::equal: + case EXP::notEqual: + case EXP::identity: + case EXP::notIdentity: /* Comparison operators must have a result type of bool. */ return false; diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index c69f5664e8c..bbde4a669e4 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -2239,7 +2239,7 @@ layout_class_initializer (ClassDeclaration *cd) ne->type = cd->type; Expression *e = ne->ctfeInterpret (); - gcc_assert (e->op == TOKclassreference); + gcc_assert (e->op == EXP::classReference); return build_class_instance (e->isClassReferenceExp ()); } diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 8e1d43e2b8f..f1c014dbc16 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -88,7 +88,7 @@ lvalue_p (Expression *e) if (ce != NULL && ce->e1->isLvalue ()) return true; - return (e->op != TOKslice && e->isLvalue ()); + return (e->op != EXP::slice && e->isLvalue ()); } /* Build an expression of code CODE, data type TYPE, and operands ARG0 and @@ -162,7 +162,7 @@ binop_assignment (tree_code code, Expression *e1, Expression *e2) { /* Skip casts for lhs assignment. */ Expression *e1b = e1; - while (e1b->op == TOKcast) + while (e1b->op == EXP::cast_) { CastExp *ce = e1b->isCastExp (); gcc_assert (same_type_p (ce->type, ce->to)); @@ -264,7 +264,7 @@ public: void visit (IdentityExp *e) { - tree_code code = (e->op == TOKidentity) ? EQ_EXPR : NE_EXPR; + tree_code code = (e->op == EXP::identity) ? EQ_EXPR : NE_EXPR; Type *tb1 = e->e1->type->toBasetype (); Type *tb2 = e->e2->type->toBasetype (); @@ -331,7 +331,7 @@ public: { Type *tb1 = e->e1->type->toBasetype (); Type *tb2 = e->e2->type->toBasetype (); - tree_code code = (e->op == TOKequal) ? EQ_EXPR : NE_EXPR; + tree_code code = (e->op == EXP::equal) ? EQ_EXPR : NE_EXPR; if ((tb1->ty == TY::Tsarray || tb1->ty == TY::Tarray) && (tb2->ty == TY::Tsarray || tb2->ty == TY::Tarray)) @@ -391,7 +391,7 @@ public: Otherwise for inequality: (e1.length != 0 && memcmp); */ tree tsizecmp = build_boolop (code, t1len, size_zero_node); - if (e->op == TOKequal) + if (e->op == EXP::equal) result = build_boolop (TRUTH_ORIF_EXPR, tsizecmp, result); else result = build_boolop (TRUTH_ANDIF_EXPR, tsizecmp, result); @@ -404,7 +404,7 @@ public: else { tree tlencmp = build_boolop (code, t1len, t2len); - if (e->op == TOKequal) + if (e->op == EXP::equal) result = build_boolop (TRUTH_ANDIF_EXPR, tlencmp, result); else result = build_boolop (TRUTH_ORIF_EXPR, tlencmp, result); @@ -428,7 +428,7 @@ public: d_array_convert (e->e2), build_typeinfo (e->loc, t1array)); - if (e->op == TOKnotequal) + if (e->op == EXP::notEqual) result = build1 (TRUTH_NOT_EXPR, build_ctype (e->type), result); this->result_ = result; @@ -453,7 +453,7 @@ public: build_expr (e->e1), build_expr (e->e2)); - if (e->op == TOKnotequal) + if (e->op == EXP::notEqual) result = build1 (TRUTH_NOT_EXPR, build_ctype (e->type), result); this->result_ = result; @@ -499,19 +499,19 @@ public: switch (e->op) { - case TOKle: + case EXP::lessOrEqual: code = LE_EXPR; break; - case TOKlt: + case EXP::lessThan: code = LT_EXPR; break; - case TOKge: + case EXP::greaterOrEqual: code = GE_EXPR; break; - case TOKgt: + case EXP::greaterThan: code = GT_EXPR; break; @@ -540,7 +540,7 @@ public: void visit (LogicalExp *e) { - tree_code code = (e->op == TOKandand) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR; + tree_code code = (e->op == EXP::andAnd) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR; if (e->e2->type->toBasetype ()->ty != TY::Tvoid) { @@ -559,7 +559,7 @@ public: tree t2 = build_expr_dtor (e->e2); /* Invert condition for logical or if expression. */ - if (e->op == TOKoror) + if (e->op == EXP::orOr) t1 = build1 (TRUTH_NOT_EXPR, d_bool_type, t1); this->result_ = build_condition (build_ctype (e->type), @@ -576,8 +576,8 @@ public: switch (e->op) { - case TOKadd: - case TOKmin: + case EXP::add: + case EXP::min: if ((e->e1->type->isreal () && e->e2->type->isimaginary ()) || (e->e1->type->isimaginary () && e->e2->type->isreal ())) { @@ -586,7 +586,7 @@ public: tree t1 = build_expr (e->e1); tree t2 = build_expr (e->e2); - if (e->op == TOKmin) + if (e->op == EXP::min) t2 = build1 (NEGATE_EXPR, TREE_TYPE (t2), t2); if (e->e1->type->isreal ()) @@ -597,22 +597,22 @@ public: return; } else - code = (e->op == TOKadd) + code = (e->op == EXP::add) ? PLUS_EXPR : MINUS_EXPR; break; - case TOKmul: + case EXP::mul: code = MULT_EXPR; break; - case TOKdiv: + case EXP::div: /* Determine if the div expression is a lowered pointer diff operation. The front-end rewrites `(p1 - p2)' into `(p1 - p2) / stride'. */ if (MinExp *me = e->e1->isMinExp ()) { if (me->e1->type->ty == TY::Tpointer && me->e2->type->ty == TY::Tpointer - && e->e2->op == TOKint64) + && e->e2->op == EXP::int64) { code = EXACT_DIV_EXPR; break; @@ -623,32 +623,32 @@ public: ? TRUNC_DIV_EXPR : RDIV_EXPR; break; - case TOKmod: + case EXP::mod: code = e->e1->type->isfloating () ? FLOAT_MOD_EXPR : TRUNC_MOD_EXPR; break; - case TOKand: + case EXP::and_: code = BIT_AND_EXPR; break; - case TOKor: + case EXP::or_: code = BIT_IOR_EXPR; break; - case TOKxor: + case EXP::xor_: code = BIT_XOR_EXPR; break; - case TOKshl: + case EXP::leftShift: code = LSHIFT_EXPR; break; - case TOKshr: + case EXP::rightShift: code = RSHIFT_EXPR; break; - case TOKushr: + case EXP::unsignedRightShift: code = UNSIGNED_RSHIFT_EXPR; break; @@ -678,15 +678,15 @@ public: tree result; - if (e->e1->op == TOKcat) + if (e->e1->op == EXP::concatenate) { /* Flatten multiple concatenations to an array. So the expression ((a ~ b) ~ c) becomes [a, b, c] */ int ndims = 2; - for (Expression *ex = e->e1; ex->op == TOKcat;) + for (Expression *ex = e->e1; ex->op == EXP::concatenate;) { - if (ex->op == TOKcat) + if (ex->op == EXP::concatenate) { ex = ex->isCatExp ()->e1; ndims++; @@ -703,7 +703,7 @@ public: int dim = ndims - 1; for (Expression *oe = ce->e2; oe != NULL; - (ce->e1->op != TOKcat + (ce->e1->op != EXP::concatenate ? (oe = ce->e1) : (ce = ce->e1->isCatExp (), oe = ce->e2))) { @@ -751,59 +751,59 @@ public: switch (e->op) { - case TOKaddass: + case EXP::addAssign: code = PLUS_EXPR; break; - case TOKminass: + case EXP::minAssign: code = MINUS_EXPR; break; - case TOKmulass: + case EXP::mulAssign: code = MULT_EXPR; break; - case TOKdivass: + case EXP::divAssign: code = e->e1->type->isintegral () ? TRUNC_DIV_EXPR : RDIV_EXPR; break; - case TOKmodass: + case EXP::modAssign: code = e->e1->type->isfloating () ? FLOAT_MOD_EXPR : TRUNC_MOD_EXPR; break; - case TOKandass: + case EXP::andAssign: code = BIT_AND_EXPR; break; - case TOKorass: + case EXP::orAssign: code = BIT_IOR_EXPR; break; - case TOKxorass: + case EXP::xorAssign: code = BIT_XOR_EXPR; break; - case TOKpowass: + case EXP::powAssign: gcc_unreachable (); - case TOKshlass: + case EXP::leftShiftAssign: code = LSHIFT_EXPR; break; - case TOKshrass: - case TOKushrass: + case EXP::rightShiftAssign: + case EXP::unsignedRightShiftAssign: /* Use the original lhs type before it was promoted. The left operand of `>>>=' does not undergo integral promotions before shifting. Strip off casts just incase anyway. */ - while (e1b->op == TOKcast) + while (e1b->op == EXP::cast_) { CastExp *ce = e1b->isCastExp (); gcc_assert (same_type_p (ce->type, ce->to)); e1b = ce->e1; } - code = (e->op == TOKshrass) ? RSHIFT_EXPR : UNSIGNED_RSHIFT_EXPR; + code = (e->op == EXP::rightShiftAssign) ? RSHIFT_EXPR : UNSIGNED_RSHIFT_EXPR; break; default: @@ -908,7 +908,7 @@ public: /* First, handle special assignment semantics. */ /* Look for array.length = n; */ - if (e->e1->op == TOKarraylength) + if (e->e1->op == EXP::arrayLength) { /* This case should have been rewritten to `_d_arraysetlengthT` in the semantic phase. */ @@ -916,7 +916,7 @@ public: } /* Look for array[] = n; */ - if (e->e1->op == TOKslice) + if (e->e1->op == EXP::slice) { SliceExp *se = e->e1->isSliceExp (); Type *stype = se->e1->type->toBasetype (); @@ -937,15 +937,18 @@ public: tree init = stabilize_expr (&t1); t1 = d_save_expr (t1); - if ((postblit || destructor) && e->op != TOKblit) + if ((postblit || destructor) && e->op != EXP::blit) { - libcall_fn libcall = (e->op == TOKconstruct) - ? LIBCALL_ARRAYSETCTOR : LIBCALL_ARRAYSETASSIGN; + /* Need to call postblit/destructor as part of assignment. + Construction has already been handled by the front-end. */ + gcc_assert (e->op != EXP::construct); + /* So we can call postblits on const/immutable objects. */ Type *tm = etype->unSharedOf ()->mutableOf (); tree ti = build_typeinfo (e->loc, tm); - result = build_libcall (libcall, Type::tvoid, 4, + /* Generate: _d_arraysetassign (t1.ptr, &t2, t1.length, ti); */ + result = build_libcall (LIBCALL_ARRAYSETASSIGN, Type::tvoid, 4, d_array_ptr (t1), build_address (t2), d_array_length (t1), ti); @@ -1011,14 +1014,11 @@ public: this->result_ = compound_expr (result, t1); } - else if ((postblit || destructor) && e->op != TOKblit) + else if ((postblit || destructor) + && e->op != EXP::blit && e->op != EXP::construct) { - /* Generate: _d_arrayassign(ti, from, to) - or: _d_arrayctor(ti, from, to) */ - libcall_fn libcall = (e->op == TOKconstruct) - ? LIBCALL_ARRAYCTOR : LIBCALL_ARRAYASSIGN; - - this->result_ = build_libcall (libcall, e->type, 3, + /* Generate: _d_arrayassign(ti, from, to); */ + this->result_ = build_libcall (LIBCALL_ARRAYASSIGN, e->type, 3, build_typeinfo (e->loc, etype), d_array_convert (e->e2), d_array_convert (e->e1)); @@ -1039,8 +1039,8 @@ public: /* Look for reference initializations. */ if (e->memset == MemorySet::referenceInit) { - gcc_assert (e->op == TOKconstruct || e->op == TOKblit); - gcc_assert (e->e1->op == TOKvar); + gcc_assert (e->op == EXP::construct || e->op == EXP::blit); + gcc_assert (e->e1->op == EXP::variable); Declaration *decl = e->e1->isVarExp ()->var; if (decl->storage_class & (STCout | STCref)) @@ -1060,7 +1060,7 @@ public: /* Other types of assignments that may require post construction. */ Type *tb1 = e->e1->type->toBasetype (); - tree_code modifycode = (e->op == TOKconstruct) ? INIT_EXPR : MODIFY_EXPR; + tree_code modifycode = (e->op == EXP::construct) ? INIT_EXPR : MODIFY_EXPR; /* Look for struct assignment. */ if (tb1->ty == TY::Tstruct) @@ -1071,10 +1071,10 @@ public: StructDeclaration *sd = tb1->isTypeStruct ()->sym; /* Look for struct = 0. */ - if (e->e2->op == TOKint64) + if (e->e2->op == EXP::int64) { /* Use memset to fill struct. */ - gcc_assert (e->op == TOKblit); + gcc_assert (e->op == EXP::blit); tree result = build_memset_call (t1); /* Maybe set-up hidden pointer to outer scope context. */ @@ -1095,8 +1095,8 @@ public: tree init = NULL_TREE; /* Fill any alignment holes in the struct using memset. */ - if ((e->op == TOKconstruct - || (e->e2->op == TOKstructliteral && e->op == TOKblit)) + if ((e->op == EXP::construct + || (e->e2->op == EXP::structLiteral && e->op == EXP::blit)) && (sd->isUnionDeclaration () || !identity_compare_p (sd))) { t1 = stabilize_reference (t1); @@ -1120,10 +1120,10 @@ public: if (tb1->ty == TY::Tsarray) { /* Look for array = 0. */ - if (e->e2->op == TOKint64) + if (e->e2->op == EXP::int64) { /* Use memset to fill the array. */ - gcc_assert (e->op == TOKblit); + gcc_assert (e->op == EXP::blit); this->result_ = build_memset_call (build_expr (e->e1)); return; } @@ -1132,17 +1132,17 @@ public: gcc_assert (e->e2->type->toBasetype ()->ty == TY::Tsarray); /* Determine if we need to run postblit. */ - bool postblit = needs_postblit (etype); - bool destructor = needs_dtor (etype); - bool lvalue = lvalue_p (e->e2); + const bool postblit = needs_postblit (etype); + const bool destructor = needs_dtor (etype); + const bool lvalue = lvalue_p (e->e2); /* Optimize static array assignment with array literal. Even if the elements in rhs are all rvalues and don't have to call postblits, this assignment should call dtors on old assigned elements. */ if ((!postblit && !destructor) - || (e->op == TOKconstruct && e->e2->op == TOKarrayliteral) - || (e->op == TOKconstruct && !lvalue && postblit) - || (e->op == TOKblit || e->e1->type->size () == 0)) + || (e->op == EXP::construct && e->e2->op == EXP::arrayLiteral) + || (e->op == EXP::construct && !lvalue && postblit) + || (e->op == EXP::blit || e->e1->type->size () == 0)) { tree t1 = build_expr (e->e1); tree t2 = convert_for_assignment (build_expr (e->e2), @@ -1152,32 +1152,22 @@ public: return; } + /* All other kinds of lvalue or rvalue static array assignment. + Array construction has already been handled by the front-end. */ + gcc_assert (e->op != EXP::construct); + + /* Generate: _d_arrayassign_l() + or: _d_arrayassign_r() */ + libcall_fn libcall = (lvalue) + ? LIBCALL_ARRAYASSIGN_L : LIBCALL_ARRAYASSIGN_R; + tree elembuf = build_local_temp (build_ctype (etype)); Type *arrtype = (e->type->ty == TY::Tsarray) ? etype->arrayOf () : e->type; - tree result; - - if (e->op == TOKconstruct) - { - /* Generate: _d_arrayctor(ti, from, to) */ - result = build_libcall (LIBCALL_ARRAYCTOR, arrtype, 3, - build_typeinfo (e->loc, etype), - d_array_convert (e->e2), - d_array_convert (e->e1)); - } - else - { - /* Generate: _d_arrayassign_l() - or: _d_arrayassign_r() */ - libcall_fn libcall = (lvalue) - ? LIBCALL_ARRAYASSIGN_L : LIBCALL_ARRAYASSIGN_R; - tree elembuf = build_local_temp (build_ctype (etype)); - - result = build_libcall (libcall, arrtype, 4, - build_typeinfo (e->loc, etype), - d_array_convert (e->e2), - d_array_convert (e->e1), - build_address (elembuf)); - } + tree result = build_libcall (libcall, arrtype, 4, + build_typeinfo (e->loc, etype), + d_array_convert (e->e2), + d_array_convert (e->e1), + build_address (elembuf)); /* Cast the libcall result back to a static array. */ if (e->type->ty == TY::Tsarray) @@ -1202,12 +1192,12 @@ public: { tree result; - if (e->op == TOKplusplus) + if (e->op == EXP::plusPlus) { result = build2 (POSTINCREMENT_EXPR, build_ctype (e->type), build_expr (e->e1), build_expr (e->e2)); } - else if (e->op == TOKminusminus) + else if (e->op == EXP::minusMinus) { result = build2 (POSTDECREMENT_EXPR, build_ctype (e->type), build_expr (e->e1), build_expr (e->e2)); @@ -1441,7 +1431,7 @@ public: the destructor is called for the object instance. */ libcall_fn libcall; - if (e->e1->op == TOKvar) + if (e->e1->op == EXP::variable) { VarDeclaration *v = e->e1->isVarExp ()->var->isVarDeclaration (); if (v && v->onstack) @@ -1586,10 +1576,10 @@ public: size_t offset; tree result; - if (e->e1->op == TOKadd) + if (e->e1->op == EXP::add) { AddExp *ae = e->e1->isAddExp (); - if (ae->e1->op == TOKaddress + if (ae->e1->op == EXP::address && ae->e2->isConst () && ae->e2->type->isintegral ()) { Expression *ex = ae->e1->isAddrExp ()->e1; @@ -1598,7 +1588,7 @@ public: offset = ae->e2->toUInteger (); } } - else if (e->e1->op == TOKsymoff) + else if (e->e1->op == EXP::symbolOffset) { SymOffExp *se = e->e1->isSymOffExp (); if (!declaration_reference_p (se->var)) @@ -1650,7 +1640,7 @@ public: /* The frontend optimizer can convert const symbol into a struct literal. Taking the address of a struct literal is otherwise illegal. */ - if (e->e1->op == TOKstructliteral) + if (e->e1->op == EXP::structLiteral) { StructLiteralExp *sle = e->e1->isStructLiteralExp ()->origin; gcc_assert (sle != NULL); @@ -1689,21 +1679,21 @@ public: TypeFunction *tf = NULL; /* Calls to delegates can sometimes look like this. */ - if (e1b->op == TOKcomma) + if (e1b->op == EXP::comma) { e1b = e1b->isCommaExp ()->e2; - gcc_assert (e1b->op == TOKvar); + gcc_assert (e1b->op == EXP::variable); Declaration *var = e1b->isVarExp ()->var; gcc_assert (var->isFuncDeclaration () && !var->needThis ()); } - if (e1b->op == TOKdotvar && tb->ty != TY::Tdelegate) + if (e1b->op == EXP::dotVariable && tb->ty != TY::Tdelegate) { DotVarExp *dve = e1b->isDotVarExp (); /* Don't modify the static initializer for struct literals. */ - if (dve->e1->op == TOKstructliteral) + if (dve->e1->op == EXP::structLiteral) { StructLiteralExp *sle = dve->e1->isStructLiteralExp (); sle->useStaticInit = false; @@ -1775,7 +1765,7 @@ public: { /* This could be a delegate expression (TY == Tdelegate), but not actually a delegate variable. */ - if (e1b->op == TOKdotvar) + if (e1b->op == EXP::dotVariable) { /* This gets the true function type, getting the function type from e1->type can sometimes be incorrect, such as when calling @@ -1795,7 +1785,7 @@ public: object = delegate_object (callee); callee = delegate_method (callee); } - else if (e1b->op == TOKvar) + else if (e1b->op == EXP::variable) { FuncDeclaration *fd = e1b->isVarExp ()->var->isFuncDeclaration (); gcc_assert (fd != NULL); @@ -1877,7 +1867,7 @@ public: if (e->func->isNested () && !e->func->isThis ()) { - if (e->e1->op == TOKnull) + if (e->e1->op == EXP::null_) object = build_expr (e->e1); else object = get_frame_for_symbol (e->func); @@ -1908,7 +1898,7 @@ public: /* Get pointer to function out of the virtual table. */ if (e->func->isVirtual () && !e->func->isFinalFunc () - && e->e1->op != TOKsuper && e->e1->op != TOKdottype) + && e->e1->op != EXP::super_ && e->e1->op != EXP::dotType) { tree fntype = build_pointer_type (TREE_TYPE (fndecl)); object = d_save_expr (object); @@ -2105,9 +2095,9 @@ public: Type *ftype = e->type->toBasetype (); /* This check is for lambda's, remove `vthis' as function isn't nested. */ - if (e->fd->tok == TOKreserved && ftype->ty == TY::Tpointer) + if (e->fd->tok == TOK::reserved && ftype->ty == TY::Tpointer) { - e->fd->tok = TOKfunction; + e->fd->tok = TOK::function_; e->fd->vthis = NULL; } @@ -2196,9 +2186,9 @@ public: FuncLiteralDeclaration *fld = e->var->isFuncLiteralDeclaration (); if (fld != NULL) { - if (fld->tok == TOKreserved) + if (fld->tok == TOK::reserved) { - fld->tok = TOKfunction; + fld->tok = TOK::function_; fld->vthis = NULL; } @@ -2210,7 +2200,7 @@ public: { /* Want the initializer, not the expression. */ VarDeclaration *var = e->var->isVarDeclaration (); - SymbolDeclaration *sd = e->var->isSymbolDeclaration (); + SymbolDeclaration *sdecl = e->var->isSymbolDeclaration (); tree init = NULL_TREE; if (var && (var->isConst () || var->isImmutable ()) @@ -2226,8 +2216,15 @@ public: var->inuse--; } } - else if (sd && sd->dsym) - init = layout_struct_initializer (sd->dsym); + else if (sdecl && sdecl->dsym) + { + if (StructDeclaration *sd = sdecl->dsym->isStructDeclaration ()) + init = layout_struct_initializer (sd); + else if (ClassDeclaration *cd = sdecl->dsym->isClassDeclaration ()) + init = layout_class_initializer (cd); + else + gcc_unreachable (); + } else error_at (make_location_t (e->loc), "non-constant expression %qs", e->toChars ()); @@ -2242,6 +2239,26 @@ public: tree result = get_decl_tree (e->var); TREE_USED (result) = 1; + /* The variable expression generated for `__traits(initSymbol)'. */ + if (SymbolDeclaration *sd = e->var->isSymbolDeclaration ()) + { + if (e->type->isTypeDArray ()) + { + /* Generate a slice for non-zero initialized aggregates, + otherwise create an empty array. */ + gcc_assert (e->type == Type::tvoid->arrayOf ()->constOf ()); + + tree type = build_ctype (e->type); + tree length = size_int (sd->dsym->structsize); + tree ptr = (sd->dsym->isStructDeclaration () + && sd->dsym->type->isZeroInit (e->loc)) + ? null_pointer_node : build_address (result); + + this->result_ = d_array_value (type, length, ptr); + return; + } + } + /* For variables that are references - currently only out/inout arguments; objects don't count - evaluating the variable means we want what it refers to. */ @@ -2954,7 +2971,7 @@ public: tree type = build_ctype (e->type); /* First handle array literal expressions. */ - if (e->e1->op == TOKarrayliteral) + if (e->e1->op == EXP::arrayLiteral) { ArrayLiteralExp *ale = e->e1->isArrayLiteralExp (); vec *elms = NULL; diff --git a/gcc/d/intrinsics.cc b/gcc/d/intrinsics.cc index b14b0ca5111..dec2bd47265 100644 --- a/gcc/d/intrinsics.cc +++ b/gcc/d/intrinsics.cc @@ -431,7 +431,7 @@ expand_intrinsic_rotate (intrinsic_code intrinsic, tree callexp) gcc_assert (ti && ti->tiargs && ti->tiargs->length == 2); Expression *e = isExpression ((*ti->tiargs)[0]); - gcc_assert (e && e->op == TOKint64); + gcc_assert (e && e->op == EXP::int64); count = build_expr (e, true); } diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt index d0a5e2f6859..893bc238631 100644 --- a/gcc/d/lang.opt +++ b/gcc/d/lang.opt @@ -380,10 +380,6 @@ fpreview=inclusiveincontracts D RejectNegative Implement 'in' contracts of overridden methods to be a superset of parent contract. -fpreview=intpromote -D RejectNegative -Use C-style integral promotion for unary '+', '-' and '~'. - fpreview=nosharedaccess D RejectNegative Disable access to shared memory objects. @@ -412,6 +408,10 @@ frevert=dtorfields D RejectNegative Don't destruct fields of partially constructed objects. +frevert=intpromote +D RejectNegative +Use C-style integral promotion for unary '+', '-' and '~'. + frevert=markdown D RejectNegative Disable Markdown replacements in Ddoc. diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def index fdff6db0626..3961a1d9bed 100644 --- a/gcc/d/runtime.def +++ b/gcc/d/runtime.def @@ -140,13 +140,6 @@ DEF_D_RUNTIME (ARRAYASSIGN_R, "_d_arrayassign_r", RT(ARRAY_VOID), DEF_D_RUNTIME (ARRAYSETASSIGN, "_d_arraysetassign", RT(VOIDPTR), P4(VOIDPTR, VOIDPTR, SIZE_T, CONST_TYPEINFO), 0) -/* Used for constructing a new array from an existing array. The `set' variant - is for when the constructor value is a single element. */ -DEF_D_RUNTIME (ARRAYCTOR, "_d_arrayctor", RT(ARRAY_VOID), - P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0) -DEF_D_RUNTIME (ARRAYSETCTOR, "_d_arraysetctor", RT(VOIDPTR), - P4(VOIDPTR, VOIDPTR, SIZE_T, CONST_TYPEINFO), 0) - /* Used for concatenating two or more arrays together. Then `n' variant is for when there is more than two arrays to handle. */ DEF_D_RUNTIME (ARRAYCATT, "_d_arraycatT", RT(ARRAY_BYTE), diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc index 55d63f89cb7..17b63ba8a7d 100644 --- a/gcc/d/toir.cc +++ b/gcc/d/toir.cc @@ -969,8 +969,7 @@ public: StructLiteralExp *sle = NULL; bool using_rvo_p = false; - if (DotVarExp *dve = (s->exp->op == TOKcall - && s->exp->isCallExp ()->e1->op == TOKdotvar + if (DotVarExp *dve = (s->exp->isCallExp () ? s->exp->isCallExp ()->e1->isDotVarExp () : NULL)) { diff --git a/gcc/d/types.cc b/gcc/d/types.cc index b39b92eb822..1d551e5249b 100644 --- a/gcc/d/types.cc +++ b/gcc/d/types.cc @@ -338,7 +338,7 @@ layout_aggregate_members (Dsymbols *members, tree context, bool inherited_p) RootObject *ro = (*td->objects)[j]; gcc_assert (ro->dyncast () == DYNCAST_EXPRESSION); Expression *e = (Expression *) ro; - gcc_assert (e->op == TOKdsymbol); + gcc_assert (e->op == EXP::dSymbol); DsymbolExp *se = e->isDsymbolExp (); tmembers.push (se->s);