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 -------------------------------------------------------------------------*/
25 #include "../common.h"
33 #include "dbuf_string.h"
36 #ifdef WORDS_BIGENDIAN
37 #define _ENDIAN(x) (3-x)
39 #define _ENDIAN(x) (x)
42 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
43 #define IS_GLOBAL(sym) ((sym)->level == 0)
45 extern symbol *interrupts[256];
46 static void showAllMemmaps(FILE *of); // XXX: emits initialized symbols
50 extern unsigned maxInterrupts;
52 extern char *VersionString;
53 extern struct dbuf_s *codeOutBuf;
54 extern char *iComments1;
55 extern char *iComments2;
56 //extern void emitStaticSeg (memmap * map);
57 set *pic14_localFunctions = NULL;
59 extern DEFSETFUNC (closeTmpFiles);
60 extern DEFSETFUNC (rmTmpFiles);
62 extern void AnalyzeBanking (void);
63 extern void ReuseReg(void);
64 extern void InlinepCode(void);
65 extern void writeUsedRegs(FILE *);
67 extern void initialComments (FILE * afile);
68 extern void printPublics (FILE * afile);
70 extern void printChar (FILE * ofile, char *s, int plen);
71 void pCodeInitRegisters(void);
72 int getConfigWord(int address);
73 int getHasSecondConfigReg(void);
74 void pic14_debugLogClose(void); // from ralloc.c
76 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
77 int pic14_hasInterrupt = 0; // Indicates whether to emit interrupt handler or not
79 /* dbufs for initialized data (idata and code sections),
80 * extern, and global declarations */
81 struct dbuf_s *ivalBuf, *extBuf, *gloBuf, *gloDefBuf;
83 static set *emitted = NULL;
84 int pic14_stringInSet(const char *str, set **world, int autoAdd);
86 /*-----------------------------------------------------------------*/
87 /* aopLiteral - string from a literal value */
88 /*-----------------------------------------------------------------*/
89 unsigned int pic14aopLiteral (value *val, int offset)
96 /* if it is a float then it gets tricky */
97 /* otherwise it is fairly simple */
98 if (!IS_FLOAT(val->type)) {
99 unsigned long v = ulFromVal (val);
101 return ( (v >> (offset * 8)) & 0xff);
104 /* it is type float */
105 fl.f = (float) floatFromVal(val);
106 #ifdef WORDS_BIGENDIAN
107 return fl.c[3-offset];
116 is_valid_identifier( const char *name )
122 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
123 if (!((a >= 'a' && a <= 'z')
124 || (a >= 'A' && a <= 'z')
129 while ((a = *name++))
131 if (!((a >= 'a' && a <= 'z')
132 || (a >= 'A' && a <= 'Z')
133 || (a >= '0' && a <= '9')
138 /* valid identifier */
144 emitPseudoStack(struct dbuf_s *oBuf, struct dbuf_s *oBufExt)
146 int shared, low, high, size, i;
149 /* also emit STK symbols
150 * XXX: This is ugly and fails as soon as devices start to get
151 * differently sized sharebanks, since STK12 will be
152 * required by larger devices but only up to STK03 might
153 * be defined using smaller devices. */
154 shared = pic14_getSharedStack(&low, &high, &size);
155 if (!pic14_options.isLibrarySource)
157 pic = pic14_getPIC();
159 dbuf_printf (oBuf, "\n");
160 dbuf_printf (oBuf, "\tglobal PSAVE\n");
161 dbuf_printf (oBuf, "\tglobal SSAVE\n");
162 dbuf_printf (oBuf, "\tglobal WSAVE\n");
163 for (i = size - 4; i >= 0; i--) {
164 dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
166 dbuf_printf (oBuf, "\n");
168 // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
171 // for single banked devices: use normal, "banked" RAM
172 dbuf_printf (oBuf, "sharebank udata_ovr 0x%04X\n", low);
174 // for devices with at least two banks, require a sharebank section
175 dbuf_printf (oBuf, "sharebank udata_shr\n");
177 dbuf_printf (oBuf, "PSAVE\tres 1\n");
178 dbuf_printf (oBuf, "SSAVE\tres 1\n");
179 dbuf_printf (oBuf, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
180 /* fill rest of sharebank with stack STKxx .. STK00 */
181 for (i = size - 4; i >= 0; i--) {
182 dbuf_printf (oBuf, "STK%02d\tres 1\n", i);
185 /* declare STKxx as extern for all files
186 * except the one containing main() */
187 dbuf_printf (oBufExt, "\n");
188 dbuf_printf (oBufExt, "\textern PSAVE\n");
189 dbuf_printf (oBufExt, "\textern SSAVE\n");
190 dbuf_printf (oBufExt, "\textern WSAVE\n");
191 for (i = size - 4; i >= 0; i--) {
193 SNPRINTF(&buffer[0], 127, "STK%02d", i);
194 dbuf_printf (oBufExt, "\textern %s\n", &buffer[0]);
195 pic14_stringInSet(&buffer[0], &emitted, 1);
198 dbuf_printf (oBuf, "\n");
202 emitIfNew(struct dbuf_s *oBuf, set **emitted, const char *fmt,
205 int wasPresent = pic14_stringInSet(name, emitted, 1);
208 dbuf_printf (oBuf, fmt, name);
210 return (!wasPresent);
213 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
214 extern int IS_CONFIG_ADDRESS( int addr );
216 pic14_constructAbsMap (struct dbuf_s *oBuf, struct dbuf_s *gloBuf)
218 memmap *maps[] = { data, sfr, NULL };
223 int addr, min=-1, max=-1;
226 for (i=0; maps[i] != NULL; i++)
228 for (sym = (symbol *)setFirstItem (maps[i]->syms);
229 sym; sym = setNextItem (maps[i]->syms))
231 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
233 addr = SPEC_ADDR(sym->etype);
235 /* handle CONFIG words here */
236 if (IS_CONFIG_ADDRESS( addr ))
238 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
239 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
241 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
243 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
248 if (max == -1 || addr > max) max = addr;
249 if (min == -1 || addr < min) min = addr;
250 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
251 aliases = hTabItemWithKey (ht, addr);
253 /* May not use addSetHead, as we cannot update the
254 * list's head in the hastable `ht'. */
255 addSet (&aliases, sym);
257 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
258 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
261 addSet (&aliases, sym);
262 hTabAddItem (&ht, addr, aliases);
268 /* now emit definitions for all absolute symbols */
269 dbuf_printf (oBuf, "%s", iComments2);
270 dbuf_printf (oBuf, "; absolute symbol definitions\n");
271 dbuf_printf (oBuf, "%s", iComments2);
272 for (addr=min; addr <= max; addr++)
275 aliases = hTabItemWithKey (ht, addr);
276 if (aliases && elementsInSet(aliases)) {
277 /* Make sure there is no initialized value at this location! */
278 for (sym = setFirstItem(aliases); sym; sym = setNextItem(aliases)) {
279 if (sym->ival) break;
283 dbuf_printf (oBuf, "UD_abs_%s_%x\tudata_ovr\t0x%04x\n",
284 moduleName, addr, addr);
285 for (sym = setFirstItem (aliases); sym;
286 sym = setNextItem (aliases))
288 if (getSize(sym->type) > size) {
289 size = getSize(sym->type);
292 /* initialized values are handled somewhere else */
293 if (sym->ival) continue;
295 /* emit STATUS as well as _STATUS, required for SFRs only */
296 //dbuf_printf (oBuf, "%s\tres\t0\n", sym->name);
297 dbuf_printf (oBuf, "%s\n", sym->rname);
299 if (IS_GLOBAL(sym) && !IS_STATIC(sym->etype)) {
300 //emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->name);
301 emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
304 dbuf_printf (oBuf, "\tres\t%d\n", size);
310 /*-----------------------------------------------------------------*/
311 /* emitRegularMap - emit code for maps with no special cases */
312 /*-----------------------------------------------------------------*/
314 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
319 /* print the area name */
321 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
323 for (sym = setFirstItem (map->syms); sym;
324 sym = setNextItem (map->syms)) {
326 //printf("%s\n",sym->name);
328 /* ignore if config word */
329 if (SPEC_ABSA(sym->etype)
330 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
333 /* if extern then add it into the extern list */
334 if (IS_EXTERN (sym->etype)) {
335 addSetHead (&externs, sym);
339 /* if allocation required check is needed
340 then check if the symbol really requires
341 allocation only for local variables */
342 if (arFlag && !IS_AGGREGATE (sym->type) &&
343 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
344 !sym->allocreq && sym->level)
347 /* if global variable & not static or extern
348 and addPublics allowed then add it to the public set */
349 if ((sym->level == 0 ||
350 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
352 !IS_STATIC (sym->etype))
354 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
355 addSetHead (&publics, sym);
358 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
361 /* if extern then do nothing or is a function
363 if (IS_FUNC (sym->type))
366 /* print extra debug info if required */
367 if (options.debug || sym->level == 0)
369 if (!sym->level) /* global */
370 if (IS_STATIC (sym->etype))
371 dbuf_printf (&map->oBuf, "F%s_", moduleName); /* scope is file */
373 dbuf_printf (&map->oBuf, "G_"); /* scope is global */
375 /* symbol is local */
376 dbuf_printf (&map->oBuf, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
377 dbuf_printf (&map->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
380 /* absolute symbols are handled in pic14_constructAbsMap */
381 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
384 /* if it has an absolute address then generate
385 an equate for this no need to allocate space */
386 if (0 && SPEC_ABSA (sym->etype))
388 //if (options.debug || sym->level == 0)
389 //dbuf_printf (&map->oBuf,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
391 dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
393 SPEC_ADDR (sym->etype));
399 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
400 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
401 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
402 if (IS_BITVAR (sym->etype))
409 emitSymbol (&map->oBuf,
412 getSize (sym->type) & 0xffff,
413 SPEC_ABSA(sym->etype)
414 ? SPEC_ADDR(sym->etype)
423 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
425 for (i = 1; i < size; i++)
426 dbuf_printf (&map->oBuf, "\t%s_%d\n", sym->rname, i);
431 //dbuf_printf (&map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
434 /* if it has a initial value then do it only if
435 it is a global variable */
437 /* mark symbol as already defined */
438 pic14_stringInSet(sym->name, &emitted, 1);
439 pic14_stringInSet(sym->rname, &emitted, 1);
442 /* if it has a initial value then do it only if
443 it is a global variable */
444 if (sym->ival && sym->level == 0) {
447 if (IS_AGGREGATE (sym->type))
448 ival = initAggregates (sym, sym->ival, NULL);
450 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
451 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
452 codeOutBuf = &statsg->oBuf;
454 eBBlockFromiCode (iCodeFromAst (ival));
464 /*-----------------------------------------------------------------*/
465 /* printIvalType - generates ival for int/char */
466 /*-----------------------------------------------------------------*/
468 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
473 //fprintf(stderr, "%s\n",__FUNCTION__);
475 /* if initList is deep */
476 if (ilist->type == INIT_DEEP)
477 ilist = ilist->init.deep;
479 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
480 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
483 if (!(val = list2val (ilist))) {
484 // assuming a warning has been thrown
485 val = constCharVal (0);
488 if (val->type != type) {
489 val = valCastLiteral(type, floatFromVal(val));
493 ulval = ulFromVal (val);
497 switch (getSize (type)) {
499 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
503 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
504 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
508 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
509 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
510 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
511 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
516 /*-----------------------------------------------------------------*/
517 /* printIvalBitFields - generate initializer for bitfields */
518 /*-----------------------------------------------------------------*/
519 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
523 initList *lilist = *ilist ;
524 unsigned long ival = 0;
530 val = list2val(lilist);
532 if (SPEC_BLEN(lsym->etype) > 8) {
533 size += ((SPEC_BLEN (lsym->etype) / 8) +
534 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
537 size = ((SPEC_BLEN (lsym->etype) / 8) +
538 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
541 i <<= SPEC_BSTR (lsym->etype);
543 if (! ( lsym->next &&
544 (IS_BITFIELD(lsym->next->type)) &&
545 (SPEC_BSTR(lsym->next->etype)))) break;
547 lilist = lilist->next;
551 //tfprintf (oFile, "\t!db !constbyte\n",ival);
552 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
556 //tfprintf (oFile, "\t!dw !constword\n",ival);
557 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
558 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
561 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
562 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
563 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
564 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
565 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
572 /*-----------------------------------------------------------------*/
573 /* printIvalStruct - generates initial value for structures */
574 /*-----------------------------------------------------------------*/
575 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
578 initList *iloop = NULL;
580 sflds = SPEC_STRUCT (type)->fields;
583 if (ilist->type != INIT_DEEP) {
584 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
588 iloop = ilist->init.deep;
591 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
592 if (IS_BITFIELD(sflds->type)) {
593 printIvalBitFields(&sflds,&iloop,pb);
595 printIval (sym, sflds->type, iloop, pb);
599 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
604 /*-----------------------------------------------------------------*/
605 /* printIvalChar - generates initital value for character array */
606 /*-----------------------------------------------------------------*/
608 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
616 //fprintf(stderr, "%s\n",__FUNCTION__);
620 val = list2val (ilist);
622 /* if the value is a character string */
623 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
625 ilen = DCL_ELEM(val->type);
627 if (!DCL_ELEM (type))
628 DCL_ELEM (type) = ilen;
630 /* emit string constant */
631 for (remain = 0; remain < ilen; remain++) {
632 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
635 /* fill array up to desired size */
636 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
638 //tfprintf (oFile, "\t!db !constbyte\n", 0);
639 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
646 //printChar (oFile, s, strlen (s) + 1);
648 for(remain=0; remain<(int)strlen(s); remain++) {
649 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
650 //fprintf(stderr,"0x%02x ",s[remain]);
652 //fprintf(stderr,"\n");
657 /*-----------------------------------------------------------------*/
658 /* printIvalArray - generates code for array initialization */
659 /*-----------------------------------------------------------------*/
661 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
670 /* take care of the special case */
671 /* array of characters can be init */
673 if (IS_CHAR (type->next)) {
674 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
675 if (!IS_LITERAL(list2val(ilist)->etype)) {
676 werror (W_INIT_WRONG);
679 if (printIvalChar (type,
680 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
681 pb, SPEC_CVAL (sym->etype).v_char))
684 /* not the special case */
685 if (ilist->type != INIT_DEEP) {
686 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
690 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
691 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
692 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
695 printIval (sym, type->next, iloop, pb);
699 if (DCL_ELEM(type)) {
700 // pad with zeros if needed
701 if (size<DCL_ELEM(type)) {
702 size = (DCL_ELEM(type) - size) * getSize(type->next);
704 //tfprintf (oFile, "\t!db !constbyte\n", 0);
705 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
709 // we have not been given a size, but we now know it
710 DCL_ELEM (type) = size;
716 /*-----------------------------------------------------------------*/
717 /* printIvalPtr - generates code for initial value of pointers */
718 /*-----------------------------------------------------------------*/
719 extern value *initPointer (initList *, sym_link *toType);
722 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
729 fprintf (stderr, "FIXME: initializers for pointers...\n");
730 printTypeChain (type, stderr);
732 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
733 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
735 if (ilist && (ilist->type == INIT_DEEP))
736 ilist = ilist->init.deep;
738 /* function pointers */
739 if (IS_FUNC (type->next))
741 assert ( !"function pointers not yet handled" );
742 //printIvalFuncPtr (type, ilist, pb);
745 if (!(val = initPointer (ilist, type)))
748 if (IS_CHAR (type->next))
750 if (printIvalChar (type, ilist, pb, NULL)) return;
754 if (compareType (type, val->type) == 0)
756 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
757 printFromToType (val->type, type);
760 if (IS_LITERAL (val->etype))
762 switch (getSize (type))
765 fprintf (stderr, "BYTE: %i\n", (unsigned char) ulFromVal (val) & 0x00FF);
768 fprintf (stderr, "WORD: %i\n", (unsigned int) ulFromVal (val) & 0x00FFFF);
770 case 3: /* gneric pointers */
771 assert ( !"generic pointers not yet handled" );
773 fprintf (stderr, "LONG: %i\n", (unsigned int) ulFromVal (val) & 0x0000FFFFFFFF);
776 assert ( !"invaild size of value -- aborting" );
782 /* now handle symbolic values */
783 switch (getSize (type))
786 fprintf (stderr, "BYTE: %s", val->name);
789 fprintf (stderr, "WORD: %s", val->name);
792 fprintf (stderr, "LONG: %s", val->name);
795 assert ( !"invalid size of (symbolic) value -- aborting" );
799 /*-----------------------------------------------------------------*/
800 /* printIval - generates code for initial value */
801 /*-----------------------------------------------------------------*/
803 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
808 /* if structure then */
809 if (IS_STRUCT (type))
811 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
812 printIvalStruct (sym, type, ilist, pb);
816 /* if this is an array */
819 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
820 printIvalArray (sym, type, ilist, pb);
824 /* if this is a pointer */
827 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
828 printIvalPtr (sym, type, ilist, pb);
832 /* if type is SPECIFIER */
835 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
836 printIvalType (sym, type, ilist, pb);
843 extern void pCodeConstString(char *name, char *value);
844 /*-----------------------------------------------------------------*/
845 /* emitStaticSeg - emitcode for the static segment */
846 /*-----------------------------------------------------------------*/
848 pic14emitStaticSeg (memmap * map)
852 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
854 //fprintf(stderr, "%s\n",__FUNCTION__);
856 /* for all variables in this segment do */
857 for (sym = setFirstItem (map->syms); sym;
858 sym = setNextItem (map->syms))
860 /* if extern then add it into the extern list */
861 if (IS_EXTERN (sym->etype)) {
862 addSetHead (&externs, sym);
866 /* if it is not static add it to the public
868 if (!IS_STATIC (sym->etype))
869 addSetHead (&publics, sym);
871 /* print extra debug info if required */
872 if (options.debug || sym->level == 0)
876 if (IS_STATIC (sym->etype))
877 dbuf_printf (&code->oBuf, "F%s_", moduleName); /* scope is file */
879 dbuf_printf (&code->oBuf, "G_"); /* scope is global */
882 /* symbol is local */
883 dbuf_printf (&code->oBuf, "L%s_",
884 (sym->localof ? sym->localof->name : "-null-"));
885 dbuf_printf (&code->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
889 /* if it has an absolute address */
890 if (SPEC_ABSA (sym->etype))
892 if (options.debug || sym->level == 0)
893 dbuf_printf (&code->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
895 dbuf_printf (&code->oBuf, "%s\t=\t0x%04x\n",
897 SPEC_ADDR (sym->etype));
901 if (options.debug || sym->level == 0)
902 dbuf_printf (&code->oBuf, " == .\n");
904 /* if it has an initial value */
910 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
912 resolveIvalSym (sym->ival, sym->type);
913 //printIval (sym, sym->type, sym->ival, &code->oBuf);
914 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
916 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
918 printIval (sym, sym->type, sym->ival, pb);
926 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
927 /* special case for character strings */
928 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
929 SPEC_CVAL (sym->etype).v_char)
930 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
931 /*printChar (code->oFile,
932 SPEC_CVAL (sym->etype).v_char,
933 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
935 dbuf_printf (&code->oBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
945 /*-----------------------------------------------------------------*/
946 /* emitMaps - emits the code for the data portion the code */
947 /*-----------------------------------------------------------------*/
951 pic14_constructAbsMap (&sfr->oBuf);
952 emitPseudoStack(&sfr->oBuf, &sfr->oBuf);
953 /* no special considerations for the following
954 data, idata & bit & xdata */
955 pic14emitRegularMap (data, TRUE, TRUE);
956 pic14emitRegularMap (idata, TRUE, TRUE);
957 pic14emitRegularMap (bit, TRUE, FALSE);
958 pic14emitRegularMap (xdata, TRUE, TRUE);
959 pic14emitRegularMap (sfr, TRUE, FALSE);
960 pic14emitRegularMap (sfrbit, FALSE, FALSE);
961 pic14emitRegularMap (code, TRUE, FALSE);
962 pic14emitStaticSeg (statsg);
963 pic14emitStaticSeg (c_abs);
967 /*-----------------------------------------------------------------*/
968 /* createInterruptVect - creates the interrupt vector */
969 /*-----------------------------------------------------------------*/
970 pCodeOp *popGetExternal (char *str, int isReg);
972 pic14createInterruptVect (struct dbuf_s * vBuf)
974 mainf = newSymbol ("main", 0);
977 /* only if the main function exists */
978 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
980 struct options *op = &options;
981 if (!(op->cc_only || noAssemble))
982 // werror (E_NO_MAIN);
983 fprintf(stderr,"WARNING: function 'main' undefined\n");
987 /* if the main is only a prototype ie. no body then do nothing */
988 if (!IFFUNC_HASBODY(mainf->type))
990 /* if ! compile only then main function should be present */
991 if (!(options.cc_only || noAssemble))
992 // werror (E_NO_MAIN);
993 fprintf(stderr,"WARNING: function 'main' undefined\n");
997 dbuf_printf (vBuf, "%s", iComments2);
998 dbuf_printf (vBuf, "; reset vector \n");
999 dbuf_printf (vBuf, "%s", iComments2);
1000 dbuf_printf (vBuf, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1001 dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */
1002 dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n");
1003 dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n");
1004 popGetExternal("__sdcc_gsinit_startup", 0);
1008 /*-----------------------------------------------------------------*/
1009 /* initialComments - puts in some initial comments */
1010 /*-----------------------------------------------------------------*/
1012 pic14initialComments (FILE * afile)
1014 initialComments (afile);
1015 fprintf (afile, "; PIC port for the 14-bit core\n");
1016 fprintf (afile, iComments2);
1021 pic14_stringInSet(const char *str, set **world, int autoAdd)
1028 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1031 if (0 == strcmp(s, str)) return 1;
1035 if (autoAdd) addSet(world, Safe_strdup(str));
1041 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1043 if (!pic14_stringInSet(sym, &emitted, 1)) {
1044 /* sym was not in emittedSymbols */
1045 if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1046 /* sym is not a locally defined function---avoid bug #1443651 */
1047 fprintf( file, fmt, sym );
1056 /*-------------------------------------------------------------------*/
1057 /* emitSymbol - write a symbol definition only if it is not */
1058 /* already present */
1059 /*-------------------------------------------------------------------*/
1061 emitSymbol (struct dbuf_s *oBuf, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
1063 static unsigned int sec_idx = 0;
1065 /* workaround: variables declared via `sbit' result in a numeric
1066 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
1067 * sbit is heavily used in the inc2h-generated header files!
1069 if (!is_valid_identifier(name))
1071 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
1075 /* check whether the symbol is already defined */
1076 if (pic14_stringInSet(name, &emitted, 1)) return;
1078 /* new symbol -- define it */
1079 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
1081 dbuf_printf (oBuf, "%s\tEQU\t0x%04x\n", name, addr);
1083 /* we place each symbol into a section of its own to allow the linker
1084 * to distribute the data into all available memory banks */
1085 if (!section_type) section_type = "udata";
1088 /* absolute symbols are handled in pic14_constructAbsMap */
1091 if (globalize) dbuf_printf (oBuf, "\tglobal\t%s\n", name);
1092 dbuf_printf (oBuf, "udata_%s_%u\t%s\n", moduleName,
1093 sec_idx++, section_type);
1094 dbuf_printf (oBuf, "%s\tres\t%d\n", name, size);
1102 /*-----------------------------------------------------------------*/
1103 /* printExterns - generates extern for external variables */
1104 /*-----------------------------------------------------------------*/
1106 pic14printExterns (FILE * afile)
1110 fprintf (afile, "%s", iComments2);
1111 fprintf (afile, "; extern variables in this module\n");
1112 fprintf (afile, "%s", iComments2);
1114 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1115 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1118 /*-----------------------------------------------------------------*/
1119 /* printPublics - generates .global for publics */
1120 /*-----------------------------------------------------------------*/
1122 pic14printPublics (FILE * afile)
1126 fprintf (afile, "%s", iComments2);
1127 fprintf (afile, "; public variables in this module\n");
1128 fprintf (afile, "%s", iComments2);
1130 for (sym = setFirstItem (publics); sym;
1131 sym = setNextItem (publics)) {
1133 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1134 if (!IS_BITVAR(sym->type))
1135 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1137 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1138 /* Not any longer! */
1139 //if (!SPEC_ABSA (sym->etype))
1140 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1147 * Interface to BANKSEL generation.
1148 * This function should return != 0 iff str1 and str2 denote operands that
1149 * are known to be allocated into the same bank. Consequently, there will
1150 * be no BANKSEL emitted if str2 is accessed while str1 has been used to
1151 * select the current bank just previously.
1153 * If in doubt, return 0.
1156 pic14_operandsAllocatedInSameBank(const char *str1, const char *str2) {
1157 // see pic14printLocals
1159 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
1160 // no clustering applied, each register resides in its own bank
1162 // check whether BOTH names are local registers
1163 // XXX: This is some kind of shortcut, should be safe...
1164 // In this model, all r0xXXXX are allocated into a single section
1165 // per file, so no BANKSEL required if accessing a r0xXXXX after a
1166 // (different) r0xXXXX. Works great for multi-byte operands.
1167 if (str1 && str2 && str1[0] == 'r' && str2[0] == 'r') return (1);
1170 // assume operands in different banks
1175 pic14printLocals (struct dbuf_s *oBuf)
1177 set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
1178 dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
1180 int i, is_first = 1;
1181 static unsigned sectionNr = 0;
1183 /* emit all registers from all possible sets */
1184 for (i = 0; i < 6; i++) {
1185 if (allregs[i] == NULL) continue;
1187 for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
1188 if (reg->isEmitted) continue;
1190 if (reg->wasUsed && !reg->isExtern) {
1191 if (!pic14_stringInSet(reg->name, &emitted, 1)) {
1193 // Should not happen, really...
1194 assert ( !"Compiler-assigned variables should not be pinned... This is a bug." );
1195 dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
1196 moduleName, sectionNr++, reg->address, reg->name, reg->size);
1198 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
1199 // assign each local register into its own section
1200 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
1201 moduleName, sectionNr++, reg->name, reg->size);
1203 // group all local registers into a single section
1204 // This should greatly improve BANKSEL generation...
1206 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++);
1209 dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size);
1219 /*-----------------------------------------------------------------*/
1220 /* emitOverlay - will emit code for the overlay stuff */
1221 /*-----------------------------------------------------------------*/
1223 pic14emitOverlay (struct dbuf_s * aBuf)
1227 /* if (!elementsInSet (ovrSetSets))*/
1229 /* the hack below, fixes translates for devices which
1230 * only have udata_shr memory */
1231 dbuf_printf (aBuf, "%s\t%s\n",
1232 (elementsInSet(ovrSetSets)?"":";"),
1233 port->mem.overlay_name);
1235 /* for each of the sets in the overlay segment do */
1236 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1237 ovrset = setNextItem (ovrSetSets))
1242 if (elementsInSet (ovrset))
1244 /* this dummy area is used to fool the assembler
1245 otherwise the assembler will append each of these
1246 declarations into one chunk and will not overlay
1249 /* I don't think this applies to us. We are using gpasm. CRF */
1251 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1252 /* output the area informtion */
1253 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1256 for (sym = setFirstItem (ovrset); sym;
1257 sym = setNextItem (ovrset))
1260 /* if extern then do nothing */
1261 if (IS_EXTERN (sym->etype))
1264 /* if allocation required check is needed
1265 then check if the symbol really requires
1266 allocation only for local variables */
1267 if (!IS_AGGREGATE (sym->type) &&
1268 !(sym->_isparm && !IS_REGPARM (sym->etype))
1269 && !sym->allocreq && sym->level)
1272 /* if global variable & not static or extern
1273 and addPublics allowed then add it to the public set */
1274 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1275 && !IS_STATIC (sym->etype))
1276 addSetHead (&publics, sym);
1278 /* if extern then do nothing or is a function
1280 if (IS_FUNC (sym->type))
1283 /* print extra debug info if required */
1284 if (options.debug || sym->level == 0)
1288 if (IS_STATIC (sym->etype))
1289 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
1291 dbuf_printf (aBuf, "G_"); /* scope is global */
1294 /* symbol is local */
1295 dbuf_printf (aBuf, "L%s_",
1296 (sym->localof ? sym->localof->name : "-null-"));
1297 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
1300 /* if is has an absolute address then generate
1301 an equate for this no need to allocate space */
1302 if (SPEC_ABSA (sym->etype))
1305 if (options.debug || sym->level == 0)
1306 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1308 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1310 SPEC_ADDR (sym->etype));
1314 if (options.debug || sym->level == 0)
1315 dbuf_printf (aBuf, "==.\n");
1317 /* allocate space */
1318 dbuf_printf (aBuf, "%s:\n", sym->rname);
1319 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1328 pic14_emitInterruptHandler (FILE * asmFile)
1330 if (pic14_hasInterrupt)
1333 fprintf (asmFile, "%s", iComments2);
1334 fprintf (asmFile, "; interrupt and initialization code\n");
1335 fprintf (asmFile, "%s", iComments2);
1336 // Note - for mplink may have to enlarge section vectors in .lnk file
1337 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1338 // source files's code segment (interrupt.c -> code_interrupt)
1339 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1341 /* interrupt service routine */
1342 fprintf (asmFile, "__sdcc_interrupt\n");
1343 copypCode(asmFile, 'I');
1347 /*-----------------------------------------------------------------*/
1348 /* glue - the final glue that hold the whole thing together */
1349 /*-----------------------------------------------------------------*/
1354 struct dbuf_s ovrBuf;
1357 dbuf_init(&ovrBuf, 4096);
1358 dbuf_init(&vBuf, 4096);
1360 pCodeInitRegisters();
1362 /* check for main() */
1363 mainf = newSymbol ("main", 0);
1365 mainf = findSymWithLevel (SymbolTab, mainf);
1367 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1369 /* main missing -- import stack from main module */
1370 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1371 pic14_options.isLibrarySource = 1;
1375 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1377 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1380 /* entry point @ start of CSEG */
1381 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1382 /* put in the call to main */
1383 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1385 if (options.mainreturn) {
1387 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1388 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1392 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1393 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1399 /* At this point we've got all the code in the form of pCode structures */
1400 /* Now it needs to be rearranged into the order it should be placed in the */
1403 movepBlock2Head('P'); // Last
1404 movepBlock2Head(code->dbName);
1405 movepBlock2Head('X');
1406 movepBlock2Head(statsg->dbName); // First
1409 /* print the global struct definitions */
1413 /* emit code for the all the variables declared */
1415 /* do the overlay segments */
1416 pic14emitOverlay(&ovrBuf);
1418 /* PENDING: this isnt the best place but it will do */
1419 if (port->general.glue_up_main) {
1420 /* create the interrupt vector table */
1421 pic14createInterruptVect (&vBuf);
1426 ReuseReg(); // ReuseReg where call tree permits
1432 if (options.debug) pcode_test();
1435 /* now put it all together into the assembler file */
1436 /* create the assembler file name */
1438 if ((noAssemble || options.c1mode) && fullDstFileName)
1440 sprintf (buffer, fullDstFileName);
1444 sprintf (buffer, dstFileName);
1445 strcat (buffer, ".asm");
1448 if (!(asmFile = fopen (buffer, "w"))) {
1449 werror (E_FILE_OPEN_ERR, buffer);
1453 /* prepare statistics */
1454 resetpCodeStatistics ();
1456 /* initial comments */
1457 pic14initialComments (asmFile);
1459 /* print module name */
1460 fprintf (asmFile, "%s\t.file\t\"%s\"\n",
1461 options.debug ? "" : ";", fullSrcFileName);
1463 /* Let the port generate any global directives, etc. */
1464 if (port->genAssemblerPreamble)
1466 port->genAssemblerPreamble(asmFile);
1469 /* print the global variables in this module */
1470 //pic14printPublics (asmFile);
1472 /* print the extern variables in this module */
1473 //pic14printExterns (asmFile);
1475 /* copy the sfr segment */
1477 fprintf (asmFile, "%s", iComments2);
1478 fprintf (asmFile, "; special function registers\n");
1479 fprintf (asmFile, "%s", iComments2);
1480 dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1483 if (udata_section_name) {
1484 sprintf(udata_name,"%s",udata_section_name);
1486 sprintf(udata_name,"data_%s",moduleName);
1488 fprintf (asmFile, "%s", iComments2);
1489 fprintf (asmFile, "; udata\n");
1490 fprintf (asmFile, "%s", iComments2);
1491 fprintf (asmFile, "%s\tudata\n", udata_name);
1492 dbuf_write_and_destroy(&data->oBuf, asmFile);
1495 /* Put all variables into a cblock */
1498 /* emit initialized data */
1499 showAllMemmaps(asmFile);
1501 /* print the locally defined variables in this module */
1502 writeUsedRegs(asmFile);
1504 /* create the overlay segments */
1505 fprintf (asmFile, "%s", iComments2);
1506 fprintf (asmFile, "; overlayable items in internal ram \n");
1507 fprintf (asmFile, "%s", iComments2);
1508 dbuf_write_and_destroy (&ovrBuf, asmFile);
1512 /* create the stack segment MOF */
1513 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1514 fprintf (asmFile, "%s", iComments2);
1515 fprintf (asmFile, "; Stack segment in internal ram \n");
1516 fprintf (asmFile, "%s", iComments2);
1517 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1518 ";__start__stack:\n;\t.ds\t1\n\n");
1521 /* create the idata segment */
1522 fprintf (asmFile, "%s", iComments2);
1523 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1524 fprintf (asmFile, "%s", iComments2);
1525 dbuf_write_and_destroy (&idata->oBuf, asmFile);
1527 /* if external stack then reserve space of it */
1528 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1529 fprintf (asmFile, "%s", iComments2);
1530 fprintf (asmFile, "; external stack \n");
1531 fprintf (asmFile, "%s", iComments2);
1532 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1533 fprintf (asmFile,";\t.ds 256\n");
1536 /* copy xtern ram data */
1537 fprintf (asmFile, "%s", iComments2);
1538 fprintf (asmFile, "; external ram data\n");
1539 fprintf (asmFile, "%s", iComments2);
1540 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1544 /* copy the bit segment */
1546 fprintf (asmFile, "%s", iComments2);
1547 fprintf (asmFile, "; bit data\n");
1548 fprintf (asmFile, "%s", iComments2);
1549 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1552 /* copy the interrupt vector table */
1553 if (mainf && IFFUNC_HASBODY(mainf->type))
1554 dbuf_write_and_destroy (&vBuf, asmFile);
1556 dbuf_destroy(&vBuf);
1558 /* create interupt ventor handler */
1559 pic14_emitInterruptHandler (asmFile);
1561 /* copy over code */
1562 fprintf (asmFile, "%s", iComments2);
1563 fprintf (asmFile, "; code\n");
1564 fprintf (asmFile, "%s", iComments2);
1565 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1568 copypCode(asmFile, 'X');
1570 /* _main function */
1571 copypCode(asmFile, 'M');
1573 /* other functions */
1574 copypCode(asmFile, code->dbName);
1577 copypCode(asmFile, 'P');
1579 dumppCodeStatistics (asmFile);
1581 fprintf (asmFile,"\tend\n");
1584 pic14_debugLogClose();
1588 * Deal with initializers.
1593 #define DEBUGprintf printf
1596 #define DEBUGprintf 1 ? (void)0 : (void)printf
1600 void ast_print (ast * tree, FILE *outfile, int indent);
1607 showInitList(initList *list, int level)
1609 static const char *list_type[] = { "INIT_NODE", "INIT_DEEP", "INIT_HOLE" };
1610 static const char *ast_type[] = { "EX_OP", "EX_VALUE", "EX_LINK", "EX_OPERAND" };
1613 printf (" %d: type %u (%s), init %p, next %p\n", level, list->type, list_type[list->type], list->init.node, list->next);
1614 if (list->type == INIT_DEEP) {
1615 showInitList(list->init.deep, level + 1);
1616 } else if (list->type == INIT_NODE) {
1617 ast = list->init.node;
1618 printf (" type %u (%s), level %d, block %d, seqPoint %d\n",
1619 ast->type, ast_type[ast->type], ast->level, ast->block, ast->seqPoint);
1620 if (ast->type == EX_VALUE) {
1621 printf (" VAL %lf\n", floatFromVal(ast->opval.val));
1622 } else if (ast->type == EX_LINK) {
1623 printTypeChain(ast->opval.lnk, NULL);
1624 } else if (ast->type == EX_OP) {
1625 printf (" OP %u\n", ast->opval.op);
1634 * DEBUG: Print a value.
1637 printVal(value *val)
1639 printf ("value %p: name %s, type %p, etype %p, sym %s, vArgs %d, lit 0x%lx/%ld\n",
1640 val, val->name, val->type, val->etype,
1641 val->sym ? val->sym->name : NULL, val->vArgs,
1642 (long) ulFromVal (val), (long) ulFromVal (val));
1643 printTypeChain(val->type, stdout);
1645 printTypeChain(val->etype, stdout);
1649 //prototype from ../SDCCicode.c
1650 operand *operandFromAst (ast * tree,int lvl);
1653 parseIvalAst (ast *node, int *inCodeSpace) {
1655 char *buffer = NULL;
1658 if (IS_AST_VALUE(node)) {
1659 value *val = AST_VALUE(node);
1660 symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
1661 if (inCodeSpace && val->type
1662 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
1666 if (inCodeSpace && sym
1667 && (IS_FUNC(sym->type)
1668 || IS_CODE(getSpec(sym->type))))
1673 DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
1674 if (IS_AST_LIT_VALUE(node)) {
1675 buffer = Safe_alloc(LEN);
1676 SNPRINTF(buffer, LEN, "0x%lx", AST_ULONG_VALUE (node));
1677 } else if (IS_AST_SYM_VALUE(node)) {
1678 assert ( AST_SYMBOL(node) );
1680 printf ("sym %s: ", AST_SYMBOL(node)->rname);
1681 printTypeChain(AST_SYMBOL(node)->type, stdout);
1682 printTypeChain(AST_SYMBOL(node)->etype, stdout);
1683 printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
1685 buffer = Safe_strdup(AST_SYMBOL(node)->rname);
1687 assert ( !"Invalid values type for initializers in AST." );
1689 } else if (IS_AST_OP(node)) {
1690 DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
1691 switch (node->opval.op) {
1693 assert (node->right);
1694 buffer = parseIvalAst(node->right, inCodeSpace);
1695 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1698 assert ( node->left && !node->right );
1699 buffer = parseIvalAst(node->left, inCodeSpace);
1700 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1703 assert (node->left && node->right );
1704 left = parseIvalAst(node->left, inCodeSpace);
1705 right = parseIvalAst(node->right, inCodeSpace);
1706 buffer = Safe_alloc(LEN);
1707 SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
1708 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1713 assert ( node->left && node->right );
1714 assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
1715 right = parseIvalAst(node->right, inCodeSpace);
1716 buffer = Safe_alloc(LEN);
1717 SNPRINTF(buffer, LEN, "(%s + %u * %s)",
1718 AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
1720 DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
1723 assert ( !"Unhandled operation in initializer." );
1727 assert ( !"Invalid construct in initializer." );
1734 * Emit the section preamble, absolute location (if any) and
1735 * symbol name(s) for intialized data.
1738 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
1741 static int in_code = 0;
1742 static int sectionNr = 0;
1745 // code or data space?
1746 if (IS_CODE(getSpec(sym->type))) {
1753 dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
1754 if (SPEC_ABSA(getSpec(sym->type))) {
1755 // specify address for absolute symbols
1756 dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
1758 dbuf_printf(oBuf, "\n%s\n", sym->rname);
1760 addSet(&emitted, sym->rname);
1765 char *get_op(pCodeOp *pcop,char *buffer, size_t size);
1767 * Actually emit the initial values in .asm format.
1770 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
1776 int inCodeSpace = 0;
1780 assert (size <= sizeof(long));
1781 assert (!list || (list->type == INIT_NODE));
1782 node = list ? list->init.node : NULL;
1784 in_code = emitIvalLabel(oBuf, sym);
1785 if (!in_code) dbuf_printf (oBuf, "\tdb\t");
1788 // initialize as zero
1789 for (i=0; i < size; i++) {
1791 dbuf_printf (oBuf, "\tretlw 0x00");
1793 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
1796 dbuf_printf (oBuf, "\n");
1801 if (constExprTree(node) && (val = constExprValue(node, 0))) {
1802 op = operandFromValue(val);
1803 DEBUGprintf ("%s: constExpr ", __FUNCTION__);
1805 } else if (IS_AST_VALUE(node)) {
1806 op = operandFromAst(node, 0);
1807 } else if (IS_AST_OP(node)) {
1808 str = parseIvalAst(node, &inCodeSpace);
1809 DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
1812 assert ( !"Unhandled construct in intializer." );
1818 //printOperand(op, of);
1821 for (i=0; i < size; i++) {
1825 * FIXME: This is hacky and needs some more thought.
1827 if (op && IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) {
1828 /* This branch is introduced to fix #1427663. */
1829 PCOI(AOP(op)->aopu.pcop)->offset+=i;
1830 text = get_op(AOP(op)->aopu.pcop, NULL, 0);
1831 PCOI(AOP(op)->aopu.pcop)->offset-=i;
1833 text = op ? aopGet(AOP(op), i, 0, 0)
1834 : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
1837 dbuf_printf (oBuf, "\tretlw %s\n", text);
1839 dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
1842 dbuf_printf (oBuf, "\n");
1846 * For UNIONs, we first have to find the correct alternative to map the
1847 * initializer to. This function maps the structure of the initializer to
1848 * the UNION members recursively.
1849 * Returns the type of the first `fitting' member.
1852 matchIvalToUnion (initList *list, sym_link *type, int size)
1858 if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
1861 if (!list || (list->type == INIT_NODE)) {
1862 DEBUGprintf ("OK, simple type\n");
1865 DEBUGprintf ("ERROR, simple type\n");
1868 } else if (IS_BITFIELD(type)) {
1869 if (!list || (list->type == INIT_NODE)) {
1870 DEBUGprintf ("OK, bitfield\n");
1873 DEBUGprintf ("ERROR, bitfield\n");
1876 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
1877 if (!list || (list->type == INIT_DEEP)) {
1878 if (list) list = list->init.deep;
1879 sym = SPEC_STRUCT(type)->fields;
1881 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
1882 if (!matchIvalToUnion(list, sym->type, 0)) {
1883 DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
1886 if (list) list = list->next;
1890 // excess initializers?
1892 DEBUGprintf ("ERROR, excess initializers\n");
1896 DEBUGprintf ("OK, struct\n");
1900 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
1901 if (!list || (list->type == INIT_DEEP)) {
1902 if (list) list = list->init.deep;
1903 sym = SPEC_STRUCT(type)->fields;
1905 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
1906 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
1907 && matchIvalToUnion(list, sym->type, size))
1909 DEBUGprintf ("Matched UNION member %s.\n", sym->name);
1916 DEBUGprintf ("ERROR, no match found.\n");
1919 assert ( !"Unhandled type in UNION." );
1922 assert ( !"No match found in UNION for the given initializer structure." );
1927 * Parse the type and its initializer and emit it (recursively).
1930 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
1937 size = getSize(my_type);
1939 if (IS_PTR(my_type)) {
1940 DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
1941 emitIvals(oBuf, topsym, list, 0, size);
1945 if (IS_ARRAY(my_type) && topsym && topsym->isstrlit) {
1946 str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
1947 emitIvalLabel(oBuf, topsym);
1949 dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
1954 if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
1955 fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
1956 assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
1960 if (IS_ARRAY(my_type)) {
1961 DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
1962 assert (!list || list->type == INIT_DEEP);
1963 if (list) list = list->init.deep;
1964 for (i = 0; i < DCL_ELEM(my_type); i++) {
1965 emitInitVal(oBuf, topsym, my_type->next, list);
1967 if (list) list = list->next;
1972 if (IS_FLOAT(my_type)) {
1974 DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
1975 emitIvals(oBuf, topsym, list, 0, size);
1979 if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
1980 // integral type, 8, 16, or 32 bit
1981 DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
1982 emitIvals(oBuf, topsym, list, 0, size);
1985 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
1987 DEBUGprintf ("(struct, %d byte) handled below\n", size);
1988 assert (!list || (list->type == INIT_DEEP));
1990 // iterate over struct members and initList
1991 if (list) list = list->init.deep;
1992 sym = SPEC_STRUCT(my_type)->fields;
1996 if (IS_BITFIELD(sym->type)) {
1997 while (sym && IS_BITFIELD(sym->type)) {
1998 assert (!list || ((list->type == INIT_NODE)
1999 && IS_AST_LIT_VALUE(list->init.node)));
2000 lit = (long) (list ? list2int(list) : 0);
2001 DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
2002 lit, SPEC_BLEN(getSpec(sym->type)),
2003 SPEC_BSTR(getSpec(sym->type)), bitfield);
2004 bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
2005 len += SPEC_BLEN(getSpec(sym->type));
2008 if (list) list = list->next;
2010 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
2011 len = (len + 7) & ~0x07; // round up to full bytes
2012 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
2017 emitInitVal(oBuf, topsym, sym->type, list);
2020 if (list) list = list->next;
2024 assert ( !"Excess initializers." );
2028 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
2030 DEBUGprintf ("(union, %d byte) handled below\n", size);
2031 assert (list && list->type == INIT_DEEP);
2033 // iterate over union members and initList, try to map number and type of fields and initializers
2034 my_type = matchIvalToUnion(list, my_type, size);
2036 emitInitVal(oBuf, topsym, my_type, list->init.deep);
2038 size -= getSize(my_type);
2040 // pad with (leading) zeros
2041 emitIvals(oBuf, NULL, NULL, 0, size);
2046 assert ( !"No UNION member matches the initializer structure.");
2047 } else if (IS_BITFIELD(my_type)) {
2048 assert ( !"bitfields should only occur in structs..." );
2051 printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
2052 assert( !"Unhandled initialized type.");
2057 * Emit a set of symbols.
2058 * type - 0: have symbol tell whether it is local, extern or global
2059 * 1: assume all symbols in set to be global
2060 * 2: assume all symbols in set to be extern
2063 emitSymbolSet(set *s, int type)
2067 unsigned sectionNr = 0;
2069 for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
2071 fprintf (stdout, "; name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
2072 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
2075 if (sym->etype && SPEC_ABSA(sym->etype)
2076 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))
2079 // handle config words
2080 pic14_assignConfigWordValue(SPEC_ADDR(sym->etype),
2081 (int)list2int(sym->ival));
2082 pic14_stringInSet(sym->rname, &emitted, 1);
2086 if (sym->isstrlit) {
2087 // special case: string literals
2088 emitInitVal(ivalBuf, sym, sym->type, NULL);
2092 if (type != 0 || sym->cdef
2093 || (!IS_STATIC(sym->etype)
2096 // bail out for ___fsadd and friends
2097 if (sym->cdef && !sym->used) continue;
2099 /* export or import non-static globals */
2100 if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
2102 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
2104 /* do not add to emitted set, it might occur again! */
2105 //if (!sym->used) continue;
2107 emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
2110 emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
2111 if (!sym->ival && !IS_FUNC(sym->type)) {
2112 // also define symbol
2113 if (IS_ABSOLUTE(sym->etype)) {
2114 // absolute location?
2115 //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
2116 // deferred to pic14_constructAbsMap
2118 dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
2119 dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
2123 pic14_stringInSet(sym->rname, &emitted, 1);
2127 //if (list) showInitList(list, 0);
2129 resolveIvalSym( list, sym->type );
2130 emitInitVal(ivalBuf, sym, sym->type, sym->ival);
2131 dbuf_printf (ivalBuf, "\n");
2137 * Iterate over all memmaps and emit their contents (attributes, symbols).
2140 showAllMemmaps(FILE *of)
2142 struct dbuf_s locBuf;
2144 xstack, istack, code, data, pdata, xdata, xidata, xinit,
2145 idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
2146 sfr, sfrbit, reg, generic, overlay, eeprom, home };
2150 DEBUGprintf ("---begin memmaps---\n");
2151 if (!extBuf) extBuf = dbuf_new(1024);
2152 if (!gloBuf) gloBuf = dbuf_new(1024);
2153 if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
2154 if (!ivalBuf) ivalBuf = dbuf_new(1024);
2155 dbuf_init(&locBuf, 1024);
2157 dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
2158 dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
2159 dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
2160 dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
2161 dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
2163 for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
2165 //DEBUGprintf ("memmap %i: %p\n", i, map);
2168 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",
2169 map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
2170 map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
2171 map->codesp, map->regsp, map->syms);
2173 emitSymbolSet(map->syms, 0);
2176 DEBUGprintf ("---end of memmaps---\n");
2178 emitSymbolSet(publics, 1);
2179 emitSymbolSet(externs, 2);
2181 emitPseudoStack(gloBuf, extBuf);
2182 pic14_constructAbsMap(gloDefBuf, gloBuf);
2183 pic14printLocals (&locBuf);
2184 pic14_emitConfigWord(of); // must be done after all the rest
2186 dbuf_write_and_destroy(extBuf, of);
2187 dbuf_write_and_destroy(gloBuf, of);
2188 dbuf_write_and_destroy(gloDefBuf, of);
2189 dbuf_write_and_destroy(&locBuf, of);
2190 dbuf_write_and_destroy(ivalBuf, of);
2192 extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;