1 /* GDC -- D front-end for GCC
2 Copyright (C) 2004 David Friedman
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "d-gcc-includes.h"
26 #include "d-codegen.h"
30 convert (tree type
, tree expr
)
32 Type
* target_type
= g
.irs
->getDType(type
);
33 Type
* expr_type
= g
.irs
->getDType(TREE_TYPE(expr
));
34 if (target_type
&& expr_type
)
35 return g
.irs
->convertTo(expr
, expr_type
, target_type
);
37 return d_convert_basic(type
, expr
);
41 CondExp::toElem(IRState
* irs
)
43 tree cn
= irs
->convertForCondition( econd
);
44 tree t1
= e1
->toElem( irs
);
45 tree t2
= e2
->toElem( irs
);
46 return build(COND_EXPR
, type
->toCtype(), cn
, t1
, t2
);
50 signed_compare_check(tree
* e1
, tree
* e2
)
52 tree t1
= TREE_TYPE( *e1
);
53 tree t2
= TREE_TYPE( *e2
);
54 if (INTEGRAL_TYPE_P( t1
) &&
55 INTEGRAL_TYPE_P( t2
)) {
56 int u1
= TREE_UNSIGNED( t1
);
57 int u2
= TREE_UNSIGNED( t2
);
60 if (gen
.warnSignCompare
) {
61 d_warning (0, "unsigned comparison with signed operand");
64 * e1
= convert( d_unsigned_type( t1
), * e1
);
66 * e2
= convert( d_unsigned_type( t2
), * e2
);
72 make_bool_binop(TOK op
, tree e1
, tree e2
, IRState
* irs
)
74 bool is_compare
= false; // %% should this be true for unordered comparisons?
78 case TOKidentity
: // fall through
83 case TOKnotidentity
: // fall through
89 out_code
= TRUTH_ANDIF_EXPR
;
92 out_code
= TRUTH_ORIF_EXPR
;
96 // ordering for complex isn't defined, all that is guaranteed is the 'unordered part'
102 if ( COMPLEX_FLOAT_TYPE_P( TREE_TYPE( e1
)) ) {
103 // GCC doesn't handle these.
104 e1
= irs
->maybeMakeTemp(e1
);
105 e2
= irs
->maybeMakeTemp(e2
);
108 return irs
->boolOp(TRUTH_ANDIF_EXPR
,
109 make_bool_binop(TOKleg
, irs
->realPart(e1
), irs
->realPart(e2
), irs
),
110 make_bool_binop(TOKleg
, irs
->imagPart(e1
), irs
->imagPart(e2
), irs
));
112 return irs
->boolOp(TRUTH_ORIF_EXPR
,
113 make_bool_binop(TOKunord
, irs
->realPart(e1
), irs
->realPart(e2
), irs
),
114 make_bool_binop(TOKunord
, irs
->imagPart(e1
), irs
->imagPart(e2
), irs
));
116 return irs
->boolOp(TRUTH_ANDIF_EXPR
,
117 make_bool_binop(TOKleg
, e1
, e2
, irs
),
118 make_bool_binop(TOKnotequal
, e1
, e2
, irs
));
120 return irs
->boolOp(TRUTH_ORIF_EXPR
,
121 make_bool_binop(TOKunord
, e1
, e2
, irs
),
122 make_bool_binop(TOKequal
, e1
, e2
, irs
));
125 // From cmath2.d: if imaginary parts are equal,
126 // result is comparison of real parts; otherwise, result false
128 // Does D define an ordering for complex numbers?
130 // make a target-independent _cmplxCmp ?
133 bool unordered
= false;
167 it
= make_bool_binop(hard
, irs
->imagPart(e2
), irs
->imagPart(e1
), irs
);
169 it
= irs
->boolOp(TRUTH_ANDIF_EXPR
,
170 make_bool_binop(TOKleg
, irs
->realPart(e2
), irs
->realPart(e1
), irs
),
172 rt
= irs
->boolOp(TRUTH_ANDIF_EXPR
,
173 make_bool_binop(TOKequal
, irs
->imagPart(e2
), irs
->imagPart(e1
), irs
),
174 make_bool_binop(soft
, irs
->realPart(e2
), irs
->realPart(e1
), irs
));
175 it
= irs
->boolOp(TRUTH_ANDIF_EXPR
, it
, rt
);
177 it
= irs
->boolOp(TRUTH_ORIF_EXPR
,
178 make_bool_binop(TOKunord
, e1
, e2
, irs
),
187 case TOKlt
: out_code
= LT_EXPR
; is_compare
= true; break;
188 case TOKgt
: out_code
= GT_EXPR
; is_compare
= true; break;
189 case TOKle
: out_code
= LE_EXPR
; is_compare
= true; break;
190 case TOKge
: out_code
= GE_EXPR
; is_compare
= true; break;
191 case TOKunord
: out_code
= UNORDERED_EXPR
; break;
194 e1
= irs
->maybeMakeTemp(e1
);
195 e2
= irs
->maybeMakeTemp(e2
);
196 return irs
->boolOp(TRUTH_ORIF_EXPR
,
197 build(LT_EXPR
, boolean_type_node
, e1
, e2
),
198 build(GT_EXPR
, boolean_type_node
, e1
, e2
));
202 /* GCC 3.4 (others?) chokes on these unless
203 at least one operand is floating point. */
204 if (FLOAT_TYPE_P( TREE_TYPE( e1
)) &&
205 FLOAT_TYPE_P( TREE_TYPE( e2
))) {
207 case TOKleg
: out_code
= ORDERED_EXPR
; break;
208 case TOKule
: out_code
= UNLE_EXPR
; break;
209 case TOKul
: out_code
= UNLT_EXPR
; break;
210 case TOKuge
: out_code
= UNGE_EXPR
; break;
211 case TOKug
: out_code
= UNGT_EXPR
; break;
212 case TOKue
: out_code
= UNEQ_EXPR
; break;
219 // %% is this properly optimized away?
220 return irs
->voidCompound(irs
->compound(e1
,e2
),
221 convert(boolean_type_node
, integer_one_node
));
223 case TOKule
: out_code
= LE_EXPR
; break;
224 case TOKul
: out_code
= LT_EXPR
; break;
225 case TOKuge
: out_code
= GE_EXPR
; break;
226 case TOKug
: out_code
= GT_EXPR
; break;
227 case TOKue
: out_code
= EQ_EXPR
; break;
236 signed_compare_check(& e1
, & e2
);
238 tree t
= build(out_code
, boolean_type_node
, // exp->type->toCtype(),
241 /* Need to use fold(). Otherwise, complex-var == complex-cst is not
242 gimplified correctly. */
244 if (COMPLEX_FLOAT_TYPE_P( TREE_TYPE( e1
)) ||
245 COMPLEX_FLOAT_TYPE_P( TREE_TYPE( e2
)))
252 make_bool_binop(BinExp
* exp
, IRState
* irs
)
254 tree t1
= exp
->e1
->toElem(irs
);
255 tree t2
= exp
->e2
->toElem(irs
);
256 if (exp
->op
== TOKandand
|| exp
->op
== TOKoror
) {
257 t1
= irs
->convertForCondition(t1
, exp
->e1
->type
);
258 t2
= irs
->convertForCondition(t2
, exp
->e2
->type
);
260 tree t
= make_bool_binop(exp
->op
, t1
, t2
, irs
);
261 return convert(exp
->type
->toCtype(), t
);
265 IdentityExp::toElem(IRState
* irs
)
267 TY ty1
= e1
->type
->toBasetype()->ty
;
269 // Assuming types are the same from typeCombine
270 //if (ty1 != e2->type->toBasetype()->ty)
275 return build(op
== TOKidentity
? EQ_EXPR
: NE_EXPR
,
277 irs
->addressOf(e1
->toElem(irs
)),
278 irs
->addressOf(e2
->toElem(irs
)));
282 return make_bool_binop(this, irs
);
284 // For operand types other than class objects, static or dynamic
285 // arrays, identity is defined as being the same as equality
287 // Assumes object == object has been changed to function call
288 // ... impl is really the same as the special cales
289 return make_bool_binop(this, irs
);
294 EqualExp::toElem(IRState
* irs
)
296 Type
* base_type_1
= e1
->type
->toBasetype();
297 TY base_ty_1
= base_type_1
->ty
;
298 TY base_ty_2
= e2
->type
->toBasetype()->ty
;
300 if ( (base_ty_1
== Tsarray
|| base_ty_1
== Tarray
||
301 base_ty_2
== Tsarray
|| base_ty_2
== Tarray
) ) {
303 Type
* elem_type
= base_type_1
->nextOf()->toBasetype();
305 // _adCmp compares each element. If bitwise comparison is ok,
308 if (elem_type
->isfloating() || elem_type
->isClassHandle() ||
309 elem_type
->ty
== Tsarray
|| elem_type
->ty
== Tarray
||
310 elem_type
->ty
== Tstruct
)
315 irs
->typeinfoReference(elem_type
) };
316 tree result
= irs
->libCall(LIBCALL_ADEQ
, 3, args
);
317 result
= convert(type
->toCtype(), result
);
318 if (op
== TOKnotequal
)
319 result
= build1(TRUTH_NOT_EXPR
, type
->toCtype(), result
);
321 } else if (base_ty_1
== Tsarray
&& base_ty_2
== Tsarray
) {
322 // assuming sizes are equal
323 // shouldn't need to check for Tbit
324 return make_bool_binop(this, irs
);
329 gcc_assert(elem_type
->ty
!= Tbit
);
331 for (int i
= 0; i
< 2; i
++) {
332 Expression
* e
= i
== 0 ? e1
: e2
;
333 TY e_base_ty
= i
== 0 ? base_ty_1
: base_ty_2
;
335 if ( e_base_ty
== Tarray
) {
336 tree array_expr
= irs
->maybeMakeTemp( e
->toElem(irs
) );
338 data_expr
[i
] = irs
->darrayPtrRef( array_expr
);
339 len_expr
[i
] = irs
->darrayLenRef( array_expr
); // may be used twice -- should be okay
341 data_expr
[i
] = irs
->addressOf( e
->toElem(irs
) );
342 len_expr
[i
] = ((TypeSArray
*) e
->type
->toBasetype())->dim
->toElem(irs
);
346 tree t_memcmp
= built_in_decls
[BUILT_IN_MEMCMP
];
350 size
= build(MULT_EXPR
, size_type_node
,
351 convert(size_type_node
, len_expr
[0]), // should be size_type already, though
352 size_int(elem_type
->size()));
355 result
= irs
->buildCall( TREE_TYPE(TREE_TYPE( t_memcmp
)),
356 irs
->addressOf( t_memcmp
),
357 tree_cons( NULL_TREE
, data_expr
[0],
358 tree_cons( NULL_TREE
, data_expr
[1],
359 tree_cons( NULL_TREE
, size
, NULL_TREE
))));
361 result
= irs
->boolOp(op
== TOKequal
? TRUTH_ANDIF_EXPR
: TRUTH_ORIF_EXPR
,
362 irs
->boolOp(op
== TOKequal
? EQ_EXPR
: NE_EXPR
, len_expr
[0], len_expr
[1]),
363 irs
->boolOp(op
== TOKequal
? EQ_EXPR
: NE_EXPR
, result
, integer_zero_node
));
365 return convert(type
->toCtype(), result
);
368 // Taarray case not defined in spec, probably should be a library call
369 return make_bool_binop(this, irs
);
374 InExp::toElem(IRState
* irs
)
376 Type
* e2_base_type
= e2
->type
->toBasetype();
378 assert( e2_base_type
->ty
== Taarray
);
381 Type
* key_type
= ((TypeAArray
*) e2_base_type
)->index
->toBasetype();
382 args
[0] = e2
->toElem(irs
);
383 args
[1] = irs
->typeinfoReference(key_type
);
384 args
[2] = aoe
.set(irs
, irs
->convertTo( e1
, key_type
) );
385 return d_convert_basic(type
->toCtype(),
386 aoe
.finish(irs
, irs
->libCall(LIBCALL_AAINP
, 3, args
) ));
390 CmpExp::toElem(IRState
* irs
)
392 Type
* base_type_1
= e1
->type
->toBasetype();
393 TY base_ty_1
= base_type_1
->ty
;
394 TY base_ty_2
= e2
->type
->toBasetype()->ty
;
396 if ( (base_ty_1
== Tsarray
|| base_ty_1
== Tarray
||
397 base_ty_2
== Tsarray
|| base_ty_2
== Tarray
) ) {
399 Type
* elem_type
= base_type_1
->nextOf()->toBasetype();
404 args
[0] = irs
->toDArray(e1
);
405 args
[1] = irs
->toDArray(e2
);
407 switch (elem_type
->ty
) {
409 lib_call
= LIBCALL_ADCMPCHAR
;
412 gcc_assert(elem_type
->ty
!= Tbit
);
414 // Tuns8, Tchar, Tbool
415 if (elem_type
->size() == 1 && elem_type
->isscalar() &&
416 elem_type
->isunsigned())
417 lib_call
= LIBCALL_ADCMPCHAR
;
420 args
[2] = irs
->typeinfoReference(elem_type
);
422 lib_call
= LIBCALL_ADCMP
;
427 tree result
= irs
->libCall(lib_call
, n_args
, args
);
428 enum tree_code out_code
;
430 // %% For float element types, warn that NaN is not taken into account ?
433 case TOKlt
: out_code
= LT_EXPR
; break;
434 case TOKgt
: out_code
= GT_EXPR
; break;
435 case TOKle
: out_code
= LE_EXPR
; break;
436 case TOKge
: out_code
= GE_EXPR
; break;
438 case TOKlg
: out_code
= NE_EXPR
; break;
441 // %% Could do a check for side effects and drop the unused condition
442 return build(COMPOUND_EXPR
, boolean_type_node
,
444 d_truthvalue_conversion( this->op
== TOKunord
? integer_zero_node
: integer_one_node
));
445 case TOKule
: out_code
= LE_EXPR
; break;
446 case TOKul
: out_code
= LT_EXPR
; break;
447 case TOKuge
: out_code
= GE_EXPR
; break;
448 case TOKug
: out_code
= GT_EXPR
; break;
449 case TOKue
: out_code
= EQ_EXPR
; break;
456 result
= build(out_code
, boolean_type_node
, result
, integer_zero_node
);
457 return convert(type
->toCtype(), result
);
459 return make_bool_binop(this, irs
);
464 make_math_op(TOK op
, tree e1
, Type
* e1_type
, tree e2
, Type
* e2_type
, Type
* exp_type
, IRState
* irs
)
466 // Integral promotions have already been done in the front end
469 // %% faster: check if result is complex
470 if (( ( e1_type
->isreal() && e2_type
->isimaginary() ) ||
471 ( e1_type
->isimaginary() && e2_type
->isreal() )) &&
472 (op
== TOKadd
|| op
== TOKmin
)) {
473 // %%TODO: need to check size/modes
480 e2_adj
= build1(NEGATE_EXPR
, TREE_TYPE(e2
), e2
);
483 if (e1_type
->isreal()) {
491 return build(COMPLEX_EXPR
, exp_type
->toCtype(), e_real
, e_imag
);
495 case TOKadd
: out_code
= PLUS_EXPR
; break;
496 case TOKmin
: out_code
= MINUS_EXPR
; break;
497 case TOKmul
: out_code
= MULT_EXPR
; break;
498 case TOKxor
: out_code
= BIT_XOR_EXPR
; break;
499 case TOKor
: out_code
= BIT_IOR_EXPR
; break;
500 case TOKand
: out_code
= BIT_AND_EXPR
; break;
501 case TOKshl
: out_code
= LSHIFT_EXPR
; break;
502 case TOKushr
: // drop through
503 case TOKshr
: out_code
= RSHIFT_EXPR
; break;
505 if (e1_type
->isintegral())
506 out_code
= TRUNC_MOD_EXPR
;
508 return irs
->floatMod(e1
, e2
, e1_type
);
512 if (e1_type
->isintegral())
513 out_code
= TRUNC_DIV_EXPR
;
515 out_code
= RDIV_EXPR
;
523 bool is_unsigned
= e1_type
->isunsigned() || e2_type
->isunsigned()
525 if (exp_type
->isintegral() &&
526 ( exp_type
->isunsigned() != 0 ) != is_unsigned
) {
527 tree e_new_type_1
= is_unsigned
?
528 d_unsigned_type(exp_type
->toCtype()) :
529 d_signed_type(exp_type
->toCtype());
530 tree t
= build(out_code
, e_new_type_1
, e1
, e2
);
531 return convert(exp_type
->toCtype(), t
);
533 /* Front-end does not do this conversion and GCC does not
534 always do it right. */
535 tree_code tc1
= TREE_CODE(TREE_TYPE(e1
));
536 tree_code tc2
= TREE_CODE(TREE_TYPE(e2
));
537 if (tc1
== COMPLEX_TYPE
&& tc2
!= COMPLEX_TYPE
)
538 e2
= irs
->convertTo(e2
, e2_type
, e1_type
);
539 else if (tc2
== COMPLEX_TYPE
&& tc1
!= COMPLEX_TYPE
)
540 e1
= irs
->convertTo(e1
, e1_type
, e2_type
);
542 return build(out_code
, exp_type
->toCtype(), e1
, e2
);
547 make_math_op(BinExp
* exp
, IRState
* irs
)
549 return make_math_op(exp
->op
,
550 exp
->e1
->toElem(irs
), exp
->e1
->type
,
551 exp
->e2
->toElem(irs
), exp
->e2
->type
,
557 AndAndExp::toElem(IRState
* irs
)
559 if (e2
->type
->toBasetype()->ty
!= Tvoid
)
560 return make_bool_binop(this, irs
);
562 return build(COND_EXPR
, type
->toCtype(),
563 e1
->toElem(irs
), e2
->toElem(irs
), d_void_zero_node
);
567 OrOrExp::toElem(IRState
* irs
)
569 if (e2
->type
->toBasetype()->ty
!= Tvoid
)
570 return make_bool_binop(this, irs
);
572 return build(COND_EXPR
, type
->toCtype(),
573 build1(TRUTH_NOT_EXPR
, boolean_type_node
, e1
->toElem(irs
)),
574 e2
->toElem(irs
), d_void_zero_node
);
578 XorExp::toElem(IRState
* irs
) { return make_math_op(this, irs
); }
580 OrExp::toElem(IRState
* irs
) { return make_math_op(this, irs
); }
582 AndExp::toElem(IRState
* irs
) { return make_math_op(this, irs
); }
584 UshrExp::toElem(IRState
* irs
) { return make_math_op(this, irs
); }
586 ShrExp::toElem(IRState
* irs
) { return make_math_op(this, irs
); }
588 ShlExp::toElem(IRState
* irs
) { return make_math_op(this, irs
); }
591 ModExp::toElem(IRState
* irs
)
593 return make_math_op(this, irs
);
596 DivExp::toElem(IRState
* irs
)
598 return make_math_op(this, irs
);
601 MulExp::toElem(IRState
* irs
)
603 return make_math_op(this, irs
);
607 one_elem_array(IRState
* irs
, Expression
* value
, tree
& var_decl_out
)
609 tree v
= irs
->maybeExprVar(value
->toElem(irs
), & var_decl_out
);
610 return irs
->darrayVal(value
->type
->arrayOf(), 1, irs
->addressOf(v
));
614 CatExp::toElem(IRState
* irs
)
618 // One of the operands may be an element instead of an array.
619 // Logic copied from CatExp::semantic
621 Type
* tb1
= e1
->type
->toBasetype();
622 Type
* tb2
= e2
->type
->toBasetype();
624 if ((tb1
->ty
== Tsarray
|| tb1
->ty
== Tarray
) &&
625 irs
->typesCompatible(e2
->type
, tb1
->nextOf()))
627 elem_type
= tb1
->nextOf();
628 else if ((tb2
->ty
== Tsarray
|| tb2
->ty
== Tarray
) &&
629 irs
->typesCompatible(e1
->type
, tb2
->nextOf()))
631 elem_type
= tb2
->nextOf();
633 elem_type
= tb1
->nextOf();
636 // Flatten multiple concatenations
638 unsigned n_operands
= 2;
646 while (e
->op
== TOKcat
) {
647 e
= ((CatExp
*) e
)->e1
;
652 n_args
= 1 + (n_operands
> 2 ? 1 : 0) +
653 (n_operands
* (irs
->splitDynArrayVarArgs
? 2 : 1));
654 args
= new tree
[n_args
];
655 args
[0] = irs
->typeinfoReference(type
);
657 args
[1] = irs
->integerConstant(n_operands
, Type::tuns32
);
659 unsigned ai
= n_args
- 1;
663 Expression
*oe
= ce
->e2
;
667 if (irs
->typesCompatible(oe
->type
->toBasetype(), elem_type
))
669 tree elem_var
= NULL_TREE
;
670 array_exp
= one_elem_array(irs
, oe
, elem_var
);
672 elem_vars
.push(elem_var
);
675 array_exp
= irs
->toDArray(oe
);
676 if (irs
->splitDynArrayVarArgs
)
678 array_exp
= irs
->maybeMakeTemp(array_exp
);
679 args
[ai
--] = irs
->darrayPtrRef(array_exp
); // note: filling array
680 args
[ai
--] = irs
->darrayLenRef(array_exp
); // backwards, so ptr 1st
683 args
[ai
--] = array_exp
;
686 if (ce
->e1
->op
!= TOKcat
) {
689 // finish with atomtic lhs
691 ce
= (CatExp
*) ce
->e1
;
692 break; // continue with lhs CatExp
700 result
= irs
->libCall(n_operands
> 2 ? LIBCALL_ARRAYCATNT
: LIBCALL_ARRAYCATT
,
701 n_args
, args
, type
->toCtype());
703 for (unsigned i
= 0; i
< elem_vars
.dim
; ++i
)
705 tree elem_var
= (tree
) elem_vars
.data
[i
];
706 result
= irs
->binding(elem_var
, result
);
713 MinExp::toElem(IRState
* irs
)
715 // The front end has already taken care of pointer-int and pointer-pointer
716 return make_math_op(this, irs
);
720 AddExp::toElem(IRState
* irs
)
722 TY ty1
= e1
->type
->toBasetype()->ty
;
723 TY ty2
= e2
->type
->toBasetype()->ty
;
725 if ((ty1
== Tarray
|| ty1
== Tsarray
) &&
726 (ty2
== Tarray
|| ty2
== Tsarray
) ) {
727 error("Array operations not implemented");
728 return irs
->errorMark(type
);
730 // The front end has already taken care of (pointer + integer)
731 return make_math_op(this, irs
);
734 tree
chain_cvt(tree t
, Type
* typ
, Array
& casts
, IRState
* irs
)
736 for (int i
= casts
.dim
- 1; i
>= 0; i
--) {
737 t
= irs
->convertTo(t
, typ
, (Type
*) casts
.data
[i
]);
738 typ
= (Type
*) casts
.data
[i
];
743 tree
make_assign_math_op(BinExp
* exp
, IRState
* irs
)
745 Expression
* e1_to_use
;
749 Array lhs_casts
; // no more than two casts?
752 case TOKaddass
: out_code
= TOKadd
; break;
753 case TOKminass
: out_code
= TOKmin
; break;
754 case TOKmulass
: out_code
= TOKmul
; break;
755 case TOKxorass
: out_code
= TOKxor
; break;
756 case TOKorass
: out_code
= TOKor
; break;
757 case TOKandass
: out_code
= TOKand
; break;
758 case TOKshlass
: out_code
= TOKshl
; break;
759 case TOKushrass
: out_code
= TOKushr
; break;
760 case TOKshrass
: out_code
= TOKshr
; break;
761 case TOKmodass
: out_code
= TOKmod
; break;
762 case TOKdivass
: out_code
= TOKdiv
; break;
768 lhs_type
= e1_to_use
->type
;
769 while (e1_to_use
->op
== TOKcast
) {
770 CastExp
* cast_exp
= (CastExp
*) e1_to_use
;
771 assert(irs
->typesCompatible(cast_exp
->type
, cast_exp
->to
)); // %% check, basetype?
772 lhs_casts
.push(cast_exp
->to
);
773 e1_to_use
= cast_exp
->e1
;
776 tree tgt
= stabilize_reference( irs
->toElemLvalue(e1_to_use
) );
777 tree lhs
= chain_cvt(tgt
, e1_to_use
->type
, lhs_casts
, irs
);
779 Type
* src_type
= lhs_type
;
782 /* Determine the correct combined type from BinExp::typeCombine. */
783 TY ty
= (TY
) Type::impcnvResult
[lhs_type
->toBasetype()->ty
][exp
->e2
->type
->toBasetype()->ty
];
785 src_type
= Type::basic
[ty
];
787 if ((out_code
== TOKmul
|| out_code
== TOKdiv
) && exp
->e1
->type
->isimaginary())
789 assert( exp
->e2
->type
->isfloating() );
790 if ( ! exp
->e2
->type
->isimaginary() && ! exp
->e2
->type
->iscomplex() )
792 assert( exp
->e1
->type
->size() == exp
->e2
->type
->size() );
793 src_type
= exp
->e1
->type
;
796 tree src
= make_math_op(out_code
, lhs
, lhs_type
,
797 exp
->e2
->toElem(irs
), exp
->e2
->type
,
799 result
= build(MODIFY_EXPR
, exp
->type
->toCtype(),
800 tgt
, irs
->convertForAssignment(src
, src_type
, e1_to_use
->type
));
806 XorAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
808 OrAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
810 AndAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
812 UshrAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
814 ShrAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
816 ShlAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
818 ModAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
820 DivAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
822 MulAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
825 CatAssignExp::toElem(IRState
* irs
) {
827 Type
* elem_type
= e1
->type
->toBasetype()->nextOf()->toBasetype();
831 args
[0] = irs
->typeinfoReference( type
);
832 args
[1] = irs
->addressOf( irs
->toElemLvalue(e1
) );
834 gcc_assert(elem_type
->ty
!= Tbit
);
836 if (irs
->typesCompatible(elem_type
, e2
->type
->toBasetype())) {
838 args
[2] = aoe
.set(irs
, e2
->toElem(irs
) );
839 lib_call
= LIBCALL_ARRAYAPPENDCTP
;
842 args
[2] = irs
->toDArray(e2
);
843 lib_call
= LIBCALL_ARRAYAPPENDT
;
845 return aoe
.finish(irs
, irs
->libCall(lib_call
, 3, args
, type
->toCtype()));
849 MinAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
851 AddAssignExp::toElem(IRState
* irs
) { return make_assign_math_op(this, irs
); }
854 void do_array_set(IRState
* irs
, tree in_ptr
, tree in_val
, tree in_cnt
) {
855 irs
->startBindings(); // %%maybe not
857 tree count_var
= irs
->localVar(Type::tsize_t
);
858 tree ptr_var
= irs
->localVar(TREE_TYPE(in_ptr
));
859 tree val_var
= NULL_TREE
;
860 tree value_to_use
= NULL_TREE
;
862 DECL_INITIAL(count_var
) = in_cnt
;
863 DECL_INITIAL(ptr_var
) = in_ptr
;
865 irs
->expandDecl(count_var
);
866 irs
->expandDecl(ptr_var
);
868 if (irs
->isFreeOfSideEffects(in_val
)) {
869 value_to_use
= in_val
;
871 val_var
= irs
->localVar(TREE_TYPE(in_val
));
872 DECL_INITIAL(val_var
) = in_val
;
873 irs
->expandDecl(val_var
);
874 value_to_use
= val_var
;
877 irs
->startLoop(NULL
);
881 irs
->exitIfFalse( build(NE_EXPR
, boolean_type_node
, integer_zero_node
, count_var
) );
883 irs
->doExp( build(MODIFY_EXPR
, void_type_node
, irs
->indirect(ptr_var
), value_to_use
));
884 irs
->doExp( build(MODIFY_EXPR
, void_type_node
, ptr_var
,
885 build(PLUS_EXPR
, TREE_TYPE(ptr_var
), ptr_var
,
886 TYPE_SIZE_UNIT(TREE_TYPE(TREE_TYPE(ptr_var
))))) );
887 irs
->doExp( build(MODIFY_EXPR
, void_type_node
, count_var
,
888 build(MINUS_EXPR
, TREE_TYPE(count_var
), count_var
, integer_one_node
)) );
896 // Create a tree node to set multiple elements to a single value
897 tree
array_set_expr(IRState
* irs
, tree ptr
, tree src
, tree count
) {
899 tree exp
= build( (enum tree_code
) D_ARRAY_SET_EXPR
, void_type_node
,
901 TREE_SIDE_EFFECTS( exp
) = 1;
904 irs
->pushStatementList();
905 do_array_set(irs
, ptr
, src
, count
);
906 return irs
->popStatementList();
911 AssignExp::toElem(IRState
* irs
) {
912 // First, handle special assignment semantics
913 if (e1
->op
== TOKarraylength
) {
914 // Assignment to an array's length property; resize the array.
923 Expression
* ae
= ((ArrayLengthExp
*) e1
)->e1
;
924 array_type
= ae
->type
;
925 elem_type
= ae
->type
->toBasetype()->nextOf(); // don't want ->toBasetype for the element type
926 array_exp
= irs
->addressOf( ae
->toElem( irs
));
930 gcc_assert(! elem_type
->isbit());
933 args
[0] = irs
->typeinfoReference(array_type
);
934 args
[1] = irs
->convertTo(e2
, Type::tsize_t
);
937 LibCall lib_call
= elem_type
->isZeroInit() ?
938 LIBCALL_ARRAYSETLENGTHT
: LIBCALL_ARRAYSETLENGTHIT
;
940 result
= irs
->libCall(lib_call
, 3, args
);
941 result
= irs
->darrayLenRef( result
);
944 } else if (e1
->op
== TOKslice
) {
945 Type
* elem_type
= e1
->type
->toBasetype()->nextOf()->toBasetype();
947 gcc_assert(elem_type
->ty
!= Tbit
);
949 if (irs
->typesCompatible(elem_type
, e2
->type
->toBasetype())) {
950 // Set a range of elements to one value.
952 // %% This is used for initing on-stack static arrays..
953 // should optimize with memset if possible
956 tree dyn_array_exp
= irs
->maybeMakeTemp( e1
->toElem(irs
) );
960 Type
* t
= elem_type
;
961 while (t
->ty
== Tsarray
)
962 t
= t
->nextOf()->toBasetype();
963 if (t
->ty
== Tstruct
)
965 StructDeclaration
*sd
= ((TypeStruct
*)elem_type
)->sym
;
971 args
[0] = irs
->darrayPtrRef(dyn_array_exp
);
972 args
[1] = aoe
.set(irs
, e2
->toElem(irs
));
973 args
[2] = irs
->darrayLenRef(dyn_array_exp
);
974 args
[3] = irs
->typeinfoReference(elem_type
);
975 e
= irs
->libCall(op
== TOKconstruct
?
976 LIBCALL_ARRAYSETCTOR
: LIBCALL_ARRAYSETASSIGN
,
978 e
= irs
->compound(aoe
.finish(irs
, e
), dyn_array_exp
);
986 tree set_exp
= array_set_expr( irs
, irs
->darrayPtrRef(dyn_array_exp
),
987 e2
->toElem(irs
), irs
->darrayLenRef(dyn_array_exp
));
988 return irs
->compound(set_exp
, dyn_array_exp
);
990 bool postblit
= false;
992 Type
* t
= elem_type
;
993 while (t
->ty
== Tsarray
)
994 t
= t
->nextOf()->toBasetype();
995 if (t
->ty
== Tstruct
)
997 StructDeclaration
*sd
= ((TypeStruct
*)elem_type
)->sym
;
1002 if (postblit
&& op
!= TOKblit
)
1005 irs
->typeinfoReference(elem_type
),
1009 return irs
->libCall(op
== TOKconstruct
?
1010 LIBCALL_ARRAYCTOR
: LIBCALL_ARRAYASSIGN
,
1011 3, args
, type
->toCtype());
1015 if (global
.params
.useArrayBounds
)
1018 irs
->integerConstant(elem_type
->size(), Type::tsize_t
),
1020 irs
->toDArray(e1
) };
1021 return irs
->libCall(LIBCALL_ARRAYCOPY
, 3, args
, type
->toCtype());
1026 irs
->maybeMakeTemp( irs
->toDArray(e1
) ),
1027 irs
->toDArray(e2
) };
1028 tree t_memcpy
= built_in_decls
[BUILT_IN_MEMCPY
];
1032 size
= build(MULT_EXPR
, size_type_node
,
1033 convert(size_type_node
, irs
->darrayLenRef(array
[0])),
1034 size_int(elem_type
->size()));
1035 size
= fold( size
);
1037 result
= irs
->buildCall( TREE_TYPE(TREE_TYPE( t_memcpy
)),
1038 irs
->addressOf( t_memcpy
),
1039 tree_cons( NULL_TREE
, irs
->darrayPtrRef(array
[0]),
1040 tree_cons( NULL_TREE
, irs
->darrayPtrRef(array
[1]),
1041 tree_cons( NULL_TREE
, size
, NULL_TREE
))));
1043 return irs
->compound( result
, array
[0], type
->toCtype() );
1047 // Simple assignment
1049 tree lhs
= irs
->toElemLvalue(e1
);
1050 tree result
= build(MODIFY_EXPR
, type
->toCtype(),
1051 lhs
, irs
->convertForAssignment(e2
, e1
->type
));
1058 PostExp::toElem(IRState
* irs
)
1061 if (op
== TOKplusplus
)
1062 tc
= POSTINCREMENT_EXPR
;
1063 else if (op
== TOKminusminus
)
1064 tc
= POSTDECREMENT_EXPR
;
1068 return irs
->errorMark(type
);
1070 tree result
= build(tc
, type
->toCtype(),
1071 irs
->toElemLvalue(e1
), e2
->toElem(irs
));
1072 TREE_SIDE_EFFECTS(result
) = 1;
1077 IndexExp::toElem(IRState
* irs
)
1079 Type
* array_type
= e1
->type
->toBasetype();
1081 if (array_type
->ty
!= Taarray
) {
1082 ArrayScope
aryscp(irs
, lengthVar
, loc
);
1083 /* arrayElemRef will call aryscp.finish. This result
1084 of this function may be used as an lvalue and we
1085 do not want it to be a BIND_EXPR. */
1086 return irs
->arrayElemRef( this, & aryscp
);
1088 Type
* key_type
= ((TypeAArray
*) array_type
)->index
->toBasetype();
1092 args
[0] = e1
->toElem(irs
);
1093 args
[1] = irs
->typeinfoReference(key_type
);
1094 args
[2] = irs
->integerConstant( array_type
->nextOf()->size(), Type::tsize_t
);
1095 args
[3] = aoe
.set(irs
, irs
->convertTo( e2
, key_type
) );
1096 t
= irs
->libCall(LIBCALL_AAGETRVALUEP
, 4, args
, type
->pointerTo()->toCtype());
1097 t
= aoe
.finish(irs
, t
);
1098 if (global
.params
.useArrayBounds
) {
1100 t
= build(COND_EXPR
, TREE_TYPE(t
), t
, t
,
1101 irs
->assertCall(loc
, LIBCALL_ARRAY_BOUNDS
));
1103 t
= irs
->indirect(t
, type
->toCtype());
1109 CommaExp::toElem(IRState
* irs
)
1111 // CommaExp is used with DotTypeExp..?
1112 if (e1
->op
== TOKdottype
&& e2
->op
== TOKvar
) {
1113 VarExp
* ve
= (VarExp
*) e2
;
1114 VarDeclaration
* vd
;
1115 FuncDeclaration
* fd
;
1116 /* Handle references to static variable and functions. Otherwise,
1117 just let the DotTypeExp report an error. */
1118 if (( (vd
= ve
->var
->isVarDeclaration()) && ! vd
->needThis() ) ||
1119 ( (fd
= ve
->var
->isFuncDeclaration()) && ! fd
->isThis() ))
1120 return e2
->toElem(irs
);
1122 tree t1
= e1
->toElem( irs
);
1123 tree t2
= e2
->toElem( irs
);
1124 return build(COMPOUND_EXPR
, type
->toCtype(), t1
, t2
);
1128 ArrayLengthExp::toElem(IRState
* irs
)
1130 if (e1
->type
->toBasetype()->ty
== Tarray
) {
1131 return irs
->darrayLenRef(e1
->toElem(irs
));
1133 // Tsarray case seems to be handled by front-end
1135 error("unexpected type for array length: %s", type
->toChars());
1136 return irs
->errorMark(type
);
1141 SliceExp::toElem(IRState
* irs
)
1143 // This function assumes that the front end casts the result to a dynamic array.
1144 assert(type
->toBasetype()->ty
== Tarray
);
1146 // Use convert-to-dynamic-array code if possible
1147 if (e1
->type
->toBasetype()->ty
== Tsarray
&& ! upr
&& ! lwr
)
1148 return irs
->convertTo(e1
->toElem(irs
), e1
->type
, type
);
1150 Type
* orig_array_type
= e1
->type
->toBasetype();
1152 tree orig_array_expr
= NULL
;
1153 tree orig_pointer_expr
;
1154 tree final_len_expr
= NULL
;
1155 tree final_ptr_expr
= NULL
;
1156 tree array_len_expr
= NULL
;
1157 tree lwr_tree
= NULL
;
1159 ArrayScope
aryscp(irs
, lengthVar
, loc
);
1161 orig_array_expr
= aryscp
.setArrayExp( e1
->toElem(irs
), e1
->type
);
1162 orig_array_expr
= irs
->maybeMakeTemp( orig_array_expr
);
1163 // specs don't say bounds if are checked for error or clipped to current size
1165 // Get the data pointer for static and dynamic arrays
1166 orig_pointer_expr
= irs
->convertTo(orig_array_expr
, orig_array_type
,
1167 orig_array_type
->nextOf()->pointerTo());
1169 final_ptr_expr
= orig_pointer_expr
;
1171 // orig_array_expr is already a save_expr if necessary, so
1172 // we don't make array_len_expr a save_expr which is, at most,
1173 // a COMPONENT_REF on top of orig_array_expr.
1174 if ( orig_array_type
->ty
== Tarray
) {
1175 array_len_expr
= irs
->darrayLenRef( orig_array_expr
);
1176 } else if ( orig_array_type
->ty
== Tsarray
) {
1177 array_len_expr
= ((TypeSArray
*) orig_array_type
)->dim
->toElem(irs
);
1179 // array_len_expr == NULL indicates no bounds check is possible
1183 lwr_tree
= lwr
->toElem(irs
);
1184 if (integer_zerop(lwr_tree
))
1185 lwr_tree
= NULL_TREE
;
1188 final_len_expr
= upr
->toElem(irs
);
1189 if (global
.params
.useArrayBounds
&& array_len_expr
) {
1190 final_len_expr
= irs
->maybeMakeTemp(final_len_expr
);
1191 final_len_expr
= irs
->checkedIndex(loc
, final_len_expr
, array_len_expr
, true);
1194 lwr_tree
= irs
->maybeMakeTemp(lwr_tree
);
1196 final_len_expr
= build(MINUS_EXPR
, TREE_TYPE(final_len_expr
), final_len_expr
, lwr_tree
);
1199 // If this is the case, than there is no lower bound specified and
1200 // there is no need to subtract.
1201 switch (orig_array_type
->ty
) {
1203 final_len_expr
= irs
->darrayLenRef(orig_array_expr
);
1206 final_len_expr
= ((TypeSArray
*) orig_array_type
)->dim
->toElem(irs
);
1209 ::error("Attempt to take length of something that was not an array");
1210 return irs
->errorMark(type
);
1214 if (global
.params
.useArrayBounds
&& array_len_expr
) { // %% && ! is zero
1215 lwr_tree
= irs
->maybeMakeTemp(lwr_tree
);
1216 lwr_tree
= irs
->checkedIndex(loc
, lwr_tree
, array_len_expr
, true); // lower bound can equal length
1220 gcc_assert(! orig_array_type
->next
->isbit());
1223 final_ptr_expr
= irs
->pointerIntSum(irs
->pvoidOkay(final_ptr_expr
), lwr_tree
);
1224 final_ptr_expr
= irs
->nop(final_ptr_expr
, TREE_TYPE( orig_pointer_expr
));
1227 return aryscp
.finish( irs
->darrayVal(type
->toCtype(), final_len_expr
, final_ptr_expr
) );
1231 CastExp::toElem(IRState
* irs
)
1233 return irs
->convertTo(e1
, to
);
1237 make_aa_del(IRState
* irs
, Expression
* e_array
, Expression
* e_index
)
1240 Type
* key_type
= ((TypeAArray
*) e_array
->type
->toBasetype())->index
->toBasetype();
1243 args
[0] = e_array
->toElem(irs
);
1244 args
[1] = irs
->typeinfoReference(key_type
);
1245 args
[2] = aoe
.set(irs
, irs
->convertTo( e_index
, key_type
));
1246 return aoe
.finish(irs
, irs
->libCall(LIBCALL_AADELP
, 3, args
) );
1250 DeleteExp::toElem(IRState
* irs
)
1252 // Does this look like an associative array delete?
1253 if (e1
->op
== TOKindex
&&
1254 ((IndexExp
*)e1
)->e1
->type
->toBasetype()->ty
== Taarray
) {
1256 if (! global
.params
.useDeprecated
)
1257 error("delete aa[key] deprecated, use aa.remove(key)", e1
->toChars());
1259 Expression
* e_array
= ((BinExp
*) e1
)->e1
;
1260 Expression
* e_index
= ((BinExp
*) e1
)->e2
;
1262 // Check that the array is actually an associative array
1263 if (e_array
->type
->toBasetype()->ty
== Taarray
)
1264 return make_aa_del(irs
, e_array
, e_index
);
1267 // Otherwise, this is normal delete
1269 tree t
= e1
->toElem(irs
);
1270 Type
* base_type
= e1
->type
->toBasetype();
1272 switch (base_type
->ty
) {
1277 base_type
->isClassHandle()->isInterfaceDeclaration() != NULL
;
1279 if (e1
->op
== TOKvar
&&
1280 ( v
= ((VarExp
*) e1
)->var
->isVarDeclaration() ) && v
->onstack
)
1281 lib_call
= is_intfc
?
1282 LIBCALL_CALLINTERFACEFINALIZER
: LIBCALL_CALLFINALIZER
;
1284 lib_call
= is_intfc
? LIBCALL_DELINTERFACE
: LIBCALL_DELCLASS
;
1287 case Tarray
: lib_call
= LIBCALL_DELARRAY
; break;
1288 case Tpointer
: lib_call
= LIBCALL_DELMEMORY
; break;
1290 error("don't know how to delete %s", e1
->toChars());
1291 return irs
->errorMark(type
);
1294 if (lib_call
!= LIBCALL_CALLFINALIZER
&& lib_call
!= LIBCALL_CALLINTERFACEFINALIZER
)
1295 t
= irs
->addressOf( t
);
1297 return irs
->libCall(lib_call
, 1, & t
);
1301 RemoveExp::toElem(IRState
* irs
)
1303 Expression
* e_array
= e1
;
1304 Expression
* e_index
= e2
;
1306 // Check that the array is actually an associative array
1307 if (e_array
->type
->toBasetype()->ty
== Taarray
) {
1308 return make_aa_del(irs
, e_array
, e_index
);
1310 error("%s is not an associative array", e_array
->toChars());
1311 return irs
->errorMark(type
);
1316 BoolExp::toElem(IRState
* irs
)
1318 return d_convert_basic(type
->toCtype(), irs
->convertForCondition(e1
));
1322 NotExp::toElem(IRState
* irs
)
1324 // %% doc: need to convert to boolean type or this will fail.
1325 tree t
= build1(TRUTH_NOT_EXPR
, boolean_type_node
,
1326 irs
->convertForCondition(e1
));
1327 return convert(type
->toCtype(), t
);
1331 ComExp::toElem(IRState
* irs
)
1333 return build1(BIT_NOT_EXPR
, type
->toCtype(), e1
->toElem( irs
));
1337 NegExp::toElem(IRState
* irs
)
1339 // %% GCC B.E. won't optimize (NEGATE_EXPR (INTEGER_CST ..))..
1340 // %% is type correct?
1341 return build1(NEGATE_EXPR
, type
->toCtype(), e1
->toElem(irs
));
1345 PtrExp::toElem(IRState
* irs
)
1347 /* add this from c-typeck.c:
1348 TREE_READONLY (ref) = TYPE_READONLY (t);
1349 TREE_SIDE_EFFECTS (ref)
1350 = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
1351 TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
1354 /* Produce better code by converting *(#rec + n) to
1355 COMPONENT_REFERENCE. Otherwise, the variable will always be
1356 allocated in memory because its address is taken. */
1357 Type
* rec_type
= 0;
1358 target_size_t the_offset
;
1361 if (e1
->op
== TOKadd
) {
1362 BinExp
* add_exp
= (BinExp
*) e1
;
1363 if (add_exp
->e1
->op
== TOKaddress
&&
1364 add_exp
->e2
->isConst() && add_exp
->e2
->type
->isintegral()) {
1365 Expression
* rec_exp
= ((AddrExp
*) add_exp
->e1
)->e1
;
1366 rec_type
= rec_exp
->type
->toBasetype();
1367 rec_tree
= rec_exp
->toElem(irs
);
1368 the_offset
= add_exp
->e2
->toUInteger();
1370 } else if (e1
->op
== TOKsymoff
) {
1371 // is this ever not a VarDeclaration?
1372 SymOffExp
* sym_exp
= (SymOffExp
*) e1
;
1373 if ( ! irs
->isDeclarationReferenceType(sym_exp
->var
)) {
1374 rec_type
= sym_exp
->var
->type
->toBasetype();
1375 VarDeclaration
* v
= sym_exp
->var
->isVarDeclaration();
1377 rec_tree
= irs
->var(v
);
1379 rec_tree
= sym_exp
->var
->toSymbol()->Stree
;
1380 the_offset
= sym_exp
->offset
;
1382 // otherwise, no real benefit?
1385 if (rec_type
&& rec_type
->ty
== Tstruct
) {
1386 StructDeclaration
* sd
= ((TypeStruct
*)rec_type
)->sym
;
1387 for (unsigned i
= 0; i
< sd
->fields
.dim
; i
++) {
1388 VarDeclaration
* field
= (VarDeclaration
*) sd
->fields
.data
[i
];
1389 if (field
->offset
== the_offset
&&
1390 irs
->typesSame(field
->type
, this->type
)) {
1391 if (irs
->isErrorMark(rec_tree
))
1392 return rec_tree
; // backend will ICE otherwise
1393 return irs
->component(rec_tree
, field
->toSymbol()->Stree
);
1394 } else if (field
->offset
> the_offset
) {
1400 tree e
= irs
->indirect(e1
->toElem(irs
), type
->toCtype());
1401 if (irs
->inVolatile())
1402 TREE_THIS_VOLATILE( e
) = 1;
1407 AddrExp::toElem(IRState
* irs
)
1409 return irs
->nop(irs
->addressOf(e1
->toElem(irs
)), type
->toCtype());
1413 CallExp::toElem(IRState
* irs
)
1415 tree t
= irs
->call(e1
, arguments
);
1416 // Some library calls are defined to return a generic type.
1417 // this->type is the real type. (See crash2.d)
1418 TREE_TYPE(t
) = type
->toCtype();
1423 Expression::toElem(IRState
* irs
)
1425 error("abstract Expression::toElem called");
1426 return irs
->errorMark(type
);
1430 DotTypeExp::toElem(IRState
*irs
)
1432 // The only case in which this seems to be a valid expression is when
1433 // it is used to specify a non-virtual call ( SomeClass.func(...) ).
1434 // This case is handled in IRState::objectInstanceMethod.
1436 error("cannot use \"%s\" as an expression", toChars());
1438 // Can cause ICEs later; should just exit now.
1439 return irs
->errorMark(type
);
1442 // The result will probably just be converted to a CONSTRUCTOR for a Tdelegate struct
1444 DelegateExp::toElem(IRState
* irs
)
1446 Type
* t
= e1
->type
->toBasetype();
1447 if (t
->ty
== Tclass
|| t
->ty
== Tstruct
) {
1448 // %% Need to see if DotVarExp ever has legitimate
1449 // <aggregate>.<static method>. If not, move this test
1450 // to objectInstanceMethod.
1451 if (! func
->isThis())
1452 error("delegates are only for non-static functions");
1453 return irs
->objectInstanceMethod(e1
, func
, type
);
1455 assert(func
->isNested() || func
->isThis());
1456 return irs
->methodCallExpr(irs
->functionPointer(func
),
1458 #if D_NO_TRAMPOLINES
1459 irs
->getFrameForFunction(func
)
1463 : e1
->toElem(irs
), type
);
1468 DotVarExp::toElem(IRState
* irs
)
1470 FuncDeclaration
* func_decl
;
1471 VarDeclaration
* var_decl
;
1472 Type
* obj_basetype
= e1
->type
->toBasetype();
1473 TY obj_basetype_ty
= obj_basetype
->ty
;
1474 switch (obj_basetype_ty
) {
1476 if (obj_basetype
->nextOf()->toBasetype()->ty
!= Tstruct
) {
1483 if ( (func_decl
= var
->isFuncDeclaration()) ) {
1484 // if Tstruct, objInstanceMethod will use the address of e1
1485 return irs
->objectInstanceMethod(e1
, func_decl
, type
);
1486 } else if ( (var_decl
= var
->isVarDeclaration()) ) {
1487 if (var_decl
->storage_class
& STCfield
) {
1488 tree this_tree
= e1
->toElem(irs
);
1489 if ( obj_basetype_ty
!= Tstruct
)
1490 this_tree
= irs
->indirect(this_tree
);
1491 return irs
->component(this_tree
, var_decl
->toSymbol()->Stree
);
1493 return irs
->var(var_decl
);
1502 ::error("Don't know how to handle %s", toChars());
1503 return irs
->errorMark(type
);
1507 AssertExp::toElem(IRState
* irs
)
1509 // %% todo: Do we call a Tstruct's invariant if
1510 // e1 is a pointer to the struct?
1511 if (global
.params
.useAssert
) {
1512 Type
* base_type
= e1
->type
->toBasetype();
1513 TY ty
= base_type
->ty
;
1514 tree assert_call
= msg
?
1515 irs
->assertCall(loc
, msg
) : irs
->assertCall(loc
);
1518 ClassDeclaration
* cd
= base_type
->isClassHandle();
1519 tree arg
= e1
->toElem(irs
);
1520 if (cd
->isCOMclass())
1522 return build(COND_EXPR
, void_type_node
,
1523 irs
->boolOp(NE_EXPR
, arg
, d_null_pointer
),
1524 d_void_zero_node
, assert_call
);
1526 else if (cd
->isInterfaceDeclaration())
1528 arg
= irs
->convertTo(arg
, base_type
, irs
->getObjectType());
1530 return irs
->libCall(LIBCALL_INVARIANT
, 1, & arg
); // this does a null pointer check
1532 // build: ( (bool) e1 ? (void)0 : _d_assert(...) )
1533 // or: ( e1 != null ? (void)0 : _d_assert(...), e1._invariant() )
1535 tree invc
= NULL_TREE
;
1536 tree e1_t
= e1
->toElem(irs
);
1538 if (ty
== Tpointer
) {
1539 Type
* sub_type
= base_type
->nextOf()->toBasetype();
1540 if (sub_type
->ty
== Tstruct
) {
1541 AggregateDeclaration
* agg_decl
= ((TypeStruct
*) sub_type
)->sym
;
1542 if (agg_decl
->inv
) {
1544 e1_t
= irs
->maybeMakeTemp(e1_t
);
1545 invc
= irs
->call(agg_decl
->inv
, e1_t
, & args
);
1550 result
= build(COND_EXPR
, void_type_node
,
1551 irs
->convertForCondition( e1_t
, e1
->type
),
1552 d_void_zero_node
, assert_call
);
1554 result
= build(COMPOUND_EXPR
, void_type_node
, result
, invc
);
1558 return d_void_zero_node
;
1562 DeclarationExp::toElem(IRState
* irs
)
1564 // VarDeclaration::toObjFile was modified to call d_gcc_emit_local_variable
1565 // if needed. This assumes irs == g.irs
1567 tree rtl_expr
= expand_start_stmt_expr(0);
1568 declaration
->toObjFile(false);
1569 expand_end_stmt_expr (rtl_expr
);
1572 irs
->pushStatementList();
1573 declaration
->toObjFile(false);
1574 return irs
->popStatementList();
1579 d_gcc_emit_local_variable(VarDeclaration
* v
)
1581 g
.irs
->emitLocalVar(v
);
1585 d_gcc_supports_weak()
1587 return SUPPORTS_WEAK
;
1590 // %% check calling this directly?
1592 FuncExp::toElem(IRState
* irs
)
1594 fd
->toObjFile(false);
1596 Type
* func_type
= type
->toBasetype();
1598 if (func_type
->ty
== Tpointer
)
1599 func_type
= func_type
->nextOf()->toBasetype();
1601 switch (func_type
->ty
) {
1603 return irs
->nop(irs
->addressOf(fd
), type
->toCtype());
1605 return irs
->methodCallExpr(irs
->functionPointer(fd
), // trampoline or not
1606 #if D_NO_TRAMPOLINES
1607 irs
->getFrameForFunction(fd
),
1609 convert(ptr_type_node
, integer_one_node
),
1613 ::error("Unexpected FunExp type");
1614 return irs
->errorMark(type
);
1617 // If nested, this will be a trampoline...
1621 HaltExp::toElem(IRState
* irs
)
1623 // Needs improvement. Avoid library calls if possible..
1624 tree t_abort
= built_in_decls
[BUILT_IN_ABORT
];
1625 return irs
->buildCall( TREE_TYPE(TREE_TYPE(t_abort
)),
1626 irs
->addressOf(t_abort
), NULL_TREE
);
1631 SymbolExp::toElem(IRState
* irs
)
1634 if (var
->storage_class
& STCfield
) {
1635 /*::*/error("Need 'this' to access member %s", var
->ident
->string
);
1636 return irs
->errorMark(type
);
1639 // For variables that are references (currently only out/inout arguments;
1640 // objects don't count), evaluating the variable means we want what it refers to.
1642 // TODO: is this ever not a VarDeclaration; (four sequences like this...)
1643 VarDeclaration
* v
= var
->isVarDeclaration();
1648 e
= var
->toSymbol()->Stree
;
1650 if ( irs
->isDeclarationReferenceType(var
) ) {
1651 e
= irs
->indirect(e
, var
->type
->toCtype());
1652 if (irs
->inVolatile()) {
1653 TREE_THIS_VOLATILE(e
) = 1;
1656 if (irs
->inVolatile()) {
1657 e
= irs
->addressOf(e
);
1658 TREE_THIS_VOLATILE(e
) = 1;
1659 e
= irs
->indirect(e
);
1660 TREE_THIS_VOLATILE(e
) = 1;
1664 } else if (op
== TOKsymoff
) {
1665 target_size_t offset
= ((SymOffExp
*) this)->offset
;
1667 VarDeclaration
* v
= var
->isVarDeclaration();
1672 a
= var
->toSymbol()->Stree
;
1674 if ( irs
->isDeclarationReferenceType(var
) )
1675 assert(POINTER_TYPE_P(TREE_TYPE(a
)));
1677 a
= irs
->addressOf(a
);
1680 return convert(type
->toCtype(), a
);
1682 tree b
= irs
->integerConstant(offset
, Type::tsize_t
);
1683 return build(PLUS_EXPR
, type
->toCtype(), a
, b
) ;
1686 gcc_assert(op
== TOKvar
|| op
== TOKsymoff
);
1687 return error_mark_node
;
1691 VarExp::toElem(IRState
* irs
)
1693 if (var
->storage_class
& STCfield
) {
1694 /*::*/error("Need 'this' to access member %s", var
->ident
->string
);
1695 return irs
->errorMark(type
);
1698 // For variables that are references (currently only out/inout arguments;
1699 // objects don't count), evaluating the variable means we want what it refers to.
1700 //tree e = irs->var(var);
1701 VarDeclaration
* v
= var
->isVarDeclaration();
1706 e
= var
->toSymbol()->Stree
;
1708 if ( irs
->isDeclarationReferenceType(var
) ) {
1709 e
= irs
->indirect(e
, var
->type
->toCtype());
1710 if (irs
->inVolatile()) {
1711 TREE_THIS_VOLATILE(e
) = 1;
1714 if (irs
->inVolatile()) {
1715 e
= irs
->addressOf(e
);
1716 TREE_THIS_VOLATILE(e
) = 1;
1717 e
= irs
->indirect(e
);
1718 TREE_THIS_VOLATILE(e
) = 1;
1725 SymOffExp::toElem(IRState
* irs
) {
1726 //tree a = irs->var(var);
1728 VarDeclaration
* v
= var
->isVarDeclaration();
1732 a
= var
->toSymbol()->Stree
;
1734 if ( irs
->isDeclarationReferenceType(var
) )
1735 assert(POINTER_TYPE_P(TREE_TYPE(a
)));
1737 a
= irs
->addressOf(var
);
1740 return convert(type
->toCtype(), a
);
1742 tree b
= irs
->integerConstant(offset
, Type::tsize_t
);
1743 return build(PLUS_EXPR
, type
->toCtype(), a
, b
) ;
1748 isClassNestedIn(ClassDeclaration
*inner
, ClassDeclaration
*outer
)
1750 // not implemented yet
1754 static FuncDeclaration
*
1755 isClassNestedInFunction(ClassDeclaration
* cd
)
1758 if (cd
->isNested()) {
1759 Dsymbol
* s
= cd
->toParent2();
1760 FuncDeclaration
* fd
= s
->isFuncDeclaration();
1765 cd
= s
->isClassDeclaration();
1778 Starting from the current function, try to find a suitable value of
1779 'this' in nested functions and (not implemented yet:) nested class
1782 A suitable 'this' value is an instance of target_cd or a class that
1783 has target_cd as a base.
1787 findThis(IRState
* irs
, ClassDeclaration
* target_cd
)
1789 FuncDeclaration
* fd
= irs
->func
;
1792 AggregateDeclaration
* fd_ad
;
1793 ClassDeclaration
* fd_cd
;
1795 if ((fd_ad
= fd
->isThis()) &&
1796 (fd_cd
= fd_ad
->isClassDeclaration())) {
1797 if (target_cd
== fd_cd
) {
1798 return irs
->var(fd
->vthis
);
1799 } else if (target_cd
->isBaseOf(fd_cd
, NULL
)) {
1800 assert(fd
->vthis
); // && fd->vthis->csym->Stree
1801 return irs
->convertTo(irs
->var(fd
->vthis
),
1802 fd_cd
->type
, target_cd
->type
);
1803 } else if (isClassNestedIn(fd_cd
, target_cd
)) {
1807 fd
= isClassNestedInFunction(fd_cd
);
1809 } else if (fd
->isNested()) {
1810 fd
= fd
->toParent2()->isFuncDeclaration();
1818 NewExp::toElem(IRState
* irs
)
1820 Type
* base_type
= newtype
->toBasetype();
1826 switch (base_type
->ty
) {
1829 TypeClass
* class_type
= (TypeClass
*) base_type
;
1830 ClassDeclaration
* class_decl
= class_type
->sym
;
1833 tree setup_exp
= NULL_TREE
;
1834 // type->toCtype() is a REFERENCE_TYPE; we want the RECORD_TYPE
1835 tree rec_type
= TREE_TYPE( class_type
->toCtype() );
1837 // Allocation call (custom allocator or _d_newclass)
1839 tree stack_var
= irs
->localVar( rec_type
);
1840 irs
->expandDecl(stack_var
);
1841 new_call
= irs
->addressOf(stack_var
);
1842 setup_exp
= build(MODIFY_EXPR
, rec_type
,
1843 irs
->indirect(new_call
, rec_type
),
1844 class_decl
->toInitializer()->Stree
);
1845 } else if (allocator
) {
1846 new_call
= irs
->call(allocator
, newargs
);
1847 new_call
= save_expr( new_call
);
1849 setup_exp
= build(MODIFY_EXPR
, rec_type
,
1850 irs
->indirect(new_call
, rec_type
),
1851 class_decl
->toInitializer()->Stree
);
1853 tree arg
= irs
->addressOf( class_decl
->toSymbol()->Stree
);
1854 new_call
= irs
->libCall(LIBCALL_NEWCLASS
, 1, & arg
);
1857 if (class_type
->sym
->isNested()) {
1858 tree vthis_value
= NULL_TREE
;
1859 tree vthis_field
= class_type
->sym
->vthis
->toSymbol()->Stree
;
1862 ClassDeclaration
*thisexp_cd
= thisexp
->type
->isClassHandle();
1863 Dsymbol
*outer
= class_decl
->toParent2();
1864 target_ptrdiff_t offset
= 0;
1866 vthis_value
= thisexp
->toElem(irs
);
1867 if (outer
!= thisexp_cd
) {
1868 ClassDeclaration
* outer_cd
= outer
->isClassDeclaration();
1869 int i
= outer_cd
->isBaseOf(thisexp_cd
, & offset
);
1871 // could just add offset
1872 vthis_value
= irs
->convertTo(vthis_value
, thisexp
->type
, outer_cd
->type
);
1875 Dsymbol
*outer
= class_decl
->toParent2();
1876 ClassDeclaration
*cd_outer
= outer
->isClassDeclaration();
1877 FuncDeclaration
*fd_outer
= outer
->isFuncDeclaration();
1880 vthis_value
= findThis(irs
, cd_outer
);
1881 if (vthis_value
== NULL_TREE
)
1882 error("outer class %s 'this' needed to 'new' nested class %s",
1883 cd_outer
->ident
->string
, class_decl
->ident
->string
);
1884 } else if (fd_outer
) {
1885 /* If a class nested in a function has no methods
1886 and there are no other nested functions,
1887 lower_nested_functions is never called and any
1888 STATIC_CHAIN_EXPR created here will never be
1889 translated. Use a null pointer for the link in
1893 fd_outer
->closureVars
.dim
||
1894 irs
->getFrameInfo(fd_outer
)->creates_closure
1896 fd_outer
->nestedFrameRef
1899 vthis_value
= irs
->getFrameForNestedClass(class_decl
); // %% V2: rec_type->class_type
1901 vthis_value
= d_null_pointer
;
1909 new_call
= save_expr( new_call
);
1910 setup_exp
= irs
->maybeCompound(setup_exp
,
1911 build(MODIFY_EXPR
, TREE_TYPE(vthis_field
),
1912 irs
->component( irs
->indirect(new_call
, rec_type
),
1918 new_call
= irs
->maybeCompound(setup_exp
, new_call
);
1922 result
= irs
->call(member
, new_call
, arguments
);
1926 return irs
->convertTo(result
, base_type
, type
);
1930 assert( ! allocator
);
1931 assert( arguments
&& arguments
->dim
> 0 );
1935 Type
* elem_init_type
= newtype
;
1937 /* First, skip past dynamic array dimensions/types that will be
1938 allocated by this call. */
1939 for (unsigned i
= 0; i
< arguments
->dim
; i
++)
1940 elem_init_type
= elem_init_type
->toBasetype()->nextOf(); // assert ty == Tarray
1943 gcc_assert(! elem_init_type
->isbit());
1946 if (arguments
->dim
== 1)
1948 lib_call
= elem_init_type
->isZeroInit() ?
1949 LIBCALL_NEWARRAYT
: LIBCALL_NEWARRAYIT
;
1952 args
[0] = irs
->typeinfoReference(type
);
1953 args
[1] = ((Expression
*) arguments
->data
[0])->toElem(irs
);
1954 result
= irs
->libCall(lib_call
, 2, args
, type
->toCtype());
1958 lib_call
= elem_init_type
->isZeroInit() ?
1959 LIBCALL_NEWARRAYMTP
: LIBCALL_NEWARRAYMITP
;
1961 tree dims_var
= irs
->exprVar(irs
->arrayType(size_type_node
, arguments
->dim
));
1966 elms
.reserve( arguments
->dim
);
1967 for (unsigned i
= 0; i
< arguments
->dim
/* - 1*/; i
++)
1968 elms
.cons( irs
->integerConstant(i
, size_type_node
),
1969 ((Expression
*) arguments
->data
[i
])->toElem(irs
) );
1970 //elms.cons(final_length);
1971 dims_init
= make_node(CONSTRUCTOR
);
1972 TREE_TYPE( dims_init
) = TREE_TYPE( dims_var
);
1973 CONSTRUCTOR_ELTS( dims_init
) = elms
.head
;
1974 DECL_INITIAL(dims_var
) = dims_init
;
1978 args
[0] = irs
->typeinfoReference(type
);
1979 args
[1] = irs
->integerConstant(arguments
->dim
, Type::tint32
); // The ndims arg is declared as 'int'
1980 args
[2] = irs
->addressOf(dims_var
);
1982 result
= irs
->libCall(lib_call
, 3, args
, type
->toCtype());
1983 result
= irs
->binding(dims_var
, result
);
1986 return irs
->convertTo(result
, base_type
, type
);
1991 Type
* object_type
= newtype
;
1992 Type
* handle_type
= base_type
->pointerTo();
1995 bool need_init
= true;
1998 tree stack_var
= irs
->localVar( object_type
);
1999 irs
->expandDecl(stack_var
);
2000 new_call
= irs
->addressOf( stack_var
);
2001 } else if (allocator
) {
2002 new_call
= irs
->call(allocator
, newargs
);
2005 LibCall lib_call
= object_type
->isZeroInit() ?
2006 LIBCALL_NEWARRAYT
: LIBCALL_NEWARRAYIT
;
2007 args
[0] = irs
->typeinfoReference( object_type
->arrayOf() );
2008 args
[1] = irs
->integerConstant(1, Type::tsize_t
);
2009 new_call
= irs
->libCall(lib_call
, 2, args
);
2010 new_call
= irs
->darrayPtrRef(new_call
);
2013 new_call
= irs
->nop(new_call
, handle_type
->toCtype());
2015 // Save the result allocation call.
2016 new_call
= save_expr( new_call
);
2017 t
= irs
->indirect(new_call
);
2018 t
= build(MODIFY_EXPR
, TREE_TYPE(t
), t
,
2019 irs
->convertForAssignment(object_type
->defaultInit(), object_type
) );
2020 new_call
= irs
->compound(t
, new_call
);
2022 return irs
->nop(new_call
, type
->toCtype());
2028 elem
* ScopeExp::toElem(IRState
* irs
) {
2029 ::error("%s is not an expression", toChars());
2030 return irs
->errorMark(type
);
2033 elem
* TypeExp::toElem(IRState
* irs
) {
2034 ::error("%s is not an expression", toChars());
2035 return irs
->errorMark(type
);
2038 elem
* TypeDotIdExp::toElem(IRState
* irs
) {
2039 ::error("TypeDotIdExp::toElem: don't know what to do (%s)", toChars());
2040 return irs
->errorMark(type
);
2044 StringExp::toElem(IRState
* irs
)
2046 Type
* base_type
= type
->toBasetype();
2047 TY base_ty
= type
? base_type
->ty
: (TY
) Tvoid
;
2053 // Assuming this->string is null terminated
2054 // .. need to terminate with more nulls for wchar and dchar?
2055 value
= build_string((len
+ 1) * sz
,
2056 gen
.hostToTargetString((char *) string
, len
+ 1, sz
));
2060 value
= build_string(len
* sz
,
2061 gen
.hostToTargetString((char *) string
, len
, sz
));
2064 error("Invalid type for string constant: %s", type
->toChars());
2065 return irs
->errorMark(type
);
2068 // %% endianess of wchar and dchar
2069 TREE_CONSTANT (value
) = 1;
2070 TREE_READONLY (value
) = 1;
2071 // %% array type doesn't match string length if null term'd...
2072 TREE_TYPE( value
) = irs
->arrayType(base_ty
!= Tvoid
?
2073 base_type
->nextOf() : Type::tchar
, len
);
2077 value
= irs
->darrayVal(type
, len
, irs
->addressOf( value
));
2080 value
= irs
->addressOf( value
);
2084 TREE_TYPE(value
) = type
->toCtype();
2094 TupleExp::toElem(IRState
* irs
)
2096 tree result
= NULL_TREE
;
2097 if (exps
&& exps
->dim
) {
2098 for (unsigned i
= 0; i
< exps
->dim
; ++i
) {
2099 Expression
* e
= (Expression
*) exps
->data
[i
];
2100 result
= irs
->maybeVoidCompound(result
, e
->toElem(irs
));
2103 result
= d_void_zero_node
;
2108 /* Returns an expression that assignes the expressions in ALE to static
2109 array pointed to by MEM. */
2111 // probably will need to pass the D array element type to get assignmets correct...
2112 // [ [1,2,3], 4 ]; // doesn't work, so maybe not..
2113 // opt: if all/most constant, should make a var and do array copy
2115 array_literal_assign(IRState
* irs
, tree mem
, ArrayLiteralExp
* ale
)
2117 tree result
= NULL_TREE
;
2118 tree offset
= size_int(0);
2119 tree elem_size
= size_int( ale
->type
->toBasetype()->nextOf()->size() );
2121 for (unsigned i
= 0; i
< ale
->elements
->dim
; i
++) {
2122 Expression
* e
= (Expression
*) ale
->elements
->data
[i
];
2123 tree elemp_e
= build2(PLUS_EXPR
, TREE_TYPE(mem
), mem
, offset
);
2124 tree assgn_e
= irs
->vmodify( irs
->indirect(elemp_e
),
2126 result
= irs
->maybeCompound(result
, assgn_e
);
2128 offset
= size_binop(PLUS_EXPR
, offset
, elem_size
);
2134 ArrayLiteralExp::toElem(IRState
* irs
)
2136 Type
* array_type
= type
->toBasetype();
2137 assert( array_type
->ty
== Tarray
|| array_type
->ty
== Tsarray
||
2138 array_type
->ty
== Tpointer
);
2139 tree elem_type
= array_type
->nextOf()->toCtype();
2140 tree d_array_type
= array_type
->nextOf()->arrayOf()->toCtype();
2142 tree args
[2] = { irs
->typeinfoReference(array_type
->nextOf()->arrayOf()),
2143 irs
->integerConstant(elements
->dim
, size_type_node
) };
2144 // Unfortunately, this does a useles initialization
2145 LibCall lib_call
= array_type
->nextOf()->isZeroInit() ?
2146 LIBCALL_NEWARRAYT
: LIBCALL_NEWARRAYIT
;
2147 tree d_array
= irs
->libCall(lib_call
, 2, args
, d_array_type
);
2149 tree mem
= irs
->maybeMakeTemp( irs
->darrayPtrRef( d_array
));
2150 tree result
= irs
->maybeCompound( array_literal_assign(irs
, mem
, this),
2152 if ( array_type
->ty
== Tarray
) {
2153 result
= irs
->darrayVal(d_array_type
, elements
->dim
, result
);
2155 tree s_array_type
= irs
->arrayType(elem_type
, elements
->dim
);
2156 if (array_type
->ty
== Tsarray
)
2157 result
= irs
->indirect(result
, s_array_type
);
2164 AssocArrayLiteralExp::toElem(IRState
* irs
)
2166 TypeAArray
* aa_type
= (TypeAArray
*)type
->toBasetype();
2167 assert(aa_type
->ty
== Taarray
);
2168 assert(keys
!= NULL
);
2169 assert(values
!= NULL
);
2171 tree keys_var
= irs
->exprVar(irs
->arrayType(aa_type
->index
, keys
->dim
)); //?
2172 tree vals_var
= irs
->exprVar(irs
->arrayType(aa_type
->next
, keys
->dim
));
2173 tree keys_ptr
= irs
->nop(irs
->addressOf(keys_var
),
2174 aa_type
->index
->pointerTo()->toCtype());
2175 tree vals_ptr
= irs
->nop(irs
->addressOf(vals_var
),
2176 aa_type
->next
->pointerTo()->toCtype());
2177 tree keys_offset
= size_int(0);
2178 tree vals_offset
= size_int(0);
2179 tree keys_size
= size_int( aa_type
->index
->size() );
2180 tree vals_size
= size_int( aa_type
->next
->size() );
2181 tree result
= NULL_TREE
;
2183 for (unsigned i
= 0; i
< keys
->dim
; i
++)
2186 tree elemp_e
, assgn_e
;
2188 e
= (Expression
*) keys
->data
[i
];
2189 elemp_e
= build2(PLUS_EXPR
, TREE_TYPE(keys_ptr
), keys_ptr
, keys_offset
);
2190 assgn_e
= irs
->vmodify( irs
->indirect(elemp_e
), e
->toElem(irs
) );
2191 keys_offset
= size_binop(PLUS_EXPR
, keys_offset
, keys_size
);
2192 result
= irs
->maybeCompound(result
, assgn_e
);
2194 e
= (Expression
*) values
->data
[i
];
2195 elemp_e
= build2(PLUS_EXPR
, TREE_TYPE(vals_ptr
), vals_ptr
, vals_offset
);
2196 assgn_e
= irs
->vmodify( irs
->indirect(elemp_e
), e
->toElem(irs
) );
2197 vals_offset
= size_binop(PLUS_EXPR
, vals_offset
, vals_size
);
2198 result
= irs
->maybeCompound(result
, assgn_e
);
2201 tree args
[4] = { irs
->typeinfoReference(aa_type
),
2202 irs
->integerConstant(keys
->dim
, Type::tsize_t
),
2203 keys_ptr
, vals_ptr
};
2204 result
= irs
->maybeCompound(result
,
2205 irs
->libCall(LIBCALL_ASSOCARRAYLITERALTP
, 4, args
));
2207 result
= irs
->binding(keys_var
, irs
->binding(vals_var
, result
));
2209 tree ctor
= make_node( CONSTRUCTOR
);
2211 TREE_TYPE( ctor
) = aa_type
->toCtype();
2212 ce
.cons(TYPE_FIELDS(TREE_TYPE( ctor
)), result
);
2213 CONSTRUCTOR_ELTS( ctor
) = ce
.head
;
2215 return irs
->nop(ctor
, type
->toCtype());
2219 StructLiteralExp::toElem(IRState
*irs
)
2221 assert(irs
->typesSame(type
->toBasetype(), sd
->type
->toBasetype()));
2223 tree ctor
= make_node( CONSTRUCTOR
);
2225 TREE_TYPE( ctor
) = type
->toCtype();
2228 for (unsigned i
= 0; i
< elements
->dim
; ++i
)
2230 Expression
* e
= (Expression
*) elements
->data
[i
];
2233 VarDeclaration
* fld
= (VarDeclaration
*) sd
->fields
.data
[i
];
2234 ce
.cons(fld
->csym
->Stree
, irs
->convertTo(e
, fld
->type
));
2238 CONSTRUCTOR_ELTS( ctor
) = ce
.head
;
2243 NullExp::toElem(IRState
* irs
)
2245 TY base_ty
= type
->toBasetype()->ty
;
2246 // 0 -> dynamic array. This is a special case conversion.
2247 // Move to convert for convertTo if it shows up elsewhere.
2250 return irs
->darrayVal( type
, 0, NULL
);
2253 tree ctor
= make_node(CONSTRUCTOR
);
2257 TREE_TYPE(ctor
) = type
->toCtype();
2258 fa
= TYPE_FIELDS(TREE_TYPE(ctor
));
2259 ce
.cons(fa
, convert(TREE_TYPE(fa
), integer_zero_node
));
2260 CONSTRUCTOR_ELTS(ctor
) = ce
.head
;
2265 // makeDelegateExpression ?
2266 return irs
->delegateVal(convert(ptr_type_node
, integer_zero_node
),
2267 convert(ptr_type_node
, integer_zero_node
), type
);
2269 return convert( type
->toCtype(), integer_zero_node
);
2274 ThisExp::toElem(IRState
* irs
) {
2276 return irs
->var(var
->isVarDeclaration());
2277 // %% DMD issue -- creates ThisExp without setting var to vthis
2278 // %%TODO: updated in 0.79-0.81?
2279 assert( irs
->func
);
2280 assert( irs
->func
->vthis
);
2281 return irs
->var(irs
->func
->vthis
);
2285 ComplexExp::toElem(IRState
* irs
)
2287 TypeBasic
* compon_type
;
2288 switch (type
->toBasetype()->ty
) {
2289 case Tcomplex32
: compon_type
= (TypeBasic
*) Type::tfloat32
; break;
2290 case Tcomplex64
: compon_type
= (TypeBasic
*) Type::tfloat64
; break;
2291 case Tcomplex80
: compon_type
= (TypeBasic
*) Type::tfloat80
; break;
2295 return build_complex(type
->toCtype(),
2296 irs
->floatConstant(creall(value
), compon_type
),
2297 irs
->floatConstant(cimagl(value
), compon_type
));
2301 RealExp::toElem(IRState
* irs
)
2303 return irs
->floatConstant(value
, type
->toBasetype()->isTypeBasic());
2307 IntegerExp::toElem(IRState
* irs
)
2309 return irs
->integerConstant(value
, type
);
2315 genericize_function(tree fndecl
)
2318 int local_dump_flags
;
2320 struct cgraph_node
*cgn
;
2323 /* Dump the C-specific tree IR. */
2324 dump_file
= dump_begin (TDI_original
, &local_dump_flags
);
2327 fprintf (dump_file
, "\n;; Function %s",
2328 lang_hooks
.decl_printable_name (fndecl
, 2));
2329 fprintf (dump_file
, " (%s)\n",
2330 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl
)));
2331 fprintf (dump_file
, ";; enabled by -%s\n", dump_flag_name (TDI_original
));
2332 fprintf (dump_file
, "\n");
2334 //if (local_dump_flags & TDF_RAW)
2335 dump_node (DECL_SAVED_TREE (fndecl
),
2336 TDF_SLIM
| local_dump_flags
, dump_file
);
2338 //print_c_tree (dump_file, DECL_SAVED_TREE (fndecl));
2339 fprintf (dump_file
, "\n");
2341 dump_end (TDI_original
, dump_file
);
2344 /* Go ahead and gimplify for now. */
2346 gimplify_function_tree (fndecl
);
2349 /* Dump the genericized tree IR. */
2350 dump_function (TDI_generic
, fndecl
);
2352 /* Genericize all nested functions now. We do things in this order so
2353 that items like VLA sizes are expanded properly in the context of
2354 the correct function. */
2355 cgn
= cgraph_node (fndecl
);
2356 for (cgn
= cgn
->nested
; cgn
; cgn
= cgn
->next_nested
)
2357 genericize_function (cgn
->decl
);
2364 FuncDeclaration::toObjFile(int multiobj
)
2366 if (!g
.ofile
->shouldEmit(this))
2368 if (! global
.params
.useUnitTests
&& isUnitTestDeclaration())
2371 Symbol
* this_sym
= toSymbol();
2372 if (this_sym
->outputStage
)
2375 if (g
.irs
->shouldDeferFunction(this))
2378 this_sym
->outputStage
= InProgress
;
2380 tree fn_decl
= this_sym
->Stree
;
2384 // %% Should set this earlier...
2385 DECL_EXTERNAL (fn_decl
) = 1;
2386 TREE_PUBLIC( fn_decl
) = 1;
2388 g
.ofile
->rodc(fn_decl
, 1);
2394 tree parm_decl
= NULL_TREE
;
2396 #if D_NO_TRAMPOLINES
2397 tree static_chain_expr
= NULL_TREE
;
2399 FuncDeclaration
* closure_func
= NULL
;
2400 tree closure_expr
= NULL_TREE
;
2403 ClassDeclaration
* cd
;
2404 AggregateDeclaration
* ad
= NULL
;
2406 announce_function( fn_decl
);
2407 IRState
* irs
= IRState::startFunction(this);
2409 irs
->useClosure(NULL
, NULL_TREE
);
2413 bool saved_omit_frame_pointer
= flag_omit_frame_pointer
;
2414 flag_omit_frame_pointer
= gen
.originalOmitFramePointer
|| naked
;
2416 if (gen
.functionNeedsChain(this))
2417 push_function_context();
2419 // in 4.0, doesn't use push_function_context
2420 tree old_current_function_decl
= current_function_decl
;
2421 function
* old_cfun
= cfun
;
2424 current_function_decl
= fn_decl
;
2426 TREE_STATIC( fn_decl
) = 1;
2429 Type
* func_type
= tintro
? tintro
: type
;
2430 Type
* ret_type
= func_type
->nextOf()->toBasetype();
2431 if (isMain() && ret_type
->ty
== Tvoid
)
2432 ret_type
= Type::tint32
;
2433 result_decl
= build_decl( RESULT_DECL
, NULL_TREE
, ret_type
->toCtype() );
2435 g
.ofile
->setDeclLoc(result_decl
, this);
2436 DECL_RESULT( fn_decl
) = result_decl
;
2437 DECL_CONTEXT( result_decl
) = fn_decl
;
2438 //layout_decl( result_decl, 0 );
2441 allocate_struct_function( fn_decl
);
2442 // assuming the above sets cfun
2443 if (endloc
.filename
) {
2444 cfun
->function_end_locus
.file
= endloc
.filename
;
2445 cfun
->function_end_locus
.line
= endloc
.linnum
;
2447 cfun
->function_end_locus
.file
= DECL_SOURCE_FILE (fn_decl
);
2448 cfun
->function_end_locus
.line
= DECL_SOURCE_LINE (fn_decl
);
2452 param_list
= NULL_TREE
;
2455 bool needs_static_chain
= irs
->functionNeedsChain(this);
2458 int n_parameters
= parameters
? parameters
->dim
: 0;
2460 // Special arguments...
2461 static const int VTHIS
= -2;
2462 static const int VARGUMENTS
= -1;
2464 for (int i
= VTHIS
; i
< (int) n_parameters
; i
++) {
2465 VarDeclaration
* param
= 0;
2471 if ( (ad
= isThis()) )
2473 else if (isNested()) {
2474 /* DMD still generates a vthis, but it should not be
2475 referenced in any expression.
2477 This parameter is hidden from the debugger.
2479 parm_type
= ptr_type_node
;
2480 parm_decl
= build_decl(PARM_DECL
, NULL_TREE
, parm_type
);
2481 DECL_ARTIFICIAL( parm_decl
) = 1;
2482 DECL_IGNORED_P( parm_decl
) = 1;
2483 DECL_ARG_TYPE (parm_decl
) = TREE_TYPE (parm_decl
); // %% doc need this arg silently disappears
2484 #if D_NO_TRAMPOLINES
2486 if (! needs_static_chain
)
2488 closure_func
= toParent2()->isFuncDeclaration();
2489 closure_expr
= parm_decl
;
2494 static_chain_expr
= parm_decl
;
2499 } else if (i
== VARGUMENTS
) {
2500 if (v_arguments
/*varargs && linkage == LINKd*/)
2501 param
= v_arguments
;
2505 param
= (VarDeclaration
*) parameters
->data
[i
];
2508 parm_decl
= param
->toSymbol()->Stree
;
2511 DECL_CONTEXT (parm_decl
) = fn_decl
;
2512 // param->loc is not set, so use the function's loc
2513 // %%doc not setting this crashes debug generating code
2514 g
.ofile
->setDeclLoc( parm_decl
, param
? (Dsymbol
*) param
: (Dsymbol
*) this );
2516 // chain them in the correct order
2517 param_list
= chainon (param_list
, parm_decl
);
2520 // param_list is a number of PARM_DECL trees chained together (*not* a TREE_LIST of PARM_DECLs).
2521 // The leftmost parameter is the first in the chain. %% varargs?
2522 DECL_ARGUMENTS( fn_decl
) = param_list
; // %% in treelang, useless ? because it just sets them to getdecls() later
2525 rest_of_decl_compilation(fn_decl
, NULL
, /*toplevel*/1, /*atend*/0); // http://www.tldp.org/HOWTO/GCC-Frontend-HOWTO-7.html
2526 make_decl_rtl (fn_decl
, NULL
); // %% needed?
2528 rest_of_decl_compilation(fn_decl
, /*toplevel*/1, /*atend*/0);
2530 // ... has this here, but with more args...
2532 DECL_INITIAL( fn_decl
) = error_mark_node
; // Just doing what they tell me to do...
2534 IRState::initFunctionStart(fn_decl
, loc
);
2535 #if D_NO_TRAMPOLINES
2536 /* If this is a member function that nested (possibly indirectly) in another
2537 function, construct an expession for this member function's static chain
2538 by going through parent link of nested classes.
2540 if (ad
&& (cd
= ad
->isClassDeclaration()) && ! (static_chain_expr
2545 /* D 2.0 Closures: this->vthis is passed as a normal parameter and
2546 is valid to access as Stree before the closure frame is created. */
2547 tree t
= vthis
->toSymbol()->Stree
;
2548 while ( cd
->isNested() ) {
2549 Dsymbol
* d
= cd
->toParent2();
2552 tree vthis_field
= cd
->vthis
->toSymbol()->Stree
;
2553 t
= irs
->component(irs
->indirect(t
), vthis_field
);
2554 FuncDeclaration
* f
;
2555 if ( (f
= d
->isFuncDeclaration() )) {
2557 if (! needs_static_chain
)
2565 static_chain_expr
= t
;
2568 } else if ( (cd
= d
->isClassDeclaration()) ) {
2578 cfun
->naked
= naked
? 1 : 0;
2581 // Must be done before expand_function_start.
2582 cfun
->static_chain_expr
= static_chain_expr
;
2584 expand_function_start (fn_decl
, 0);
2586 /* If this function is the C `main', emit a call to `__main'
2587 to run global initializers, etc. */
2588 if (linkage
== LINKc
&&
2589 DECL_ASSEMBLER_NAME (fn_decl
)
2590 && MAIN_NAME_P (DECL_ASSEMBLER_NAME (fn_decl
)) // other langs use DECL_NAME..
2591 && DECL_FILE_SCOPE_P (fn_decl
)
2593 expand_main_function ();
2596 //cfun->x_whole_function_mode_p = 1; // %% I gues...
2597 //cfun->function_frequency = ; // %% it'd be nice to do something with this..
2598 //need DECL_RESULT ?
2600 // Start a binding level for the function/arguments
2601 (*lang_hooks
.decls
.pushlevel
) (0);
2602 expand_start_bindings (2);
2604 // Add the argument declarations to the symbol table for the back end
2605 set_decl_binding_chain( DECL_ARGUMENTS( fn_decl
));
2607 // %% TREE_ADDRESSABLE and TREE_USED...
2609 // Start a binding level for the function body
2610 //(*lang_hooks.decls.pushlevel) (0);
2613 irs
->pushStatementList();
2617 irs
->doLineNote(loc
);
2620 if (static_chain_expr
) {
2621 cfun
->custom_static_chain
= 1;
2622 irs
->doExp( build2(MODIFY_EXPR
, ptr_type_node
,
2623 build0( STATIC_CHAIN_DECL
, ptr_type_node
), static_chain_expr
) );
2628 if (static_chain_expr
|| closure_expr
)
2629 irs
->useParentClosure();
2633 if (! DECL_P(closure_expr
)) {
2634 tree c
= irs
->localVar(ptr_type_node
);
2635 DECL_INITIAL(c
) = closure_expr
;
2639 irs
->useClosure(closure_func
, closure_expr
);
2642 buildClosure(irs
); // may change irs->closureLink and irs->closureFunc
2646 irs
->emitLocalVar(vresult
);
2650 tree var
= irs
->var(v_argptr
);
2651 tree init_exp
= irs
->buildCall(void_type_node
,
2652 irs
->addressOf( built_in_decls
[BUILT_IN_VA_START
] ),
2653 tree_cons(NULL_TREE
, irs
->addressOf(var
),
2654 tree_cons( NULL_TREE
, parm_decl
, NULL_TREE
)));
2655 tree cleanup
= irs
->buildCall(void_type_node
,
2656 irs
->addressOf( built_in_decls
[BUILT_IN_VA_END
] ),
2657 tree_cons(NULL_TREE
, irs
->addressOf(var
), NULL_TREE
));
2658 v_argptr
->init
= NULL
; // VoidInitializer?
2659 irs
->emitLocalVar(v_argptr
, true);
2662 /* Note: cleanup will not run if v_argptr is a closure variable.
2663 Probably okay for now because va_end doesn't do anything for any
2666 if (! v_argptr
->toSymbol()->SclosureField
)
2669 expand_decl_cleanup(var
, cleanup
);
2670 expand_expr_stmt_value(init_exp
, 0, 1);
2673 irs
->pushStatementList();
2676 if (v_arguments_var
)
2677 irs
->emitLocalVar(v_arguments_var
, true);
2679 Statement
* the_body
= fbody
;
2680 if (isSynchronized()) {
2681 AggregateDeclaration
* asym
;
2682 ClassDeclaration
* sym
;
2684 if ( (asym
= isMember()) && (sym
= asym
->isClassDeclaration()) ) {
2685 if (vthis
!= NULL
) {
2686 VarExp
* ve
= new VarExp(fbody
->loc
, vthis
);
2687 the_body
= new SynchronizedStatement(fbody
->loc
, ve
, fbody
);
2689 if (!sym
->vclassinfo
)
2690 sym
->vclassinfo
= new ClassInfoDeclaration(sym
);
2691 Expression
* e
= new VarExp(fbody
->loc
, sym
->vclassinfo
);
2692 e
= new AddrExp(fbody
->loc
, e
);
2693 e
->type
= sym
->type
;
2694 the_body
= new SynchronizedStatement(fbody
->loc
, e
, fbody
);
2697 error("synchronized function %s must be a member of a class", toChars());
2700 the_body
->toIR(irs
);
2702 if (this_sym
->otherNestedFuncs
)
2704 for (unsigned i
= 0; i
< this_sym
->otherNestedFuncs
->dim
; ++i
)
2706 ((FuncDeclaration
*) this_sym
->otherNestedFuncs
->data
[i
])->toObjFile(false);
2711 /* Users of inline assembler statements expect to be able to leave
2712 the result in ST(0). Because GCC does not know about this, it
2713 will load NaN before generating the return instruction.
2715 Solve this by faking an instruction that we claim loads a value
2716 into ST(0), make GCC store it into a temp variable, and then
2717 return the temp variable.
2719 When optimization is turned on, this whole process results in
2722 /* This would apply to complex types as well, but GDC currently
2723 returns complex types as a struct instead of in ST(0) and ST(1).
2725 if (inlineAsm
&& ! naked
&& type
->nextOf()->isfloating() &&
2726 ! type
->nextOf()->iscomplex())
2728 tree result_var
= irs
->localVar(TREE_TYPE(result_decl
));
2730 tree nop_str
= build_string(0, "");
2731 tree cns_str
= build_string(2, "=t");
2732 tree out_arg
= tree_cons(tree_cons(NULL_TREE
, cns_str
, NULL_TREE
),
2733 result_var
, NULL_TREE
);
2735 irs
->expandDecl(result_var
);
2736 irs
->doAsm(nop_str
, out_arg
, NULL_TREE
, NULL_TREE
);
2737 irs
->doReturn( build(MODIFY_EXPR
, TREE_TYPE(result_decl
),
2738 result_decl
, result_var
) );
2745 tree body
= irs
->popStatementList();
2746 tree var
= irs
->var(v_argptr
);
2747 tree init_exp
= irs
->buildCall(void_type_node
,
2748 irs
->addressOf( built_in_decls
[BUILT_IN_VA_START
] ),
2749 tree_cons(NULL_TREE
, irs
->addressOf(var
),
2750 tree_cons( NULL_TREE
, parm_decl
, NULL_TREE
)));
2751 v_argptr
->init
= NULL
; // VoidInitializer?
2752 irs
->emitLocalVar(v_argptr
, true);
2753 irs
->addExp(init_exp
);
2755 tree cleanup
= irs
->buildCall(void_type_node
,
2756 irs
->addressOf( built_in_decls
[BUILT_IN_VA_END
] ),
2757 tree_cons(NULL_TREE
, irs
->addressOf(var
), NULL_TREE
));
2758 irs
->addExp( build2( TRY_FINALLY_EXPR
, void_type_node
, body
, cleanup
));
2765 expand_function_end ();
2766 block
= (*lang_hooks
.decls
.poplevel
) (1, 0, 1);
2768 DECL_SAVED_TREE(fn_decl
) = irs
->popStatementList();
2770 /* In tree-nested.c, init_tmp_var expects a statement list to come
2771 from somewhere. popStatementList returns expressions when
2772 there is a single statement. This code creates a statemnt list
2773 unconditionally because the DECL_SAVED_TREE will always be a
2778 tree body
= DECL_SAVED_TREE(fn_decl
);
2781 gcc_assert(TREE_CODE(body
) == BIND_EXPR
);
2783 t
= TREE_OPERAND(body
, 1);
2784 if (TREE_CODE(t
) != STATEMENT_LIST
) {
2785 tree sl
= alloc_stmt_list();
2786 append_to_statement_list_force(t
, & sl
);
2787 TREE_OPERAND(body
, 1) = sl
;
2788 } else if (! STATEMENT_LIST_HEAD(t
)) {
2789 /* For empty functions: Without this, there is a
2790 segfault when inlined. Seen on build=ppc-linux but
2791 not others (why?). */
2792 append_to_statement_list_force(
2793 build1(RETURN_EXPR
,void_type_node
,NULL_TREE
), & t
);
2797 //block = (*lang_hooks.decls.poplevel) (1, 0, 1);
2798 block
= poplevel(1, 0, 1);
2801 DECL_INITIAL (fn_decl
) = block
; // %% redundant, see poplevel
2802 BLOCK_SUPERCONTEXT( DECL_INITIAL (fn_decl
) ) = fn_decl
; // done in C, don't know effect
2805 expand_end_bindings (NULL_TREE
, 0, 1);
2807 if (! errorcount
&& ! global
.errors
)
2808 genericize_function (fn_decl
);
2811 this_sym
->outputStage
= Finished
;
2812 if (! errorcount
&& ! global
.errors
)
2813 g
.ofile
->outputFunction(this);
2816 //rest_of_compilation( fn_decl );
2817 if (gen
.functionNeedsChain(this))
2818 pop_function_context();
2820 current_function_decl
= NULL_TREE
; // must come before endFunction
2822 g
.irs
->endFunction();
2824 flag_omit_frame_pointer
= saved_omit_frame_pointer
;
2826 current_function_decl
= old_current_function_decl
; // must come before endFunction
2836 FuncDeclaration::buildClosure(IRState
* irs
)
2838 FuncFrameInfo
* ffi
= irs
->getFrameInfo(this);
2839 if (! ffi
->creates_closure
)
2842 tree closure_rec_type
= make_node(RECORD_TYPE
);
2843 tree ptr_field
= build_decl(FIELD_DECL
, get_identifier("__closptr"), ptr_type_node
);
2844 DECL_CONTEXT(ptr_field
) = closure_rec_type
;
2846 fields
.chain(ptr_field
);
2848 for (unsigned i
= 0; i
< closureVars
.dim
; ++i
)
2850 VarDeclaration
*v
= (VarDeclaration
*)closureVars
.data
[i
];
2851 tree field
= build_decl(FIELD_DECL
,
2852 v
->ident
? get_identifier(v
->ident
->string
) : NULL_TREE
,
2853 gen
.trueDeclarationType(v
));
2854 v
->toSymbol()->SclosureField
= field
;
2855 g
.ofile
->setDeclLoc( field
, v
);
2856 DECL_CONTEXT(field
) = closure_rec_type
;
2857 fields
.chain(field
);
2859 TYPE_FIELDS(closure_rec_type
) = fields
.head
;
2860 layout_type(closure_rec_type
);
2862 ffi
->closure_rec
= closure_rec_type
;
2864 tree closure_ptr
= irs
->localVar(build_pointer_type(closure_rec_type
));
2865 DECL_NAME(closure_ptr
) = get_identifier("__closptr");
2866 DECL_ARTIFICIAL(closure_ptr
) = DECL_IGNORED_P(closure_ptr
) = 0;
2868 tree arg
= d_convert_basic(Type::tsize_t
->toCtype(),
2869 TYPE_SIZE_UNIT(closure_rec_type
));
2871 DECL_INITIAL(closure_ptr
) =
2872 irs
->nop(irs
->libCall(LIBCALL_ALLOCMEMORY
, 1, & arg
),
2873 TREE_TYPE(closure_ptr
));
2874 irs
->expandDecl(closure_ptr
);
2876 // set the first entry to the parent closure, if any
2877 tree cl
= irs
->closureLink();
2879 irs
->doExp(irs
->vmodify(irs
->component(irs
->indirect(closure_ptr
),
2882 // copy parameters that are referenced nonlocally
2883 for (unsigned i
= 0; i
< closureVars
.dim
; i
++)
2885 VarDeclaration
*v
= (VarDeclaration
*)closureVars
.data
[i
];
2887 if (! v
->isParameter())
2890 Symbol
* vsym
= v
->toSymbol();
2891 irs
->doExp(irs
->vmodify(irs
->component(irs
->indirect(closure_ptr
),
2892 vsym
->SclosureField
), vsym
->Stree
));
2895 irs
->useClosure(this, closure_ptr
);
2901 Module::genobjfile(int multiobj
)
2903 /* Normally would create an ObjFile here, but gcc is limited to one obj file
2904 per pass and there may be more than one module per obj file. */
2907 g
.ofile
->beginModule(this);
2910 for (unsigned i
= 0; i
< members
->dim
; i
++) {
2911 Dsymbol
* dsym
= (Dsymbol
*) members
->data
[i
];
2913 dsym
->toObjFile(multiobj
);
2917 if (needModuleInfo()) {
2919 ModuleInfo
& mi
= * g
.mi();
2922 sctor
= g
.ofile
->doFunctionToCallFunctions("*__modctor", & mi
.ctors
)->toSymbol();
2924 sdtor
= g
.ofile
->doFunctionToCallFunctions("*__moddtor", & mi
.dtors
)->toSymbol();
2925 if (mi
.unitTests
.dim
)
2926 stest
= g
.ofile
->doFunctionToCallFunctions("*__modtest", & mi
.unitTests
)->toSymbol();
2932 g
.ofile
->endModule();
2935 // This is not used for GCC
2936 unsigned Type::totym() { return 0; }
2942 case Tvoid
: return void_type_node
;
2943 case Tint8
: return intQI_type_node
;
2944 case Tuns8
: return unsigned_intQI_type_node
;
2945 case Tint16
: return intHI_type_node
;
2946 case Tuns16
: return unsigned_intHI_type_node
;
2947 case Tint32
: return intSI_type_node
;
2948 case Tuns32
: return unsigned_intSI_type_node
;
2949 case Tint64
: return intDI_type_node
;
2950 case Tuns64
: return unsigned_intDI_type_node
;
2951 case Tfloat32
: return float_type_node
;
2952 case Tfloat64
: return double_type_node
;
2953 case Tfloat80
: return long_double_type_node
;
2954 case Tcomplex32
: return complex_float_type_node
;
2955 case Tcomplex64
: return complex_double_type_node
;
2956 case Tcomplex80
: return complex_long_double_type_node
;
2958 if (int_size_in_bytes( boolean_type_node
) == 1)
2959 return boolean_type_node
;
2960 // else, drop through
2962 ctype
= make_unsigned_type(1);
2963 TREE_SET_CODE(ctype
, BOOLEAN_TYPE
);
2964 assert(int_size_in_bytes( ctype
) == 1);
2968 ctype
= build_type_copy( unsigned_intQI_type_node
);
2971 ctype
= build_type_copy( unsigned_intHI_type_node
);
2974 ctype
= build_type_copy( unsigned_intSI_type_node
);
2977 ctype
= build_type_copy( float_type_node
);
2980 ctype
= build_type_copy( double_type_node
);
2983 ctype
= build_type_copy( long_double_type_node
);
2986 case Terror
: return error_mark_node
;
2988 /* We can get Tident with forward references. There seems to
2989 be a legitame case (dstress:debug_info_03). I have not seen this
2990 happen for an error, so maybe it's okay...
2992 A way to handle this would be to partially construct
2993 function types and not complete it until it was actually
2995 case Tident
: return void_type_node
;
2998 ::error("unexpected call to Type::toCtype() for %s\n", this->toChars());
3006 // This is not used for GCC
3007 type
* Type::toCParamtype() { return 0; }
3008 // This is not used for GCC
3009 Symbol
* Type::toSymbol() { return 0; }
3012 apply_type_attributes(Expressions
* attrs
, tree
& type_node
, bool in_place
= false)
3015 decl_attributes(& type_node
, gen
.attributes(attrs
),
3016 in_place
? ATTR_FLAG_TYPE_IN_PLACE
: 0);
3020 TypeTypedef::toCtype()
3022 // %%TODO: create info for debugging
3023 tree type_node
= sym
->basetype
->toCtype();
3024 apply_type_attributes(sym
->attributes
, type_node
);
3027 tree type_decl = build_decl(TYPE_DECL, get_identifier( sym->ident->string ),
3029 DECL_CONTEXT( type_decl ) =
3030 rest_of_decl_compilation(type_decl, NULL, ?context?, 0); //%% flag
3035 TypeTypedef::toCParamtype()
3041 TypedefDeclaration::toDebug()
3050 tree enum_mem_type_node
= sym
->memtype
->toCtype();
3052 ctype
= make_node( ENUMERAL_TYPE
);
3053 // %% c-decl.c: if (flag_short_enums) TYPE_PACKED(enumtype) = 1;
3054 TYPE_PRECISION( ctype
) = size(0) * 8;
3055 TYPE_SIZE( ctype
) = 0; // as in c-decl.c
3056 apply_type_attributes(sym
->attributes
, ctype
, true);
3058 /* Because minval and maxval are of this type,
3059 ctype needs to be completed enough for
3060 build_int_cst to work properly. */
3061 TYPE_MIN_VALUE( ctype
) = sym
->minval
->toElem(& gen
);
3062 TYPE_MAX_VALUE( ctype
) = sym
->maxval
->toElem(& gen
);
3064 TYPE_MIN_VALUE( ctype
) = gen
.integerConstant(sym
->minval
, enum_mem_type_node
);
3065 TYPE_MAX_VALUE( ctype
) = gen
.integerConstant(sym
->maxval
, enum_mem_type_node
);
3067 layout_type( ctype
);
3068 TREE_UNSIGNED( ctype
) = isunsigned() != 0; // layout_type can change this
3070 // Move this to toDebug() ?
3071 ListMaker enum_values
;
3073 for (unsigned i
= 0; i
< sym
->members
->dim
; i
++) {
3074 EnumMember
* member
= (EnumMember
*) sym
->members
->data
[i
];
3078 ident
= concat(sym
->ident
->string
, ".",
3079 member
->ident
->string
, NULL
);
3081 ident
= (char *) member
->ident
->string
;
3083 enum_values
.cons( get_identifier(ident
),
3084 gen
.integerConstant(member
->value
->toInteger(), ctype
) );
3090 TYPE_VALUES( ctype
) = enum_values
.head
;
3092 g
.ofile
->initTypeDecl(ctype
, sym
);
3093 g
.ofile
->declareType(ctype
, sym
);
3099 TypeStruct::toCtype()
3102 // need to set this right away in case of self-references
3103 ctype
= make_node( sym
->isUnionDeclaration() ? UNION_TYPE
: RECORD_TYPE
);
3105 TYPE_LANG_SPECIFIC( ctype
) = build_d_type_lang_specific(this);
3107 /* %% copied from AggLayout::finish -- also have to set the size
3108 for (indirect) self-references. */
3110 /* Must set up the overall size, etc. before determining the
3111 context or laying out fields as those types may make references
3113 TYPE_SIZE( ctype
) = bitsize_int( sym
->structsize
* BITS_PER_UNIT
);
3114 TYPE_SIZE_UNIT( ctype
) = size_int( sym
->structsize
);
3115 TYPE_ALIGN( ctype
) = sym
->alignsize
* BITS_PER_UNIT
; // %%doc int, not a tree
3116 // TYPE_ALIGN_UNIT is not an lvalue
3117 TYPE_PACKED ( ctype
) = TYPE_PACKED ( ctype
); // %% todo
3118 apply_type_attributes(sym
->attributes
, ctype
, true);
3119 compute_record_mode ( ctype
);
3121 // %% stor-layout.c:finalize_type_size ... it's private to that file
3123 TYPE_CONTEXT( ctype
) = gen
.declContext(sym
);
3125 g
.ofile
->initTypeDecl(ctype
, sym
);
3127 AggLayout
agg_layout(sym
, ctype
);
3130 /* On PowerPC 64, GCC may not always clear the padding at the end
3131 of the struct. Adding 32-bit words at the end helps. */
3132 if (global
.params
.isX86_64
&& ! sym
->isUnionDeclaration() && sym
->fields
.dim
)
3136 VarDeclaration
* last_decl
= ((VarDeclaration
*)(sym
->fields
.data
[sym
->fields
.dim
-1]));
3137 ofs
= last_decl
->offset
+ last_decl
->size(0);
3141 while (ofs
< sym
->structsize
&& sym
->structsize
- ofs
>= 4)
3143 tree f
= build_decl(FIELD_DECL
, get_identifier("_pad"), d_type_for_size(32, 1));
3144 DECL_FCONTEXT( f
) = ctype
;
3145 DECL_ARTIFICIAL( f
) = DECL_IGNORED_P( f
) = 1;
3146 DECL_IGNORED_P( f
) = 1;
3147 agg_layout
.addField(f
, ofs
);
3152 agg_layout
.finish(sym
->attributes
);
3158 StructDeclaration::toDebug()
3160 tree ctype
= type
->toCtype();
3161 g
.ofile
->addAggMethods(ctype
, this);
3162 g
.ofile
->declareType(ctype
, this);
3165 Symbol
* TypeClass::toSymbol() { return sym
->toSymbol(); }
3167 unsigned TypeFunction::totym() { return 0; } // Unused
3170 TypeFunction::toCtype() {
3171 // %%TODO: If x86, and D linkage, use regparm(1)
3174 ListMaker type_list
;
3177 // Function type can be reference by parameters, etc. Set ctype early.
3178 ctype
= make_node(FUNCTION_TYPE
);
3180 if (varargs
== 1 && linkage
== LINKd
) {
3181 // hidden _arguments parameter
3183 type_list
.cons( Type::typeinfotypelist
->type
->toCtype() );
3185 type_list
.cons( Type::typeinfo
->type
->arrayOf()->toCtype() );
3190 size_t n_args
= Argument::dim(parameters
);
3191 for (size_t i
= 0; i
< n_args
; i
++) {
3192 Argument
* arg
= Argument::getNth(parameters
, i
);
3193 type_list
.cons( IRState::trueArgumentType(arg
) );
3197 /* Last parm if void indicates fixed length list (as opposed to
3198 printf style va_* list). */
3200 type_list
.cons( void_type_node
);
3203 ret_type
= next
->toCtype();
3205 ret_type
= void_type_node
;
3208 TREE_TYPE( ctype
) = ret_type
;
3209 TYPE_ARG_TYPES( ctype
) = type_list
.head
;
3212 if (linkage
== LINKwindows
)
3213 ctype
= gen
.addTypeAttribute(ctype
, "stdcall");
3215 #ifdef D_DMD_CALLING_CONVENTIONS
3217 /* Setting this on all targets. TARGET_RETURN_IN_MEMORY has precedence
3218 over this attribute. So, only targets on which flag_pcc_struct_return
3219 is considered will be affected. */
3220 if ( (linkage
== LINKd
&& next
->size() <= 8) ||
3221 (next
&& next
->toBasetype()->ty
== Tarray
))
3222 ctype
= gen
.addTypeAttribute(ctype
, "no_pcc_struct_return");
3225 if (linkage
== LINKd
&& ! TARGET_64BIT
)
3226 ctype
= gen
.addTypeAttribute(ctype
, "regparm", integer_one_node
);
3235 TypeFunction::retStyle()
3237 /* Need the ctype to determine this, but this is called from
3238 the front end before semantic processing is finished. An
3239 accurate value is not currently needed anyway. */
3244 TypeSArray::toCtype()
3247 if (dim
->isConst() && dim
->type
->isintegral()) {
3248 uinteger_t size
= dim
->toUInteger();
3251 gcc_assert(! next
->isbit());
3254 if (next
->toBasetype()->ty
== Tvoid
)
3255 ctype
= gen
.arrayType(Type::tuns8
, size
);
3257 ctype
= gen
.arrayType(next
, size
);
3260 ::error("invalid expressions for static array dimension: %s", dim
->toChars());
3267 type
*TypeSArray::toCParamtype() { return 0; }
3270 TypeDArray::toCtype()
3273 ctype
= gen
.twoFieldType(Type::tsize_t
, next
->pointerTo(), this,
3279 TypeAArray::toCtype()
3283 IRState::convertForCondition
3290 /* Library functions expect a struct-of-pointer which could be passed
3291 differently from a pointer. */
3292 static tree aa_type
= NULL_TREE
;
3295 aa_type
= make_node( RECORD_TYPE
);
3296 tree f0
= build_decl(FIELD_DECL
, get_identifier("ptr"), ptr_type_node
);
3297 DECL_CONTEXT(f0
) = aa_type
;
3298 TYPE_FIELDS(aa_type
) = f0
;
3299 layout_type(aa_type
);
3309 TypePointer::toCtype()
3312 ctype
= build_pointer_type( next
->toCtype() );
3317 TypeMaybe::toCtype()
3320 ctype
= next
->toCtype();
3325 TypeDelegate::toCtype()
3328 assert(next
->toBasetype()->ty
== Tfunction
);
3329 ctype
= gen
.twoFieldType(Type::tvoid
->pointerTo(), next
->pointerTo(),
3330 this, "object", "func");
3336 /* Create debug information for a ClassDeclaration's inheritance tree.
3337 Interfaces are not included. */
3339 binfo_for(tree tgt_binfo
, ClassDeclaration
* cls
)
3343 make_tree_vec(BINFO_ELTS
)
3348 TREE_TYPE (binfo
) = TREE_TYPE( cls
->type
->toCtype() ); // RECORD_TYPE, not REFERENCE_TYPE
3349 BINFO_INHERITANCE_CHAIN(binfo
) = tgt_binfo
;
3350 BINFO_OFFSET (binfo
) = size_zero_node
; // %% type?, otherwize, integer_zero_node
3352 if (cls
->baseClass
) {
3354 BINFO_BASETYPES(binfo
) = make_tree_vec(1);
3355 BINFO_BASETYPE(binfo
, 0) = binfo_for(binfo
, cls
->baseClass
);
3357 BINFO_BASE_APPEND(binfo
, binfo_for(binfo
, cls
->baseClass
));
3359 #ifdef BINFO_BASEACCESSES
3361 #error update vector stuff
3365 BINFO_BASEACCESSES(binfo
) = make_tree_vec(1);
3366 switch ( ((BaseClass
*) cls
->baseclasses
.data
[0])->protection
) {
3368 prot_tree
= access_public_node
;
3371 prot_tree
= access_protected_node
;
3374 prot_tree
= access_private_node
;
3377 prot_tree
= access_public_node
;
3380 BINFO_BASEACCESS(binfo
,0) = prot_tree
;
3387 /* Create debug information for an InterfaceDeclaration's inheritance
3388 tree. In order to access all inherited methods in the debugger,
3389 the entire tree must be described.
3391 This function makes assumptions about inherface layout. */
3393 intfc_binfo_for(tree tgt_binfo
, ClassDeclaration
* iface
, unsigned & inout_offset
)
3397 make_tree_vec(BINFO_ELTS
)
3399 make_tree_binfo(iface
->baseclasses
.dim
)
3402 TREE_TYPE (binfo
) = TREE_TYPE( iface
->type
->toCtype() ); // RECORD_TYPE, not REFERENCE_TYPE
3403 BINFO_INHERITANCE_CHAIN(binfo
) = tgt_binfo
;
3404 BINFO_OFFSET (binfo
) = size_int(inout_offset
* PTRSIZE
);
3406 if (iface
->baseclasses
.dim
) {
3408 BINFO_BASETYPES(binfo
) = make_tree_vec(iface
->baseclasses
.dim
);
3410 #ifdef BINFO_BASEACCESSES
3411 BINFO_BASEACCESSES(binfo
) = make_tree_vec(iface
->baseclasses
.dim
);
3414 for (unsigned i
= 0; i
< iface
->baseclasses
.dim
; i
++) {
3415 BaseClass
* bc
= (BaseClass
*) iface
->baseclasses
.data
[i
];
3421 BINFO_BASETYPE(binfo
, i
) = intfc_binfo_for(binfo
, bc
->base
, inout_offset
);
3423 BINFO_BASE_APPEND(binfo
, intfc_binfo_for(binfo
, bc
->base
, inout_offset
));
3425 #ifdef BINFO_BASEACCESSES
3427 switch ( bc
->protection
) {
3429 prot_tree
= access_public_node
;
3432 prot_tree
= access_protected_node
;
3435 prot_tree
= access_private_node
;
3438 prot_tree
= access_public_node
;
3441 BINFO_BASEACCESS(binfo
, i
) = prot_tree
;
3449 TypeClass::toCtype()
3453 Array base_class_decls
;
3454 bool inherited
= sym
->baseClass
!= 0;
3458 /* Need to set ctype right away in case of self-references to
3459 the type during this call. */
3460 rec_type
= make_node( RECORD_TYPE
);
3461 //apply_type_attributes(sym->attributes, rec_type, true);
3462 ctype
= build_reference_type( rec_type
);
3463 dkeep(ctype
); // because BINFO moved out to toDebug
3464 g
.ofile
->initTypeDecl(rec_type
, sym
);
3466 obj_rec_type
= TREE_TYPE( gen
.getObjectType()->toCtype() );
3468 // Note that this is set on the reference type, not the record type.
3469 TYPE_LANG_SPECIFIC( ctype
) = build_d_type_lang_specific( this );
3471 AggLayout
agg_layout(sym
, rec_type
);
3473 // Most of this silly code is just to produce correct debugging information.
3475 /* gdb apparently expects the vtable field to be named
3476 "_vptr$...." (stabsread.c) Otherwise, the debugger gives
3477 lots of annoying error messages. C++ appends the class
3478 name of the first base witht that field after the '$'. */
3479 /* update: annoying messages might not appear anymore after making
3481 // Add the virtual table pointer
3482 tree decl
= build_decl(FIELD_DECL
, get_identifier("_vptr$"), /*vtbl_type*/d_vtbl_ptr_type_node
);
3483 agg_layout
.addField( decl
, 0 ); // %% target stuff..
3486 vfield
= copy_node( decl
);
3487 DECL_ARTIFICIAL( decl
) = DECL_IGNORED_P( decl
) = 1;
3491 DECL_VIRTUAL_P( vfield
) = 1;
3492 TYPE_VFIELD( rec_type
) = vfield
; // This only seems to affect debug info
3494 if (! sym
->isInterfaceDeclaration()) {
3495 DECL_FCONTEXT( vfield
) = obj_rec_type
;
3499 decl
= build_decl(FIELD_DECL
, get_identifier("_monitor"), ptr_type_node
);
3500 DECL_FCONTEXT( decl
) = obj_rec_type
;
3501 DECL_ARTIFICIAL( decl
) = DECL_IGNORED_P( decl
) = inherited
;
3502 agg_layout
.addField( decl
, PTRSIZE
);
3504 // Add the fields of each base class
3507 ClassDeclaration
* p
= sym
;
3508 while (p
->baseclasses
.dim
) {
3509 p
= ((BaseClass
*) p
->baseclasses
.data
[0])->base
;
3511 DECL_FCONTEXT( vfield
) = TREE_TYPE( p
->type
->toCtype() );
3514 TYPE_CONTEXT( rec_type
) = gen
.declContext(sym
);
3516 agg_layout
.finish(sym
->attributes
);
3523 ClassDeclaration::toDebug()
3525 tree rec_type
= TREE_TYPE( type
->toCtype() );
3526 /* Used to create BINFO even if debugging was off. This was needed to keep
3527 references to inherited types. */
3529 g
.ofile
->addAggMethods(rec_type
, this);
3531 if ( ! isInterfaceDeclaration() )
3532 TYPE_BINFO( rec_type
) = binfo_for(NULL_TREE
, this);
3534 unsigned offset
= 0;
3537 TYPE_BINFO( rec_type
) = intfc_binfo_for(NULL_TREE
, this, offset
);
3540 g
.ofile
->declareType(rec_type
, this);
3544 LabelStatement::toIR(IRState
* irs
)
3546 FuncDeclaration
* func
= irs
->func
;
3547 LabelDsymbol
* label
= isReturnLabel
? func
->returnLabel
: func
->searchLabel(ident
);
3548 tree t
= irs
->getLabelTree( label
);
3552 if (label
->asmLabelNum
)
3553 d_expand_priv_asm_label(irs
, label
->asmLabelNum
);
3555 if (isReturnLabel
&& func
->fensure
)
3556 func
->fensure
->toIR(irs
);
3558 statement
->toIR(irs
);
3560 // else, there was an error
3564 GotoStatement::toIR(IRState
* irs
)
3566 g
.ofile
->setLoc(loc
); /* This makes the 'undefined label' error show up on the correct line...
3567 The extra doLineNote in doJump shouldn't cause a problem. */
3568 tree t
= irs
->getLabelTree( label
);
3570 irs
->doJump(this, t
);
3571 // else, there was an error
3575 GotoCaseStatement::toIR(IRState
* irs
)
3577 // assumes cblocks have been set in SwitchStatement::toIR
3578 irs
->doJump(this, cs
->cblock
);
3582 GotoDefaultStatement::toIR(IRState
* irs
)
3584 // assumes cblocks have been set in SwitchStatement::toIR
3585 irs
->doJump(this, sw
->sdefault
->cblock
);
3589 SwitchErrorStatement::toIR(IRState
* irs
)
3591 irs
->doLineNote( loc
);
3592 irs
->doExp( irs
->assertCall(loc
, LIBCALL_SWITCH_ERROR
) );
3596 VolatileStatement::toIR(IRState
* irs
)
3598 irs
->pushVolatile();
3599 statement
->toIR( irs
);
3604 ThrowStatement::toIR(IRState
* irs
)
3606 ClassDeclaration
* class_decl
= exp
->type
->toBasetype()->isClassHandle();
3607 // Front end already checks for isClassHandle
3608 InterfaceDeclaration
* intfc_decl
= class_decl
->isInterfaceDeclaration();
3610 tree arg
= exp
->toElem(irs
);
3613 if ( ! intfc_decl
->isCOMclass()) {
3614 arg
= irs
->convertTo(arg
, exp
->type
, irs
->getObjectType());
3616 error("cannot throw COM interfaces");
3620 irs
->doLineNote(loc
);
3621 irs
->doExp( irs
->libCall(LIBCALL_THROW
, 1, & arg
) );
3622 // %%TODO: somehow indicate flow stops here? -- set attribute noreturn on _d_throw
3626 TryFinallyStatement::toIR(IRState
* irs
)
3628 // %% doc: this is not the same as a start_eh/end_eh_cleanup sequence
3629 tree t_body
= body
? irs
->makeStmtExpr(body
) : d_void_zero_node
;
3630 tree t_finl
= finalbody
? irs
->makeStmtExpr(finalbody
) : d_void_zero_node
;
3631 tree tf
= build(TRY_FINALLY_EXPR
, void_type_node
, t_body
, t_finl
);
3632 // TREE_SIDE_EFFECTS(tf) = 1; // probably not needed
3633 irs
->doLineNote(loc
);
3638 TryCatchStatement::toIR(IRState
* irs
)
3640 irs
->doLineNote(loc
);
3641 irs
->startTry(this);
3644 irs
->startCatches();
3646 for (unsigned i
= 0; i
< catches
->dim
; i
++) {
3647 Catch
* a_catch
= (Catch
*) catches
->data
[i
];
3649 irs
->startCatch(a_catch
->type
->toCtype()); //expand_start_catch( xxx );
3651 irs
->doLineNote(a_catch
->loc
);
3654 if ( a_catch
->var
) {
3655 tree exc_obj
= irs
->convertTo(irs
->exceptionObject(),
3656 irs
->getObjectType(), a_catch
->type
);
3657 // need to override initializer...
3658 // set DECL_INITIAL now and emitLocalVar will know not to change it
3659 DECL_INITIAL( a_catch
->var
->toSymbol()->Stree
) = exc_obj
;
3660 irs
->emitLocalVar(a_catch
->var
);
3663 if (a_catch
->handler
)
3664 a_catch
->handler
->toIR(irs
);
3673 OnScopeStatement::toIR(IRState
*)
3679 WithStatement::toIR(IRState
* irs
)
3683 irs
->emitLocalVar(wthis
);
3692 SynchronizedStatement::toIR(IRState
* irs
)
3695 InterfaceDeclaration
* iface
;
3697 irs
->startBindings();
3698 tree decl
= irs
->localVar(IRState::getObjectType());
3700 DECL_IGNORED_P( decl
) = 1;
3701 tree cleanup
= irs
->libCall(LIBCALL_MONITOREXIT
, 1, & decl
);
3702 // assuming no conversions needed
3705 assert(exp
->type
->toBasetype()->ty
== Tclass
);
3706 iface
= ((TypeClass
*) exp
->type
->toBasetype())->sym
->isInterfaceDeclaration();
3708 if (! iface
->isCOMclass()) {
3709 init_exp
= irs
->convertTo(exp
, irs
->getObjectType());
3711 error("cannot synchronize on a COM interface");
3712 init_exp
= error_mark_node
;
3715 init_exp
= exp
->toElem(irs
);
3718 DECL_INITIAL(decl
) = init_exp
;
3720 irs
->doLineNote(loc
);
3723 irs
->expandDecl(decl
);
3724 irs
->doExp( irs
->libCall(LIBCALL_MONITORENTER
, 1, & decl
));
3725 expand_decl_cleanup(decl
, cleanup
); // nope,nope just do it diffrent ways or just jump the cleanup like below..
3729 irs
->expandDecl(decl
);
3730 irs
->doExp( irs
->libCall(LIBCALL_MONITORENTER
, 1, & decl
));
3731 irs
->startTry(this);
3734 irs
->startFinally();
3735 irs
->doExp( cleanup
);
3740 #ifndef D_CRITSEC_SIZE
3741 #define D_CRITSEC_SIZE 64
3743 static tree critsec_type
= 0;
3745 if (! critsec_type
) {
3746 critsec_type
= irs
->arrayType(Type::tuns8
, D_CRITSEC_SIZE
);
3749 tree critsec_decl
= build_decl(VAR_DECL
, NULL_TREE
, critsec_type
);
3750 // name is only used to prevent ICEs
3751 g
.ofile
->giveDeclUniqueName(critsec_decl
, "__critsec");
3752 tree critsec_ref
= irs
->addressOf(critsec_decl
); // %% okay to use twice?
3753 dkeep(critsec_decl
);
3755 TREE_STATIC(critsec_decl
) = 1;
3756 TREE_PRIVATE(critsec_decl
) = 1;
3757 DECL_ARTIFICIAL(critsec_decl
) = 1;
3758 DECL_IGNORED_P(critsec_decl
) = 1;
3760 g
.ofile
->rodc(critsec_decl
, 1);
3763 expand_eh_region_start();
3764 expand_expr_stmt_value(irs
->libCall(LIBCALL_CRITICALENTER
, 1, & critsec_ref
), 0, 1);
3767 expand_expr_stmt_value(irs
->libCall(LIBCALL_CRITICALEXIT
, 1, & critsec_ref
), 0, 1);
3768 expand_eh_region_end_cleanup(irs
->libCall(LIBCALL_CRITICALEXIT
, 1, & critsec_ref
));
3770 irs
->startTry(this);
3771 irs
->doExp( irs
->libCall(LIBCALL_CRITICALENTER
, 1, & critsec_ref
) );
3774 irs
->startFinally();
3775 irs
->doExp( irs
->libCall(LIBCALL_CRITICALEXIT
, 1, & critsec_ref
) );
3782 ContinueStatement::toIR(IRState
* irs
)
3784 irs
->doLineNote(loc
);
3785 irs
->continueLoop(ident
);
3789 BreakStatement::toIR(IRState
* irs
)
3791 irs
->doLineNote(loc
);
3792 irs
->exitLoop(ident
);
3796 ReturnStatement::toIR(IRState
* irs
)
3798 irs
->doLineNote(loc
);
3801 if (exp
->type
->toBasetype()->ty
!= Tvoid
) { // %% == Type::tvoid ?
3802 FuncDeclaration
* func
= irs
->func
;
3803 Type
* ret_type
= func
->tintro
?
3804 func
->tintro
->nextOf() : func
->type
->nextOf();
3806 if (func
->isMain() && ret_type
->toBasetype()->ty
== Tvoid
)
3807 ret_type
= Type::tint32
;
3809 tree result_decl
= DECL_RESULT( irs
->func
->toSymbol()->Stree
);
3810 tree result_assign
= build ( MODIFY_EXPR
,
3811 TREE_TYPE( result_decl
), result_decl
,
3812 // %% convert for init -- if we were returning a reference,
3813 // would want to take the address...
3814 irs
->convertForAssignment(exp
, (Type
*)ret_type
) );
3816 irs
->doReturn(result_assign
); // expand_return(result_assign);
3819 irs
->doReturn(NULL_TREE
);
3822 irs
->doReturn(NULL_TREE
);
3827 DefaultStatement::toIR(IRState
* irs
)
3829 irs
->doCase(NULL_TREE
, cblock
);
3831 statement
->toIR( irs
);
3835 CaseStatement::toIR(IRState
* irs
)
3839 if ( exp
->type
->isscalar() )
3840 case_value
= exp
->toElem(irs
);
3842 case_value
= irs
->integerConstant(index
, Type::tint32
);
3843 irs
->doCase(case_value
, cblock
);
3845 statement
->toIR( irs
);
3849 SwitchStatement::toIR(IRState
* irs
)
3852 // %% also what about c-semantics doing emit_nop() ?
3853 irs
->doLineNote( loc
);
3855 cond_tree
= condition
->toElem( irs
);
3857 Type
* cond_type
= condition
->type
->toBasetype();
3858 if (cond_type
->ty
== Tarray
) {
3859 Type
* elem_type
= cond_type
->nextOf()->toBasetype();
3861 switch (elem_type
->ty
) {
3862 case Tchar
: lib_call
= LIBCALL_SWITCH_STRING
; break;
3863 case Twchar
: lib_call
= LIBCALL_SWITCH_USTRING
; break;
3864 case Tdchar
: lib_call
= LIBCALL_SWITCH_DSTRING
; break;
3866 ::error("switch statement value must be an array of some character type, not %s", elem_type
->toChars());
3870 // Apparently the backend is supposed to sort and set the indexes
3871 // on the case array
3872 // have to change them to be useable
3873 cases
->sort(); // %%!!
3875 Symbol
* s
= static_sym();
3876 dt_t
** pdt
= & s
->Sdt
;
3878 for (unsigned case_i
= 0; case_i
< cases
->dim
; case_i
++) {
3879 CaseStatement
* case_stmt
= (CaseStatement
*) cases
->data
[case_i
];
3880 pdt
= case_stmt
->exp
->toDt( pdt
);
3881 case_stmt
->index
= case_i
;
3884 tree p_table
= irs
->addressOf(s
->Stree
);
3887 irs
->darrayVal(cond_type
->arrayOf()->toCtype(), cases
->dim
,
3891 cond_tree
= irs
->libCall(lib_call
, 2, args
);
3892 } else if (! cond_type
->isscalar()) {
3893 ::error("cannot handle switch condition of type %s", cond_type
->toChars());
3897 // Build LABEL_DECLs now so they can be refered to by goto case
3899 for (unsigned i
= 0; i
< cases
->dim
; i
++) {
3900 CaseStatement
* case_stmt
= (CaseStatement
*) cases
->data
[i
];
3901 case_stmt
->cblock
= irs
->label(case_stmt
->loc
); //make_case_label(case_stmt->loc);
3904 sdefault
->cblock
= irs
->label(sdefault
->loc
); //make_case_label(sdefault->loc);
3907 cond_tree
= fold(cond_tree
);
3908 irs
->startCase(this, cond_tree
);
3911 irs
->endCase(cond_tree
);
3916 Statement::toIR(IRState
*)
3918 ::error("Statement::toIR: don't know what to do (%s)", toChars());
3923 IfStatement::toIR(IRState
* irs
)
3927 irs
->emitLocalVar(match
);
3929 irs
->startCond(this, condition
);
3931 ifbody
->toIR( irs
);
3934 elsebody
->toIR ( irs
);
3942 ForeachStatement::toIR(IRState
* irs
)
3944 // %% better?: set iter to start - 1 and use result of increment for condition?
3948 Type
* agg_type
= aggr
->type
->toBasetype();
3949 Type
* elem_type
= agg_type
->nextOf()->toBasetype();
3952 tree iter_init_expr
;
3953 tree aggr_expr
= irs
->maybeMakeTemp( aggr
->toElem(irs
) );
3957 gcc_assert(elem_type
->ty
!= Tbit
);
3960 irs
->startBindings(); /* Variables created by the function will probably
3961 end up in a contour created by emitLocalVar. This
3962 startBindings call is just to be safe */
3963 irs
->doLineNote( loc
);
3969 fprintf(stderr
, "EXPER: I need this\n");
3970 default_loc
= Loc(g
.mod
, 1); // %% fix
3973 if (! value
->loc
.filename
)
3974 g
.ofile
->setDeclLoc( value
->toSymbol()->Stree
, default_loc
);
3976 irs
->emitLocalVar(value
, true);
3979 if (! key
->loc
.filename
)
3980 g
.ofile
->setDeclLoc( key
->toSymbol()->Stree
, default_loc
);
3982 DECL_INITIAL( key
->toSymbol()->Stree
) = op
== TOKforeach
?
3983 irs
->integerConstant(0, key
->type
) :
3984 irs
->arrayLength(aggr_expr
, agg_type
);
3986 irs
->emitLocalVar(key
); // %% getExpInitializer causes uneeded initialization
3990 if (value
->isRef() || value
->isOut()) {
3991 iter_is_value
= true;
3992 iter_decl
= irs
->var(value
);
3994 iter_is_value
= false;
3995 iter_decl
= irs
->localVar(elem_type
->pointerTo());
3996 irs
->expandDecl(iter_decl
);
3999 if ( agg_type
->ty
== Tsarray
) {
4000 bound_expr
= ((TypeSArray
*) agg_type
)->dim
->toElem(irs
);
4001 iter_init_expr
= irs
->addressOf( aggr_expr
);
4002 // Type needs to be pointer-to-element to get pointerIntSum
4004 iter_init_expr
= irs
->nop(iter_init_expr
,
4005 agg_type
->nextOf()->pointerTo()->toCtype());
4007 bound_expr
= irs
->darrayLenRef( aggr_expr
);
4008 iter_init_expr
= irs
->darrayPtrRef( aggr_expr
);
4010 iter_init_expr
= save_expr( iter_init_expr
);
4011 bound_expr
= irs
->pointerIntSum(iter_init_expr
, bound_expr
);
4012 // aggr. isn't supposed to be modified, so...
4013 bound_expr
= save_expr( bound_expr
);
4015 enum tree_code iter_op
= PLUS_EXPR
;
4017 if (op
== TOKforeach_reverse
)
4019 tree t
= iter_init_expr
;
4020 iter_init_expr
= bound_expr
;
4023 iter_op
= MINUS_EXPR
;
4026 tree condition
= build(NE_EXPR
, boolean_type_node
, iter_decl
, bound_expr
);
4028 build(MODIFY_EXPR
, void_type_node
, iter_decl
,
4029 build(iter_op
, TREE_TYPE(iter_decl
), iter_decl
,
4030 size_int(elem_type
->size())));
4032 tree key_decl
= irs
->var(key
);
4033 tree key_incr_expr
=
4034 build(MODIFY_EXPR
, void_type_node
, key_decl
,
4035 build(iter_op
, TREE_TYPE(key_decl
), key_decl
,
4036 irs
->integerConstant(1, TREE_TYPE(key_decl
))));
4037 incr_expr
= irs
->compound(incr_expr
, key_incr_expr
);
4040 irs
->doExp( build(MODIFY_EXPR
, void_type_node
, iter_decl
, iter_init_expr
) );
4042 irs
->startLoop(this);
4043 irs
->exitIfFalse(condition
);
4044 if ( op
== TOKforeach_reverse
)
4045 irs
->doExp( incr_expr
);
4046 if ( ! iter_is_value
)
4047 irs
->doExp( build(MODIFY_EXPR
, void_type_node
, irs
->var(value
),
4048 irs
->indirect(iter_decl
)) );
4051 irs
->continueHere();
4053 if ( op
== TOKforeach
)
4054 irs
->doExp( incr_expr
);
4058 irs
->endBindings(); // not really needed
4065 ForeachRangeStatement::toIR(IRState
* irs
)
4067 bool fwd
= op
== TOKforeach
;
4070 irs
->startBindings(); /* Variables created by the function will probably
4071 end up in a contour created by emitLocalVar. This
4072 startBindings call is just to be safe */
4073 irs
->doLineNote( loc
);
4075 gcc_assert(key
!= NULL
);
4076 gcc_assert(lwr
!= NULL
);
4077 gcc_assert(upr
!= NULL
);
4079 // Front end ensures no storage class
4080 irs
->emitLocalVar(key
, true);
4081 tree key_decl
= irs
->var(key
);
4082 tree lwr_decl
= irs
->localVar(lwr
->type
);
4083 tree upr_decl
= irs
->localVar(upr
->type
);
4084 tree iter_expr
= irs
->vmodify(key_decl
,
4085 build2(fwd
? PLUS_EXPR
: MINUS_EXPR
, TREE_TYPE(key_decl
),
4086 key_decl
, irs
->integerConstant(1, TREE_TYPE(key_decl
))));
4089 irs
->expandDecl(lwr_decl
);
4090 irs
->expandDecl(upr_decl
);
4091 irs
->doExp( irs
->vmodify(lwr_decl
, lwr
->toElem(irs
)) );
4092 irs
->doExp( irs
->vmodify(upr_decl
, upr
->toElem(irs
)) );
4094 condition
= build2(fwd
? LT_EXPR
: GT_EXPR
, boolean_type_node
,
4095 key_decl
, fwd
? upr_decl
: lwr_decl
);
4097 irs
->doExp( irs
->vmodify(key_decl
, fwd
? lwr_decl
: upr_decl
) );
4099 irs
->startLoop(this);
4101 irs
->continueHere();
4102 irs
->exitIfFalse(condition
);
4104 irs
->doExp(iter_expr
);
4108 irs
->continueHere();
4109 irs
->doExp(iter_expr
);
4113 irs
->endBindings(); // not really needed
4120 ForStatement::toIR(IRState
* irs
)
4122 irs
->doLineNote(loc
);
4126 irs
->startLoop(this);
4128 irs
->exitIfFalse(condition
);
4131 irs
->continueHere();
4133 irs
->doExp(increment
->toElem(irs
)); // force side effects?
4138 DoStatement::toIR(IRState
* irs
)
4140 irs
->doLineNote(loc
);
4141 irs
->startLoop(this);
4144 irs
->continueHere();
4145 irs
->exitIfFalse(condition
);
4150 WhileStatement::toIR(IRState
* irs
)
4152 irs
->doLineNote(loc
); // store for next statement...
4153 irs
->startLoop(this);
4154 irs
->continueHere();
4155 irs
->exitIfFalse(condition
, 1); // 1 == is topcond .. good as deprecated..
4162 ScopeStatement::toIR(IRState
* irs
)
4166 statement
->toIR( irs
);
4172 CompoundStatement::toIR(IRState
* irs
)
4175 for (unsigned i
= 0; i
< statements
->dim
; i
++) {
4176 Statement
* statement
= (Statement
*) statements
->data
[i
];
4179 statement
->toIR(irs
);
4185 UnrolledLoopStatement::toIR(IRState
* irs
)
4188 irs
->startLoop(this);
4189 irs
->continueHere();
4190 for (unsigned i
= 0; i
< statements
->dim
; i
++) {
4191 Statement
* statement
= (Statement
*) statements
->data
[i
];
4195 irs
->setContinueLabel( irs
->label(loc
) );
4196 statement
->toIR(irs
);
4197 irs
->continueHere();
4200 irs
->exitLoop(NULL
);
4206 ExpStatement::toIR(IRState
* irs
)
4209 gen
.doLineNote(loc
);
4211 tree exp_tree
= exp
->toElem(irs
);
4213 irs
->doExp(exp_tree
);
4221 PragmaStatement::toIR(IRState
*)
4228 EnumDeclaration::toDebug()
4234 Dsymbol::cvMember(unsigned char*)
4239 EnumDeclaration::cvMember(unsigned char*)
4244 FuncDeclaration::cvMember(unsigned char*)
4249 VarDeclaration::cvMember(unsigned char*)
4254 TypedefDeclaration::cvMember(unsigned char*)
4262 d_expand_expr(tree exp
, rtx target
, enum machine_mode tmode
, int modifier
, rtx
*)
4264 if ( TREE_CODE(exp
) == (enum tree_code
) D_STMT_EXPR
) {
4268 gen
.retrieveStmtExpr(exp
, & stmt
, & irs
);
4269 // need push_temp_slots()?
4271 tree rtl_expr
= expand_start_stmt_expr(1);
4272 // This startBindings call is needed so get_last_insn() doesn't return NULL
4273 // in expand_start_case().
4274 irs
->startBindings();
4275 // preserve_temp_slots as in c-common.c:c_expand_expr
4280 expand_end_stmt_expr (rtl_expr
);
4282 rtx result
= expand_expr (rtl_expr
, target
, tmode
, (enum expand_modifier
) modifier
);
4285 } else if ( TREE_CODE(exp
) == (enum tree_code
) D_ARRAY_SET_EXPR
){
4286 // %% if single byte element, expand to memset
4288 assert( POINTER_TYPE_P( TREE_TYPE( TREE_OPERAND( exp
, 0 ))));
4289 assert( INTEGRAL_TYPE_P( TREE_TYPE( TREE_OPERAND( exp
, 2 ))));
4290 // assuming unsigned source is unsigned
4292 push_temp_slots (); // will this work? maybe expand_start_binding
4293 tree rtl_expr
= expand_start_stmt_expr(1);
4295 do_array_set(g
.irs
, // %% fix!
4296 TREE_OPERAND(exp
, 0), TREE_OPERAND(exp
, 1), TREE_OPERAND(exp
, 2));
4298 expand_end_stmt_expr(rtl_expr
);
4299 rtx result
= expand_expr(rtl_expr
, target
, tmode
, (enum expand_modifier
) modifier
);
4309 void x(tree ptr, tree src, tree count) {
4312 build(BIND_EXPR, count_var, t_loop, block???0
4317 d_build_eh_type_type(tree type
)
4319 TypeClass
* d_type
= (TypeClass
*) IRState::getDType(type
);
4321 d_type
= (TypeClass
*) d_type
->toBasetype();
4322 assert(d_type
->ty
== Tclass
);
4323 return IRState::addressOf( d_type
->sym
->toSymbol()->Stree
);
4326 tree d_void_zero_node
;
4328 tree d_null_pointer
;
4329 tree d_vtbl_ptr_type_node
;
4332 gcc_d_backend_init()
4334 // %% need this here to add the type decls ...
4335 init_global_binding_level();
4337 // This allows the code in d-builtins2 to not have to worry about
4338 // converting (C signed char *) to (D char *) for string arguments of
4339 // built-in functions.
4340 flag_signed_char
= 0;
4341 // This is required or we'll crash pretty early on. %%log
4342 build_common_tree_nodes (flag_signed_char
4348 // This is also required (or the manual equivalent) or crashes
4350 size_type_node
= d_type_for_mode(ptr_mode
, 1);
4352 // c was: TREE_TYPE (identifier_global_value (get_identifier (SIZE_TYPE)));
4353 //signed_size_type_node = c_common_signed_type (size_type_node);
4355 // If this is called after the next statements, you'll get an ICE.
4356 set_sizetype(size_type_node
);
4359 // need this for void.. %% but this crashes... probably need to impl
4360 // some things in dc-lang.cc
4361 build_common_tree_nodes_2 (0 /* %% support the option */);
4363 // Specific to D (but so far all taken from C)
4365 d_void_zero_node
= build_int_2 (0, 0);
4366 TREE_TYPE (d_void_zero_node
) = void_type_node
;
4368 d_void_zero_node
= build_int_cst (void_type_node
, 0);
4370 // %%TODO: we are relying on default boolean_type_node being 8bit / same as Tbit
4372 d_null_pointer
= convert(ptr_type_node
, integer_zero_node
);
4374 TYPE_NAME( integer_type_node
) = build_decl(TYPE_DECL
, get_identifier("int"), integer_type_node
);
4375 TYPE_NAME( char_type_node
) = build_decl(TYPE_DECL
, get_identifier("cchar"), char_type_node
); // "char?"
4377 REALSIZE
= int_size_in_bytes(long_double_type_node
);
4379 PTRSIZE
= int_size_in_bytes(ptr_type_node
);
4380 switch (int_size_in_bytes(size_type_node
)) {
4392 switch ( PTRSIZE
) {
4394 assert(POINTER_SIZE
== 32);
4395 Tptrdiff_t
= Tint32
;
4398 assert(POINTER_SIZE
== 64);
4399 Tptrdiff_t
= Tint64
;
4405 CLASSINFO_SIZE
= 19 * PTRSIZE
;
4407 CLASSINFO_SIZE
= 18 * PTRSIZE
;
4412 if (flag_exceptions
) {
4413 eh_personality_libfunc
= init_one_libfunc(d_using_sjlj_exceptions()
4414 ? "__gdc_personality_sj0" : "__gdc_personality_v0");
4416 default_init_unwind_resume_libfunc ();
4418 lang_eh_runtime_type
= d_build_eh_type_type
;
4419 using_eh_for_cleanups ();
4420 // lang_proctect_cleanup_actions = ...; // no need? ... probably needed for autos
4423 /* copied and modified from cp/decl.c; only way for vtable to work in gdb... */
4424 // or not, I'm feeling very confused...
4426 /* Make sure we get a unique function type, so we can give
4427 its pointer type a name. (This wins for gdb.) */
4428 tree vfunc_type
= make_node (FUNCTION_TYPE
);
4429 TREE_TYPE (vfunc_type
) = Type::tint32
->toCtype(); // integer_type_node; messed up built in types?
4430 TYPE_ARG_TYPES (vfunc_type
) = NULL_TREE
;
4431 layout_type (vfunc_type
);
4433 tree vtable_entry_type
= build_pointer_type (vfunc_type
);
4434 d_vtbl_ptr_type_node
= build_pointer_type(vtable_entry_type
);
4435 layout_type (d_vtbl_ptr_type_node
);// %%TODO: check if needed
4438 // This also allows virtual functions to be called, but when vtbl entries,
4439 // are inspected, function symbol names do not appear.
4440 // d_vtbl_ptr_type_node = Type::tvoid->pointerTo()->pointerTo()->toCtype();
4442 // This is the C main, not the D main
4443 main_identifier_node
= get_identifier ("main");
4447 gcc_d_backend_term()