/*-----------------------------------------------------------------*/ void allocIntoSeg (symbol *sym) { memmap *segment; if (SPEC_ADDRSPACE (sym->etype)) { namedspacemap *nm; for (nm = namedspacemaps; nm; nm = nm->next) if (!strcmp (nm->name, SPEC_ADDRSPACE (sym->etype)->name)) break; if (!nm) { nm = Safe_alloc (sizeof (namedspacemap)); nm->name = Safe_alloc (strlen(SPEC_ADDRSPACE (sym->etype)->name) + 1); strcpy (nm->name, SPEC_ADDRSPACE (sym->etype)->name); nm->is_const = (SPEC_ADDRSPACE (sym->etype)->type && SPEC_CONST (SPEC_ADDRSPACE (sym->etype)->type)); nm->map = nm->is_const ? allocMap (0, 1, 0, 0, 0, 1, options.code_loc, SPEC_ADDRSPACE (sym->etype)->name, 'C', CPOINTER) : allocMap (0, 0, 0, 1, 0, 0, options.data_loc, SPEC_ADDRSPACE (sym->etype)->name, 'E', POINTER); nm->next = namedspacemaps; namedspacemaps = nm; } addSet (&nm->map->syms, sym); return; } segment = SPEC_OCLS (sym->etype); addSet (&segment->syms, sym); if (segment == pdata) sym->iaccess = 1; }
/*-----------------------------------------------------------------*/ hTab * newHashTable (int size) { hTab *htab; htab = Safe_alloc ( sizeof (hTab)); if (!(htab->table = Safe_alloc ((size + 1) * sizeof (hashtItem *)))) { fprintf (stderr, "out of virtual memory %s %d\n", __FILE__, (size + 1) * (int) sizeof (hashtItem *)); exit (1); } htab->minKey = htab->size = size; return htab; }
/*-----------------------------------------------------------------*/ static void add_line_node (const char *line) { lineNode *pl; pl = Safe_alloc (sizeof (lineNode)); #if 1 memcpy (pl, (lineElem_t *) & genLine.lineElement, sizeof (lineElem_t)); #else pl->ic = genLine.lineElement.ic; pl->isInline = genLine.lineElement.isInline; pl->isComment = genLine.lineElement.isComment; pl->isDebug = genLine.lineElement.isDebug; pl->isLabel = genLine.lineElement.isLabel; pl->visited = genLine.lineElement.visited; pl->aln = genLine.lineElement.aln; #endif pl->line = Safe_strdup (line); if (genLine.lineCurr) { pl->next = NULL; genLine.lineCurr->next = pl; pl->prev = genLine.lineCurr; genLine.lineCurr = pl; } else { pl->prev = pl->next = NULL; genLine.lineCurr = genLine.lineHead = pl; } }
/*-----------------------------------------------------------------*/ eBBlock * neweBBlock () { eBBlock *ebb; ebb = Safe_alloc (sizeof (eBBlock)); return ebb; }
/*-----------------------------------------------------------------*/ lineNode * newLineNode (const char *line) { lineNode *pl; pl = Safe_alloc (sizeof (lineNode)); pl->line = Safe_strdup (line); pl->ic = NULL; return pl; }
static asmLineNode * newAsmLineNode (void) { asmLineNode *aln; aln = Safe_alloc ( sizeof (asmLineNode)); aln->size = 0; return aln; }
char *Safe_strdup(const char *sz) { char *pret; assert(sz); pret = Safe_alloc(strlen(sz) +1); strcpy(pret, sz); return pret; }
/*-----------------------------------------------------------------*/ edge * newEdge (eBBlock * from, eBBlock * to) { edge *ep; ep = Safe_alloc (sizeof (edge)); ep->from = from; ep->to = to; return ep; }
static asmLineNode * newAsmLineNode (void) { asmLineNode *aln; aln = Safe_alloc ( sizeof (asmLineNode)); aln->size = 0; aln->regsRead = NULL; aln->regsWritten = NULL; return aln; }
/*-----------------------------------------------------------------*/ static hashtItem * _newHashtItem (int key, void *pkey, void *item) { hashtItem *htip; htip = Safe_alloc ( sizeof (hashtItem)); htip->key = key; htip->pkey = pkey; htip->item = item; htip->next = NULL; return htip; }
int my_system (const char *cmd) { int argsStart, e, i = 0; char *cmdLine = NULL; argsStart = strstr (cmd, " ") - cmd; // try to find the command in predefined path's while (ExePathList[i]) { cmdLine = (char *) Safe_alloc (strlen (ExePathList[i]) + strlen (cmd) + 10); strcpy (cmdLine, ExePathList[i]); // the path strcat (cmdLine, DIR_SEPARATOR_STRING); strncat (cmdLine, cmd, argsStart); // the command #if NATIVE_WIN32 strcat (cmdLine, ".exe"); #endif if (access (cmdLine, X_OK) == 0) { // the arguments strcat (cmdLine, cmd + argsStart); break; } Safe_free (cmdLine); cmdLine = NULL; i++; } if (verboseExec) { printf ("+ %s\n", cmdLine ? cmdLine : cmd); } if (cmdLine) { // command found in predefined path e = system (cmdLine); Safe_free (cmdLine); } else { // trust on $PATH e = system (cmd); } return e; }
/*-----------------------------------------------------------------*/ void computeControlFlow (ebbIndex * ebbi) { eBBlock ** ebbs = ebbi->bbOrder; int dfCount = ebbi->count; int i; /* initialise some things */ for (i = 0; i < ebbi->count; i++) { setToNull ((void *) &ebbs[i]->predList); setToNull ((void *) &ebbs[i]->domVect); setToNull ((void *) &ebbs[i]->succList); setToNull ((void *) &ebbs[i]->succVect); ebbs[i]->visited = 0; ebbs[i]->dfnum = 0; } setToNull ((void *) &graphEdges); /* this will put in the */ /* successor information for each blk */ eBBSuccessors (ebbi); /* compute the depth first ordering */ computeDFOrdering (ebbi->bbOrder[0], &dfCount); /* mark blocks with no paths to them */ markNoPath (ebbi); /* with the depth first info in place */ /* add the predecessors for the blocks */ eBBPredecessors (ebbi); /* compute the dominance graph */ computeDominance (ebbi); /* sort it by dfnumber */ if (!ebbi->dfOrder) ebbi->dfOrder = Safe_alloc ((ebbi->count+1) * sizeof (eBBlock *)); for (i = 0; i < (ebbi->count+1); i++) { ebbi->dfOrder[i] = ebbi->bbOrder[i]; } qsort (ebbi->dfOrder, ebbi->count, sizeof (eBBlock *), dfNumCompare); }
/*-----------------------------------------------------------------*/ memmap * allocMap (char rspace, /* sfr space */ char farmap, /* far or near segment */ char paged, /* can this segment be paged */ char direct, /* directly addressable */ char bitaddr, /* bit addressable space */ char codemap, /* this is code space */ unsigned sloc, /* starting location */ const char *name, /* 8 character name */ char dbName, /* debug name */ int ptrType /* pointer type for this space */ ) { memmap *map; if (!name) return NULL; if (!(map = Safe_alloc (sizeof (memmap)))) { werror (E_OUT_OF_MEM, __FILE__, sizeof (memmap)); exit (1); } memset (map, ZERO, sizeof (memmap)); map->regsp = rspace; map->fmap = farmap; map->paged = paged; map->direct = direct; map->bitsp = bitaddr; map->codesp = codemap; map->sloc = sloc; map->sname = name; map->dbName = dbName; map->ptrType = ptrType; map->syms = NULL; dbuf_init(&map->oBuf, 4096); return map; }
static void _setValues(void) { const char *s; if (options.nostdlib == FALSE) { const char *s; char path[PATH_MAX]; struct dbuf_s dbuf; dbuf_init(&dbuf, PATH_MAX); for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet)) { buildCmdLine2(path, sizeof path, "-k\"%s" DIR_SEPARATOR_STRING "{port}\" ", s); dbuf_append_str(&dbuf, path); } buildCmdLine2(path, sizeof path, "-l\"{port}.lib\"", s); dbuf_append_str(&dbuf, path); setMainValue ("z80libspec", dbuf_c_str(&dbuf)); dbuf_destroy(&dbuf); for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet)) { struct stat stat_buf; buildCmdLine2(path, sizeof path, "%s" DIR_SEPARATOR_STRING "{port}" DIR_SEPARATOR_STRING "crt0{objext}", s); if (stat(path, &stat_buf) == 0) break; } if (s == NULL) setMainValue ("z80crt0", "\"crt0{objext}\""); else { char *buf; size_t len = strlen(path) + 3; buf = Safe_alloc(len); SNPRINTF(buf, len, "\"%s\"", path); setMainValue("z80crt0", buf); Safe_free(buf); } } else { setMainValue ("z80libspec", ""); setMainValue ("z80crt0", ""); } setMainValue ("z80extralibfiles", (s = joinStrSet(libFilesSet))); Safe_free((void *)s); setMainValue ("z80extralibpaths", (s = joinStrSet(libPathsSet))); Safe_free((void *)s); if (IS_GB) { setMainValue ("z80outputtypeflag", "-Z"); setMainValue ("z80outext", ".gb"); } else { setMainValue ("z80outputtypeflag", "-i"); setMainValue ("z80outext", ".ihx"); } setMainValue ("stdobjdstfilename" , "{dstfilename}{objext}"); setMainValue ("stdlinkdstfilename", "{dstfilename}{z80outext}"); setMainValue ("z80extraobj", (s = joinStrSet(relFilesSet))); Safe_free((void *)s); sprintf (buffer, "-b_CODE=0x%04X -b_DATA=0x%04X", options.code_loc, options.data_loc); setMainValue ("z80bases", buffer); }
/*-----------------------------------------------------------------*/ ebbIndex * iCodeBreakDown (iCode * ic) { eBBlock **ebbs = NULL; iCode *loop = ic; ebbIndex *ebbi; ebbi = Safe_alloc (sizeof (ebbIndex)); ebbi->count = 0; ebbi->dfOrder = NULL; /* no depth first order information yet */ /* allocate for the first entry */ ebbs = Safe_alloc (sizeof (eBBlock *)); ebbi->bbOrder = ebbs; while (loop) { /* convert 2 block */ eBBlock *ebb = iCode2eBBlock (loop); loop = ebb->ech->next; ebb->ech->next = NULL; /* mark the end of this chain */ if (loop) loop->prev = NULL; ebb->bbnum = ebbi->count; /* save this block number */ /* put it in the array */ ebbs[(ebbi->count)++] = ebb; /* allocate for the next one. Remember to clear the new */ /* pointer at the end, that was created by realloc. */ ebbs = Safe_realloc (ebbs, (ebbi->count + 1) * sizeof (eBBlock *)); ebbi->bbOrder = ebbs; ebbs[ebbi->count] = 0; /* if this one ends in a goto or a conditional */ /* branch then check if the block it is going */ /* to already exists, if yes then this could */ /* be a loop, add a preheader to the block it */ /* goes to if it does not already have one */ if (ebbs[(ebbi->count) - 1]->ech && (ebbs[(ebbi->count) - 1]->ech->op == GOTO || ebbs[(ebbi->count) - 1]->ech->op == IFX)) { symbol *label; eBBlock *destBlock; if (ebbs[(ebbi->count) - 1]->ech->op == GOTO) label = IC_LABEL (ebbs[(ebbi->count) - 1]->ech); else if (!(label = IC_TRUE (ebbs[(ebbi->count) - 1]->ech))) label = IC_FALSE (ebbs[(ebbi->count) - 1]->ech); if ((destBlock = eBBWithEntryLabel (ebbi, label)) && destBlock->preHeader == NULL && otherPathsPresent (ebbs, destBlock)) { symbol *preHeaderLabel = newiTempLoopHeaderLabel (1); int i, j; eBBlock *pBlock; /* go thru all block replacing the entryLabel with new label */ /* till we reach the block , then we insert a new ebblock */ for (i = 0; i < (ebbi->count); i++) { if (ebbs[i] == destBlock) break; replaceLabel (ebbs[i], label, preHeaderLabel); } (ebbi->count)++; /* if we have stopped at the block , allocate for an extra one */ ebbs = Safe_realloc (ebbs, (ebbi->count + 1) * sizeof (eBBlock *)); ebbi->bbOrder = ebbs; ebbs[ebbi->count] = 0; /* then move the block down one count */ pBlock = ebbs[j = i]; for (i += 1; i < (ebbi->count); i++) { eBBlock *xBlock; xBlock = ebbs[i]; ebbs[i] = pBlock; ebbs[i]->bbnum = i; pBlock = xBlock; } destBlock->preHeader = ebbs[j] = neweBBlock (); ebbs[j]->bbnum = j; ebbs[j]->entryLabel = preHeaderLabel; ebbs[j]->sch = ebbs[j]->ech = newiCodeLabelGoto (LABEL, preHeaderLabel); ebbs[j]->sch->filename = destBlock->sch->filename; ebbs[j]->sch->lineno = destBlock->sch->lineno; } } } /* mark the end */ ebbs[ebbi->count] = NULL; return ebbi; }
/*-----------------------------------------------------------------*/ static bool removeDeadPopPush (const char *pReg, lineNode *currPl, lineNode *head) { lineNode *pushPl, *pl; /* A pop/push pair can be removed, if these criteria are met (ar0 is just an example here, ar0...ar7 are possible): pop ar0 ; area 1 ; There must not be in area 1: ; - read or write access of ar0 ; - "acall", "lcall", "pop", "ret", "reti" or "jmp @a+dptr" opcodes ; - "push" opcode, which doesn't push ar0 ; - inline assembly ; - a jump in or out of area 1 (see checkLabelRef()) ; area 1 must be terminated by a: push ar0 ; area 2 ; There must not be: ; - read access of ar0 ; - "jmp @a+dptr" opcode ; - inline assembly ; - a jump in or out of area 2 (see checkLabelRef()) ; An "acall", "lcall" (not callee save), "ret" (not PCALL with ; callee save), "reti" or write access of r0 terminate ; the search, and the "pop/push ar0" can safely be removed. */ /* area 1 */ pushPl = currPl->next; if (!doPushScan (&pushPl, pReg)) return FALSE; if (!checkLabelRef()) return FALSE; /* area 2 */ pl = pushPl->next; if (!doTermScan (&pl, pReg)) return FALSE; if (!checkLabelRef()) return FALSE; /* Success! */ if (options.noPeepComments) { /* remove pushPl from list */ pushPl->prev->next = pushPl->next; pushPl->next->prev = pushPl->prev; } else { /* replace 'push ar0' by comment */ #define STR ";\tPeephole\tpush %s removed" int size = sizeof(STR) + 2; pushPl->line = Safe_alloc (size); SNPRINTF (pushPl->line, size, STR, pReg); pushPl->isComment = TRUE; } /* 'pop ar0' will be removed by peephole framework after returning TRUE */ return TRUE; }
static char * parseIvalAst (ast *node, int *inCodeSpace) { #define LEN 4096 char *buffer = NULL; char *left, *right; if (IS_AST_VALUE(node)) { value *val = AST_VALUE(node); symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL; if (inCodeSpace && val->type && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type)))) { *inCodeSpace = 1; } if (inCodeSpace && sym && (IS_FUNC(sym->type) || IS_CODE(getSpec(sym->type)))) { *inCodeSpace = 1; } DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__); if (IS_AST_LIT_VALUE(node)) { buffer = Safe_alloc(LEN); SNPRINTF(buffer, LEN, "0x%lx", AST_ULONG_VALUE (node)); } else if (IS_AST_SYM_VALUE(node)) { assert ( AST_SYMBOL(node) ); /* printf ("sym %s: ", AST_SYMBOL(node)->rname); printTypeChain(AST_SYMBOL(node)->type, stdout); printTypeChain(AST_SYMBOL(node)->etype, stdout); printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname); */ buffer = Safe_strdup(AST_SYMBOL(node)->rname); } else { assert ( !"Invalid values type for initializers in AST." ); } } else if (IS_AST_OP(node)) { DEBUGprintf ("%s: AST_OP\n", __FUNCTION__); switch (node->opval.op) { case CAST: assert (node->right); buffer = parseIvalAst(node->right, inCodeSpace); DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer); break; case '&': assert ( node->left && !node->right ); buffer = parseIvalAst(node->left, inCodeSpace); DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer); break; case '+': assert (node->left && node->right ); left = parseIvalAst(node->left, inCodeSpace); right = parseIvalAst(node->right, inCodeSpace); buffer = Safe_alloc(LEN); SNPRINTF(buffer, LEN, "(%s + %s)", left, right); DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer); Safe_free(left); Safe_free(right); break; case '[': assert ( node->left && node->right ); assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym ); right = parseIvalAst(node->right, inCodeSpace); buffer = Safe_alloc(LEN); SNPRINTF(buffer, LEN, "(%s + %u * %s)", AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right); Safe_free(right); DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]); break; default: assert ( !"Unhandled operation in initializer." ); break; } } else { assert ( !"Invalid construct in initializer." ); } return (buffer); }