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 // 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
);
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);
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);
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
);
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
);
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
650 IRState::toDArray(Expression
* exp
)
652 TY ty
= exp
->type
->toBasetype()->ty
;
655 val
= convertTo(exp
, exp
->type
->toBasetype()->nextOf()->arrayOf());
656 } else if (ty
== Tarray
) {
657 val
= exp
->toElem(this);
659 gcc_assert(ty
== Tsarray
|| ty
== Tarray
);
667 IRState::pointerIntSum(tree ptr_node
, tree idx_exp
)
669 tree result_type_node
= TREE_TYPE( ptr_node
);
670 tree intop
= idx_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
)));
690 if ( integer_zerop(intop
) )
693 return build(PLUS_EXPR
, result_type_node
, ptr_node
, intop
);
696 // Doesn't do some of the omptimizations in ::makeArrayElemRef
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
),
704 assertCall(loc
, LIBCALL_ARRAY_BOUNDS
));
711 // index must be wrapped in a SAVE_EXPR to prevent multiple evaluation...
713 IRState::boundsCond(tree index
, tree upper_bound
, bool inclusive
)
717 bound_check
= build(inclusive
? LE_EXPR
: LT_EXPR
, boolean_type_node
,
718 convert( d_unsigned_type(TREE_TYPE(index
)), index
),
721 if (! TREE_UNSIGNED( TREE_TYPE( index
))) {
722 bound_check
= build(TRUTH_ANDIF_EXPR
, boolean_type_node
, bound_check
,
724 build(GE_EXPR
, boolean_type_node
, index
, integer_zero_node
));
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
);
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
);
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
);
759 IRState::hwi2toli(HOST_WIDE_INT low
, HOST_WIDE_INT high
)
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
;
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
);
793 IRState::libCall(LibCall lib_call
, unsigned n_args
, tree
*args
, tree force_result_type
)
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
);
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
;
829 tree
IRState::errorMark(Type
* t
)
831 return nop(error_mark_node
, t
->toCtype());
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
;
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
;
868 if (fd
->isNested()) {
870 object
= getFrameForFunction(fd
);
872 // Pass fake argument for nested functions
873 object
= d_null_pointer
;
875 } else if (fd
->needThis()) {
876 expr
->error("need 'this' to access member %s", fd
->toChars());
877 object
= d_null_pointer
; // continue processing...
881 tf
= get_function_type(t
);
883 return call(tf
, callee
, object
, arguments
);
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
);
894 IRState::call(FuncDeclaration
* func_decl
, tree object
, Array
* args
)
896 return call((TypeFunction
*)func_decl
->type
, functionPointer(func_decl
),
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
);
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 */ {
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
;
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;
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
);
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
) );
984 actual_arg_tree
= actual_arg_exp
->toElem( this );
986 /* Not all targets support passing unpromoted types, so
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",
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",
1014 //"_aaIn", "_aaGet", "_aaGetRvalue", "_aaDel",
1015 "_aaInp", "_aaGetp", "_aaGetRvaluep", "_aaDelp",
1018 "_d_arraycatT", "_d_arraycatnT",
1020 /*"_d_arrayappendc", */"_d_arrayappendcTp",
1022 "_d_arrayassign", "_d_arrayctor", "_d_arraysetassign",
1025 "_d_monitorenter", "_d_monitorexit",
1026 "_d_criticalenter", "_d_criticalexit",
1028 "_d_switch_string", "_d_switch_ustring", "_d_switch_dstring",
1029 "_d_assocarrayliteralTp"
1036 static FuncDeclaration
* libcall_decls
[LIBCALL_count
];
1039 IRState::replaceLibCallDecl(FuncDeclaration
* d_decl
)
1041 if ( ! d_decl
->ident
)
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
1058 libcall_decls
[i
] = d_decl
;
1066 IRState::getLibCallDecl(LibCall lib_call
)
1068 FuncDeclaration
* decl
= libcall_decls
[lib_call
];
1071 bool varargs
= false;
1074 Type
* return_type
= Type::tvoid
;
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
);
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
);
1091 case LIBCALL_NEWCLASS
:
1092 arg_types
.push( ClassDeclaration::classinfo
->type
);
1093 return_type
= getObjectType();
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();
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
);
1109 case LIBCALL_ALLOCMEMORY
:
1110 arg_types
.push( Type::tsize_t
);
1111 return_type
= Type::tvoidptr
;
1113 case LIBCALL_DELCLASS
:
1114 case LIBCALL_DELINTERFACE
:
1115 arg_types
.push(Type::tvoid
->pointerTo());
1117 case LIBCALL_DELARRAY
:
1118 arg_types
.push(Type::tvoid
->arrayOf()->pointerTo());
1120 case LIBCALL_DELMEMORY
:
1121 arg_types
.push(Type::tvoid
->pointerTo()->pointerTo());
1123 case LIBCALL_CALLFINALIZER
:
1124 case LIBCALL_CALLINTERFACEFINALIZER
:
1125 arg_types
.push(Type::tvoid
->pointerTo());
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();
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();
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
;
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
;
1154 // case LIBCALL_AAIN:
1155 // case LIBCALL_AAGET:
1156 // case LIBCALL_AAGETRVALUE:
1157 // case LIBCALL_AADEL:
1160 case LIBCALL_AAGETP
:
1161 case LIBCALL_AAGETRVALUEP
:
1162 case LIBCALL_AADELP
:
1164 static Type
* aa_type
= NULL
;
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
;
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());
1189 case LIBCALL_AAGETP
:
1190 case LIBCALL_AAGETRVALUEP
:
1191 return_type
= Type::tvoid
->pointerTo();
1193 case LIBCALL_AADELP
:
1194 return_type
= Type::tvoid
;
1201 case LIBCALL_ARRAYCAST
:
1202 t
= Type::tvoid
->arrayOf();
1203 arg_types
.push(Type::tsize_t
);
1204 arg_types
.push(Type::tsize_t
);
1208 case LIBCALL_ARRAYCOPY
:
1209 t
= Type::tvoid
->arrayOf();
1210 arg_types
.push(Type::tsize_t
);
1215 case LIBCALL_ARRAYCATT
:
1216 arg_types
.push(Type::typeinfo
->type
);
1217 t
= Type::tvoid
->arrayOf();
1222 case LIBCALL_ARRAYCATNT
:
1223 arg_types
.push(Type::typeinfo
->type
);
1224 arg_types
.push(Type::tuns32
); // Currently 'uint', even if 64-bit
1226 return_type
= Type::tvoid
->arrayOf();
1228 case LIBCALL_ARRAYAPPENDT
:
1229 arg_types
.push(Type::typeinfo
->type
);
1230 t
= Type::tuns8
->arrayOf();
1231 arg_types
.push(t
->pointerTo());
1233 return_type
= Type::tvoid
->arrayOf();
1235 // case LIBCALL_ARRAYAPPENDCT:
1236 case LIBCALL_ARRAYAPPENDCTP
:
1237 arg_types
.push(Type::typeinfo
->type
);
1238 t
= Type::tuns8
->arrayOf();
1240 arg_types
.push(Type::tvoid
->pointerTo()); // varargs = true;
1241 return_type
= Type::tvoid
->arrayOf();
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();
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();
1259 case LIBCALL_MONITORENTER
:
1260 case LIBCALL_MONITOREXIT
:
1262 case LIBCALL_INVARIANT
:
1263 arg_types
.push(getObjectType());
1265 case LIBCALL_CRITICALENTER
:
1266 case LIBCALL_CRITICALEXIT
:
1267 arg_types
.push(Type::tvoid
->pointerTo());
1269 case LIBCALL_SWITCH_USTRING
:
1271 goto do_switch_string
;
1272 case LIBCALL_SWITCH_DSTRING
:
1274 goto do_switch_string
;
1275 case LIBCALL_SWITCH_STRING
:
1279 arg_types
.push(t
->arrayOf());
1281 return_type
= Type::tint32
;
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();
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
1295 arg_types
.push(Type::tvoid
->pointerTo());
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
],
1310 tf
->parameters
= args
;
1312 libcall_decls
[lib_call
] = decl
;
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
);
1327 tree
IRState::maybeExpandSpecialCall(tree call_exp
)
1329 // More code duplication from C
1331 tree callee
= TREE_OPERAND(call_exp
, 0);
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
1340 } else if (DECL_BUILT_IN_CLASS(callee
) == BUILT_IN_NORMAL
) {
1341 switch (DECL_FUNCTION_CODE(callee
)) {
1344 case BUILT_IN_LLABS
:
1345 case BUILT_IN_IMAXABS
:
1346 /* The above are required for both 3.4. Not sure about later
1348 /* OLDOLDOLD below supposedly for 3.3 only */
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:
1361 } else if (DECL_BUILT_IN_CLASS(callee
) == BUILT_IN_FRONTEND
) {
1362 Intrinsic intrinsic
= (Intrinsic
) DECL_FUNCTION_CODE(callee
);
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);
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
));
1402 tree type2
= d_type_promotes_to(type
);
1403 t
= build1(VA_ARG_EXPR
, type2
, t
);
1405 // silently convert promoted type...
1406 t
= d_convert_basic(type
, t
);
1410 case INTRINSIC_C_VA_START
:
1413 // signature is (inout va_list), but VA_ARG_EXPR expects the
1415 if ( TREE_CODE( t ) == ADDR_EXPR ) {
1416 t = TREE_OPERAND(t, 0);
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
);
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
)));
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)!!
1463 // %% types should be correct, but should still check..
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));
1479 case INTRINSIC_BSWAP
:
1480 #if defined(TARGET_386)
1485 case INTRINSIC_INPW
:
1486 case INTRINSIC_INPL
:
1487 case INTRINSIC_OUTP
:
1488 case INTRINSIC_OUTPW
:
1489 case INTRINSIC_OUTPL
:
1492 ::error("Port I/O intrinsic '%s' is only available on ix86 targets",
1493 IDENTIFIER_POINTER(DECL_NAME(callee
)));
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
;
1515 gcc_assert(! base_type
->next
->isbit());
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
) {
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
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
);
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?
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
);
1577 ptr_exp
= e1
->toElem( this );
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
)));
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
);
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
);
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
;
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
;
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
;
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
);
1647 assert( POINTER_TYPE_P( TREE_TYPE( data
)));
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
;
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
));
1675 IRState::hostToTargetString(char * str
, size_t length
, unsigned unit_size
)
1679 assert(unit_size
== 2 || unit_size
== 4);
1683 # ifdef HOST_WORDS_BIG_ENDIAN
1684 flip
= (bool) ! BYTES_BIG_ENDIAN
;
1686 flip
= (bool) BYTES_BIG_ENDIAN
;
1689 # if WORDS_BIG_ENDIAN
1690 flip
= (bool) ! BYTES_BIG_ENDIAN
;
1692 flip
= (bool) BYTES_BIG_ENDIAN
;
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
;
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];
1722 IRState::arrayLength(tree exp
, Type
* exp_type
)
1724 Type
* base_type
= exp_type
->toBasetype();
1725 switch (base_type
->ty
) {
1727 return size_int( ((TypeSArray
*) base_type
)->dim
->toUInteger() );
1729 return darrayLenRef(exp
);
1731 ::error("can't determine the length of a %s", exp_type
->toChars());
1732 return error_mark_node
;
1737 IRState::floatMod(tree a
, tree b
, Type
* d_type
)
1739 enum built_in_function fn
;
1740 switch (d_type
->toBasetype()->ty
) {
1743 fn
= BUILT_IN_FMODF
;
1752 if (! haveLongDouble())
1753 goto no_long_double
;
1754 fn
= BUILT_IN_FMODL
;
1757 ::error("tried to perform floating-point modulo division on %s",
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
1765 return buildCall(TREE_TYPE(TREE_TYPE(decl
)),
1767 tree_cons(NULL_TREE
, a
,
1768 tree_cons(NULL_TREE
, b
, NULL_TREE
)));
1772 IRState::typeinfoReference(Type
* t
)
1774 tree ti_ref
= t
->getInternalTypeInfo(NULL
)->toElem(this);
1775 assert( POINTER_TYPE_P( TREE_TYPE( ti_ref
)) );
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
;
1791 result
= tree_low_cst( t
, 1 );
1796 // struct delegate {
1797 // void * frame_or_object;
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
);
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
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.
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
;
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
;
1854 IRState::extractMethodCallExpr(tree mcr
, tree
& callee_out
, tree
& object_out
) {
1855 assert( D_IS_METHOD_CALL_EXPR( mcr
));
1857 tree elts
= CONSTRUCTOR_ELTS( mcr
);
1858 object_out
= TREE_VALUE( elts
);
1859 callee_out
= TREE_VALUE( TREE_CHAIN( elts
));
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
;
1868 IRState::objectInstanceMethod(Expression
* obj_exp
, FuncDeclaration
* func
, Type
* d_type
)
1870 Type
* obj_type
= obj_exp
->type
->toBasetype();
1871 if (func
->isThis()) {
1875 // DotTypeExp cannot be evaluated
1876 if (obj_exp
->op
== TOKdottype
) {
1878 this_expr
= ((DotTypeExp
*) obj_exp
)->e1
->toElem( this );
1879 } else if (obj_exp
->op
== TOKcast
&&
1880 ((CastExp
*) obj_exp
)->e1
->op
== TOKdottype
) {
1882 // see expression.c:"See if we need to adjust the 'this' pointer"
1883 this_expr
= ((DotTypeExp
*) ((CastExp
*) obj_exp
)->e1
)->e1
->toElem( this );
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
);
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
);
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
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);
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
);
1933 // Static method; ignore the object instance
1934 return addressOf(func
);
1940 IRState::realPart(tree c
) {
1941 return build1(REALPART_EXPR
, TREE_TYPE(TREE_TYPE(c
)), c
);
1944 IRState::imagPart(tree c
) {
1945 return build1(IMAGPART_EXPR
, TREE_TYPE(TREE_TYPE(c
)), c
);
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
);
1957 //return e->toElem(this);
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
);
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);
1988 // Create a record type from two field types
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
);
1996 IRState::twoFieldCtor(tree rec_type
, tree f1
, tree f2
, int storage_class
)
1998 tree ctor
= make_node( CONSTRUCTOR
);
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
);
2011 CONSTRUCTOR_ELTS( ctor
) = ce
.head
;
2016 // This could be made more lax to allow better CSE (?)
2018 needs_temp(tree t
) {
2019 // %%TODO: check for anything with TREE_SIDE_EFFECTS?
2020 switch (TREE_CODE(t
)) {
2030 case REFERENCE_EXPR
:
2032 /* This check is needed for 4.0. Without it, typeinfo.methodCall may not be
2034 return ! (DECL_P(TREE_OPERAND(t
, 0)));
2039 case NON_LVALUE_EXPR
:
2040 case VIEW_CONVERT_EXPR
:
2041 return needs_temp(TREE_OPERAND(t
, 0));
2047 TREE_CODE_CLASS(TREE_CODE(t
)) == tcc_constant
)
2049 TREE_CODE_CLASS(TREE_CODE(t
)) == 'c')
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
);
2066 IRState::maybeMakeTemp(tree t
)
2068 if (needs_temp(t
)) {
2069 if (TREE_CODE(TREE_TYPE(t
)) != ARRAY_TYPE
)
2070 return save_expr(t
);
2072 return stabilize_reference(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;
2084 IRState::maybeSetUpBuiltin(Declaration
* decl
)
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
[] = {
2096 "bt", "btc", "btr", "bts",
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
) {
2114 case INTRINSIC_BSWAP
:
2115 #if defined(TARGET_386)
2116 //have_intrinsic = true;
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;
2132 if (have_intrinsic
) {
2133 DECL_BUILT_IN_CLASS( t
) = BUILT_IN_FRONTEND
;
2134 DECL_FUNCTION_CODE( t
) = (built_in_function
) i
;
2141 ti
= dsym
->isTemplateInstance();
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
;
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
;
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
;
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
) {
2172 if ( decl
->isOut() || decl
->isRef() ||
2173 ( decl
->isParameter() && base_type
->ty
== Tsarray
) ) {
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();
2198 // These should match the Declaration versions above
2200 IRState::isArgumentReferenceType(Argument
* arg
)
2202 Type
* base_type
= arg
->type
->toBasetype();
2204 if ( base_type
->ty
== Treference
) {
2208 if ( (arg
->storageClass
& (STCout
| STCref
)) || base_type
->ty
== Tsarray
) {
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();
2231 IRState::arrayType(tree type_node
, uinteger_t size
)
2233 tree index_type_node
;
2235 index_type_node
= size_int( size
- 1 );
2236 index_type_node
= build_index_type(index_type_node
);
2238 // See c-decl.c grokdeclarator for zero-length arrays
2239 index_type_node
= build_range_type (sizetype
, size_zero_node
,
2243 tree array_type
= build_array_type(type_node
, index_type_node
);
2246 layout_type(array_type
);
2248 TYPE_SIZE(array_type
) = bitsize_zero_node
;
2249 TYPE_SIZE_UNIT(array_type
) = size_zero_node
;
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
2266 value
= tree_cons(NULL_TREE
, value
, NULL_TREE
);
2267 TYPE_ATTRIBUTES( type
) = tree_cons( get_identifier(attrname
), value
,
2268 TYPE_ATTRIBUTES( type
));
2273 IRState::addDeclAttribute(tree type
, const char * attrname
, tree value
)
2276 value
= tree_cons(NULL_TREE
, value
, NULL_TREE
);
2277 DECL_ATTRIBUTES( type
) = tree_cons( get_identifier(attrname
), value
,
2278 DECL_ATTRIBUTES( type
));
2282 IRState::attributes(Expressions
* in_attrs
)
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
;
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
;
2305 for (unsigned ai
= 0; ai
< c
->arguments
->dim
; ai
++) {
2306 Expression
* ae
= (Expression
*) c
->arguments
->data
[ai
];
2308 if (ae
->op
== TOKstring
&& ((StringExp
*) ae
)->sz
== 1)
2310 StringExp
* s
= (StringExp
*) ae
;
2311 aet
= build_string(s
->len
, (const char*) s
->string
);
2314 aet
= ae
->toElem(&gen
);
2324 out_attrs
.cons(get_identifier(ident_e
->ident
->string
), args
.head
);
2327 return out_attrs
.head
;
2331 IRState::integerConstant(xdmd_integer_t value
, tree type
) {
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);
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);
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
);
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);
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
);
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
;
2385 g
.ofile
->setDeclLoc(t_label
, loc
);
2390 IRState::getFrameForFunction(FuncDeclaration
* f
)
2393 return getFrameForSymbol(f
);
2396 // Should error on line that references f
2397 f
->error("nested function missing body");
2398 return d_null_pointer
;
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
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
);
2433 /* It's a class. NewExp::toElem has already determined its
2434 outer scope is not another class, so it must be a
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.
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.
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
;
2474 if (! nested_func
->isNested())
2475 goto cannot_access_frame
;
2476 while ( (o
= o
->toParent2()) )
2477 if ( (nested_func
= o
->isFuncDeclaration()) )
2479 } while (o
&& o
!= outer_func
);
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'
2492 if (getFrameInfo(outer_func
)->creates_closure
)
2493 return getClosureRef(outer_func
);
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
;
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
);
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
2518 isFuncNestedInFunc(FuncDeclaration
* fd
, FuncDeclaration
*fo
)
2525 AggregateDeclaration
* ad
;
2526 ClassDeclaration
* cd
;
2530 //fprintf(stderr, "%s is nested in %s\n", fd->toChars(), fo->toChars());
2533 else if (fd
->isNested())
2534 fd
= fd
->toParent2()->isFuncDeclaration();
2535 else if ( (ad
= fd
->isThis()) && (cd
= ad
->isClassDeclaration()) )
2538 while (cd
&& cd
->isNested())
2540 Dsymbol
* dsym
= cd
->toParent2();
2541 if ( (fd
= dsym
->isFuncDeclaration()) )
2544 cd
= dsym
->isClassDeclaration();
2551 //fprintf(stderr, "%s is NOT nested in %s\n", fd->toChars(), fo->toChars());
2556 IRState::getFrameInfo(FuncDeclaration
*fd
)
2558 Symbol
* fds
= fd
->toSymbol();
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;
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
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
;
2588 AggregateDeclaration
* ad
;
2589 ClassDeclaration
* cd
;
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;
2610 ff
= ff
->toParent2()->isFuncDeclaration();
2611 else if ( (ad
= ff
->isThis()) && (cd
= ad
->isClassDeclaration()) )
2614 while (cd
&& cd
->isNested())
2616 Dsymbol
* dsym
= cd
->toParent2();
2617 if ( (ff
= dsym
->isFuncDeclaration()) )
2620 cd
= dsym
->isClassDeclaration();
2631 /*fprintf(stderr, "%s %s\n", ffi->creates_closure ? "YES" : "NO ",
2637 // Return a pointer to the closure block of outer_func
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
);
2656 fd
= fd
->toParent2()->isFuncDeclaration();
2658 else if ( (ad
= fd
->isThis()) && (cd
= ad
->isClassDeclaration()) )
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()) )
2679 cd
= dsym
->isClassDeclaration();
2686 if (fd
== outer_func
)
2688 tree closure_rec
= getFrameInfo(outer_func
)->closure_rec
;
2689 result
= nop(result
, build_pointer_type(closure_rec
));
2694 func
->error("cannot access frame of %s", outer_func
->toChars());
2695 return d_null_pointer
;
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.)
2706 IRState::functionNeedsChain(FuncDeclaration
*f
)
2709 ClassDeclaration
* a
;
2710 FuncDeclaration
*pf
= 0;
2714 && ! getFrameInfo(f
->toParent2()->isFuncDeclaration())->creates_closure
2723 while ( s
&& (a
= s
->isClassDeclaration()) && a
->isNested() ) {
2725 if ( (pf
= s
->isFuncDeclaration())
2727 && ! getFrameInfo(pf
)->creates_closure
2736 IRState::toElemLvalue(Expression
* e
)
2739 if (e->op == TOKcast)
2740 fprintf(stderr, "IRState::toElemLvalue TOKcast\n");
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();
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(),
2762 this->libCall(LIBCALL_AAGETP
, 4, args
, type
->pointerTo()->toCtype())));
2765 return e
->toElem(this);
2772 IRState::startCond(Statement
* stmt
, Expression
* e_cond
) {
2774 g
.ofile
->doLineNote(stmt
->loc
);
2775 expand_start_cond( convertForCondition( e_cond
), 0 );
2779 IRState::startElse() { expand_start_else(); }
2782 IRState::endCond() { expand_end_cond(); }
2785 IRState::startLoop(Statement
* stmt
) {
2786 beginFlow(stmt
, expand_start_loop_continue_elsewhere(1));
2790 IRState::continueHere()
2792 Flow
* f
= currentFlow();
2793 if (f
->overrideContinueLabel
)
2794 doLabel(f
->overrideContinueLabel
);
2796 expand_loop_continue_here();
2800 IRState::setContinueLabel(tree lbl
)
2802 currentFlow()->overrideContinueLabel
= lbl
;
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
);
2813 IRState::startCase(Statement
* stmt
, tree t_cond
)
2816 g
.ofile
->doLineNote(stmt
->loc
);
2817 expand_start_case( 1, t_cond
, TREE_TYPE( t_cond
), "switch statement" );
2818 beginFlow(stmt
, NULL
);
2822 IRState::doCase(tree t_value
, tree t_label
)
2825 // %% not the same convert that is in d-glue!!
2826 pushcase( t_value
, convert
, t_label
, & dummy
);
2830 IRState::endCase(tree t_cond
)
2832 expand_end_case( t_cond
);
2837 IRState::endLoop() {
2843 IRState::continueLoop(Identifier
* ident
) {
2844 Flow
* f
= getLoopForLabel( ident
, true );
2845 if (f
->overrideContinueLabel
)
2846 doJump(NULL
, f
->overrideContinueLabel
);
2848 expand_continue_loop( f
->loop
);
2852 IRState::exitLoop(Identifier
* ident
)
2855 Flow
* flow
= getLoopForLabel( ident
);
2857 expand_exit_loop( flow
->loop
);
2859 if (! flow
->exitLabel
)
2860 flow
->exitLabel
= label(flow
->statement
->loc
);
2861 expand_goto( flow
->exitLabel
);
2864 expand_exit_something();
2869 IRState::startTry(Statement
* stmt
)
2871 expand_eh_region_start();
2875 IRState::startCatches()
2877 expand_start_all_catch();
2881 IRState::startCatch(tree t_type
)
2883 expand_start_catch( t_type
);
2893 IRState::endCatches()
2895 expand_end_all_catch();
2899 IRState::startFinally()
2905 IRState::endFinally()
2911 IRState::doReturn(tree t_value
)
2914 expand_return(t_value
);
2916 expand_null_return();
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 ;
2925 g
.ofile
->doLineNote( stmt
->loc
);
2926 expand_goto( t_label
);
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);
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
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
;
2968 IRState::startElse()
2970 currentFlow()->trueBranch
= popStatementList();
2971 pushStatementList();
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
;
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
);
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
3000 IRState::continueHere() {
3001 doLabel(currentFlow()->continueLabel
);
3005 IRState::setContinueLabel(tree lbl
)
3007 currentFlow()->continueLabel
= lbl
;
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
)));
3017 IRState::startCase(Statement
* stmt
, tree t_cond
)
3019 Flow
* f
= beginFlow(stmt
);
3020 f
->condition
= t_cond
;
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
));
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
,
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
);
3051 IRState::continueLoop(Identifier
* ident
) {
3052 //doFlowLabel(stmt, ident, Continue);
3053 doJump(NULL
, getLoopForLabel(ident
, true)->continueLabel
);
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
);
3066 IRState::startTry(Statement
* stmt
)
3072 IRState::startCatches()
3074 currentFlow()->tryBody
= popStatementList();
3075 pushStatementList();
3079 IRState::startCatch(tree t_type
)
3081 currentFlow()->catchType
= t_type
;
3082 pushStatementList();
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
));
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
));
3107 IRState::startFinally()
3109 currentFlow()->tryBody
= popStatementList();
3110 pushStatementList();
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
));
3124 IRState::doReturn(tree t_value
)
3126 addExp(build1(RETURN_EXPR
, void_type_node
, t_value
));
3130 IRState::doJump(Statement
* stmt
, tree t_label
)
3133 g
.ofile
->doLineNote( stmt
->loc
);
3134 addExp(build1(GOTO_EXPR
, void_type_node
, t_label
));
3138 IRState::makeStmtExpr(Statement
* statement
)
3142 pushStatementList();
3143 statement
->toIR(this);
3144 t_list
= popStatementList();
3154 IRState::doAsm(tree insn_tmpl
, tree outputs
, tree inputs
, tree clobbers
)
3157 expand_asm_operands(insn_tmpl
, outputs
, inputs
, clobbers
, 1, input_location
);
3159 tree t
= d_build_asm_stmt(insn_tmpl
, outputs
, inputs
, clobbers
);
3160 ASM_VOLATILE_P( t
) = 1;
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
;
3173 WrappedExp::toCBuffer(OutBuffer
*buf
)
3175 buf
->printf("< wrapped exprission >");
3179 WrappedExp::toElem(IRState
*)
3185 void AggLayout::doFields(Array
* fields
, AggregateDeclaration
* agg
)
3187 bool inherited
= agg
!= this->aggDecl
;
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
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
)
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. */
3307 Symbol
* s
= v
->toSymbol();
3308 tree decl
= s
->Stree
;
3309 DECL_CONTEXT( decl
) = irs
->getLocalContext();
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
);
3328 ArrayScope::finish(tree e
)
3332 Symbol
* s
= v
->toSymbol();
3334 if (TREE_CODE(t
) == VAR_DECL
)
3337 if (s
->SclosureField
)
3338 return irs
->compound( irs
->vmodify(irs
->var(v
),
3339 DECL_INITIAL(t
) ), e
);
3342 return gen
.binding(v
->toSymbol()->Stree
, e
);
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
);