Support maybe dynamic arrays.
[delight/core.git] / d-codegen.cc
blob1f228c85afd68ea0e256548345455e0f36599fe1
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"
20 #include "d-lang.h"
21 #include "d-codegen.h"
22 #include <math.h>
23 #include <limits.h>
24 #include "total.h"
25 #include "template.h"
26 #include "init.h"
27 #include "symbol.h"
28 #include "dt.h"
30 GlobalValues g;
31 IRState gen;
32 Array IRState::stmtExprList;
33 TemplateEmission IRState::emitTemplates;
34 bool IRState::splitDynArrayVarArgs;
35 bool IRState::useBuiltins;
36 bool IRState::warnSignCompare = false;
37 bool IRState::originalOmitFramePointer;
39 bool
40 d_gcc_force_templates()
42 return IRState::emitTemplates == TEprivate ||
43 IRState::emitTemplates == TEall;
46 void
47 IRState::emitLocalVar(VarDeclaration * v, bool no_init)
49 if (v->isDataseg() || (v->storage_class & STCfield))
50 return;
52 Symbol * sym = v->toSymbol();
53 tree var_decl = sym->Stree;
55 gcc_assert(! TREE_STATIC( var_decl ));
56 if (TREE_CODE(var_decl) == CONST_DECL)
57 return;
59 DECL_CONTEXT( var_decl ) = getLocalContext();
61 tree var_exp;
62 #if V2
63 if (sym->SclosureField)
64 var_exp = var(v);
65 else
66 #endif
68 var_exp = var_decl;
69 pushdecl(var_decl);
70 #if D_GCC_VER < 40
71 expand_decl(var_decl);
72 #endif
75 tree init_exp = NULL_TREE; // complete initializer expression (include MODIFY_EXPR, e.g.)
76 tree init_val = NULL_TREE;
78 if (! no_init && ! DECL_INITIAL( var_decl ) && v->init ) {
79 if (! v->init->isVoidInitializer()) {
80 ExpInitializer * exp_init = v->init->isExpInitializer();
81 Expression * ie = exp_init->toExpression();
82 if ( ! (init_val = assignValue(ie, v)) )
83 init_exp = ie->toElem(this);
85 else
86 no_init = true;
89 if (! no_init) {
90 g.ofile->doLineNote(v->loc);
92 if (! init_val)
93 init_val = DECL_INITIAL(var_decl);
94 #if D_GCC_VER < 40
95 if (init_val
96 #if V2
97 && ! sym->SclosureField
98 #endif
101 // not sure if there is any advantage to doing this...
102 DECL_INITIAL(var_decl) = init_val;
103 expand_decl_init(var_decl);
105 else
106 #endif
107 if (! init_exp && init_val)
108 init_exp = vmodify(var_exp, init_val);
110 if (init_exp)
111 addExp(init_exp);
112 else if (! init_val && v->size(v->loc)) // Zero-length arrays do not have an initializer
113 d_warning(OPT_Wuninitialized, "uninitialized variable '%s'", v->ident ? v->ident->string : "(no name)");
117 tree
118 IRState::localVar(tree t_type) {
119 tree t_decl = build_decl(VAR_DECL, NULL_TREE, t_type);
120 DECL_CONTEXT( t_decl ) = getLocalContext();
121 DECL_ARTIFICIAL( t_decl ) = 1;
122 DECL_IGNORED_P( t_decl ) = 1;
123 pushdecl(t_decl);
124 return t_decl;
127 tree
128 IRState::exprVar(tree t_type)
130 tree t_decl = build_decl(VAR_DECL, NULL_TREE, t_type);
131 DECL_CONTEXT( t_decl ) = getLocalContext();
132 DECL_ARTIFICIAL( t_decl ) = 1;
133 DECL_IGNORED_P( t_decl ) = 1;
134 return t_decl;
137 static bool
138 needs_expr_var(tree exp)
140 switch (TREE_CODE(exp)) {
141 case VAR_DECL:
142 case FUNCTION_DECL:
143 case PARM_DECL:
144 case CONST_DECL:
145 case INDIRECT_REF:
146 case ARRAY_REF:
147 return false;
148 case COMPONENT_REF:
149 return needs_expr_var(TREE_OPERAND(exp,0));
150 default:
151 return true;
155 tree
156 IRState::maybeExprVar(tree exp, tree * out_var)
158 if ( needs_expr_var(exp) ) {
159 *out_var = exprVar(TREE_TYPE(exp));
160 DECL_INITIAL( *out_var ) = exp;
161 return *out_var;
162 } else {
163 *out_var = NULL_TREE;
164 return exp;
168 tree
169 IRState::declContext(Dsymbol * d_sym)
171 Dsymbol * orig_sym = d_sym;
172 AggregateDeclaration * agg_decl;
174 while ( (d_sym = d_sym->toParent2()) ) {
175 if (d_sym->isFuncDeclaration()) {
176 // 3.3.x (others?) dwarf2out chokes without this check... (output_pubnames)
177 FuncDeclaration * f = orig_sym->isFuncDeclaration();
178 if (f && ! gen.functionNeedsChain(f))
179 return 0;
180 return d_sym->toSymbol()->Stree;
181 } else if ( (agg_decl = d_sym->isAggregateDeclaration()) ) {
182 ClassDeclaration * cd;
184 tree ctx = agg_decl->type->toCtype();
185 if ( (cd = d_sym->isClassDeclaration()) )
186 ctx = TREE_TYPE(ctx); // RECORD_TYPE instead of REFERENCE_TYPE
187 return ctx;
188 } else if ( d_sym->isModule() ) {
189 return d_sym->toSymbol()->ScontextDecl;
192 return NULL_TREE;
195 void
196 IRState::expandDecl(tree t_decl)
198 #if D_GCC_VER < 40
199 expand_decl(t_decl);
200 if (DECL_INITIAL(t_decl))
201 expand_decl_init(t_decl);
202 #else
203 // nothing, pushdecl will add t_decl to a BIND_EXPR
204 if (DECL_INITIAL(t_decl)) {
205 // void_type_node%%?
206 doExp(build2(MODIFY_EXPR, void_type_node, t_decl, DECL_INITIAL(t_decl)));
207 DECL_INITIAL(t_decl) = NULL_TREE;
209 #endif
212 #if V2
213 tree
214 IRState::var(VarDeclaration * v)
216 bool is_closure_var = v->toSymbol()->SclosureField != NULL;
218 /* // testing...
219 bool test2 = false;
220 Dsymbol * vp = v->toParent2();
221 if (vp)
223 FuncDeclaration * f = vp->isFuncDeclaration();
224 /* //testing...
225 if (f && getFrameInfo(f)->creates_closure)
227 for (unsigned i = 0; i < f->closureVars.dim; ++i)
228 if (v == f->closureVars.data[i])
230 test2 = true;
231 break;
234 gcc_assert(is_closure_var == test2);
236 //...testing */
238 if (is_closure_var)
240 FuncDeclaration * f = v->toParent2()->isFuncDeclaration();
242 tree cf = getClosureRef(f);
243 tree field = v->toSymbol()->SclosureField;
244 gcc_assert(field != NULL_TREE);
245 return component(indirect(cf), field);
247 else
248 // Static var or auto var that the back end will handle for us
249 return v->toSymbol()->Stree;
251 #endif
254 tree
255 IRState::convertTo(Expression * exp, Type * target_type)
257 return convertTo(exp->toElem( this ), exp->type, target_type);
260 tree
261 IRState::convertTo(tree exp, Type * exp_type, Type * target_type)
263 tree result = 0;
264 target_type = target_type->toBasetype();
266 assert(exp_type);
267 exp_type = exp_type->toBasetype();
269 if (typesSame(exp_type, target_type))
270 return exp;
272 switch (exp_type->ty) {
273 case Tdelegate:
274 // %%TODO:NOP/VIEW_CONVERT
275 if (target_type->ty == Tdelegate) {
276 exp = maybeMakeTemp(exp);
277 return delegateVal( delegateMethodRef(exp), delegateObjectRef(exp),
278 target_type);
279 } else if (target_type->ty == Tpointer) {
280 // The front-end converts <delegate>.ptr to cast(void*)<delegate>.
281 // Maybe should only allow void*?
282 exp = delegateObjectRef(exp);
283 } else {
284 ::error("can't convert a delegate expression to %s", target_type->toChars());
285 return error_mark_node;
287 break;
288 case Tclass:
289 if (target_type->ty == Tclass) {
290 ClassDeclaration * target_class_decl = ((TypeClass *) target_type)->sym;
291 ClassDeclaration * obj_class_decl = ((TypeClass *) exp_type)->sym;
292 bool use_dynamic = false;
294 target_ptrdiff_t offset;
295 if (target_class_decl->isBaseOf(obj_class_decl, & offset)) {
296 // Casting up the inheritance tree: Don't do anything special.
297 // Cast to an implemented interface: Handle at compile time.
298 if (offset == OFFSET_RUNTIME) {
299 use_dynamic = true;
300 } else if (offset) {
301 tree t = target_type->toCtype();
302 exp = maybeMakeTemp(exp);
303 return build(COND_EXPR, t,
304 boolOp(NE_EXPR, exp, nullPointer()),
305 build(PLUS_EXPR, t, exp, size_int(offset)),
306 nullPointer());
307 } else {
308 // d_convert will make a NOP cast
309 break;
311 } else if ( target_class_decl == obj_class_decl ) {
312 // d_convert will make a NOP cast
313 break;
314 } else if ( ! obj_class_decl->isCOMclass() ) {
315 use_dynamic = true;
318 if (use_dynamic) {
319 // Otherwise, do dynamic cast
320 tree args[2] = { exp, addressOf( target_class_decl->toSymbol()->Stree ) }; // ##v (and why not just addresOf(target_class_decl)
321 return libCall(obj_class_decl->isInterfaceDeclaration()
322 ? LIBCALL_INTERFACE_CAST : LIBCALL_DYNAMIC_CAST, 2, args);
323 } else {
324 d_warning(0, "cast to %s will yield null result", target_type->toChars());
325 result = convert(target_type->toCtype(), d_null_pointer);
326 if (TREE_SIDE_EFFECTS( exp )) { // make sure the expression is still evaluated if necessary
327 result = compound(exp, result);
329 return result;
331 } else {
332 // nothing; default
334 break;
335 case Tsarray:
337 if (target_type->ty == Tpointer) {
338 result = nop( addressOf( exp ), target_type->toCtype() );
339 } else if (target_type->ty == Tarray) {
340 TypeSArray * a_type = (TypeSArray*) exp_type;
342 uinteger_t array_len = a_type->dim->toUInteger();
343 d_uns64 sz_a = a_type->next->size();
344 d_uns64 sz_b = target_type->nextOf()->size();
346 // conversions to different sizes
347 // Assumes tvoid->size() == 1
348 // %% TODO: handle misalign like _d_arraycast_xxx ?
349 #if ! V2
350 gcc_assert(a_type->next->isbit() == target_type->next->isbit());
351 #endif
353 if (sz_a != sz_b)
354 array_len = array_len * sz_a / sz_b;
356 tree pointer_value = nop( addressOf( exp ),
357 target_type->nextOf()->pointerTo()->toCtype() );
359 // Assumes casting to dynamic array of same type or void
360 return darrayVal(target_type, array_len, pointer_value);
361 } else if (target_type->ty == Tsarray) {
362 // DMD apparently allows casting a static array to any static array type
363 return indirect(addressOf(exp), target_type->toCtype());
365 // %% else error?
367 break;
368 case Tarray:
369 if (target_type->ty == Tpointer) {
370 return convert(target_type->toCtype(), darrayPtrRef( exp ));
371 } else if (target_type->ty == Tarray) {
372 // assume tvoid->size() == 1
374 Type * src_elem_type = exp_type->nextOf()->toBasetype();
375 Type * dst_elem_type = target_type->nextOf()->toBasetype();
376 d_uns64 sz_a = src_elem_type->size();
377 d_uns64 sz_b = dst_elem_type->size();
379 gcc_assert((src_elem_type->ty == Tbit) ==
380 (dst_elem_type->ty == Tbit));
382 if (sz_a != sz_b) {
383 unsigned mult = 1;
384 #if ! V2
385 if (dst_elem_type->isbit())
386 mult = 8;
387 #endif
388 tree args[3] = {
389 // assumes Type::tbit->size() == 1
390 integerConstant(sz_b, Type::tsize_t),
391 integerConstant(sz_a * mult,
392 Type::tsize_t),
395 return libCall(LIBCALL_ARRAYCAST, 3, args, target_type->toCtype());
396 } else {
397 // %% VIEW_CONVERT_EXPR or NOP_EXPR ? (and the two cases below)
398 // Convert to/from void[] or elements are the same size -- don't change length
399 return build1(NOP_EXPR, target_type->toCtype(), exp);
402 // else, default conversion, which should produce an error
403 break;
404 case Taarray:
405 if (target_type->ty == Taarray)
406 return build1(NOP_EXPR, target_type->toCtype(), exp);
407 // else, default conversion, which should product an error
408 break;
409 case Tpointer:
410 /* For some reason, convert_to_integer converts pointers
411 to a signed type. */
412 if (target_type->isintegral())
413 exp = d_convert_basic(d_type_for_size(POINTER_SIZE, 1), exp);
414 break;
415 default:
416 if (exp_type->isreal() && target_type->isimaginary() ||
417 exp_type->isimaginary() && target_type->isreal()) {
418 // warn? handle in front end?
420 result = build_real_from_int_cst( target_type->toCtype(), integer_zero_node );
421 if (TREE_SIDE_EFFECTS( exp ))
422 result = compound(exp, result);
423 return result;
424 } else if (exp_type->iscomplex()) {
425 Type * part_type;
426 // creal.re, .im implemented by cast to real or ireal
427 // Assumes target type is the same size as the original's components size
428 if (target_type->isreal()) {
429 // maybe install lang_specific...
430 switch (exp_type->ty) {
431 case Tcomplex32: part_type = Type::tfloat32; break;
432 case Tcomplex64: part_type = Type::tfloat64; break;
433 case Tcomplex80: part_type = Type::tfloat80; break;
434 default:
435 abort();
437 result = realPart(exp);
438 } else if (target_type->isimaginary()) {
439 switch (exp_type->ty) {
440 case Tcomplex32: part_type = Type::timaginary32; break;
441 case Tcomplex64: part_type = Type::timaginary64; break;
442 case Tcomplex80: part_type = Type::timaginary80; break;
443 default:
444 abort();
446 result = imagPart(exp);
447 } else {
448 // default conversion
449 break;
451 result = convertTo(result, part_type, target_type);
452 } else if (target_type->iscomplex()) {
453 tree c1, c2, t;
454 c1 = convert(TREE_TYPE(target_type->toCtype()), exp);
455 c2 = build_real_from_int_cst( TREE_TYPE(target_type->toCtype()), integer_zero_node);
457 if (exp_type->isreal()) {
458 // nothing
459 } else if (exp_type->isimaginary()) {
460 t = c1;
461 c1 = c2;
462 c2 = t;
463 } else {
464 // default conversion
465 break;
467 result = build(COMPLEX_EXPR, target_type->toCtype(), c1, c2);
468 } else {
469 assert( TREE_CODE( exp ) != STRING_CST );
470 // default conversion
474 if (! result)
475 result = d_convert_basic(target_type->toCtype(), exp);
476 return result;
479 tree
480 IRState::convertForArgument(Expression * exp, Argument * arg)
482 if ( isArgumentReferenceType(arg) ) {
483 tree exp_tree = this->toElemLvalue(exp);
484 // front-end already sometimes automatically takes the address
485 // TODO: Make this safer? Can this be confused by a non-zero SymOff?
486 if (exp->op != TOKaddress && exp->op != TOKsymoff && exp->op != TOKadd)
487 return addressOf( exp_tree );
488 else
489 return exp_tree;
490 } else {
491 // Lazy arguments: exp should already be a delegate
493 Type * et = exp->type->toBasetype();
494 Type * at = arg->type->toBasetype();
495 if (et != at) {
496 if ((et->ty == Taarray && at == Type::tvoid->arrayOf()) ||
497 (et->ty == Tarray && at == Type::tvoid->arrayOf()) ||
498 (et->ty == Tdelegate && at->ty == Tdelegate) ||
499 (et->ty == Tclass && at->ty == Tpointer) ||
500 (et->ty == Tpointer && at->ty == Tpointer)
502 } else {
503 g.ofile->setLoc(exp->loc);
504 ::warning("ackthpbpt: must convert %s to %s\n",
505 exp->type->toChars(), arg->type->toChars());
508 else
510 return exp->toElem(this);
514 // Apply semantics of assignment to a values of type <target_type> to <exp>
515 // (e.g., pointer = array -> pointer = & array[0])
517 // Expects base type to be passed
518 static Type *
519 final_sa_elem_type(Type * type)
521 while (type->ty == Tsarray) {
522 type = type->nextOf()->toBasetype();
524 return type;
527 tree
528 IRState::convertForAssignment(Expression * exp, Type * target_type)
530 Type * exp_base_type = exp->type->toBasetype();
531 Type * target_base_type = target_type->toBasetype();
533 // Assuming this only has to handle converting a non Tsarray type to
534 // arbitrarily dimensioned Tsarrays.
535 if (target_base_type->ty == Tsarray &&
536 typesCompatible(final_sa_elem_type(target_base_type), exp_base_type)) { // %% what about implicit converions...?
538 TypeSArray * sa_type = (TypeSArray *) target_base_type;
539 uinteger_t count = sa_type->dim->toUInteger();
541 tree ctor = make_node( CONSTRUCTOR );
542 TREE_TYPE( ctor ) = target_type->toCtype();
543 if (count) {
544 CtorEltMaker ce;
545 ce.cons( build(RANGE_EXPR, Type::tsize_t->toCtype(),
546 integer_zero_node, integerConstant( count - 1 )),
547 g.ofile->stripVarDecl(convertForAssignment(exp, sa_type->next)));
548 CONSTRUCTOR_ELTS( ctor ) = ce.head;
550 TREE_READONLY( ctor ) = 1;
551 TREE_CONSTANT( ctor ) = 1;
552 return ctor;
553 } else if (! target_type->isscalar() && exp_base_type->isintegral()) {
554 // D Front end uses IntegerExp(0) to mean zero-init a structure
555 // This could go in convert for assignment, but we only see this for
556 // internal init code -- this also includes default init for _d_newarrayi...
558 if (exp->toInteger() == 0) {
559 CtorEltMaker ce;
560 tree empty = make_node( CONSTRUCTOR );
561 TREE_TYPE( empty ) = target_type->toCtype();
562 CONSTRUCTOR_ELTS( empty ) = ce.head; // %% will this zero-init?
563 TREE_CONSTANT( empty ) = 1;
564 // static?
565 return empty;
566 // %%TODO: Use a code (lang_specific in decl or flag) to memset instead?
567 } else {
568 abort();
572 tree exp_tree = exp->toElem(this);
573 return convertForAssignment(exp_tree, exp->type, target_type);
576 tree
577 IRState::convertForAssignment(tree expr, Type * expr_type, Type * target_type)
579 return convertTo(expr, expr_type, target_type);
582 // could be like C c-typeck.c:default_conversion
583 // todo:
585 /* Perform default promotions for C data used in expressions.
586 Arrays and functions are converted to pointers;
587 enumeral types or short or char, to int.
588 In addition, manifest constants symbols are replaced by their values. */
590 // what about float->double?
592 tree
593 IRState::convertForCondition(tree exp_tree, Type * exp_type) {
594 tree result = exp_tree;
595 tree a, b, tmp;
597 switch (exp_type->toBasetype()->ty) {
598 case Taarray:
599 // Shouldn't this be...
600 // result = libCall(LIBCALL_AALEN, 1, & exp_tree);
602 result = component(exp_tree, TYPE_FIELDS(TREE_TYPE(exp_tree)));
603 break;
604 case Tarray:
605 // DMD checks (length || ptr) (i.e ary !is null)
606 tmp = maybeMakeTemp(result);
607 a = delegateObjectRef(tmp);
608 b = delegateMethodRef(tmp);
609 if (TYPE_MODE(TREE_TYPE(a)) == TYPE_MODE(TREE_TYPE(b)))
610 result = build(BIT_IOR_EXPR, TREE_TYPE(a), a, b);
611 else {
612 a = d_truthvalue_conversion(a);
613 b = d_truthvalue_conversion(b);
614 // probably not worth TRUTH_OROR ...
615 result = build(TRUTH_OR_EXPR, TREE_TYPE(a), a, b);
617 break;
618 case Tdelegate:
619 // DMD checks (function || object), but what good
620 // is if if there is a null function pointer?
621 if ( D_IS_METHOD_CALL_EXPR(result) ) {
622 extractMethodCallExpr(result, a, b);
623 } else {
624 tmp = maybeMakeTemp(result);
625 a = delegateObjectRef(tmp);
626 b = delegateMethodRef(tmp);
628 // not worth using or TRUTH_ORIF...
629 // %%TODO: Is this okay for all targets?
630 result = build(BIT_IOR_EXPR, TREE_TYPE(a), a, b);
631 break;
632 default:
633 break;
635 // see expr.c:do_jump for the types of trees that can be passed to expand_start_cond
636 //TREE_USED( <result> ) = 1; // %% maybe not.. expr optimized away because constant expression?
637 return d_truthvalue_conversion( result );
640 /* Convert EXP to a dynamic array. EXP must be a static array or
641 dynamic array. */
642 tree
643 IRState::toDArray(Expression * exp)
645 TY ty = exp->type->toBasetype()->ty;
646 tree val;
647 if (ty == Tsarray) {
648 val = convertTo(exp, exp->type->toBasetype()->nextOf()->arrayOf());
649 } else if (ty == Tarray) {
650 val = exp->toElem(this);
651 } else {
652 gcc_assert(ty == Tsarray || ty == Tarray);
653 return NULL_TREE;
655 return val;
659 tree
660 IRState::pointerIntSum(tree ptr_node, tree idx_exp)
662 tree result_type_node = TREE_TYPE( ptr_node );
663 tree intop = idx_exp;
664 tree size_exp;
666 // %% TODO: real-not-long-double issues...
668 // %% test for void case ...
669 size_exp = size_in_bytes( TREE_TYPE( result_type_node ) ); // array element size
670 if (integer_zerop(size_exp))
671 size_exp = integer_one_node;
673 if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
674 || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
675 intop = convert (d_type_for_size (TYPE_PRECISION (sizetype),
676 TREE_UNSIGNED (sizetype)), intop);
678 intop = convert (result_type_node,
679 build/*_binary_op*/ (MULT_EXPR, TREE_TYPE(size_exp), intop, // the type here may be wrong %%
680 convert (TREE_TYPE (intop), size_exp)));
681 intop = fold(intop);
683 if ( integer_zerop(intop) )
684 return ptr_node;
685 else
686 return build(PLUS_EXPR, result_type_node, ptr_node, intop);
689 // Doesn't do some of the omptimizations in ::makeArrayElemRef
690 tree
691 IRState::checkedIndex(Loc loc, tree index, tree upper_bound, bool inclusive)
693 if (global.params.useArrayBounds) {
694 return build(COND_EXPR, TREE_TYPE(index),
695 boundsCond(index, upper_bound, inclusive),
696 index,
697 assertCall(loc, LIBCALL_ARRAY_BOUNDS));
698 } else {
699 return index;
704 // index must be wrapped in a SAVE_EXPR to prevent multiple evaluation...
705 tree
706 IRState::boundsCond(tree index, tree upper_bound, bool inclusive)
708 tree bound_check;
710 bound_check = build(inclusive ? LE_EXPR : LT_EXPR, boolean_type_node,
711 convert( d_unsigned_type(TREE_TYPE(index)), index ),
712 upper_bound);
714 if (! TREE_UNSIGNED( TREE_TYPE( index ))) {
715 bound_check = build(TRUTH_ANDIF_EXPR, boolean_type_node, bound_check,
716 // %% conversions
717 build(GE_EXPR, boolean_type_node, index, integer_zero_node));
720 return bound_check;
723 tree
724 IRState::assertCall(Loc loc, LibCall libcall)
726 tree args[2] = { darrayString(loc.filename ? loc.filename : ""),
727 integerConstant(loc.linnum, Type::tuns32) };
728 return libCall(libcall, 2, args);
731 tree
732 IRState::assertCall(Loc loc, Expression * msg)
734 tree args[3] = { msg->toElem(this),
735 darrayString(loc.filename ? loc.filename : ""),
736 integerConstant(loc.linnum, Type::tuns32) };
737 return libCall(LIBCALL_ASSERT_MSG, 3, args);
740 tree
741 IRState::floatConstant(const real_t & value, TypeBasic * target_type )
743 REAL_VALUE_TYPE converted_val;
745 tree type_node = target_type->toCtype();
746 real_convert(& converted_val, TYPE_MODE(type_node), & value.rv());
748 return build_real(type_node, converted_val);
751 xdmd_integer_t
752 IRState::hwi2toli(HOST_WIDE_INT low, HOST_WIDE_INT high)
754 uinteger_t result;
755 if (sizeof(HOST_WIDE_INT) < sizeof(xdmd_integer_t))
757 gcc_assert(sizeof(HOST_WIDE_INT) * 2 == sizeof(xdmd_integer_t));
758 result = (unsigned HOST_WIDE_INT) low;
759 result += ((uinteger_t) (unsigned HOST_WIDE_INT) high) << HOST_BITS_PER_WIDE_INT;
761 else
762 result = low;
763 return result;
767 #if D_GCC_VER >= 40
768 tree
769 IRState::binding(tree var_chain, tree body)
771 // BIND_EXPR/DECL_INITIAL not supported in 4.0?
772 gcc_assert(TREE_CHAIN(var_chain) == NULL_TREE); // TODO: only handles one var
774 if ( DECL_INITIAL(var_chain) )
776 tree ini = build2(MODIFY_EXPR, void_type_node, var_chain, DECL_INITIAL(var_chain));
777 DECL_INITIAL(var_chain) = NULL_TREE;
778 body = compound(ini, body);
781 return build3(BIND_EXPR, TREE_TYPE(body), var_chain, body, NULL_TREE);
783 #endif
785 tree
786 IRState::libCall(LibCall lib_call, unsigned n_args, tree *args, tree force_result_type)
788 tree result;
789 tree callee = functionPointer( getLibCallDecl( lib_call ));
790 // for force_result_type, assumes caller knows what it is doing %%
791 tree result_type = force_result_type != NULL_TREE ?
792 force_result_type : TREE_TYPE(TREE_TYPE(TREE_OPERAND(callee, 0)));
793 tree arg_list = NULL_TREE;
794 for (int i = n_args - 1; i >= 0; i--) {
795 arg_list = tree_cons(NULL_TREE, args[i], arg_list);
798 result = buildCall(result_type, callee, arg_list);
799 return result;
802 static inline bool
803 function_type_p(tree t)
805 return TREE_CODE(t) == FUNCTION_TYPE || TREE_CODE(t) == METHOD_TYPE;
808 // Assumes T is already ->toBasetype()
809 static TypeFunction *
810 get_function_type(Type * t)
812 TypeFunction* tf = NULL;
813 if (t->ty == Tpointer)
814 t = t->nextOf()->toBasetype();
815 if (t->ty == Tfunction)
816 tf = (TypeFunction *) t;
817 else if (t->ty == Tdelegate)
818 tf = (TypeFunction *) ((TypeDelegate *) t)->next;
819 return tf;
822 tree IRState::errorMark(Type * t)
824 return nop(error_mark_node, t->toCtype());
827 tree
828 IRState::call(Expression * expr, /*TypeFunction * func_type, */ Array * arguments)
830 // Calls to delegates can sometimes look like this:
831 if (expr->op == TOKcomma)
833 CommaExp * ce = (CommaExp *) expr;
834 expr = ce->e2;
836 VarExp * ve;
837 gcc_assert( ce->e2->op == TOKvar );
838 ve = (VarExp *) ce->e2;
839 gcc_assert(ve->var->isFuncDeclaration() && ! ve->var->needThis());
842 Type* t = expr->type->toBasetype();
843 TypeFunction* tf = NULL;
844 tree callee = expr->toElem(this);
845 tree object = NULL_TREE;
847 if ( D_IS_METHOD_CALL_EXPR( callee ) ) {
848 /* This could be a delegate expression (TY == Tdelegate), but not
849 actually a delegate variable. */
850 tf = get_function_type(t);
851 extractMethodCallExpr(callee, callee, object);
852 } else if ( t->ty == Tdelegate) {
853 tf = (TypeFunction*) ((TypeDelegate *) t)->next;
854 callee = maybeMakeTemp(callee);
855 object = delegateObjectRef(callee);
856 callee = delegateMethodRef(callee);
857 } else if (expr->op == TOKvar) {
858 FuncDeclaration * fd = ((VarExp *) expr)->var->isFuncDeclaration();
859 tf = (TypeFunction *) fd->type;
860 if (fd) {
861 if (fd->isNested()) {
862 #if D_NO_TRAMPOLINES
863 object = getFrameForFunction(fd);
864 #else
865 // Pass fake argument for nested functions
866 object = d_null_pointer;
867 #endif
868 } else if (fd->needThis()) {
869 expr->error("need 'this' to access member %s", fd->toChars());
870 object = d_null_pointer; // continue processing...
873 } else {
874 tf = get_function_type(t);
876 return call(tf, callee, object, arguments);
879 tree
880 IRState::call(FuncDeclaration * func_decl, Array * args)
882 assert(! func_decl->isNested()); // Otherwise need to copy code from above
883 return call((TypeFunction *) func_decl->type, func_decl->toSymbol()->Stree, NULL_TREE, args);
886 tree
887 IRState::call(FuncDeclaration * func_decl, tree object, Array * args)
889 return call((TypeFunction *)func_decl->type, functionPointer(func_decl),
890 object, args);
893 tree
894 IRState::call(TypeFunction *func_type, tree callable, tree object, Array * arguments)
896 // Using TREE_TYPE( callable ) instead of func_type->toCtype can save a build_method_type
897 tree func_type_node = TREE_TYPE( callable );
898 tree actual_callee = callable;
900 if ( POINTER_TYPE_P( func_type_node ) )
901 func_type_node = TREE_TYPE( func_type_node );
902 else
903 actual_callee = addressOf( callable );
905 assert( function_type_p( func_type_node ) );
906 assert( func_type != NULL );
907 assert( func_type->ty == Tfunction );
909 bool is_d_vararg = func_type->varargs == 1 && func_type->linkage == LINKd;
911 // Account for the hidden object/frame pointer argument
913 if ( TREE_CODE( func_type_node ) == FUNCTION_TYPE ) {
914 if ( object != NULL_TREE ) {
915 // Happens when a delegate value is called
916 tree method_type = build_method_type( TREE_TYPE( object ), func_type_node );
917 TYPE_ATTRIBUTES( method_type ) = TYPE_ATTRIBUTES( func_type_node );
918 func_type_node = method_type;
920 } else /* METHOD_TYPE */ {
921 if ( ! object ) {
922 // Front-end apparently doesn't check this.
923 if (TREE_CODE(callable) == FUNCTION_DECL ) {
924 error("need 'this' to access member %s", IDENTIFIER_POINTER( DECL_NAME( callable )));
925 return error_mark_node;
926 } else {
927 // Probably an internal error
928 assert(object != NULL_TREE);
933 ListMaker actual_arg_list;
935 /* If this is a delegate call or a nested function being called as
936 a delegate, the object should not be NULL. */
937 if (object != NULL_TREE)
938 actual_arg_list.cons( object );
940 Arguments * formal_args = func_type->parameters; // can be NULL for genCfunc decls
941 size_t n_formal_args = formal_args ? (int) Argument::dim(formal_args) : 0;
942 size_t n_actual_args = arguments ? arguments->dim : 0;
943 size_t fi = 0;
945 // assumes arguments->dim <= formal_args->dim if (! this->varargs)
946 for (size_t ai = 0; ai < n_actual_args; ++ai) {
947 tree actual_arg_tree;
949 Expression * actual_arg_exp = (Expression *) arguments->data[ai];
950 if (ai == 0 && is_d_vararg) {
951 // The hidden _arguments parameter
952 actual_arg_tree = actual_arg_exp->toElem(this);
953 } else if (fi < n_formal_args) {
954 // Actual arguments for declared formal arguments
955 Argument * formal_arg = Argument::getNth(formal_args, fi);
957 actual_arg_tree = convertForArgument(actual_arg_exp, formal_arg);
959 // from c-typeck.c: convert_arguments, default_conversion, ...
960 if (INTEGRAL_TYPE_P (TREE_TYPE(actual_arg_tree))
961 && (TYPE_PRECISION (TREE_TYPE(actual_arg_tree)) <
962 TYPE_PRECISION (integer_type_node))) {
964 actual_arg_tree = d_convert_basic(integer_type_node, actual_arg_tree);
966 ++fi;
967 } else {
968 if (splitDynArrayVarArgs && actual_arg_exp->type->toBasetype()->ty == Tarray)
970 tree da_exp = maybeMakeTemp( actual_arg_exp->toElem(this) );
971 actual_arg_list.cons( darrayLenRef( da_exp ) );
972 actual_arg_list.cons( darrayPtrRef( da_exp ) );
973 continue;
975 else
977 actual_arg_tree = actual_arg_exp->toElem( this );
979 /* Not all targets support passing unpromoted types, so
980 promote anyway. */
981 tree prom_type = d_type_promotes_to( TREE_TYPE( actual_arg_tree ));
982 if (prom_type != TREE_TYPE( actual_arg_tree ))
983 actual_arg_tree = d_convert_basic(prom_type, actual_arg_tree);
987 //TREE_USED( actual_arg_tree ) = 1; // needed ?
988 actual_arg_list.cons( actual_arg_tree );
991 tree result = buildCall(TREE_TYPE(func_type_node), actual_callee, actual_arg_list.head);
992 return maybeExpandSpecialCall(result);
995 static const char * libcall_ids[LIBCALL_count] =
996 { "_d_assert", "_d_assert_msg", "_d_array_bounds", "_d_switch_error",
997 "_D9invariant12_d_invariantFC6ObjectZv",
998 "_d_newclass", "_d_newarrayT",
999 "_d_newarrayiT",
1000 "_d_newarraymTp", "_d_newarraymiTp", "_d_allocmemory",
1001 "_d_delclass", "_d_delinterface", "_d_delarray",
1002 "_d_delmemory", "_d_callfinalizer", "_d_callinterfacefinalizer",
1003 "_d_arraysetlengthT", "_d_arraysetlengthiT",
1004 "_d_dynamic_cast", "_d_interface_cast",
1005 "_adEq", "_adCmp", "_adCmpChar",
1006 "_aaLen",
1007 //"_aaIn", "_aaGet", "_aaGetRvalue", "_aaDel",
1008 "_aaInp", "_aaGetp", "_aaGetRvaluep", "_aaDelp",
1009 "_d_arraycast",
1010 "_d_arraycopy",
1011 "_d_arraycatT", "_d_arraycatnT",
1012 "_d_arrayappendT",
1013 /*"_d_arrayappendc", */"_d_arrayappendcTp",
1014 #if V2
1015 "_d_arrayassign", "_d_arrayctor", "_d_arraysetassign",
1016 "_d_arraysetctor",
1017 #endif
1018 "_d_monitorenter", "_d_monitorexit",
1019 "_d_criticalenter", "_d_criticalexit",
1020 "_d_throw",
1021 "_d_switch_string", "_d_switch_ustring", "_d_switch_dstring",
1022 "_d_assocarrayliteralTp"
1023 #if V2
1025 "_d_hidden_func"
1026 #endif
1029 static FuncDeclaration * libcall_decls[LIBCALL_count];
1031 void
1032 IRState::replaceLibCallDecl(FuncDeclaration * d_decl)
1034 if ( ! d_decl->ident )
1035 return;
1036 for (unsigned i = 0; i < LIBCALL_count; i++) {
1037 if ( strcmp(d_decl->ident->string, libcall_ids[i]) == 0 ) {
1038 // %% warn if libcall already set?
1039 // Only do this for the libcalls where it's a problem, otherwise
1040 // it causes other problems...
1041 switch ((LibCall) i) {
1042 // case LIBCALL_GNU_BITARRAYSLICEP:
1043 case LIBCALL_ARRAYCOPY: // this could be solved by turning copy of char into memcpy
1044 case LIBCALL_ARRAYCAST:
1045 // replace the function declaration
1046 break;
1047 default:
1048 // don't replace
1049 return;
1051 libcall_decls[i] = d_decl;
1052 break;
1058 FuncDeclaration *
1059 IRState::getLibCallDecl(LibCall lib_call)
1061 FuncDeclaration * decl = libcall_decls[lib_call];
1062 Array arg_types;
1063 Type * t = NULL;
1064 bool varargs = false;
1066 if (! decl) {
1067 Type * return_type = Type::tvoid;
1069 switch (lib_call) {
1070 case LIBCALL_ASSERT:
1071 case LIBCALL_ARRAY_BOUNDS:
1072 case LIBCALL_SWITCH_ERROR:
1073 // need to spec chararray/string because internal code passes string constants
1074 arg_types.reserve(2);
1075 arg_types.push( Type::tchar->arrayOf() );
1076 arg_types.push( Type::tuns32 );
1077 break;
1078 case LIBCALL_ASSERT_MSG:
1079 arg_types.reserve(3);
1080 arg_types.push( Type::tchar->arrayOf() );
1081 arg_types.push( Type::tchar->arrayOf() );
1082 arg_types.push( Type::tuns32 );
1083 break;
1084 case LIBCALL_NEWCLASS:
1085 arg_types.push( ClassDeclaration::classinfo->type );
1086 return_type = getObjectType();
1087 break;
1088 case LIBCALL_NEWARRAYT:
1089 case LIBCALL_NEWARRAYIT:
1090 arg_types.push( Type::typeinfo->type );
1091 arg_types.push( Type::tsize_t );
1092 return_type = Type::tvoid->arrayOf();
1093 break;
1094 case LIBCALL_NEWARRAYMTP:
1095 case LIBCALL_NEWARRAYMITP:
1096 arg_types.push( Type::tsize_t );
1097 arg_types.push( Type::tint32 ); // Currently 'int', even if 64-bit
1098 arg_types.push( Type::typeinfo->type );
1099 if (lib_call == LIBCALL_NEWARRAYMITP)
1100 arg_types.push( Type::tsize_t );
1101 break;
1102 case LIBCALL_ALLOCMEMORY:
1103 arg_types.push( Type::tsize_t );
1104 return_type = Type::tvoidptr;
1105 break;
1106 case LIBCALL_DELCLASS:
1107 case LIBCALL_DELINTERFACE:
1108 arg_types.push(Type::tvoid->pointerTo());
1109 break;
1110 case LIBCALL_DELARRAY:
1111 arg_types.push(Type::tvoid->arrayOf()->pointerTo());
1112 break;
1113 case LIBCALL_DELMEMORY:
1114 arg_types.push(Type::tvoid->pointerTo()->pointerTo());
1115 break;
1116 case LIBCALL_CALLFINALIZER:
1117 case LIBCALL_CALLINTERFACEFINALIZER:
1118 arg_types.push(Type::tvoid->pointerTo());
1119 break;
1120 case LIBCALL_ARRAYSETLENGTHT:
1121 case LIBCALL_ARRAYSETLENGTHIT:
1122 arg_types.push( Type::typeinfo->type );
1123 arg_types.push( Type::tsize_t );
1124 arg_types.push( Type::tvoid->arrayOf()->pointerTo() );
1125 return_type = Type::tvoid->arrayOf();
1126 break;
1127 case LIBCALL_DYNAMIC_CAST:
1128 case LIBCALL_INTERFACE_CAST:
1129 arg_types.push( getObjectType() );
1130 arg_types.push( ClassDeclaration::classinfo->type );
1131 return_type = getObjectType();
1132 break;
1133 case LIBCALL_ADEQ:
1134 case LIBCALL_ADCMP:
1135 arg_types.reserve(3);
1136 arg_types.push(Type::tvoid->arrayOf());
1137 arg_types.push(Type::tvoid->arrayOf());
1138 arg_types.push(Type::typeinfo->type);
1139 return_type = Type::tint32;
1140 break;
1141 case LIBCALL_ADCMPCHAR:
1142 arg_types.reserve(2);
1143 arg_types.push(Type::tchar->arrayOf());
1144 arg_types.push(Type::tchar->arrayOf());
1145 return_type = Type::tint32;
1146 break;
1147 // case LIBCALL_AAIN:
1148 // case LIBCALL_AAGET:
1149 // case LIBCALL_AAGETRVALUE:
1150 // case LIBCALL_AADEL:
1151 case LIBCALL_AALEN:
1152 case LIBCALL_AAINP:
1153 case LIBCALL_AAGETP:
1154 case LIBCALL_AAGETRVALUEP:
1155 case LIBCALL_AADELP:
1157 static Type * aa_type = NULL;
1158 if (! aa_type)
1159 aa_type = new TypeAArray(Type::tvoid->pointerTo(),
1160 Type::tvoid->pointerTo());
1162 if (lib_call == LIBCALL_AALEN)
1164 arg_types.push(aa_type);
1165 return_type = Type::tsize_t;
1166 break;
1169 if (lib_call == LIBCALL_AAGETP)
1170 aa_type = aa_type->pointerTo();
1172 arg_types.reserve(3);
1173 arg_types.push(aa_type);
1174 arg_types.push(Type::typeinfo->type); // typeinfo reference
1175 if ( lib_call == LIBCALL_AAGETP || lib_call == LIBCALL_AAGETRVALUEP)
1176 arg_types.push(Type::tsize_t);
1178 arg_types.push(Type::tvoid->pointerTo());
1180 switch (lib_call) {
1181 case LIBCALL_AAINP:
1182 case LIBCALL_AAGETP:
1183 case LIBCALL_AAGETRVALUEP:
1184 return_type = Type::tvoid->pointerTo();
1185 break;
1186 case LIBCALL_AADELP:
1187 return_type = Type::tvoid;
1188 break;
1189 default:
1190 assert(0);
1193 break;
1194 case LIBCALL_ARRAYCAST:
1195 t = Type::tvoid->arrayOf();
1196 arg_types.push(Type::tsize_t);
1197 arg_types.push(Type::tsize_t);
1198 arg_types.push(t);
1199 return_type = t;
1200 break;
1201 case LIBCALL_ARRAYCOPY:
1202 t = Type::tvoid->arrayOf();
1203 arg_types.push(Type::tsize_t);
1204 arg_types.push(t);
1205 arg_types.push(t);
1206 return_type = t;
1207 break;
1208 case LIBCALL_ARRAYCATT:
1209 arg_types.push(Type::typeinfo->type);
1210 t = Type::tvoid->arrayOf();
1211 arg_types.push(t);
1212 arg_types.push(t);
1213 return_type = t;
1214 break;
1215 case LIBCALL_ARRAYCATNT:
1216 arg_types.push(Type::typeinfo->type);
1217 arg_types.push(Type::tuns32); // Currently 'uint', even if 64-bit
1218 varargs = true;
1219 return_type = Type::tvoid->arrayOf();
1220 break;
1221 case LIBCALL_ARRAYAPPENDT:
1222 arg_types.push(Type::typeinfo->type);
1223 t = Type::tuns8->arrayOf();
1224 arg_types.push(t->pointerTo());
1225 arg_types.push(t);
1226 return_type = Type::tvoid->arrayOf();
1227 break;
1228 // case LIBCALL_ARRAYAPPENDCT:
1229 case LIBCALL_ARRAYAPPENDCTP:
1230 arg_types.push(Type::typeinfo->type);
1231 t = Type::tuns8->arrayOf();
1232 arg_types.push(t);
1233 arg_types.push(Type::tvoid->pointerTo()); // varargs = true;
1234 return_type = Type::tvoid->arrayOf();
1235 break;
1236 #if V2
1237 case LIBCALL_ARRAYASSIGN:
1238 case LIBCALL_ARRAYCTOR:
1239 arg_types.push(Type::typeinfo->type);
1240 arg_types.push(Type::tvoid->arrayOf());
1241 return_type = Type::tvoid->arrayOf();
1242 break;
1243 case LIBCALL_ARRAYSETASSIGN:
1244 case LIBCALL_ARRAYSETCTOR:
1245 arg_types.push(Type::tvoid->pointerTo());
1246 arg_types.push(Type::tvoid->pointerTo());
1247 arg_types.push(Type::tsize_t);
1248 arg_types.push(Type::typeinfo->type);
1249 return_type = Type::tvoid->pointerTo();
1250 break;
1251 #endif
1252 case LIBCALL_MONITORENTER:
1253 case LIBCALL_MONITOREXIT:
1254 case LIBCALL_THROW:
1255 case LIBCALL_INVARIANT:
1256 arg_types.push(getObjectType());
1257 break;
1258 case LIBCALL_CRITICALENTER:
1259 case LIBCALL_CRITICALEXIT:
1260 arg_types.push(Type::tvoid->pointerTo());
1261 break;
1262 case LIBCALL_SWITCH_USTRING:
1263 t = Type::twchar;
1264 goto do_switch_string;
1265 case LIBCALL_SWITCH_DSTRING:
1266 t = Type::tdchar;
1267 goto do_switch_string;
1268 case LIBCALL_SWITCH_STRING:
1269 t = Type::tchar;
1270 do_switch_string:
1271 t = t->arrayOf();
1272 arg_types.push(t->arrayOf());
1273 arg_types.push(t);
1274 return_type = Type::tint32;
1275 break;
1276 case LIBCALL_ASSOCARRAYLITERALTP:
1277 arg_types.push(Type::typeinfo->type);
1278 arg_types.push(Type::tsize_t);
1279 arg_types.push(Type::tvoid->pointerTo());
1280 arg_types.push(Type::tvoid->pointerTo());
1281 return_type = Type::tvoid->pointerTo();
1282 break;
1283 #if V2
1284 case LIBCALL_HIDDEN_FUNC:
1285 /* Argument is an Object, but can't use that as
1286 LIBCALL_HIDDEN_FUNC is needed before the Object type is
1287 created. */
1288 arg_types.push(Type::tvoid->pointerTo());
1289 break;
1290 #endif
1291 default:
1292 gcc_unreachable();
1294 decl = FuncDeclaration::genCfunc(return_type, (char *) libcall_ids[lib_call]);
1296 TypeFunction * tf = (TypeFunction *) decl->type;
1297 tf->varargs = varargs ? 1 : 0;
1298 Arguments * args = new Arguments;
1299 args->setDim( arg_types.dim );
1300 for (unsigned i = 0; i < arg_types.dim; i++)
1301 args->data[i] = new Argument( STCin, (Type *) arg_types.data[i],
1302 NULL, NULL);
1303 tf->parameters = args;
1305 libcall_decls[lib_call] = decl;
1307 return decl;
1310 static tree
1311 fix_d_va_list_type(tree val)
1313 if (POINTER_TYPE_P(va_list_type_node) ||
1314 INTEGRAL_TYPE_P(va_list_type_node))
1315 return build1(NOP_EXPR, va_list_type_node, val);
1316 else
1317 return val;
1320 tree IRState::maybeExpandSpecialCall(tree call_exp)
1322 // More code duplication from C
1324 tree callee = TREE_OPERAND(call_exp, 0);
1325 tree t, op;
1326 if (POINTER_TYPE_P(TREE_TYPE( callee ))) {
1327 callee = TREE_OPERAND(callee, 0);
1329 if (TREE_CODE(callee) == FUNCTION_DECL) {
1330 if (DECL_BUILT_IN_CLASS(callee) == NOT_BUILT_IN) {
1331 // the most common case
1332 return call_exp;
1333 } else if (DECL_BUILT_IN_CLASS(callee) == BUILT_IN_NORMAL) {
1334 switch (DECL_FUNCTION_CODE(callee)) {
1335 case BUILT_IN_ABS:
1336 case BUILT_IN_LABS:
1337 case BUILT_IN_LLABS:
1338 case BUILT_IN_IMAXABS:
1339 /* The above are required for both 3.4. Not sure about later
1340 versions. */
1341 /* OLDOLDOLD below supposedly for 3.3 only */
1343 case BUILT_IN_FABS:
1344 case BUILT_IN_FABSL:
1345 case BUILT_IN_FABSF:
1347 op = TREE_VALUE( TREE_OPERAND( call_exp, 1 ));
1348 t = build1(ABS_EXPR, TREE_TYPE(op), op);
1349 return d_convert_basic(TREE_TYPE(call_exp), t);
1350 // probably need a few more cases:
1351 default:
1352 return call_exp;
1354 } else if (DECL_BUILT_IN_CLASS(callee) == BUILT_IN_FRONTEND) {
1355 Intrinsic intrinsic = (Intrinsic) DECL_FUNCTION_CODE(callee);
1356 tree type;
1357 Type *d_type;
1358 switch (intrinsic) {
1359 case INTRINSIC_C_VA_ARG:
1360 // %% should_check c_promotes_to as in va_arg now
1361 // just drop though for now...
1362 case INTRINSIC_STD_VA_ARG:
1363 t = TREE_VALUE(TREE_OPERAND(call_exp, 1));
1364 // signature is (inout va_list), but VA_ARG_EXPR expects the
1365 // list itself... but not if the va_list type is an array. In that
1366 // case, it should be a pointer
1367 if ( TREE_CODE( va_list_type_node ) != ARRAY_TYPE ) {
1368 if ( TREE_CODE( t ) == ADDR_EXPR ) {
1369 t = TREE_OPERAND(t, 0);
1370 } else {
1371 // this probably doesn't happen... passing an inout va_list argument,
1372 // but again, it's probably { & ( * inout_arg ) }
1373 t = build1(INDIRECT_REF, TREE_TYPE(TREE_TYPE(t)), t);
1376 t = fix_d_va_list_type(t);
1377 type = TREE_TYPE(TREE_TYPE(callee));
1378 if (splitDynArrayVarArgs && (d_type = getDType(type)) &&
1379 d_type->toBasetype()->ty == Tarray)
1381 // should create a temp var of type TYPE and move the binding
1382 // to outside this expression.
1383 t = stabilize_reference(t);
1384 tree ltype = TREE_TYPE( TYPE_FIELDS( type ));
1385 tree ptype = TREE_TYPE( TREE_CHAIN( TYPE_FIELDS( type )));
1386 tree lvar = exprVar(ltype);
1387 tree pvar = exprVar(ptype);
1388 tree e1 = vmodify(lvar, build1(VA_ARG_EXPR, ltype, t));
1389 tree e2 = vmodify(pvar, build1(VA_ARG_EXPR, ptype, t));
1390 tree b = compound( compound( e1, e2 ), darrayVal(type, lvar, pvar) );
1391 return binding(lvar, binding(pvar, b));
1393 else
1395 tree type2 = d_type_promotes_to(type);
1396 t = build1(VA_ARG_EXPR, type2, t);
1397 if (type != type2)
1398 // silently convert promoted type...
1399 t = d_convert_basic(type, t);
1400 return t;
1402 break;
1403 case INTRINSIC_C_VA_START:
1405 t = TREE_VALUE();
1406 // signature is (inout va_list), but VA_ARG_EXPR expects the
1407 // list itself...
1408 if ( TREE_CODE( t ) == ADDR_EXPR ) {
1409 t = TREE_OPERAND(t, 0);
1410 } else {
1411 // this probably doesn't happen... passing an inout va_list argument,
1412 // but again, it's probably { & ( * inout_arg ) }
1413 t = build1(INDIRECT_REF, TREE_TYPE(TREE_TYPE(t)), t);
1416 // The va_list argument should already have its
1417 // address taken. The second argument, however, is
1418 // inout and that needs to be fixed to prevent a warning.
1420 tree val_arg = TREE_VALUE(TREE_OPERAND(call_exp, 1));
1421 // kinda wrong... could be casting.. so need to check type too?
1422 while ( TREE_CODE( val_arg ) == NOP_EXPR )
1423 val_arg = TREE_OPERAND(val_arg, 0);
1424 if ( TREE_CODE( val_arg ) == ADDR_EXPR ) {
1425 val_arg = TREE_OPERAND(val_arg, 0);
1426 val_arg = fix_d_va_list_type(val_arg);
1427 val_arg = addressOf( val_arg );
1428 } else
1429 val_arg = fix_d_va_list_type(val_arg);
1431 t = TREE_VALUE(TREE_CHAIN(TREE_OPERAND(call_exp, 1)));
1432 if ( TREE_CODE( t ) == ADDR_EXPR ) {
1433 t = TREE_OPERAND(t, 0);
1436 return buildCall( void_type_node, // assuming nobody tries to change the return type
1437 addressOf( built_in_decls[BUILT_IN_VA_START] ),
1438 tree_cons( NULL_TREE, val_arg,
1439 tree_cons( NULL_TREE, t, NULL_TREE )));
1441 default:
1442 abort();
1443 break;
1446 } else if (0 /** WIP **/ && DECL_BUILT_IN_CLASS(callee) == BUILT_IN_FRONTEND) {
1447 // %%TODO: need to handle BITS_BIG_ENDIAN
1448 // %%TODO: need to make expressions unsigned
1450 Intrinsic intrinsic = (Intrinsic) DECL_FUNCTION_CODE(callee);
1451 // Might as well do intrinsics here...
1452 switch (intrinsic) {
1453 case INTRINSIC_BSF: // This will use bsf on x86, but BSR becomes 31-(bsf)!!
1454 // drop through
1455 case INTRINSIC_BSR:
1456 // %% types should be correct, but should still check..
1457 // %% 64-bit..
1458 return call_exp;
1459 //YOWZA1
1460 #if D_GCC_VER >= 34
1461 return buildCall(TREE_TYPE(call_exp),
1462 built_in_decls[intrinsic == INTRINSIC_BSF ? BUILT_IN_CTZ : BUILT_IN_CLZ],
1463 TREE_OPERAND(call_exp, 1));
1464 #else
1465 return call_exp;
1466 #endif
1467 case INTRINSIC_BT:
1468 case INTRINSIC_BTC:
1469 case INTRINSIC_BTR:
1470 case INTRINSIC_BTS:
1471 break;
1472 case INTRINSIC_BSWAP:
1473 #if defined(TARGET_386)
1475 #endif
1476 break;
1477 case INTRINSIC_INP:
1478 case INTRINSIC_INPW:
1479 case INTRINSIC_INPL:
1480 case INTRINSIC_OUTP:
1481 case INTRINSIC_OUTPW:
1482 case INTRINSIC_OUTPL:
1483 #ifdef TARGET_386
1484 #else
1485 ::error("Port I/O intrinsic '%s' is only available on ix86 targets",
1486 IDENTIFIER_POINTER(DECL_NAME(callee)));
1487 #endif
1488 break;
1489 default:
1490 abort();
1495 return call_exp;
1498 tree
1499 IRState::arrayElemRef(IndexExp * aer_exp, ArrayScope * aryscp)
1501 Expression * e1 = aer_exp->e1;
1502 Expression * e2 = aer_exp->e2;
1504 Type * base_type = e1->type->toBasetype();
1505 TY base_type_ty = base_type->ty;
1507 #if ! V2
1508 gcc_assert(! base_type->next->isbit());
1509 #endif
1511 tree index_expr; // logical index
1512 tree subscript_expr; // expr that indexes the array data
1513 tree ptr_exp; // base pointer to the elements
1514 tree elem_ref; // reference the the element
1516 index_expr = e2->toElem( this );
1517 subscript_expr = index_expr;
1519 switch (base_type_ty) {
1520 case Tarray:
1521 case Tsarray:
1523 tree e1_tree = e1->toElem(this);
1525 e1_tree = aryscp->setArrayExp(e1_tree, e1->type);
1527 if ( global.params.useArrayBounds &&
1528 // If it's a static array and the index is
1529 // constant, the front end has already
1530 // checked the bounds.
1531 ! (base_type_ty == Tsarray && e2->isConst()) ) {
1534 tree array_len_expr, throw_expr, oob_cond;
1535 // implement bounds check as a conditional expression:
1536 // a[ inbounds(index) ? index : { throw ArrayBoundsError } ]
1538 // First, set up the index expression to only be evaluated
1539 // once.
1540 // %% save_expr does this check: if (! TREE_CONSTANT( index_expr ))
1541 // %% so we don't do a <0 check for a[2]...
1542 index_expr = maybeMakeTemp( index_expr );
1544 if (base_type_ty == Tarray) {
1545 e1_tree = maybeMakeTemp(e1_tree);
1546 array_len_expr = darrayLenRef(e1_tree);
1547 } else {
1548 array_len_expr = ((TypeSArray *) base_type)->dim->toElem(this);
1551 oob_cond = boundsCond(index_expr, array_len_expr, false);
1552 throw_expr = assertCall(aer_exp->loc, LIBCALL_ARRAY_BOUNDS);
1554 subscript_expr = build( COND_EXPR, TREE_TYPE( index_expr ),
1555 oob_cond, index_expr, throw_expr );
1558 // %% TODO: make this an ARRAY_REF?
1559 if (base_type_ty == Tarray)
1560 ptr_exp = darrayPtrRef( e1_tree ); // %% do convert in darrayPtrRef?
1561 else
1562 ptr_exp = addressOf( e1_tree );
1563 // This conversion is required for static arrays and is just-to-be-safe
1564 // for dynamic arrays
1565 ptr_exp = d_convert_basic(base_type->nextOf()->pointerTo()->toCtype(), ptr_exp);
1567 break;
1568 case Tpointer:
1569 // Ignores aryscp
1570 ptr_exp = e1->toElem( this );
1571 break;
1572 default:
1573 abort();
1576 ptr_exp = pvoidOkay( ptr_exp );
1577 subscript_expr = aryscp->finish( subscript_expr );
1578 elem_ref = indirect(pointerIntSum( ptr_exp, subscript_expr),
1579 TREE_TYPE(TREE_TYPE(ptr_exp)));
1581 return elem_ref;
1584 tree
1585 IRState::darrayPtrRef(tree exp)
1587 // Get the backend type for the array and pick out the array data
1588 // pointer field (assumed to be the second field.)
1589 tree ptr_field = TREE_CHAIN( TYPE_FIELDS( TREE_TYPE( exp )));
1590 //return build(COMPONENT_REF, TREE_TYPE( ptr_field ), exp, ptr_field);
1591 return component(exp, ptr_field);
1594 tree
1595 IRState::darrayLenRef(tree exp)
1597 // Get the backend type for the array and pick out the array length
1598 // field (assumed to be the first field.)
1599 tree len_field = TYPE_FIELDS( TREE_TYPE( exp ));
1600 return component(exp, len_field);
1604 tree
1605 IRState::darrayVal(tree type, tree len, tree data)
1607 // %% assert type is a darray
1608 tree ctor = make_node( CONSTRUCTOR );
1609 tree len_field, ptr_field;
1610 CtorEltMaker ce;
1612 TREE_TYPE( ctor ) = type;
1613 TREE_STATIC( ctor ) = 0; // can be set by caller if needed
1614 TREE_CONSTANT( ctor ) = 0; // "
1615 len_field = TYPE_FIELDS( TREE_TYPE( ctor ));
1616 ptr_field = TREE_CHAIN( len_field );
1618 ce.cons(len_field, len);
1619 ce.cons(ptr_field, data); // shouldn't need to convert the pointer...
1620 CONSTRUCTOR_ELTS( ctor ) = ce.head;
1622 return ctor;
1625 tree
1626 IRState::darrayVal(tree type, uinteger_t len, tree data)
1628 // %% assert type is a darray
1629 tree ctor = make_node( CONSTRUCTOR );
1630 tree len_value, ptr_value, len_field, ptr_field;
1631 CtorEltMaker ce;
1633 TREE_TYPE( ctor ) = type;
1634 TREE_STATIC( ctor ) = 0; // can be set by caller if needed
1635 TREE_CONSTANT( ctor ) = 0; // "
1636 len_field = TYPE_FIELDS( TREE_TYPE( ctor ));
1637 ptr_field = TREE_CHAIN( len_field );
1639 if (data ) {
1640 assert( POINTER_TYPE_P( TREE_TYPE( data )));
1641 ptr_value = data;
1642 } else {
1643 ptr_value = d_null_pointer;
1646 len_value = integerConstant(len, TREE_TYPE(len_field));
1648 ce.cons(len_field, len_value);
1649 ce.cons(ptr_field, ptr_value ); // shouldn't need to convert the pointer...
1651 CONSTRUCTOR_ELTS( ctor ) = ce.head;
1653 return ctor;
1656 tree
1657 IRState::darrayString(const char * str)
1659 unsigned len = strlen(str);
1660 // %% assumes str is null-terminated
1661 tree str_tree = build_string(len + 1, str);
1663 TREE_TYPE( str_tree ) = arrayType(Type::tchar, len);
1664 return darrayVal(Type::tchar->arrayOf()->toCtype(), len, addressOf(str_tree));
1667 char *
1668 IRState::hostToTargetString(char * str, size_t length, unsigned unit_size)
1670 if (unit_size == 1)
1671 return str;
1672 assert(unit_size == 2 || unit_size == 4);
1674 bool flip;
1675 #if D_GCC_VER < 41
1676 # ifdef HOST_WORDS_BIG_ENDIAN
1677 flip = (bool) ! BYTES_BIG_ENDIAN;
1678 # else
1679 flip = (bool) BYTES_BIG_ENDIAN;
1680 # endif
1681 #else
1682 # if WORDS_BIG_ENDIAN
1683 flip = (bool) ! BYTES_BIG_ENDIAN;
1684 # else
1685 flip = (bool) BYTES_BIG_ENDIAN;
1686 # endif
1687 #endif
1689 if (flip) {
1690 char * out_str = (char *) xmalloc(length * unit_size);
1691 const d_uns8 * p_src = (const d_uns8 *) str;
1692 d_uns8 * p_out = (d_uns8 *) out_str;
1694 while (length--) {
1695 if (unit_size == 2) {
1696 p_out[0] = p_src[1];
1697 p_out[1] = p_src[0];
1698 } else /* unit_size == 4 */ {
1699 p_out[0] = p_src[3];
1700 p_out[1] = p_src[2];
1701 p_out[2] = p_src[1];
1702 p_out[3] = p_src[0];
1704 p_src += unit_size;
1705 p_out += unit_size;
1707 return out_str;
1708 } else {
1709 return str;
1714 tree
1715 IRState::arrayLength(tree exp, Type * exp_type)
1717 Type * base_type = exp_type->toBasetype();
1718 switch (base_type->ty) {
1719 case Tsarray:
1720 return size_int( ((TypeSArray *) base_type)->dim->toUInteger() );
1721 case Tarray:
1722 return darrayLenRef(exp);
1723 default:
1724 ::error("can't determine the length of a %s", exp_type->toChars());
1725 return error_mark_node;
1729 tree
1730 IRState::floatMod(tree a, tree b, Type * d_type)
1732 enum built_in_function fn;
1733 switch (d_type->toBasetype()->ty) {
1734 case Tfloat32:
1735 case Timaginary32:
1736 fn = BUILT_IN_FMODF;
1737 break;
1738 case Tfloat64:
1739 case Timaginary64:
1740 no_long_double:
1741 fn = BUILT_IN_FMOD;
1742 break;
1743 case Tfloat80:
1744 case Timaginary80:
1745 if (! haveLongDouble())
1746 goto no_long_double;
1747 fn = BUILT_IN_FMODL;
1748 break;
1749 default:
1750 ::error("tried to perform floating-point modulo division on %s",
1751 d_type->toChars());
1752 return error_mark_node;
1754 tree decl = built_in_decls[fn];
1755 // %% assuming no arg conversion needed
1756 // %% bypassing buildCall since this shouldn't have
1757 // side effects
1758 return buildCall(TREE_TYPE(TREE_TYPE(decl)),
1759 addressOf(decl),
1760 tree_cons(NULL_TREE, a,
1761 tree_cons(NULL_TREE, b, NULL_TREE)));
1764 tree
1765 IRState::typeinfoReference(Type * t)
1767 tree ti_ref = t->getInternalTypeInfo(NULL)->toElem(this);
1768 assert( POINTER_TYPE_P( TREE_TYPE( ti_ref )) );
1769 return ti_ref;
1772 target_size_t
1773 IRState::getTargetSizeConst(tree t)
1775 target_size_t result;
1776 if (sizeof(HOST_WIDE_INT) < sizeof(target_size_t))
1778 gcc_assert(sizeof(HOST_WIDE_INT) * 2 == sizeof(target_size_t));
1779 result = (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW( t );
1780 result += ((target_size_t) (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH( t ))
1781 << HOST_BITS_PER_WIDE_INT;
1783 else
1784 result = tree_low_cst( t, 1 );
1785 return result;
1788 // delegate is
1789 // struct delegate {
1790 // void * frame_or_object;
1791 // void * function;
1792 // }
1794 tree
1795 IRState::delegateObjectRef(tree exp)
1797 // Get the backend type for the array and pick out the array data
1798 // pointer field (assumed to be the first field.)
1799 tree obj_field = TYPE_FIELDS( TREE_TYPE( exp ));
1800 //return build(COMPONENT_REF, TREE_TYPE( obj_field ), exp, obj_field);
1801 return component(exp, obj_field);
1804 tree
1805 IRState::delegateMethodRef(tree exp)
1807 // Get the backend type for the array and pick out the array length
1808 // field (assumed to be the second field.)
1809 tree method_field = TREE_CHAIN( TYPE_FIELDS( TREE_TYPE( exp )));
1810 //return build(COMPONENT_REF, TREE_TYPE( method_field ), exp, method_field);
1811 return component(exp, method_field);
1814 // Converts pointer types of method_exp and object_exp to match d_type
1815 tree
1816 IRState::delegateVal(tree method_exp, tree object_exp, Type * d_type)
1818 Type * base_type = d_type->toBasetype();
1819 if ( base_type->ty == Tfunction ) {
1820 // Called from DotVarExp. These are just used to
1821 // make function calls and not to make Tdelegate variables.
1822 // Clearing the type makes sure of this.
1823 base_type = 0;
1824 } else {
1825 assert(base_type->ty == Tdelegate);
1828 tree type = base_type ? base_type->toCtype() : NULL_TREE;
1829 tree ctor = make_node( CONSTRUCTOR );
1830 tree obj_field = NULL_TREE;
1831 tree func_field = NULL_TREE;
1832 CtorEltMaker ce;
1834 if (type) {
1835 TREE_TYPE( ctor ) = type;
1836 obj_field = TYPE_FIELDS( type );
1837 func_field = TREE_CHAIN( obj_field );
1839 ce.cons(obj_field, object_exp);
1840 ce.cons(func_field, method_exp);
1841 CONSTRUCTOR_ELTS( ctor ) = ce.head;
1843 return ctor;
1846 void
1847 IRState::extractMethodCallExpr(tree mcr, tree & callee_out, tree & object_out) {
1848 assert( D_IS_METHOD_CALL_EXPR( mcr ));
1849 #if D_GCC_VER < 41
1850 tree elts = CONSTRUCTOR_ELTS( mcr );
1851 object_out = TREE_VALUE( elts );
1852 callee_out = TREE_VALUE( TREE_CHAIN( elts ));
1853 #else
1854 VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS( mcr );
1855 object_out = VEC_index(constructor_elt, elts, 0)->value;
1856 callee_out = VEC_index(constructor_elt, elts, 1)->value;
1857 #endif
1860 tree
1861 IRState::objectInstanceMethod(Expression * obj_exp, FuncDeclaration * func, Type * d_type)
1863 Type * obj_type = obj_exp->type->toBasetype();
1864 if (func->isThis()) {
1865 bool is_dottype;
1866 tree this_expr;
1868 // DotTypeExp cannot be evaluated
1869 if (obj_exp->op == TOKdottype) {
1870 is_dottype = true;
1871 this_expr = ((DotTypeExp *) obj_exp)->e1->toElem( this );
1872 } else if (obj_exp->op == TOKcast &&
1873 ((CastExp*) obj_exp)->e1->op == TOKdottype) {
1874 is_dottype = true;
1875 // see expression.c:"See if we need to adjust the 'this' pointer"
1876 this_expr = ((DotTypeExp *) ((CastExp*) obj_exp)->e1)->e1->toElem( this );
1877 } else {
1878 is_dottype = false;
1879 this_expr = obj_exp->toElem( this );
1882 // Calls to super are static (func is the super's method)
1883 // Structs don't have vtables.
1884 // Final and non-virtual methods can be called directly.
1885 // DotTypeExp means non-virtual
1887 if (obj_exp->op == TOKsuper ||
1888 obj_type->ty == Tstruct || obj_type->ty == Tpointer ||
1889 func->isFinal() || ! func->isVirtual() || is_dottype) {
1891 if (obj_type->ty == Tstruct)
1892 this_expr = addressOf(this_expr);
1893 return methodCallExpr(functionPointer(func), this_expr, d_type);
1894 } else {
1895 // Interface methods are also in the class's vtable, so we don't
1896 // need to convert from a class pointer to an interface pointer.
1897 this_expr = maybeMakeTemp( this_expr );
1899 tree vtbl_ref;
1900 //#if D_GCC_VER >= 40
1901 /* Folding of *&<static var> fails because of the type of the
1902 address expression is 'Object' while the type of the static
1903 var is a particular class (why?). This prevents gimplification
1904 of the expression.
1906 if (TREE_CODE(this_expr) == ADDR_EXPR /*&&
1907 // can't use this check
1908 TREE_TYPE(TREE_OPERAND(this_expr, 0)) ==
1909 TREE_TYPE(TREE_TYPE(this_expr))*/)
1910 vtbl_ref = TREE_OPERAND(this_expr, 0);
1911 else
1912 //#endif
1913 vtbl_ref = indirect(this_expr);
1915 tree field = TYPE_FIELDS( TREE_TYPE( vtbl_ref )); // the vtbl is the first field
1916 //vtbl_ref = build( COMPONENT_REF, TREE_TYPE( field ), vtbl_ref, field ); // vtbl field (a pointer)
1917 vtbl_ref = component( vtbl_ref, field ); // vtbl field (a pointer)
1918 // %% better to do with array ref?
1919 vtbl_ref = build( PLUS_EXPR, TREE_TYPE(vtbl_ref), vtbl_ref,
1920 size_int( PTRSIZE * func->vtblIndex ));
1921 vtbl_ref = indirect(vtbl_ref, TREE_TYPE( functionPointer(func) ));
1923 return methodCallExpr(vtbl_ref, this_expr, d_type);
1925 } else {
1926 // Static method; ignore the object instance
1927 return addressOf(func);
1932 tree
1933 IRState::realPart(tree c) {
1934 return build1(REALPART_EXPR, TREE_TYPE(TREE_TYPE(c)), c);
1936 tree
1937 IRState::imagPart(tree c) {
1938 return build1(IMAGPART_EXPR, TREE_TYPE(TREE_TYPE(c)), c);
1941 tree
1942 IRState::assignValue(Expression * e, VarDeclaration * v)
1944 if (e->op == TOKassign || e->op == TOKconstruct || e->op == TOKblit)
1946 AssignExp * a_exp = (AssignExp *) e;
1947 if (a_exp->e1->op == TOKvar && ((VarExp *) a_exp->e1)->var == v)
1948 return convertForAssignment(a_exp->e2, v->type);
1949 //else
1950 //return e->toElem(this);
1952 return NULL_TREE;
1956 tree
1957 IRState::twoFieldType(tree rec_type, tree ft1, tree ft2, Type * d_type, const char * n1, const char * n2)
1959 tree f0 = build_decl(FIELD_DECL, get_identifier(n1), ft1);
1960 tree f1 = build_decl(FIELD_DECL, get_identifier(n2), ft2);
1961 DECL_CONTEXT(f0) = rec_type;
1962 DECL_CONTEXT(f1) = rec_type;
1963 TYPE_FIELDS(rec_type) = chainon(f0, f1);
1964 layout_type(rec_type);
1965 if (d_type) {
1966 /* This is needed so that maybeExpandSpecialCall knows to
1967 split dynamic array varargs. */
1968 TYPE_LANG_SPECIFIC( rec_type ) = build_d_type_lang_specific(d_type);
1970 /* ObjectFile::declareType will try to declare it as top-level type
1971 which can break debugging info for element types. */
1972 tree stub_decl = build_decl(TYPE_DECL, get_identifier(d_type->toChars()), rec_type);
1973 TYPE_STUB_DECL(rec_type) = stub_decl;
1974 TYPE_NAME(rec_type) = stub_decl;
1975 DECL_ARTIFICIAL(stub_decl) = 1;
1976 g.ofile->rodc(stub_decl, 0);
1978 return rec_type;
1981 // Create a record type from two field types
1982 tree
1983 IRState::twoFieldType(Type * ft1, Type * ft2, Type * d_type, const char * n1, const char * n2)
1985 return twoFieldType( make_node( RECORD_TYPE ), ft1->toCtype(), ft2->toCtype(), d_type, n1, n2 );
1988 tree
1989 IRState::twoFieldCtor(tree rec_type, tree f1, tree f2, int storage_class)
1991 tree ctor = make_node( CONSTRUCTOR );
1992 tree ft1, ft2;
1993 CtorEltMaker ce;
1995 TREE_TYPE( ctor ) = rec_type;
1996 TREE_STATIC( ctor ) = (storage_class & STCstatic) != 0;
1997 TREE_CONSTANT( ctor ) = (storage_class & STCconst) != 0;
1998 TREE_READONLY( ctor ) = (storage_class & STCconst) != 0;
1999 ft1 = TYPE_FIELDS( rec_type );
2000 ft2 = TREE_CHAIN( ft1 );
2002 ce.cons(ft1, f1);
2003 ce.cons(ft2, f2);
2004 CONSTRUCTOR_ELTS( ctor ) = ce.head;
2006 return ctor;
2009 // This could be made more lax to allow better CSE (?)
2010 bool
2011 needs_temp(tree t) {
2012 // %%TODO: check for anything with TREE_SIDE_EFFECTS?
2013 switch (TREE_CODE(t)) {
2014 case VAR_DECL:
2015 case FUNCTION_DECL:
2016 case PARM_DECL:
2017 case CONST_DECL:
2018 case SAVE_EXPR:
2019 return false;
2021 case ADDR_EXPR:
2022 #if D_GCC_VER < 40
2023 case REFERENCE_EXPR:
2024 #endif
2025 /* This check is needed for 4.0. Without it, typeinfo.methodCall may not be
2027 return ! (DECL_P(TREE_OPERAND(t, 0)));
2029 case INDIRECT_REF:
2030 case COMPONENT_REF:
2031 case NOP_EXPR:
2032 case NON_LVALUE_EXPR:
2033 case VIEW_CONVERT_EXPR:
2034 return needs_temp(TREE_OPERAND(t, 0));
2035 case ARRAY_REF:
2036 return true;
2037 default:
2038 if (
2039 #if D_GCC_VER >= 40
2040 TREE_CODE_CLASS(TREE_CODE(t)) == tcc_constant)
2041 #else
2042 TREE_CODE_CLASS(TREE_CODE(t)) == 'c')
2043 #endif
2044 return false;
2045 else
2046 return true;
2050 bool
2051 IRState::isFreeOfSideEffects(tree t)
2053 // SAVE_EXPR is safe to reference more than once, but not to
2054 // expand in a loop.
2055 return TREE_CODE(t) != SAVE_EXPR && ! needs_temp(t);
2058 tree
2059 IRState::maybeMakeTemp(tree t)
2061 if (needs_temp(t)) {
2062 if (TREE_CODE(TREE_TYPE(t)) != ARRAY_TYPE)
2063 return save_expr(t);
2064 else
2065 return stabilize_reference(t);
2066 } else
2067 return t;
2070 Module * IRState::builtinsModule = 0;
2071 Module * IRState::intrinsicModule = 0;
2072 TemplateDeclaration * IRState::stdargTemplateDecl = 0;
2073 TemplateDeclaration * IRState::cstdargStartTemplateDecl = 0;
2074 TemplateDeclaration * IRState::cstdargArgTemplateDecl = 0;
2076 bool
2077 IRState::maybeSetUpBuiltin(Declaration * decl)
2079 Dsymbol * dsym;
2080 TemplateInstance * ti;
2082 // Don't use toParent2. We are looking for a template below.
2083 dsym = decl->toParent();
2085 if (dsym->getModule() == intrinsicModule) {
2086 // Matches order of Intrinsic enum
2087 static const char * intrinsic_names[] = {
2088 "bsf", "bsr",
2089 "bt", "btc", "btr", "bts",
2090 "bswap",
2091 "inp", "inpw", "inpl",
2092 "outp", "outw", "outl", NULL
2094 for (int i = 0; intrinsic_names[i]; i++) {
2095 if ( ! strcmp( decl->ident->string, intrinsic_names[i] ) ) {
2096 bool have_intrinsic = false;
2097 tree t = decl->toSymbol()->Stree;
2099 switch ( (Intrinsic) i ) {
2100 case INTRINSIC_BSF:
2101 case INTRINSIC_BSR:
2102 case INTRINSIC_BT:
2103 case INTRINSIC_BTC:
2104 case INTRINSIC_BTR:
2105 case INTRINSIC_BTS:
2106 break;
2107 case INTRINSIC_BSWAP:
2108 #if defined(TARGET_386)
2109 //have_intrinsic = true;
2110 #endif
2111 break;
2112 case INTRINSIC_INP:
2113 case INTRINSIC_INPW:
2114 case INTRINSIC_INPL:
2115 case INTRINSIC_OUTP:
2116 case INTRINSIC_OUTPW:
2117 case INTRINSIC_OUTPL:
2118 // Only on ix86, but need to given error message on others
2119 have_intrinsic = true;
2120 break;
2121 default:
2122 abort();
2125 if (have_intrinsic) {
2126 DECL_BUILT_IN_CLASS( t ) = BUILT_IN_FRONTEND;
2127 DECL_FUNCTION_CODE( t ) = (built_in_function) i;
2128 return true;
2129 } else
2130 return false;
2133 } else if (dsym) {
2134 ti = dsym->isTemplateInstance();
2135 if (ti) {
2136 tree t = decl->toSymbol()->Stree;
2137 if (ti->tempdecl == stdargTemplateDecl) {
2138 DECL_BUILT_IN_CLASS(t) = BUILT_IN_FRONTEND;
2139 DECL_FUNCTION_CODE(t) = (built_in_function) INTRINSIC_STD_VA_ARG;
2140 return true;
2141 } else if (ti->tempdecl == cstdargArgTemplateDecl) {
2142 DECL_BUILT_IN_CLASS(t) = BUILT_IN_FRONTEND;
2143 DECL_FUNCTION_CODE(t) = (built_in_function) INTRINSIC_C_VA_ARG;
2144 return true;
2145 } else if (ti->tempdecl == cstdargStartTemplateDecl) {
2146 DECL_BUILT_IN_CLASS(t) = BUILT_IN_FRONTEND;
2147 DECL_FUNCTION_CODE(t) = (built_in_function) INTRINSIC_C_VA_START;
2148 return true;
2152 return false;
2155 bool
2156 IRState::isDeclarationReferenceType(Declaration * decl)
2158 Type * base_type = decl->type->toBasetype();
2160 // D doesn't do this now..
2161 if ( base_type->ty == Treference ) {
2162 return true;
2165 if ( decl->isOut() || decl->isRef() ||
2166 ( decl->isParameter() && base_type->ty == Tsarray ) ) {
2167 return true;
2170 return false;
2173 tree
2174 IRState::trueDeclarationType(Declaration * decl)
2176 // If D supported references, we would have to check twice for
2177 // (out T &) -- disallow, maybe or make isDeclarationReferenceType return
2178 // the number of levels to reference
2179 tree decl_type = decl->type->toCtype();
2180 if ( isDeclarationReferenceType( decl )) {
2181 return build_reference_type( decl_type );
2182 } else if (decl->storage_class & STClazy) {
2183 TypeFunction *tf = new TypeFunction(NULL, decl->type, 0, LINKd);
2184 TypeDelegate *t = new TypeDelegate(tf);
2185 return t->merge()->toCtype();
2186 } else {
2187 return decl_type;
2191 // These should match the Declaration versions above
2192 bool
2193 IRState::isArgumentReferenceType(Argument * arg)
2195 Type * base_type = arg->type->toBasetype();
2197 if ( base_type->ty == Treference ) {
2198 return true;
2201 if ( (arg->storageClass & (STCout | STCref)) || base_type->ty == Tsarray ) {
2202 return true;
2205 return false;
2208 tree
2209 IRState::trueArgumentType(Argument * arg)
2211 tree arg_type = arg->type->toCtype();
2212 if ( isArgumentReferenceType( arg )) {
2213 return build_reference_type( arg_type );
2214 } else if (arg->storageClass & STClazy) {
2215 TypeFunction *tf = new TypeFunction(NULL, arg->type, 0, LINKd);
2216 TypeDelegate *t = new TypeDelegate(tf);
2217 return t->merge()->toCtype();
2218 } else {
2219 return arg_type;
2223 tree
2224 IRState::arrayType(tree type_node, uinteger_t size)
2226 tree index_type_node;
2227 if (size > 0) {
2228 index_type_node = size_int( size - 1 );
2229 index_type_node = build_index_type(index_type_node);
2230 } else {
2231 // See c-decl.c grokdeclarator for zero-length arrays
2232 index_type_node = build_range_type (sizetype, size_zero_node,
2233 NULL_TREE);
2236 tree array_type = build_array_type(type_node, index_type_node);
2237 if (size == 0) {
2238 #if D_GCC_VER < 40
2239 layout_type(array_type);
2240 #endif
2241 TYPE_SIZE(array_type) = bitsize_zero_node;
2242 TYPE_SIZE_UNIT(array_type) = size_zero_node;
2244 return array_type;
2247 tree
2248 IRState::addTypeAttribute(tree type, const char * attrname, tree value)
2250 // use build_type_copy / build_type_attribute_variant
2252 // types built by functions in tree.c need to be treated as immutable
2253 if ( ! TYPE_ATTRIBUTES( type )) { // ! TYPE_ATTRIBUTES -- need a better check
2254 type = build_type_copy( type );
2255 // TYPE_STUB_DECL( type ) = .. if we need this for structs, etc.. since
2256 // TREE_CHAIN is cleared by COPY_NODE
2258 if (value)
2259 value = tree_cons(NULL_TREE, value, NULL_TREE);
2260 TYPE_ATTRIBUTES( type ) = tree_cons( get_identifier(attrname), value,
2261 TYPE_ATTRIBUTES( type ));
2262 return type;
2265 void
2266 IRState::addDeclAttribute(tree type, const char * attrname, tree value)
2268 if (value)
2269 value = tree_cons(NULL_TREE, value, NULL_TREE);
2270 DECL_ATTRIBUTES( type ) = tree_cons( get_identifier(attrname), value,
2271 DECL_ATTRIBUTES( type ));
2274 tree
2275 IRState::attributes(Expressions * in_attrs)
2277 if (! in_attrs)
2278 return NULL_TREE;
2280 ListMaker out_attrs;
2282 for (unsigned i = 0; i < in_attrs->dim; i++)
2284 Expression * e = (Expression *) in_attrs->data[i];
2285 IdentifierExp * ident_e = NULL;
2287 ListMaker args;
2289 if (e->op == TOKidentifier)
2290 ident_e = (IdentifierExp *) e;
2291 else if (e->op == TOKcall)
2293 CallExp * c = (CallExp *) e;
2294 assert(c->e1->op == TOKidentifier);
2295 ident_e = (IdentifierExp *) c->e1;
2297 if (c->arguments) {
2298 for (unsigned ai = 0; ai < c->arguments->dim; ai++) {
2299 Expression * ae = (Expression *) c->arguments->data[ai];
2300 tree aet;
2301 if (ae->op == TOKstring && ((StringExp *) ae)->sz == 1)
2303 StringExp * s = (StringExp *) ae;
2304 aet = build_string(s->len, (const char*) s->string);
2306 else
2307 aet = ae->toElem(&gen);
2308 args.cons(aet);
2312 else
2314 gcc_unreachable();
2315 continue;
2317 out_attrs.cons(get_identifier(ident_e->ident->string), args.head);
2320 return out_attrs.head;
2323 tree
2324 IRState::integerConstant(xdmd_integer_t value, tree type) {
2325 #if D_GCC_VER < 40
2326 // Assuming xdmd_integer_t is 64 bits
2327 # if HOST_BITS_PER_WIDE_INT == 32
2328 tree tree_value = build_int_2(value & 0xffffffff, (value >> 32) & 0xffffffff);
2329 # elif HOST_BITS_PER_WIDE_INT == 64
2330 tree tree_value = build_int_2(value,
2331 type && ! TREE_UNSIGNED(type) && (value & 0x8000000000000000ULL) ?
2332 ~(unsigned HOST_WIDE_INT) 0 : 0);
2333 # else
2334 # error Fix This
2335 # endif
2336 if (type) {
2337 TREE_TYPE( tree_value ) = type;
2338 // May not to call force_fit_type for 3.3.x and 3.4.x, but being safe.
2339 force_fit_type(tree_value, 0);
2341 #else
2342 # if HOST_BITS_PER_WIDE_INT == 32
2343 tree tree_value = build_int_cst_wide(type,
2344 value & 0xffffffff, (value >> 32) & 0xffffffff);
2345 # elif HOST_BITS_PER_WIDE_INT == 64
2346 tree tree_value = build_int_cst_type(type, value);
2347 # else
2348 # error Fix This
2349 # endif
2350 /* VALUE may be an incorrect representation for TYPE. Example:
2351 uint x = cast(uint) -3; // becomes "-3u" -- value=0xfffffffffffffd type=Tuns32
2352 Constant folding will not work correctly unless this is done. */
2353 tree_value = force_fit_type(tree_value, 0, 0, 0);
2354 #endif
2355 return tree_value;
2358 tree
2359 IRState::exceptionObject()
2361 tree obj_type = getObjectType()->toCtype();
2362 // Like gjc, the actual D exception object is one
2363 // pointer behind the exception header
2364 tree t = build (EXC_PTR_EXPR, ptr_type_node);
2365 t = build1(NOP_EXPR, build_pointer_type(obj_type), t); // treat exception header as ( Object* )
2366 t = build(MINUS_EXPR, TREE_TYPE(t), t, TYPE_SIZE_UNIT(TREE_TYPE(t)));
2367 t = build1(INDIRECT_REF, obj_type, t);
2368 return t;
2371 tree
2372 IRState::label(Loc loc, Identifier * ident) {
2373 tree t_label = build_decl(LABEL_DECL,
2374 ident ? get_identifier(ident->string) : NULL_TREE, void_type_node);
2375 DECL_CONTEXT( t_label ) = current_function_decl;
2376 DECL_MODE( t_label ) = VOIDmode;
2377 if (loc.filename)
2378 g.ofile->setDeclLoc(t_label, loc);
2379 return t_label;
2382 tree
2383 IRState::getFrameForFunction(FuncDeclaration * f)
2385 if (f->fbody)
2386 return getFrameForSymbol(f);
2387 else
2389 // Should error on line that references f
2390 f->error("nested function missing body");
2391 return d_null_pointer;
2394 tree
2395 IRState::getFrameForNestedClass(ClassDeclaration *c)
2397 return getFrameForSymbol(c);
2400 /* If nested_sym is a nested function, return the static chain to be
2401 used when invoking that function.
2403 If nested_sym is a nested class, return the static chain to be used
2404 when creating an instance of the class.
2406 This method is protected to enforce the type checking of
2407 getFrameForFunction and getFrameForNestedClass.
2408 getFrameForFunction also checks that the nestd function is properly
2409 defined.
2412 tree
2413 IRState::getFrameForSymbol(Dsymbol * nested_sym)
2415 FuncDeclaration * nested_func = 0;
2416 FuncDeclaration * outer_func = 0;
2418 if ( (nested_func = nested_sym->isFuncDeclaration()) )
2420 // gcc_assert(nested_func->isNested())
2421 outer_func = nested_func->toParent2()->isFuncDeclaration();
2422 gcc_assert(outer_func != NULL);
2424 else
2426 /* It's a class. NewExp::toElem has already determined its
2427 outer scope is not another class, so it must be a
2428 function. */
2430 Dsymbol * sym = nested_sym;
2432 while (sym && ! (outer_func = sym->isFuncDeclaration()))
2433 sym = sym->toParent2();
2435 /* Make sure we can access the frame of outer_func.
2437 For GCC < 4.0:
2439 f() {
2440 class X {
2441 m() { }
2443 g() {
2444 h() {
2445 new X // <-- you are here
2450 In order to get the static chain we must know a
2451 function nested in F. If we are currently in such a
2452 nested function, use that.
2454 f() {
2455 class X { m() { } }
2456 new X // <-- you are here
2459 If we are at the level of the function containing the
2460 class, the answer is just 'virtual_stack_vars_rtx'.
2463 if (outer_func != func) {
2465 Dsymbol * o = nested_func = func;
2466 do {
2467 if (! nested_func->isNested())
2468 goto cannot_access_frame;
2469 while ( (o = o->toParent2()) )
2470 if ( (nested_func = o->isFuncDeclaration()) )
2471 break;
2472 } while (o && o != outer_func);
2474 if (! o) {
2475 cannot_access_frame:
2476 error("cannot access frame of function '%s' from '%s'",
2477 outer_func->ident->string, func->ident->string);
2478 return d_null_pointer;
2481 // else, the answer is 'virtual_stack_vars_rtx'
2484 #if V2
2485 if (getFrameInfo(outer_func)->creates_closure)
2486 return getClosureRef(outer_func);
2487 #endif
2489 #if D_GCC_VER < 40
2490 tree result = make_node (RTL_EXPR);
2491 TREE_TYPE (result) = ptr_type_node;
2492 RTL_EXPR_RTL (result) = nested_func ?
2493 lookup_static_chain(nested_func->toSymbol()->Stree) :
2494 virtual_stack_vars_rtx;
2495 return result;
2496 #else
2497 if (! outer_func)
2498 outer_func = nested_func->toParent2()->isFuncDeclaration();
2499 gcc_assert(outer_func != NULL);
2500 return build1(STATIC_CHAIN_EXPR, ptr_type_node, outer_func->toSymbol()->Stree);
2501 #endif
2504 #if V2
2506 /* For the purposes this is used, fd is assumed to be a nested
2507 function or a method of a class that is (eventually) nested in a
2508 function.
2510 static bool
2511 isFuncNestedInFunc(FuncDeclaration * fd, FuncDeclaration *fo)
2513 if (fd == fo)
2514 return false;
2516 while (fd)
2518 AggregateDeclaration * ad;
2519 ClassDeclaration * cd;
2521 if (fd == fo)
2523 //fprintf(stderr, "%s is nested in %s\n", fd->toChars(), fo->toChars());
2524 return true;
2526 else if (fd->isNested())
2527 fd = fd->toParent2()->isFuncDeclaration();
2528 else if ( (ad = fd->isThis()) && (cd = ad->isClassDeclaration()) )
2530 fd = NULL;
2531 while (cd && cd->isNested())
2533 Dsymbol * dsym = cd->toParent2();
2534 if ( (fd = dsym->isFuncDeclaration()) )
2535 break;
2536 else
2537 cd = dsym->isClassDeclaration();
2540 else
2541 break;
2544 //fprintf(stderr, "%s is NOT nested in %s\n", fd->toChars(), fo->toChars());
2545 return false;
2548 FuncFrameInfo *
2549 IRState::getFrameInfo(FuncDeclaration *fd)
2551 Symbol * fds = fd->toSymbol();
2552 if (fds->frameInfo)
2553 return fds->frameInfo;
2555 FuncFrameInfo * ffi = new FuncFrameInfo;
2556 ffi->creates_closure = false;
2557 ffi->closure_rec = NULL_TREE;
2559 fds->frameInfo = ffi;
2561 Dsymbol * s = fd->toParent2();
2563 if (fd->needsClosure())
2564 ffi->creates_closure = true;
2565 else
2567 /* If fd is nested (deeply) in a function 'g' that creates a
2568 closure and there exists a function 'h' nested (deeply) in
2569 fd and 'h' accesses the frame of 'g', then fd must also
2570 create a closure.
2572 This is for the sake of a simple implementation. An alternative
2573 is, when determining the frame to pass to 'h', pass the pointer
2574 to 'g' (the deepest 'g' whose frame is accessed by 'h') instead
2575 of the usual frame that 'h' would take.
2577 FuncDeclaration * ff = fd;
2579 while (ff)
2581 AggregateDeclaration * ad;
2582 ClassDeclaration * cd;
2584 if (ff != fd)
2586 if (getFrameInfo(ff)->creates_closure)
2588 for (int i = 0; i < ff->closureVars.dim; i++)
2589 { VarDeclaration *v = (VarDeclaration *)ff->closureVars.data[i];
2590 for (int j = 0; j < v->nestedrefs.dim; j++)
2591 { FuncDeclaration *fi = (FuncDeclaration *)v->nestedrefs.data[j];
2592 if (isFuncNestedInFunc(fi, fd))
2594 ffi->creates_closure = true;
2595 goto L_done;
2602 if (ff->isNested())
2603 ff = ff->toParent2()->isFuncDeclaration();
2604 else if ( (ad = ff->isThis()) && (cd = ad->isClassDeclaration()) )
2606 ff = NULL;
2607 while (cd && cd->isNested())
2609 Dsymbol * dsym = cd->toParent2();
2610 if ( (ff = dsym->isFuncDeclaration()) )
2611 break;
2612 else
2613 cd = dsym->isClassDeclaration();
2616 else
2617 break;
2620 L_done:
2624 /*fprintf(stderr, "%s %s\n", ffi->creates_closure ? "YES" : "NO ",
2625 fd->toChars());*/
2627 return ffi;
2630 // Return a pointer to the closure block of outer_func
2631 tree
2632 IRState::getClosureRef(FuncDeclaration * outer_func)
2634 tree result = closureLink();
2635 FuncDeclaration * fd = closureFunc;
2637 while (fd && fd != outer_func)
2639 AggregateDeclaration * ad;
2640 ClassDeclaration * cd;
2642 gcc_assert(getFrameInfo(fd)->creates_closure); // remove this if we loosen creates_closure
2644 // like compon(indirect, field0) parent closure link is the first field;
2645 result = indirect(result, ptr_type_node);
2647 if (fd->isNested())
2649 fd = fd->toParent2()->isFuncDeclaration();
2651 else if ( (ad = fd->isThis()) && (cd = ad->isClassDeclaration()) )
2653 fd = NULL;
2654 while (cd && cd->isNested())
2656 /* Shouldn't need to do this. getClosureRef is only
2657 used to get the pointer to a function's frame (not
2658 a class instances.) With the current implementation,
2659 the link the closure record always points to the
2660 outer function's frame even if there are intervening
2661 nested classes. So, we can just skip over those...
2663 tree vthis_field = cd->vthis->toSymbol()->Stree;
2664 result = nop(result, cd->type->toCtype());
2665 result = component(indirect(result), vthis_field);
2668 Dsymbol * dsym = cd->toParent2();
2669 if ( (fd = dsym->isFuncDeclaration()) )
2670 break;
2671 else
2672 cd = dsym->isClassDeclaration();
2675 else
2676 break;
2679 if (fd == outer_func)
2681 tree closure_rec = getFrameInfo(outer_func)->closure_rec;
2682 result = nop(result, build_pointer_type(closure_rec));
2683 return result;
2685 else
2687 func->error("cannot access frame of %s", outer_func->toChars());
2688 return d_null_pointer;
2692 #endif
2694 /* Return true if function F needs to have the static chain passed to
2695 it. This only applies to nested function handling provided by the
2696 GCC back end (not D closures.)
2698 bool
2699 IRState::functionNeedsChain(FuncDeclaration *f)
2701 Dsymbol * s;
2702 ClassDeclaration * a;
2703 FuncDeclaration *pf = 0;
2705 if (f->isNested()
2706 #if V2
2707 && ! getFrameInfo(f->toParent2()->isFuncDeclaration())->creates_closure
2708 #endif
2710 return true;
2711 if (f->isStatic())
2712 return false;
2714 s = f->toParent2();
2716 while ( s && (a = s->isClassDeclaration()) && a->isNested() ) {
2717 s = s->toParent2();
2718 if ( (pf = s->isFuncDeclaration())
2719 #if V2
2720 && ! getFrameInfo(pf)->creates_closure
2721 #endif
2723 return true;
2725 return false;
2728 tree
2729 IRState::toElemLvalue(Expression * e)
2732 if (e->op == TOKcast)
2733 fprintf(stderr, "IRState::toElemLvalue TOKcast\n");
2734 else
2737 if (e->op == TOKindex) {
2738 IndexExp * ie = (IndexExp *) e;
2739 Expression * e1 = ie->e1;
2740 Expression * e2 = ie->e2;
2741 Type * type = e->type;
2742 Type * array_type = e1->type->toBasetype();
2744 if (array_type->ty == Taarray) {
2745 Type * key_type = ((TypeAArray *) array_type)->index->toBasetype();
2746 AddrOfExpr aoe;
2748 tree args[4];
2749 args[0] = this->addressOf( this->toElemLvalue(e1) );
2750 args[1] = this->typeinfoReference(key_type);
2751 args[2] = this->integerConstant( array_type->nextOf()->size(), Type::tsize_t );
2752 args[3] = aoe.set(this, this->convertTo( e2, key_type ));
2753 return build1(INDIRECT_REF, type->toCtype(),
2754 aoe.finish(this,
2755 this->libCall(LIBCALL_AAGETP, 4, args, type->pointerTo()->toCtype())));
2758 return e->toElem(this);
2762 #if D_GCC_VER < 40
2764 void
2765 IRState::startCond(Statement * stmt, Expression * e_cond) {
2766 clear_last_expr ();
2767 g.ofile->doLineNote(stmt->loc);
2768 expand_start_cond( convertForCondition( e_cond ), 0 );
2771 void
2772 IRState::startElse() { expand_start_else(); }
2774 void
2775 IRState::endCond() { expand_end_cond(); }
2777 void
2778 IRState::startLoop(Statement * stmt) {
2779 beginFlow(stmt, expand_start_loop_continue_elsewhere(1));
2782 void
2783 IRState::continueHere()
2785 Flow * f = currentFlow();
2786 if (f->overrideContinueLabel)
2787 doLabel(f->overrideContinueLabel);
2788 else
2789 expand_loop_continue_here();
2792 void
2793 IRState::setContinueLabel(tree lbl)
2795 currentFlow()->overrideContinueLabel = lbl;
2798 void
2799 IRState::exitIfFalse(tree t_cond, bool is_top_cond) {
2801 // %% topcond compaitble with continue_elswehre?
2802 expand_exit_loop_if_false(currentFlow()->loop, t_cond);
2805 void
2806 IRState::startCase(Statement * stmt, tree t_cond)
2808 clear_last_expr ();
2809 g.ofile->doLineNote(stmt->loc);
2810 expand_start_case( 1, t_cond, TREE_TYPE( t_cond ), "switch statement" );
2811 beginFlow(stmt, NULL);
2814 void
2815 IRState::doCase(tree t_value, tree t_label)
2817 tree dummy;
2818 // %% not the same convert that is in d-glue!!
2819 pushcase( t_value, convert, t_label, & dummy);
2822 void
2823 IRState::endCase(tree t_cond)
2825 expand_end_case( t_cond );
2826 endFlow();
2829 void
2830 IRState::endLoop() {
2831 expand_end_loop();
2832 endFlow();
2835 void
2836 IRState::continueLoop(Identifier * ident) {
2837 Flow * f = getLoopForLabel( ident, true );
2838 if (f->overrideContinueLabel)
2839 doJump(NULL, f->overrideContinueLabel);
2840 else
2841 expand_continue_loop( f->loop );
2844 void
2845 IRState::exitLoop(Identifier * ident)
2847 if (ident) {
2848 Flow * flow = getLoopForLabel( ident );
2849 if (flow->loop)
2850 expand_exit_loop( flow->loop );
2851 else {
2852 if (! flow->exitLabel)
2853 flow->exitLabel = label(flow->statement->loc);
2854 expand_goto( flow->exitLabel );
2856 } else {
2857 expand_exit_something();
2861 void
2862 IRState::startTry(Statement * stmt)
2864 expand_eh_region_start();
2867 void
2868 IRState::startCatches()
2870 expand_start_all_catch();
2873 void
2874 IRState::startCatch(tree t_type)
2876 expand_start_catch( t_type );
2879 void
2880 IRState::endCatch()
2882 expand_end_catch();
2885 void
2886 IRState::endCatches()
2888 expand_end_all_catch();
2891 void
2892 IRState::startFinally()
2894 abort();
2897 void
2898 IRState::endFinally()
2900 abort();
2903 void
2904 IRState::doReturn(tree t_value)
2906 if (t_value)
2907 expand_return(t_value);
2908 else
2909 expand_null_return();
2912 void
2913 IRState::doJump(Statement * stmt, tree t_label)
2915 // %%TODO: c-semantics.c:expand_stmt GOTO_STMT branch prediction
2916 TREE_USED( t_label ) = 1 ;
2917 if (stmt)
2918 g.ofile->doLineNote( stmt->loc );
2919 expand_goto( t_label );
2922 tree
2923 IRState::makeStmtExpr(Statement * statement)
2925 tree t = build1((enum tree_code) D_STMT_EXPR, void_type_node, NULL_TREE);
2926 TREE_SIDE_EFFECTS(t) = 1; // %%
2927 stmtExprList.push(t);
2928 stmtExprList.push(statement);
2929 stmtExprList.push(this);
2930 return t;
2933 void
2934 IRState::retrieveStmtExpr(tree t, Statement ** s_out, IRState ** i_out)
2936 for (int i = stmtExprList.dim - 3; i >= 0 ; i -= 3) {
2937 if ( (tree) stmtExprList.data[i] == t ) {
2938 *s_out = (Statement *) stmtExprList.data[i + 1];
2939 *i_out = (IRState *) stmtExprList.data[i + 2];
2940 // The expression could be evaluated multiples times, so we must
2941 // keep the values forever --- %% go back to per-function list
2942 return;
2945 abort();
2946 return;
2949 #else
2951 void
2952 IRState::startCond(Statement * stmt, Expression * e_cond)
2954 tree t_cond = convertForCondition(e_cond);
2956 Flow * f = beginFlow(stmt/*, 0*/);
2957 f->condition = t_cond;
2960 void
2961 IRState::startElse()
2963 currentFlow()->trueBranch = popStatementList();
2964 pushStatementList();
2967 void
2968 IRState::endCond()
2970 Flow * f = currentFlow();
2971 tree t_brnch = popStatementList(); // endFlow(); -- can't pop -- need the info?
2972 tree t_false_brnch = NULL_TREE;
2974 if (f->trueBranch == NULL_TREE)
2975 f->trueBranch = t_brnch;
2976 else
2977 t_false_brnch = t_brnch;
2979 g.ofile->doLineNote(f->statement->loc);
2980 tree t_stmt = build3(COND_EXPR, void_type_node,
2981 f->condition, f->trueBranch, t_false_brnch);
2982 endFlow();
2983 addExp(t_stmt);
2986 void
2987 IRState::startLoop(Statement * stmt) {
2988 Flow * f = beginFlow(stmt/*, Break|Continue*/);
2989 f->continueLabel = label(stmt ? stmt->loc : 0); // should be end for 'do' loop
2992 void
2993 IRState::continueHere() {
2994 doLabel(currentFlow()->continueLabel);
2997 void
2998 IRState::setContinueLabel(tree lbl)
3000 currentFlow()->continueLabel = lbl;
3003 void
3004 IRState::exitIfFalse(tree t_cond, bool /*unused*/) {
3005 addExp(build1(EXIT_EXPR, void_type_node,
3006 build1(TRUTH_NOT_EXPR, TREE_TYPE(t_cond), t_cond)));
3009 void
3010 IRState::startCase(Statement * stmt, tree t_cond)
3012 Flow * f = beginFlow(stmt);
3013 f->condition = t_cond;
3016 void
3017 IRState::doCase(tree t_value, tree t_label)
3019 addExp(build3(CASE_LABEL_EXPR, void_type_node,
3020 t_value, NULL_TREE, t_label));
3023 void
3024 IRState::endCase(tree /*t_cond*/)
3026 Flow * f = currentFlow();
3027 tree t_body = popStatementList();
3028 tree t_stmt = build3(SWITCH_EXPR, void_type_node, f->condition,
3029 t_body, NULL_TREE);
3030 addExp(t_stmt);
3031 endFlow();
3034 void
3035 IRState::endLoop() {
3036 // says must contain an EXIT_EXPR -- what about while(1)..goto;? something other thand LOOP_EXPR?
3037 tree t_body = popStatementList();
3038 tree t_loop = build1(LOOP_EXPR, void_type_node, t_body);
3039 addExp(t_loop);
3040 endFlow();
3043 void
3044 IRState::continueLoop(Identifier * ident) {
3045 //doFlowLabel(stmt, ident, Continue);
3046 doJump(NULL, getLoopForLabel(ident, true)->continueLabel );
3049 void
3050 IRState::exitLoop(Identifier * ident) {
3051 Flow * flow = getLoopForLabel(ident);
3052 if (! flow->exitLabel)
3053 flow->exitLabel = label(flow->statement->loc);
3054 doJump(NULL, flow->exitLabel);
3058 void
3059 IRState::startTry(Statement * stmt)
3061 beginFlow(stmt);
3064 void
3065 IRState::startCatches()
3067 currentFlow()->tryBody = popStatementList();
3068 pushStatementList();
3071 void
3072 IRState::startCatch(tree t_type)
3074 currentFlow()->catchType = t_type;
3075 pushStatementList();
3078 void
3079 IRState::endCatch()
3081 tree t_body = popStatementList();
3082 // % wrong loc.. can set pass statement to startCatch, set
3083 // the loc on t_type and then use it here..
3084 // may not be important?
3085 doExp(build2(CATCH_EXPR, void_type_node,
3086 currentFlow()->catchType, t_body));
3089 void
3090 IRState::endCatches()
3092 tree t_catches = popStatementList();
3093 g.ofile->doLineNote(currentFlow()->statement->loc);
3094 doExp(build2(TRY_CATCH_EXPR, void_type_node,
3095 currentFlow()->tryBody, t_catches));
3096 endFlow();
3099 void
3100 IRState::startFinally()
3102 currentFlow()->tryBody = popStatementList();
3103 pushStatementList();
3106 void
3107 IRState::endFinally()
3109 tree t_finally = popStatementList();
3110 g.ofile->doLineNote(currentFlow()->statement->loc);
3111 doExp(build2(TRY_FINALLY_EXPR, void_type_node,
3112 currentFlow()->tryBody, t_finally));
3113 endFlow();
3116 void
3117 IRState::doReturn(tree t_value)
3119 addExp(build1(RETURN_EXPR, void_type_node, t_value));
3122 void
3123 IRState::doJump(Statement * stmt, tree t_label)
3125 if (stmt)
3126 g.ofile->doLineNote( stmt->loc );
3127 addExp(build1(GOTO_EXPR, void_type_node, t_label));
3130 tree
3131 IRState::makeStmtExpr(Statement * statement)
3133 tree t_list;
3135 pushStatementList();
3136 statement->toIR(this);
3137 t_list = popStatementList();
3139 // addExp(t_list);
3141 return t_list;
3144 #endif
3146 void
3147 IRState::doAsm(tree insn_tmpl, tree outputs, tree inputs, tree clobbers)
3149 #if D_GCC_VER < 40
3150 expand_asm_operands(insn_tmpl, outputs, inputs, clobbers, 1, input_location);
3151 #else
3152 tree t = d_build_asm_stmt(insn_tmpl, outputs, inputs, clobbers);
3153 ASM_VOLATILE_P( t ) = 1;
3154 addExp( t );
3155 #endif
3158 WrappedExp::WrappedExp(Loc loc, enum TOK op, tree exp_node, Type * type)
3159 : Expression(loc, op, sizeof(WrappedExp))
3161 this->exp_node = exp_node;
3162 this->type = type;
3165 void
3166 WrappedExp::toCBuffer(OutBuffer *buf)
3168 buf->printf("< wrapped exprission >");
3171 elem *
3172 WrappedExp::toElem(IRState *)
3174 return exp_node;
3178 void AggLayout::doFields(Array * fields, AggregateDeclaration * agg)
3180 bool inherited = agg != this->aggDecl;
3181 tree fcontext;
3183 fcontext = agg->type->toCtype();
3184 if ( POINTER_TYPE_P( fcontext ))
3185 fcontext = TREE_TYPE(fcontext);
3187 // tree new_field_chain = NULL_TREE;
3188 for (unsigned i = 0; i < fields->dim; i++) {
3189 // %% D anonymous unions just put the fields into the outer struct...
3190 // does this cause problems?
3192 VarDeclaration * var_decl = (VarDeclaration *) fields->data[i];
3194 assert( var_decl->storage_class & STCfield );
3196 tree ident = var_decl->ident ? get_identifier(var_decl->ident->string) : NULL_TREE;
3197 tree field_decl = build_decl(FIELD_DECL, ident,
3198 gen.trueDeclarationType( var_decl ));
3199 g.ofile->setDeclLoc( field_decl, var_decl );
3200 var_decl->csym = new Symbol;
3201 var_decl->csym->Stree = field_decl;
3203 DECL_CONTEXT( field_decl ) = aggType;
3204 DECL_FCONTEXT( field_decl ) = fcontext;
3205 DECL_FIELD_OFFSET (field_decl) = size_int( var_decl->offset );
3206 DECL_FIELD_BIT_OFFSET (field_decl) = bitsize_zero_node;
3208 DECL_ARTIFICIAL( field_decl ) =
3209 DECL_IGNORED_P( field_decl ) = inherited;
3212 // GCC 4.0 requires DECL_OFFSET_ALIGN to be set
3213 // %% .. using TYPE_ALIGN may not be same as DMD..
3214 SET_DECL_OFFSET_ALIGN( field_decl,
3215 TYPE_ALIGN( TREE_TYPE( field_decl )));
3217 //SET_DECL_OFFSET_ALIGN (field_decl, BIGGEST_ALIGNMENT); // ?
3218 layout_decl( field_decl, 0 );
3220 // get_inner_reference doesn't check these, leaves a variable unitialized
3221 // DECL_SIZE is NULL if size is zero.
3222 if (var_decl->size(var_decl->loc)) {
3223 assert(DECL_MODE(field_decl) != VOIDmode);
3224 assert(DECL_SIZE(field_decl) != NULL_TREE);
3226 fieldList.chain( field_decl );
3230 void AggLayout::doInterfaces(Array * bases, AggregateDeclaration * /*agg*/)
3232 //tree fcontext = TREE_TYPE( agg->type->toCtype() );
3233 for (unsigned i = 0; i < bases->dim; i++) {
3234 BaseClass * bc = (BaseClass *) bases->data[i];
3235 tree decl = build_decl(FIELD_DECL, NULL_TREE,
3236 Type::tvoid->pointerTo()->pointerTo()->toCtype() /* %% better */ );
3237 //DECL_VIRTUAL_P( decl ) = 1; %% nobody cares, boo hoo
3238 DECL_ARTIFICIAL( decl ) =
3239 DECL_IGNORED_P( decl ) = 1;
3240 // DECL_FCONTEXT( decl ) = fcontext; // shouldn't be needed since it's ignored
3241 addField(decl, bc->offset);
3245 void AggLayout::addField(tree field_decl, target_size_t offset)
3247 DECL_CONTEXT( field_decl ) = aggType;
3248 // DECL_FCONTEXT( field_decl ) = aggType; // caller needs to set this
3249 DECL_FIELD_OFFSET (field_decl) = size_int( offset );
3250 DECL_FIELD_BIT_OFFSET (field_decl) = bitsize_int( 0 );
3251 Loc l(aggDecl->getModule(), 1); // Must set this or we crash with DWARF debugging
3252 // gen.setDeclLoc( field_decl, aggDecl->loc ); // aggDecl->loc isn't set
3253 g.ofile->setDeclLoc(field_decl, l);
3255 layout_decl( field_decl, 0 );
3256 fieldList.chain( field_decl );
3259 void AggLayout::finish(Expressions * attrs)
3261 unsigned size_to_use = aggDecl->structsize;
3262 unsigned align_to_use = aggDecl->alignsize;
3264 /* probably doesn't do anything */
3266 if (aggDecl->structsize == 0 && aggDecl->isInterfaceDeclaration())
3267 size_to_use = Type::tvoid->pointerTo()->size();
3270 TYPE_SIZE( aggType ) = bitsize_int( size_to_use * BITS_PER_UNIT );
3271 TYPE_SIZE_UNIT( aggType ) = size_int( size_to_use );
3272 TYPE_ALIGN( aggType ) = align_to_use * BITS_PER_UNIT;
3273 // TYPE_ALIGN_UNIT is not an lvalue
3274 TYPE_PACKED (aggType ) = TYPE_PACKED (aggType ); // %% todo
3276 if (attrs)
3277 decl_attributes(& aggType, gen.attributes(attrs),
3278 ATTR_FLAG_TYPE_IN_PLACE);
3280 compute_record_mode ( aggType );
3281 // %% stor-layout.c:finalize_type_size ... it's private to that file
3283 // c-decl.c -- set up variants ? %%
3284 for (tree x = TYPE_MAIN_VARIANT( aggType ); x; x = TYPE_NEXT_VARIANT( x )) {
3285 TYPE_FIELDS (x) = TYPE_FIELDS (aggType);
3286 TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (aggType);
3287 TYPE_ALIGN (x) = TYPE_ALIGN (aggType);
3288 TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (aggType);
3292 ArrayScope::ArrayScope(IRState * ini_irs, VarDeclaration * ini_v, const Loc & loc) :
3293 v(ini_v), irs(ini_irs)
3295 if (v) {
3296 /* Need to set the location or the expand_decl in the BIND_EXPR will
3297 cause the line numbering for the statement to be incorrect. */
3298 /* The variable itself is not included in the debugging information. */
3299 v->loc = loc;
3300 Symbol * s = v->toSymbol();
3301 tree decl = s->Stree;
3302 DECL_CONTEXT( decl ) = irs->getLocalContext();
3306 tree
3307 ArrayScope::setArrayExp(tree e, Type * t)
3309 /* If STCconst, the value will be assigned in d-decls.cc
3310 of the runtime length of the array expression. */
3311 if (v && ! (v->storage_class & STCconst))
3313 if (t->toBasetype()->ty != Tsarray) // %%
3314 e = irs->maybeMakeTemp(e);
3315 DECL_INITIAL(v->toSymbol()->Stree) = irs->arrayLength(e, t);
3317 return e;
3320 tree
3321 ArrayScope::finish(tree e)
3323 if (v)
3325 Symbol * s = v->toSymbol();
3326 tree t = s->Stree;
3327 if (TREE_CODE(t) == VAR_DECL)
3329 #if V2
3330 if (s->SclosureField)
3331 return irs->compound( irs->vmodify(irs->var(v),
3332 DECL_INITIAL(t) ), e);
3333 else
3334 #endif
3335 return gen.binding(v->toSymbol()->Stree, e);
3339 return e;
3342 void
3343 FieldVisitor::visit(AggregateDeclaration * decl)
3345 ClassDeclaration * class_decl = decl->isClassDeclaration();
3347 if (class_decl && class_decl->baseClass)
3348 FieldVisitor::visit(class_decl->baseClass);
3350 doFields(& decl->fields, decl);
3352 if (class_decl && class_decl->vtblInterfaces)
3353 doInterfaces(class_decl->vtblInterfaces, decl);