aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/expr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/d/expr.cc')
-rw-r--r--gcc/d/expr.cc193
1 files changed, 90 insertions, 103 deletions
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index d055e0b..268a176 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1,5 +1,5 @@
/* expr.cc -- Lower D frontend expressions to GCC trees.
- Copyright (C) 2015-2024 Free Software Foundation, Inc.
+ Copyright (C) 2015-2025 Free Software Foundation, Inc.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -295,14 +295,14 @@ public:
this->result_ = d_convert (build_ctype (e->type),
build_boolop (code, t1, t2));
}
- else if (tb1->isfloating () && tb1->ty != TY::Tvector)
+ else if (tb1->isFloating () && tb1->ty != TY::Tvector)
{
/* For floating-point values, identity is defined as the bits in the
operands being identical. */
tree t1 = d_save_expr (build_expr (e->e1));
tree t2 = d_save_expr (build_expr (e->e2));
- if (!tb1->iscomplex ())
+ if (!tb1->isComplex ())
this->result_ = build_float_identity (code, t1, t2);
else
{
@@ -388,7 +388,7 @@ public:
e1.length == e2.length && memcmp(e1.ptr, e2.ptr, size) == 0;
Or when generating a NE expression:
e1.length != e2.length || memcmp(e1.ptr, e2.ptr, size) != 0; */
- if ((t1elem->isintegral () || t1elem->ty == TY::Tvoid
+ if ((t1elem->isIntegral () || t1elem->ty == TY::Tvoid
|| (t1elem->ty == TY::Tstruct
&& !t1elem->isTypeStruct ()->sym->xeq))
&& t1elem->ty == t2elem->ty)
@@ -414,7 +414,8 @@ public:
if (t1elem->ty != TY::Tstruct
|| identity_compare_p (t1elem->isTypeStruct ()->sym))
{
- tree size = size_mult_expr (t1len, size_int (t1elem->size ()));
+ tree size =
+ size_mult_expr (t1len, size_int (dmd::size (t1elem)));
result = build_memcmp_call (t1ptr, t2ptr, size);
result = build_boolop (code, result, integer_zero_node);
@@ -442,7 +443,7 @@ public:
The frontend should have already guaranteed that static arrays
have same size. */
if (tb1->ty == TY::Tsarray && tb2->ty == TY::Tsarray)
- gcc_assert (tb1->size () == tb2->size ());
+ gcc_assert (dmd::size (tb1) == dmd::size (tb2));
else
{
tree tlencmp = build_boolop (code, t1len, t2len);
@@ -620,8 +621,8 @@ public:
{
case EXP::add:
case EXP::min:
- if ((e->e1->type->isreal () && e->e2->type->isimaginary ())
- || (e->e1->type->isimaginary () && e->e2->type->isreal ()))
+ if ((e->e1->type->isReal () && e->e2->type->isImaginary ())
+ || (e->e1->type->isImaginary () && e->e2->type->isReal ()))
{
/* If the result is complex, then we can shortcut binary_op.
Frontend should have already validated types and sizes. */
@@ -631,7 +632,7 @@ public:
if (e->op == EXP::min)
t2 = build1 (NEGATE_EXPR, TREE_TYPE (t2), t2);
- if (e->e1->type->isreal ())
+ if (e->e1->type->isReal ())
this->result_ = complex_expr (build_ctype (e->type), t1, t2);
else
this->result_ = complex_expr (build_ctype (e->type), t2, t1);
@@ -661,12 +662,12 @@ public:
}
}
- code = e->e1->type->isintegral ()
+ code = e->e1->type->isIntegral ()
? TRUNC_DIV_EXPR : RDIV_EXPR;
break;
case EXP::mod:
- code = e->e1->type->isfloating ()
+ code = e->e1->type->isFloating ()
? FLOAT_MOD_EXPR : TRUNC_MOD_EXPR;
break;
@@ -750,12 +751,12 @@ public:
break;
case EXP::divAssign:
- code = e->e1->type->isintegral ()
+ code = e->e1->type->isIntegral ()
? TRUNC_DIV_EXPR : RDIV_EXPR;
break;
case EXP::modAssign:
- code = e->e1->type->isfloating ()
+ code = e->e1->type->isFloating ()
? FLOAT_MOD_EXPR : TRUNC_MOD_EXPR;
break;
@@ -917,7 +918,7 @@ public:
if (integer_zerop (t2))
{
tree size = size_mult_expr (d_array_length (t1),
- size_int (etype->size ()));
+ size_int (dmd::size (etype)));
result = build_memset_call (d_array_ptr (t1), size);
}
else
@@ -943,7 +944,8 @@ public:
tree t2ptr = d_array_ptr (t2);
/* Generate: memcpy(to, from, size) */
- tree size = size_mult_expr (t1len, size_int (etype->size ()));
+ tree size =
+ size_mult_expr (t1len, size_int (dmd::size (etype)));
tree result = build_memcpy_call (t1ptr, t2ptr, size);
/* Insert check that array lengths match and do not overlap. */
@@ -986,7 +988,7 @@ public:
{
/* Generate: _d_arraycopy() */
this->result_ = build_libcall (LIBCALL_ARRAYCOPY, e->type, 3,
- size_int (etype->size ()),
+ size_int (dmd::size (etype)),
d_array_convert (e->e2),
d_array_convert (e->e1));
}
@@ -1024,7 +1026,6 @@ public:
if (tb1->ty == TY::Tstruct)
{
tree t1 = build_expr (e->e1);
- tree t2 = convert_for_assignment (e->e2, e->e1->type, true);
StructDeclaration *sd = tb1->isTypeStruct ()->sym;
/* Look for struct = 0. */
@@ -1049,25 +1050,8 @@ public:
else
{
/* Simple struct literal assignment. */
- tree init = NULL_TREE;
-
- /* Fill any alignment holes in the struct using memset. */
- if ((e->op == EXP::construct
- || (e->e2->op == EXP::structLiteral && e->op == EXP::blit))
- && (sd->isUnionDeclaration () || !identity_compare_p (sd)))
- {
- t1 = stabilize_reference (t1);
- init = build_memset_call (t1);
- }
-
- /* Elide generating assignment if init is all zeroes. */
- if (init != NULL_TREE && initializer_zerop (t2))
- this->result_ = compound_expr (init, t1);
- else
- {
- tree result = build_assign (modifycode, t1, t2);
- this->result_ = compound_expr (init, result);
- }
+ tree t2 = convert_for_assignment (e->e2, e->e1->type, true);
+ this->result_ = build_assign (modifycode, t1, t2);
}
return;
@@ -1100,7 +1084,7 @@ public:
|| (e->op == EXP::construct && e->e2->op == EXP::arrayLiteral)
|| (e->op == EXP::construct && e->e2->op == EXP::call)
|| (e->op == EXP::construct && !lvalue && postblit)
- || (e->op == EXP::blit || e->e1->type->size () == 0))
+ || (e->op == EXP::blit || dmd::size (e->e1->type) == 0))
{
tree t1 = build_expr (e->e1);
tree t2 = convert_for_assignment (e->e2, e->e1->type);
@@ -1190,7 +1174,7 @@ public:
/* Index the associative array. */
tree result = build_libcall (libcall, dmd::pointerTo (e->type), 4,
ptr, tinfo,
- size_int (tb1->nextOf ()->size ()),
+ size_int (dmd::size (tb1->nextOf ())),
build_address (key));
if (!e->indexIsInBounds && array_bounds_check ())
@@ -1497,14 +1481,14 @@ public:
void visit (PtrExp *e) final override
{
Type *tnext = NULL;
- size_t offset;
+ dinteger_t offset;
tree result;
if (e->e1->op == EXP::add)
{
AddExp *ae = e->e1->isAddExp ();
if (ae->e1->op == EXP::address
- && ae->e2->isConst () && ae->e2->type->isintegral ())
+ && ae->e2->isConst () && ae->e2->type->isIntegral ())
{
Expression *ex = ae->e1->isAddrExp ()->e1;
tnext = ex->type->toBasetype ();
@@ -1620,7 +1604,7 @@ public:
if (dve->e1->op == EXP::structLiteral)
{
StructLiteralExp *sle = dve->e1->isStructLiteralExp ();
- sle->useStaticInit = false;
+ sle->useStaticInit (false);
}
FuncDeclaration *fd = dve->var->isFuncDeclaration ();
@@ -1752,7 +1736,7 @@ public:
if (returnvalue != NULL_TREE)
exp = compound_expr (exp, returnvalue);
- if (tf->isref ())
+ if (tf->isRef ())
exp = build_deref (exp);
/* Some library calls are defined to return a generic type.
@@ -1781,7 +1765,7 @@ public:
void visit (DelegateExp *e) final override
{
- if (e->func->semanticRun == PASS::semantic3done)
+ if (e->func->semanticRun () == PASS::semantic3done)
{
/* Add the function as nested function if it belongs to this module.
ie: it is a member of this module, or it is a template instance. */
@@ -2072,7 +2056,7 @@ public:
void visit (SymOffExp *e) final override
{
/* Build the address and offset of the symbol. */
- size_t soffset = e->isSymOffExp ()->offset;
+ dinteger_t soffset = e->isSymOffExp ()->offset;
tree result = get_decl_tree (e->var);
TREE_USED (result) = 1;
@@ -2178,7 +2162,7 @@ public:
tree type = build_ctype (e->type);
tree length = size_int (sd->dsym->structsize);
tree ptr = (sd->dsym->isStructDeclaration ()
- && sd->dsym->type->isZeroInit (e->loc))
+ && dmd::isZeroInit (sd->dsym->type, e->loc))
? null_pointer_node : build_address (result);
this->result_ = d_array_value (type, length, ptr);
@@ -2241,18 +2225,24 @@ public:
storage class, then the instance is allocated on the stack
rather than the heap or using the class specific allocator. */
tree var = build_local_temp (TREE_TYPE (type));
+ SET_DECL_ALIGN (var, cd->alignsize * BITS_PER_UNIT);
+ DECL_USER_ALIGN (var) = 1;
new_call = build_nop (type, build_address (var));
setup_exp = modify_expr (var, aggregate_initializer_decl (cd));
}
- else if (global.params.ehnogc && e->thrownew)
+ else if (e->placement != NULL)
{
- /* Allocating a `@nogc' Exception with `_d_newThrowable' has already
- been handled by the front-end. */
- gcc_unreachable ();
+ /* Generate: placement_expr = typeid(class).init */
+ tree placement_expr = build_expr (e->placement);
+ new_call = build_nop (type, build_address (placement_expr));
+ tree class_init = build_vconvert (TREE_TYPE (placement_expr),
+ aggregate_initializer_decl (cd));
+ setup_exp = modify_expr (placement_expr, class_init);
}
else
{
- /* Generate: _d_newclass() */
+ /* Generate: _d_newclass()
+ or: _d_newThrowable() */
new_call = build_expr (e->lowering);
}
@@ -2321,12 +2311,22 @@ public:
return;
}
- /* This case should have been rewritten to `_d_newitemT' during the
- semantic phase. */
- gcc_assert (e->lowering);
+ if (e->placement != NULL)
+ {
+ /* Generate: &placement_expr */
+ tree placement_expr = build_expr (e->placement);
+ new_call = build_nop (build_ctype (tb),
+ build_address (placement_expr));
+ }
+ else
+ {
+ /* This case should have been rewritten to `_d_newitemT' during the
+ semantic phase. */
+ gcc_assert (e->lowering);
- /* Generate: _d_newitemT() */
- new_call = build_expr (e->lowering);
+ /* Generate: _d_newitemT() */
+ new_call = build_expr (e->lowering);
+ }
if (e->member || !e->arguments)
{
@@ -2391,7 +2391,7 @@ public:
/* Allocating memory for a new pointer. */
TypePointer *tpointer = tb->isTypePointer ();
- if (tpointer->next->size () == 0)
+ if (dmd::size (tpointer->next) == 0)
{
/* Pointer element size is unknown. */
this->result_ = d_convert (build_ctype (e->type),
@@ -2399,12 +2399,22 @@ public:
return;
}
- /* This case should have been rewritten to `_d_newitemT' during the
- semantic phase. */
- gcc_assert (e->lowering);
+ if (e->placement != NULL)
+ {
+ /* Generate: &placement_expr */
+ tree placement_expr = build_expr (e->placement);
+ result = build_nop (build_ctype (tb),
+ build_address (placement_expr));
+ }
+ else
+ {
+ /* This case should have been rewritten to `_d_newitemT' during the
+ semantic phase. */
+ gcc_assert (e->lowering);
- /* Generate: _d_newitemT() */
- result = build_expr (e->lowering);
+ /* Generate: _d_newitemT() */
+ result = build_expr (e->lowering);
+ }
if (e->arguments && e->arguments->length == 1)
{
@@ -2429,7 +2439,7 @@ public:
CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (aatype), mem);
result = build_nop (build_ctype (e->type),
- build_constructor (aatype, ce));
+ build_padded_constructor (aatype, ce));
}
else
gcc_unreachable ();
@@ -2502,7 +2512,7 @@ public:
CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
}
- tree ctor = build_constructor (type, elms);
+ tree ctor = build_padded_constructor (type, elms);
TREE_CONSTANT (ctor) = 1;
this->result_ = ctor;
return;
@@ -2584,8 +2594,10 @@ public:
this->result_ = d_array_value (build_ctype (e->type),
size_int (0), null_pointer_node);
else
- this->result_ = build_constructor (make_array_type (tb->nextOf (), 0),
- NULL);
+ {
+ tree arrtype = make_array_type (tb->nextOf (), 0);
+ this->result_ = build_padded_constructor (arrtype, NULL);
+ }
return;
}
@@ -2626,7 +2638,7 @@ public:
/* Now return the constructor as the correct type. For static arrays there
is nothing else to do. For dynamic arrays, return a two field struct.
For pointers, return the address. */
- tree ctor = build_constructor (satype, elms);
+ tree ctor = build_padded_constructor (satype, elms);
tree type = build_ctype (e->type);
/* Nothing else to do for static arrays. */
@@ -2655,22 +2667,6 @@ public:
if (constant_p && initializer_constant_valid_p (ctor, TREE_TYPE (ctor)))
TREE_STATIC (ctor) = 1;
- /* Use memset to fill any alignment holes in the array. */
- if (!this->constp_ && !this->literalp_)
- {
- TypeStruct *ts = etype->baseElemOf ()->isTypeStruct ();
-
- if (ts != NULL && (!identity_compare_p (ts->sym)
- || ts->sym->isUnionDeclaration ()))
- {
- tree var = build_local_temp (TREE_TYPE (ctor));
- tree init = build_memset_call (var);
- /* Evaluate memset() first, then any saved elements. */
- saved_elems = compound_expr (init, saved_elems);
- ctor = compound_expr (modify_expr (var, ctor), var);
- }
- }
-
this->result_ = compound_expr (saved_elems, d_convert (type, ctor));
}
else if (e->onstack)
@@ -2692,10 +2688,13 @@ public:
/* Now copy the constructor into memory. */
tree size = size_mult_expr (size_int (e->elements->length),
- size_int (tb->nextOf ()->size ()));
+ size_int (dmd::size (tb->nextOf ())));
tree result = build_memcpy_call (mem, build_address (ctor), size);
+ /* Fill any alignment holes in the array. */
+ result = compound_expr (result, build_clear_padding_call (mem));
+
/* Return the array pointed to by MEM. */
result = compound_expr (result, mem);
@@ -2727,7 +2726,7 @@ public:
TypeAArray *ta = tb->isTypeAArray ();
if (e->keys->length == 0)
{
- this->result_ = build_constructor (build_ctype (ta), NULL);
+ this->result_ = build_padded_constructor (build_ctype (ta), NULL);
return;
}
@@ -2759,7 +2758,7 @@ public:
CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (aatype), mem);
tree result = build_nop (build_ctype (e->type),
- build_constructor (aatype, ce));
+ build_padded_constructor (aatype, ce));
this->result_ = compound_expr (init, result);
}
@@ -2770,13 +2769,13 @@ public:
/* Handle empty struct literals. */
if (e->elements == NULL || e->sd->fields.length == 0)
{
- this->result_ = build_constructor (build_ctype (e->type), NULL);
+ this->result_ = build_padded_constructor (build_ctype (e->type), NULL);
return;
}
/* Building sinit trees are delayed until after frontend semantic
processing has complete. Build the static initializer now. */
- if (e->useStaticInit && !this->constp_ && !e->sd->isCsymbol ())
+ if (e->useStaticInit () && !this->constp_ && !e->sd->isCsymbol ())
{
tree init = aggregate_initializer_decl (e->sd);
@@ -2821,7 +2820,7 @@ public:
elem = d_save_expr (elem);
if (initializer_zerop (elem))
- value = build_constructor (build_ctype (ftype), NULL);
+ value = build_padded_constructor (build_ctype (ftype), NULL);
else
value = build_array_from_val (ftype, elem);
}
@@ -2844,7 +2843,7 @@ public:
tree field = get_symbol_decl (e->sd->vthis);
tree value = build_vthis (e->sd);
CONSTRUCTOR_APPEND_ELT (ve, field, value);
- gcc_assert (e->useStaticInit == false);
+ gcc_assert (e->useStaticInit () == false);
}
/* Build a constructor in the correct shape of the aggregate type. */
@@ -2869,18 +2868,6 @@ public:
tree var = build_deref (e->sym);
ctor = compound_expr (modify_expr (var, ctor), var);
}
- else if (!this->literalp_)
- {
- /* Use memset to fill any alignment holes in the object. */
- if (!identity_compare_p (e->sd) || e->sd->isUnionDeclaration ())
- {
- tree var = build_local_temp (TREE_TYPE (ctor));
- tree init = build_memset_call (var);
- /* Evaluate memset() first, then any saved element constructors. */
- saved_elems = compound_expr (init, saved_elems);
- ctor = compound_expr (modify_expr (var, ctor), var);
- }
- }
this->result_ = compound_expr (saved_elems, ctor);
}
@@ -2920,7 +2907,7 @@ public:
if (constant_p)
this->result_ = build_vector_from_ctor (type, elms);
else
- this->result_ = build_constructor (type, elms);
+ this->result_ = build_padded_constructor (type, elms);
}
else if (e->e1->type->toBasetype ()->ty == TY::Tsarray)
{
@@ -3060,7 +3047,7 @@ build_return_dtor (Expression *e, Type *type, TypeFunction *tf)
tree result = build_expr (e);
/* Convert for initializing the DECL_RESULT. */
- if (tf->isref ())
+ if (tf->isRef ())
{
/* If we are returning a reference, take the address. */
result = convert_expr (result, e->type, type);