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;
51 extern int maxRegBank;
53 extern char *VersionString;
54 extern struct dbuf_s *codeOutBuf;
55 extern char *iComments1;
56 extern char *iComments2;
57 //extern void emitStaticSeg (memmap * map);
58 set *pic14_localFunctions = NULL;
60 extern DEFSETFUNC (closeTmpFiles);
61 extern DEFSETFUNC (rmTmpFiles);
63 extern void AnalyzeBanking (void);
64 extern void ReuseReg(void);
65 extern void InlinepCode(void);
66 extern void writeUsedRegs(FILE *);
68 extern void initialComments (FILE * afile);
69 extern void printPublics (FILE * afile);
71 extern void printChar (FILE * ofile, char *s, int plen);
72 void pCodeInitRegisters(void);
73 int getConfigWord(int address);
74 int getHasSecondConfigReg(void);
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, *ivalCodeBuf, *extBuf, *gloBuf, *gloDefBuf, *locBuf;
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 = (unsigned long) floatFromVal(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", i);
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", i);
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
488 if (val->type != type) {
489 val = valCastLiteral(type, floatFromVal(val));
493 ulval = (unsigned long) floatFromVal (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));
540 i = (unsigned long)floatFromVal(val);
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)floatFromVal (val) & 0x00FF);
768 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
770 case 3: /* gneric pointers */
771 assert ( !"generic pointers not yet handled" );
773 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (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);
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");
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 pic14printLocals (struct dbuf_s *oBuf)
1149 set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
1150 dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
1153 static unsigned sectionNr = 0;
1155 /* emit all registers from all possible sets */
1156 for (i = 0; i < 6; i++) {
1157 if (allregs[i] == NULL) continue;
1159 for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
1160 if (reg->isEmitted) continue;
1162 if (reg->wasUsed && !reg->isExtern) {
1163 if (!pic14_stringInSet(reg->name, &emitted, 1)) {
1165 // Should not happen, really...
1166 dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
1167 moduleName, sectionNr++, reg->address, reg->name, reg->size);
1169 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
1170 moduleName, sectionNr++, reg->name, reg->size);
1179 /*-----------------------------------------------------------------*/
1180 /* emitOverlay - will emit code for the overlay stuff */
1181 /*-----------------------------------------------------------------*/
1183 pic14emitOverlay (struct dbuf_s * aBuf)
1187 /* if (!elementsInSet (ovrSetSets))*/
1189 /* the hack below, fixes translates for devices which
1190 * only have udata_shr memory */
1191 dbuf_printf (aBuf, "%s\t%s\n",
1192 (elementsInSet(ovrSetSets)?"":";"),
1193 port->mem.overlay_name);
1195 /* for each of the sets in the overlay segment do */
1196 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1197 ovrset = setNextItem (ovrSetSets))
1202 if (elementsInSet (ovrset))
1204 /* this dummy area is used to fool the assembler
1205 otherwise the assembler will append each of these
1206 declarations into one chunk and will not overlay
1209 /* I don't think this applies to us. We are using gpasm. CRF */
1211 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1212 /* output the area informtion */
1213 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1216 for (sym = setFirstItem (ovrset); sym;
1217 sym = setNextItem (ovrset))
1220 /* if extern then do nothing */
1221 if (IS_EXTERN (sym->etype))
1224 /* if allocation required check is needed
1225 then check if the symbol really requires
1226 allocation only for local variables */
1227 if (!IS_AGGREGATE (sym->type) &&
1228 !(sym->_isparm && !IS_REGPARM (sym->etype))
1229 && !sym->allocreq && sym->level)
1232 /* if global variable & not static or extern
1233 and addPublics allowed then add it to the public set */
1234 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1235 && !IS_STATIC (sym->etype))
1236 addSetHead (&publics, sym);
1238 /* if extern then do nothing or is a function
1240 if (IS_FUNC (sym->type))
1243 /* print extra debug info if required */
1244 if (options.debug || sym->level == 0)
1248 if (IS_STATIC (sym->etype))
1249 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
1251 dbuf_printf (aBuf, "G_"); /* scope is global */
1254 /* symbol is local */
1255 dbuf_printf (aBuf, "L%s_",
1256 (sym->localof ? sym->localof->name : "-null-"));
1257 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
1260 /* if is has an absolute address then generate
1261 an equate for this no need to allocate space */
1262 if (SPEC_ABSA (sym->etype))
1265 if (options.debug || sym->level == 0)
1266 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1268 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1270 SPEC_ADDR (sym->etype));
1274 if (options.debug || sym->level == 0)
1275 dbuf_printf (aBuf, "==.\n");
1277 /* allocate space */
1278 dbuf_printf (aBuf, "%s:\n", sym->rname);
1279 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1288 pic14_emitInterruptHandler (FILE * asmFile)
1290 if (pic14_hasInterrupt)
1293 fprintf (asmFile, "%s", iComments2);
1294 fprintf (asmFile, "; interrupt and initialization code\n");
1295 fprintf (asmFile, "%s", iComments2);
1296 // Note - for mplink may have to enlarge section vectors in .lnk file
1297 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1298 // source files's code segment (interrupt.c -> code_interrupt)
1299 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1301 /* interrupt service routine */
1302 fprintf (asmFile, "__sdcc_interrupt\n");
1303 copypCode(asmFile, 'I');
1307 /*-----------------------------------------------------------------*/
1308 /* glue - the final glue that hold the whole thing together */
1309 /*-----------------------------------------------------------------*/
1314 struct dbuf_s ovrBuf;
1317 dbuf_init(&ovrBuf, 4096);
1318 dbuf_init(&vBuf, 4096);
1320 pCodeInitRegisters();
1322 /* check for main() */
1323 mainf = newSymbol ("main", 0);
1325 mainf = findSymWithLevel (SymbolTab, mainf);
1327 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1329 /* main missing -- import stack from main module */
1330 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1331 pic14_options.isLibrarySource = 1;
1335 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1337 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1340 /* entry point @ start of CSEG */
1341 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1342 /* put in the call to main */
1343 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1345 if (options.mainreturn) {
1347 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1348 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1352 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1353 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1359 /* At this point we've got all the code in the form of pCode structures */
1360 /* Now it needs to be rearranged into the order it should be placed in the */
1363 movepBlock2Head('P'); // Last
1364 movepBlock2Head(code->dbName);
1365 movepBlock2Head('X');
1366 movepBlock2Head(statsg->dbName); // First
1369 /* print the global struct definitions */
1373 /* emit code for the all the variables declared */
1375 /* do the overlay segments */
1376 pic14emitOverlay(&ovrBuf);
1378 /* PENDING: this isnt the best place but it will do */
1379 if (port->general.glue_up_main) {
1380 /* create the interrupt vector table */
1381 pic14createInterruptVect (&vBuf);
1386 ReuseReg(); // ReuseReg where call tree permits
1395 /* now put it all together into the assembler file */
1396 /* create the assembler file name */
1398 if ((noAssemble || options.c1mode) && fullDstFileName)
1400 sprintf (buffer, fullDstFileName);
1404 sprintf (buffer, dstFileName);
1405 strcat (buffer, ".asm");
1408 if (!(asmFile = fopen (buffer, "w"))) {
1409 werror (E_FILE_OPEN_ERR, buffer);
1413 /* prepare statistics */
1414 resetpCodeStatistics ();
1416 /* initial comments */
1417 pic14initialComments (asmFile);
1419 /* print module name */
1420 fprintf (asmFile, ";\t.module %s\n", moduleName);
1422 /* Let the port generate any global directives, etc. */
1423 if (port->genAssemblerPreamble)
1425 port->genAssemblerPreamble(asmFile);
1428 /* Emit the __config directive */
1429 pic14_emitConfigWord (asmFile);
1431 /* print the global variables in this module */
1432 //pic14printPublics (asmFile);
1434 /* print the extern variables in this module */
1435 //pic14printExterns (asmFile);
1437 /* copy the sfr segment */
1439 fprintf (asmFile, "%s", iComments2);
1440 fprintf (asmFile, "; special function registers\n");
1441 fprintf (asmFile, "%s", iComments2);
1442 dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1445 if (udata_section_name) {
1446 sprintf(udata_name,"%s",udata_section_name);
1448 sprintf(udata_name,"data_%s",moduleName);
1450 fprintf (asmFile, "%s", iComments2);
1451 fprintf (asmFile, "; udata\n");
1452 fprintf (asmFile, "%s", iComments2);
1453 fprintf (asmFile, "%s\tudata\n", udata_name);
1454 dbuf_write_and_destroy(&data->oBuf, asmFile);
1457 /* Put all variables into a cblock */
1460 /* emit initialized data */
1461 showAllMemmaps(asmFile);
1463 /* print the locally defined variables in this module */
1464 writeUsedRegs(asmFile);
1466 /* create the overlay segments */
1467 fprintf (asmFile, "%s", iComments2);
1468 fprintf (asmFile, "; overlayable items in internal ram \n");
1469 fprintf (asmFile, "%s", iComments2);
1470 dbuf_write_and_destroy (&ovrBuf, asmFile);
1474 /* create the stack segment MOF */
1475 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1476 fprintf (asmFile, "%s", iComments2);
1477 fprintf (asmFile, "; Stack segment in internal ram \n");
1478 fprintf (asmFile, "%s", iComments2);
1479 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1480 ";__start__stack:\n;\t.ds\t1\n\n");
1483 /* create the idata segment */
1484 fprintf (asmFile, "%s", iComments2);
1485 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1486 fprintf (asmFile, "%s", iComments2);
1487 dbuf_write_and_destroy (&idata->oBuf, asmFile);
1489 /* if external stack then reserve space of it */
1490 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1491 fprintf (asmFile, "%s", iComments2);
1492 fprintf (asmFile, "; external stack \n");
1493 fprintf (asmFile, "%s", iComments2);
1494 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1495 fprintf (asmFile,";\t.ds 256\n");
1498 /* copy xtern ram data */
1499 fprintf (asmFile, "%s", iComments2);
1500 fprintf (asmFile, "; external ram data\n");
1501 fprintf (asmFile, "%s", iComments2);
1502 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1506 /* copy the bit segment */
1508 fprintf (asmFile, "%s", iComments2);
1509 fprintf (asmFile, "; bit data\n");
1510 fprintf (asmFile, "%s", iComments2);
1511 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1514 /* copy the interrupt vector table */
1515 if (mainf && IFFUNC_HASBODY(mainf->type))
1516 dbuf_write_and_destroy (&vBuf, asmFile);
1518 dbuf_destroy(&vBuf);
1520 /* create interupt ventor handler */
1521 pic14_emitInterruptHandler (asmFile);
1523 /* copy over code */
1524 fprintf (asmFile, "%s", iComments2);
1525 fprintf (asmFile, "; code\n");
1526 fprintf (asmFile, "%s", iComments2);
1527 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1530 copypCode(asmFile, 'X');
1532 /* _main function */
1533 copypCode(asmFile, 'M');
1535 /* other functions */
1536 copypCode(asmFile, code->dbName);
1539 copypCode(asmFile, 'P');
1541 dumppCodeStatistics (asmFile);
1543 fprintf (asmFile,"\tend\n");
1549 * Deal with initializers.
1554 #define DEBUGprintf printf
1557 #define DEBUGprintf 1 ? (void)0 : (void)printf
1561 void ast_print (ast * tree, FILE *outfile, int indent);
1568 showInitList(initList *list, int level)
1570 static const char *list_type[] = { "INIT_NODE", "INIT_DEEP", "INIT_HOLE" };
1571 static const char *ast_type[] = { "EX_OP", "EX_VALUE", "EX_LINK", "EX_OPERAND" };
1574 printf (" %d: type %u (%s), init %p, next %p\n", level, list->type, list_type[list->type], list->init.node, list->next);
1575 if (list->type == INIT_DEEP) {
1576 showInitList(list->init.deep, level + 1);
1577 } else if (list->type == INIT_NODE) {
1578 ast = list->init.node;
1579 printf (" type %u (%s), level %d, block %d, seqPoint %d\n",
1580 ast->type, ast_type[ast->type], ast->level, ast->block, ast->seqPoint);
1581 if (ast->type == EX_VALUE) {
1582 printf (" VAL %lf\n", floatFromVal(ast->opval.val));
1583 } else if (ast->type == EX_LINK) {
1584 printTypeChain(ast->opval.lnk, NULL);
1585 } else if (ast->type == EX_OP) {
1586 printf (" OP %u\n", ast->opval.op);
1595 * DEBUG: Print a value.
1598 printVal(value *val)
1600 printf ("value %p: name %s, type %p, etype %p, sym %s, vArgs %d, lit 0x%lx/%ld\n",
1601 val, val->name, val->type, val->etype,
1602 val->sym ? val->sym->name : NULL, val->vArgs,
1603 (long)floatFromVal(val), (long)floatFromVal(val));
1604 printTypeChain(val->type, stdout);
1606 printTypeChain(val->etype, stdout);
1610 //prototype from ../SDCCicode.c
1611 operand *operandFromAst (ast * tree,int lvl);
1614 parseIvalAst (ast *node, int *inCodeSpace) {
1616 char *buffer = NULL;
1619 if (IS_AST_VALUE(node)) {
1620 value *val = AST_VALUE(node);
1621 symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
1622 if (inCodeSpace && val->type
1623 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
1627 if (inCodeSpace && sym
1628 && (IS_FUNC(sym->type)
1629 || IS_CODE(getSpec(sym->type))))
1634 DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
1635 if (IS_AST_LIT_VALUE(node)) {
1636 buffer = Safe_alloc(LEN);
1637 SNPRINTF(buffer, LEN, "0x%lx", (long)AST_LIT_VALUE(node));
1638 } else if (IS_AST_SYM_VALUE(node)) {
1639 assert ( AST_SYMBOL(node) );
1641 printf ("sym %s: ", AST_SYMBOL(node)->rname);
1642 printTypeChain(AST_SYMBOL(node)->type, stdout);
1643 printTypeChain(AST_SYMBOL(node)->etype, stdout);
1644 printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
1646 buffer = Safe_strdup(AST_SYMBOL(node)->rname);
1648 assert ( !"Invalid values type for initializers in AST." );
1650 } else if (IS_AST_OP(node)) {
1651 DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
1652 switch (node->opval.op) {
1654 assert (node->right);
1655 buffer = parseIvalAst(node->right, inCodeSpace);
1656 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1659 assert ( node->left && !node->right );
1660 buffer = parseIvalAst(node->left, inCodeSpace);
1661 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1664 assert (node->left && node->right );
1665 left = parseIvalAst(node->left, inCodeSpace);
1666 right = parseIvalAst(node->right, inCodeSpace);
1667 buffer = Safe_alloc(LEN);
1668 SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
1669 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1674 assert ( node->left && node->right );
1675 assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
1676 right = parseIvalAst(node->right, inCodeSpace);
1677 buffer = Safe_alloc(LEN);
1678 SNPRINTF(buffer, LEN, "(%s + %u * %s)",
1679 AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
1681 DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
1684 assert ( !"Unhandled operation in initializer." );
1688 assert ( !"Invalid construct in initializer." );
1695 * Emit the section preamble, absolute location (if any) and
1696 * symbol name(s) for intialized data.
1699 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
1702 static int in_code = 0;
1703 static int sectionNr = 0;
1706 // code or data space?
1707 if (IS_CODE(getSpec(sym->type))) {
1714 dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
1715 if (SPEC_ABSA(getSpec(sym->type))) {
1716 // specify address for absolute symbols
1717 dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
1719 dbuf_printf(oBuf, "\n%s\n", sym->rname);
1721 addSet(&emitted, sym->rname);
1726 char *get_op(pCodeOp *pcop,char *buffer, size_t size);
1728 * Actually emit the initial values in .asm format.
1731 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
1737 int inCodeSpace = 0;
1741 assert (size <= sizeof(long));
1742 assert (!list || (list->type == INIT_NODE));
1743 node = list ? list->init.node : NULL;
1745 in_code = emitIvalLabel(oBuf, sym);
1746 if (!in_code) dbuf_printf (oBuf, "\tdb\t");
1749 // initialize as zero
1750 for (i=0; i < size; i++) {
1752 dbuf_printf (oBuf, "\tretlw 0x00");
1754 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
1757 dbuf_printf (oBuf, "\n");
1762 if (constExprTree(node) && (val = constExprValue(node, 0))) {
1763 op = operandFromValue(val);
1764 DEBUGprintf ("%s: constExpr ", __FUNCTION__);
1766 } else if (IS_AST_VALUE(node)) {
1767 op = operandFromAst(node, 0);
1768 } else if (IS_AST_OP(node)) {
1769 str = parseIvalAst(node, &inCodeSpace);
1770 DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
1773 assert ( !"Unhandled construct in intializer." );
1779 //printOperand(op, of);
1782 for (i=0; i < size; i++) {
1783 char *text = op ? aopGet(AOP(op), i, 0, 0)
1784 : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
1786 dbuf_printf (oBuf, "\tretlw %s\n", text);
1788 dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
1791 dbuf_printf (oBuf, "\n");
1795 * For UNIONs, we first have to find the correct alternative to map the
1796 * initializer to. This function maps the structure of the initializer to
1797 * the UNION members recursively.
1798 * Returns the type of the first `fitting' member.
1801 matchIvalToUnion (initList *list, sym_link *type, int size)
1807 if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
1810 if (!list || (list->type == INIT_NODE)) {
1811 DEBUGprintf ("OK, simple type\n");
1814 DEBUGprintf ("ERROR, simple type\n");
1817 } else if (IS_BITFIELD(type)) {
1818 if (!list || (list->type == INIT_NODE)) {
1819 DEBUGprintf ("OK, bitfield\n");
1822 DEBUGprintf ("ERROR, bitfield\n");
1825 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
1826 if (!list || (list->type == INIT_DEEP)) {
1827 if (list) list = list->init.deep;
1828 sym = SPEC_STRUCT(type)->fields;
1830 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
1831 if (!matchIvalToUnion(list, sym->type, 0)) {
1832 DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
1835 if (list) list = list->next;
1839 // excess initializers?
1841 DEBUGprintf ("ERROR, excess initializers\n");
1845 DEBUGprintf ("OK, struct\n");
1849 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
1850 if (!list || (list->type == INIT_DEEP)) {
1851 if (list) list = list->init.deep;
1852 sym = SPEC_STRUCT(type)->fields;
1854 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
1855 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
1856 && matchIvalToUnion(list, sym->type, size))
1858 DEBUGprintf ("Matched UNION member %s.\n", sym->name);
1865 DEBUGprintf ("ERROR, no match found.\n");
1868 assert ( !"Unhandled type in UNION." );
1871 assert ( !"No match found in UNION for the given initializer structure." );
1876 * Parse the type and its initializer and emit it (recursively).
1879 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
1886 size = getSize(my_type);
1888 if (IS_PTR(my_type)) {
1889 DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
1890 emitIvals(oBuf, topsym, list, 0, size);
1894 if (IS_ARRAY(my_type) && topsym->isstrlit) {
1895 str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
1896 emitIvalLabel(oBuf, topsym);
1898 dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
1903 if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
1904 fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
1905 assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
1909 if (IS_ARRAY(my_type)) {
1910 DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
1911 assert (!list || list->type == INIT_DEEP);
1912 if (list) list = list->init.deep;
1913 for (i = 0; i < DCL_ELEM(my_type); i++) {
1914 emitInitVal(oBuf, topsym, my_type->next, list);
1916 if (list) list = list->next;
1921 if (IS_FLOAT(my_type)) {
1923 DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
1924 emitIvals(oBuf, topsym, list, 0, size);
1928 if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
1929 // integral type, 8, 16, or 32 bit
1930 DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
1931 emitIvals(oBuf, topsym, list, 0, size);
1934 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
1936 DEBUGprintf ("(struct, %d byte) handled below\n", size);
1937 assert (!list || (list->type == INIT_DEEP));
1939 // iterate over struct members and initList
1940 if (list) list = list->init.deep;
1941 sym = SPEC_STRUCT(my_type)->fields;
1945 if (IS_BITFIELD(sym->type)) {
1946 while (sym && IS_BITFIELD(sym->type)) {
1947 assert (!list || ((list->type == INIT_NODE)
1948 && IS_AST_LIT_VALUE(list->init.node)));
1949 lit = list ? list2int(list) : 0;
1950 DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
1951 lit, SPEC_BLEN(getSpec(sym->type)),
1952 SPEC_BSTR(getSpec(sym->type)), bitfield);
1953 bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
1954 len += SPEC_BLEN(getSpec(sym->type));
1957 if (list) list = list->next;
1959 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
1960 len = (len + 7) & ~0x07; // round up to full bytes
1961 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
1966 emitInitVal(oBuf, topsym, sym->type, list);
1969 if (list) list = list->next;
1973 assert ( !"Excess initializers." );
1977 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
1979 DEBUGprintf ("(union, %d byte) handled below\n", size);
1980 assert (list && list->type == INIT_DEEP);
1982 // iterate over union members and initList, try to map number and type of fields and initializers
1983 my_type = matchIvalToUnion(list, my_type, size);
1985 emitInitVal(oBuf, topsym, my_type, list->init.deep);
1987 size -= getSize(my_type);
1989 // pad with (leading) zeros
1990 emitIvals(oBuf, NULL, NULL, 0, size);
1995 assert ( !"No UNION member matches the initializer structure.");
1996 } else if (IS_BITFIELD(my_type)) {
1997 assert ( !"bitfields should only occur in structs..." );
2000 printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
2001 assert( !"Unhandled initialized type.");
2006 * Emit a set of symbols.
2007 * type - 0: have symbol tell whether it is local, extern or global
2008 * 1: assume all symbols in set to be global
2009 * 2: assume all symbols in set to be extern
2012 emitSymbolSet(set *s, int type)
2016 unsigned sectionNr = 0;
2018 for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
2020 fprintf (stdout, "; name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
2021 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
2024 if (sym->isstrlit) {
2025 // special case: string literals
2026 emitInitVal(ivalBuf, sym, sym->type, NULL);
2030 if (type != 0 || sym->cdef
2031 || (!IS_STATIC(sym->etype)
2034 // bail out for ___fsadd and friends
2035 if (sym->cdef && !sym->used) continue;
2037 /* export or import non-static globals */
2038 if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
2040 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
2042 /* do not add to emitted set, it might occur again! */
2043 //if (!sym->used) continue;
2045 emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
2048 emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
2049 if (!sym->ival && !IS_FUNC(sym->type)) {
2050 // also define symbol
2051 if (IS_ABSOLUTE(sym->etype)) {
2052 // absolute location?
2053 //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
2054 // deferred to pic14_constructAbsMap
2056 dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
2057 dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
2061 pic14_stringInSet(sym->rname, &emitted, 1);
2065 //if (list) showInitList(list, 0);
2067 resolveIvalSym( list, sym->type );
2068 emitInitVal(ivalBuf, sym, sym->type, sym->ival);
2069 dbuf_printf (ivalBuf, "\n");
2075 * Iterate over all memmaps and emit their contents (attributes, symbols).
2078 showAllMemmaps(FILE *of)
2081 xstack, istack, code, data, pdata, xdata, xidata, xinit,
2082 idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
2083 sfr, sfrbit, reg, generic, overlay, eeprom, home };
2087 DEBUGprintf ("---begin memmaps---\n");
2088 if (!extBuf) extBuf = dbuf_new(1024);
2089 if (!gloBuf) gloBuf = dbuf_new(1024);
2090 if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
2091 if (!ivalBuf) ivalBuf = dbuf_new(1024);
2092 if (!locBuf) locBuf = dbuf_new(1024);
2094 dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
2095 dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
2096 dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
2097 dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
2098 dbuf_printf (locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
2100 for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
2102 //DEBUGprintf ("memmap %i: %p\n", i, map);
2105 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",
2106 map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
2107 map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
2108 map->codesp, map->regsp, map->syms);
2110 emitSymbolSet(map->syms, 0);
2113 DEBUGprintf ("---end of memmaps---\n");
2115 emitSymbolSet(publics, 1);
2116 emitSymbolSet(externs, 2);
2118 emitPseudoStack(gloBuf, extBuf);
2119 pic14_constructAbsMap(gloDefBuf, gloBuf);
2121 pic14printLocals (locBuf);
2123 dbuf_write_and_destroy(extBuf, of);
2124 dbuf_write_and_destroy(gloBuf, of);
2125 dbuf_write_and_destroy(gloDefBuf, of);
2126 dbuf_write_and_destroy(locBuf, of);
2127 dbuf_write_and_destroy(ivalBuf, of);
2129 extBuf = gloBuf = gloDefBuf = locBuf = ivalBuf = NULL;