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"
21 #include "d-codegen.h"
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
;
40 d_gcc_force_templates()
42 return IRState::emitTemplates
== TEprivate
||
43 IRState::emitTemplates
== TEall
;
47 IRState::emitLocalVar(VarDeclaration
* v
, bool no_init
)
49 if (v
->isDataseg() || (v
->storage_class
& STCfield
))
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
)
59 DECL_CONTEXT( var_decl
) = getLocalContext();
63 if (sym
->SclosureField
)
71 expand_decl(var_decl
);
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);
90 g
.ofile
->doLineNote(v
->loc
);
93 init_val
= DECL_INITIAL(var_decl
);
97 && ! sym
->SclosureField
101 // not sure if there is any advantage to doing this...
102 DECL_INITIAL(var_decl
) = init_val
;
103 expand_decl_init(var_decl
);
107 if (! init_exp
&& init_val
)
108 init_exp
= vmodify(var_exp
, init_val
);
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)");
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;
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;
138 needs_expr_var(tree exp
)
140 switch (TREE_CODE(exp
)) {
149 return needs_expr_var(TREE_OPERAND(exp
,0));
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
;
163 *out_var
= NULL_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
))
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
188 } else if ( d_sym
->isModule() ) {
189 return d_sym
->toSymbol()->ScontextDecl
;
196 IRState::expandDecl(tree t_decl
)
200 if (DECL_INITIAL(t_decl
))
201 expand_decl_init(t_decl
);
203 // nothing, pushdecl will add t_decl to a BIND_EXPR
204 if (DECL_INITIAL(t_decl
)) {
206 doExp(build2(MODIFY_EXPR
, void_type_node
, t_decl
, DECL_INITIAL(t_decl
)));
207 DECL_INITIAL(t_decl
) = NULL_TREE
;
214 IRState::var(VarDeclaration
* v
)
216 bool is_closure_var
= v
->toSymbol()->SclosureField
!= NULL
;
220 Dsymbol * vp = v->toParent2();
223 FuncDeclaration * f = vp->isFuncDeclaration();
225 if (f && getFrameInfo(f)->creates_closure)
227 for (unsigned i = 0; i < f->closureVars.dim; ++i)
228 if (v == f->closureVars.data[i])
234 gcc_assert(is_closure_var == test2);
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
);
248 // Static var or auto var that the back end will handle for us
249 return v
->toSymbol()->Stree
;
255 IRState::convertTo(Expression
* exp
, Type
* target_type
)
257 return convertTo(exp
->toElem( this ), exp
->type
, target_type
);
261 IRState::convertTo(tree exp
, Type
* exp_type
, Type
* target_type
)
264 target_type
= target_type
->toBasetype();
267 exp_type
= exp_type
->toBasetype();
269 if (typesSame(exp_type
, target_type
))
272 switch (exp_type
->ty
) {
274 // %%TODO:NOP/VIEW_CONVERT
275 if (target_type
->ty
== Tdelegate
) {
276 exp
= maybeMakeTemp(exp
);
277 return delegateVal( delegateMethodRef(exp
), delegateObjectRef(exp
),
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
);
284 ::error("can't convert a delegate expression to %s", target_type
->toChars());
285 return error_mark_node
;
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
) {
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
)),
308 // d_convert will make a NOP cast
311 } else if ( target_class_decl
== obj_class_decl
) {
312 // d_convert will make a NOP cast
314 } else if ( ! obj_class_decl
->isCOMclass() ) {
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
);
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
);
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 ?
350 gcc_assert(a_type
->next
->isbit() == target_type
->next
->isbit());
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());
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
));
385 if (dst_elem_type
->isbit())
389 // assumes Type::tbit->size() == 1
390 integerConstant(sz_b
, Type::tsize_t
),
391 integerConstant(sz_a
* mult
,
395 return libCall(LIBCALL_ARRAYCAST
, 3, args
, target_type
->toCtype());
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
405 if (target_type
->ty
== Taarray
)
406 return build1(NOP_EXPR
, target_type
->toCtype(), exp
);
407 // else, default conversion, which should product an error
410 /* For some reason, convert_to_integer converts pointers
412 if (target_type
->isintegral())
413 exp
= d_convert_basic(d_type_for_size(POINTER_SIZE
, 1), exp
);
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
);
424 } else if (exp_type
->iscomplex()) {
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;
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;
446 result
= imagPart(exp
);
448 // default conversion
451 result
= convertTo(result
, part_type
, target_type
);
452 } else if (target_type
->iscomplex()) {
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()) {
459 } else if (exp_type
->isimaginary()) {
464 // default conversion
467 result
= build(COMPLEX_EXPR
, target_type
->toCtype(), c1
, c2
);
469 assert( TREE_CODE( exp
) != STRING_CST
);
470 // default conversion
475 result
= d_convert_basic(target_type
->toCtype(), exp
);
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
);
491 // Lazy arguments: exp should already be a delegate
493 Type * et = exp->type->toBasetype();
494 Type * at = arg->type->toBasetype();
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)
503 g.ofile->setLoc(exp->loc);
504 ::warning("ackthpbpt: must convert %s to %s\n",
505 exp->type->toChars(), arg->type->toChars());
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
519 final_sa_elem_type(Type
* type
)
521 while (type
->ty
== Tsarray
) {
522 type
= type
->nextOf()->toBasetype();
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();
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;
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) {
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;
566 // %%TODO: Use a code (lang_specific in decl or flag) to memset instead?
572 tree exp_tree
= exp
->toElem(this);
573 return convertForAssignment(exp_tree
, exp
->type
, target_type
);
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
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?
593 IRState::convertForCondition(tree exp_tree
, Type
* exp_type
) {
594 tree result
= exp_tree
;
597 switch (exp_type
->toBasetype()->ty
) {
599 // Shouldn't this be...
600 // result = libCall(LIBCALL_AALEN, 1, & exp_tree);
602 result
= component(exp_tree
, TYPE_FIELDS(TREE_TYPE(exp_tree
)));
605 // DMD checks (length || ptr) (i.e ary !is null)
606 tmp
= maybeMakeTemp(result
);
607 a
= delegateObjectRef(tmp
);
608 b
= delegateMethodRef(tmp
);
609 if (TYPE_MODE(TREE_TYPE(a
)) == TYPE_MODE(TREE_TYPE(b
)))
610 result
= build(BIT_IOR_EXPR
, TREE_TYPE(a
), a
, b
);
612 a
= d_truthvalue_conversion(a
);
613 b
= d_truthvalue_conversion(b
);
614 // probably not worth TRUTH_OROR ...
615 result
= build(TRUTH_OR_EXPR
, TREE_TYPE(a
), a
, b
);
619 // DMD checks (function || object), but what good
620 // is if if there is a null function pointer?
621 if ( D_IS_METHOD_CALL_EXPR(result
) ) {
622 extractMethodCallExpr(result
, a
, b
);
624 tmp
= maybeMakeTemp(result
);
625 a
= delegateObjectRef(tmp
);
626 b
= delegateMethodRef(tmp
);
628 // not worth using or TRUTH_ORIF...
629 // %%TODO: Is this okay for all targets?
630 result
= build(BIT_IOR_EXPR
, TREE_TYPE(a
), a
, b
);
635 // see expr.c:do_jump for the types of trees that can be passed to expand_start_cond
636 //TREE_USED( <result> ) = 1; // %% maybe not.. expr optimized away because constant expression?
637 return d_truthvalue_conversion( result
);
640 /* Convert EXP to a dynamic array. EXP must be a static array or
643 IRState::toDArray(Expression
* exp
)
645 TY ty
= exp
->type
->toBasetype()->ty
;
648 val
= convertTo(exp
, exp
->type
->toBasetype()->nextOf()->arrayOf());
649 } else if (ty
== Tarray
) {
650 val
= exp
->toElem(this);
652 gcc_assert(ty
== Tsarray
|| ty
== Tarray
);
660 IRState::pointerIntSum(tree ptr_node
, tree idx_exp
)
662 tree result_type_node
= TREE_TYPE( ptr_node
);
663 tree intop
= idx_exp
;
666 // %% TODO: real-not-long-double issues...
668 // %% test for void case ...
669 size_exp
= size_in_bytes( TREE_TYPE( result_type_node
) ); // array element size
670 if (integer_zerop(size_exp
))
671 size_exp
= integer_one_node
;
673 if (TYPE_PRECISION (TREE_TYPE (intop
)) != TYPE_PRECISION (sizetype
)
674 || TREE_UNSIGNED (TREE_TYPE (intop
)) != TREE_UNSIGNED (sizetype
))
675 intop
= convert (d_type_for_size (TYPE_PRECISION (sizetype
),
676 TREE_UNSIGNED (sizetype
)), intop
);
678 intop
= convert (result_type_node
,
679 build
/*_binary_op*/ (MULT_EXPR
, TREE_TYPE(size_exp
), intop
, // the type here may be wrong %%
680 convert (TREE_TYPE (intop
), size_exp
)));
683 if ( integer_zerop(intop
) )
686 return build(PLUS_EXPR
, result_type_node
, ptr_node
, intop
);
689 // Doesn't do some of the omptimizations in ::makeArrayElemRef
691 IRState::checkedIndex(Loc loc
, tree index
, tree upper_bound
, bool inclusive
)
693 if (global
.params
.useArrayBounds
) {
694 return build(COND_EXPR
, TREE_TYPE(index
),
695 boundsCond(index
, upper_bound
, inclusive
),
697 assertCall(loc
, LIBCALL_ARRAY_BOUNDS
));
704 // index must be wrapped in a SAVE_EXPR to prevent multiple evaluation...
706 IRState::boundsCond(tree index
, tree upper_bound
, bool inclusive
)
710 bound_check
= build(inclusive
? LE_EXPR
: LT_EXPR
, boolean_type_node
,
711 convert( d_unsigned_type(TREE_TYPE(index
)), index
),
714 if (! TREE_UNSIGNED( TREE_TYPE( index
))) {
715 bound_check
= build(TRUTH_ANDIF_EXPR
, boolean_type_node
, bound_check
,
717 build(GE_EXPR
, boolean_type_node
, index
, integer_zero_node
));
724 IRState::assertCall(Loc loc
, LibCall libcall
)
726 tree args
[2] = { darrayString(loc
.filename
? loc
.filename
: ""),
727 integerConstant(loc
.linnum
, Type::tuns32
) };
728 return libCall(libcall
, 2, args
);
732 IRState::assertCall(Loc loc
, Expression
* msg
)
734 tree args
[3] = { msg
->toElem(this),
735 darrayString(loc
.filename
? loc
.filename
: ""),
736 integerConstant(loc
.linnum
, Type::tuns32
) };
737 return libCall(LIBCALL_ASSERT_MSG
, 3, args
);
741 IRState::floatConstant(const real_t
& value
, TypeBasic
* target_type
)
743 REAL_VALUE_TYPE converted_val
;
745 tree type_node
= target_type
->toCtype();
746 real_convert(& converted_val
, TYPE_MODE(type_node
), & value
.rv());
748 return build_real(type_node
, converted_val
);
752 IRState::hwi2toli(HOST_WIDE_INT low
, HOST_WIDE_INT high
)
755 if (sizeof(HOST_WIDE_INT
) < sizeof(xdmd_integer_t
))
757 gcc_assert(sizeof(HOST_WIDE_INT
) * 2 == sizeof(xdmd_integer_t
));
758 result
= (unsigned HOST_WIDE_INT
) low
;
759 result
+= ((uinteger_t
) (unsigned HOST_WIDE_INT
) high
) << HOST_BITS_PER_WIDE_INT
;
769 IRState::binding(tree var_chain
, tree body
)
771 // BIND_EXPR/DECL_INITIAL not supported in 4.0?
772 gcc_assert(TREE_CHAIN(var_chain
) == NULL_TREE
); // TODO: only handles one var
774 if ( DECL_INITIAL(var_chain
) )
776 tree ini
= build2(MODIFY_EXPR
, void_type_node
, var_chain
, DECL_INITIAL(var_chain
));
777 DECL_INITIAL(var_chain
) = NULL_TREE
;
778 body
= compound(ini
, body
);
781 return build3(BIND_EXPR
, TREE_TYPE(body
), var_chain
, body
, NULL_TREE
);
786 IRState::libCall(LibCall lib_call
, unsigned n_args
, tree
*args
, tree force_result_type
)
789 tree callee
= functionPointer( getLibCallDecl( lib_call
));
790 // for force_result_type, assumes caller knows what it is doing %%
791 tree result_type
= force_result_type
!= NULL_TREE
?
792 force_result_type
: TREE_TYPE(TREE_TYPE(TREE_OPERAND(callee
, 0)));
793 tree arg_list
= NULL_TREE
;
794 for (int i
= n_args
- 1; i
>= 0; i
--) {
795 arg_list
= tree_cons(NULL_TREE
, args
[i
], arg_list
);
798 result
= buildCall(result_type
, callee
, arg_list
);
803 function_type_p(tree t
)
805 return TREE_CODE(t
) == FUNCTION_TYPE
|| TREE_CODE(t
) == METHOD_TYPE
;
808 // Assumes T is already ->toBasetype()
809 static TypeFunction
*
810 get_function_type(Type
* t
)
812 TypeFunction
* tf
= NULL
;
813 if (t
->ty
== Tpointer
)
814 t
= t
->nextOf()->toBasetype();
815 if (t
->ty
== Tfunction
)
816 tf
= (TypeFunction
*) t
;
817 else if (t
->ty
== Tdelegate
)
818 tf
= (TypeFunction
*) ((TypeDelegate
*) t
)->next
;
822 tree
IRState::errorMark(Type
* t
)
824 return nop(error_mark_node
, t
->toCtype());
828 IRState::call(Expression
* expr
, /*TypeFunction * func_type, */ Array
* arguments
)
830 // Calls to delegates can sometimes look like this:
831 if (expr
->op
== TOKcomma
)
833 CommaExp
* ce
= (CommaExp
*) expr
;
837 gcc_assert( ce
->e2
->op
== TOKvar
);
838 ve
= (VarExp
*) ce
->e2
;
839 gcc_assert(ve
->var
->isFuncDeclaration() && ! ve
->var
->needThis());
842 Type
* t
= expr
->type
->toBasetype();
843 TypeFunction
* tf
= NULL
;
844 tree callee
= expr
->toElem(this);
845 tree object
= NULL_TREE
;
847 if ( D_IS_METHOD_CALL_EXPR( callee
) ) {
848 /* This could be a delegate expression (TY == Tdelegate), but not
849 actually a delegate variable. */
850 tf
= get_function_type(t
);
851 extractMethodCallExpr(callee
, callee
, object
);
852 } else if ( t
->ty
== Tdelegate
) {
853 tf
= (TypeFunction
*) ((TypeDelegate
*) t
)->next
;
854 callee
= maybeMakeTemp(callee
);
855 object
= delegateObjectRef(callee
);
856 callee
= delegateMethodRef(callee
);
857 } else if (expr
->op
== TOKvar
) {
858 FuncDeclaration
* fd
= ((VarExp
*) expr
)->var
->isFuncDeclaration();
859 tf
= (TypeFunction
*) fd
->type
;
861 if (fd
->isNested()) {
863 object
= getFrameForFunction(fd
);
865 // Pass fake argument for nested functions
866 object
= d_null_pointer
;
868 } else if (fd
->needThis()) {
869 expr
->error("need 'this' to access member %s", fd
->toChars());
870 object
= d_null_pointer
; // continue processing...
874 tf
= get_function_type(t
);
876 return call(tf
, callee
, object
, arguments
);
880 IRState::call(FuncDeclaration
* func_decl
, Array
* args
)
882 assert(! func_decl
->isNested()); // Otherwise need to copy code from above
883 return call((TypeFunction
*) func_decl
->type
, func_decl
->toSymbol()->Stree
, NULL_TREE
, args
);
887 IRState::call(FuncDeclaration
* func_decl
, tree object
, Array
* args
)
889 return call((TypeFunction
*)func_decl
->type
, functionPointer(func_decl
),
894 IRState::call(TypeFunction
*func_type
, tree callable
, tree object
, Array
* arguments
)
896 // Using TREE_TYPE( callable ) instead of func_type->toCtype can save a build_method_type
897 tree func_type_node
= TREE_TYPE( callable
);
898 tree actual_callee
= callable
;
900 if ( POINTER_TYPE_P( func_type_node
) )
901 func_type_node
= TREE_TYPE( func_type_node
);
903 actual_callee
= addressOf( callable
);
905 assert( function_type_p( func_type_node
) );
906 assert( func_type
!= NULL
);
907 assert( func_type
->ty
== Tfunction
);
909 bool is_d_vararg
= func_type
->varargs
== 1 && func_type
->linkage
== LINKd
;
911 // Account for the hidden object/frame pointer argument
913 if ( TREE_CODE( func_type_node
) == FUNCTION_TYPE
) {
914 if ( object
!= NULL_TREE
) {
915 // Happens when a delegate value is called
916 tree method_type
= build_method_type( TREE_TYPE( object
), func_type_node
);
917 TYPE_ATTRIBUTES( method_type
) = TYPE_ATTRIBUTES( func_type_node
);
918 func_type_node
= method_type
;
920 } else /* METHOD_TYPE */ {
922 // Front-end apparently doesn't check this.
923 if (TREE_CODE(callable
) == FUNCTION_DECL
) {
924 error("need 'this' to access member %s", IDENTIFIER_POINTER( DECL_NAME( callable
)));
925 return error_mark_node
;
927 // Probably an internal error
928 assert(object
!= NULL_TREE
);
933 ListMaker actual_arg_list
;
935 /* If this is a delegate call or a nested function being called as
936 a delegate, the object should not be NULL. */
937 if (object
!= NULL_TREE
)
938 actual_arg_list
.cons( object
);
940 Arguments
* formal_args
= func_type
->parameters
; // can be NULL for genCfunc decls
941 size_t n_formal_args
= formal_args
? (int) Argument::dim(formal_args
) : 0;
942 size_t n_actual_args
= arguments
? arguments
->dim
: 0;
945 // assumes arguments->dim <= formal_args->dim if (! this->varargs)
946 for (size_t ai
= 0; ai
< n_actual_args
; ++ai
) {
947 tree actual_arg_tree
;
949 Expression
* actual_arg_exp
= (Expression
*) arguments
->data
[ai
];
950 if (ai
== 0 && is_d_vararg
) {
951 // The hidden _arguments parameter
952 actual_arg_tree
= actual_arg_exp
->toElem(this);
953 } else if (fi
< n_formal_args
) {
954 // Actual arguments for declared formal arguments
955 Argument
* formal_arg
= Argument::getNth(formal_args
, fi
);
957 actual_arg_tree
= convertForArgument(actual_arg_exp
, formal_arg
);
959 // from c-typeck.c: convert_arguments, default_conversion, ...
960 if (INTEGRAL_TYPE_P (TREE_TYPE(actual_arg_tree
))
961 && (TYPE_PRECISION (TREE_TYPE(actual_arg_tree
)) <
962 TYPE_PRECISION (integer_type_node
))) {
964 actual_arg_tree
= d_convert_basic(integer_type_node
, actual_arg_tree
);
968 if (splitDynArrayVarArgs
&& actual_arg_exp
->type
->toBasetype()->ty
== Tarray
)
970 tree da_exp
= maybeMakeTemp( actual_arg_exp
->toElem(this) );
971 actual_arg_list
.cons( darrayLenRef( da_exp
) );
972 actual_arg_list
.cons( darrayPtrRef( da_exp
) );
977 actual_arg_tree
= actual_arg_exp
->toElem( this );
979 /* Not all targets support passing unpromoted types, so
981 tree prom_type
= d_type_promotes_to( TREE_TYPE( actual_arg_tree
));
982 if (prom_type
!= TREE_TYPE( actual_arg_tree
))
983 actual_arg_tree
= d_convert_basic(prom_type
, actual_arg_tree
);
987 //TREE_USED( actual_arg_tree ) = 1; // needed ?
988 actual_arg_list
.cons( actual_arg_tree
);
991 tree result
= buildCall(TREE_TYPE(func_type_node
), actual_callee
, actual_arg_list
.head
);
992 return maybeExpandSpecialCall(result
);
995 static const char * libcall_ids
[LIBCALL_count
] =
996 { "_d_assert", "_d_assert_msg", "_d_array_bounds", "_d_switch_error",
997 "_D9invariant12_d_invariantFC6ObjectZv",
998 "_d_newclass", "_d_newarrayT",
1000 "_d_newarraymTp", "_d_newarraymiTp", "_d_allocmemory",
1001 "_d_delclass", "_d_delinterface", "_d_delarray",
1002 "_d_delmemory", "_d_callfinalizer", "_d_callinterfacefinalizer",
1003 "_d_arraysetlengthT", "_d_arraysetlengthiT",
1004 "_d_dynamic_cast", "_d_interface_cast",
1005 "_adEq", "_adCmp", "_adCmpChar",
1007 //"_aaIn", "_aaGet", "_aaGetRvalue", "_aaDel",
1008 "_aaInp", "_aaGetp", "_aaGetRvaluep", "_aaDelp",
1011 "_d_arraycatT", "_d_arraycatnT",
1013 /*"_d_arrayappendc", */"_d_arrayappendcTp",
1015 "_d_arrayassign", "_d_arrayctor", "_d_arraysetassign",
1018 "_d_monitorenter", "_d_monitorexit",
1019 "_d_criticalenter", "_d_criticalexit",
1021 "_d_switch_string", "_d_switch_ustring", "_d_switch_dstring",
1022 "_d_assocarrayliteralTp"
1029 static FuncDeclaration
* libcall_decls
[LIBCALL_count
];
1032 IRState::replaceLibCallDecl(FuncDeclaration
* d_decl
)
1034 if ( ! d_decl
->ident
)
1036 for (unsigned i
= 0; i
< LIBCALL_count
; i
++) {
1037 if ( strcmp(d_decl
->ident
->string
, libcall_ids
[i
]) == 0 ) {
1038 // %% warn if libcall already set?
1039 // Only do this for the libcalls where it's a problem, otherwise
1040 // it causes other problems...
1041 switch ((LibCall
) i
) {
1042 // case LIBCALL_GNU_BITARRAYSLICEP:
1043 case LIBCALL_ARRAYCOPY
: // this could be solved by turning copy of char into memcpy
1044 case LIBCALL_ARRAYCAST
:
1045 // replace the function declaration
1051 libcall_decls
[i
] = d_decl
;
1059 IRState::getLibCallDecl(LibCall lib_call
)
1061 FuncDeclaration
* decl
= libcall_decls
[lib_call
];
1064 bool varargs
= false;
1067 Type
* return_type
= Type::tvoid
;
1070 case LIBCALL_ASSERT
:
1071 case LIBCALL_ARRAY_BOUNDS
:
1072 case LIBCALL_SWITCH_ERROR
:
1073 // need to spec chararray/string because internal code passes string constants
1074 arg_types
.reserve(2);
1075 arg_types
.push( Type::tchar
->arrayOf() );
1076 arg_types
.push( Type::tuns32
);
1078 case LIBCALL_ASSERT_MSG
:
1079 arg_types
.reserve(3);
1080 arg_types
.push( Type::tchar
->arrayOf() );
1081 arg_types
.push( Type::tchar
->arrayOf() );
1082 arg_types
.push( Type::tuns32
);
1084 case LIBCALL_NEWCLASS
:
1085 arg_types
.push( ClassDeclaration::classinfo
->type
);
1086 return_type
= getObjectType();
1088 case LIBCALL_NEWARRAYT
:
1089 case LIBCALL_NEWARRAYIT
:
1090 arg_types
.push( Type::typeinfo
->type
);
1091 arg_types
.push( Type::tsize_t
);
1092 return_type
= Type::tvoid
->arrayOf();
1094 case LIBCALL_NEWARRAYMTP
:
1095 case LIBCALL_NEWARRAYMITP
:
1096 arg_types
.push( Type::tsize_t
);
1097 arg_types
.push( Type::tint32
); // Currently 'int', even if 64-bit
1098 arg_types
.push( Type::typeinfo
->type
);
1099 if (lib_call
== LIBCALL_NEWARRAYMITP
)
1100 arg_types
.push( Type::tsize_t
);
1102 case LIBCALL_ALLOCMEMORY
:
1103 arg_types
.push( Type::tsize_t
);
1104 return_type
= Type::tvoidptr
;
1106 case LIBCALL_DELCLASS
:
1107 case LIBCALL_DELINTERFACE
:
1108 arg_types
.push(Type::tvoid
->pointerTo());
1110 case LIBCALL_DELARRAY
:
1111 arg_types
.push(Type::tvoid
->arrayOf()->pointerTo());
1113 case LIBCALL_DELMEMORY
:
1114 arg_types
.push(Type::tvoid
->pointerTo()->pointerTo());
1116 case LIBCALL_CALLFINALIZER
:
1117 case LIBCALL_CALLINTERFACEFINALIZER
:
1118 arg_types
.push(Type::tvoid
->pointerTo());
1120 case LIBCALL_ARRAYSETLENGTHT
:
1121 case LIBCALL_ARRAYSETLENGTHIT
:
1122 arg_types
.push( Type::typeinfo
->type
);
1123 arg_types
.push( Type::tsize_t
);
1124 arg_types
.push( Type::tvoid
->arrayOf()->pointerTo() );
1125 return_type
= Type::tvoid
->arrayOf();
1127 case LIBCALL_DYNAMIC_CAST
:
1128 case LIBCALL_INTERFACE_CAST
:
1129 arg_types
.push( getObjectType() );
1130 arg_types
.push( ClassDeclaration::classinfo
->type
);
1131 return_type
= getObjectType();
1135 arg_types
.reserve(3);
1136 arg_types
.push(Type::tvoid
->arrayOf());
1137 arg_types
.push(Type::tvoid
->arrayOf());
1138 arg_types
.push(Type::typeinfo
->type
);
1139 return_type
= Type::tint32
;
1141 case LIBCALL_ADCMPCHAR
:
1142 arg_types
.reserve(2);
1143 arg_types
.push(Type::tchar
->arrayOf());
1144 arg_types
.push(Type::tchar
->arrayOf());
1145 return_type
= Type::tint32
;
1147 // case LIBCALL_AAIN:
1148 // case LIBCALL_AAGET:
1149 // case LIBCALL_AAGETRVALUE:
1150 // case LIBCALL_AADEL:
1153 case LIBCALL_AAGETP
:
1154 case LIBCALL_AAGETRVALUEP
:
1155 case LIBCALL_AADELP
:
1157 static Type
* aa_type
= NULL
;
1159 aa_type
= new TypeAArray(Type::tvoid
->pointerTo(),
1160 Type::tvoid
->pointerTo());
1162 if (lib_call
== LIBCALL_AALEN
)
1164 arg_types
.push(aa_type
);
1165 return_type
= Type::tsize_t
;
1169 if (lib_call
== LIBCALL_AAGETP
)
1170 aa_type
= aa_type
->pointerTo();
1172 arg_types
.reserve(3);
1173 arg_types
.push(aa_type
);
1174 arg_types
.push(Type::typeinfo
->type
); // typeinfo reference
1175 if ( lib_call
== LIBCALL_AAGETP
|| lib_call
== LIBCALL_AAGETRVALUEP
)
1176 arg_types
.push(Type::tsize_t
);
1178 arg_types
.push(Type::tvoid
->pointerTo());
1182 case LIBCALL_AAGETP
:
1183 case LIBCALL_AAGETRVALUEP
:
1184 return_type
= Type::tvoid
->pointerTo();
1186 case LIBCALL_AADELP
:
1187 return_type
= Type::tvoid
;
1194 case LIBCALL_ARRAYCAST
:
1195 t
= Type::tvoid
->arrayOf();
1196 arg_types
.push(Type::tsize_t
);
1197 arg_types
.push(Type::tsize_t
);
1201 case LIBCALL_ARRAYCOPY
:
1202 t
= Type::tvoid
->arrayOf();
1203 arg_types
.push(Type::tsize_t
);
1208 case LIBCALL_ARRAYCATT
:
1209 arg_types
.push(Type::typeinfo
->type
);
1210 t
= Type::tvoid
->arrayOf();
1215 case LIBCALL_ARRAYCATNT
:
1216 arg_types
.push(Type::typeinfo
->type
);
1217 arg_types
.push(Type::tuns32
); // Currently 'uint', even if 64-bit
1219 return_type
= Type::tvoid
->arrayOf();
1221 case LIBCALL_ARRAYAPPENDT
:
1222 arg_types
.push(Type::typeinfo
->type
);
1223 t
= Type::tuns8
->arrayOf();
1224 arg_types
.push(t
->pointerTo());
1226 return_type
= Type::tvoid
->arrayOf();
1228 // case LIBCALL_ARRAYAPPENDCT:
1229 case LIBCALL_ARRAYAPPENDCTP
:
1230 arg_types
.push(Type::typeinfo
->type
);
1231 t
= Type::tuns8
->arrayOf();
1233 arg_types
.push(Type::tvoid
->pointerTo()); // varargs = true;
1234 return_type
= Type::tvoid
->arrayOf();
1237 case LIBCALL_ARRAYASSIGN
:
1238 case LIBCALL_ARRAYCTOR
:
1239 arg_types
.push(Type::typeinfo
->type
);
1240 arg_types
.push(Type::tvoid
->arrayOf());
1241 return_type
= Type::tvoid
->arrayOf();
1243 case LIBCALL_ARRAYSETASSIGN
:
1244 case LIBCALL_ARRAYSETCTOR
:
1245 arg_types
.push(Type::tvoid
->pointerTo());
1246 arg_types
.push(Type::tvoid
->pointerTo());
1247 arg_types
.push(Type::tsize_t
);
1248 arg_types
.push(Type::typeinfo
->type
);
1249 return_type
= Type::tvoid
->pointerTo();
1252 case LIBCALL_MONITORENTER
:
1253 case LIBCALL_MONITOREXIT
:
1255 case LIBCALL_INVARIANT
:
1256 arg_types
.push(getObjectType());
1258 case LIBCALL_CRITICALENTER
:
1259 case LIBCALL_CRITICALEXIT
:
1260 arg_types
.push(Type::tvoid
->pointerTo());
1262 case LIBCALL_SWITCH_USTRING
:
1264 goto do_switch_string
;
1265 case LIBCALL_SWITCH_DSTRING
:
1267 goto do_switch_string
;
1268 case LIBCALL_SWITCH_STRING
:
1272 arg_types
.push(t
->arrayOf());
1274 return_type
= Type::tint32
;
1276 case LIBCALL_ASSOCARRAYLITERALTP
:
1277 arg_types
.push(Type::typeinfo
->type
);
1278 arg_types
.push(Type::tsize_t
);
1279 arg_types
.push(Type::tvoid
->pointerTo());
1280 arg_types
.push(Type::tvoid
->pointerTo());
1281 return_type
= Type::tvoid
->pointerTo();
1284 case LIBCALL_HIDDEN_FUNC
:
1285 /* Argument is an Object, but can't use that as
1286 LIBCALL_HIDDEN_FUNC is needed before the Object type is
1288 arg_types
.push(Type::tvoid
->pointerTo());
1294 decl
= FuncDeclaration::genCfunc(return_type
, (char *) libcall_ids
[lib_call
]);
1296 TypeFunction
* tf
= (TypeFunction
*) decl
->type
;
1297 tf
->varargs
= varargs
? 1 : 0;
1298 Arguments
* args
= new Arguments
;
1299 args
->setDim( arg_types
.dim
);
1300 for (unsigned i
= 0; i
< arg_types
.dim
; i
++)
1301 args
->data
[i
] = new Argument( STCin
, (Type
*) arg_types
.data
[i
],
1303 tf
->parameters
= args
;
1305 libcall_decls
[lib_call
] = decl
;
1311 fix_d_va_list_type(tree val
)
1313 if (POINTER_TYPE_P(va_list_type_node
) ||
1314 INTEGRAL_TYPE_P(va_list_type_node
))
1315 return build1(NOP_EXPR
, va_list_type_node
, val
);
1320 tree
IRState::maybeExpandSpecialCall(tree call_exp
)
1322 // More code duplication from C
1324 tree callee
= TREE_OPERAND(call_exp
, 0);
1326 if (POINTER_TYPE_P(TREE_TYPE( callee
))) {
1327 callee
= TREE_OPERAND(callee
, 0);
1329 if (TREE_CODE(callee
) == FUNCTION_DECL
) {
1330 if (DECL_BUILT_IN_CLASS(callee
) == NOT_BUILT_IN
) {
1331 // the most common case
1333 } else if (DECL_BUILT_IN_CLASS(callee
) == BUILT_IN_NORMAL
) {
1334 switch (DECL_FUNCTION_CODE(callee
)) {
1337 case BUILT_IN_LLABS
:
1338 case BUILT_IN_IMAXABS
:
1339 /* The above are required for both 3.4. Not sure about later
1341 /* OLDOLDOLD below supposedly for 3.3 only */
1344 case BUILT_IN_FABSL:
1345 case BUILT_IN_FABSF:
1347 op
= TREE_VALUE( TREE_OPERAND( call_exp
, 1 ));
1348 t
= build1(ABS_EXPR
, TREE_TYPE(op
), op
);
1349 return d_convert_basic(TREE_TYPE(call_exp
), t
);
1350 // probably need a few more cases:
1354 } else if (DECL_BUILT_IN_CLASS(callee
) == BUILT_IN_FRONTEND
) {
1355 Intrinsic intrinsic
= (Intrinsic
) DECL_FUNCTION_CODE(callee
);
1358 switch (intrinsic
) {
1359 case INTRINSIC_C_VA_ARG
:
1360 // %% should_check c_promotes_to as in va_arg now
1361 // just drop though for now...
1362 case INTRINSIC_STD_VA_ARG
:
1363 t
= TREE_VALUE(TREE_OPERAND(call_exp
, 1));
1364 // signature is (inout va_list), but VA_ARG_EXPR expects the
1365 // list itself... but not if the va_list type is an array. In that
1366 // case, it should be a pointer
1367 if ( TREE_CODE( va_list_type_node
) != ARRAY_TYPE
) {
1368 if ( TREE_CODE( t
) == ADDR_EXPR
) {
1369 t
= TREE_OPERAND(t
, 0);
1371 // this probably doesn't happen... passing an inout va_list argument,
1372 // but again, it's probably { & ( * inout_arg ) }
1373 t
= build1(INDIRECT_REF
, TREE_TYPE(TREE_TYPE(t
)), t
);
1376 t
= fix_d_va_list_type(t
);
1377 type
= TREE_TYPE(TREE_TYPE(callee
));
1378 if (splitDynArrayVarArgs
&& (d_type
= getDType(type
)) &&
1379 d_type
->toBasetype()->ty
== Tarray
)
1381 // should create a temp var of type TYPE and move the binding
1382 // to outside this expression.
1383 t
= stabilize_reference(t
);
1384 tree ltype
= TREE_TYPE( TYPE_FIELDS( type
));
1385 tree ptype
= TREE_TYPE( TREE_CHAIN( TYPE_FIELDS( type
)));
1386 tree lvar
= exprVar(ltype
);
1387 tree pvar
= exprVar(ptype
);
1388 tree e1
= vmodify(lvar
, build1(VA_ARG_EXPR
, ltype
, t
));
1389 tree e2
= vmodify(pvar
, build1(VA_ARG_EXPR
, ptype
, t
));
1390 tree b
= compound( compound( e1
, e2
), darrayVal(type
, lvar
, pvar
) );
1391 return binding(lvar
, binding(pvar
, b
));
1395 tree type2
= d_type_promotes_to(type
);
1396 t
= build1(VA_ARG_EXPR
, type2
, t
);
1398 // silently convert promoted type...
1399 t
= d_convert_basic(type
, t
);
1403 case INTRINSIC_C_VA_START
:
1406 // signature is (inout va_list), but VA_ARG_EXPR expects the
1408 if ( TREE_CODE( t ) == ADDR_EXPR ) {
1409 t = TREE_OPERAND(t, 0);
1411 // this probably doesn't happen... passing an inout va_list argument,
1412 // but again, it's probably { & ( * inout_arg ) }
1413 t = build1(INDIRECT_REF, TREE_TYPE(TREE_TYPE(t)), t);
1416 // The va_list argument should already have its
1417 // address taken. The second argument, however, is
1418 // inout and that needs to be fixed to prevent a warning.
1420 tree val_arg
= TREE_VALUE(TREE_OPERAND(call_exp
, 1));
1421 // kinda wrong... could be casting.. so need to check type too?
1422 while ( TREE_CODE( val_arg
) == NOP_EXPR
)
1423 val_arg
= TREE_OPERAND(val_arg
, 0);
1424 if ( TREE_CODE( val_arg
) == ADDR_EXPR
) {
1425 val_arg
= TREE_OPERAND(val_arg
, 0);
1426 val_arg
= fix_d_va_list_type(val_arg
);
1427 val_arg
= addressOf( val_arg
);
1429 val_arg
= fix_d_va_list_type(val_arg
);
1431 t
= TREE_VALUE(TREE_CHAIN(TREE_OPERAND(call_exp
, 1)));
1432 if ( TREE_CODE( t
) == ADDR_EXPR
) {
1433 t
= TREE_OPERAND(t
, 0);
1436 return buildCall( void_type_node
, // assuming nobody tries to change the return type
1437 addressOf( built_in_decls
[BUILT_IN_VA_START
] ),
1438 tree_cons( NULL_TREE
, val_arg
,
1439 tree_cons( NULL_TREE
, t
, NULL_TREE
)));
1446 } else if (0 /** WIP **/ && DECL_BUILT_IN_CLASS(callee
) == BUILT_IN_FRONTEND
) {
1447 // %%TODO: need to handle BITS_BIG_ENDIAN
1448 // %%TODO: need to make expressions unsigned
1450 Intrinsic intrinsic
= (Intrinsic
) DECL_FUNCTION_CODE(callee
);
1451 // Might as well do intrinsics here...
1452 switch (intrinsic
) {
1453 case INTRINSIC_BSF
: // This will use bsf on x86, but BSR becomes 31-(bsf)!!
1456 // %% types should be correct, but should still check..
1461 return buildCall(TREE_TYPE(call_exp
),
1462 built_in_decls
[intrinsic
== INTRINSIC_BSF
? BUILT_IN_CTZ
: BUILT_IN_CLZ
],
1463 TREE_OPERAND(call_exp
, 1));
1472 case INTRINSIC_BSWAP
:
1473 #if defined(TARGET_386)
1478 case INTRINSIC_INPW
:
1479 case INTRINSIC_INPL
:
1480 case INTRINSIC_OUTP
:
1481 case INTRINSIC_OUTPW
:
1482 case INTRINSIC_OUTPL
:
1485 ::error("Port I/O intrinsic '%s' is only available on ix86 targets",
1486 IDENTIFIER_POINTER(DECL_NAME(callee
)));
1499 IRState::arrayElemRef(IndexExp
* aer_exp
, ArrayScope
* aryscp
)
1501 Expression
* e1
= aer_exp
->e1
;
1502 Expression
* e2
= aer_exp
->e2
;
1504 Type
* base_type
= e1
->type
->toBasetype();
1505 TY base_type_ty
= base_type
->ty
;
1508 gcc_assert(! base_type
->next
->isbit());
1511 tree index_expr
; // logical index
1512 tree subscript_expr
; // expr that indexes the array data
1513 tree ptr_exp
; // base pointer to the elements
1514 tree elem_ref
; // reference the the element
1516 index_expr
= e2
->toElem( this );
1517 subscript_expr
= index_expr
;
1519 switch (base_type_ty
) {
1523 tree e1_tree
= e1
->toElem(this);
1525 e1_tree
= aryscp
->setArrayExp(e1_tree
, e1
->type
);
1527 if ( global
.params
.useArrayBounds
&&
1528 // If it's a static array and the index is
1529 // constant, the front end has already
1530 // checked the bounds.
1531 ! (base_type_ty
== Tsarray
&& e2
->isConst()) ) {
1534 tree array_len_expr
, throw_expr
, oob_cond
;
1535 // implement bounds check as a conditional expression:
1536 // a[ inbounds(index) ? index : { throw ArrayBoundsError } ]
1538 // First, set up the index expression to only be evaluated
1540 // %% save_expr does this check: if (! TREE_CONSTANT( index_expr ))
1541 // %% so we don't do a <0 check for a[2]...
1542 index_expr
= maybeMakeTemp( index_expr
);
1544 if (base_type_ty
== Tarray
) {
1545 e1_tree
= maybeMakeTemp(e1_tree
);
1546 array_len_expr
= darrayLenRef(e1_tree
);
1548 array_len_expr
= ((TypeSArray
*) base_type
)->dim
->toElem(this);
1551 oob_cond
= boundsCond(index_expr
, array_len_expr
, false);
1552 throw_expr
= assertCall(aer_exp
->loc
, LIBCALL_ARRAY_BOUNDS
);
1554 subscript_expr
= build( COND_EXPR
, TREE_TYPE( index_expr
),
1555 oob_cond
, index_expr
, throw_expr
);
1558 // %% TODO: make this an ARRAY_REF?
1559 if (base_type_ty
== Tarray
)
1560 ptr_exp
= darrayPtrRef( e1_tree
); // %% do convert in darrayPtrRef?
1562 ptr_exp
= addressOf( e1_tree
);
1563 // This conversion is required for static arrays and is just-to-be-safe
1564 // for dynamic arrays
1565 ptr_exp
= d_convert_basic(base_type
->nextOf()->pointerTo()->toCtype(), ptr_exp
);
1570 ptr_exp
= e1
->toElem( this );
1576 ptr_exp
= pvoidOkay( ptr_exp
);
1577 subscript_expr
= aryscp
->finish( subscript_expr
);
1578 elem_ref
= indirect(pointerIntSum( ptr_exp
, subscript_expr
),
1579 TREE_TYPE(TREE_TYPE(ptr_exp
)));
1585 IRState::darrayPtrRef(tree exp
)
1587 // Get the backend type for the array and pick out the array data
1588 // pointer field (assumed to be the second field.)
1589 tree ptr_field
= TREE_CHAIN( TYPE_FIELDS( TREE_TYPE( exp
)));
1590 //return build(COMPONENT_REF, TREE_TYPE( ptr_field ), exp, ptr_field);
1591 return component(exp
, ptr_field
);
1595 IRState::darrayLenRef(tree exp
)
1597 // Get the backend type for the array and pick out the array length
1598 // field (assumed to be the first field.)
1599 tree len_field
= TYPE_FIELDS( TREE_TYPE( exp
));
1600 return component(exp
, len_field
);
1605 IRState::darrayVal(tree type
, tree len
, tree data
)
1607 // %% assert type is a darray
1608 tree ctor
= make_node( CONSTRUCTOR
);
1609 tree len_field
, ptr_field
;
1612 TREE_TYPE( ctor
) = type
;
1613 TREE_STATIC( ctor
) = 0; // can be set by caller if needed
1614 TREE_CONSTANT( ctor
) = 0; // "
1615 len_field
= TYPE_FIELDS( TREE_TYPE( ctor
));
1616 ptr_field
= TREE_CHAIN( len_field
);
1618 ce
.cons(len_field
, len
);
1619 ce
.cons(ptr_field
, data
); // shouldn't need to convert the pointer...
1620 CONSTRUCTOR_ELTS( ctor
) = ce
.head
;
1626 IRState::darrayVal(tree type
, uinteger_t len
, tree data
)
1628 // %% assert type is a darray
1629 tree ctor
= make_node( CONSTRUCTOR
);
1630 tree len_value
, ptr_value
, len_field
, ptr_field
;
1633 TREE_TYPE( ctor
) = type
;
1634 TREE_STATIC( ctor
) = 0; // can be set by caller if needed
1635 TREE_CONSTANT( ctor
) = 0; // "
1636 len_field
= TYPE_FIELDS( TREE_TYPE( ctor
));
1637 ptr_field
= TREE_CHAIN( len_field
);
1640 assert( POINTER_TYPE_P( TREE_TYPE( data
)));
1643 ptr_value
= d_null_pointer
;
1646 len_value
= integerConstant(len
, TREE_TYPE(len_field
));
1648 ce
.cons(len_field
, len_value
);
1649 ce
.cons(ptr_field
, ptr_value
); // shouldn't need to convert the pointer...
1651 CONSTRUCTOR_ELTS( ctor
) = ce
.head
;
1657 IRState::darrayString(const char * str
)
1659 unsigned len
= strlen(str
);
1660 // %% assumes str is null-terminated
1661 tree str_tree
= build_string(len
+ 1, str
);
1663 TREE_TYPE( str_tree
) = arrayType(Type::tchar
, len
);
1664 return darrayVal(Type::tchar
->arrayOf()->toCtype(), len
, addressOf(str_tree
));
1668 IRState::hostToTargetString(char * str
, size_t length
, unsigned unit_size
)
1672 assert(unit_size
== 2 || unit_size
== 4);
1676 # ifdef HOST_WORDS_BIG_ENDIAN
1677 flip
= (bool) ! BYTES_BIG_ENDIAN
;
1679 flip
= (bool) BYTES_BIG_ENDIAN
;
1682 # if WORDS_BIG_ENDIAN
1683 flip
= (bool) ! BYTES_BIG_ENDIAN
;
1685 flip
= (bool) BYTES_BIG_ENDIAN
;
1690 char * out_str
= (char *) xmalloc(length
* unit_size
);
1691 const d_uns8
* p_src
= (const d_uns8
*) str
;
1692 d_uns8
* p_out
= (d_uns8
*) out_str
;
1695 if (unit_size
== 2) {
1696 p_out
[0] = p_src
[1];
1697 p_out
[1] = p_src
[0];
1698 } else /* unit_size == 4 */ {
1699 p_out
[0] = p_src
[3];
1700 p_out
[1] = p_src
[2];
1701 p_out
[2] = p_src
[1];
1702 p_out
[3] = p_src
[0];
1715 IRState::arrayLength(tree exp
, Type
* exp_type
)
1717 Type
* base_type
= exp_type
->toBasetype();
1718 switch (base_type
->ty
) {
1720 return size_int( ((TypeSArray
*) base_type
)->dim
->toUInteger() );
1722 return darrayLenRef(exp
);
1724 ::error("can't determine the length of a %s", exp_type
->toChars());
1725 return error_mark_node
;
1730 IRState::floatMod(tree a
, tree b
, Type
* d_type
)
1732 enum built_in_function fn
;
1733 switch (d_type
->toBasetype()->ty
) {
1736 fn
= BUILT_IN_FMODF
;
1745 if (! haveLongDouble())
1746 goto no_long_double
;
1747 fn
= BUILT_IN_FMODL
;
1750 ::error("tried to perform floating-point modulo division on %s",
1752 return error_mark_node
;
1754 tree decl
= built_in_decls
[fn
];
1755 // %% assuming no arg conversion needed
1756 // %% bypassing buildCall since this shouldn't have
1758 return buildCall(TREE_TYPE(TREE_TYPE(decl
)),
1760 tree_cons(NULL_TREE
, a
,
1761 tree_cons(NULL_TREE
, b
, NULL_TREE
)));
1765 IRState::typeinfoReference(Type
* t
)
1767 tree ti_ref
= t
->getInternalTypeInfo(NULL
)->toElem(this);
1768 assert( POINTER_TYPE_P( TREE_TYPE( ti_ref
)) );
1773 IRState::getTargetSizeConst(tree t
)
1775 target_size_t result
;
1776 if (sizeof(HOST_WIDE_INT
) < sizeof(target_size_t
))
1778 gcc_assert(sizeof(HOST_WIDE_INT
) * 2 == sizeof(target_size_t
));
1779 result
= (unsigned HOST_WIDE_INT
) TREE_INT_CST_LOW( t
);
1780 result
+= ((target_size_t
) (unsigned HOST_WIDE_INT
) TREE_INT_CST_HIGH( t
))
1781 << HOST_BITS_PER_WIDE_INT
;
1784 result
= tree_low_cst( t
, 1 );
1789 // struct delegate {
1790 // void * frame_or_object;
1795 IRState::delegateObjectRef(tree exp
)
1797 // Get the backend type for the array and pick out the array data
1798 // pointer field (assumed to be the first field.)
1799 tree obj_field
= TYPE_FIELDS( TREE_TYPE( exp
));
1800 //return build(COMPONENT_REF, TREE_TYPE( obj_field ), exp, obj_field);
1801 return component(exp
, obj_field
);
1805 IRState::delegateMethodRef(tree exp
)
1807 // Get the backend type for the array and pick out the array length
1808 // field (assumed to be the second field.)
1809 tree method_field
= TREE_CHAIN( TYPE_FIELDS( TREE_TYPE( exp
)));
1810 //return build(COMPONENT_REF, TREE_TYPE( method_field ), exp, method_field);
1811 return component(exp
, method_field
);
1814 // Converts pointer types of method_exp and object_exp to match d_type
1816 IRState::delegateVal(tree method_exp
, tree object_exp
, Type
* d_type
)
1818 Type
* base_type
= d_type
->toBasetype();
1819 if ( base_type
->ty
== Tfunction
) {
1820 // Called from DotVarExp. These are just used to
1821 // make function calls and not to make Tdelegate variables.
1822 // Clearing the type makes sure of this.
1825 assert(base_type
->ty
== Tdelegate
);
1828 tree type
= base_type
? base_type
->toCtype() : NULL_TREE
;
1829 tree ctor
= make_node( CONSTRUCTOR
);
1830 tree obj_field
= NULL_TREE
;
1831 tree func_field
= NULL_TREE
;
1835 TREE_TYPE( ctor
) = type
;
1836 obj_field
= TYPE_FIELDS( type
);
1837 func_field
= TREE_CHAIN( obj_field
);
1839 ce
.cons(obj_field
, object_exp
);
1840 ce
.cons(func_field
, method_exp
);
1841 CONSTRUCTOR_ELTS( ctor
) = ce
.head
;
1847 IRState::extractMethodCallExpr(tree mcr
, tree
& callee_out
, tree
& object_out
) {
1848 assert( D_IS_METHOD_CALL_EXPR( mcr
));
1850 tree elts
= CONSTRUCTOR_ELTS( mcr
);
1851 object_out
= TREE_VALUE( elts
);
1852 callee_out
= TREE_VALUE( TREE_CHAIN( elts
));
1854 VEC(constructor_elt
,gc
) *elts
= CONSTRUCTOR_ELTS( mcr
);
1855 object_out
= VEC_index(constructor_elt
, elts
, 0)->value
;
1856 callee_out
= VEC_index(constructor_elt
, elts
, 1)->value
;
1861 IRState::objectInstanceMethod(Expression
* obj_exp
, FuncDeclaration
* func
, Type
* d_type
)
1863 Type
* obj_type
= obj_exp
->type
->toBasetype();
1864 if (func
->isThis()) {
1868 // DotTypeExp cannot be evaluated
1869 if (obj_exp
->op
== TOKdottype
) {
1871 this_expr
= ((DotTypeExp
*) obj_exp
)->e1
->toElem( this );
1872 } else if (obj_exp
->op
== TOKcast
&&
1873 ((CastExp
*) obj_exp
)->e1
->op
== TOKdottype
) {
1875 // see expression.c:"See if we need to adjust the 'this' pointer"
1876 this_expr
= ((DotTypeExp
*) ((CastExp
*) obj_exp
)->e1
)->e1
->toElem( this );
1879 this_expr
= obj_exp
->toElem( this );
1882 // Calls to super are static (func is the super's method)
1883 // Structs don't have vtables.
1884 // Final and non-virtual methods can be called directly.
1885 // DotTypeExp means non-virtual
1887 if (obj_exp
->op
== TOKsuper
||
1888 obj_type
->ty
== Tstruct
|| obj_type
->ty
== Tpointer
||
1889 func
->isFinal() || ! func
->isVirtual() || is_dottype
) {
1891 if (obj_type
->ty
== Tstruct
)
1892 this_expr
= addressOf(this_expr
);
1893 return methodCallExpr(functionPointer(func
), this_expr
, d_type
);
1895 // Interface methods are also in the class's vtable, so we don't
1896 // need to convert from a class pointer to an interface pointer.
1897 this_expr
= maybeMakeTemp( this_expr
);
1900 //#if D_GCC_VER >= 40
1901 /* Folding of *&<static var> fails because of the type of the
1902 address expression is 'Object' while the type of the static
1903 var is a particular class (why?). This prevents gimplification
1906 if (TREE_CODE(this_expr
) == ADDR_EXPR
/*&&
1907 // can't use this check
1908 TREE_TYPE(TREE_OPERAND(this_expr, 0)) ==
1909 TREE_TYPE(TREE_TYPE(this_expr))*/)
1910 vtbl_ref
= TREE_OPERAND(this_expr
, 0);
1913 vtbl_ref
= indirect(this_expr
);
1915 tree field
= TYPE_FIELDS( TREE_TYPE( vtbl_ref
)); // the vtbl is the first field
1916 //vtbl_ref = build( COMPONENT_REF, TREE_TYPE( field ), vtbl_ref, field ); // vtbl field (a pointer)
1917 vtbl_ref
= component( vtbl_ref
, field
); // vtbl field (a pointer)
1918 // %% better to do with array ref?
1919 vtbl_ref
= build( PLUS_EXPR
, TREE_TYPE(vtbl_ref
), vtbl_ref
,
1920 size_int( PTRSIZE
* func
->vtblIndex
));
1921 vtbl_ref
= indirect(vtbl_ref
, TREE_TYPE( functionPointer(func
) ));
1923 return methodCallExpr(vtbl_ref
, this_expr
, d_type
);
1926 // Static method; ignore the object instance
1927 return addressOf(func
);
1933 IRState::realPart(tree c
) {
1934 return build1(REALPART_EXPR
, TREE_TYPE(TREE_TYPE(c
)), c
);
1937 IRState::imagPart(tree c
) {
1938 return build1(IMAGPART_EXPR
, TREE_TYPE(TREE_TYPE(c
)), c
);
1942 IRState::assignValue(Expression
* e
, VarDeclaration
* v
)
1944 if (e
->op
== TOKassign
|| e
->op
== TOKconstruct
|| e
->op
== TOKblit
)
1946 AssignExp
* a_exp
= (AssignExp
*) e
;
1947 if (a_exp
->e1
->op
== TOKvar
&& ((VarExp
*) a_exp
->e1
)->var
== v
)
1948 return convertForAssignment(a_exp
->e2
, v
->type
);
1950 //return e->toElem(this);
1957 IRState::twoFieldType(tree rec_type
, tree ft1
, tree ft2
, Type
* d_type
, const char * n1
, const char * n2
)
1959 tree f0
= build_decl(FIELD_DECL
, get_identifier(n1
), ft1
);
1960 tree f1
= build_decl(FIELD_DECL
, get_identifier(n2
), ft2
);
1961 DECL_CONTEXT(f0
) = rec_type
;
1962 DECL_CONTEXT(f1
) = rec_type
;
1963 TYPE_FIELDS(rec_type
) = chainon(f0
, f1
);
1964 layout_type(rec_type
);
1966 /* This is needed so that maybeExpandSpecialCall knows to
1967 split dynamic array varargs. */
1968 TYPE_LANG_SPECIFIC( rec_type
) = build_d_type_lang_specific(d_type
);
1970 /* ObjectFile::declareType will try to declare it as top-level type
1971 which can break debugging info for element types. */
1972 tree stub_decl
= build_decl(TYPE_DECL
, get_identifier(d_type
->toChars()), rec_type
);
1973 TYPE_STUB_DECL(rec_type
) = stub_decl
;
1974 TYPE_NAME(rec_type
) = stub_decl
;
1975 DECL_ARTIFICIAL(stub_decl
) = 1;
1976 g
.ofile
->rodc(stub_decl
, 0);
1981 // Create a record type from two field types
1983 IRState::twoFieldType(Type
* ft1
, Type
* ft2
, Type
* d_type
, const char * n1
, const char * n2
)
1985 return twoFieldType( make_node( RECORD_TYPE
), ft1
->toCtype(), ft2
->toCtype(), d_type
, n1
, n2
);
1989 IRState::twoFieldCtor(tree rec_type
, tree f1
, tree f2
, int storage_class
)
1991 tree ctor
= make_node( CONSTRUCTOR
);
1995 TREE_TYPE( ctor
) = rec_type
;
1996 TREE_STATIC( ctor
) = (storage_class
& STCstatic
) != 0;
1997 TREE_CONSTANT( ctor
) = (storage_class
& STCconst
) != 0;
1998 TREE_READONLY( ctor
) = (storage_class
& STCconst
) != 0;
1999 ft1
= TYPE_FIELDS( rec_type
);
2000 ft2
= TREE_CHAIN( ft1
);
2004 CONSTRUCTOR_ELTS( ctor
) = ce
.head
;
2009 // This could be made more lax to allow better CSE (?)
2011 needs_temp(tree t
) {
2012 // %%TODO: check for anything with TREE_SIDE_EFFECTS?
2013 switch (TREE_CODE(t
)) {
2023 case REFERENCE_EXPR
:
2025 /* This check is needed for 4.0. Without it, typeinfo.methodCall may not be
2027 return ! (DECL_P(TREE_OPERAND(t
, 0)));
2032 case NON_LVALUE_EXPR
:
2033 case VIEW_CONVERT_EXPR
:
2034 return needs_temp(TREE_OPERAND(t
, 0));
2040 TREE_CODE_CLASS(TREE_CODE(t
)) == tcc_constant
)
2042 TREE_CODE_CLASS(TREE_CODE(t
)) == 'c')
2051 IRState::isFreeOfSideEffects(tree t
)
2053 // SAVE_EXPR is safe to reference more than once, but not to
2054 // expand in a loop.
2055 return TREE_CODE(t
) != SAVE_EXPR
&& ! needs_temp(t
);
2059 IRState::maybeMakeTemp(tree t
)
2061 if (needs_temp(t
)) {
2062 if (TREE_CODE(TREE_TYPE(t
)) != ARRAY_TYPE
)
2063 return save_expr(t
);
2065 return stabilize_reference(t
);
2070 Module
* IRState::builtinsModule
= 0;
2071 Module
* IRState::intrinsicModule
= 0;
2072 TemplateDeclaration
* IRState::stdargTemplateDecl
= 0;
2073 TemplateDeclaration
* IRState::cstdargStartTemplateDecl
= 0;
2074 TemplateDeclaration
* IRState::cstdargArgTemplateDecl
= 0;
2077 IRState::maybeSetUpBuiltin(Declaration
* decl
)
2080 TemplateInstance
* ti
;
2082 // Don't use toParent2. We are looking for a template below.
2083 dsym
= decl
->toParent();
2085 if (dsym
->getModule() == intrinsicModule
) {
2086 // Matches order of Intrinsic enum
2087 static const char * intrinsic_names
[] = {
2089 "bt", "btc", "btr", "bts",
2091 "inp", "inpw", "inpl",
2092 "outp", "outw", "outl", NULL
2094 for (int i
= 0; intrinsic_names
[i
]; i
++) {
2095 if ( ! strcmp( decl
->ident
->string
, intrinsic_names
[i
] ) ) {
2096 bool have_intrinsic
= false;
2097 tree t
= decl
->toSymbol()->Stree
;
2099 switch ( (Intrinsic
) i
) {
2107 case INTRINSIC_BSWAP
:
2108 #if defined(TARGET_386)
2109 //have_intrinsic = true;
2113 case INTRINSIC_INPW
:
2114 case INTRINSIC_INPL
:
2115 case INTRINSIC_OUTP
:
2116 case INTRINSIC_OUTPW
:
2117 case INTRINSIC_OUTPL
:
2118 // Only on ix86, but need to given error message on others
2119 have_intrinsic
= true;
2125 if (have_intrinsic
) {
2126 DECL_BUILT_IN_CLASS( t
) = BUILT_IN_FRONTEND
;
2127 DECL_FUNCTION_CODE( t
) = (built_in_function
) i
;
2134 ti
= dsym
->isTemplateInstance();
2136 tree t
= decl
->toSymbol()->Stree
;
2137 if (ti
->tempdecl
== stdargTemplateDecl
) {
2138 DECL_BUILT_IN_CLASS(t
) = BUILT_IN_FRONTEND
;
2139 DECL_FUNCTION_CODE(t
) = (built_in_function
) INTRINSIC_STD_VA_ARG
;
2141 } else if (ti
->tempdecl
== cstdargArgTemplateDecl
) {
2142 DECL_BUILT_IN_CLASS(t
) = BUILT_IN_FRONTEND
;
2143 DECL_FUNCTION_CODE(t
) = (built_in_function
) INTRINSIC_C_VA_ARG
;
2145 } else if (ti
->tempdecl
== cstdargStartTemplateDecl
) {
2146 DECL_BUILT_IN_CLASS(t
) = BUILT_IN_FRONTEND
;
2147 DECL_FUNCTION_CODE(t
) = (built_in_function
) INTRINSIC_C_VA_START
;
2156 IRState::isDeclarationReferenceType(Declaration
* decl
)
2158 Type
* base_type
= decl
->type
->toBasetype();
2160 // D doesn't do this now..
2161 if ( base_type
->ty
== Treference
) {
2165 if ( decl
->isOut() || decl
->isRef() ||
2166 ( decl
->isParameter() && base_type
->ty
== Tsarray
) ) {
2174 IRState::trueDeclarationType(Declaration
* decl
)
2176 // If D supported references, we would have to check twice for
2177 // (out T &) -- disallow, maybe or make isDeclarationReferenceType return
2178 // the number of levels to reference
2179 tree decl_type
= decl
->type
->toCtype();
2180 if ( isDeclarationReferenceType( decl
)) {
2181 return build_reference_type( decl_type
);
2182 } else if (decl
->storage_class
& STClazy
) {
2183 TypeFunction
*tf
= new TypeFunction(NULL
, decl
->type
, 0, LINKd
);
2184 TypeDelegate
*t
= new TypeDelegate(tf
);
2185 return t
->merge()->toCtype();
2191 // These should match the Declaration versions above
2193 IRState::isArgumentReferenceType(Argument
* arg
)
2195 Type
* base_type
= arg
->type
->toBasetype();
2197 if ( base_type
->ty
== Treference
) {
2201 if ( (arg
->storageClass
& (STCout
| STCref
)) || base_type
->ty
== Tsarray
) {
2209 IRState::trueArgumentType(Argument
* arg
)
2211 tree arg_type
= arg
->type
->toCtype();
2212 if ( isArgumentReferenceType( arg
)) {
2213 return build_reference_type( arg_type
);
2214 } else if (arg
->storageClass
& STClazy
) {
2215 TypeFunction
*tf
= new TypeFunction(NULL
, arg
->type
, 0, LINKd
);
2216 TypeDelegate
*t
= new TypeDelegate(tf
);
2217 return t
->merge()->toCtype();
2224 IRState::arrayType(tree type_node
, uinteger_t size
)
2226 tree index_type_node
;
2228 index_type_node
= size_int( size
- 1 );
2229 index_type_node
= build_index_type(index_type_node
);
2231 // See c-decl.c grokdeclarator for zero-length arrays
2232 index_type_node
= build_range_type (sizetype
, size_zero_node
,
2236 tree array_type
= build_array_type(type_node
, index_type_node
);
2239 layout_type(array_type
);
2241 TYPE_SIZE(array_type
) = bitsize_zero_node
;
2242 TYPE_SIZE_UNIT(array_type
) = size_zero_node
;
2248 IRState::addTypeAttribute(tree type
, const char * attrname
, tree value
)
2250 // use build_type_copy / build_type_attribute_variant
2252 // types built by functions in tree.c need to be treated as immutable
2253 if ( ! TYPE_ATTRIBUTES( type
)) { // ! TYPE_ATTRIBUTES -- need a better check
2254 type
= build_type_copy( type
);
2255 // TYPE_STUB_DECL( type ) = .. if we need this for structs, etc.. since
2256 // TREE_CHAIN is cleared by COPY_NODE
2259 value
= tree_cons(NULL_TREE
, value
, NULL_TREE
);
2260 TYPE_ATTRIBUTES( type
) = tree_cons( get_identifier(attrname
), value
,
2261 TYPE_ATTRIBUTES( type
));
2266 IRState::addDeclAttribute(tree type
, const char * attrname
, tree value
)
2269 value
= tree_cons(NULL_TREE
, value
, NULL_TREE
);
2270 DECL_ATTRIBUTES( type
) = tree_cons( get_identifier(attrname
), value
,
2271 DECL_ATTRIBUTES( type
));
2275 IRState::attributes(Expressions
* in_attrs
)
2280 ListMaker out_attrs
;
2282 for (unsigned i
= 0; i
< in_attrs
->dim
; i
++)
2284 Expression
* e
= (Expression
*) in_attrs
->data
[i
];
2285 IdentifierExp
* ident_e
= NULL
;
2289 if (e
->op
== TOKidentifier
)
2290 ident_e
= (IdentifierExp
*) e
;
2291 else if (e
->op
== TOKcall
)
2293 CallExp
* c
= (CallExp
*) e
;
2294 assert(c
->e1
->op
== TOKidentifier
);
2295 ident_e
= (IdentifierExp
*) c
->e1
;
2298 for (unsigned ai
= 0; ai
< c
->arguments
->dim
; ai
++) {
2299 Expression
* ae
= (Expression
*) c
->arguments
->data
[ai
];
2301 if (ae
->op
== TOKstring
&& ((StringExp
*) ae
)->sz
== 1)
2303 StringExp
* s
= (StringExp
*) ae
;
2304 aet
= build_string(s
->len
, (const char*) s
->string
);
2307 aet
= ae
->toElem(&gen
);
2317 out_attrs
.cons(get_identifier(ident_e
->ident
->string
), args
.head
);
2320 return out_attrs
.head
;
2324 IRState::integerConstant(xdmd_integer_t value
, tree type
) {
2326 // Assuming xdmd_integer_t is 64 bits
2327 # if HOST_BITS_PER_WIDE_INT == 32
2328 tree tree_value
= build_int_2(value
& 0xffffffff, (value
>> 32) & 0xffffffff);
2329 # elif HOST_BITS_PER_WIDE_INT == 64
2330 tree tree_value
= build_int_2(value
,
2331 type
&& ! TREE_UNSIGNED(type
) && (value
& 0x8000000000000000ULL
) ?
2332 ~(unsigned HOST_WIDE_INT
) 0 : 0);
2337 TREE_TYPE( tree_value
) = type
;
2338 // May not to call force_fit_type for 3.3.x and 3.4.x, but being safe.
2339 force_fit_type(tree_value
, 0);
2342 # if HOST_BITS_PER_WIDE_INT == 32
2343 tree tree_value
= build_int_cst_wide(type
,
2344 value
& 0xffffffff, (value
>> 32) & 0xffffffff);
2345 # elif HOST_BITS_PER_WIDE_INT == 64
2346 tree tree_value
= build_int_cst_type(type
, value
);
2350 /* VALUE may be an incorrect representation for TYPE. Example:
2351 uint x = cast(uint) -3; // becomes "-3u" -- value=0xfffffffffffffd type=Tuns32
2352 Constant folding will not work correctly unless this is done. */
2353 tree_value
= force_fit_type(tree_value
, 0, 0, 0);
2359 IRState::exceptionObject()
2361 tree obj_type
= getObjectType()->toCtype();
2362 // Like gjc, the actual D exception object is one
2363 // pointer behind the exception header
2364 tree t
= build (EXC_PTR_EXPR
, ptr_type_node
);
2365 t
= build1(NOP_EXPR
, build_pointer_type(obj_type
), t
); // treat exception header as ( Object* )
2366 t
= build(MINUS_EXPR
, TREE_TYPE(t
), t
, TYPE_SIZE_UNIT(TREE_TYPE(t
)));
2367 t
= build1(INDIRECT_REF
, obj_type
, t
);
2372 IRState::label(Loc loc
, Identifier
* ident
) {
2373 tree t_label
= build_decl(LABEL_DECL
,
2374 ident
? get_identifier(ident
->string
) : NULL_TREE
, void_type_node
);
2375 DECL_CONTEXT( t_label
) = current_function_decl
;
2376 DECL_MODE( t_label
) = VOIDmode
;
2378 g
.ofile
->setDeclLoc(t_label
, loc
);
2383 IRState::getFrameForFunction(FuncDeclaration
* f
)
2386 return getFrameForSymbol(f
);
2389 // Should error on line that references f
2390 f
->error("nested function missing body");
2391 return d_null_pointer
;
2395 IRState::getFrameForNestedClass(ClassDeclaration
*c
)
2397 return getFrameForSymbol(c
);
2400 /* If nested_sym is a nested function, return the static chain to be
2401 used when invoking that function.
2403 If nested_sym is a nested class, return the static chain to be used
2404 when creating an instance of the class.
2406 This method is protected to enforce the type checking of
2407 getFrameForFunction and getFrameForNestedClass.
2408 getFrameForFunction also checks that the nestd function is properly
2413 IRState::getFrameForSymbol(Dsymbol
* nested_sym
)
2415 FuncDeclaration
* nested_func
= 0;
2416 FuncDeclaration
* outer_func
= 0;
2418 if ( (nested_func
= nested_sym
->isFuncDeclaration()) )
2420 // gcc_assert(nested_func->isNested())
2421 outer_func
= nested_func
->toParent2()->isFuncDeclaration();
2422 gcc_assert(outer_func
!= NULL
);
2426 /* It's a class. NewExp::toElem has already determined its
2427 outer scope is not another class, so it must be a
2430 Dsymbol
* sym
= nested_sym
;
2432 while (sym
&& ! (outer_func
= sym
->isFuncDeclaration()))
2433 sym
= sym
->toParent2();
2435 /* Make sure we can access the frame of outer_func.
2445 new X // <-- you are here
2450 In order to get the static chain we must know a
2451 function nested in F. If we are currently in such a
2452 nested function, use that.
2456 new X // <-- you are here
2459 If we are at the level of the function containing the
2460 class, the answer is just 'virtual_stack_vars_rtx'.
2463 if (outer_func
!= func
) {
2465 Dsymbol
* o
= nested_func
= func
;
2467 if (! nested_func
->isNested())
2468 goto cannot_access_frame
;
2469 while ( (o
= o
->toParent2()) )
2470 if ( (nested_func
= o
->isFuncDeclaration()) )
2472 } while (o
&& o
!= outer_func
);
2475 cannot_access_frame
:
2476 error("cannot access frame of function '%s' from '%s'",
2477 outer_func
->ident
->string
, func
->ident
->string
);
2478 return d_null_pointer
;
2481 // else, the answer is 'virtual_stack_vars_rtx'
2485 if (getFrameInfo(outer_func
)->creates_closure
)
2486 return getClosureRef(outer_func
);
2490 tree result
= make_node (RTL_EXPR
);
2491 TREE_TYPE (result
) = ptr_type_node
;
2492 RTL_EXPR_RTL (result
) = nested_func
?
2493 lookup_static_chain(nested_func
->toSymbol()->Stree
) :
2494 virtual_stack_vars_rtx
;
2498 outer_func
= nested_func
->toParent2()->isFuncDeclaration();
2499 gcc_assert(outer_func
!= NULL
);
2500 return build1(STATIC_CHAIN_EXPR
, ptr_type_node
, outer_func
->toSymbol()->Stree
);
2506 /* For the purposes this is used, fd is assumed to be a nested
2507 function or a method of a class that is (eventually) nested in a
2511 isFuncNestedInFunc(FuncDeclaration
* fd
, FuncDeclaration
*fo
)
2518 AggregateDeclaration
* ad
;
2519 ClassDeclaration
* cd
;
2523 //fprintf(stderr, "%s is nested in %s\n", fd->toChars(), fo->toChars());
2526 else if (fd
->isNested())
2527 fd
= fd
->toParent2()->isFuncDeclaration();
2528 else if ( (ad
= fd
->isThis()) && (cd
= ad
->isClassDeclaration()) )
2531 while (cd
&& cd
->isNested())
2533 Dsymbol
* dsym
= cd
->toParent2();
2534 if ( (fd
= dsym
->isFuncDeclaration()) )
2537 cd
= dsym
->isClassDeclaration();
2544 //fprintf(stderr, "%s is NOT nested in %s\n", fd->toChars(), fo->toChars());
2549 IRState::getFrameInfo(FuncDeclaration
*fd
)
2551 Symbol
* fds
= fd
->toSymbol();
2553 return fds
->frameInfo
;
2555 FuncFrameInfo
* ffi
= new FuncFrameInfo
;
2556 ffi
->creates_closure
= false;
2557 ffi
->closure_rec
= NULL_TREE
;
2559 fds
->frameInfo
= ffi
;
2561 Dsymbol
* s
= fd
->toParent2();
2563 if (fd
->needsClosure())
2564 ffi
->creates_closure
= true;
2567 /* If fd is nested (deeply) in a function 'g' that creates a
2568 closure and there exists a function 'h' nested (deeply) in
2569 fd and 'h' accesses the frame of 'g', then fd must also
2572 This is for the sake of a simple implementation. An alternative
2573 is, when determining the frame to pass to 'h', pass the pointer
2574 to 'g' (the deepest 'g' whose frame is accessed by 'h') instead
2575 of the usual frame that 'h' would take.
2577 FuncDeclaration
* ff
= fd
;
2581 AggregateDeclaration
* ad
;
2582 ClassDeclaration
* cd
;
2586 if (getFrameInfo(ff
)->creates_closure
)
2588 for (int i
= 0; i
< ff
->closureVars
.dim
; i
++)
2589 { VarDeclaration
*v
= (VarDeclaration
*)ff
->closureVars
.data
[i
];
2590 for (int j
= 0; j
< v
->nestedrefs
.dim
; j
++)
2591 { FuncDeclaration
*fi
= (FuncDeclaration
*)v
->nestedrefs
.data
[j
];
2592 if (isFuncNestedInFunc(fi
, fd
))
2594 ffi
->creates_closure
= true;
2603 ff
= ff
->toParent2()->isFuncDeclaration();
2604 else if ( (ad
= ff
->isThis()) && (cd
= ad
->isClassDeclaration()) )
2607 while (cd
&& cd
->isNested())
2609 Dsymbol
* dsym
= cd
->toParent2();
2610 if ( (ff
= dsym
->isFuncDeclaration()) )
2613 cd
= dsym
->isClassDeclaration();
2624 /*fprintf(stderr, "%s %s\n", ffi->creates_closure ? "YES" : "NO ",
2630 // Return a pointer to the closure block of outer_func
2632 IRState::getClosureRef(FuncDeclaration
* outer_func
)
2634 tree result
= closureLink();
2635 FuncDeclaration
* fd
= closureFunc
;
2637 while (fd
&& fd
!= outer_func
)
2639 AggregateDeclaration
* ad
;
2640 ClassDeclaration
* cd
;
2642 gcc_assert(getFrameInfo(fd
)->creates_closure
); // remove this if we loosen creates_closure
2644 // like compon(indirect, field0) parent closure link is the first field;
2645 result
= indirect(result
, ptr_type_node
);
2649 fd
= fd
->toParent2()->isFuncDeclaration();
2651 else if ( (ad
= fd
->isThis()) && (cd
= ad
->isClassDeclaration()) )
2654 while (cd
&& cd
->isNested())
2656 /* Shouldn't need to do this. getClosureRef is only
2657 used to get the pointer to a function's frame (not
2658 a class instances.) With the current implementation,
2659 the link the closure record always points to the
2660 outer function's frame even if there are intervening
2661 nested classes. So, we can just skip over those...
2663 tree vthis_field = cd->vthis->toSymbol()->Stree;
2664 result = nop(result, cd->type->toCtype());
2665 result = component(indirect(result), vthis_field);
2668 Dsymbol
* dsym
= cd
->toParent2();
2669 if ( (fd
= dsym
->isFuncDeclaration()) )
2672 cd
= dsym
->isClassDeclaration();
2679 if (fd
== outer_func
)
2681 tree closure_rec
= getFrameInfo(outer_func
)->closure_rec
;
2682 result
= nop(result
, build_pointer_type(closure_rec
));
2687 func
->error("cannot access frame of %s", outer_func
->toChars());
2688 return d_null_pointer
;
2694 /* Return true if function F needs to have the static chain passed to
2695 it. This only applies to nested function handling provided by the
2696 GCC back end (not D closures.)
2699 IRState::functionNeedsChain(FuncDeclaration
*f
)
2702 ClassDeclaration
* a
;
2703 FuncDeclaration
*pf
= 0;
2707 && ! getFrameInfo(f
->toParent2()->isFuncDeclaration())->creates_closure
2716 while ( s
&& (a
= s
->isClassDeclaration()) && a
->isNested() ) {
2718 if ( (pf
= s
->isFuncDeclaration())
2720 && ! getFrameInfo(pf
)->creates_closure
2729 IRState::toElemLvalue(Expression
* e
)
2732 if (e->op == TOKcast)
2733 fprintf(stderr, "IRState::toElemLvalue TOKcast\n");
2737 if (e
->op
== TOKindex
) {
2738 IndexExp
* ie
= (IndexExp
*) e
;
2739 Expression
* e1
= ie
->e1
;
2740 Expression
* e2
= ie
->e2
;
2741 Type
* type
= e
->type
;
2742 Type
* array_type
= e1
->type
->toBasetype();
2744 if (array_type
->ty
== Taarray
) {
2745 Type
* key_type
= ((TypeAArray
*) array_type
)->index
->toBasetype();
2749 args
[0] = this->addressOf( this->toElemLvalue(e1
) );
2750 args
[1] = this->typeinfoReference(key_type
);
2751 args
[2] = this->integerConstant( array_type
->nextOf()->size(), Type::tsize_t
);
2752 args
[3] = aoe
.set(this, this->convertTo( e2
, key_type
));
2753 return build1(INDIRECT_REF
, type
->toCtype(),
2755 this->libCall(LIBCALL_AAGETP
, 4, args
, type
->pointerTo()->toCtype())));
2758 return e
->toElem(this);
2765 IRState::startCond(Statement
* stmt
, Expression
* e_cond
) {
2767 g
.ofile
->doLineNote(stmt
->loc
);
2768 expand_start_cond( convertForCondition( e_cond
), 0 );
2772 IRState::startElse() { expand_start_else(); }
2775 IRState::endCond() { expand_end_cond(); }
2778 IRState::startLoop(Statement
* stmt
) {
2779 beginFlow(stmt
, expand_start_loop_continue_elsewhere(1));
2783 IRState::continueHere()
2785 Flow
* f
= currentFlow();
2786 if (f
->overrideContinueLabel
)
2787 doLabel(f
->overrideContinueLabel
);
2789 expand_loop_continue_here();
2793 IRState::setContinueLabel(tree lbl
)
2795 currentFlow()->overrideContinueLabel
= lbl
;
2799 IRState::exitIfFalse(tree t_cond
, bool is_top_cond
) {
2801 // %% topcond compaitble with continue_elswehre?
2802 expand_exit_loop_if_false(currentFlow()->loop
, t_cond
);
2806 IRState::startCase(Statement
* stmt
, tree t_cond
)
2809 g
.ofile
->doLineNote(stmt
->loc
);
2810 expand_start_case( 1, t_cond
, TREE_TYPE( t_cond
), "switch statement" );
2811 beginFlow(stmt
, NULL
);
2815 IRState::doCase(tree t_value
, tree t_label
)
2818 // %% not the same convert that is in d-glue!!
2819 pushcase( t_value
, convert
, t_label
, & dummy
);
2823 IRState::endCase(tree t_cond
)
2825 expand_end_case( t_cond
);
2830 IRState::endLoop() {
2836 IRState::continueLoop(Identifier
* ident
) {
2837 Flow
* f
= getLoopForLabel( ident
, true );
2838 if (f
->overrideContinueLabel
)
2839 doJump(NULL
, f
->overrideContinueLabel
);
2841 expand_continue_loop( f
->loop
);
2845 IRState::exitLoop(Identifier
* ident
)
2848 Flow
* flow
= getLoopForLabel( ident
);
2850 expand_exit_loop( flow
->loop
);
2852 if (! flow
->exitLabel
)
2853 flow
->exitLabel
= label(flow
->statement
->loc
);
2854 expand_goto( flow
->exitLabel
);
2857 expand_exit_something();
2862 IRState::startTry(Statement
* stmt
)
2864 expand_eh_region_start();
2868 IRState::startCatches()
2870 expand_start_all_catch();
2874 IRState::startCatch(tree t_type
)
2876 expand_start_catch( t_type
);
2886 IRState::endCatches()
2888 expand_end_all_catch();
2892 IRState::startFinally()
2898 IRState::endFinally()
2904 IRState::doReturn(tree t_value
)
2907 expand_return(t_value
);
2909 expand_null_return();
2913 IRState::doJump(Statement
* stmt
, tree t_label
)
2915 // %%TODO: c-semantics.c:expand_stmt GOTO_STMT branch prediction
2916 TREE_USED( t_label
) = 1 ;
2918 g
.ofile
->doLineNote( stmt
->loc
);
2919 expand_goto( t_label
);
2923 IRState::makeStmtExpr(Statement
* statement
)
2925 tree t
= build1((enum tree_code
) D_STMT_EXPR
, void_type_node
, NULL_TREE
);
2926 TREE_SIDE_EFFECTS(t
) = 1; // %%
2927 stmtExprList
.push(t
);
2928 stmtExprList
.push(statement
);
2929 stmtExprList
.push(this);
2934 IRState::retrieveStmtExpr(tree t
, Statement
** s_out
, IRState
** i_out
)
2936 for (int i
= stmtExprList
.dim
- 3; i
>= 0 ; i
-= 3) {
2937 if ( (tree
) stmtExprList
.data
[i
] == t
) {
2938 *s_out
= (Statement
*) stmtExprList
.data
[i
+ 1];
2939 *i_out
= (IRState
*) stmtExprList
.data
[i
+ 2];
2940 // The expression could be evaluated multiples times, so we must
2941 // keep the values forever --- %% go back to per-function list
2952 IRState::startCond(Statement
* stmt
, Expression
* e_cond
)
2954 tree t_cond
= convertForCondition(e_cond
);
2956 Flow
* f
= beginFlow(stmt
/*, 0*/);
2957 f
->condition
= t_cond
;
2961 IRState::startElse()
2963 currentFlow()->trueBranch
= popStatementList();
2964 pushStatementList();
2970 Flow
* f
= currentFlow();
2971 tree t_brnch
= popStatementList(); // endFlow(); -- can't pop -- need the info?
2972 tree t_false_brnch
= NULL_TREE
;
2974 if (f
->trueBranch
== NULL_TREE
)
2975 f
->trueBranch
= t_brnch
;
2977 t_false_brnch
= t_brnch
;
2979 g
.ofile
->doLineNote(f
->statement
->loc
);
2980 tree t_stmt
= build3(COND_EXPR
, void_type_node
,
2981 f
->condition
, f
->trueBranch
, t_false_brnch
);
2987 IRState::startLoop(Statement
* stmt
) {
2988 Flow
* f
= beginFlow(stmt
/*, Break|Continue*/);
2989 f
->continueLabel
= label(stmt
? stmt
->loc
: 0); // should be end for 'do' loop
2993 IRState::continueHere() {
2994 doLabel(currentFlow()->continueLabel
);
2998 IRState::setContinueLabel(tree lbl
)
3000 currentFlow()->continueLabel
= lbl
;
3004 IRState::exitIfFalse(tree t_cond
, bool /*unused*/) {
3005 addExp(build1(EXIT_EXPR
, void_type_node
,
3006 build1(TRUTH_NOT_EXPR
, TREE_TYPE(t_cond
), t_cond
)));
3010 IRState::startCase(Statement
* stmt
, tree t_cond
)
3012 Flow
* f
= beginFlow(stmt
);
3013 f
->condition
= t_cond
;
3017 IRState::doCase(tree t_value
, tree t_label
)
3019 addExp(build3(CASE_LABEL_EXPR
, void_type_node
,
3020 t_value
, NULL_TREE
, t_label
));
3024 IRState::endCase(tree
/*t_cond*/)
3026 Flow
* f
= currentFlow();
3027 tree t_body
= popStatementList();
3028 tree t_stmt
= build3(SWITCH_EXPR
, void_type_node
, f
->condition
,
3035 IRState::endLoop() {
3036 // says must contain an EXIT_EXPR -- what about while(1)..goto;? something other thand LOOP_EXPR?
3037 tree t_body
= popStatementList();
3038 tree t_loop
= build1(LOOP_EXPR
, void_type_node
, t_body
);
3044 IRState::continueLoop(Identifier
* ident
) {
3045 //doFlowLabel(stmt, ident, Continue);
3046 doJump(NULL
, getLoopForLabel(ident
, true)->continueLabel
);
3050 IRState::exitLoop(Identifier
* ident
) {
3051 Flow
* flow
= getLoopForLabel(ident
);
3052 if (! flow
->exitLabel
)
3053 flow
->exitLabel
= label(flow
->statement
->loc
);
3054 doJump(NULL
, flow
->exitLabel
);
3059 IRState::startTry(Statement
* stmt
)
3065 IRState::startCatches()
3067 currentFlow()->tryBody
= popStatementList();
3068 pushStatementList();
3072 IRState::startCatch(tree t_type
)
3074 currentFlow()->catchType
= t_type
;
3075 pushStatementList();
3081 tree t_body
= popStatementList();
3082 // % wrong loc.. can set pass statement to startCatch, set
3083 // the loc on t_type and then use it here..
3084 // may not be important?
3085 doExp(build2(CATCH_EXPR
, void_type_node
,
3086 currentFlow()->catchType
, t_body
));
3090 IRState::endCatches()
3092 tree t_catches
= popStatementList();
3093 g
.ofile
->doLineNote(currentFlow()->statement
->loc
);
3094 doExp(build2(TRY_CATCH_EXPR
, void_type_node
,
3095 currentFlow()->tryBody
, t_catches
));
3100 IRState::startFinally()
3102 currentFlow()->tryBody
= popStatementList();
3103 pushStatementList();
3107 IRState::endFinally()
3109 tree t_finally
= popStatementList();
3110 g
.ofile
->doLineNote(currentFlow()->statement
->loc
);
3111 doExp(build2(TRY_FINALLY_EXPR
, void_type_node
,
3112 currentFlow()->tryBody
, t_finally
));
3117 IRState::doReturn(tree t_value
)
3119 addExp(build1(RETURN_EXPR
, void_type_node
, t_value
));
3123 IRState::doJump(Statement
* stmt
, tree t_label
)
3126 g
.ofile
->doLineNote( stmt
->loc
);
3127 addExp(build1(GOTO_EXPR
, void_type_node
, t_label
));
3131 IRState::makeStmtExpr(Statement
* statement
)
3135 pushStatementList();
3136 statement
->toIR(this);
3137 t_list
= popStatementList();
3147 IRState::doAsm(tree insn_tmpl
, tree outputs
, tree inputs
, tree clobbers
)
3150 expand_asm_operands(insn_tmpl
, outputs
, inputs
, clobbers
, 1, input_location
);
3152 tree t
= d_build_asm_stmt(insn_tmpl
, outputs
, inputs
, clobbers
);
3153 ASM_VOLATILE_P( t
) = 1;
3158 WrappedExp::WrappedExp(Loc loc
, enum TOK op
, tree exp_node
, Type
* type
)
3159 : Expression(loc
, op
, sizeof(WrappedExp
))
3161 this->exp_node
= exp_node
;
3166 WrappedExp::toCBuffer(OutBuffer
*buf
)
3168 buf
->printf("< wrapped exprission >");
3172 WrappedExp::toElem(IRState
*)
3178 void AggLayout::doFields(Array
* fields
, AggregateDeclaration
* agg
)
3180 bool inherited
= agg
!= this->aggDecl
;
3183 fcontext
= agg
->type
->toCtype();
3184 if ( POINTER_TYPE_P( fcontext
))
3185 fcontext
= TREE_TYPE(fcontext
);
3187 // tree new_field_chain = NULL_TREE;
3188 for (unsigned i
= 0; i
< fields
->dim
; i
++) {
3189 // %% D anonymous unions just put the fields into the outer struct...
3190 // does this cause problems?
3192 VarDeclaration
* var_decl
= (VarDeclaration
*) fields
->data
[i
];
3194 assert( var_decl
->storage_class
& STCfield
);
3196 tree ident
= var_decl
->ident
? get_identifier(var_decl
->ident
->string
) : NULL_TREE
;
3197 tree field_decl
= build_decl(FIELD_DECL
, ident
,
3198 gen
.trueDeclarationType( var_decl
));
3199 g
.ofile
->setDeclLoc( field_decl
, var_decl
);
3200 var_decl
->csym
= new Symbol
;
3201 var_decl
->csym
->Stree
= field_decl
;
3203 DECL_CONTEXT( field_decl
) = aggType
;
3204 DECL_FCONTEXT( field_decl
) = fcontext
;
3205 DECL_FIELD_OFFSET (field_decl
) = size_int( var_decl
->offset
);
3206 DECL_FIELD_BIT_OFFSET (field_decl
) = bitsize_zero_node
;
3208 DECL_ARTIFICIAL( field_decl
) =
3209 DECL_IGNORED_P( field_decl
) = inherited
;
3212 // GCC 4.0 requires DECL_OFFSET_ALIGN to be set
3213 // %% .. using TYPE_ALIGN may not be same as DMD..
3214 SET_DECL_OFFSET_ALIGN( field_decl
,
3215 TYPE_ALIGN( TREE_TYPE( field_decl
)));
3217 //SET_DECL_OFFSET_ALIGN (field_decl, BIGGEST_ALIGNMENT); // ?
3218 layout_decl( field_decl
, 0 );
3220 // get_inner_reference doesn't check these, leaves a variable unitialized
3221 // DECL_SIZE is NULL if size is zero.
3222 if (var_decl
->size(var_decl
->loc
)) {
3223 assert(DECL_MODE(field_decl
) != VOIDmode
);
3224 assert(DECL_SIZE(field_decl
) != NULL_TREE
);
3226 fieldList
.chain( field_decl
);
3230 void AggLayout::doInterfaces(Array
* bases
, AggregateDeclaration
* /*agg*/)
3232 //tree fcontext = TREE_TYPE( agg->type->toCtype() );
3233 for (unsigned i
= 0; i
< bases
->dim
; i
++) {
3234 BaseClass
* bc
= (BaseClass
*) bases
->data
[i
];
3235 tree decl
= build_decl(FIELD_DECL
, NULL_TREE
,
3236 Type::tvoid
->pointerTo()->pointerTo()->toCtype() /* %% better */ );
3237 //DECL_VIRTUAL_P( decl ) = 1; %% nobody cares, boo hoo
3238 DECL_ARTIFICIAL( decl
) =
3239 DECL_IGNORED_P( decl
) = 1;
3240 // DECL_FCONTEXT( decl ) = fcontext; // shouldn't be needed since it's ignored
3241 addField(decl
, bc
->offset
);
3245 void AggLayout::addField(tree field_decl
, target_size_t offset
)
3247 DECL_CONTEXT( field_decl
) = aggType
;
3248 // DECL_FCONTEXT( field_decl ) = aggType; // caller needs to set this
3249 DECL_FIELD_OFFSET (field_decl
) = size_int( offset
);
3250 DECL_FIELD_BIT_OFFSET (field_decl
) = bitsize_int( 0 );
3251 Loc
l(aggDecl
->getModule(), 1); // Must set this or we crash with DWARF debugging
3252 // gen.setDeclLoc( field_decl, aggDecl->loc ); // aggDecl->loc isn't set
3253 g
.ofile
->setDeclLoc(field_decl
, l
);
3255 layout_decl( field_decl
, 0 );
3256 fieldList
.chain( field_decl
);
3259 void AggLayout::finish(Expressions
* attrs
)
3261 unsigned size_to_use
= aggDecl
->structsize
;
3262 unsigned align_to_use
= aggDecl
->alignsize
;
3264 /* probably doesn't do anything */
3266 if (aggDecl->structsize == 0 && aggDecl->isInterfaceDeclaration())
3267 size_to_use = Type::tvoid->pointerTo()->size();
3270 TYPE_SIZE( aggType
) = bitsize_int( size_to_use
* BITS_PER_UNIT
);
3271 TYPE_SIZE_UNIT( aggType
) = size_int( size_to_use
);
3272 TYPE_ALIGN( aggType
) = align_to_use
* BITS_PER_UNIT
;
3273 // TYPE_ALIGN_UNIT is not an lvalue
3274 TYPE_PACKED (aggType
) = TYPE_PACKED (aggType
); // %% todo
3277 decl_attributes(& aggType
, gen
.attributes(attrs
),
3278 ATTR_FLAG_TYPE_IN_PLACE
);
3280 compute_record_mode ( aggType
);
3281 // %% stor-layout.c:finalize_type_size ... it's private to that file
3283 // c-decl.c -- set up variants ? %%
3284 for (tree x
= TYPE_MAIN_VARIANT( aggType
); x
; x
= TYPE_NEXT_VARIANT( x
)) {
3285 TYPE_FIELDS (x
) = TYPE_FIELDS (aggType
);
3286 TYPE_LANG_SPECIFIC (x
) = TYPE_LANG_SPECIFIC (aggType
);
3287 TYPE_ALIGN (x
) = TYPE_ALIGN (aggType
);
3288 TYPE_USER_ALIGN (x
) = TYPE_USER_ALIGN (aggType
);
3292 ArrayScope::ArrayScope(IRState
* ini_irs
, VarDeclaration
* ini_v
, const Loc
& loc
) :
3293 v(ini_v
), irs(ini_irs
)
3296 /* Need to set the location or the expand_decl in the BIND_EXPR will
3297 cause the line numbering for the statement to be incorrect. */
3298 /* The variable itself is not included in the debugging information. */
3300 Symbol
* s
= v
->toSymbol();
3301 tree decl
= s
->Stree
;
3302 DECL_CONTEXT( decl
) = irs
->getLocalContext();
3307 ArrayScope::setArrayExp(tree e
, Type
* t
)
3309 /* If STCconst, the value will be assigned in d-decls.cc
3310 of the runtime length of the array expression. */
3311 if (v
&& ! (v
->storage_class
& STCconst
))
3313 if (t
->toBasetype()->ty
!= Tsarray
) // %%
3314 e
= irs
->maybeMakeTemp(e
);
3315 DECL_INITIAL(v
->toSymbol()->Stree
) = irs
->arrayLength(e
, t
);
3321 ArrayScope::finish(tree e
)
3325 Symbol
* s
= v
->toSymbol();
3327 if (TREE_CODE(t
) == VAR_DECL
)
3330 if (s
->SclosureField
)
3331 return irs
->compound( irs
->vmodify(irs
->var(v
),
3332 DECL_INITIAL(t
) ), e
);
3335 return gen
.binding(v
->toSymbol()->Stree
, e
);
3343 FieldVisitor::visit(AggregateDeclaration
* decl
)
3345 ClassDeclaration
* class_decl
= decl
->isClassDeclaration();
3347 if (class_decl
&& class_decl
->baseClass
)
3348 FieldVisitor::visit(class_decl
->baseClass
);
3350 doFields(& decl
->fields
, decl
);
3352 if (class_decl
&& class_decl
->vtblInterfaces
)
3353 doInterfaces(class_decl
->vtblInterfaces
, decl
);