Allow returning something of type void in a function that returns void
[delight/core.git] / d-codegen.cc
blob9d22da9f9b21e061e57b240876876ef5084c2520
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 // In Delight, we want empty arrays to be false.
606 // Hopefully this won't break D code :-/
607 tmp = maybeMakeTemp(result);
608 result = darrayLenRef(tmp);
609 break;
611 // DMD checks (length || ptr) (i.e ary !is null)
612 tmp = maybeMakeTemp(result);
613 a = delegateObjectRef(tmp);
614 b = delegateMethodRef(tmp);
615 if (TYPE_MODE(TREE_TYPE(a)) == TYPE_MODE(TREE_TYPE(b)))
616 result = build(BIT_IOR_EXPR, TREE_TYPE(a), a, b);
617 else {
618 a = d_truthvalue_conversion(a);
619 b = d_truthvalue_conversion(b);
620 // probably not worth TRUTH_OROR ...
621 result = build(TRUTH_OR_EXPR, TREE_TYPE(a), a, b);
623 break;
625 case Tdelegate:
626 // DMD checks (function || object), but what good
627 // is if if there is a null function pointer?
628 if ( D_IS_METHOD_CALL_EXPR(result) ) {
629 extractMethodCallExpr(result, a, b);
630 } else {
631 tmp = maybeMakeTemp(result);
632 a = delegateObjectRef(tmp);
633 b = delegateMethodRef(tmp);
635 // not worth using or TRUTH_ORIF...
636 // %%TODO: Is this okay for all targets?
637 result = build(BIT_IOR_EXPR, TREE_TYPE(a), a, b);
638 break;
639 default:
640 break;
642 // see expr.c:do_jump for the types of trees that can be passed to expand_start_cond
643 //TREE_USED( <result> ) = 1; // %% maybe not.. expr optimized away because constant expression?
644 return d_truthvalue_conversion( result );
647 /* Convert EXP to a dynamic array. EXP must be a static array or
648 dynamic array. */
649 tree
650 IRState::toDArray(Expression * exp)
652 TY ty = exp->type->toBasetype()->ty;
653 tree val;
654 if (ty == Tsarray) {
655 val = convertTo(exp, exp->type->toBasetype()->nextOf()->arrayOf());
656 } else if (ty == Tarray) {
657 val = exp->toElem(this);
658 } else {
659 gcc_assert(ty == Tsarray || ty == Tarray);
660 return NULL_TREE;
662 return val;
666 tree
667 IRState::pointerIntSum(tree ptr_node, tree idx_exp)
669 tree result_type_node = TREE_TYPE( ptr_node );
670 tree intop = idx_exp;
671 tree size_exp;
673 // %% TODO: real-not-long-double issues...
675 // %% test for void case ...
676 size_exp = size_in_bytes( TREE_TYPE( result_type_node ) ); // array element size
677 if (integer_zerop(size_exp))
678 size_exp = integer_one_node;
680 if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
681 || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
682 intop = convert (d_type_for_size (TYPE_PRECISION (sizetype),
683 TREE_UNSIGNED (sizetype)), intop);
685 intop = convert (result_type_node,
686 build/*_binary_op*/ (MULT_EXPR, TREE_TYPE(size_exp), intop, // the type here may be wrong %%
687 convert (TREE_TYPE (intop), size_exp)));
688 intop = fold(intop);
690 if ( integer_zerop(intop) )
691 return ptr_node;
692 else
693 return build(PLUS_EXPR, result_type_node, ptr_node, intop);
696 // Doesn't do some of the omptimizations in ::makeArrayElemRef
697 tree
698 IRState::checkedIndex(Loc loc, tree index, tree upper_bound, bool inclusive)
700 if (global.params.useArrayBounds) {
701 return build(COND_EXPR, TREE_TYPE(index),
702 boundsCond(index, upper_bound, inclusive),
703 index,
704 assertCall(loc, LIBCALL_ARRAY_BOUNDS));
705 } else {
706 return index;
711 // index must be wrapped in a SAVE_EXPR to prevent multiple evaluation...
712 tree
713 IRState::boundsCond(tree index, tree upper_bound, bool inclusive)
715 tree bound_check;
717 bound_check = build(inclusive ? LE_EXPR : LT_EXPR, boolean_type_node,
718 convert( d_unsigned_type(TREE_TYPE(index)), index ),
719 upper_bound);
721 if (! TREE_UNSIGNED( TREE_TYPE( index ))) {
722 bound_check = build(TRUTH_ANDIF_EXPR, boolean_type_node, bound_check,
723 // %% conversions
724 build(GE_EXPR, boolean_type_node, index, integer_zero_node));
727 return bound_check;
730 tree
731 IRState::assertCall(Loc loc, LibCall libcall)
733 tree args[2] = { darrayString(loc.filename ? loc.filename : ""),
734 integerConstant(loc.linnum, Type::tuns32) };
735 return libCall(libcall, 2, args);
738 tree
739 IRState::assertCall(Loc loc, Expression * msg)
741 tree args[3] = { msg->toElem(this),
742 darrayString(loc.filename ? loc.filename : ""),
743 integerConstant(loc.linnum, Type::tuns32) };
744 return libCall(LIBCALL_ASSERT_MSG, 3, args);
747 tree
748 IRState::floatConstant(const real_t & value, TypeBasic * target_type )
750 REAL_VALUE_TYPE converted_val;
752 tree type_node = target_type->toCtype();
753 real_convert(& converted_val, TYPE_MODE(type_node), & value.rv());
755 return build_real(type_node, converted_val);
758 xdmd_integer_t
759 IRState::hwi2toli(HOST_WIDE_INT low, HOST_WIDE_INT high)
761 uinteger_t result;
762 if (sizeof(HOST_WIDE_INT) < sizeof(xdmd_integer_t))
764 gcc_assert(sizeof(HOST_WIDE_INT) * 2 == sizeof(xdmd_integer_t));
765 result = (unsigned HOST_WIDE_INT) low;
766 result += ((uinteger_t) (unsigned HOST_WIDE_INT) high) << HOST_BITS_PER_WIDE_INT;
768 else
769 result = low;
770 return result;
774 #if D_GCC_VER >= 40
775 tree
776 IRState::binding(tree var_chain, tree body)
778 // BIND_EXPR/DECL_INITIAL not supported in 4.0?
779 gcc_assert(TREE_CHAIN(var_chain) == NULL_TREE); // TODO: only handles one var
781 if ( DECL_INITIAL(var_chain) )
783 tree ini = build2(MODIFY_EXPR, void_type_node, var_chain, DECL_INITIAL(var_chain));
784 DECL_INITIAL(var_chain) = NULL_TREE;
785 body = compound(ini, body);
788 return build3(BIND_EXPR, TREE_TYPE(body), var_chain, body, NULL_TREE);
790 #endif
792 tree
793 IRState::libCall(LibCall lib_call, unsigned n_args, tree *args, tree force_result_type)
795 tree result;
796 tree callee = functionPointer( getLibCallDecl( lib_call ));
797 // for force_result_type, assumes caller knows what it is doing %%
798 tree result_type = force_result_type != NULL_TREE ?
799 force_result_type : TREE_TYPE(TREE_TYPE(TREE_OPERAND(callee, 0)));
800 tree arg_list = NULL_TREE;
801 for (int i = n_args - 1; i >= 0; i--) {
802 arg_list = tree_cons(NULL_TREE, args[i], arg_list);
805 result = buildCall(result_type, callee, arg_list);
806 return result;
809 static inline bool
810 function_type_p(tree t)
812 return TREE_CODE(t) == FUNCTION_TYPE || TREE_CODE(t) == METHOD_TYPE;
815 // Assumes T is already ->toBasetype()
816 static TypeFunction *
817 get_function_type(Type * t)
819 TypeFunction* tf = NULL;
820 if (t->ty == Tpointer)
821 t = t->nextOf()->toBasetype();
822 if (t->ty == Tfunction)
823 tf = (TypeFunction *) t;
824 else if (t->ty == Tdelegate)
825 tf = (TypeFunction *) ((TypeDelegate *) t)->next;
826 return tf;
829 tree IRState::errorMark(Type * t)
831 return nop(error_mark_node, t->toCtype());
834 tree
835 IRState::call(Expression * expr, /*TypeFunction * func_type, */ Array * arguments)
837 // Calls to delegates can sometimes look like this:
838 if (expr->op == TOKcomma)
840 CommaExp * ce = (CommaExp *) expr;
841 expr = ce->e2;
843 VarExp * ve;
844 gcc_assert( ce->e2->op == TOKvar );
845 ve = (VarExp *) ce->e2;
846 gcc_assert(ve->var->isFuncDeclaration() && ! ve->var->needThis());
849 Type* t = expr->type->toBasetype();
850 TypeFunction* tf = NULL;
851 tree callee = expr->toElem(this);
852 tree object = NULL_TREE;
854 if ( D_IS_METHOD_CALL_EXPR( callee ) ) {
855 /* This could be a delegate expression (TY == Tdelegate), but not
856 actually a delegate variable. */
857 tf = get_function_type(t);
858 extractMethodCallExpr(callee, callee, object);
859 } else if ( t->ty == Tdelegate) {
860 tf = (TypeFunction*) ((TypeDelegate *) t)->next;
861 callee = maybeMakeTemp(callee);
862 object = delegateObjectRef(callee);
863 callee = delegateMethodRef(callee);
864 } else if (expr->op == TOKvar) {
865 FuncDeclaration * fd = ((VarExp *) expr)->var->isFuncDeclaration();
866 tf = (TypeFunction *) fd->type;
867 if (fd) {
868 if (fd->isNested()) {
869 #if D_NO_TRAMPOLINES
870 object = getFrameForFunction(fd);
871 #else
872 // Pass fake argument for nested functions
873 object = d_null_pointer;
874 #endif
875 } else if (fd->needThis()) {
876 expr->error("need 'this' to access member %s", fd->toChars());
877 object = d_null_pointer; // continue processing...
880 } else {
881 tf = get_function_type(t);
883 return call(tf, callee, object, arguments);
886 tree
887 IRState::call(FuncDeclaration * func_decl, Array * args)
889 assert(! func_decl->isNested()); // Otherwise need to copy code from above
890 return call((TypeFunction *) func_decl->type, func_decl->toSymbol()->Stree, NULL_TREE, args);
893 tree
894 IRState::call(FuncDeclaration * func_decl, tree object, Array * args)
896 return call((TypeFunction *)func_decl->type, functionPointer(func_decl),
897 object, args);
900 tree
901 IRState::call(TypeFunction *func_type, tree callable, tree object, Array * arguments)
903 // Using TREE_TYPE( callable ) instead of func_type->toCtype can save a build_method_type
904 tree func_type_node = TREE_TYPE( callable );
905 tree actual_callee = callable;
907 if ( POINTER_TYPE_P( func_type_node ) )
908 func_type_node = TREE_TYPE( func_type_node );
909 else
910 actual_callee = addressOf( callable );
912 assert( function_type_p( func_type_node ) );
913 assert( func_type != NULL );
914 assert( func_type->ty == Tfunction );
916 bool is_d_vararg = func_type->varargs == 1 && func_type->linkage == LINKd;
918 // Account for the hidden object/frame pointer argument
920 if ( TREE_CODE( func_type_node ) == FUNCTION_TYPE ) {
921 if ( object != NULL_TREE ) {
922 // Happens when a delegate value is called
923 tree method_type = build_method_type( TREE_TYPE( object ), func_type_node );
924 TYPE_ATTRIBUTES( method_type ) = TYPE_ATTRIBUTES( func_type_node );
925 func_type_node = method_type;
927 } else /* METHOD_TYPE */ {
928 if ( ! object ) {
929 // Front-end apparently doesn't check this.
930 if (TREE_CODE(callable) == FUNCTION_DECL ) {
931 error("need 'this' to access member %s", IDENTIFIER_POINTER( DECL_NAME( callable )));
932 return error_mark_node;
933 } else {
934 // Probably an internal error
935 assert(object != NULL_TREE);
940 ListMaker actual_arg_list;
942 /* If this is a delegate call or a nested function being called as
943 a delegate, the object should not be NULL. */
944 if (object != NULL_TREE)
945 actual_arg_list.cons( object );
947 Arguments * formal_args = func_type->parameters; // can be NULL for genCfunc decls
948 size_t n_formal_args = formal_args ? (int) Argument::dim(formal_args) : 0;
949 size_t n_actual_args = arguments ? arguments->dim : 0;
950 size_t fi = 0;
952 // assumes arguments->dim <= formal_args->dim if (! this->varargs)
953 for (size_t ai = 0; ai < n_actual_args; ++ai) {
954 tree actual_arg_tree;
956 Expression * actual_arg_exp = (Expression *) arguments->data[ai];
957 if (ai == 0 && is_d_vararg) {
958 // The hidden _arguments parameter
959 actual_arg_tree = actual_arg_exp->toElem(this);
960 } else if (fi < n_formal_args) {
961 // Actual arguments for declared formal arguments
962 Argument * formal_arg = Argument::getNth(formal_args, fi);
964 actual_arg_tree = convertForArgument(actual_arg_exp, formal_arg);
966 // from c-typeck.c: convert_arguments, default_conversion, ...
967 if (INTEGRAL_TYPE_P (TREE_TYPE(actual_arg_tree))
968 && (TYPE_PRECISION (TREE_TYPE(actual_arg_tree)) <
969 TYPE_PRECISION (integer_type_node))) {
971 actual_arg_tree = d_convert_basic(integer_type_node, actual_arg_tree);
973 ++fi;
974 } else {
975 if (splitDynArrayVarArgs && actual_arg_exp->type->toBasetype()->ty == Tarray)
977 tree da_exp = maybeMakeTemp( actual_arg_exp->toElem(this) );
978 actual_arg_list.cons( darrayLenRef( da_exp ) );
979 actual_arg_list.cons( darrayPtrRef( da_exp ) );
980 continue;
982 else
984 actual_arg_tree = actual_arg_exp->toElem( this );
986 /* Not all targets support passing unpromoted types, so
987 promote anyway. */
988 tree prom_type = d_type_promotes_to( TREE_TYPE( actual_arg_tree ));
989 if (prom_type != TREE_TYPE( actual_arg_tree ))
990 actual_arg_tree = d_convert_basic(prom_type, actual_arg_tree);
994 //TREE_USED( actual_arg_tree ) = 1; // needed ?
995 actual_arg_list.cons( actual_arg_tree );
998 tree result = buildCall(TREE_TYPE(func_type_node), actual_callee, actual_arg_list.head);
999 return maybeExpandSpecialCall(result);
1002 static const char * libcall_ids[LIBCALL_count] =
1003 { "_d_assert", "_d_assert_msg", "_d_array_bounds", "_d_switch_error",
1004 "_D9invariant12_d_invariantFC6ObjectZv",
1005 "_d_newclass", "_d_newarrayT",
1006 "_d_newarrayiT",
1007 "_d_newarraymTp", "_d_newarraymiTp", "_d_allocmemory",
1008 "_d_delclass", "_d_delinterface", "_d_delarray",
1009 "_d_delmemory", "_d_callfinalizer", "_d_callinterfacefinalizer",
1010 "_d_arraysetlengthT", "_d_arraysetlengthiT",
1011 "_d_dynamic_cast", "_d_interface_cast",
1012 "_adEq", "_adCmp", "_adCmpChar",
1013 "_aaLen",
1014 //"_aaIn", "_aaGet", "_aaGetRvalue", "_aaDel",
1015 "_aaInp", "_aaGetp", "_aaGetRvaluep", "_aaDelp",
1016 "_d_arraycast",
1017 "_d_arraycopy",
1018 "_d_arraycatT", "_d_arraycatnT",
1019 "_d_arrayappendT",
1020 /*"_d_arrayappendc", */"_d_arrayappendcTp",
1021 #if V2
1022 "_d_arrayassign", "_d_arrayctor", "_d_arraysetassign",
1023 "_d_arraysetctor",
1024 #endif
1025 "_d_monitorenter", "_d_monitorexit",
1026 "_d_criticalenter", "_d_criticalexit",
1027 "_d_throw",
1028 "_d_switch_string", "_d_switch_ustring", "_d_switch_dstring",
1029 "_d_assocarrayliteralTp"
1030 #if V2
1032 "_d_hidden_func"
1033 #endif
1036 static FuncDeclaration * libcall_decls[LIBCALL_count];
1038 void
1039 IRState::replaceLibCallDecl(FuncDeclaration * d_decl)
1041 if ( ! d_decl->ident )
1042 return;
1043 for (unsigned i = 0; i < LIBCALL_count; i++) {
1044 if ( strcmp(d_decl->ident->string, libcall_ids[i]) == 0 ) {
1045 // %% warn if libcall already set?
1046 // Only do this for the libcalls where it's a problem, otherwise
1047 // it causes other problems...
1048 switch ((LibCall) i) {
1049 // case LIBCALL_GNU_BITARRAYSLICEP:
1050 case LIBCALL_ARRAYCOPY: // this could be solved by turning copy of char into memcpy
1051 case LIBCALL_ARRAYCAST:
1052 // replace the function declaration
1053 break;
1054 default:
1055 // don't replace
1056 return;
1058 libcall_decls[i] = d_decl;
1059 break;
1065 FuncDeclaration *
1066 IRState::getLibCallDecl(LibCall lib_call)
1068 FuncDeclaration * decl = libcall_decls[lib_call];
1069 Array arg_types;
1070 Type * t = NULL;
1071 bool varargs = false;
1073 if (! decl) {
1074 Type * return_type = Type::tvoid;
1076 switch (lib_call) {
1077 case LIBCALL_ASSERT:
1078 case LIBCALL_ARRAY_BOUNDS:
1079 case LIBCALL_SWITCH_ERROR:
1080 // need to spec chararray/string because internal code passes string constants
1081 arg_types.reserve(2);
1082 arg_types.push( Type::tchar->arrayOf() );
1083 arg_types.push( Type::tuns32 );
1084 break;
1085 case LIBCALL_ASSERT_MSG:
1086 arg_types.reserve(3);
1087 arg_types.push( Type::tchar->arrayOf() );
1088 arg_types.push( Type::tchar->arrayOf() );
1089 arg_types.push( Type::tuns32 );
1090 break;
1091 case LIBCALL_NEWCLASS:
1092 arg_types.push( ClassDeclaration::classinfo->type );
1093 return_type = getObjectType();
1094 break;
1095 case LIBCALL_NEWARRAYT:
1096 case LIBCALL_NEWARRAYIT:
1097 arg_types.push( Type::typeinfo->type );
1098 arg_types.push( Type::tsize_t );
1099 return_type = Type::tvoid->arrayOf();
1100 break;
1101 case LIBCALL_NEWARRAYMTP:
1102 case LIBCALL_NEWARRAYMITP:
1103 arg_types.push( Type::tsize_t );
1104 arg_types.push( Type::tint32 ); // Currently 'int', even if 64-bit
1105 arg_types.push( Type::typeinfo->type );
1106 if (lib_call == LIBCALL_NEWARRAYMITP)
1107 arg_types.push( Type::tsize_t );
1108 break;
1109 case LIBCALL_ALLOCMEMORY:
1110 arg_types.push( Type::tsize_t );
1111 return_type = Type::tvoidptr;
1112 break;
1113 case LIBCALL_DELCLASS:
1114 case LIBCALL_DELINTERFACE:
1115 arg_types.push(Type::tvoid->pointerTo());
1116 break;
1117 case LIBCALL_DELARRAY:
1118 arg_types.push(Type::tvoid->arrayOf()->pointerTo());
1119 break;
1120 case LIBCALL_DELMEMORY:
1121 arg_types.push(Type::tvoid->pointerTo()->pointerTo());
1122 break;
1123 case LIBCALL_CALLFINALIZER:
1124 case LIBCALL_CALLINTERFACEFINALIZER:
1125 arg_types.push(Type::tvoid->pointerTo());
1126 break;
1127 case LIBCALL_ARRAYSETLENGTHT:
1128 case LIBCALL_ARRAYSETLENGTHIT:
1129 arg_types.push( Type::typeinfo->type );
1130 arg_types.push( Type::tsize_t );
1131 arg_types.push( Type::tvoid->arrayOf()->pointerTo() );
1132 return_type = Type::tvoid->arrayOf();
1133 break;
1134 case LIBCALL_DYNAMIC_CAST:
1135 case LIBCALL_INTERFACE_CAST:
1136 arg_types.push( getObjectType() );
1137 arg_types.push( ClassDeclaration::classinfo->type );
1138 return_type = getObjectType();
1139 break;
1140 case LIBCALL_ADEQ:
1141 case LIBCALL_ADCMP:
1142 arg_types.reserve(3);
1143 arg_types.push(Type::tvoid->arrayOf());
1144 arg_types.push(Type::tvoid->arrayOf());
1145 arg_types.push(Type::typeinfo->type);
1146 return_type = Type::tint32;
1147 break;
1148 case LIBCALL_ADCMPCHAR:
1149 arg_types.reserve(2);
1150 arg_types.push(Type::tchar->arrayOf());
1151 arg_types.push(Type::tchar->arrayOf());
1152 return_type = Type::tint32;
1153 break;
1154 // case LIBCALL_AAIN:
1155 // case LIBCALL_AAGET:
1156 // case LIBCALL_AAGETRVALUE:
1157 // case LIBCALL_AADEL:
1158 case LIBCALL_AALEN:
1159 case LIBCALL_AAINP:
1160 case LIBCALL_AAGETP:
1161 case LIBCALL_AAGETRVALUEP:
1162 case LIBCALL_AADELP:
1164 static Type * aa_type = NULL;
1165 if (! aa_type)
1166 aa_type = new TypeAArray(Type::tvoid->pointerTo(),
1167 Type::tvoid->pointerTo());
1169 if (lib_call == LIBCALL_AALEN)
1171 arg_types.push(aa_type);
1172 return_type = Type::tsize_t;
1173 break;
1176 if (lib_call == LIBCALL_AAGETP)
1177 aa_type = aa_type->pointerTo();
1179 arg_types.reserve(3);
1180 arg_types.push(aa_type);
1181 arg_types.push(Type::typeinfo->type); // typeinfo reference
1182 if ( lib_call == LIBCALL_AAGETP || lib_call == LIBCALL_AAGETRVALUEP)
1183 arg_types.push(Type::tsize_t);
1185 arg_types.push(Type::tvoid->pointerTo());
1187 switch (lib_call) {
1188 case LIBCALL_AAINP:
1189 case LIBCALL_AAGETP:
1190 case LIBCALL_AAGETRVALUEP:
1191 return_type = Type::tvoid->pointerTo();
1192 break;
1193 case LIBCALL_AADELP:
1194 return_type = Type::tvoid;
1195 break;
1196 default:
1197 assert(0);
1200 break;
1201 case LIBCALL_ARRAYCAST:
1202 t = Type::tvoid->arrayOf();
1203 arg_types.push(Type::tsize_t);
1204 arg_types.push(Type::tsize_t);
1205 arg_types.push(t);
1206 return_type = t;
1207 break;
1208 case LIBCALL_ARRAYCOPY:
1209 t = Type::tvoid->arrayOf();
1210 arg_types.push(Type::tsize_t);
1211 arg_types.push(t);
1212 arg_types.push(t);
1213 return_type = t;
1214 break;
1215 case LIBCALL_ARRAYCATT:
1216 arg_types.push(Type::typeinfo->type);
1217 t = Type::tvoid->arrayOf();
1218 arg_types.push(t);
1219 arg_types.push(t);
1220 return_type = t;
1221 break;
1222 case LIBCALL_ARRAYCATNT:
1223 arg_types.push(Type::typeinfo->type);
1224 arg_types.push(Type::tuns32); // Currently 'uint', even if 64-bit
1225 varargs = true;
1226 return_type = Type::tvoid->arrayOf();
1227 break;
1228 case LIBCALL_ARRAYAPPENDT:
1229 arg_types.push(Type::typeinfo->type);
1230 t = Type::tuns8->arrayOf();
1231 arg_types.push(t->pointerTo());
1232 arg_types.push(t);
1233 return_type = Type::tvoid->arrayOf();
1234 break;
1235 // case LIBCALL_ARRAYAPPENDCT:
1236 case LIBCALL_ARRAYAPPENDCTP:
1237 arg_types.push(Type::typeinfo->type);
1238 t = Type::tuns8->arrayOf();
1239 arg_types.push(t);
1240 arg_types.push(Type::tvoid->pointerTo()); // varargs = true;
1241 return_type = Type::tvoid->arrayOf();
1242 break;
1243 #if V2
1244 case LIBCALL_ARRAYASSIGN:
1245 case LIBCALL_ARRAYCTOR:
1246 arg_types.push(Type::typeinfo->type);
1247 arg_types.push(Type::tvoid->arrayOf());
1248 return_type = Type::tvoid->arrayOf();
1249 break;
1250 case LIBCALL_ARRAYSETASSIGN:
1251 case LIBCALL_ARRAYSETCTOR:
1252 arg_types.push(Type::tvoid->pointerTo());
1253 arg_types.push(Type::tvoid->pointerTo());
1254 arg_types.push(Type::tsize_t);
1255 arg_types.push(Type::typeinfo->type);
1256 return_type = Type::tvoid->pointerTo();
1257 break;
1258 #endif
1259 case LIBCALL_MONITORENTER:
1260 case LIBCALL_MONITOREXIT:
1261 case LIBCALL_THROW:
1262 case LIBCALL_INVARIANT:
1263 arg_types.push(getObjectType());
1264 break;
1265 case LIBCALL_CRITICALENTER:
1266 case LIBCALL_CRITICALEXIT:
1267 arg_types.push(Type::tvoid->pointerTo());
1268 break;
1269 case LIBCALL_SWITCH_USTRING:
1270 t = Type::twchar;
1271 goto do_switch_string;
1272 case LIBCALL_SWITCH_DSTRING:
1273 t = Type::tdchar;
1274 goto do_switch_string;
1275 case LIBCALL_SWITCH_STRING:
1276 t = Type::tchar;
1277 do_switch_string:
1278 t = t->arrayOf();
1279 arg_types.push(t->arrayOf());
1280 arg_types.push(t);
1281 return_type = Type::tint32;
1282 break;
1283 case LIBCALL_ASSOCARRAYLITERALTP:
1284 arg_types.push(Type::typeinfo->type);
1285 arg_types.push(Type::tsize_t);
1286 arg_types.push(Type::tvoid->pointerTo());
1287 arg_types.push(Type::tvoid->pointerTo());
1288 return_type = Type::tvoid->pointerTo();
1289 break;
1290 #if V2
1291 case LIBCALL_HIDDEN_FUNC:
1292 /* Argument is an Object, but can't use that as
1293 LIBCALL_HIDDEN_FUNC is needed before the Object type is
1294 created. */
1295 arg_types.push(Type::tvoid->pointerTo());
1296 break;
1297 #endif
1298 default:
1299 gcc_unreachable();
1301 decl = FuncDeclaration::genCfunc(return_type, (char *) libcall_ids[lib_call]);
1303 TypeFunction * tf = (TypeFunction *) decl->type;
1304 tf->varargs = varargs ? 1 : 0;
1305 Arguments * args = new Arguments;
1306 args->setDim( arg_types.dim );
1307 for (unsigned i = 0; i < arg_types.dim; i++)
1308 args->data[i] = new Argument( STCin, (Type *) arg_types.data[i],
1309 NULL, NULL);
1310 tf->parameters = args;
1312 libcall_decls[lib_call] = decl;
1314 return decl;
1317 static tree
1318 fix_d_va_list_type(tree val)
1320 if (POINTER_TYPE_P(va_list_type_node) ||
1321 INTEGRAL_TYPE_P(va_list_type_node))
1322 return build1(NOP_EXPR, va_list_type_node, val);
1323 else
1324 return val;
1327 tree IRState::maybeExpandSpecialCall(tree call_exp)
1329 // More code duplication from C
1331 tree callee = TREE_OPERAND(call_exp, 0);
1332 tree t, op;
1333 if (POINTER_TYPE_P(TREE_TYPE( callee ))) {
1334 callee = TREE_OPERAND(callee, 0);
1336 if (TREE_CODE(callee) == FUNCTION_DECL) {
1337 if (DECL_BUILT_IN_CLASS(callee) == NOT_BUILT_IN) {
1338 // the most common case
1339 return call_exp;
1340 } else if (DECL_BUILT_IN_CLASS(callee) == BUILT_IN_NORMAL) {
1341 switch (DECL_FUNCTION_CODE(callee)) {
1342 case BUILT_IN_ABS:
1343 case BUILT_IN_LABS:
1344 case BUILT_IN_LLABS:
1345 case BUILT_IN_IMAXABS:
1346 /* The above are required for both 3.4. Not sure about later
1347 versions. */
1348 /* OLDOLDOLD below supposedly for 3.3 only */
1350 case BUILT_IN_FABS:
1351 case BUILT_IN_FABSL:
1352 case BUILT_IN_FABSF:
1354 op = TREE_VALUE( TREE_OPERAND( call_exp, 1 ));
1355 t = build1(ABS_EXPR, TREE_TYPE(op), op);
1356 return d_convert_basic(TREE_TYPE(call_exp), t);
1357 // probably need a few more cases:
1358 default:
1359 return call_exp;
1361 } else if (DECL_BUILT_IN_CLASS(callee) == BUILT_IN_FRONTEND) {
1362 Intrinsic intrinsic = (Intrinsic) DECL_FUNCTION_CODE(callee);
1363 tree type;
1364 Type *d_type;
1365 switch (intrinsic) {
1366 case INTRINSIC_C_VA_ARG:
1367 // %% should_check c_promotes_to as in va_arg now
1368 // just drop though for now...
1369 case INTRINSIC_STD_VA_ARG:
1370 t = TREE_VALUE(TREE_OPERAND(call_exp, 1));
1371 // signature is (inout va_list), but VA_ARG_EXPR expects the
1372 // list itself... but not if the va_list type is an array. In that
1373 // case, it should be a pointer
1374 if ( TREE_CODE( va_list_type_node ) != ARRAY_TYPE ) {
1375 if ( TREE_CODE( t ) == ADDR_EXPR ) {
1376 t = TREE_OPERAND(t, 0);
1377 } else {
1378 // this probably doesn't happen... passing an inout va_list argument,
1379 // but again, it's probably { & ( * inout_arg ) }
1380 t = build1(INDIRECT_REF, TREE_TYPE(TREE_TYPE(t)), t);
1383 t = fix_d_va_list_type(t);
1384 type = TREE_TYPE(TREE_TYPE(callee));
1385 if (splitDynArrayVarArgs && (d_type = getDType(type)) &&
1386 d_type->toBasetype()->ty == Tarray)
1388 // should create a temp var of type TYPE and move the binding
1389 // to outside this expression.
1390 t = stabilize_reference(t);
1391 tree ltype = TREE_TYPE( TYPE_FIELDS( type ));
1392 tree ptype = TREE_TYPE( TREE_CHAIN( TYPE_FIELDS( type )));
1393 tree lvar = exprVar(ltype);
1394 tree pvar = exprVar(ptype);
1395 tree e1 = vmodify(lvar, build1(VA_ARG_EXPR, ltype, t));
1396 tree e2 = vmodify(pvar, build1(VA_ARG_EXPR, ptype, t));
1397 tree b = compound( compound( e1, e2 ), darrayVal(type, lvar, pvar) );
1398 return binding(lvar, binding(pvar, b));
1400 else
1402 tree type2 = d_type_promotes_to(type);
1403 t = build1(VA_ARG_EXPR, type2, t);
1404 if (type != type2)
1405 // silently convert promoted type...
1406 t = d_convert_basic(type, t);
1407 return t;
1409 break;
1410 case INTRINSIC_C_VA_START:
1412 t = TREE_VALUE();
1413 // signature is (inout va_list), but VA_ARG_EXPR expects the
1414 // list itself...
1415 if ( TREE_CODE( t ) == ADDR_EXPR ) {
1416 t = TREE_OPERAND(t, 0);
1417 } else {
1418 // this probably doesn't happen... passing an inout va_list argument,
1419 // but again, it's probably { & ( * inout_arg ) }
1420 t = build1(INDIRECT_REF, TREE_TYPE(TREE_TYPE(t)), t);
1423 // The va_list argument should already have its
1424 // address taken. The second argument, however, is
1425 // inout and that needs to be fixed to prevent a warning.
1427 tree val_arg = TREE_VALUE(TREE_OPERAND(call_exp, 1));
1428 // kinda wrong... could be casting.. so need to check type too?
1429 while ( TREE_CODE( val_arg ) == NOP_EXPR )
1430 val_arg = TREE_OPERAND(val_arg, 0);
1431 if ( TREE_CODE( val_arg ) == ADDR_EXPR ) {
1432 val_arg = TREE_OPERAND(val_arg, 0);
1433 val_arg = fix_d_va_list_type(val_arg);
1434 val_arg = addressOf( val_arg );
1435 } else
1436 val_arg = fix_d_va_list_type(val_arg);
1438 t = TREE_VALUE(TREE_CHAIN(TREE_OPERAND(call_exp, 1)));
1439 if ( TREE_CODE( t ) == ADDR_EXPR ) {
1440 t = TREE_OPERAND(t, 0);
1443 return buildCall( void_type_node, // assuming nobody tries to change the return type
1444 addressOf( built_in_decls[BUILT_IN_VA_START] ),
1445 tree_cons( NULL_TREE, val_arg,
1446 tree_cons( NULL_TREE, t, NULL_TREE )));
1448 default:
1449 abort();
1450 break;
1453 } else if (0 /** WIP **/ && DECL_BUILT_IN_CLASS(callee) == BUILT_IN_FRONTEND) {
1454 // %%TODO: need to handle BITS_BIG_ENDIAN
1455 // %%TODO: need to make expressions unsigned
1457 Intrinsic intrinsic = (Intrinsic) DECL_FUNCTION_CODE(callee);
1458 // Might as well do intrinsics here...
1459 switch (intrinsic) {
1460 case INTRINSIC_BSF: // This will use bsf on x86, but BSR becomes 31-(bsf)!!
1461 // drop through
1462 case INTRINSIC_BSR:
1463 // %% types should be correct, but should still check..
1464 // %% 64-bit..
1465 return call_exp;
1466 //YOWZA1
1467 #if D_GCC_VER >= 34
1468 return buildCall(TREE_TYPE(call_exp),
1469 built_in_decls[intrinsic == INTRINSIC_BSF ? BUILT_IN_CTZ : BUILT_IN_CLZ],
1470 TREE_OPERAND(call_exp, 1));
1471 #else
1472 return call_exp;
1473 #endif
1474 case INTRINSIC_BT:
1475 case INTRINSIC_BTC:
1476 case INTRINSIC_BTR:
1477 case INTRINSIC_BTS:
1478 break;
1479 case INTRINSIC_BSWAP:
1480 #if defined(TARGET_386)
1482 #endif
1483 break;
1484 case INTRINSIC_INP:
1485 case INTRINSIC_INPW:
1486 case INTRINSIC_INPL:
1487 case INTRINSIC_OUTP:
1488 case INTRINSIC_OUTPW:
1489 case INTRINSIC_OUTPL:
1490 #ifdef TARGET_386
1491 #else
1492 ::error("Port I/O intrinsic '%s' is only available on ix86 targets",
1493 IDENTIFIER_POINTER(DECL_NAME(callee)));
1494 #endif
1495 break;
1496 default:
1497 abort();
1502 return call_exp;
1505 tree
1506 IRState::arrayElemRef(IndexExp * aer_exp, ArrayScope * aryscp)
1508 Expression * e1 = aer_exp->e1;
1509 Expression * e2 = aer_exp->e2;
1511 Type * base_type = e1->type->toBasetype();
1512 TY base_type_ty = base_type->ty;
1514 #if ! V2
1515 gcc_assert(! base_type->next->isbit());
1516 #endif
1518 tree index_expr; // logical index
1519 tree subscript_expr; // expr that indexes the array data
1520 tree ptr_exp; // base pointer to the elements
1521 tree elem_ref; // reference the the element
1523 index_expr = e2->toElem( this );
1524 subscript_expr = index_expr;
1526 switch (base_type_ty) {
1527 case Tarray:
1528 case Tsarray:
1530 tree e1_tree = e1->toElem(this);
1532 e1_tree = aryscp->setArrayExp(e1_tree, e1->type);
1534 if ( global.params.useArrayBounds &&
1535 // If it's a static array and the index is
1536 // constant, the front end has already
1537 // checked the bounds.
1538 ! (base_type_ty == Tsarray && e2->isConst()) ) {
1541 tree array_len_expr, throw_expr, oob_cond;
1542 // implement bounds check as a conditional expression:
1543 // a[ inbounds(index) ? index : { throw ArrayBoundsError } ]
1545 // First, set up the index expression to only be evaluated
1546 // once.
1547 // %% save_expr does this check: if (! TREE_CONSTANT( index_expr ))
1548 // %% so we don't do a <0 check for a[2]...
1549 index_expr = maybeMakeTemp( index_expr );
1551 if (base_type_ty == Tarray) {
1552 e1_tree = maybeMakeTemp(e1_tree);
1553 array_len_expr = darrayLenRef(e1_tree);
1554 } else {
1555 array_len_expr = ((TypeSArray *) base_type)->dim->toElem(this);
1558 oob_cond = boundsCond(index_expr, array_len_expr, false);
1559 throw_expr = assertCall(aer_exp->loc, LIBCALL_ARRAY_BOUNDS);
1561 subscript_expr = build( COND_EXPR, TREE_TYPE( index_expr ),
1562 oob_cond, index_expr, throw_expr );
1565 // %% TODO: make this an ARRAY_REF?
1566 if (base_type_ty == Tarray)
1567 ptr_exp = darrayPtrRef( e1_tree ); // %% do convert in darrayPtrRef?
1568 else
1569 ptr_exp = addressOf( e1_tree );
1570 // This conversion is required for static arrays and is just-to-be-safe
1571 // for dynamic arrays
1572 ptr_exp = d_convert_basic(base_type->nextOf()->pointerTo()->toCtype(), ptr_exp);
1574 break;
1575 case Tpointer:
1576 // Ignores aryscp
1577 ptr_exp = e1->toElem( this );
1578 break;
1579 default:
1580 abort();
1583 ptr_exp = pvoidOkay( ptr_exp );
1584 subscript_expr = aryscp->finish( subscript_expr );
1585 elem_ref = indirect(pointerIntSum( ptr_exp, subscript_expr),
1586 TREE_TYPE(TREE_TYPE(ptr_exp)));
1588 return elem_ref;
1591 tree
1592 IRState::darrayPtrRef(tree exp)
1594 // Get the backend type for the array and pick out the array data
1595 // pointer field (assumed to be the second field.)
1596 tree ptr_field = TREE_CHAIN( TYPE_FIELDS( TREE_TYPE( exp )));
1597 //return build(COMPONENT_REF, TREE_TYPE( ptr_field ), exp, ptr_field);
1598 return component(exp, ptr_field);
1601 tree
1602 IRState::darrayLenRef(tree exp)
1604 // Get the backend type for the array and pick out the array length
1605 // field (assumed to be the first field.)
1606 tree len_field = TYPE_FIELDS( TREE_TYPE( exp ));
1607 return component(exp, len_field);
1611 tree
1612 IRState::darrayVal(tree type, tree len, tree data)
1614 // %% assert type is a darray
1615 tree ctor = make_node( CONSTRUCTOR );
1616 tree len_field, ptr_field;
1617 CtorEltMaker ce;
1619 TREE_TYPE( ctor ) = type;
1620 TREE_STATIC( ctor ) = 0; // can be set by caller if needed
1621 TREE_CONSTANT( ctor ) = 0; // "
1622 len_field = TYPE_FIELDS( TREE_TYPE( ctor ));
1623 ptr_field = TREE_CHAIN( len_field );
1625 ce.cons(len_field, len);
1626 ce.cons(ptr_field, data); // shouldn't need to convert the pointer...
1627 CONSTRUCTOR_ELTS( ctor ) = ce.head;
1629 return ctor;
1632 tree
1633 IRState::darrayVal(tree type, uinteger_t len, tree data)
1635 // %% assert type is a darray
1636 tree ctor = make_node( CONSTRUCTOR );
1637 tree len_value, ptr_value, len_field, ptr_field;
1638 CtorEltMaker ce;
1640 TREE_TYPE( ctor ) = type;
1641 TREE_STATIC( ctor ) = 0; // can be set by caller if needed
1642 TREE_CONSTANT( ctor ) = 0; // "
1643 len_field = TYPE_FIELDS( TREE_TYPE( ctor ));
1644 ptr_field = TREE_CHAIN( len_field );
1646 if (data ) {
1647 assert( POINTER_TYPE_P( TREE_TYPE( data )));
1648 ptr_value = data;
1649 } else {
1650 ptr_value = d_null_pointer;
1653 len_value = integerConstant(len, TREE_TYPE(len_field));
1655 ce.cons(len_field, len_value);
1656 ce.cons(ptr_field, ptr_value ); // shouldn't need to convert the pointer...
1658 CONSTRUCTOR_ELTS( ctor ) = ce.head;
1660 return ctor;
1663 tree
1664 IRState::darrayString(const char * str)
1666 unsigned len = strlen(str);
1667 // %% assumes str is null-terminated
1668 tree str_tree = build_string(len + 1, str);
1670 TREE_TYPE( str_tree ) = arrayType(Type::tchar, len);
1671 return darrayVal(Type::tchar->arrayOf()->toCtype(), len, addressOf(str_tree));
1674 char *
1675 IRState::hostToTargetString(char * str, size_t length, unsigned unit_size)
1677 if (unit_size == 1)
1678 return str;
1679 assert(unit_size == 2 || unit_size == 4);
1681 bool flip;
1682 #if D_GCC_VER < 41
1683 # ifdef HOST_WORDS_BIG_ENDIAN
1684 flip = (bool) ! BYTES_BIG_ENDIAN;
1685 # else
1686 flip = (bool) BYTES_BIG_ENDIAN;
1687 # endif
1688 #else
1689 # if WORDS_BIG_ENDIAN
1690 flip = (bool) ! BYTES_BIG_ENDIAN;
1691 # else
1692 flip = (bool) BYTES_BIG_ENDIAN;
1693 # endif
1694 #endif
1696 if (flip) {
1697 char * out_str = (char *) xmalloc(length * unit_size);
1698 const d_uns8 * p_src = (const d_uns8 *) str;
1699 d_uns8 * p_out = (d_uns8 *) out_str;
1701 while (length--) {
1702 if (unit_size == 2) {
1703 p_out[0] = p_src[1];
1704 p_out[1] = p_src[0];
1705 } else /* unit_size == 4 */ {
1706 p_out[0] = p_src[3];
1707 p_out[1] = p_src[2];
1708 p_out[2] = p_src[1];
1709 p_out[3] = p_src[0];
1711 p_src += unit_size;
1712 p_out += unit_size;
1714 return out_str;
1715 } else {
1716 return str;
1721 tree
1722 IRState::arrayLength(tree exp, Type * exp_type)
1724 Type * base_type = exp_type->toBasetype();
1725 switch (base_type->ty) {
1726 case Tsarray:
1727 return size_int( ((TypeSArray *) base_type)->dim->toUInteger() );
1728 case Tarray:
1729 return darrayLenRef(exp);
1730 default:
1731 ::error("can't determine the length of a %s", exp_type->toChars());
1732 return error_mark_node;
1736 tree
1737 IRState::floatMod(tree a, tree b, Type * d_type)
1739 enum built_in_function fn;
1740 switch (d_type->toBasetype()->ty) {
1741 case Tfloat32:
1742 case Timaginary32:
1743 fn = BUILT_IN_FMODF;
1744 break;
1745 case Tfloat64:
1746 case Timaginary64:
1747 no_long_double:
1748 fn = BUILT_IN_FMOD;
1749 break;
1750 case Tfloat80:
1751 case Timaginary80:
1752 if (! haveLongDouble())
1753 goto no_long_double;
1754 fn = BUILT_IN_FMODL;
1755 break;
1756 default:
1757 ::error("tried to perform floating-point modulo division on %s",
1758 d_type->toChars());
1759 return error_mark_node;
1761 tree decl = built_in_decls[fn];
1762 // %% assuming no arg conversion needed
1763 // %% bypassing buildCall since this shouldn't have
1764 // side effects
1765 return buildCall(TREE_TYPE(TREE_TYPE(decl)),
1766 addressOf(decl),
1767 tree_cons(NULL_TREE, a,
1768 tree_cons(NULL_TREE, b, NULL_TREE)));
1771 tree
1772 IRState::typeinfoReference(Type * t)
1774 tree ti_ref = t->getInternalTypeInfo(NULL)->toElem(this);
1775 assert( POINTER_TYPE_P( TREE_TYPE( ti_ref )) );
1776 return ti_ref;
1779 target_size_t
1780 IRState::getTargetSizeConst(tree t)
1782 target_size_t result;
1783 if (sizeof(HOST_WIDE_INT) < sizeof(target_size_t))
1785 gcc_assert(sizeof(HOST_WIDE_INT) * 2 == sizeof(target_size_t));
1786 result = (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW( t );
1787 result += ((target_size_t) (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH( t ))
1788 << HOST_BITS_PER_WIDE_INT;
1790 else
1791 result = tree_low_cst( t, 1 );
1792 return result;
1795 // delegate is
1796 // struct delegate {
1797 // void * frame_or_object;
1798 // void * function;
1799 // }
1801 tree
1802 IRState::delegateObjectRef(tree exp)
1804 // Get the backend type for the array and pick out the array data
1805 // pointer field (assumed to be the first field.)
1806 tree obj_field = TYPE_FIELDS( TREE_TYPE( exp ));
1807 //return build(COMPONENT_REF, TREE_TYPE( obj_field ), exp, obj_field);
1808 return component(exp, obj_field);
1811 tree
1812 IRState::delegateMethodRef(tree exp)
1814 // Get the backend type for the array and pick out the array length
1815 // field (assumed to be the second field.)
1816 tree method_field = TREE_CHAIN( TYPE_FIELDS( TREE_TYPE( exp )));
1817 //return build(COMPONENT_REF, TREE_TYPE( method_field ), exp, method_field);
1818 return component(exp, method_field);
1821 // Converts pointer types of method_exp and object_exp to match d_type
1822 tree
1823 IRState::delegateVal(tree method_exp, tree object_exp, Type * d_type)
1825 Type * base_type = d_type->toBasetype();
1826 if ( base_type->ty == Tfunction ) {
1827 // Called from DotVarExp. These are just used to
1828 // make function calls and not to make Tdelegate variables.
1829 // Clearing the type makes sure of this.
1830 base_type = 0;
1831 } else {
1832 assert(base_type->ty == Tdelegate);
1835 tree type = base_type ? base_type->toCtype() : NULL_TREE;
1836 tree ctor = make_node( CONSTRUCTOR );
1837 tree obj_field = NULL_TREE;
1838 tree func_field = NULL_TREE;
1839 CtorEltMaker ce;
1841 if (type) {
1842 TREE_TYPE( ctor ) = type;
1843 obj_field = TYPE_FIELDS( type );
1844 func_field = TREE_CHAIN( obj_field );
1846 ce.cons(obj_field, object_exp);
1847 ce.cons(func_field, method_exp);
1848 CONSTRUCTOR_ELTS( ctor ) = ce.head;
1850 return ctor;
1853 void
1854 IRState::extractMethodCallExpr(tree mcr, tree & callee_out, tree & object_out) {
1855 assert( D_IS_METHOD_CALL_EXPR( mcr ));
1856 #if D_GCC_VER < 41
1857 tree elts = CONSTRUCTOR_ELTS( mcr );
1858 object_out = TREE_VALUE( elts );
1859 callee_out = TREE_VALUE( TREE_CHAIN( elts ));
1860 #else
1861 VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS( mcr );
1862 object_out = VEC_index(constructor_elt, elts, 0)->value;
1863 callee_out = VEC_index(constructor_elt, elts, 1)->value;
1864 #endif
1867 tree
1868 IRState::objectInstanceMethod(Expression * obj_exp, FuncDeclaration * func, Type * d_type)
1870 Type * obj_type = obj_exp->type->toBasetype();
1871 if (func->isThis()) {
1872 bool is_dottype;
1873 tree this_expr;
1875 // DotTypeExp cannot be evaluated
1876 if (obj_exp->op == TOKdottype) {
1877 is_dottype = true;
1878 this_expr = ((DotTypeExp *) obj_exp)->e1->toElem( this );
1879 } else if (obj_exp->op == TOKcast &&
1880 ((CastExp*) obj_exp)->e1->op == TOKdottype) {
1881 is_dottype = true;
1882 // see expression.c:"See if we need to adjust the 'this' pointer"
1883 this_expr = ((DotTypeExp *) ((CastExp*) obj_exp)->e1)->e1->toElem( this );
1884 } else {
1885 is_dottype = false;
1886 this_expr = obj_exp->toElem( this );
1889 // Calls to super are static (func is the super's method)
1890 // Structs don't have vtables.
1891 // Final and non-virtual methods can be called directly.
1892 // DotTypeExp means non-virtual
1894 if (obj_exp->op == TOKsuper ||
1895 obj_type->ty == Tstruct || obj_type->ty == Tpointer ||
1896 func->isFinal() || ! func->isVirtual() || is_dottype) {
1898 if (obj_type->ty == Tstruct)
1899 this_expr = addressOf(this_expr);
1900 return methodCallExpr(functionPointer(func), this_expr, d_type);
1901 } else {
1902 // Interface methods are also in the class's vtable, so we don't
1903 // need to convert from a class pointer to an interface pointer.
1904 this_expr = maybeMakeTemp( this_expr );
1906 tree vtbl_ref;
1907 //#if D_GCC_VER >= 40
1908 /* Folding of *&<static var> fails because of the type of the
1909 address expression is 'Object' while the type of the static
1910 var is a particular class (why?). This prevents gimplification
1911 of the expression.
1913 if (TREE_CODE(this_expr) == ADDR_EXPR /*&&
1914 // can't use this check
1915 TREE_TYPE(TREE_OPERAND(this_expr, 0)) ==
1916 TREE_TYPE(TREE_TYPE(this_expr))*/)
1917 vtbl_ref = TREE_OPERAND(this_expr, 0);
1918 else
1919 //#endif
1920 vtbl_ref = indirect(this_expr);
1922 tree field = TYPE_FIELDS( TREE_TYPE( vtbl_ref )); // the vtbl is the first field
1923 //vtbl_ref = build( COMPONENT_REF, TREE_TYPE( field ), vtbl_ref, field ); // vtbl field (a pointer)
1924 vtbl_ref = component( vtbl_ref, field ); // vtbl field (a pointer)
1925 // %% better to do with array ref?
1926 vtbl_ref = build( PLUS_EXPR, TREE_TYPE(vtbl_ref), vtbl_ref,
1927 size_int( PTRSIZE * func->vtblIndex ));
1928 vtbl_ref = indirect(vtbl_ref, TREE_TYPE( functionPointer(func) ));
1930 return methodCallExpr(vtbl_ref, this_expr, d_type);
1932 } else {
1933 // Static method; ignore the object instance
1934 return addressOf(func);
1939 tree
1940 IRState::realPart(tree c) {
1941 return build1(REALPART_EXPR, TREE_TYPE(TREE_TYPE(c)), c);
1943 tree
1944 IRState::imagPart(tree c) {
1945 return build1(IMAGPART_EXPR, TREE_TYPE(TREE_TYPE(c)), c);
1948 tree
1949 IRState::assignValue(Expression * e, VarDeclaration * v)
1951 if (e->op == TOKassign || e->op == TOKconstruct || e->op == TOKblit)
1953 AssignExp * a_exp = (AssignExp *) e;
1954 if (a_exp->e1->op == TOKvar && ((VarExp *) a_exp->e1)->var == v)
1955 return convertForAssignment(a_exp->e2, v->type);
1956 //else
1957 //return e->toElem(this);
1959 return NULL_TREE;
1963 tree
1964 IRState::twoFieldType(tree rec_type, tree ft1, tree ft2, Type * d_type, const char * n1, const char * n2)
1966 tree f0 = build_decl(FIELD_DECL, get_identifier(n1), ft1);
1967 tree f1 = build_decl(FIELD_DECL, get_identifier(n2), ft2);
1968 DECL_CONTEXT(f0) = rec_type;
1969 DECL_CONTEXT(f1) = rec_type;
1970 TYPE_FIELDS(rec_type) = chainon(f0, f1);
1971 layout_type(rec_type);
1972 if (d_type) {
1973 /* This is needed so that maybeExpandSpecialCall knows to
1974 split dynamic array varargs. */
1975 TYPE_LANG_SPECIFIC( rec_type ) = build_d_type_lang_specific(d_type);
1977 /* ObjectFile::declareType will try to declare it as top-level type
1978 which can break debugging info for element types. */
1979 tree stub_decl = build_decl(TYPE_DECL, get_identifier(d_type->toChars()), rec_type);
1980 TYPE_STUB_DECL(rec_type) = stub_decl;
1981 TYPE_NAME(rec_type) = stub_decl;
1982 DECL_ARTIFICIAL(stub_decl) = 1;
1983 g.ofile->rodc(stub_decl, 0);
1985 return rec_type;
1988 // Create a record type from two field types
1989 tree
1990 IRState::twoFieldType(Type * ft1, Type * ft2, Type * d_type, const char * n1, const char * n2)
1992 return twoFieldType( make_node( RECORD_TYPE ), ft1->toCtype(), ft2->toCtype(), d_type, n1, n2 );
1995 tree
1996 IRState::twoFieldCtor(tree rec_type, tree f1, tree f2, int storage_class)
1998 tree ctor = make_node( CONSTRUCTOR );
1999 tree ft1, ft2;
2000 CtorEltMaker ce;
2002 TREE_TYPE( ctor ) = rec_type;
2003 TREE_STATIC( ctor ) = (storage_class & STCstatic) != 0;
2004 TREE_CONSTANT( ctor ) = (storage_class & STCconst) != 0;
2005 TREE_READONLY( ctor ) = (storage_class & STCconst) != 0;
2006 ft1 = TYPE_FIELDS( rec_type );
2007 ft2 = TREE_CHAIN( ft1 );
2009 ce.cons(ft1, f1);
2010 ce.cons(ft2, f2);
2011 CONSTRUCTOR_ELTS( ctor ) = ce.head;
2013 return ctor;
2016 // This could be made more lax to allow better CSE (?)
2017 bool
2018 needs_temp(tree t) {
2019 // %%TODO: check for anything with TREE_SIDE_EFFECTS?
2020 switch (TREE_CODE(t)) {
2021 case VAR_DECL:
2022 case FUNCTION_DECL:
2023 case PARM_DECL:
2024 case CONST_DECL:
2025 case SAVE_EXPR:
2026 return false;
2028 case ADDR_EXPR:
2029 #if D_GCC_VER < 40
2030 case REFERENCE_EXPR:
2031 #endif
2032 /* This check is needed for 4.0. Without it, typeinfo.methodCall may not be
2034 return ! (DECL_P(TREE_OPERAND(t, 0)));
2036 case INDIRECT_REF:
2037 case COMPONENT_REF:
2038 case NOP_EXPR:
2039 case NON_LVALUE_EXPR:
2040 case VIEW_CONVERT_EXPR:
2041 return needs_temp(TREE_OPERAND(t, 0));
2042 case ARRAY_REF:
2043 return true;
2044 default:
2045 if (
2046 #if D_GCC_VER >= 40
2047 TREE_CODE_CLASS(TREE_CODE(t)) == tcc_constant)
2048 #else
2049 TREE_CODE_CLASS(TREE_CODE(t)) == 'c')
2050 #endif
2051 return false;
2052 else
2053 return true;
2057 bool
2058 IRState::isFreeOfSideEffects(tree t)
2060 // SAVE_EXPR is safe to reference more than once, but not to
2061 // expand in a loop.
2062 return TREE_CODE(t) != SAVE_EXPR && ! needs_temp(t);
2065 tree
2066 IRState::maybeMakeTemp(tree t)
2068 if (needs_temp(t)) {
2069 if (TREE_CODE(TREE_TYPE(t)) != ARRAY_TYPE)
2070 return save_expr(t);
2071 else
2072 return stabilize_reference(t);
2073 } else
2074 return t;
2077 Module * IRState::builtinsModule = 0;
2078 Module * IRState::intrinsicModule = 0;
2079 TemplateDeclaration * IRState::stdargTemplateDecl = 0;
2080 TemplateDeclaration * IRState::cstdargStartTemplateDecl = 0;
2081 TemplateDeclaration * IRState::cstdargArgTemplateDecl = 0;
2083 bool
2084 IRState::maybeSetUpBuiltin(Declaration * decl)
2086 Dsymbol * dsym;
2087 TemplateInstance * ti;
2089 // Don't use toParent2. We are looking for a template below.
2090 dsym = decl->toParent();
2092 if (dsym->getModule() == intrinsicModule) {
2093 // Matches order of Intrinsic enum
2094 static const char * intrinsic_names[] = {
2095 "bsf", "bsr",
2096 "bt", "btc", "btr", "bts",
2097 "bswap",
2098 "inp", "inpw", "inpl",
2099 "outp", "outw", "outl", NULL
2101 for (int i = 0; intrinsic_names[i]; i++) {
2102 if ( ! strcmp( decl->ident->string, intrinsic_names[i] ) ) {
2103 bool have_intrinsic = false;
2104 tree t = decl->toSymbol()->Stree;
2106 switch ( (Intrinsic) i ) {
2107 case INTRINSIC_BSF:
2108 case INTRINSIC_BSR:
2109 case INTRINSIC_BT:
2110 case INTRINSIC_BTC:
2111 case INTRINSIC_BTR:
2112 case INTRINSIC_BTS:
2113 break;
2114 case INTRINSIC_BSWAP:
2115 #if defined(TARGET_386)
2116 //have_intrinsic = true;
2117 #endif
2118 break;
2119 case INTRINSIC_INP:
2120 case INTRINSIC_INPW:
2121 case INTRINSIC_INPL:
2122 case INTRINSIC_OUTP:
2123 case INTRINSIC_OUTPW:
2124 case INTRINSIC_OUTPL:
2125 // Only on ix86, but need to given error message on others
2126 have_intrinsic = true;
2127 break;
2128 default:
2129 abort();
2132 if (have_intrinsic) {
2133 DECL_BUILT_IN_CLASS( t ) = BUILT_IN_FRONTEND;
2134 DECL_FUNCTION_CODE( t ) = (built_in_function) i;
2135 return true;
2136 } else
2137 return false;
2140 } else if (dsym) {
2141 ti = dsym->isTemplateInstance();
2142 if (ti) {
2143 tree t = decl->toSymbol()->Stree;
2144 if (ti->tempdecl == stdargTemplateDecl) {
2145 DECL_BUILT_IN_CLASS(t) = BUILT_IN_FRONTEND;
2146 DECL_FUNCTION_CODE(t) = (built_in_function) INTRINSIC_STD_VA_ARG;
2147 return true;
2148 } else if (ti->tempdecl == cstdargArgTemplateDecl) {
2149 DECL_BUILT_IN_CLASS(t) = BUILT_IN_FRONTEND;
2150 DECL_FUNCTION_CODE(t) = (built_in_function) INTRINSIC_C_VA_ARG;
2151 return true;
2152 } else if (ti->tempdecl == cstdargStartTemplateDecl) {
2153 DECL_BUILT_IN_CLASS(t) = BUILT_IN_FRONTEND;
2154 DECL_FUNCTION_CODE(t) = (built_in_function) INTRINSIC_C_VA_START;
2155 return true;
2159 return false;
2162 bool
2163 IRState::isDeclarationReferenceType(Declaration * decl)
2165 Type * base_type = decl->type->toBasetype();
2167 // D doesn't do this now..
2168 if ( base_type->ty == Treference ) {
2169 return true;
2172 if ( decl->isOut() || decl->isRef() ||
2173 ( decl->isParameter() && base_type->ty == Tsarray ) ) {
2174 return true;
2177 return false;
2180 tree
2181 IRState::trueDeclarationType(Declaration * decl)
2183 // If D supported references, we would have to check twice for
2184 // (out T &) -- disallow, maybe or make isDeclarationReferenceType return
2185 // the number of levels to reference
2186 tree decl_type = decl->type->toCtype();
2187 if ( isDeclarationReferenceType( decl )) {
2188 return build_reference_type( decl_type );
2189 } else if (decl->storage_class & STClazy) {
2190 TypeFunction *tf = new TypeFunction(NULL, decl->type, 0, LINKd);
2191 TypeDelegate *t = new TypeDelegate(tf);
2192 return t->merge()->toCtype();
2193 } else {
2194 return decl_type;
2198 // These should match the Declaration versions above
2199 bool
2200 IRState::isArgumentReferenceType(Argument * arg)
2202 Type * base_type = arg->type->toBasetype();
2204 if ( base_type->ty == Treference ) {
2205 return true;
2208 if ( (arg->storageClass & (STCout | STCref)) || base_type->ty == Tsarray ) {
2209 return true;
2212 return false;
2215 tree
2216 IRState::trueArgumentType(Argument * arg)
2218 tree arg_type = arg->type->toCtype();
2219 if ( isArgumentReferenceType( arg )) {
2220 return build_reference_type( arg_type );
2221 } else if (arg->storageClass & STClazy) {
2222 TypeFunction *tf = new TypeFunction(NULL, arg->type, 0, LINKd);
2223 TypeDelegate *t = new TypeDelegate(tf);
2224 return t->merge()->toCtype();
2225 } else {
2226 return arg_type;
2230 tree
2231 IRState::arrayType(tree type_node, uinteger_t size)
2233 tree index_type_node;
2234 if (size > 0) {
2235 index_type_node = size_int( size - 1 );
2236 index_type_node = build_index_type(index_type_node);
2237 } else {
2238 // See c-decl.c grokdeclarator for zero-length arrays
2239 index_type_node = build_range_type (sizetype, size_zero_node,
2240 NULL_TREE);
2243 tree array_type = build_array_type(type_node, index_type_node);
2244 if (size == 0) {
2245 #if D_GCC_VER < 40
2246 layout_type(array_type);
2247 #endif
2248 TYPE_SIZE(array_type) = bitsize_zero_node;
2249 TYPE_SIZE_UNIT(array_type) = size_zero_node;
2251 return array_type;
2254 tree
2255 IRState::addTypeAttribute(tree type, const char * attrname, tree value)
2257 // use build_type_copy / build_type_attribute_variant
2259 // types built by functions in tree.c need to be treated as immutable
2260 if ( ! TYPE_ATTRIBUTES( type )) { // ! TYPE_ATTRIBUTES -- need a better check
2261 type = build_type_copy( type );
2262 // TYPE_STUB_DECL( type ) = .. if we need this for structs, etc.. since
2263 // TREE_CHAIN is cleared by COPY_NODE
2265 if (value)
2266 value = tree_cons(NULL_TREE, value, NULL_TREE);
2267 TYPE_ATTRIBUTES( type ) = tree_cons( get_identifier(attrname), value,
2268 TYPE_ATTRIBUTES( type ));
2269 return type;
2272 void
2273 IRState::addDeclAttribute(tree type, const char * attrname, tree value)
2275 if (value)
2276 value = tree_cons(NULL_TREE, value, NULL_TREE);
2277 DECL_ATTRIBUTES( type ) = tree_cons( get_identifier(attrname), value,
2278 DECL_ATTRIBUTES( type ));
2281 tree
2282 IRState::attributes(Expressions * in_attrs)
2284 if (! in_attrs)
2285 return NULL_TREE;
2287 ListMaker out_attrs;
2289 for (unsigned i = 0; i < in_attrs->dim; i++)
2291 Expression * e = (Expression *) in_attrs->data[i];
2292 IdentifierExp * ident_e = NULL;
2294 ListMaker args;
2296 if (e->op == TOKidentifier)
2297 ident_e = (IdentifierExp *) e;
2298 else if (e->op == TOKcall)
2300 CallExp * c = (CallExp *) e;
2301 assert(c->e1->op == TOKidentifier);
2302 ident_e = (IdentifierExp *) c->e1;
2304 if (c->arguments) {
2305 for (unsigned ai = 0; ai < c->arguments->dim; ai++) {
2306 Expression * ae = (Expression *) c->arguments->data[ai];
2307 tree aet;
2308 if (ae->op == TOKstring && ((StringExp *) ae)->sz == 1)
2310 StringExp * s = (StringExp *) ae;
2311 aet = build_string(s->len, (const char*) s->string);
2313 else
2314 aet = ae->toElem(&gen);
2315 args.cons(aet);
2319 else
2321 gcc_unreachable();
2322 continue;
2324 out_attrs.cons(get_identifier(ident_e->ident->string), args.head);
2327 return out_attrs.head;
2330 tree
2331 IRState::integerConstant(xdmd_integer_t value, tree type) {
2332 #if D_GCC_VER < 40
2333 // Assuming xdmd_integer_t is 64 bits
2334 # if HOST_BITS_PER_WIDE_INT == 32
2335 tree tree_value = build_int_2(value & 0xffffffff, (value >> 32) & 0xffffffff);
2336 # elif HOST_BITS_PER_WIDE_INT == 64
2337 tree tree_value = build_int_2(value,
2338 type && ! TREE_UNSIGNED(type) && (value & 0x8000000000000000ULL) ?
2339 ~(unsigned HOST_WIDE_INT) 0 : 0);
2340 # else
2341 # error Fix This
2342 # endif
2343 if (type) {
2344 TREE_TYPE( tree_value ) = type;
2345 // May not to call force_fit_type for 3.3.x and 3.4.x, but being safe.
2346 force_fit_type(tree_value, 0);
2348 #else
2349 # if HOST_BITS_PER_WIDE_INT == 32
2350 tree tree_value = build_int_cst_wide(type,
2351 value & 0xffffffff, (value >> 32) & 0xffffffff);
2352 # elif HOST_BITS_PER_WIDE_INT == 64
2353 tree tree_value = build_int_cst_type(type, value);
2354 # else
2355 # error Fix This
2356 # endif
2357 /* VALUE may be an incorrect representation for TYPE. Example:
2358 uint x = cast(uint) -3; // becomes "-3u" -- value=0xfffffffffffffd type=Tuns32
2359 Constant folding will not work correctly unless this is done. */
2360 tree_value = force_fit_type(tree_value, 0, 0, 0);
2361 #endif
2362 return tree_value;
2365 tree
2366 IRState::exceptionObject()
2368 tree obj_type = getObjectType()->toCtype();
2369 // Like gjc, the actual D exception object is one
2370 // pointer behind the exception header
2371 tree t = build (EXC_PTR_EXPR, ptr_type_node);
2372 t = build1(NOP_EXPR, build_pointer_type(obj_type), t); // treat exception header as ( Object* )
2373 t = build(MINUS_EXPR, TREE_TYPE(t), t, TYPE_SIZE_UNIT(TREE_TYPE(t)));
2374 t = build1(INDIRECT_REF, obj_type, t);
2375 return t;
2378 tree
2379 IRState::label(Loc loc, Identifier * ident) {
2380 tree t_label = build_decl(LABEL_DECL,
2381 ident ? get_identifier(ident->string) : NULL_TREE, void_type_node);
2382 DECL_CONTEXT( t_label ) = current_function_decl;
2383 DECL_MODE( t_label ) = VOIDmode;
2384 if (loc.filename)
2385 g.ofile->setDeclLoc(t_label, loc);
2386 return t_label;
2389 tree
2390 IRState::getFrameForFunction(FuncDeclaration * f)
2392 if (f->fbody)
2393 return getFrameForSymbol(f);
2394 else
2396 // Should error on line that references f
2397 f->error("nested function missing body");
2398 return d_null_pointer;
2401 tree
2402 IRState::getFrameForNestedClass(ClassDeclaration *c)
2404 return getFrameForSymbol(c);
2407 /* If nested_sym is a nested function, return the static chain to be
2408 used when invoking that function.
2410 If nested_sym is a nested class, return the static chain to be used
2411 when creating an instance of the class.
2413 This method is protected to enforce the type checking of
2414 getFrameForFunction and getFrameForNestedClass.
2415 getFrameForFunction also checks that the nestd function is properly
2416 defined.
2419 tree
2420 IRState::getFrameForSymbol(Dsymbol * nested_sym)
2422 FuncDeclaration * nested_func = 0;
2423 FuncDeclaration * outer_func = 0;
2425 if ( (nested_func = nested_sym->isFuncDeclaration()) )
2427 // gcc_assert(nested_func->isNested())
2428 outer_func = nested_func->toParent2()->isFuncDeclaration();
2429 gcc_assert(outer_func != NULL);
2431 else
2433 /* It's a class. NewExp::toElem has already determined its
2434 outer scope is not another class, so it must be a
2435 function. */
2437 Dsymbol * sym = nested_sym;
2439 while (sym && ! (outer_func = sym->isFuncDeclaration()))
2440 sym = sym->toParent2();
2442 /* Make sure we can access the frame of outer_func.
2444 For GCC < 4.0:
2446 f() {
2447 class X {
2448 m() { }
2450 g() {
2451 h() {
2452 new X // <-- you are here
2457 In order to get the static chain we must know a
2458 function nested in F. If we are currently in such a
2459 nested function, use that.
2461 f() {
2462 class X { m() { } }
2463 new X // <-- you are here
2466 If we are at the level of the function containing the
2467 class, the answer is just 'virtual_stack_vars_rtx'.
2470 if (outer_func != func) {
2472 Dsymbol * o = nested_func = func;
2473 do {
2474 if (! nested_func->isNested())
2475 goto cannot_access_frame;
2476 while ( (o = o->toParent2()) )
2477 if ( (nested_func = o->isFuncDeclaration()) )
2478 break;
2479 } while (o && o != outer_func);
2481 if (! o) {
2482 cannot_access_frame:
2483 error("cannot access frame of function '%s' from '%s'",
2484 outer_func->ident->string, func->ident->string);
2485 return d_null_pointer;
2488 // else, the answer is 'virtual_stack_vars_rtx'
2491 #if V2
2492 if (getFrameInfo(outer_func)->creates_closure)
2493 return getClosureRef(outer_func);
2494 #endif
2496 #if D_GCC_VER < 40
2497 tree result = make_node (RTL_EXPR);
2498 TREE_TYPE (result) = ptr_type_node;
2499 RTL_EXPR_RTL (result) = nested_func ?
2500 lookup_static_chain(nested_func->toSymbol()->Stree) :
2501 virtual_stack_vars_rtx;
2502 return result;
2503 #else
2504 if (! outer_func)
2505 outer_func = nested_func->toParent2()->isFuncDeclaration();
2506 gcc_assert(outer_func != NULL);
2507 return build1(STATIC_CHAIN_EXPR, ptr_type_node, outer_func->toSymbol()->Stree);
2508 #endif
2511 #if V2
2513 /* For the purposes this is used, fd is assumed to be a nested
2514 function or a method of a class that is (eventually) nested in a
2515 function.
2517 static bool
2518 isFuncNestedInFunc(FuncDeclaration * fd, FuncDeclaration *fo)
2520 if (fd == fo)
2521 return false;
2523 while (fd)
2525 AggregateDeclaration * ad;
2526 ClassDeclaration * cd;
2528 if (fd == fo)
2530 //fprintf(stderr, "%s is nested in %s\n", fd->toChars(), fo->toChars());
2531 return true;
2533 else if (fd->isNested())
2534 fd = fd->toParent2()->isFuncDeclaration();
2535 else if ( (ad = fd->isThis()) && (cd = ad->isClassDeclaration()) )
2537 fd = NULL;
2538 while (cd && cd->isNested())
2540 Dsymbol * dsym = cd->toParent2();
2541 if ( (fd = dsym->isFuncDeclaration()) )
2542 break;
2543 else
2544 cd = dsym->isClassDeclaration();
2547 else
2548 break;
2551 //fprintf(stderr, "%s is NOT nested in %s\n", fd->toChars(), fo->toChars());
2552 return false;
2555 FuncFrameInfo *
2556 IRState::getFrameInfo(FuncDeclaration *fd)
2558 Symbol * fds = fd->toSymbol();
2559 if (fds->frameInfo)
2560 return fds->frameInfo;
2562 FuncFrameInfo * ffi = new FuncFrameInfo;
2563 ffi->creates_closure = false;
2564 ffi->closure_rec = NULL_TREE;
2566 fds->frameInfo = ffi;
2568 Dsymbol * s = fd->toParent2();
2570 if (fd->needsClosure())
2571 ffi->creates_closure = true;
2572 else
2574 /* If fd is nested (deeply) in a function 'g' that creates a
2575 closure and there exists a function 'h' nested (deeply) in
2576 fd and 'h' accesses the frame of 'g', then fd must also
2577 create a closure.
2579 This is for the sake of a simple implementation. An alternative
2580 is, when determining the frame to pass to 'h', pass the pointer
2581 to 'g' (the deepest 'g' whose frame is accessed by 'h') instead
2582 of the usual frame that 'h' would take.
2584 FuncDeclaration * ff = fd;
2586 while (ff)
2588 AggregateDeclaration * ad;
2589 ClassDeclaration * cd;
2591 if (ff != fd)
2593 if (getFrameInfo(ff)->creates_closure)
2595 for (int i = 0; i < ff->closureVars.dim; i++)
2596 { VarDeclaration *v = (VarDeclaration *)ff->closureVars.data[i];
2597 for (int j = 0; j < v->nestedrefs.dim; j++)
2598 { FuncDeclaration *fi = (FuncDeclaration *)v->nestedrefs.data[j];
2599 if (isFuncNestedInFunc(fi, fd))
2601 ffi->creates_closure = true;
2602 goto L_done;
2609 if (ff->isNested())
2610 ff = ff->toParent2()->isFuncDeclaration();
2611 else if ( (ad = ff->isThis()) && (cd = ad->isClassDeclaration()) )
2613 ff = NULL;
2614 while (cd && cd->isNested())
2616 Dsymbol * dsym = cd->toParent2();
2617 if ( (ff = dsym->isFuncDeclaration()) )
2618 break;
2619 else
2620 cd = dsym->isClassDeclaration();
2623 else
2624 break;
2627 L_done:
2631 /*fprintf(stderr, "%s %s\n", ffi->creates_closure ? "YES" : "NO ",
2632 fd->toChars());*/
2634 return ffi;
2637 // Return a pointer to the closure block of outer_func
2638 tree
2639 IRState::getClosureRef(FuncDeclaration * outer_func)
2641 tree result = closureLink();
2642 FuncDeclaration * fd = closureFunc;
2644 while (fd && fd != outer_func)
2646 AggregateDeclaration * ad;
2647 ClassDeclaration * cd;
2649 gcc_assert(getFrameInfo(fd)->creates_closure); // remove this if we loosen creates_closure
2651 // like compon(indirect, field0) parent closure link is the first field;
2652 result = indirect(result, ptr_type_node);
2654 if (fd->isNested())
2656 fd = fd->toParent2()->isFuncDeclaration();
2658 else if ( (ad = fd->isThis()) && (cd = ad->isClassDeclaration()) )
2660 fd = NULL;
2661 while (cd && cd->isNested())
2663 /* Shouldn't need to do this. getClosureRef is only
2664 used to get the pointer to a function's frame (not
2665 a class instances.) With the current implementation,
2666 the link the closure record always points to the
2667 outer function's frame even if there are intervening
2668 nested classes. So, we can just skip over those...
2670 tree vthis_field = cd->vthis->toSymbol()->Stree;
2671 result = nop(result, cd->type->toCtype());
2672 result = component(indirect(result), vthis_field);
2675 Dsymbol * dsym = cd->toParent2();
2676 if ( (fd = dsym->isFuncDeclaration()) )
2677 break;
2678 else
2679 cd = dsym->isClassDeclaration();
2682 else
2683 break;
2686 if (fd == outer_func)
2688 tree closure_rec = getFrameInfo(outer_func)->closure_rec;
2689 result = nop(result, build_pointer_type(closure_rec));
2690 return result;
2692 else
2694 func->error("cannot access frame of %s", outer_func->toChars());
2695 return d_null_pointer;
2699 #endif
2701 /* Return true if function F needs to have the static chain passed to
2702 it. This only applies to nested function handling provided by the
2703 GCC back end (not D closures.)
2705 bool
2706 IRState::functionNeedsChain(FuncDeclaration *f)
2708 Dsymbol * s;
2709 ClassDeclaration * a;
2710 FuncDeclaration *pf = 0;
2712 if (f->isNested()
2713 #if V2
2714 && ! getFrameInfo(f->toParent2()->isFuncDeclaration())->creates_closure
2715 #endif
2717 return true;
2718 if (f->isStatic())
2719 return false;
2721 s = f->toParent2();
2723 while ( s && (a = s->isClassDeclaration()) && a->isNested() ) {
2724 s = s->toParent2();
2725 if ( (pf = s->isFuncDeclaration())
2726 #if V2
2727 && ! getFrameInfo(pf)->creates_closure
2728 #endif
2730 return true;
2732 return false;
2735 tree
2736 IRState::toElemLvalue(Expression * e)
2739 if (e->op == TOKcast)
2740 fprintf(stderr, "IRState::toElemLvalue TOKcast\n");
2741 else
2744 if (e->op == TOKindex) {
2745 IndexExp * ie = (IndexExp *) e;
2746 Expression * e1 = ie->e1;
2747 Expression * e2 = ie->e2;
2748 Type * type = e->type;
2749 Type * array_type = e1->type->toBasetype();
2751 if (array_type->ty == Taarray) {
2752 Type * key_type = ((TypeAArray *) array_type)->index->toBasetype();
2753 AddrOfExpr aoe;
2755 tree args[4];
2756 args[0] = this->addressOf( this->toElemLvalue(e1) );
2757 args[1] = this->typeinfoReference(key_type);
2758 args[2] = this->integerConstant( array_type->nextOf()->size(), Type::tsize_t );
2759 args[3] = aoe.set(this, this->convertTo( e2, key_type ));
2760 return build1(INDIRECT_REF, type->toCtype(),
2761 aoe.finish(this,
2762 this->libCall(LIBCALL_AAGETP, 4, args, type->pointerTo()->toCtype())));
2765 return e->toElem(this);
2769 #if D_GCC_VER < 40
2771 void
2772 IRState::startCond(Statement * stmt, Expression * e_cond) {
2773 clear_last_expr ();
2774 g.ofile->doLineNote(stmt->loc);
2775 expand_start_cond( convertForCondition( e_cond ), 0 );
2778 void
2779 IRState::startElse() { expand_start_else(); }
2781 void
2782 IRState::endCond() { expand_end_cond(); }
2784 void
2785 IRState::startLoop(Statement * stmt) {
2786 beginFlow(stmt, expand_start_loop_continue_elsewhere(1));
2789 void
2790 IRState::continueHere()
2792 Flow * f = currentFlow();
2793 if (f->overrideContinueLabel)
2794 doLabel(f->overrideContinueLabel);
2795 else
2796 expand_loop_continue_here();
2799 void
2800 IRState::setContinueLabel(tree lbl)
2802 currentFlow()->overrideContinueLabel = lbl;
2805 void
2806 IRState::exitIfFalse(tree t_cond, bool is_top_cond) {
2808 // %% topcond compaitble with continue_elswehre?
2809 expand_exit_loop_if_false(currentFlow()->loop, t_cond);
2812 void
2813 IRState::startCase(Statement * stmt, tree t_cond)
2815 clear_last_expr ();
2816 g.ofile->doLineNote(stmt->loc);
2817 expand_start_case( 1, t_cond, TREE_TYPE( t_cond ), "switch statement" );
2818 beginFlow(stmt, NULL);
2821 void
2822 IRState::doCase(tree t_value, tree t_label)
2824 tree dummy;
2825 // %% not the same convert that is in d-glue!!
2826 pushcase( t_value, convert, t_label, & dummy);
2829 void
2830 IRState::endCase(tree t_cond)
2832 expand_end_case( t_cond );
2833 endFlow();
2836 void
2837 IRState::endLoop() {
2838 expand_end_loop();
2839 endFlow();
2842 void
2843 IRState::continueLoop(Identifier * ident) {
2844 Flow * f = getLoopForLabel( ident, true );
2845 if (f->overrideContinueLabel)
2846 doJump(NULL, f->overrideContinueLabel);
2847 else
2848 expand_continue_loop( f->loop );
2851 void
2852 IRState::exitLoop(Identifier * ident)
2854 if (ident) {
2855 Flow * flow = getLoopForLabel( ident );
2856 if (flow->loop)
2857 expand_exit_loop( flow->loop );
2858 else {
2859 if (! flow->exitLabel)
2860 flow->exitLabel = label(flow->statement->loc);
2861 expand_goto( flow->exitLabel );
2863 } else {
2864 expand_exit_something();
2868 void
2869 IRState::startTry(Statement * stmt)
2871 expand_eh_region_start();
2874 void
2875 IRState::startCatches()
2877 expand_start_all_catch();
2880 void
2881 IRState::startCatch(tree t_type)
2883 expand_start_catch( t_type );
2886 void
2887 IRState::endCatch()
2889 expand_end_catch();
2892 void
2893 IRState::endCatches()
2895 expand_end_all_catch();
2898 void
2899 IRState::startFinally()
2901 abort();
2904 void
2905 IRState::endFinally()
2907 abort();
2910 void
2911 IRState::doReturn(tree t_value)
2913 if (t_value)
2914 expand_return(t_value);
2915 else
2916 expand_null_return();
2919 void
2920 IRState::doJump(Statement * stmt, tree t_label)
2922 // %%TODO: c-semantics.c:expand_stmt GOTO_STMT branch prediction
2923 TREE_USED( t_label ) = 1 ;
2924 if (stmt)
2925 g.ofile->doLineNote( stmt->loc );
2926 expand_goto( t_label );
2929 tree
2930 IRState::makeStmtExpr(Statement * statement)
2932 tree t = build1((enum tree_code) D_STMT_EXPR, void_type_node, NULL_TREE);
2933 TREE_SIDE_EFFECTS(t) = 1; // %%
2934 stmtExprList.push(t);
2935 stmtExprList.push(statement);
2936 stmtExprList.push(this);
2937 return t;
2940 void
2941 IRState::retrieveStmtExpr(tree t, Statement ** s_out, IRState ** i_out)
2943 for (int i = stmtExprList.dim - 3; i >= 0 ; i -= 3) {
2944 if ( (tree) stmtExprList.data[i] == t ) {
2945 *s_out = (Statement *) stmtExprList.data[i + 1];
2946 *i_out = (IRState *) stmtExprList.data[i + 2];
2947 // The expression could be evaluated multiples times, so we must
2948 // keep the values forever --- %% go back to per-function list
2949 return;
2952 abort();
2953 return;
2956 #else
2958 void
2959 IRState::startCond(Statement * stmt, Expression * e_cond)
2961 tree t_cond = convertForCondition(e_cond);
2963 Flow * f = beginFlow(stmt/*, 0*/);
2964 f->condition = t_cond;
2967 void
2968 IRState::startElse()
2970 currentFlow()->trueBranch = popStatementList();
2971 pushStatementList();
2974 void
2975 IRState::endCond()
2977 Flow * f = currentFlow();
2978 tree t_brnch = popStatementList(); // endFlow(); -- can't pop -- need the info?
2979 tree t_false_brnch = NULL_TREE;
2981 if (f->trueBranch == NULL_TREE)
2982 f->trueBranch = t_brnch;
2983 else
2984 t_false_brnch = t_brnch;
2986 g.ofile->doLineNote(f->statement->loc);
2987 tree t_stmt = build3(COND_EXPR, void_type_node,
2988 f->condition, f->trueBranch, t_false_brnch);
2989 endFlow();
2990 addExp(t_stmt);
2993 void
2994 IRState::startLoop(Statement * stmt) {
2995 Flow * f = beginFlow(stmt/*, Break|Continue*/);
2996 f->continueLabel = label(stmt ? stmt->loc : 0); // should be end for 'do' loop
2999 void
3000 IRState::continueHere() {
3001 doLabel(currentFlow()->continueLabel);
3004 void
3005 IRState::setContinueLabel(tree lbl)
3007 currentFlow()->continueLabel = lbl;
3010 void
3011 IRState::exitIfFalse(tree t_cond, bool /*unused*/) {
3012 addExp(build1(EXIT_EXPR, void_type_node,
3013 build1(TRUTH_NOT_EXPR, TREE_TYPE(t_cond), t_cond)));
3016 void
3017 IRState::startCase(Statement * stmt, tree t_cond)
3019 Flow * f = beginFlow(stmt);
3020 f->condition = t_cond;
3023 void
3024 IRState::doCase(tree t_value, tree t_label)
3026 addExp(build3(CASE_LABEL_EXPR, void_type_node,
3027 t_value, NULL_TREE, t_label));
3030 void
3031 IRState::endCase(tree /*t_cond*/)
3033 Flow * f = currentFlow();
3034 tree t_body = popStatementList();
3035 tree t_stmt = build3(SWITCH_EXPR, void_type_node, f->condition,
3036 t_body, NULL_TREE);
3037 addExp(t_stmt);
3038 endFlow();
3041 void
3042 IRState::endLoop() {
3043 // says must contain an EXIT_EXPR -- what about while(1)..goto;? something other thand LOOP_EXPR?
3044 tree t_body = popStatementList();
3045 tree t_loop = build1(LOOP_EXPR, void_type_node, t_body);
3046 addExp(t_loop);
3047 endFlow();
3050 void
3051 IRState::continueLoop(Identifier * ident) {
3052 //doFlowLabel(stmt, ident, Continue);
3053 doJump(NULL, getLoopForLabel(ident, true)->continueLabel );
3056 void
3057 IRState::exitLoop(Identifier * ident) {
3058 Flow * flow = getLoopForLabel(ident);
3059 if (! flow->exitLabel)
3060 flow->exitLabel = label(flow->statement->loc);
3061 doJump(NULL, flow->exitLabel);
3065 void
3066 IRState::startTry(Statement * stmt)
3068 beginFlow(stmt);
3071 void
3072 IRState::startCatches()
3074 currentFlow()->tryBody = popStatementList();
3075 pushStatementList();
3078 void
3079 IRState::startCatch(tree t_type)
3081 currentFlow()->catchType = t_type;
3082 pushStatementList();
3085 void
3086 IRState::endCatch()
3088 tree t_body = popStatementList();
3089 // % wrong loc.. can set pass statement to startCatch, set
3090 // the loc on t_type and then use it here..
3091 // may not be important?
3092 doExp(build2(CATCH_EXPR, void_type_node,
3093 currentFlow()->catchType, t_body));
3096 void
3097 IRState::endCatches()
3099 tree t_catches = popStatementList();
3100 g.ofile->doLineNote(currentFlow()->statement->loc);
3101 doExp(build2(TRY_CATCH_EXPR, void_type_node,
3102 currentFlow()->tryBody, t_catches));
3103 endFlow();
3106 void
3107 IRState::startFinally()
3109 currentFlow()->tryBody = popStatementList();
3110 pushStatementList();
3113 void
3114 IRState::endFinally()
3116 tree t_finally = popStatementList();
3117 g.ofile->doLineNote(currentFlow()->statement->loc);
3118 doExp(build2(TRY_FINALLY_EXPR, void_type_node,
3119 currentFlow()->tryBody, t_finally));
3120 endFlow();
3123 void
3124 IRState::doReturn(tree t_value)
3126 addExp(build1(RETURN_EXPR, void_type_node, t_value));
3129 void
3130 IRState::doJump(Statement * stmt, tree t_label)
3132 if (stmt)
3133 g.ofile->doLineNote( stmt->loc );
3134 addExp(build1(GOTO_EXPR, void_type_node, t_label));
3137 tree
3138 IRState::makeStmtExpr(Statement * statement)
3140 tree t_list;
3142 pushStatementList();
3143 statement->toIR(this);
3144 t_list = popStatementList();
3146 // addExp(t_list);
3148 return t_list;
3151 #endif
3153 void
3154 IRState::doAsm(tree insn_tmpl, tree outputs, tree inputs, tree clobbers)
3156 #if D_GCC_VER < 40
3157 expand_asm_operands(insn_tmpl, outputs, inputs, clobbers, 1, input_location);
3158 #else
3159 tree t = d_build_asm_stmt(insn_tmpl, outputs, inputs, clobbers);
3160 ASM_VOLATILE_P( t ) = 1;
3161 addExp( t );
3162 #endif
3165 WrappedExp::WrappedExp(Loc loc, enum TOK op, tree exp_node, Type * type)
3166 : Expression(loc, op, sizeof(WrappedExp))
3168 this->exp_node = exp_node;
3169 this->type = type;
3172 void
3173 WrappedExp::toCBuffer(OutBuffer *buf)
3175 buf->printf("< wrapped exprission >");
3178 elem *
3179 WrappedExp::toElem(IRState *)
3181 return exp_node;
3185 void AggLayout::doFields(Array * fields, AggregateDeclaration * agg)
3187 bool inherited = agg != this->aggDecl;
3188 tree fcontext;
3190 fcontext = agg->type->toCtype();
3191 if ( POINTER_TYPE_P( fcontext ))
3192 fcontext = TREE_TYPE(fcontext);
3194 // tree new_field_chain = NULL_TREE;
3195 for (unsigned i = 0; i < fields->dim; i++) {
3196 // %% D anonymous unions just put the fields into the outer struct...
3197 // does this cause problems?
3199 VarDeclaration * var_decl = (VarDeclaration *) fields->data[i];
3201 assert( var_decl->storage_class & STCfield );
3203 tree ident = var_decl->ident ? get_identifier(var_decl->ident->string) : NULL_TREE;
3204 tree field_decl = build_decl(FIELD_DECL, ident,
3205 gen.trueDeclarationType( var_decl ));
3206 g.ofile->setDeclLoc( field_decl, var_decl );
3207 var_decl->csym = new Symbol;
3208 var_decl->csym->Stree = field_decl;
3210 DECL_CONTEXT( field_decl ) = aggType;
3211 DECL_FCONTEXT( field_decl ) = fcontext;
3212 DECL_FIELD_OFFSET (field_decl) = size_int( var_decl->offset );
3213 DECL_FIELD_BIT_OFFSET (field_decl) = bitsize_zero_node;
3215 DECL_ARTIFICIAL( field_decl ) =
3216 DECL_IGNORED_P( field_decl ) = inherited;
3219 // GCC 4.0 requires DECL_OFFSET_ALIGN to be set
3220 // %% .. using TYPE_ALIGN may not be same as DMD..
3221 SET_DECL_OFFSET_ALIGN( field_decl,
3222 TYPE_ALIGN( TREE_TYPE( field_decl )));
3224 //SET_DECL_OFFSET_ALIGN (field_decl, BIGGEST_ALIGNMENT); // ?
3225 layout_decl( field_decl, 0 );
3227 // get_inner_reference doesn't check these, leaves a variable unitialized
3228 // DECL_SIZE is NULL if size is zero.
3229 if (var_decl->size(var_decl->loc)) {
3230 assert(DECL_MODE(field_decl) != VOIDmode);
3231 assert(DECL_SIZE(field_decl) != NULL_TREE);
3233 fieldList.chain( field_decl );
3237 void AggLayout::doInterfaces(Array * bases, AggregateDeclaration * /*agg*/)
3239 //tree fcontext = TREE_TYPE( agg->type->toCtype() );
3240 for (unsigned i = 0; i < bases->dim; i++) {
3241 BaseClass * bc = (BaseClass *) bases->data[i];
3242 tree decl = build_decl(FIELD_DECL, NULL_TREE,
3243 Type::tvoid->pointerTo()->pointerTo()->toCtype() /* %% better */ );
3244 //DECL_VIRTUAL_P( decl ) = 1; %% nobody cares, boo hoo
3245 DECL_ARTIFICIAL( decl ) =
3246 DECL_IGNORED_P( decl ) = 1;
3247 // DECL_FCONTEXT( decl ) = fcontext; // shouldn't be needed since it's ignored
3248 addField(decl, bc->offset);
3252 void AggLayout::addField(tree field_decl, target_size_t offset)
3254 DECL_CONTEXT( field_decl ) = aggType;
3255 // DECL_FCONTEXT( field_decl ) = aggType; // caller needs to set this
3256 DECL_FIELD_OFFSET (field_decl) = size_int( offset );
3257 DECL_FIELD_BIT_OFFSET (field_decl) = bitsize_int( 0 );
3258 Loc l(aggDecl->getModule(), 1); // Must set this or we crash with DWARF debugging
3259 // gen.setDeclLoc( field_decl, aggDecl->loc ); // aggDecl->loc isn't set
3260 g.ofile->setDeclLoc(field_decl, l);
3262 layout_decl( field_decl, 0 );
3263 fieldList.chain( field_decl );
3266 void AggLayout::finish(Expressions * attrs)
3268 unsigned size_to_use = aggDecl->structsize;
3269 unsigned align_to_use = aggDecl->alignsize;
3271 /* probably doesn't do anything */
3273 if (aggDecl->structsize == 0 && aggDecl->isInterfaceDeclaration())
3274 size_to_use = Type::tvoid->pointerTo()->size();
3277 TYPE_SIZE( aggType ) = bitsize_int( size_to_use * BITS_PER_UNIT );
3278 TYPE_SIZE_UNIT( aggType ) = size_int( size_to_use );
3279 TYPE_ALIGN( aggType ) = align_to_use * BITS_PER_UNIT;
3280 // TYPE_ALIGN_UNIT is not an lvalue
3281 TYPE_PACKED (aggType ) = TYPE_PACKED (aggType ); // %% todo
3283 if (attrs)
3284 decl_attributes(& aggType, gen.attributes(attrs),
3285 ATTR_FLAG_TYPE_IN_PLACE);
3287 compute_record_mode ( aggType );
3288 // %% stor-layout.c:finalize_type_size ... it's private to that file
3290 // c-decl.c -- set up variants ? %%
3291 for (tree x = TYPE_MAIN_VARIANT( aggType ); x; x = TYPE_NEXT_VARIANT( x )) {
3292 TYPE_FIELDS (x) = TYPE_FIELDS (aggType);
3293 TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (aggType);
3294 TYPE_ALIGN (x) = TYPE_ALIGN (aggType);
3295 TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (aggType);
3299 ArrayScope::ArrayScope(IRState * ini_irs, VarDeclaration * ini_v, const Loc & loc) :
3300 v(ini_v), irs(ini_irs)
3302 if (v) {
3303 /* Need to set the location or the expand_decl in the BIND_EXPR will
3304 cause the line numbering for the statement to be incorrect. */
3305 /* The variable itself is not included in the debugging information. */
3306 v->loc = loc;
3307 Symbol * s = v->toSymbol();
3308 tree decl = s->Stree;
3309 DECL_CONTEXT( decl ) = irs->getLocalContext();
3313 tree
3314 ArrayScope::setArrayExp(tree e, Type * t)
3316 /* If STCconst, the value will be assigned in d-decls.cc
3317 of the runtime length of the array expression. */
3318 if (v && ! (v->storage_class & STCconst))
3320 if (t->toBasetype()->ty != Tsarray) // %%
3321 e = irs->maybeMakeTemp(e);
3322 DECL_INITIAL(v->toSymbol()->Stree) = irs->arrayLength(e, t);
3324 return e;
3327 tree
3328 ArrayScope::finish(tree e)
3330 if (v)
3332 Symbol * s = v->toSymbol();
3333 tree t = s->Stree;
3334 if (TREE_CODE(t) == VAR_DECL)
3336 #if V2
3337 if (s->SclosureField)
3338 return irs->compound( irs->vmodify(irs->var(v),
3339 DECL_INITIAL(t) ), e);
3340 else
3341 #endif
3342 return gen.binding(v->toSymbol()->Stree, e);
3346 return e;
3349 void
3350 FieldVisitor::visit(AggregateDeclaration * decl)
3352 ClassDeclaration * class_decl = decl->isClassDeclaration();
3354 if (class_decl && class_decl->baseClass)
3355 FieldVisitor::visit(class_decl->baseClass);
3357 doFields(& decl->fields, decl);
3359 if (class_decl && class_decl->vtblInterfaces)
3360 doInterfaces(class_decl->vtblInterfaces, decl);