1 /*-------------------------------------------------------------------------
3 SDCCglue.c - glues everything we have done together into one file.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
26 #include "dbuf_string.h"
38 extern struct dbuf_s *codeOutBuf;
40 extern DEFSETFUNC(closeTmpFiles);
41 extern DEFSETFUNC(rmTmpFiles);
42 extern void initialComments(FILE *afile);
43 extern operand *operandFromAst(ast *tree, int lvl);
44 extern value *initPointer(initList *ilist, sym_link *toType);
47 set *pic14_localFunctions = NULL;
48 int pic14_hasInterrupt = 0; // Indicates whether to emit interrupt handler or not
50 int pic14_stringInSet(const char *str, set **world, int autoAdd);
53 #ifdef WORDS_BIGENDIAN
54 #define _ENDIAN(x) (3-x)
56 #define _ENDIAN(x) (x)
59 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
60 #define IS_GLOBAL(sym) ((sym)->level == 0)
61 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
63 /* dbufs for initialized data (idata and code sections),
64 * extern, and global declarations */
65 static struct dbuf_s *ivalBuf, *extBuf, *gloBuf, *gloDefBuf;
67 static set *emitted = NULL;
69 static void showAllMemmaps(FILE *of); // XXX: emits initialized symbols
72 emitPseudoStack(struct dbuf_s *oBuf, struct dbuf_s *oBufExt)
74 int shared, low, high, size, i;
77 /* also emit STK symbols
78 * XXX: This is ugly and fails as soon as devices start to get
79 * differently sized sharebanks, since STK12 will be
80 * required by larger devices but only up to STK03 might
81 * be defined using smaller devices. */
82 shared = pic14_getSharedStack(&low, &high, &size);
83 if (!pic14_options.isLibrarySource)
87 dbuf_printf (oBuf, "\n");
88 dbuf_printf (oBuf, "\tglobal PSAVE\n");
89 dbuf_printf (oBuf, "\tglobal SSAVE\n");
90 dbuf_printf (oBuf, "\tglobal WSAVE\n");
91 for (i = size - 4; i >= 0; i--) {
92 dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
94 dbuf_printf (oBuf, "\n");
96 // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
99 // for single banked devices: use normal, "banked" RAM
100 dbuf_printf (oBuf, "sharebank udata_ovr 0x%04X\n", low);
102 // for devices with at least two banks, require a sharebank section
103 dbuf_printf (oBuf, "sharebank udata_shr\n");
105 dbuf_printf (oBuf, "PSAVE\tres 1\n");
106 dbuf_printf (oBuf, "SSAVE\tres 1\n");
107 dbuf_printf (oBuf, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
108 /* fill rest of sharebank with stack STKxx .. STK00 */
109 for (i = size - 4; i >= 0; i--) {
110 dbuf_printf (oBuf, "STK%02d\tres 1\n", i);
113 /* declare STKxx as extern for all files
114 * except the one containing main() */
115 dbuf_printf (oBufExt, "\n");
116 dbuf_printf (oBufExt, "\textern PSAVE\n");
117 dbuf_printf (oBufExt, "\textern SSAVE\n");
118 dbuf_printf (oBufExt, "\textern WSAVE\n");
119 for (i = size - 4; i >= 0; i--) {
121 SNPRINTF(&buffer[0], 127, "STK%02d", i);
122 dbuf_printf (oBufExt, "\textern %s\n", &buffer[0]);
123 pic14_stringInSet(&buffer[0], &emitted, 1);
126 dbuf_printf (oBuf, "\n");
130 emitIfNew(struct dbuf_s *oBuf, set **emitted, const char *fmt,
133 int wasPresent = pic14_stringInSet(name, emitted, 1);
136 dbuf_printf (oBuf, fmt, name);
138 return (!wasPresent);
142 pic14_constructAbsMap (struct dbuf_s *oBuf, struct dbuf_s *gloBuf)
144 memmap *maps[] = { data, sfr, NULL };
149 int addr, min=-1, max=-1;
152 for (i=0; maps[i] != NULL; i++)
154 for (sym = (symbol *)setFirstItem (maps[i]->syms);
155 sym; sym = setNextItem (maps[i]->syms))
157 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
159 addr = SPEC_ADDR(sym->etype);
161 /* handle CONFIG words here */
162 if (IS_CONFIG_ADDRESS( addr ))
164 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
165 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
167 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
169 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
174 if (max == -1 || addr > max) max = addr;
175 if (min == -1 || addr < min) min = addr;
176 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
177 aliases = hTabItemWithKey (ht, addr);
179 /* May not use addSetHead, as we cannot update the
180 * list's head in the hastable `ht'. */
181 addSet (&aliases, sym);
183 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
184 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
187 addSet (&aliases, sym);
188 hTabAddItem (&ht, addr, aliases);
194 /* now emit definitions for all absolute symbols */
195 dbuf_printf (oBuf, "%s", iComments2);
196 dbuf_printf (oBuf, "; absolute symbol definitions\n");
197 dbuf_printf (oBuf, "%s", iComments2);
198 for (addr=min; addr <= max; addr++)
201 aliases = hTabItemWithKey (ht, addr);
202 if (aliases && elementsInSet(aliases)) {
203 /* Make sure there is no initialized value at this location! */
204 for (sym = setFirstItem(aliases); sym; sym = setNextItem(aliases)) {
205 if (sym->ival) break;
209 dbuf_printf (oBuf, "UD_abs_%s_%x\tudata_ovr\t0x%04x\n",
210 moduleName, addr, addr);
211 for (sym = setFirstItem (aliases); sym;
212 sym = setNextItem (aliases))
214 if (getSize(sym->type) > size) {
215 size = getSize(sym->type);
218 /* initialized values are handled somewhere else */
219 if (sym->ival) continue;
221 /* emit STATUS as well as _STATUS, required for SFRs only */
222 //dbuf_printf (oBuf, "%s\tres\t0\n", sym->name);
223 dbuf_printf (oBuf, "%s\n", sym->rname);
225 if (IS_GLOBAL(sym) && !IS_STATIC(sym->etype)) {
226 //emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->name);
227 emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
230 dbuf_printf (oBuf, "\tres\t%d\n", size);
235 /*-----------------------------------------------------------------*/
236 /* createInterruptVect - creates the interrupt vector */
237 /*-----------------------------------------------------------------*/
239 pic14createInterruptVect (struct dbuf_s * vBuf)
241 mainf = newSymbol ("main", 0);
244 /* only if the main function exists */
245 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
247 struct options *op = &options;
248 if (!(op->cc_only || noAssemble))
249 // werror (E_NO_MAIN);
250 fprintf(stderr,"WARNING: function 'main' undefined\n");
254 /* if the main is only a prototype ie. no body then do nothing */
255 if (!IFFUNC_HASBODY(mainf->type))
257 /* if ! compile only then main function should be present */
258 if (!(options.cc_only || noAssemble))
259 // werror (E_NO_MAIN);
260 fprintf(stderr,"WARNING: function 'main' undefined\n");
264 dbuf_printf (vBuf, "%s", iComments2);
265 dbuf_printf (vBuf, "; reset vector \n");
266 dbuf_printf (vBuf, "%s", iComments2);
267 dbuf_printf (vBuf, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
268 dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */
269 dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n");
270 dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n");
271 popGetExternal("__sdcc_gsinit_startup", 0);
275 /*-----------------------------------------------------------------*/
276 /* initialComments - puts in some initial comments */
277 /*-----------------------------------------------------------------*/
279 pic14initialComments (FILE * afile)
281 initialComments (afile);
282 fprintf (afile, "; PIC port for the 14-bit core\n");
283 fprintf (afile, iComments2);
288 pic14_stringInSet(const char *str, set **world, int autoAdd)
295 for (s = setFirstItem(*world); s; s = setNextItem(*world))
298 if (0 == strcmp(s, str)) return 1;
302 if (autoAdd) addSet(world, Safe_strdup(str));
307 pic14printLocals (struct dbuf_s *oBuf)
309 set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
310 dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
313 static unsigned sectionNr = 0;
315 /* emit all registers from all possible sets */
316 for (i = 0; i < 6; i++) {
317 if (allregs[i] == NULL) continue;
319 for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
320 if (reg->isEmitted) continue;
322 if (reg->wasUsed && !reg->isExtern) {
323 if (!pic14_stringInSet(reg->name, &emitted, 1)) {
325 // Should not happen, really...
326 assert ( !"Compiler-assigned variables should not be pinned... This is a bug." );
327 dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
328 moduleName, sectionNr++, reg->address, reg->name, reg->size);
330 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
331 // assign each local register into its own section
332 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
333 moduleName, sectionNr++, reg->name, reg->size);
335 // group all local registers into a single section
336 // This should greatly improve BANKSEL generation...
338 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++);
341 dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size);
351 /*-----------------------------------------------------------------*/
352 /* emitOverlay - will emit code for the overlay stuff */
353 /*-----------------------------------------------------------------*/
355 pic14emitOverlay (struct dbuf_s * aBuf)
359 /* if (!elementsInSet (ovrSetSets))*/
361 /* the hack below, fixes translates for devices which
362 * only have udata_shr memory */
363 dbuf_printf (aBuf, "%s\t%s\n",
364 (elementsInSet(ovrSetSets)?"":";"),
365 port->mem.overlay_name);
367 /* for each of the sets in the overlay segment do */
368 for (ovrset = setFirstItem (ovrSetSets); ovrset;
369 ovrset = setNextItem (ovrSetSets))
374 if (elementsInSet (ovrset))
376 /* this dummy area is used to fool the assembler
377 otherwise the assembler will append each of these
378 declarations into one chunk and will not overlay
381 /* I don't think this applies to us. We are using gpasm. CRF */
383 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
384 /* output the area informtion */
385 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
388 for (sym = setFirstItem (ovrset); sym;
389 sym = setNextItem (ovrset))
392 /* if extern then do nothing */
393 if (IS_EXTERN (sym->etype))
396 /* if allocation required check is needed
397 then check if the symbol really requires
398 allocation only for local variables */
399 if (!IS_AGGREGATE (sym->type) &&
400 !(sym->_isparm && !IS_REGPARM (sym->etype))
401 && !sym->allocreq && sym->level)
404 /* if global variable & not static or extern
405 and addPublics allowed then add it to the public set */
406 if ((sym->_isparm && !IS_REGPARM (sym->etype))
407 && !IS_STATIC (sym->etype))
408 addSetHead (&publics, sym);
410 /* if extern then do nothing or is a function
412 if (IS_FUNC (sym->type))
415 /* print extra debug info if required */
416 if (options.debug || sym->level == 0)
420 if (IS_STATIC (sym->etype))
421 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
423 dbuf_printf (aBuf, "G_"); /* scope is global */
426 /* symbol is local */
427 dbuf_printf (aBuf, "L%s_",
428 (sym->localof ? sym->localof->name : "-null-"));
429 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
432 /* if is has an absolute address then generate
433 an equate for this no need to allocate space */
434 if (SPEC_ABSA (sym->etype))
437 if (options.debug || sym->level == 0)
438 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
440 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
442 SPEC_ADDR (sym->etype));
446 if (options.debug || sym->level == 0)
447 dbuf_printf (aBuf, "==.\n");
450 dbuf_printf (aBuf, "%s:\n", sym->rname);
451 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
460 pic14_emitInterruptHandler (FILE * asmFile)
462 if (pic14_hasInterrupt)
465 fprintf (asmFile, "%s", iComments2);
466 fprintf (asmFile, "; interrupt and initialization code\n");
467 fprintf (asmFile, "%s", iComments2);
468 // Note - for mplink may have to enlarge section vectors in .lnk file
469 // Note: Do NOT name this code_interrupt to avoid nameclashes with
470 // source files's code segment (interrupt.c -> code_interrupt)
471 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
473 /* interrupt service routine */
474 fprintf (asmFile, "__sdcc_interrupt\n");
475 copypCode(asmFile, 'I');
479 /*-----------------------------------------------------------------*/
480 /* glue - the final glue that hold the whole thing together */
481 /*-----------------------------------------------------------------*/
486 struct dbuf_s ovrBuf;
489 dbuf_init(&ovrBuf, 4096);
490 dbuf_init(&vBuf, 4096);
492 pCodeInitRegisters();
494 /* check for main() */
495 mainf = newSymbol ("main", 0);
497 mainf = findSymWithLevel (SymbolTab, mainf);
499 if (!mainf || !IFFUNC_HASBODY(mainf->type))
501 /* main missing -- import stack from main module */
502 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
503 pic14_options.isLibrarySource = 1;
506 /* At this point we've got all the code in the form of pCode structures */
507 /* Now it needs to be rearranged into the order it should be placed in the */
510 movepBlock2Head('P'); // Last
511 movepBlock2Head(code->dbName);
512 movepBlock2Head('X');
513 movepBlock2Head(statsg->dbName); // First
516 /* print the global struct definitions */
520 /* do the overlay segments */
521 pic14emitOverlay(&ovrBuf);
523 /* PENDING: this isnt the best place but it will do */
524 if (port->general.glue_up_main) {
525 /* create the interrupt vector table */
526 pic14createInterruptVect (&vBuf);
531 ReuseReg(); // ReuseReg where call tree permits
537 if (options.debug) pcode_test();
540 /* now put it all together into the assembler file */
541 /* create the assembler file name */
543 if ((noAssemble || options.c1mode) && fullDstFileName)
545 sprintf (buffer, fullDstFileName);
549 sprintf (buffer, dstFileName);
550 strcat (buffer, ".asm");
553 if (!(asmFile = fopen (buffer, "w"))) {
554 werror (E_FILE_OPEN_ERR, buffer);
558 /* prepare statistics */
559 resetpCodeStatistics ();
561 /* initial comments */
562 pic14initialComments (asmFile);
564 /* print module name */
565 fprintf (asmFile, "%s\t.file\t\"%s\"\n",
566 options.debug ? "" : ";", fullSrcFileName);
568 /* Let the port generate any global directives, etc. */
569 if (port->genAssemblerPreamble)
571 port->genAssemblerPreamble(asmFile);
574 /* Put all variables into a cblock */
577 /* emit initialized data */
578 showAllMemmaps(asmFile);
580 /* print the locally defined variables in this module */
581 writeUsedRegs(asmFile);
583 /* create the overlay segments */
584 fprintf (asmFile, "%s", iComments2);
585 fprintf (asmFile, "; overlayable items in internal ram \n");
586 fprintf (asmFile, "%s", iComments2);
587 dbuf_write_and_destroy (&ovrBuf, asmFile);
589 /* copy the interrupt vector table */
590 if (mainf && IFFUNC_HASBODY(mainf->type))
591 dbuf_write_and_destroy (&vBuf, asmFile);
595 /* create interupt ventor handler */
596 pic14_emitInterruptHandler (asmFile);
599 fprintf (asmFile, "%s", iComments2);
600 fprintf (asmFile, "; code\n");
601 fprintf (asmFile, "%s", iComments2);
602 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
605 copypCode(asmFile, 'X');
608 copypCode(asmFile, 'M');
610 /* other functions */
611 copypCode(asmFile, code->dbName);
614 copypCode(asmFile, 'P');
616 dumppCodeStatistics (asmFile);
618 fprintf (asmFile,"\tend\n");
621 pic14_debugLogClose();
625 * Deal with initializers.
630 #define DEBUGprintf printf
633 #define DEBUGprintf 1 ? (void)0 : (void)printf
637 parseIvalAst (ast *node, int *inCodeSpace) {
642 if (IS_AST_VALUE(node)) {
643 value *val = AST_VALUE(node);
644 symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
645 if (inCodeSpace && val->type
646 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
650 if (inCodeSpace && sym
651 && (IS_FUNC(sym->type)
652 || IS_CODE(getSpec(sym->type))))
657 DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
658 if (IS_AST_LIT_VALUE(node)) {
659 buffer = Safe_alloc(LEN);
660 SNPRINTF(buffer, LEN, "0x%lx", AST_ULONG_VALUE (node));
661 } else if (IS_AST_SYM_VALUE(node)) {
662 assert ( AST_SYMBOL(node) );
664 printf ("sym %s: ", AST_SYMBOL(node)->rname);
665 printTypeChain(AST_SYMBOL(node)->type, stdout);
666 printTypeChain(AST_SYMBOL(node)->etype, stdout);
667 printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
669 buffer = Safe_strdup(AST_SYMBOL(node)->rname);
671 assert ( !"Invalid values type for initializers in AST." );
673 } else if (IS_AST_OP(node)) {
674 DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
675 switch (node->opval.op) {
677 assert (node->right);
678 buffer = parseIvalAst(node->right, inCodeSpace);
679 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
682 assert ( node->left && !node->right );
683 buffer = parseIvalAst(node->left, inCodeSpace);
684 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
687 assert (node->left && node->right );
688 left = parseIvalAst(node->left, inCodeSpace);
689 right = parseIvalAst(node->right, inCodeSpace);
690 buffer = Safe_alloc(LEN);
691 SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
692 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
697 assert ( node->left && node->right );
698 assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
699 right = parseIvalAst(node->right, inCodeSpace);
700 buffer = Safe_alloc(LEN);
701 SNPRINTF(buffer, LEN, "(%s + %u * %s)",
702 AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
704 DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
707 assert ( !"Unhandled operation in initializer." );
711 assert ( !"Invalid construct in initializer." );
718 * Emit the section preamble, absolute location (if any) and
719 * symbol name(s) for intialized data.
722 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
725 static int in_code = 0;
726 static int sectionNr = 0;
729 // code or data space?
730 if (IS_CODE(getSpec(sym->type))) {
737 dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
738 if (SPEC_ABSA(getSpec(sym->type))) {
739 // specify address for absolute symbols
740 dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
742 dbuf_printf(oBuf, "\n%s\n", sym->rname);
744 addSet(&emitted, sym->rname);
750 * Actually emit the initial values in .asm format.
753 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
763 assert (size <= sizeof(long));
764 assert (!list || (list->type == INIT_NODE));
765 node = list ? list->init.node : NULL;
767 in_code = emitIvalLabel(oBuf, sym);
768 if (!in_code) dbuf_printf (oBuf, "\tdb\t");
771 // initialize as zero
772 for (i=0; i < size; i++) {
774 dbuf_printf (oBuf, "\tretlw 0x00");
776 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
779 dbuf_printf (oBuf, "\n");
784 if (constExprTree(node) && (val = constExprValue(node, 0))) {
785 op = operandFromValue(val);
786 DEBUGprintf ("%s: constExpr ", __FUNCTION__);
787 } else if (IS_AST_VALUE(node)) {
788 op = operandFromAst(node, 0);
789 } else if (IS_AST_OP(node)) {
790 str = parseIvalAst(node, &inCodeSpace);
791 DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
794 assert ( !"Unhandled construct in intializer." );
800 //printOperand(op, of);
803 for (i=0; i < size; i++) {
807 * FIXME: This is hacky and needs some more thought.
809 if (op && IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) {
810 /* This branch is introduced to fix #1427663. */
811 PCOI(AOP(op)->aopu.pcop)->offset+=i;
812 text = get_op(AOP(op)->aopu.pcop, NULL, 0);
813 PCOI(AOP(op)->aopu.pcop)->offset-=i;
815 text = op ? aopGet(AOP(op), i, 0, 0)
816 : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
819 dbuf_printf (oBuf, "\tretlw %s\n", text);
821 dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
824 dbuf_printf (oBuf, "\n");
828 * For UNIONs, we first have to find the correct alternative to map the
829 * initializer to. This function maps the structure of the initializer to
830 * the UNION members recursively.
831 * Returns the type of the first `fitting' member.
834 matchIvalToUnion (initList *list, sym_link *type, int size)
840 if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
843 if (!list || (list->type == INIT_NODE)) {
844 DEBUGprintf ("OK, simple type\n");
847 DEBUGprintf ("ERROR, simple type\n");
850 } else if (IS_BITFIELD(type)) {
851 if (!list || (list->type == INIT_NODE)) {
852 DEBUGprintf ("OK, bitfield\n");
855 DEBUGprintf ("ERROR, bitfield\n");
858 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
859 if (!list || (list->type == INIT_DEEP)) {
860 if (list) list = list->init.deep;
861 sym = SPEC_STRUCT(type)->fields;
863 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
864 if (!matchIvalToUnion(list, sym->type, 0)) {
865 DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
868 if (list) list = list->next;
872 // excess initializers?
874 DEBUGprintf ("ERROR, excess initializers\n");
878 DEBUGprintf ("OK, struct\n");
882 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
883 if (!list || (list->type == INIT_DEEP)) {
884 if (list) list = list->init.deep;
885 sym = SPEC_STRUCT(type)->fields;
887 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
888 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
889 && matchIvalToUnion(list, sym->type, size))
891 DEBUGprintf ("Matched UNION member %s.\n", sym->name);
898 DEBUGprintf ("ERROR, no match found.\n");
901 assert ( !"Unhandled type in UNION." );
904 assert ( !"No match found in UNION for the given initializer structure." );
909 * Parse the type and its initializer and emit it (recursively).
912 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
919 size = getSize(my_type);
921 if (IS_PTR(my_type)) {
922 DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
923 emitIvals(oBuf, topsym, list, 0, size);
927 if (IS_ARRAY(my_type) && topsym && topsym->isstrlit) {
928 str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
929 emitIvalLabel(oBuf, topsym);
931 dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
936 if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
937 fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
938 assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
942 if (IS_ARRAY(my_type)) {
943 DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
944 assert (!list || list->type == INIT_DEEP);
945 if (list) list = list->init.deep;
946 for (i = 0; i < DCL_ELEM(my_type); i++) {
947 emitInitVal(oBuf, topsym, my_type->next, list);
949 if (list) list = list->next;
954 if (IS_FLOAT(my_type)) {
956 DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
957 emitIvals(oBuf, topsym, list, 0, size);
961 if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
962 // integral type, 8, 16, or 32 bit
963 DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
964 emitIvals(oBuf, topsym, list, 0, size);
967 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
969 DEBUGprintf ("(struct, %d byte) handled below\n", size);
970 assert (!list || (list->type == INIT_DEEP));
972 // iterate over struct members and initList
973 if (list) list = list->init.deep;
974 sym = SPEC_STRUCT(my_type)->fields;
978 if (IS_BITFIELD(sym->type)) {
979 while (sym && IS_BITFIELD(sym->type)) {
980 assert (!list || ((list->type == INIT_NODE)
981 && IS_AST_LIT_VALUE(list->init.node)));
982 lit = (long) (list ? list2int(list) : 0);
983 DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
984 lit, SPEC_BLEN(getSpec(sym->type)),
985 SPEC_BSTR(getSpec(sym->type)), bitfield);
986 bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
987 len += SPEC_BLEN(getSpec(sym->type));
990 if (list) list = list->next;
992 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
993 len = (len + 7) & ~0x07; // round up to full bytes
994 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
999 emitInitVal(oBuf, topsym, sym->type, list);
1002 if (list) list = list->next;
1006 assert ( !"Excess initializers." );
1010 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
1012 DEBUGprintf ("(union, %d byte) handled below\n", size);
1013 assert (list && list->type == INIT_DEEP);
1015 // iterate over union members and initList, try to map number and type of fields and initializers
1016 my_type = matchIvalToUnion(list, my_type, size);
1018 emitInitVal(oBuf, topsym, my_type, list->init.deep);
1020 size -= getSize(my_type);
1022 // pad with (leading) zeros
1023 emitIvals(oBuf, NULL, NULL, 0, size);
1028 assert ( !"No UNION member matches the initializer structure.");
1029 } else if (IS_BITFIELD(my_type)) {
1030 assert ( !"bitfields should only occur in structs..." );
1033 printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
1034 assert( !"Unhandled initialized type.");
1039 * Emit a set of symbols.
1040 * type - 0: have symbol tell whether it is local, extern or global
1041 * 1: assume all symbols in set to be global
1042 * 2: assume all symbols in set to be extern
1045 emitSymbolSet(set *s, int type)
1049 unsigned sectionNr = 0;
1051 for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
1053 fprintf (stdout, "; name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
1054 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
1057 if (sym->etype && SPEC_ABSA(sym->etype)
1058 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))
1061 // handle config words
1062 pic14_assignConfigWordValue(SPEC_ADDR(sym->etype),
1063 (int)list2int(sym->ival));
1064 pic14_stringInSet(sym->rname, &emitted, 1);
1068 if (sym->isstrlit) {
1069 // special case: string literals
1070 emitInitVal(ivalBuf, sym, sym->type, NULL);
1074 if (type != 0 || sym->cdef
1075 || (!IS_STATIC(sym->etype)
1078 // bail out for ___fsadd and friends
1079 if (sym->cdef && !sym->used) continue;
1081 /* export or import non-static globals */
1082 if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
1084 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
1086 /* do not add to emitted set, it might occur again! */
1087 //if (!sym->used) continue;
1089 emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
1092 emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
1093 if (!sym->ival && !IS_FUNC(sym->type)) {
1094 // also define symbol
1095 if (IS_ABSOLUTE(sym->etype)) {
1096 // absolute location?
1097 //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
1098 // deferred to pic14_constructAbsMap
1100 dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
1101 dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
1105 pic14_stringInSet(sym->rname, &emitted, 1);
1109 //if (list) showInitList(list, 0);
1111 resolveIvalSym( list, sym->type );
1112 emitInitVal(ivalBuf, sym, sym->type, sym->ival);
1113 dbuf_printf (ivalBuf, "\n");
1119 * Iterate over all memmaps and emit their contents (attributes, symbols).
1122 showAllMemmaps(FILE *of)
1124 struct dbuf_s locBuf;
1126 xstack, istack, code, data, pdata, xdata, xidata, xinit,
1127 idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
1128 sfr, sfrbit, reg, generic, overlay, eeprom, home };
1132 DEBUGprintf ("---begin memmaps---\n");
1133 if (!extBuf) extBuf = dbuf_new(1024);
1134 if (!gloBuf) gloBuf = dbuf_new(1024);
1135 if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
1136 if (!ivalBuf) ivalBuf = dbuf_new(1024);
1137 dbuf_init(&locBuf, 1024);
1139 dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
1140 dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
1141 dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
1142 dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
1143 dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
1145 for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
1147 //DEBUGprintf ("memmap %i: %p\n", i, map);
1150 fprintf (stdout, "; pageno %c, sname %s, dbName %c, ptrType %d, slbl %d, sloc %u, fmap %u, paged %u, direct %u, bitsp %u, codesp %u, regsp %u, syms %p\n",
1151 map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
1152 map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
1153 map->codesp, map->regsp, map->syms);
1155 emitSymbolSet(map->syms, 0);
1158 DEBUGprintf ("---end of memmaps---\n");
1160 emitSymbolSet(publics, 1);
1161 emitSymbolSet(externs, 2);
1163 emitPseudoStack(gloBuf, extBuf);
1164 pic14_constructAbsMap(gloDefBuf, gloBuf);
1165 pic14printLocals (&locBuf);
1166 pic14_emitConfigWord(of); // must be done after all the rest
1168 dbuf_write_and_destroy(extBuf, of);
1169 dbuf_write_and_destroy(gloBuf, of);
1170 dbuf_write_and_destroy(gloDefBuf, of);
1171 dbuf_write_and_destroy(&locBuf, of);
1172 dbuf_write_and_destroy(ivalBuf, of);
1174 extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;