Support covariant maybe return types
[delight/core.git] / d-objfile.cc
blobf35198c03236a5e193681d355407538e90d54320
1 #include "d-gcc-includes.h"
2 #include "d-lang.h"
3 #include "d-codegen.h"
4 #include <math.h>
5 #include <limits.h>
6 #include "total.h"
7 #include "template.h"
8 #include "init.h"
9 #include "symbol.h"
10 #include "dt.h"
12 #if D_GCC_VER < 40
13 /* struct rtx was modified for c++; this macro from rtl.h needs to
14 be modified accordingly. */
15 #undef XEXP
16 #define XEXP(RTX, N) (RTL_CHECK2 (RTX, N, 'e', 'u').rt_rtx)
17 #endif
19 static tree dt2tree(dt_t * dt);
21 ModuleInfo * ObjectFile::moduleInfo;
22 Array ObjectFile::modules;
23 unsigned ObjectFile::moduleSearchIndex;
24 Array ObjectFile::deferredThunks;
25 Array ObjectFile::staticCtorList;
26 Array ObjectFile::staticDtorList;
28 typedef struct {
29 tree decl;
30 tree target;
31 target_ptrdiff_t offset;
32 } DeferredThunk;
34 ObjectFile::ObjectFile()
38 void
39 ObjectFile::beginModule(Module * m)
41 moduleInfo = new ModuleInfo;
42 g.mod = m;
45 void
46 ObjectFile::endModule()
48 for (unsigned i = 0; i < deferredThunks.dim; i++) {
49 DeferredThunk * t = (DeferredThunk *) deferredThunks.data[i];
50 outputThunk(t->decl, t->target, t->offset);
52 deferredThunks.setDim(0);
53 moduleInfo = NULL;
54 g.mod = NULL;
57 bool
58 ObjectFile::hasModule(Module *m)
60 if (!m || ! modules.dim)
61 return false;
63 if (modules.data[moduleSearchIndex] == m)
64 return true;
65 for (unsigned i = 0; i < modules.dim; i++) {
66 if ( (Module*) modules.data[i] == m ) {
67 moduleSearchIndex = i;
68 return true;
71 return false;
74 void
75 ObjectFile::finish()
77 /* If the target does not directly support static constructors,
78 staticCtorList contains a list of all static constructors defined
79 so far. This routine will create a function to call all of those
80 and is picked up by collect2. */
81 if (staticCtorList.dim) {
82 doFunctionToCallFunctions(IDENTIFIER_POINTER(get_file_function_name('I')),
83 & staticCtorList, true);
85 if (staticDtorList.dim) {
86 doFunctionToCallFunctions(IDENTIFIER_POINTER(get_file_function_name('D')),
87 & staticDtorList, true);
91 void
92 ObjectFile::doLineNote(const Loc & loc)
94 if (loc.filename) {
95 setLoc(loc);
96 #if D_GCC_VER < 40
97 location_t gcc_loc = { loc.filename, loc.linnum };
98 emit_line_note (gcc_loc);
99 #endif
100 } else {
101 // do nothing
105 void
106 ObjectFile::setLoc(const Loc & loc)
108 if (loc.filename) {
109 location_t gcc_loc = { loc.filename, loc.linnum };
110 input_location = gcc_loc;
111 } else {
112 // do nothing
116 void
117 ObjectFile::setDeclLoc(tree t, const Loc & loc)
119 // DWARF2 will often crash if the DECL_SOURCE_FILE is not set. It's
120 // easier the error here.
121 assert(loc.filename);
122 DECL_SOURCE_FILE (t) = loc.filename;
123 DECL_SOURCE_LINE (t) = loc.linnum;
126 void
127 ObjectFile::setDeclLoc(tree t, Dsymbol * decl)
129 while (decl) {
130 if (decl->loc.filename) {
131 setDeclLoc(t, decl->loc);
132 return;
134 decl = decl->toParent();
137 // fallback; backend sometimes crashes if not set
139 Loc l;
141 Module * m = decl->getModule();
142 if (m && m->srcfile && m->srcfile->name) {
143 l.filename = m->srcfile->name->str;
144 } else {
145 l.filename = "<no_file>"; // Emptry string can mess up debug info
147 l.linnum = 1;
148 setDeclLoc(t, l);
151 void
152 ObjectFile::giveDeclUniqueName(tree decl, const char * prefix)
154 /* It would be nice to be able to use TRANSLATION_UNIT_DECL
155 so lhd_set_decl_assembler_name would do this automatically.
156 Unforntuately, the non-NULL decl context confuses dwarf2out.
158 Maybe this is fixed in later versions of GCC.
161 const char *name;
162 if (prefix)
163 name = prefix;
164 else if (DECL_NAME(decl))
165 name = IDENTIFIER_POINTER(DECL_NAME(decl));
166 else
167 name = "___s";
168 char *label = d_asm_format_private_name(name, DECL_UID(decl));
169 SET_DECL_ASSEMBLER_NAME(decl, get_identifier(label));
170 free(label);
173 #if V2
174 static bool
175 is_function_nested_in_function(Dsymbol * dsym)
177 FuncDeclaration * fd = dsym->isFuncDeclaration();
178 AggregateDeclaration * ad;
179 ClassDeclaration * cd;
181 if (! fd)
182 return false;
183 else if (fd->isNested())
184 return true;
185 else if ( (ad = fd->isThis()) && (cd = ad->isClassDeclaration()) )
187 while (cd && cd->isNested())
189 dsym = cd->toParent2();
190 if (dsym->isFuncDeclaration())
191 return true;
192 else
193 cd = dsym->isClassDeclaration();
197 return false;
199 #endif
201 void
202 ObjectFile::makeDeclOneOnly(tree decl_tree, Dsymbol * dsym)
204 /* First method: Use one-only/coalesced attribute.
206 If user has specified -femit-templates=private, honor that
207 even if the target supports one-only. */
208 if ( ! D_DECL_IS_TEMPLATE( decl_tree ) || gen.emitTemplates != TEprivate ) {
209 /* Weak definitions have to be public. Nested functions may or
210 may not be emitted as public even if TREE_PUBLIC is set.
211 There is no way to tell if the back end implements
212 make_decl_one_only with DECL_WEAK, so this check is
213 done first. */
214 if ( (TREE_CODE(decl_tree) == FUNCTION_DECL &&
215 decl_function_context(decl_tree) != NULL_TREE &&
216 ! DECL_NO_STATIC_CHAIN(decl_tree))
217 #if V2
218 || ( dsym && is_function_nested_in_function(dsym) )
219 #endif
222 return;
225 #ifdef MAKE_DECL_COALESCED
226 // %% TODO: check if available like SUPPORTS_ONE_ONLY
227 // for Apple gcc...
228 MAKE_DECL_COALESCED( decl_tree );
229 return;
230 #endif
231 /* The following makes assumptions about the behavior
232 of make_decl_one_only */
233 if (SUPPORTS_ONE_ONLY) { // Must check, otherwise backend will abort
234 make_decl_one_only( decl_tree );
235 return;
236 } else if (SUPPORTS_WEAK) {
237 tree orig_init = DECL_INITIAL( decl_tree );
238 DECL_INITIAL( decl_tree ) = integer_zero_node;
239 make_decl_one_only( decl_tree );
240 DECL_INITIAL( decl_tree ) = orig_init;
241 return;
245 /* Second method: Make a private copy.
247 For RTTI, we can always make a private copy. For templates, only do
248 this if the user specified -femit-templates=private. */
249 if ( ! D_DECL_IS_TEMPLATE( decl_tree ) || gen.emitTemplates == TEprivate ) {
250 TREE_PRIVATE(decl_tree) = 1;
251 TREE_PUBLIC(decl_tree) = 0;
252 } else {
253 static bool warned = false;
254 if (! warned) {
255 warned = true;
256 ::warning(0, "system does not support one-only linkage");
261 void
262 ObjectFile::setupSymbolStorage(Dsymbol * dsym, tree decl_tree, bool force_static_public)
264 Declaration * real_decl = dsym->isDeclaration();
265 FuncDeclaration * func_decl = real_decl ? real_decl->isFuncDeclaration() : 0;
267 if (force_static_public ||
268 ( TREE_CODE( decl_tree ) == VAR_DECL && (real_decl && real_decl->isDataseg()) ) ||
269 ( TREE_CODE( decl_tree ) == FUNCTION_DECL ) ) {
271 bool is_template = false;
272 Dsymbol * sym = dsym->toParent();
273 Module * ti_obj_file_mod;
275 while (sym) {
276 TemplateInstance * ti = sym->isTemplateInstance();
277 if (ti) {
278 ti_obj_file_mod = ti->objFileModule;
279 is_template = true;
280 break;
282 sym = sym->toParent();
285 bool is_static;
287 if (is_template) {
288 D_DECL_ONE_ONLY( decl_tree ) = 1;
289 D_DECL_IS_TEMPLATE( decl_tree ) = 1;
290 is_static = hasModule(ti_obj_file_mod) && gen.emitTemplates != TEnone;
291 } else {
292 is_static = hasModule(dsym->getModule());
295 if (func_decl)
296 fprintf(stderr, "%s: is_template = %d is_static = %d te = %d m = %s cur = %s\n",
297 func_decl->toPrettyChars(), is_template, is_static, emitTemplates,
298 dsym->getModule() ? dsym->getModule()->toChars() : "none",
299 getCurrentModule()->toChars());
301 if (TREE_CODE( decl_tree ) == VAR_DECL &&
302 (real_decl && (real_decl->storage_class & STCextern)) )
303 is_static = false;
305 if ( is_static ) {
306 DECL_EXTERNAL( decl_tree ) = 0;
307 TREE_STATIC( decl_tree ) = 1; // %% don't set until there is a body?
308 if (real_decl && (real_decl->storage_class & STCcomdat))
309 D_DECL_ONE_ONLY( decl_tree ) = 1;
310 } else {
311 DECL_EXTERNAL( decl_tree ) = 1;
312 TREE_STATIC( decl_tree ) = 0;
315 if ( ( real_decl ) ) {
316 switch (real_decl->prot()) {
317 case PROTexport:
318 case PROTpublic:
319 case PROTpackage:
320 case PROTprotected:
321 // %% set for specials like init,vtbl ? -- otherwise,special case
322 // for reverse the default
323 TREE_PUBLIC( decl_tree ) = 1;
324 break;
325 default:
326 if ( (func_decl && (func_decl->isMain() || func_decl->isWinMain() ||
327 func_decl->isDllMain())) ||
328 (real_decl->isMember() && ! real_decl->isThis())) { // %% check this -- static members/
329 // DMD seems to ignore private in this case...
330 TREE_PUBLIC( decl_tree ) = 1;
331 } else {
332 // From DMD:
333 /* private statics should still get a global symbol, in case
334 * another module inlines a function that references it.
337 // TREE_PUBLIC( decl_tree ) = 0;
338 TREE_PUBLIC( decl_tree ) = 1;
343 if (D_DECL_ONE_ONLY( decl_tree ))
344 makeDeclOneOnly(decl_tree, dsym);
346 if ( func_decl && func_decl->isNested() )
347 TREE_PUBLIC( decl_tree ) = 0;
348 } else {
349 TREE_STATIC( decl_tree ) = 0;
350 DECL_EXTERNAL( decl_tree ) = 0;
351 TREE_PUBLIC( decl_tree ) = 0;
354 if (real_decl && real_decl->attributes)
355 decl_attributes(& decl_tree, gen.attributes(real_decl->attributes), 0);
358 void
359 ObjectFile::setupStaticStorage(Dsymbol * dsym, tree decl_tree)
361 TREE_PUBLIC( decl_tree ) = 1; // Do this by default, but allow private templates to override
362 setupSymbolStorage(dsym, decl_tree, true);
365 void
366 ObjectFile::outputStaticSymbol(tree t) {
367 d_add_global_function(t);
369 // %%TODO: flags
371 /* D allows zero-length declarations. Such a declaration ends up with
372 DECL_SIZE(t) == NULL_TREE which is what the backend function
373 assembler_variable checks. This could change in later versions...
375 Maybe all of these variables should be aliased to one symbol... */
377 // %%TODO: could move this to lang_hooks.decls.prepare_assemble_variable to
378 // make this check less precarious. -- or finish_incomplete_decl (from
379 // wrapup_global_declarations
380 if ( DECL_SIZE(t) == 0 ) {
381 DECL_SIZE(t) = bitsize_int(0);
382 DECL_SIZE_UNIT(t) = size_int(0);
383 } // Otherwise, if DECL_SIZE == 0, just let it fail...
385 rodc(t, 1);
388 void
389 ObjectFile::outputFunction(FuncDeclaration * f)
391 Symbol * s = f->toSymbol();
392 tree t = s->Stree;
394 if (TREE_CODE(t) == FUNCTION_DECL)
396 if (DECL_STATIC_CONSTRUCTOR( t ))
398 // %% check for nested function -- error
399 // otherwise, shouldn't be in a function, so safe to do asm_out
401 if (targetm.have_ctors_dtors) {
402 #if D_GCC_VER < 40
403 (* targetm.asm_out.constructor) (XEXP (DECL_RTL (t), 0),
404 DEFAULT_INIT_PRIORITY);
405 #endif
406 // #else, handled in d_expand_function
407 } else {
408 // %% assert FuncDeclaration
409 staticCtorList.push(f);
410 // %%TODO: fallback if ! targetm.have_ctors_dtors
413 if (DECL_STATIC_DESTRUCTOR( t )) {
414 if (targetm.have_ctors_dtors) {
415 #if D_GCC_VER < 40
416 (* targetm.asm_out.destructor) (XEXP (DECL_RTL (t), 0),
417 DEFAULT_INIT_PRIORITY);
418 #endif
419 // #else, handled in d_expand_function
420 } else {
421 // %% assert FuncDeclaration
422 staticDtorList.push(f);
423 // %%TODO: fallback if ! targetm.have_ctors_dtors
428 #if D_GCC_VER < 40
429 rest_of_compilation(t);
430 #else
431 if (! gen.functionNeedsChain(f))
432 cgraph_finalize_function(t,
433 decl_function_context(t) != NULL);
434 #endif
437 bool
438 ObjectFile::shouldEmit(Dsymbol * d_sym)
440 if (gen.emitTemplates != TEnone)
441 return true;
443 Dsymbol * sym = d_sym->toParent();
444 while (sym) {
445 if (sym->isTemplateInstance()) {
446 return false;
447 break;
449 sym = sym->toParent();
451 return true;
454 bool
455 ObjectFile::shouldEmit(Symbol * sym)
457 return (gen.emitTemplates != TEnone) || ! D_DECL_IS_TEMPLATE(sym->Stree);
460 void
461 ObjectFile::addAggMethods(tree rec_type, AggregateDeclaration * agg)
463 if (write_symbols != NO_DEBUG) {
464 ListMaker methods;
465 for (unsigned i = 0; i < agg->methods.dim; i++) {
466 FuncDeclaration * fd = (FuncDeclaration *) agg->methods.data[i];
468 methods.chain(fd->toSymbol()->Stree);
470 TYPE_METHODS( rec_type ) = methods.head;
474 void
475 ObjectFile::initTypeDecl(tree t, Dsymbol * d_sym)
477 assert( ! POINTER_TYPE_P( t ) );
478 if (! TYPE_STUB_DECL(t))
480 const char * name = d_sym->ident ? d_sym->ident->string : "fix";
481 tree decl = build_decl(TYPE_DECL, get_identifier(name), t);
482 DECL_CONTEXT( decl ) = gen.declContext(d_sym);
483 setDeclLoc(decl, d_sym);
484 initTypeDecl(t, decl);
489 void
490 ObjectFile::declareType(tree t, Type * d_type)
492 // Note: It is not safe to call d_type->toCtype().
493 Loc l;
494 tree decl = build_decl(TYPE_DECL, get_identifier(d_type->toChars()), t);
495 l.filename = "<internal>";
496 l.linnum = 1;
497 setDeclLoc(decl, l);
499 declareType(t, decl);
502 void
503 ObjectFile::declareType(tree t, Dsymbol * d_sym)
505 initTypeDecl(t, d_sym);
506 declareType(t, TYPE_NAME(t));
510 void
511 ObjectFile::initTypeDecl(tree t, tree decl)
513 if ( ! TYPE_STUB_DECL(t))
515 assert( ! POINTER_TYPE_P( t ) );
517 TYPE_CONTEXT( t ) = DECL_CONTEXT( decl );
518 TYPE_NAME( t ) = decl;
519 switch (TREE_CODE(t))
521 case ENUMERAL_TYPE:
522 case RECORD_TYPE:
523 case UNION_TYPE:
524 /* Not sure if there is a need for separate TYPE_DECLs in
525 TYPE_NAME and TYPE_STUB_DECL. */
526 TYPE_STUB_DECL( t ) = build_decl(TYPE_DECL, DECL_NAME(decl), t);
527 // g++ does this and the debugging code assumes it:
528 DECL_ARTIFICIAL( TYPE_STUB_DECL( t ) ) = 1;
529 break;
530 default:
531 // nothing
532 break;
537 void
538 ObjectFile::declareType(tree t, tree decl)
540 bool top_level = /*DECL_CONTEXT(decl) == fileContext || */
541 ! DECL_CONTEXT(decl);
543 // okay to do this?
544 rodc(decl, top_level);
547 tree
548 ObjectFile::stripVarDecl(tree value) {
549 if ( TREE_CODE( value ) != VAR_DECL ) {
550 return value;
551 } else if ( DECL_INITIAL(value) ) {
552 return DECL_INITIAL(value);
553 } else {
554 Type * d_type = gen.getDType( TREE_TYPE( value ));
555 if (d_type) {
556 d_type = d_type->toBasetype();
557 switch (d_type->ty) {
558 case Tstruct:
560 //tree t = gen.aggregateInitializer(((TypeStruct *) d_type)->sym, NULL, NULL, NULL_TREE);
561 // %% maker sure this is doing the right thing...
562 // %% better do get rid of it..
564 // need to VIEW_CONVERT?
565 dt_t * dt = NULL;
566 d_type->toDt(& dt);
567 tree t = dt2tree( dt );
568 TREE_CONSTANT(t) = 1;
569 return t;
571 break;
572 default:
573 // error below
574 break;
577 abort();
581 void
582 ObjectFile::doThunk(tree thunk_decl, tree target_decl, target_ptrdiff_t offset)
584 if (current_function_decl) {
585 DeferredThunk * t = new DeferredThunk;
586 t->decl = thunk_decl;
587 t->target = target_decl;
588 t->offset = offset;
589 deferredThunks.push(t);
590 } else {
591 outputThunk(thunk_decl, target_decl, offset);
595 /* Thunk code is based on g++ */
597 #ifdef ASM_OUTPUT_DEF
598 static int thunk_labelno;
600 /* Create a static alias to function. */
602 static tree
603 make_alias_for_thunk (tree function)
605 tree alias;
606 char buf[256];
608 #if defined (TARGET_IS_PE_COFF)
609 /* make_alias_for_thunk does not seem to be needed for TARGET_IS_PE_COFF
610 at all, and apparently causes problems... */
611 //if (DECL_ONE_ONLY (function))
612 return function;
613 #endif
614 // For gdc: Thunks may reference extern functions which cannot be aliased.
615 if (DECL_EXTERNAL(function))
616 return function;
618 ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno);
619 thunk_labelno++;
620 alias = build_decl (FUNCTION_DECL, get_identifier (buf),
621 TREE_TYPE (function));
622 DECL_CONTEXT (alias) = NULL;
623 TREE_READONLY (alias) = TREE_READONLY (function);
624 TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function);
625 TREE_PUBLIC (alias) = 0;
626 DECL_EXTERNAL (alias) = 0;
627 DECL_ARTIFICIAL (alias) = 1;
628 DECL_NO_STATIC_CHAIN (alias) = 1;
629 DECL_INLINE (alias) = 0;
630 DECL_DECLARED_INLINE_P (alias) = 0;
631 //DECL_INITIAL (alias) = error_mark_node;
632 TREE_ADDRESSABLE (alias) = 1;
633 TREE_USED (alias) = 1;
634 SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
635 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
636 if (!flag_syntax_only)
637 assemble_alias (alias, DECL_ASSEMBLER_NAME (function));
638 return alias;
640 #endif
642 void
643 ObjectFile::outputThunk(tree thunk_decl, tree target_decl, target_ptrdiff_t offset)
645 target_ptrdiff_t delta = -offset;
646 tree alias;
648 #ifdef ASM_OUTPUT_DEF
649 alias = make_alias_for_thunk(target_decl);
650 #else
651 alias = target_decl;
652 #endif
654 TREE_ADDRESSABLE(target_decl) = 1;
655 TREE_USED(target_decl) = 1;
656 DECL_VISIBILITY (thunk_decl) = DECL_VISIBILITY (target_decl);
657 #if ASM_OUTPUT_DEF \
658 && !defined (TARGET_IS_PE_COFF)
659 if (targetm.have_named_sections)
661 resolve_unique_section (target_decl, 0, flag_function_sections);
663 if (DECL_SECTION_NAME (target_decl) != NULL && DECL_ONE_ONLY (target_decl))
665 resolve_unique_section (thunk_decl, 0, flag_function_sections);
667 /* Output the thunk into the same section as function. */
668 DECL_SECTION_NAME (thunk_decl) = DECL_SECTION_NAME (target_decl);
671 #endif
672 // cp/method.c:
673 /* The back-end expects DECL_INITIAL to contain a BLOCK, so we
674 create one. */
675 // ... actually doesn't seem to be the case for output_mi_thunk
676 DECL_INITIAL (thunk_decl) = make_node (BLOCK);
677 BLOCK_VARS (DECL_INITIAL (thunk_decl)) = DECL_ARGUMENTS (thunk_decl);
679 if (targetm.asm_out.can_output_mi_thunk(thunk_decl, delta, 0, alias)) {
680 const char *fnname;
682 current_function_decl = thunk_decl;
683 DECL_RESULT( thunk_decl ) = build_decl(RESULT_DECL, 0, integer_type_node);
685 fnname = XSTR(XEXP(DECL_RTL(thunk_decl), 0), 0);
686 gen.initFunctionStart(thunk_decl, 0);
687 current_function_is_thunk = 1;
688 assemble_start_function (thunk_decl, fnname);
689 targetm.asm_out.output_mi_thunk (asm_out_file, thunk_decl,
690 delta, 0, alias);
691 assemble_end_function(thunk_decl, fnname);
692 current_function_decl = 0;
693 cfun = 0;
694 #if D_GCC_VER < 40
695 /* Because init_function_start increments this, we must
696 decrement it. */
697 immediate_size_expand--;
698 #endif
699 TREE_ASM_WRITTEN (thunk_decl) = 1;
700 } else {
701 sorry("backend for this target machine does not support thunks");
705 FuncDeclaration *
706 ObjectFile::doSimpleFunction(const char * name, tree expr, bool static_ctor, bool public_fn)
708 Module * mod = g.mod;
709 if (! mod)
710 mod = d_gcc_get_output_module();
712 if (name[0] == '*') {
713 Symbol * s = mod->toSymbolX(name + 1, 0, 0, "FZv");
714 name = s->Sident;
717 TypeFunction * func_type = new TypeFunction(0, Type::tvoid, 0, LINKc);
718 FuncDeclaration * func = new FuncDeclaration(mod->loc, mod->loc, // %% locs may be wrong
719 Lexer::idPool(name), STCstatic, func_type); // name is only to prevent crashes
720 func->loc = Loc(mod, 1); // to prevent debug info crash // maybe not needed if DECL_ARTIFICIAL?
721 func->linkage = func_type->linkage;
722 func->parent = mod;
723 func->protection = public_fn ? PROTpublic : PROTprivate;
725 tree func_decl = func->toSymbol()->Stree;
726 if (static_ctor)
727 DECL_STATIC_CONSTRUCTOR( func_decl ) = 1; // apparently, the back end doesn't do anything with this
729 // D static ctors, dtors, unittests, and the ModuleInfo chain function
730 // are always private (see ObjectFile::setupSymbolStorage, default case)
731 TREE_PUBLIC( func_decl ) = public_fn;
733 // %% maybe remove the identifier
735 func->fbody = new ExpStatement(mod->loc,
736 new WrappedExp(mod->loc, TOKcomma, expr, Type::tvoid));
738 func->toObjFile(false);
740 return func;
743 /* force: If true, create a new function even there is only one function in the
744 list.
746 FuncDeclaration *
747 ObjectFile::doFunctionToCallFunctions(const char * name, Array * functions, bool force_and_public)
749 Module * mod = g.mod;
751 // If there is only one function, just return that
752 if (functions->dim == 1 && ! force_and_public) {
753 return (FuncDeclaration *) functions->data[0];
754 } else if (functions->dim >= 1) {
755 // %% shouldn't front end build these?
756 tree exp = NULL_TREE;
757 tree call_exp = NULL_TREE;
758 for (unsigned i = 0; i < functions->dim; i++) {
759 FuncDeclaration * fn_decl = (FuncDeclaration *) functions->data[i];
760 call_exp = gen.buildCall(void_type_node, gen.addressOf(fn_decl), NULL_TREE);
761 if (! exp)
762 exp = call_exp;
763 else {
764 exp = build(COMPOUND_EXPR, void_type_node, exp, call_exp);
768 return doSimpleFunction(name, exp, false, force_and_public);
769 } else {
770 return NULL;
774 dt_t**
775 dtnwords(dt_t** pdt, size_t word_count, void * pwords, unsigned word_size)
777 return dtnbytes(pdt, word_count * word_size,
778 gen.hostToTargetString((char*) pwords, word_count, word_size));
781 dt_t**
782 dtawords(dt_t** pdt, size_t word_count, void * pwords, unsigned word_size)
784 return dtabytes(pdt, TYnptr, 0, word_count * word_size,
785 gen.hostToTargetString((char*) pwords, word_count, word_size));
788 /* Add a 32-bit value to a dt. If pad_to_word is true, adds any
789 necessary padding so that the next value is aligned to PTRSIZE. */
790 dt_t**
791 dti32(dt_t** pdt, unsigned val, int pad_to_word)
793 dt_t** result = dttree(pdt, gen.integerConstant(val, Type::tuns32));
794 if (! pad_to_word || PTRSIZE == 4)
795 return result;
796 else if (PTRSIZE == 8)
797 return dttree(result, gen.integerConstant(0, Type::tuns32));
798 else
799 gcc_unreachable();
802 dt_t**
803 dtcontainer(dt_t** pdt, Type * type, dt_t* values)
805 dt_t * d = new dt_t;
806 d->dt = DT_container;
807 d->DTnext = 0;
808 d->DTtype = type;
809 d->DTvalues = values;
810 return dtcat(pdt, d);
815 target_size_t
816 dt_size(dt_t * dt)
818 target_size_t size = 0;
820 while (dt) {
821 switch (dt->dt) {
822 case DT_azeros:
823 case DT_common:
824 case DT_nbytes:
825 size += dt->DTint;
826 break;
827 case DT_abytes:
828 case DT_xoff:
829 size += PTRSIZE;
830 break;
831 case DT_word:
832 // This may cause problems for 64-bit since dtdword is used for
833 // (uint? / size_t?) and pointers... Nearly all cases are for size_t
834 // and pointer, though.
835 size += PTRSIZE;
836 break;
837 case DT_tree:
839 tree t_size = TYPE_SIZE_UNIT( TREE_TYPE( dt->DTtree ));
840 size += gen.getTargetSizeConst(t_size);
842 break;
843 case DT_container:
844 size += dt_size(dt->DTvalues);
845 break;
846 default:
847 assert(0);
849 dt = dt->DTnext;
852 return size;
855 static tree
856 check_static_sym(Symbol * sym)
858 if (! sym->Stree) {
859 //assert( sym->Sdt );// Unfortunately cannot check for this; it might be an empty dt_t list...
861 tree t_ini = dt2tree( sym->Sdt ); // %% recursion problems?
862 tree t_var = build_decl( VAR_DECL, NULL_TREE, TREE_TYPE( t_ini ));
863 g.ofile->giveDeclUniqueName(t_var);
864 DECL_INITIAL( t_var ) = t_ini;
865 TREE_STATIC( t_var ) = 1;
866 if (sym->Sseg == CDATA) {
867 TREE_CONSTANT( t_var ) = TREE_CONSTANT( t_ini ) = 1;
868 TREE_READONLY( t_var ) = TREE_READONLY( t_ini ) = 1;
870 // %% need to check SCcomdat?
872 TREE_PRIVATE( t_var ) = 1;
873 DECL_IGNORED_P( t_var ) = 1;
874 DECL_ARTIFICIAL( t_var ) = 1;
875 sym->Stree = t_var;
877 return sym->Stree;
880 static tree
881 dt2tree_list_of_elems(dt_t * dt);
883 static tree
884 dt2node(dt_t * dt)
886 switch (dt->dt) {
887 case DT_azeros:
888 case DT_common:
890 tree a = make_node(CONSTRUCTOR);
891 TREE_TYPE(a) = gen.arrayType(Type::tuns8, dt->DTint);
892 TREE_READONLY(a) = 1;
893 TREE_CONSTANT(a) = 1;
894 return a;
896 case DT_nbytes:
898 tree s = build_string(dt->DTint, (char *) dt->DTpointer);
899 TREE_TYPE( s ) = gen.arrayType(Type::tuns8, dt->DTint);
900 return s;
902 case DT_abytes:
904 tree s = build_string(dt->DTint, (char *) dt->DTpointer);
905 TREE_TYPE( s ) = gen.arrayType(Type::tuns8, dt->DTint);
906 TREE_STATIC( s ) = 1;
907 return gen.addressOf( s );
909 case DT_word:
910 // %% make sure this is the target word type
911 return gen.integerConstant(dt->DTint, Type::tsize_t);
912 case DT_xoff:
913 return build(PLUS_EXPR, ptr_type_node,
914 gen.addressOf(check_static_sym(dt->DTsym)),
915 gen.integerConstant(dt->DTint, Type::tsize_t) );
916 case DT_tree:
917 return dt->DTtree;
918 case DT_container:
920 /* It is necessary to give static array data its original
921 type. Otherwise, the SRA pass will not find the array
922 elements.
924 SRA accesses struct elements by field offset, so the ad
925 hoc type from dt2tree is fine. It must still be a
926 CONSTRUCTOR, or the CCP pass may use it incorrectly.
928 Type *tb = NULL;
929 if (dt->DTtype)
930 tb = dt->DTtype->toBasetype();
931 if (tb && tb->ty == Tsarray)
933 TypeSArray * tsa = (TypeSArray *) tb;
934 CtorEltMaker ctor_elts;
935 dt_t * dte = dt->DTvalues;
936 target_size_t i = 0;
937 ctor_elts.reserve(tsa->dim->toInteger());
938 while (dte)
940 ctor_elts.cons(gen.integerConstant(i++, size_type_node),
941 dt2node(dte));
942 dte = dte->DTnext;
944 tree ctor = make_node(CONSTRUCTOR);
945 TREE_TYPE(ctor) = dt->DTtype->toCtype();
947 // DT data should always be constant. If the decl is not TREE_CONSTANT, fine.
948 TREE_CONSTANT(ctor) = 1;
950 TREE_READONLY(ctor) = 1;
951 TREE_STATIC(ctor) = 1;
952 CONSTRUCTOR_ELTS(ctor) = ctor_elts.head;
953 return ctor;
955 else if (tb && tb->ty == Tstruct)
956 return dt2tree_list_of_elems(dt->DTvalues);
957 else
958 return dt2tree(dt->DTvalues);
960 default:
961 abort();
963 return NULL;
966 static tree
967 dt2tree(dt_t * dt)
969 if (dt && /*dt->dt == DT_container || */dt->DTnext == NULL)
970 return dt2node(dt);
971 else
972 return dt2tree_list_of_elems(dt);
975 static tree
976 dt2tree_list_of_elems(dt_t * dt)
978 // Generate type on the fly
979 CtorEltMaker elts;
980 ListMaker fields;
981 tree offset = size_zero_node;
983 tree aggtype = make_node(RECORD_TYPE);
985 while (dt) {
986 tree value = dt2node(dt);
987 tree field = build_decl(FIELD_DECL, NULL_TREE, TREE_TYPE(value));
988 DECL_CONTEXT(field) = aggtype;
989 DECL_FIELD_OFFSET(field) = offset;
990 DECL_FIELD_BIT_OFFSET(field) = bitsize_zero_node;
991 DECL_ARTIFICIAL(field) = 1;
992 DECL_IGNORED_P(field) = 1;
993 layout_decl(field, 0);
995 fields.chain(field);
996 elts.cons(field, value);
997 offset = size_binop(PLUS_EXPR, offset, TYPE_SIZE_UNIT( TREE_TYPE( value )));
999 dt = dt->DTnext;
1002 TYPE_FIELDS(aggtype) = fields.head; // or finish_laout
1003 TYPE_SIZE(aggtype) = convert( bitsizetype,
1004 size_binop( MULT_EXPR, offset, size_int( BITS_PER_UNIT )));
1005 TYPE_SIZE_UNIT(aggtype) = offset;
1006 // okay no alignment -- decl (which has the correct type) should take care of it..
1007 // align=bits per word?
1008 compute_record_mode(aggtype);
1010 tree ctor = make_node(CONSTRUCTOR);
1011 TREE_TYPE(ctor) = aggtype;
1012 TREE_READONLY(ctor) = 1;
1013 // dt created data is always static
1014 TREE_STATIC(ctor) = 1;
1015 // should always be constant
1016 TREE_CONSTANT(ctor) = 1;
1018 // DT data should always be constant. If the decl is not TREE_CONSTANT, fine.
1019 CONSTRUCTOR_ELTS(ctor) = elts.head;
1020 return ctor;
1023 void
1024 outdata(Symbol * sym)
1026 tree t = check_static_sym( sym );
1028 assert( t );
1030 if (sym->Sdt && DECL_INITIAL( t ) == NULL_TREE)
1031 DECL_INITIAL( t ) = dt2tree( sym->Sdt );
1033 if (! g.ofile->shouldEmit(sym))
1034 return;
1036 if ( DECL_EXTERNAL( t ) ) {
1037 // %% Oops, this was supposed to be static.
1038 // This is for typeinfo decls ... may
1039 // insert into module instead?
1040 DECL_EXTERNAL( t ) = 0;
1041 TREE_STATIC( t ) = 1;
1044 layout_decl(t, 0);
1046 // from outputStaticSymbol:
1047 if ( DECL_SIZE(t) == NULL_TREE ) {
1048 DECL_SIZE(t) = bitsize_int(0);
1049 DECL_SIZE_UNIT(t) = size_int(0);
1050 } // Otherwise, if DECL_SIZE == 0, just let it fail...
1052 d_add_global_function(t);
1054 g.ofile->rodc(t, 1);
1057 void
1058 obj_includelib(char *name)
1060 d_warning(OPT_Wunknown_pragmas, "pragma(lib) not implemented");
1063 void
1064 obj_startaddress(Symbol *s)
1066 d_warning(OPT_Wunknown_pragmas, "pragma(startaddress) not implemented");
1069 void
1070 obj_append(Dsymbol *s)
1072 // GDC does not do multi-obj, so just write it out now.
1073 s->toObjFile(false);
1076 void
1077 obj_moduleinfo(Symbol *sym)
1080 Generate:
1081 struct _modref_t {
1082 _modref_t * next;
1083 ModuleInfo m;
1085 extern (C) _modref_t * _Dmodule_ref;
1086 private _modref_t our_mod_ref =
1087 { next: null, m: _ModuleInfo_xxx };
1088 void ___modinit() { // a static constructor
1089 our_mod_ref.next = _Dmodule_ref;
1090 _Dmodule_ref = & our_mod_ref;
1093 // struct ModuleReference in moduleinit.d
1094 tree mod_ref_type = gen.twoFieldType(Type::tvoid->pointerTo(), gen.getObjectType(),
1095 NULL, "next", "mod");
1096 tree f0 = TYPE_FIELDS( mod_ref_type );
1097 tree f1 = TREE_CHAIN( f0 );
1099 tree our_mod_ref = build_decl(VAR_DECL, NULL_TREE, mod_ref_type);
1100 dkeep(our_mod_ref);
1101 g.ofile->giveDeclUniqueName(our_mod_ref, "__mod_ref");
1103 tree init = make_node(CONSTRUCTOR);
1104 CtorEltMaker ce;
1105 TREE_TYPE( init ) = mod_ref_type;
1106 ce.cons(f0, d_null_pointer);
1107 ce.cons(f1, gen.addressOf(sym->Stree));
1108 CONSTRUCTOR_ELTS( init ) = ce.head;
1109 TREE_STATIC( init ) = 1;
1110 DECL_ARTIFICIAL( our_mod_ref ) = 1;
1111 DECL_IGNORED_P( our_mod_ref ) = 1;
1112 TREE_PRIVATE( our_mod_ref ) = 1;
1113 TREE_STATIC( our_mod_ref ) = 1;
1114 DECL_INITIAL( our_mod_ref ) = init;
1115 g.ofile->rodc(our_mod_ref, 1);
1117 tree the_mod_ref = build_decl(VAR_DECL, get_identifier("_Dmodule_ref"),
1118 build_pointer_type( mod_ref_type ));
1119 dkeep(the_mod_ref);
1120 DECL_EXTERNAL( the_mod_ref ) = 1;
1121 TREE_PUBLIC( the_mod_ref ) = 1;
1123 tree m1 = build(MODIFY_EXPR, void_type_node,
1124 gen.component(our_mod_ref, f0),
1125 the_mod_ref);
1126 tree m2 = build(MODIFY_EXPR, void_type_node,
1127 the_mod_ref, gen.addressOf(our_mod_ref));
1128 tree exp = build(COMPOUND_EXPR, void_type_node, m1, m2);
1130 g.ofile->doSimpleFunction("*__modinit", exp, true);