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"
25 #include "d-codegen.h"
27 static ListMaker bi_fn_list
;
29 // Necessary for built-in struct types
30 static Array builtin_converted_types
;
31 static Array builtin_converted_decls
;
33 static Type
* gcc_type_to_d_type(tree t
);
35 Type
* d_gcc_builtin_va_list_d_type
;
38 d_bi_init(int nt
, int nb
)
40 // assumes va_list_type_node already built
41 d_gcc_builtin_va_list_d_type
= gcc_type_to_d_type(va_list_type_node
);
42 if (! d_gcc_builtin_va_list_d_type
) {
43 // fallback to array of byte of the same size?
44 error("cannot represent built in va_list type in D");
47 if (! d_gcc_builtin_va_list_d_type
->ctype
)
48 d_gcc_builtin_va_list_d_type
->toCtype();
52 Set ctype directly for complex types to save toCtype() the work.
53 For others, it is not useful or, in the cast of (C char) -> (D char),
54 will cause errors. This also means char* ...
56 NOTE: We cannot always use type->pointerTo (in V2, at least) because
57 (explanation TBD -- see TypeFunction::semantic and
58 TypePointer::semantic: {deco = NULL;} .)
62 gcc_type_to_d_type(tree t
)
65 switch (TREE_CODE(t
)) {
67 // Check for strings first. There are currently no 'char' arguments
68 // for built-in functions, so this is all that needs to be done for
70 if (TYPE_MAIN_VARIANT(TREE_TYPE(t
)) == char_type_node
)
71 return Type::tchar
->pointerTo();
72 d
= gcc_type_to_d_type(TREE_TYPE(t
));
75 if (d
->ty
== Tfunction
)
76 return new TypePointer(d
);
78 return d
->pointerTo();
82 d
= gcc_type_to_d_type(TREE_TYPE(t
));
84 // Want to assign ctype directly so that the REFERENCE_TYPE
85 // code can be turned into an InOut argument below. Can't use
86 // pointerTo(), because that Type is shared.
87 d
= new TypePointer(d
);
94 unsigned sz
= tree_low_cst( TYPE_SIZE_UNIT( t
), 1 );
95 bool unsgn
= TREE_UNSIGNED( t
);
97 // This search assumes that integer types come before char and bit...
98 for (int i
= 0; i
< (int) TMAX
; i
++) {
100 if (d
&& d
->isintegral() && d
->size() == sz
&&
101 (d
->isunsigned()?true:false) == unsgn
) {
109 // Double and long double may be the same size
110 if (t
== double_type_node
)
111 return Type::tfloat64
;
112 else if (t
== long_double_type_node
)
113 return Type::tfloat80
;
115 unsigned sz
= tree_low_cst( TYPE_SIZE_UNIT( t
), 1 );
116 for (int i
= 0; i
< (int) TMAX
; i
++) {
118 if (d
&& d
->isfloating() && ! d
->iscomplex() && ! d
->isimaginary() &&
127 unsigned sz
= tree_low_cst( TYPE_SIZE_UNIT( t
), 1 );
128 for (int i
= 0; i
< (int) TMAX
; i
++) {
130 if (d
&& d
->iscomplex() && d
->size() == sz
) {
139 d
= gcc_type_to_d_type(TREE_TYPE(t
));
141 tree index
= TYPE_DOMAIN (t
);
142 tree ub
= TYPE_MAX_VALUE (index
);
143 tree lb
= TYPE_MIN_VALUE (index
);
145 = size_binop (PLUS_EXPR
, size_one_node
,
147 fold (build (MINUS_EXPR
,
150 d
= new TypeSArray(d
,
151 new IntegerExp(0, gen
.getTargetSizeConst(length
),
159 for (unsigned i
= 0; i
< builtin_converted_types
.dim
; i
+= 2)
161 tree ti
= (tree
) builtin_converted_types
.data
[i
];
163 return (Type
*) builtin_converted_types
.data
[i
+ 1];
171 name
= IDENTIFIER_POINTER( DECL_NAME( TYPE_NAME( t
)));
174 snprintf(name_buf
, sizeof(name_buf
), "__bi_type_%d", ++serial
);
178 StructDeclaration
* sd
= new StructDeclaration(0, Lexer::idPool(name
));
179 /* The gcc.builtins module may not exist yet, so cannot set
180 sd->parent here. If it is va_list, the parent needs to
181 be set to the object module which will not exist when
183 sd
->structsize
= int_size_in_bytes( t
);
184 sd
->alignsize
= TYPE_ALIGN_UNIT( t
);
187 d
= new TypeStruct(sd
);
189 sd
->handle
= new TypePointer(d
);
191 /* Does not seem necessary to convert fields, but the
192 members field must be non-null for the above size
194 sd
->members
= new Array
;
198 builtin_converted_types
.push(t
);
199 builtin_converted_types
.push(d
);
200 builtin_converted_decls
.push(sd
);
205 Type
* ret
= gcc_type_to_d_type(TREE_TYPE(t
));
209 tree t_arg_types
= TYPE_ARG_TYPES(t
);
210 int varargs
= t_arg_types
!= NULL_TREE
;
211 Arguments
* args
= new Arguments
;
212 args
->reserve(list_length(t_arg_types
));
213 for (tree tl
= t_arg_types
; tl
!= NULL_TREE
; tl
= TREE_CHAIN(tl
))
215 tree ta
= TREE_VALUE(tl
);
216 if (ta
!= void_type_node
)
220 if ( TREE_CODE( ta
) == REFERENCE_TYPE
)
222 ta
= TREE_TYPE( ta
);
226 Type
* d_arg_type
= gcc_type_to_d_type(ta
);
229 args
->push(new Argument(io
, d_arg_type
, NULL
, NULL
));
234 d
= new TypeFunction(args
, ret
, varargs
, LINKc
);
247 d_bi_builtin_func(tree decl
)
249 bi_fn_list
.cons(NULL_TREE
, decl
);
255 // std.stdarg is different: it expects pointer types (i.e. _argptr)
257 We can make it work fine as long as the argument to va_varg is _argptr,
258 we just call va_arg on the hidden va_list. As long _argptr is not
259 otherwise modified, it will work. */
262 d_gcc_magic_stdarg_module(Module
*m
, bool is_c_std_arg
)
264 Array
* members
= m
->members
;
265 Identifier
* id
= Lexer::idPool("va_arg");
266 Identifier
* id_start
= Lexer::idPool("va_start");
267 for (unsigned i
= 0; i
< members
->dim
; i
++) {
268 TemplateDeclaration
* td
=
269 ((Dsymbol
*) members
->data
[i
])->isTemplateDeclaration();
271 if (td
->ident
== id
) {
273 IRState::setCStdArgArg(td
);
275 IRState::setStdArg(td
);
276 } else if (td
->ident
== id_start
&& is_c_std_arg
) {
277 IRState::setCStdArgStart(td
);
281 if ( TREE_CODE( va_list_type_node
) == ARRAY_TYPE
) {
282 /* For GCC, a va_list can be an array. D static arrays are
283 automatically passed by reference, but the 'inout'
284 modifier is not allowed. */
286 for (unsigned j
= 0; j
< td
->members
->dim
; j
++) {
287 FuncDeclaration
* fd
=
288 ((Dsymbol
*) td
->members
->data
[j
])->isFuncDeclaration();
289 if (fd
&& (fd
->ident
== id
|| fd
->ident
== id_start
)) {
292 // Should have nice error message instead of ICE in case some tries
293 // to tweak the file.
294 assert( ! fd
->parameters
);
295 tf
= (TypeFunction
*) fd
->type
;
296 assert( tf
->ty
== Tfunction
&&
297 tf
->parameters
&& tf
->parameters
->dim
>= 1 );
298 ((Argument
*) tf
->parameters
->data
[0])->storageClass
&= ~(STCin
|STCout
|STCref
);
299 ((Argument
*) tf
->parameters
->data
[0])->storageClass
|= STCin
;
308 d_gcc_magic_builtins_module(Module
*m
)
310 Array
* funcs
= new Array
;
312 for (tree n
= bi_fn_list
.head
; n
; n
= TREE_CHAIN(n
))
314 tree decl
= TREE_VALUE(n
);
315 const char * name
= IDENTIFIER_POINTER(DECL_NAME(decl
));
316 TypeFunction
* dtf
= (TypeFunction
*) gcc_type_to_d_type(TREE_TYPE(decl
));
319 //warning("cannot create built in function type for %s", name);
322 if (dtf
->parameters
&& dtf
->parameters
->dim
== 0 && dtf
->varargs
)
324 //warning("one-arg va problem: %s", name);
327 FuncDeclaration
* func
= new FuncDeclaration(0, 0,
328 Lexer::idPool(name
), STCextern
, dtf
);
329 func
->isym
= new Symbol
;
330 func
->isym
->Stree
= decl
;
335 for (unsigned i
= 0; i
< builtin_converted_decls
.dim
; ++i
)
337 Dsymbol
* sym
= (Dsymbol
*) builtin_converted_decls
.data
[i
];
339 /* va_list is a pain. It can be referenced without importing
340 gcc.builtins so it really needs to go in the object module. */
342 Declaration
* decl
= sym
->isDeclaration();
343 if (! decl
|| decl
->type
!= d_gcc_builtin_va_list_d_type
) {
345 /* Currently, there is no need to run semantic, but we do
346 want to output inits, etc. */
352 Type
* d
= gcc_type_to_d_type(va_list_type_node
);
354 funcs
->push( new AliasDeclaration(0,
355 Lexer::idPool("__builtin_va_list"), d
) );
358 /* Provide access to target-specific integer types. */
360 d
= gcc_type_to_d_type(long_integer_type_node
);
362 funcs
->push( new AliasDeclaration(0,
363 Lexer::idPool("__builtin_Clong"), d
) );
364 d
= gcc_type_to_d_type(long_unsigned_type_node
);
366 funcs
->push( new AliasDeclaration(0,
367 Lexer::idPool("__builtin_Culong"), d
) );
368 d
= gcc_type_to_d_type(d_type_for_mode(word_mode
, 0));
370 funcs
->push( new AliasDeclaration(0,
371 Lexer::idPool("__builtin_machine_int"), d
) );
372 d
= gcc_type_to_d_type(d_type_for_mode(word_mode
, 1));
374 funcs
->push( new AliasDeclaration(0,
375 Lexer::idPool("__builtin_machine_uint"), d
) );
376 d
= gcc_type_to_d_type(d_type_for_mode(ptr_mode
, 0));
378 funcs
->push( new AliasDeclaration(0,
379 Lexer::idPool("__builtin_pointer_int"), d
) );
380 d
= gcc_type_to_d_type(d_type_for_mode(ptr_mode
, 1));
382 funcs
->push( new AliasDeclaration(0,
383 Lexer::idPool("__builtin_pointer_uint"), d
) );
385 m
->members
->push( new LinkDeclaration(LINKc
, funcs
) );
389 void d_gcc_magic_module(Module
*m
)
391 ModuleDeclaration
* md
= m
->md
;
392 if (md
&& md
->packages
&& md
->id
) {
393 if (md
->packages
->dim
== 1 &&
394 ! strcmp( ((Identifier
*) md
->packages
->data
[0])->string
, "gcc" ) &&
395 ! strcmp( md
->id
->string
, "builtins" )) {
396 d_gcc_magic_builtins_module(m
);
397 } else if (md
->packages
->dim
>= 1 &&
398 ! strcmp( ((Identifier
*) md
->packages
->data
[0])->string
, "std" )) {
400 if (! strcmp( md
->id
->string
, "stdarg" )) {
401 if (md
->packages
->dim
== 1) {
402 d_gcc_magic_stdarg_module(m
, false);
403 } else if (md
->packages
->dim
== 2 &&
404 ! strcmp( ((Identifier
*) md
->packages
->data
[1])->string
, "c" )) {
405 d_gcc_magic_stdarg_module(m
, true);
407 } else if (! strcmp( md
->id
->string
, "intrinsic") &&
408 md
->packages
->dim
== 1) {
409 IRState::setIntrinsicModule(m
);