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 TypeDelegate::toCtype()
3320 assert(next
->toBasetype()->ty
== Tfunction
);
3321 ctype
= gen
.twoFieldType(Type::tvoid
->pointerTo(), next
->pointerTo(),
3322 this, "object", "func");
3328 /* Create debug information for a ClassDeclaration's inheritance tree.
3329 Interfaces are not included. */
3331 binfo_for(tree tgt_binfo
, ClassDeclaration
* cls
)
3335 make_tree_vec(BINFO_ELTS
)
3340 TREE_TYPE (binfo
) = TREE_TYPE( cls
->type
->toCtype() ); // RECORD_TYPE, not REFERENCE_TYPE
3341 BINFO_INHERITANCE_CHAIN(binfo
) = tgt_binfo
;
3342 BINFO_OFFSET (binfo
) = size_zero_node
; // %% type?, otherwize, integer_zero_node
3344 if (cls
->baseClass
) {
3346 BINFO_BASETYPES(binfo
) = make_tree_vec(1);
3347 BINFO_BASETYPE(binfo
, 0) = binfo_for(binfo
, cls
->baseClass
);
3349 BINFO_BASE_APPEND(binfo
, binfo_for(binfo
, cls
->baseClass
));
3351 #ifdef BINFO_BASEACCESSES
3353 #error update vector stuff
3357 BINFO_BASEACCESSES(binfo
) = make_tree_vec(1);
3358 switch ( ((BaseClass
*) cls
->baseclasses
.data
[0])->protection
) {
3360 prot_tree
= access_public_node
;
3363 prot_tree
= access_protected_node
;
3366 prot_tree
= access_private_node
;
3369 prot_tree
= access_public_node
;
3372 BINFO_BASEACCESS(binfo
,0) = prot_tree
;
3379 /* Create debug information for an InterfaceDeclaration's inheritance
3380 tree. In order to access all inherited methods in the debugger,
3381 the entire tree must be described.
3383 This function makes assumptions about inherface layout. */
3385 intfc_binfo_for(tree tgt_binfo
, ClassDeclaration
* iface
, unsigned & inout_offset
)
3389 make_tree_vec(BINFO_ELTS
)
3391 make_tree_binfo(iface
->baseclasses
.dim
)
3394 TREE_TYPE (binfo
) = TREE_TYPE( iface
->type
->toCtype() ); // RECORD_TYPE, not REFERENCE_TYPE
3395 BINFO_INHERITANCE_CHAIN(binfo
) = tgt_binfo
;
3396 BINFO_OFFSET (binfo
) = size_int(inout_offset
* PTRSIZE
);
3398 if (iface
->baseclasses
.dim
) {
3400 BINFO_BASETYPES(binfo
) = make_tree_vec(iface
->baseclasses
.dim
);
3402 #ifdef BINFO_BASEACCESSES
3403 BINFO_BASEACCESSES(binfo
) = make_tree_vec(iface
->baseclasses
.dim
);
3406 for (unsigned i
= 0; i
< iface
->baseclasses
.dim
; i
++) {
3407 BaseClass
* bc
= (BaseClass
*) iface
->baseclasses
.data
[i
];
3413 BINFO_BASETYPE(binfo
, i
) = intfc_binfo_for(binfo
, bc
->base
, inout_offset
);
3415 BINFO_BASE_APPEND(binfo
, intfc_binfo_for(binfo
, bc
->base
, inout_offset
));
3417 #ifdef BINFO_BASEACCESSES
3419 switch ( bc
->protection
) {
3421 prot_tree
= access_public_node
;
3424 prot_tree
= access_protected_node
;
3427 prot_tree
= access_private_node
;
3430 prot_tree
= access_public_node
;
3433 BINFO_BASEACCESS(binfo
, i
) = prot_tree
;
3441 TypeClass::toCtype()
3445 Array base_class_decls
;
3446 bool inherited
= sym
->baseClass
!= 0;
3450 /* Need to set ctype right away in case of self-references to
3451 the type during this call. */
3452 rec_type
= make_node( RECORD_TYPE
);
3453 //apply_type_attributes(sym->attributes, rec_type, true);
3454 ctype
= build_reference_type( rec_type
);
3455 dkeep(ctype
); // because BINFO moved out to toDebug
3456 g
.ofile
->initTypeDecl(rec_type
, sym
);
3458 obj_rec_type
= TREE_TYPE( gen
.getObjectType()->toCtype() );
3460 // Note that this is set on the reference type, not the record type.
3461 TYPE_LANG_SPECIFIC( ctype
) = build_d_type_lang_specific( this );
3463 AggLayout
agg_layout(sym
, rec_type
);
3465 // Most of this silly code is just to produce correct debugging information.
3467 /* gdb apparently expects the vtable field to be named
3468 "_vptr$...." (stabsread.c) Otherwise, the debugger gives
3469 lots of annoying error messages. C++ appends the class
3470 name of the first base witht that field after the '$'. */
3471 /* update: annoying messages might not appear anymore after making
3473 // Add the virtual table pointer
3474 tree decl
= build_decl(FIELD_DECL
, get_identifier("_vptr$"), /*vtbl_type*/d_vtbl_ptr_type_node
);
3475 agg_layout
.addField( decl
, 0 ); // %% target stuff..
3478 vfield
= copy_node( decl
);
3479 DECL_ARTIFICIAL( decl
) = DECL_IGNORED_P( decl
) = 1;
3483 DECL_VIRTUAL_P( vfield
) = 1;
3484 TYPE_VFIELD( rec_type
) = vfield
; // This only seems to affect debug info
3486 if (! sym
->isInterfaceDeclaration()) {
3487 DECL_FCONTEXT( vfield
) = obj_rec_type
;
3491 decl
= build_decl(FIELD_DECL
, get_identifier("_monitor"), ptr_type_node
);
3492 DECL_FCONTEXT( decl
) = obj_rec_type
;
3493 DECL_ARTIFICIAL( decl
) = DECL_IGNORED_P( decl
) = inherited
;
3494 agg_layout
.addField( decl
, PTRSIZE
);
3496 // Add the fields of each base class
3499 ClassDeclaration
* p
= sym
;
3500 while (p
->baseclasses
.dim
) {
3501 p
= ((BaseClass
*) p
->baseclasses
.data
[0])->base
;
3503 DECL_FCONTEXT( vfield
) = TREE_TYPE( p
->type
->toCtype() );
3506 TYPE_CONTEXT( rec_type
) = gen
.declContext(sym
);
3508 agg_layout
.finish(sym
->attributes
);
3515 ClassDeclaration::toDebug()
3517 tree rec_type
= TREE_TYPE( type
->toCtype() );
3518 /* Used to create BINFO even if debugging was off. This was needed to keep
3519 references to inherited types. */
3521 g
.ofile
->addAggMethods(rec_type
, this);
3523 if ( ! isInterfaceDeclaration() )
3524 TYPE_BINFO( rec_type
) = binfo_for(NULL_TREE
, this);
3526 unsigned offset
= 0;
3529 TYPE_BINFO( rec_type
) = intfc_binfo_for(NULL_TREE
, this, offset
);
3532 g
.ofile
->declareType(rec_type
, this);
3536 LabelStatement::toIR(IRState
* irs
)
3538 FuncDeclaration
* func
= irs
->func
;
3539 LabelDsymbol
* label
= isReturnLabel
? func
->returnLabel
: func
->searchLabel(ident
);
3540 tree t
= irs
->getLabelTree( label
);
3544 if (label
->asmLabelNum
)
3545 d_expand_priv_asm_label(irs
, label
->asmLabelNum
);
3547 if (isReturnLabel
&& func
->fensure
)
3548 func
->fensure
->toIR(irs
);
3550 statement
->toIR(irs
);
3552 // else, there was an error
3556 GotoStatement::toIR(IRState
* irs
)
3558 g
.ofile
->setLoc(loc
); /* This makes the 'undefined label' error show up on the correct line...
3559 The extra doLineNote in doJump shouldn't cause a problem. */
3560 tree t
= irs
->getLabelTree( label
);
3562 irs
->doJump(this, t
);
3563 // else, there was an error
3567 GotoCaseStatement::toIR(IRState
* irs
)
3569 // assumes cblocks have been set in SwitchStatement::toIR
3570 irs
->doJump(this, cs
->cblock
);
3574 GotoDefaultStatement::toIR(IRState
* irs
)
3576 // assumes cblocks have been set in SwitchStatement::toIR
3577 irs
->doJump(this, sw
->sdefault
->cblock
);
3581 SwitchErrorStatement::toIR(IRState
* irs
)
3583 irs
->doLineNote( loc
);
3584 irs
->doExp( irs
->assertCall(loc
, LIBCALL_SWITCH_ERROR
) );
3588 VolatileStatement::toIR(IRState
* irs
)
3590 irs
->pushVolatile();
3591 statement
->toIR( irs
);
3596 ThrowStatement::toIR(IRState
* irs
)
3598 ClassDeclaration
* class_decl
= exp
->type
->toBasetype()->isClassHandle();
3599 // Front end already checks for isClassHandle
3600 InterfaceDeclaration
* intfc_decl
= class_decl
->isInterfaceDeclaration();
3602 tree arg
= exp
->toElem(irs
);
3605 if ( ! intfc_decl
->isCOMclass()) {
3606 arg
= irs
->convertTo(arg
, exp
->type
, irs
->getObjectType());
3608 error("cannot throw COM interfaces");
3612 irs
->doLineNote(loc
);
3613 irs
->doExp( irs
->libCall(LIBCALL_THROW
, 1, & arg
) );
3614 // %%TODO: somehow indicate flow stops here? -- set attribute noreturn on _d_throw
3618 TryFinallyStatement::toIR(IRState
* irs
)
3620 // %% doc: this is not the same as a start_eh/end_eh_cleanup sequence
3621 tree t_body
= body
? irs
->makeStmtExpr(body
) : d_void_zero_node
;
3622 tree t_finl
= finalbody
? irs
->makeStmtExpr(finalbody
) : d_void_zero_node
;
3623 tree tf
= build(TRY_FINALLY_EXPR
, void_type_node
, t_body
, t_finl
);
3624 // TREE_SIDE_EFFECTS(tf) = 1; // probably not needed
3625 irs
->doLineNote(loc
);
3630 TryCatchStatement::toIR(IRState
* irs
)
3632 irs
->doLineNote(loc
);
3633 irs
->startTry(this);
3636 irs
->startCatches();
3638 for (unsigned i
= 0; i
< catches
->dim
; i
++) {
3639 Catch
* a_catch
= (Catch
*) catches
->data
[i
];
3641 irs
->startCatch(a_catch
->type
->toCtype()); //expand_start_catch( xxx );
3643 irs
->doLineNote(a_catch
->loc
);
3646 if ( a_catch
->var
) {
3647 tree exc_obj
= irs
->convertTo(irs
->exceptionObject(),
3648 irs
->getObjectType(), a_catch
->type
);
3649 // need to override initializer...
3650 // set DECL_INITIAL now and emitLocalVar will know not to change it
3651 DECL_INITIAL( a_catch
->var
->toSymbol()->Stree
) = exc_obj
;
3652 irs
->emitLocalVar(a_catch
->var
);
3655 if (a_catch
->handler
)
3656 a_catch
->handler
->toIR(irs
);
3665 OnScopeStatement::toIR(IRState
*)
3671 WithStatement::toIR(IRState
* irs
)
3675 irs
->emitLocalVar(wthis
);
3684 SynchronizedStatement::toIR(IRState
* irs
)
3687 InterfaceDeclaration
* iface
;
3689 irs
->startBindings();
3690 tree decl
= irs
->localVar(IRState::getObjectType());
3692 DECL_IGNORED_P( decl
) = 1;
3693 tree cleanup
= irs
->libCall(LIBCALL_MONITOREXIT
, 1, & decl
);
3694 // assuming no conversions needed
3697 assert(exp
->type
->toBasetype()->ty
== Tclass
);
3698 iface
= ((TypeClass
*) exp
->type
->toBasetype())->sym
->isInterfaceDeclaration();
3700 if (! iface
->isCOMclass()) {
3701 init_exp
= irs
->convertTo(exp
, irs
->getObjectType());
3703 error("cannot synchronize on a COM interface");
3704 init_exp
= error_mark_node
;
3707 init_exp
= exp
->toElem(irs
);
3710 DECL_INITIAL(decl
) = init_exp
;
3712 irs
->doLineNote(loc
);
3715 irs
->expandDecl(decl
);
3716 irs
->doExp( irs
->libCall(LIBCALL_MONITORENTER
, 1, & decl
));
3717 expand_decl_cleanup(decl
, cleanup
); // nope,nope just do it diffrent ways or just jump the cleanup like below..
3721 irs
->expandDecl(decl
);
3722 irs
->doExp( irs
->libCall(LIBCALL_MONITORENTER
, 1, & decl
));
3723 irs
->startTry(this);
3726 irs
->startFinally();
3727 irs
->doExp( cleanup
);
3732 #ifndef D_CRITSEC_SIZE
3733 #define D_CRITSEC_SIZE 64
3735 static tree critsec_type
= 0;
3737 if (! critsec_type
) {
3738 critsec_type
= irs
->arrayType(Type::tuns8
, D_CRITSEC_SIZE
);
3741 tree critsec_decl
= build_decl(VAR_DECL
, NULL_TREE
, critsec_type
);
3742 // name is only used to prevent ICEs
3743 g
.ofile
->giveDeclUniqueName(critsec_decl
, "__critsec");
3744 tree critsec_ref
= irs
->addressOf(critsec_decl
); // %% okay to use twice?
3745 dkeep(critsec_decl
);
3747 TREE_STATIC(critsec_decl
) = 1;
3748 TREE_PRIVATE(critsec_decl
) = 1;
3749 DECL_ARTIFICIAL(critsec_decl
) = 1;
3750 DECL_IGNORED_P(critsec_decl
) = 1;
3752 g
.ofile
->rodc(critsec_decl
, 1);
3755 expand_eh_region_start();
3756 expand_expr_stmt_value(irs
->libCall(LIBCALL_CRITICALENTER
, 1, & critsec_ref
), 0, 1);
3759 expand_expr_stmt_value(irs
->libCall(LIBCALL_CRITICALEXIT
, 1, & critsec_ref
), 0, 1);
3760 expand_eh_region_end_cleanup(irs
->libCall(LIBCALL_CRITICALEXIT
, 1, & critsec_ref
));
3762 irs
->startTry(this);
3763 irs
->doExp( irs
->libCall(LIBCALL_CRITICALENTER
, 1, & critsec_ref
) );
3766 irs
->startFinally();
3767 irs
->doExp( irs
->libCall(LIBCALL_CRITICALEXIT
, 1, & critsec_ref
) );
3774 ContinueStatement::toIR(IRState
* irs
)
3776 irs
->doLineNote(loc
);
3777 irs
->continueLoop(ident
);
3781 BreakStatement::toIR(IRState
* irs
)
3783 irs
->doLineNote(loc
);
3784 irs
->exitLoop(ident
);
3788 ReturnStatement::toIR(IRState
* irs
)
3790 irs
->doLineNote(loc
);
3793 if (exp
->type
->toBasetype()->ty
!= Tvoid
) { // %% == Type::tvoid ?
3794 FuncDeclaration
* func
= irs
->func
;
3795 Type
* ret_type
= func
->tintro
?
3796 func
->tintro
->nextOf() : func
->type
->nextOf();
3798 if (func
->isMain() && ret_type
->toBasetype()->ty
== Tvoid
)
3799 ret_type
= Type::tint32
;
3801 tree result_decl
= DECL_RESULT( irs
->func
->toSymbol()->Stree
);
3802 tree result_assign
= build ( MODIFY_EXPR
,
3803 TREE_TYPE( result_decl
), result_decl
,
3804 // %% convert for init -- if we were returning a reference,
3805 // would want to take the address...
3806 irs
->convertForAssignment(exp
, (Type
*)ret_type
) );
3808 irs
->doReturn(result_assign
); // expand_return(result_assign);
3811 irs
->doReturn(NULL_TREE
);
3814 irs
->doReturn(NULL_TREE
);
3819 DefaultStatement::toIR(IRState
* irs
)
3821 irs
->doCase(NULL_TREE
, cblock
);
3823 statement
->toIR( irs
);
3827 CaseStatement::toIR(IRState
* irs
)
3831 if ( exp
->type
->isscalar() )
3832 case_value
= exp
->toElem(irs
);
3834 case_value
= irs
->integerConstant(index
, Type::tint32
);
3835 irs
->doCase(case_value
, cblock
);
3837 statement
->toIR( irs
);
3841 SwitchStatement::toIR(IRState
* irs
)
3844 // %% also what about c-semantics doing emit_nop() ?
3845 irs
->doLineNote( loc
);
3847 cond_tree
= condition
->toElem( irs
);
3849 Type
* cond_type
= condition
->type
->toBasetype();
3850 if (cond_type
->ty
== Tarray
) {
3851 Type
* elem_type
= cond_type
->nextOf()->toBasetype();
3853 switch (elem_type
->ty
) {
3854 case Tchar
: lib_call
= LIBCALL_SWITCH_STRING
; break;
3855 case Twchar
: lib_call
= LIBCALL_SWITCH_USTRING
; break;
3856 case Tdchar
: lib_call
= LIBCALL_SWITCH_DSTRING
; break;
3858 ::error("switch statement value must be an array of some character type, not %s", elem_type
->toChars());
3862 // Apparently the backend is supposed to sort and set the indexes
3863 // on the case array
3864 // have to change them to be useable
3865 cases
->sort(); // %%!!
3867 Symbol
* s
= static_sym();
3868 dt_t
** pdt
= & s
->Sdt
;
3870 for (unsigned case_i
= 0; case_i
< cases
->dim
; case_i
++) {
3871 CaseStatement
* case_stmt
= (CaseStatement
*) cases
->data
[case_i
];
3872 pdt
= case_stmt
->exp
->toDt( pdt
);
3873 case_stmt
->index
= case_i
;
3876 tree p_table
= irs
->addressOf(s
->Stree
);
3879 irs
->darrayVal(cond_type
->arrayOf()->toCtype(), cases
->dim
,
3883 cond_tree
= irs
->libCall(lib_call
, 2, args
);
3884 } else if (! cond_type
->isscalar()) {
3885 ::error("cannot handle switch condition of type %s", cond_type
->toChars());
3889 // Build LABEL_DECLs now so they can be refered to by goto case
3891 for (unsigned i
= 0; i
< cases
->dim
; i
++) {
3892 CaseStatement
* case_stmt
= (CaseStatement
*) cases
->data
[i
];
3893 case_stmt
->cblock
= irs
->label(case_stmt
->loc
); //make_case_label(case_stmt->loc);
3896 sdefault
->cblock
= irs
->label(sdefault
->loc
); //make_case_label(sdefault->loc);
3899 cond_tree
= fold(cond_tree
);
3900 irs
->startCase(this, cond_tree
);
3903 irs
->endCase(cond_tree
);
3908 Statement::toIR(IRState
*)
3910 ::error("Statement::toIR: don't know what to do (%s)", toChars());
3915 IfStatement::toIR(IRState
* irs
)
3919 irs
->emitLocalVar(match
);
3921 irs
->startCond(this, condition
);
3923 ifbody
->toIR( irs
);
3926 elsebody
->toIR ( irs
);
3934 ForeachStatement::toIR(IRState
* irs
)
3936 // %% better?: set iter to start - 1 and use result of increment for condition?
3940 Type
* agg_type
= aggr
->type
->toBasetype();
3941 Type
* elem_type
= agg_type
->nextOf()->toBasetype();
3944 tree iter_init_expr
;
3945 tree aggr_expr
= irs
->maybeMakeTemp( aggr
->toElem(irs
) );
3949 gcc_assert(elem_type
->ty
!= Tbit
);
3952 irs
->startBindings(); /* Variables created by the function will probably
3953 end up in a contour created by emitLocalVar. This
3954 startBindings call is just to be safe */
3955 irs
->doLineNote( loc
);
3961 fprintf(stderr
, "EXPER: I need this\n");
3962 default_loc
= Loc(g
.mod
, 1); // %% fix
3965 if (! value
->loc
.filename
)
3966 g
.ofile
->setDeclLoc( value
->toSymbol()->Stree
, default_loc
);
3968 irs
->emitLocalVar(value
, true);
3971 if (! key
->loc
.filename
)
3972 g
.ofile
->setDeclLoc( key
->toSymbol()->Stree
, default_loc
);
3974 DECL_INITIAL( key
->toSymbol()->Stree
) = op
== TOKforeach
?
3975 irs
->integerConstant(0, key
->type
) :
3976 irs
->arrayLength(aggr_expr
, agg_type
);
3978 irs
->emitLocalVar(key
); // %% getExpInitializer causes uneeded initialization
3982 if (value
->isRef() || value
->isOut()) {
3983 iter_is_value
= true;
3984 iter_decl
= irs
->var(value
);
3986 iter_is_value
= false;
3987 iter_decl
= irs
->localVar(elem_type
->pointerTo());
3988 irs
->expandDecl(iter_decl
);
3991 if ( agg_type
->ty
== Tsarray
) {
3992 bound_expr
= ((TypeSArray
*) agg_type
)->dim
->toElem(irs
);
3993 iter_init_expr
= irs
->addressOf( aggr_expr
);
3994 // Type needs to be pointer-to-element to get pointerIntSum
3996 iter_init_expr
= irs
->nop(iter_init_expr
,
3997 agg_type
->nextOf()->pointerTo()->toCtype());
3999 bound_expr
= irs
->darrayLenRef( aggr_expr
);
4000 iter_init_expr
= irs
->darrayPtrRef( aggr_expr
);
4002 iter_init_expr
= save_expr( iter_init_expr
);
4003 bound_expr
= irs
->pointerIntSum(iter_init_expr
, bound_expr
);
4004 // aggr. isn't supposed to be modified, so...
4005 bound_expr
= save_expr( bound_expr
);
4007 enum tree_code iter_op
= PLUS_EXPR
;
4009 if (op
== TOKforeach_reverse
)
4011 tree t
= iter_init_expr
;
4012 iter_init_expr
= bound_expr
;
4015 iter_op
= MINUS_EXPR
;
4018 tree condition
= build(NE_EXPR
, boolean_type_node
, iter_decl
, bound_expr
);
4020 build(MODIFY_EXPR
, void_type_node
, iter_decl
,
4021 build(iter_op
, TREE_TYPE(iter_decl
), iter_decl
,
4022 size_int(elem_type
->size())));
4024 tree key_decl
= irs
->var(key
);
4025 tree key_incr_expr
=
4026 build(MODIFY_EXPR
, void_type_node
, key_decl
,
4027 build(iter_op
, TREE_TYPE(key_decl
), key_decl
,
4028 irs
->integerConstant(1, TREE_TYPE(key_decl
))));
4029 incr_expr
= irs
->compound(incr_expr
, key_incr_expr
);
4032 irs
->doExp( build(MODIFY_EXPR
, void_type_node
, iter_decl
, iter_init_expr
) );
4034 irs
->startLoop(this);
4035 irs
->exitIfFalse(condition
);
4036 if ( op
== TOKforeach_reverse
)
4037 irs
->doExp( incr_expr
);
4038 if ( ! iter_is_value
)
4039 irs
->doExp( build(MODIFY_EXPR
, void_type_node
, irs
->var(value
),
4040 irs
->indirect(iter_decl
)) );
4043 irs
->continueHere();
4045 if ( op
== TOKforeach
)
4046 irs
->doExp( incr_expr
);
4050 irs
->endBindings(); // not really needed
4057 ForeachRangeStatement::toIR(IRState
* irs
)
4059 bool fwd
= op
== TOKforeach
;
4062 irs
->startBindings(); /* Variables created by the function will probably
4063 end up in a contour created by emitLocalVar. This
4064 startBindings call is just to be safe */
4065 irs
->doLineNote( loc
);
4067 gcc_assert(key
!= NULL
);
4068 gcc_assert(lwr
!= NULL
);
4069 gcc_assert(upr
!= NULL
);
4071 // Front end ensures no storage class
4072 irs
->emitLocalVar(key
, true);
4073 tree key_decl
= irs
->var(key
);
4074 tree lwr_decl
= irs
->localVar(lwr
->type
);
4075 tree upr_decl
= irs
->localVar(upr
->type
);
4076 tree iter_expr
= irs
->vmodify(key_decl
,
4077 build2(fwd
? PLUS_EXPR
: MINUS_EXPR
, TREE_TYPE(key_decl
),
4078 key_decl
, irs
->integerConstant(1, TREE_TYPE(key_decl
))));
4081 irs
->expandDecl(lwr_decl
);
4082 irs
->expandDecl(upr_decl
);
4083 irs
->doExp( irs
->vmodify(lwr_decl
, lwr
->toElem(irs
)) );
4084 irs
->doExp( irs
->vmodify(upr_decl
, upr
->toElem(irs
)) );
4086 condition
= build2(fwd
? LT_EXPR
: GT_EXPR
, boolean_type_node
,
4087 key_decl
, fwd
? upr_decl
: lwr_decl
);
4089 irs
->doExp( irs
->vmodify(key_decl
, fwd
? lwr_decl
: upr_decl
) );
4091 irs
->startLoop(this);
4093 irs
->continueHere();
4094 irs
->exitIfFalse(condition
);
4096 irs
->doExp(iter_expr
);
4100 irs
->continueHere();
4101 irs
->doExp(iter_expr
);
4105 irs
->endBindings(); // not really needed
4112 ForStatement::toIR(IRState
* irs
)
4114 irs
->doLineNote(loc
);
4118 irs
->startLoop(this);
4120 irs
->exitIfFalse(condition
);
4123 irs
->continueHere();
4125 irs
->doExp(increment
->toElem(irs
)); // force side effects?
4130 DoStatement::toIR(IRState
* irs
)
4132 irs
->doLineNote(loc
);
4133 irs
->startLoop(this);
4136 irs
->continueHere();
4137 irs
->exitIfFalse(condition
);
4142 WhileStatement::toIR(IRState
* irs
)
4144 irs
->doLineNote(loc
); // store for next statement...
4145 irs
->startLoop(this);
4146 irs
->continueHere();
4147 irs
->exitIfFalse(condition
, 1); // 1 == is topcond .. good as deprecated..
4154 ScopeStatement::toIR(IRState
* irs
)
4158 statement
->toIR( irs
);
4164 CompoundStatement::toIR(IRState
* irs
)
4167 for (unsigned i
= 0; i
< statements
->dim
; i
++) {
4168 Statement
* statement
= (Statement
*) statements
->data
[i
];
4171 statement
->toIR(irs
);
4177 UnrolledLoopStatement::toIR(IRState
* irs
)
4180 irs
->startLoop(this);
4181 irs
->continueHere();
4182 for (unsigned i
= 0; i
< statements
->dim
; i
++) {
4183 Statement
* statement
= (Statement
*) statements
->data
[i
];
4187 irs
->setContinueLabel( irs
->label(loc
) );
4188 statement
->toIR(irs
);
4189 irs
->continueHere();
4192 irs
->exitLoop(NULL
);
4198 ExpStatement::toIR(IRState
* irs
)
4201 gen
.doLineNote(loc
);
4203 tree exp_tree
= exp
->toElem(irs
);
4205 irs
->doExp(exp_tree
);
4213 PragmaStatement::toIR(IRState
*)
4220 EnumDeclaration::toDebug()
4226 Dsymbol::cvMember(unsigned char*)
4231 EnumDeclaration::cvMember(unsigned char*)
4236 FuncDeclaration::cvMember(unsigned char*)
4241 VarDeclaration::cvMember(unsigned char*)
4246 TypedefDeclaration::cvMember(unsigned char*)
4254 d_expand_expr(tree exp
, rtx target
, enum machine_mode tmode
, int modifier
, rtx
*)
4256 if ( TREE_CODE(exp
) == (enum tree_code
) D_STMT_EXPR
) {
4260 gen
.retrieveStmtExpr(exp
, & stmt
, & irs
);
4261 // need push_temp_slots()?
4263 tree rtl_expr
= expand_start_stmt_expr(1);
4264 // This startBindings call is needed so get_last_insn() doesn't return NULL
4265 // in expand_start_case().
4266 irs
->startBindings();
4267 // preserve_temp_slots as in c-common.c:c_expand_expr
4272 expand_end_stmt_expr (rtl_expr
);
4274 rtx result
= expand_expr (rtl_expr
, target
, tmode
, (enum expand_modifier
) modifier
);
4277 } else if ( TREE_CODE(exp
) == (enum tree_code
) D_ARRAY_SET_EXPR
){
4278 // %% if single byte element, expand to memset
4280 assert( POINTER_TYPE_P( TREE_TYPE( TREE_OPERAND( exp
, 0 ))));
4281 assert( INTEGRAL_TYPE_P( TREE_TYPE( TREE_OPERAND( exp
, 2 ))));
4282 // assuming unsigned source is unsigned
4284 push_temp_slots (); // will this work? maybe expand_start_binding
4285 tree rtl_expr
= expand_start_stmt_expr(1);
4287 do_array_set(g
.irs
, // %% fix!
4288 TREE_OPERAND(exp
, 0), TREE_OPERAND(exp
, 1), TREE_OPERAND(exp
, 2));
4290 expand_end_stmt_expr(rtl_expr
);
4291 rtx result
= expand_expr(rtl_expr
, target
, tmode
, (enum expand_modifier
) modifier
);
4301 void x(tree ptr, tree src, tree count) {
4304 build(BIND_EXPR, count_var, t_loop, block???0
4309 d_build_eh_type_type(tree type
)
4311 TypeClass
* d_type
= (TypeClass
*) IRState::getDType(type
);
4313 d_type
= (TypeClass
*) d_type
->toBasetype();
4314 assert(d_type
->ty
== Tclass
);
4315 return IRState::addressOf( d_type
->sym
->toSymbol()->Stree
);
4318 tree d_void_zero_node
;
4320 tree d_null_pointer
;
4321 tree d_vtbl_ptr_type_node
;
4324 gcc_d_backend_init()
4326 // %% need this here to add the type decls ...
4327 init_global_binding_level();
4329 // This allows the code in d-builtins2 to not have to worry about
4330 // converting (C signed char *) to (D char *) for string arguments of
4331 // built-in functions.
4332 flag_signed_char
= 0;
4333 // This is required or we'll crash pretty early on. %%log
4334 build_common_tree_nodes (flag_signed_char
4340 // This is also required (or the manual equivalent) or crashes
4342 size_type_node
= d_type_for_mode(ptr_mode
, 1);
4344 // c was: TREE_TYPE (identifier_global_value (get_identifier (SIZE_TYPE)));
4345 //signed_size_type_node = c_common_signed_type (size_type_node);
4347 // If this is called after the next statements, you'll get an ICE.
4348 set_sizetype(size_type_node
);
4351 // need this for void.. %% but this crashes... probably need to impl
4352 // some things in dc-lang.cc
4353 build_common_tree_nodes_2 (0 /* %% support the option */);
4355 // Specific to D (but so far all taken from C)
4357 d_void_zero_node
= build_int_2 (0, 0);
4358 TREE_TYPE (d_void_zero_node
) = void_type_node
;
4360 d_void_zero_node
= build_int_cst (void_type_node
, 0);
4362 // %%TODO: we are relying on default boolean_type_node being 8bit / same as Tbit
4364 d_null_pointer
= convert(ptr_type_node
, integer_zero_node
);
4366 TYPE_NAME( integer_type_node
) = build_decl(TYPE_DECL
, get_identifier("int"), integer_type_node
);
4367 TYPE_NAME( char_type_node
) = build_decl(TYPE_DECL
, get_identifier("cchar"), char_type_node
); // "char?"
4369 REALSIZE
= int_size_in_bytes(long_double_type_node
);
4371 PTRSIZE
= int_size_in_bytes(ptr_type_node
);
4372 switch (int_size_in_bytes(size_type_node
)) {
4384 switch ( PTRSIZE
) {
4386 assert(POINTER_SIZE
== 32);
4387 Tptrdiff_t
= Tint32
;
4390 assert(POINTER_SIZE
== 64);
4391 Tptrdiff_t
= Tint64
;
4397 CLASSINFO_SIZE
= 19 * PTRSIZE
;
4399 CLASSINFO_SIZE
= 18 * PTRSIZE
;
4404 if (flag_exceptions
) {
4405 eh_personality_libfunc
= init_one_libfunc(d_using_sjlj_exceptions()
4406 ? "__gdc_personality_sj0" : "__gdc_personality_v0");
4408 default_init_unwind_resume_libfunc ();
4410 lang_eh_runtime_type
= d_build_eh_type_type
;
4411 using_eh_for_cleanups ();
4412 // lang_proctect_cleanup_actions = ...; // no need? ... probably needed for autos
4415 /* copied and modified from cp/decl.c; only way for vtable to work in gdb... */
4416 // or not, I'm feeling very confused...
4418 /* Make sure we get a unique function type, so we can give
4419 its pointer type a name. (This wins for gdb.) */
4420 tree vfunc_type
= make_node (FUNCTION_TYPE
);
4421 TREE_TYPE (vfunc_type
) = Type::tint32
->toCtype(); // integer_type_node; messed up built in types?
4422 TYPE_ARG_TYPES (vfunc_type
) = NULL_TREE
;
4423 layout_type (vfunc_type
);
4425 tree vtable_entry_type
= build_pointer_type (vfunc_type
);
4426 d_vtbl_ptr_type_node
= build_pointer_type(vtable_entry_type
);
4427 layout_type (d_vtbl_ptr_type_node
);// %%TODO: check if needed
4430 // This also allows virtual functions to be called, but when vtbl entries,
4431 // are inspected, function symbol names do not appear.
4432 // d_vtbl_ptr_type_node = Type::tvoid->pointerTo()->pointerTo()->toCtype();
4434 // This is the C main, not the D main
4435 main_identifier_node
= get_identifier ("main");
4439 gcc_d_backend_term()