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 #ifndef GCC_DCMPLR_CODEGEN_H
20 #define GCC_DCMPLR_CODEGEN_H
22 #include "d-irstate.h"
24 typedef integer_t xdmd_integer_t
;
26 #include "d-objfile.h"
39 //LIBCALL_NEWARRAYMIT,
46 LIBCALL_CALLFINALIZER
,
47 LIBCALL_CALLINTERFACEFINALIZER
,
48 LIBCALL_ARRAYSETLENGTHT
,
49 LIBCALL_ARRAYSETLENGTHIT
,
51 LIBCALL_INTERFACE_CAST
,
69 //LIBCALL_ARRAYAPPENDCT,
70 LIBCALL_ARRAYAPPENDCTP
,
74 LIBCALL_ARRAYSETASSIGN
,
79 LIBCALL_CRITICALENTER
,
82 LIBCALL_SWITCH_STRING
,
83 LIBCALL_SWITCH_USTRING
,
84 LIBCALL_SWITCH_DSTRING
,
85 LIBCALL_ASSOCARRAYLITERALTP
,
100 // Code generation routines should be in a separate namespace, but so many
101 // routines need a reference to an IRState to expand Expressions. Solution
102 // is to make IRState the code generation namespace with the actual IR state
103 // routines as a mixin. There is still the global 'gen' which can be used when
104 // it is known the full function IR state is not needed. Also a lot of routines
105 // are static (don't need IR state or expand Expressions), but are still called
108 // Functions without a verb create trees
109 // Functions with 'do' affect the current instruction stream (or output assembler code.)
110 // functions with other names are for attribute manipulate, etc.
112 struct IRState
: IRBase
115 INTRINSIC_BSF
, INTRINSIC_BSR
,
116 INTRINSIC_BT
, INTRINSIC_BTC
, INTRINSIC_BTR
, INTRINSIC_BTS
,
118 INTRINSIC_INP
, INTRINSIC_INPW
, INTRINSIC_INPL
,
119 INTRINSIC_OUTP
, INTRINSIC_OUTPW
, INTRINSIC_OUTPL
,
120 INTRINSIC_STD_VA_ARG
,
122 INTRINSIC_C_VA_START
,
126 static tree
declContext(Dsymbol
* d_sym
);
128 // ** Local variables
129 void emitLocalVar(VarDeclaration
* v
, bool no_init
= false);
130 tree
localVar(tree t_type
);
131 tree
localVar(Type
* e_type
) { return localVar(e_type
->toCtype()); }
132 tree
exprVar(tree t_type
);
133 tree
maybeExprVar(tree exp
, tree
* out_var
);
134 void expandDecl(tree t_decl
);
137 tree
var(VarDeclaration
* v
);
139 tree
var(VarDeclaration
* v
) { return v
->toSymbol()->Stree
; }
142 // ** Type conversion
144 // 'convertTo' just to give it a different name from the extern "C" convert
145 tree
convertTo(Expression
* exp
, Type
* target_type
);
146 tree
convertTo(tree exp
, Type
* exp_type
, Type
* target_type
);
148 tree
convertForAssignment(Expression
* exp
, Type
* target_type
);
149 tree
convertForAssignment(tree exp_tree
, Type
* exp_type
, Type
* target_type
);
151 tree
convertForArgument(Expression
* exp
, Argument
* arg
);
152 tree
convertForCondition(Expression
* exp
) {
153 return convertForCondition(exp
->toElem(this), exp
->type
); }
154 tree
convertForCondition(tree exp_tree
, Type
* exp_type
);
155 tree
toDArray(Expression
* exp
);
156 static bool typesSame(Type
* t1
, Type
* t2
) {
158 return t1
->mutableOf()->equals(t2
->mutableOf());
160 return t1
->equals(t2
);
163 static bool typesCompatible(Type
* t1
, Type
* t2
) {
165 return t1
->implicitConvTo(t2
) >= MATCHconst
;
167 return t1
->equals(t2
);
172 // ** Type management
173 static Type
* getDType(tree t
) {
174 // %% TODO: assert that its a type node..
175 struct lang_type
* l
= TYPE_LANG_SPECIFIC( t
);
176 return l
? l
->d_type
: 0;
179 static Type
* getObjectType() {
180 return ClassDeclaration::object
->type
;
183 // Routines to handle variables that are references.
184 static bool isDeclarationReferenceType(Declaration
* decl
);
185 static tree
trueDeclarationType(Declaration
* decl
);
186 static bool isArgumentReferenceType(Argument
* arg
);
187 static tree
trueArgumentType(Argument
* arg
);
189 static tree
arrayType(Type
* d_type
, uinteger_t size
) // %% use of integer_t
190 { return arrayType(d_type
->toCtype(), size
); }
191 static tree
arrayType(tree type_node
, uinteger_t size
);
193 // Can't call this until common types have been built
194 static bool haveLongDouble() {
195 return TYPE_MODE(long_double_type_node
) != TYPE_MODE(double_type_node
);
198 static tree
addTypeAttribute(tree type
, const char * attrname
, tree value
= NULL_TREE
);
199 static void addDeclAttribute(tree type
, const char * attrname
, tree value
= NULL_TREE
);
200 static tree
attributes(Expressions
* in_attrs
);
202 // ** Simple constants
204 static tree
nullPointer() { return d_null_pointer
; }
205 static tree
integerConstant(xdmd_integer_t value
, tree type
= 0);
206 static tree
integerConstant(xdmd_integer_t value
, Type
* type
) {
207 return integerConstant(value
, type
->toCtype());
210 static tree
floatConstant(const real_t
& value
, TypeBasic
* target_type
);
212 static xdmd_integer_t
hwi2toli(HOST_WIDE_INT low
, HOST_WIDE_INT high
);
214 // ** Routines for built in structured types
216 static tree
realPart(tree c
);
217 static tree
imagPart(tree c
);
220 static tree
darrayPtrRef(tree exp
);
221 tree
darrayPtrRef(Expression
* e
) { return darrayPtrRef(e
->toElem(this)); }
222 static tree
darrayLenRef(tree exp
);
224 static tree
darrayVal(tree type
, tree len
, tree data
);
225 // data may be NULL for a null pointer value
226 static tree
darrayVal(tree type
, uinteger_t len
, tree data
);
227 static tree
darrayVal(Type
* type
, uinteger_t len
, tree data
) {
228 return darrayVal(type
->toCtype(), len
, data
);
230 static tree
darrayString(const char * str
);
232 static char * hostToTargetString(char * str
, size_t length
, unsigned unit_size
);
234 // Length of either a static or dynamic array
235 tree
arrayLength(Expression
* exp
)
236 { return arrayLength(exp
->toElem(this), exp
->type
); }
237 static tree
arrayLength(tree exp
, Type
* exp_type
);
240 static tree
delegateMethodRef(tree exp
);
241 static tree
delegateObjectRef(tree exp
);
242 static tree
delegateVal(tree method_exp
, tree object_exp
, Type
* d_type
);
243 // These are for references to nested functions/methods as opposed to a variable of
245 tree
methodCallExpr(tree callee
, tree object
, Type
* d_type
) {
246 tree t
= delegateVal(callee
, object
, d_type
);
247 D_IS_METHOD_CALL_EXPR( t
) = 1;
250 void extractMethodCallExpr(tree mcr
, tree
& callee_out
, tree
& object_out
);
251 tree
objectInstanceMethod(Expression
* obj_exp
, FuncDeclaration
* func
, Type
* d_type
);
253 static tree
twoFieldType(tree rec_type
, tree ft1
, tree ft2
, Type
* d_type
= 0, const char * n1
= "_a", const char * n2
= "_b");
254 static tree
twoFieldType(Type
* ft1
, Type
* ft2
, Type
* d_type
= 0, const char * n1
= "_a", const char * n2
= "_b");
255 static tree
twoFieldCtor(tree rec_type
, tree f1
, tree f2
, int storage_class
= 0);
257 // ** Temporaries (currently just SAVE_EXPRs)
259 // Create a SAVE_EXPR if 't' might have unwanted side effects if referenced
260 // more than once in an expression.
261 tree
maybeMakeTemp(tree t
);
263 // Return true if t can be evaluated multiple times (i.e., in a loop body)
264 // without unwanted side effects. This is a stronger test than
265 // the one used for maybeMakeTemp.
266 static bool isFreeOfSideEffects(tree t
);
268 // ** Various expressions
269 tree
toElemLvalue(Expression
* e
);
271 static tree
addressOf(tree exp
) {
274 d_mark_addressable(exp
);
276 // Gimplify doesn't like &(*(ptr-to-array-type)) with static arrays
277 if (TREE_CODE(exp
) == INDIRECT_REF
)
278 t
= nop(TREE_OPERAND(exp
, 0), build_pointer_type(TREE_TYPE(exp
)));
281 t
= build1(ADDR_EXPR
, build_pointer_type(TREE_TYPE(exp
)), exp
);
283 if (TREE_CODE( exp
) == FUNCTION_DECL
)
284 TREE_STATIC( t
) = 1;
288 static tree
addressOf(Dsymbol
*d
) {
289 return addressOf( d
->toSymbol()->Stree
); }
290 /* Cast exp (which should be a pointer) to TYPE* and then indirect. The
291 back-end requires this cast in many cases. */
292 static tree
indirect(tree exp
, tree type
) {
293 return build1(INDIRECT_REF
, type
,
294 nop(exp
, build_pointer_type(type
)));
296 static tree
indirect(tree exp
) {
297 return build1(INDIRECT_REF
, TREE_TYPE(TREE_TYPE(exp
)), exp
); }
298 static tree
vmodify(tree dst
, tree src
) {
299 return build2(MODIFY_EXPR
, void_type_node
, dst
, src
); }
301 tree
pointerIntSum(Expression
* ptr_exp
, Expression
* idx_exp
) {
302 return pointerIntSum(ptr_exp
->toElem(this), idx_exp
->toElem(this)); }
303 tree
pointerIntSum(tree ptr_node
, tree idx_exp
);
305 static tree
nop(tree e
, tree t
) {
306 return build1(NOP_EXPR
, t
, e
); }
308 // DMD allows { void[] a; & a[3]; }
311 if ( VOID_TYPE_P( TREE_TYPE( TREE_TYPE( t
))) ) {
312 // ::warning("indexing array of void");
313 return convert(Type::tuns8
->pointerTo()->toCtype(), t
);
318 tree
boolOp(enum tree_code code
, tree a
, tree b
) {
319 return build(code
, boolean_type_node
, a
, b
);
322 tree
checkedIndex(Loc loc
, tree index
, tree upper_bound
, bool inclusive
);
323 tree
boundsCond(tree index
, tree upper_bound
, bool inclusive
);
325 tree
arrayElemRef(IndexExp
* aer_exp
, ArrayScope
* aryscp
);
328 static tree
binding(tree var_chain
, tree body
)
330 return build(BIND_EXPR
, TREE_TYPE(body
), var_chain
, body
, NULL_TREE
);
333 static tree
binding(tree var_chain
, tree body
);
336 static tree
compound(tree a
, tree b
, tree type
= 0) {
337 return build(COMPOUND_EXPR
, type
? type
: TREE_TYPE(b
), a
, b
);
339 tree
voidCompound(tree a
, tree b
) { return compound(a
, b
, void_type_node
); }
340 tree
maybeCompound(tree a
, tree b
) {
343 else if (b
== NULL_TREE
)
346 return build(COMPOUND_EXPR
, TREE_TYPE(b
), a
, b
);
348 tree
maybeVoidCompound(tree a
, tree b
) {
351 else if (b
== NULL_TREE
)
354 return build(COMPOUND_EXPR
, void_type_node
, a
, b
);
357 static tree
component(tree v
, tree f
)
360 return build(COMPONENT_REF
, TREE_TYPE(f
), v
, f
);
362 return build3(COMPONENT_REF
, TREE_TYPE(f
), v
, f
, NULL_TREE
);
366 // Giving error_mark_node a type allows for some assumptions about
367 // the type of an arbitrary expression.
368 static tree
errorMark(Type
* t
);
369 static bool isErrorMark(tree t
) {
370 return TREE_CODE(t
) == ERROR_MARK
||
371 (TREE_CODE(t
) == NOP_EXPR
&&
372 TREE_CODE( TREE_OPERAND(t
, 0) ) == ERROR_MARK
);
376 tree
call(Expression
* expr
, Array
* arguments
);
377 tree
call(FuncDeclaration
* func_decl
, Array
* args
);
378 tree
call(FuncDeclaration
* func_decl
, tree object
, Array
* args
);
379 tree
call(TypeFunction
*guess
, tree callable
, tree object
, Array
* arguments
);
381 tree
assertCall(Loc loc
, LibCall libcall
= LIBCALL_ASSERT
);
382 tree
assertCall(Loc loc
, Expression
* msg
);
383 static FuncDeclaration
* getLibCallDecl(LibCall lib_call
);
384 static void replaceLibCallDecl(FuncDeclaration
* d_decl
);
385 // This does not perform conversions on the arguments. This allows
386 // arbitrary data to be passed through varargs without going through the
387 // usual conversions.
388 static tree
libCall(LibCall lib_call
, unsigned n_args
, tree
*args
, tree force_result_type
= 0);
390 // GCC 3.3 does not set TREE_SIDE_EFFECTS call by default. GCC 3.4
391 // sets it depending on the const/pure attributes of the funcion
392 // and the SIDE_EFFECTS flags of the arguments.
393 static tree
buildCall(tree type
, tree callee
, tree args
) {
395 tree t
= build(CALL_EXPR
, type
, callee
, args
);
397 tree t
= build3(CALL_EXPR
, type
, callee
, args
, NULL_TREE
);
400 TREE_SIDE_EFFECTS(t
) = 1;
405 tree
assignValue(Expression
* e
, VarDeclaration
* v
);
407 static TemplateEmission emitTemplates
;
408 static bool splitDynArrayVarArgs
;
409 static bool useBuiltins
;
412 static bool warnSignCompare
;
415 static bool originalOmitFramePointer
;
418 tree
maybeExpandSpecialCall(tree call_exp
);
420 tree
floatMod(tree a
, tree b
, Type
* d_type
);
422 tree
typeinfoReference(Type
* t
);
424 target_size_t
getTargetSizeConst(tree t
);
426 static Module
* builtinsModule
;
427 static Module
* intrinsicModule
;
428 static TemplateDeclaration
* stdargTemplateDecl
;
429 static TemplateDeclaration
* cstdargStartTemplateDecl
;
430 static TemplateDeclaration
* cstdargArgTemplateDecl
;
431 static void setBuiltinsModule(Module
* mod
) { builtinsModule
= mod
; }
432 static void setIntrinsicModule(Module
* mod
) { intrinsicModule
= mod
; }
433 static void setStdArg(TemplateDeclaration
* td
) { stdargTemplateDecl
= td
; }
434 static void setCStdArgStart(TemplateDeclaration
* td
) { cstdargStartTemplateDecl
= td
; }
435 static void setCStdArgArg(TemplateDeclaration
* td
) { cstdargArgTemplateDecl
= td
; }
436 static bool maybeSetUpBuiltin(Declaration
* decl
);
438 static tree
functionPointer(FuncDeclaration
* func_decl
) { return addressOf(func_decl
); }
440 // Returns the D object that was thrown. Different from the generic exception pointer
441 static tree
exceptionObject();
443 static tree
label(Loc loc
, Identifier
* ident
= 0);
445 // Static chain for nested functions
446 tree
getFrameForFunction(FuncDeclaration
* f
);
447 tree
getFrameForNestedClass(ClassDeclaration
* c
);
449 void useClosure(FuncDeclaration
* f
, tree l
) {
453 void useParentClosure() {
456 _closureLink
= ((IRState
*)parent
)->_closureLink
;
457 closureFunc
= ((IRState
*)parent
)->closureFunc
;
460 tree
closureLink() { return _closureLink
; }
463 tree
getFrameForSymbol(Dsymbol
* nested_sym
);
465 tree
getClosureRef(FuncDeclaration
*outer_func
);
466 FuncDeclaration
* closureFunc
;
469 static FuncFrameInfo
* getFrameInfo(FuncDeclaration
*fd
);
472 static bool functionNeedsChain(FuncDeclaration
*f
);
474 // ** Instruction stream manipulation
475 void startCond(Statement
* stmt
, Expression
* e_cond
);
478 void startLoop(Statement
* stmt
);
480 void setContinueLabel(tree lbl
);
481 void exitIfFalse(tree t_cond
, bool is_top_cond
= 0);
482 void exitIfFalse(Expression
* e_cond
, bool is_top_cond
= 0) {
483 exitIfFalse(convertForCondition(e_cond
), is_top_cond
);
486 void startCase(Statement
* stmt
, tree t_cond
);
487 void doCase(tree t_value
, tree t_label
);
488 void endCase(tree t_cond
);
489 void continueLoop(Identifier
* ident
);
490 void exitLoop(Identifier
* ident
);
491 void startTry(Statement
* stmt
);
493 void startCatch(tree t_type
);
498 /*static*/ void doReturn(tree t_value
);
499 /*static*/ void doJump(Statement
* stmt
, tree t_label
);
500 void doExp(tree t
) { addExp(t
); }
501 void doExp(Expression
* e
) { doExp(e
->toElem(this)); } // %% should handle volatile...?
502 void doAsm(tree insn_tmpl
, tree outputs
, tree inputs
, tree clobbers
);
504 // ** Callback statement evalutation
506 static Array stmtExprList
;
508 tree
makeStmtExpr(Statement
* statement
);
509 static void retrieveStmtExpr(tree t
, Statement
** s_out
, IRState
** i_out
);
511 static void doLineNote(const Loc
& loc
) { ObjectFile::doLineNote(loc
); }
514 struct GlobalValues
{
518 ModuleInfo
* mi() { return ofile
->moduleInfo
; }
521 extern GlobalValues g
;
525 // Various helpers that need extra state
527 struct WrappedExp
: Expression
530 WrappedExp(Loc loc
, enum TOK op
, tree exp_node
, Type
* type
);
531 void toCBuffer(OutBuffer
*buf
);
532 elem
*toElem(IRState
*irs
);
538 ListMaker() : head(NULL_TREE
), ptail( & head
) { }
539 ListMaker(tree
* alt_head
) : head(NULL_TREE
), ptail( alt_head
) { }
540 void reserve(int i
) { }
541 void chain(tree t
) { *ptail
= t
; ptail
= & TREE_CHAIN(t
); }
542 void cons(tree p
, tree v
) {
543 *ptail
= tree_cons(p
,v
,NULL_TREE
);
544 ptail
= & TREE_CHAIN(*ptail
);
546 void cons(tree v
) { cons(NULL_TREE
, v
); }
550 typedef ListMaker CtorEltMaker
;
553 struct CtorEltMaker
{
554 VEC(constructor_elt
,gc
) *head
;
555 CtorEltMaker() : head(NULL
) { }
556 void reserve(int i
) { VEC_reserve(constructor_elt
,gc
,head
,i
); }
557 void cons(tree p
, tree v
) {
558 constructor_elt
* ce
;
559 ce
= VEC_safe_push(constructor_elt
,gc
,head
,NULL
);
563 void cons(tree v
) { cons(NULL_TREE
, v
); }
570 AggregateDeclaration
* aggDecl
;
571 FieldVisitor(AggregateDeclaration
* decl
) : aggDecl(decl
) { }
572 //virtual doField(VarDeclaration * field) = 0;
573 virtual void doFields(Array
* fields
, AggregateDeclaration
* agg
) = 0;
574 virtual void doInterfaces(Array
* bases
, AggregateDeclaration
* agg
) = 0;
575 void go() { visit(aggDecl
); }
576 void visit(AggregateDeclaration
* decl
);
579 class AggLayout
: public FieldVisitor
{
583 AggLayout(AggregateDeclaration
* ini_agg_decl
, tree ini_agg_type
) :
584 FieldVisitor(ini_agg_decl
),
585 aggType(ini_agg_type
),
586 fieldList(& TYPE_FIELDS( aggType
)) { }
587 void doFields(Array
* fields
, AggregateDeclaration
* agg
);
588 void doInterfaces(Array
* bases
, AggregateDeclaration
* agg
);
589 void addField(tree field_decl
, target_size_t offset
);
590 void finish(Expressions
* attrs
);
597 ArrayScope(IRState
* ini_irs
, VarDeclaration
* ini_v
, const Loc
& loc
);
598 tree
setArrayExp(tree e
, Type
* t
);
605 AddrOfExpr() { var
= NULL_TREE
; }
606 tree
set(IRState
* irs
, tree exp
) {
607 return irs
->addressOf( irs
->maybeExprVar(exp
, & var
) );
609 tree
finish(IRState
* irs
, tree e2
) {
610 return var
? irs
->binding(var
, e2
) : e2
;