12static bool compareCFGRegAndRegID(
void *a,
void *b)
62 fatalError(
"bug: unsatisfiable register constraints on t%d", arg->
ID);
76 result->
defs[i] = NULL;
78 result->
uses[i] = NULL;
79 result->
instr = instr;
88static void deleteBBNode(
t_bbNode *node)
97static void bbNodeComputeDefUses(
t_bbNode *node)
106 if (instr->
rDest != NULL)
107 regDest = createCFGRegister(graph, instr->
rDest);
108 if (instr->
rSrc1 != NULL)
109 regSource1 = createCFGRegister(graph, instr->
rSrc1);
110 if (instr->
rSrc2 != NULL)
111 regSource2 = createCFGRegister(graph, instr->
rSrc2);
116 node->
defs[defIdx++] = regDest;
119 node->
uses[useIdx++] = regSource1;
121 node->
uses[useIdx++] = regSource2;
134 result->
nodes = NULL;
150 while (curNode != NULL) {
152 deleteBBNode(curCFGNode);
153 curNode = curNode->
next;
186 t_bbNode *newNode = newBBNode(instr);
189 bbNodeComputeDefUses(newNode);
198 fatalError(
"bug: invalid basic block node; corrupt CFG?");
200 t_bbNode *newNode = newBBNode(instr);
203 bbNodeComputeDefUses(newNode);
212 fatalError(
"bug: invalid basic block node; corrupt CFG?");
214 t_bbNode *newNode = newBBNode(instr);
217 bbNodeComputeDefUses(newNode);
222static t_cfg *newCFG(
void)
245 curNode = curNode->
next;
255 curNode = curNode->
next;
280 while (curNode != NULL) {
286 if ((curCFGNode->instr)->label != NULL) {
287 if ((curCFGNode->instr)->label->labelID == label->
labelID)
292 curNode = curNode->
next;
301 return instr->
label != NULL;
309static void cfgComputeTransitions(
t_cfg *graph)
318 while (curNode != NULL) {
338 fatalError(
"bug: malformed jump instruction with no label in CFG");
340 if (jumpBlock == NULL)
341 fatalError(
"bug: malformed jump instruction with invalid label in CFG");
353 if (nextNode != NULL) {
366 curNode = curNode->
next;
372 t_cfg *result = newCFG();
386 while (curNode != NULL) {
392 if (instrIsStartingNode(curInstr) || bblock == NULL)
400 if (instrIsEndingNode(curInstr))
403 curNode = curNode->
next;
408 cfgComputeTransitions(result);
421 while (curBlockNode != NULL) {
424 while (curInnerNode != NULL) {
430 curInnerNode = curInnerNode->
next;
432 curBlockNode = curBlockNode->
next;
438 int (*callback)(
t_bbNode *node,
int nodeIndex,
void *context))
444 while (curBlockNode != NULL) {
448 while (curInnerNode != NULL) {
451 exitcode = callback(curCFGNode, counter, context);
456 curInnerNode = curInnerNode->
next;
459 curBlockNode = curBlockNode->
next;
469 if (bblock->
nodes == NULL)
481 if (bblock->
nodes == NULL)
489 bool (*compareFunc)(
void *a,
void *b),
bool *modified)
497 if (modified != NULL)
505 bool (*compareFunc)(
void *a,
void *b),
bool *modified)
509 while (curNode != NULL) {
510 void *curData = curNode->
data;
511 set = addElementToSet(set, curData, compareFunc, modified);
512 curNode = curNode->
next;
531 liveIn = addElementToSet(liveIn, uses[i], NULL, NULL);
539 if (defs[defIdx] == NULL)
544 for (
int useIdx = 0; useIdx <
CFG_MAX_USES && !found; useIdx++) {
545 if (uses[useIdx] && uses[useIdx]->tempRegID == defs[defIdx]->tempRegID)
564 while (curSuccNode != NULL) {
571 result = addElementsToSet(result, liveINRegs, NULL, NULL);
575 curSuccNode = curSuccNode->
next;
584 bool modified =
false;
591 t_listNode *successorsLiveIn = cfgComputeLiveOutOfBlock(graph, bblock);
593 while (curLI != NULL) {
600 addElementsToSet(curNode->out, successorsLiveIn, NULL, &modified);
606 computeLiveInSetEquation(curNode->defs, curNode->uses, curNode->out);
607 curNode->in = addElementsToSet(curNode->in, liveIn, NULL, &modified);
611 successorsLiveIn = liveIn;
623static bool cfgPerformLivenessIteration(
t_cfg *graph)
625 bool modified =
false;
627 while (curNode != NULL) {
631 if (cfgUpdateLivenessOfNodesInBlock(graph, curBlock))
634 curNode = curNode->
prev;
643 modified = cfgPerformLivenessIteration(graph);
648static void dumpCFGRegister(
t_cfgReg *reg, FILE *fout)
651 fprintf(fout,
"<!UNDEF!>");
654 fprintf(fout,
"%s", regName);
659static void dumpArrayOfCFGRegisters(
t_cfgReg **array,
int size, FILE *fout)
663 for (
int i = 0; i < size; i++) {
670 dumpCFGRegister(array[i], fout);
677static void dumpListOfCFGRegisters(
t_listNode *regs, FILE *fout)
685 while (currentListNode != NULL) {
687 dumpCFGRegister(curReg, fout);
688 if (currentListNode->
next != NULL)
691 currentListNode = currentListNode->
next;
712 fatalError(
"bug: malformed CFG, found basic block not in list");
715static void dumpBBList(
t_listNode *list, FILE *fout)
720 fprintf(fout,
"%d", cfgComputeBBIndex(bb));
727static void cfgDumpBB(
t_basicBlock *block, FILE *fout,
bool verbose)
734 fprintf(fout,
" Predecessor blocks: {");
735 dumpBBList(block->
pred, fout);
736 fprintf(fout,
"}\n");
737 fprintf(fout,
" Successor blocks: {");
738 dumpBBList(block->
succ, fout);
739 fprintf(fout,
"}\n");
743 while (elem != NULL) {
746 fprintf(fout,
" Node %4d: ", count);
747 if (curCFGNode->instr == NULL)
748 fprintf(fout,
"(null)");
754 fprintf(fout,
" def = {");
755 dumpArrayOfCFGRegisters(curCFGNode->defs,
CFG_MAX_DEFS, fout);
756 fprintf(fout,
"}\n");
757 fprintf(fout,
" use = {");
758 dumpArrayOfCFGRegisters(curCFGNode->uses,
CFG_MAX_USES, fout);
759 fprintf(fout,
"}\n");
761 fprintf(fout,
" in = {");
762 dumpListOfCFGRegisters(curCFGNode->in, fout);
763 fprintf(fout,
"}\n");
764 fprintf(fout,
" out = {");
765 dumpListOfCFGRegisters(curCFGNode->out, fout);
766 fprintf(fout,
"}\n");
782 fprintf(fout,
"# Control Flow Graph dump\n\n");
786 "Note: The value of register \'zero\' is immutable.\n"
787 "As a result, it does not appear in the liveness sets.\n\n");
794 fprintf(fout,
"## Basic Blocks\n\n");
798 while (curNode != NULL) {
800 fprintf(fout,
"Block %d:\n", counter);
801 cfgDumpBB(curBlock, fout, verbose);
805 curNode = curNode->
next;
void bbAddPred(t_basicBlock *block, t_basicBlock *pred)
t_basicBlock * newBasicBlock(void)
void deleteBasicBlock(t_basicBlock *block)
t_basicBlock * cfgCreateBlock(t_cfg *graph)
void bbAddSucc(t_basicBlock *block, t_basicBlock *succ)
Control Flow Graph generation and related analyses.
bool printInstruction(t_instruction *instr, FILE *fp, bool machineRegIDs)
char * registerIDToString(t_regID regID, bool machineRegIDs)
t_listNode * pred
List of predecessors to this basic block.
t_regID tempRegID
Register identifier.
t_listNode * registers
List of all temporary registers used in the program.
t_listNode * mcRegWhitelist
Physical register whitelist. Used by the register allocator.
t_listNode * in
Set of registers live at the entry of the node ('in' set).
t_listNode * nodes
List of instructions in the block.
t_cfg * parent
The containing basic block.
t_basicBlock * parent
Pointer to the containing basic block.
t_listNode * out
Set of registers live at the exit of the node ('out' set).
t_listNode * succ
List of successors to this basic block.
t_instruction * instr
Pointer to the instruction associated with this node.
t_listNode * blocks
List of all the basic blocks, in program order.
t_basicBlock * endingBlock
t_cfgReg * defs[CFG_MAX_DEFS]
Set of registers defined by this node ('def' set). NULL slots are ignored.
t_cfgReg * uses[CFG_MAX_USES]
Set of registers used by this node ('use' set). NULL slots are ignored.
void cfgToProgram(t_program *program, t_cfg *graph)
void cfgComputeLiveness(t_cfg *graph)
void deleteCFG(t_cfg *graph)
t_listNode * bbGetLiveOut(t_basicBlock *bblock)
int cfgIterateNodes(t_cfg *graph, void *context, int(*callback)(t_bbNode *node, int nodeIndex, void *context))
#define CFG_MAX_USES
Maximum number of temporary register uses for each node.
t_bbNode * bbInsertInstruction(t_basicBlock *block, t_instruction *instr)
#define CFG_MAX_DEFS
Maximum number of temporary register definitions for each node.
t_bbNode * bbInsertInstructionBefore(t_basicBlock *block, t_instruction *instr, t_bbNode *ip)
void cfgDump(t_cfg *graph, FILE *fout, bool verbose)
t_listNode * bbGetLiveIn(t_basicBlock *bblock)
t_cfg * programToCFG(t_program *program)
t_bbNode * bbInsertInstructionAfter(t_basicBlock *block, t_instruction *instr, t_bbNode *ip)
void fatalError(const char *format,...)
void * data
Pointer to the data associated to this node.
t_listNode * listInsertBefore(t_listNode *list, t_listNode *listPos, void *data)
t_listNode * listFindAndRemove(t_listNode *list, void *data)
t_listNode * listInsertAfter(t_listNode *list, t_listNode *listPos, void *data)
t_listNode * listClone(t_listNode *list)
t_listNode * listInsert(t_listNode *list, void *data, int pos)
t_listNode * listFind(t_listNode *list, void *data)
int listLength(t_listNode *list)
t_listNode * deleteList(t_listNode *list)
t_listNode * listFindWithCallback(t_listNode *list, void *data, bool(*compareFunc)(void *a, void *b))
t_listNode * listRemoveNode(t_listNode *list, t_listNode *element)
t_listNode * listGetLastNode(t_listNode *list)
t_listNode * instructions
List of instructions.
t_listNode * mcRegWhitelist
unsigned int labelID
Unique numeric identifier for the label.
t_instrArg * rSrc1
First source argument (or NULL if none).
t_instrArg * rSrc2
Second source argument (or NULL if none).
t_regID ID
The register identifier.
t_label * label
Label associated with the instruction, or NULL.
t_instrArg * rDest
Destination argument (or NULL if none).
#define REG_INVALID
Constant used for invalid register identifiers.
#define REG_0
Constant identifying a register whose value is always zero.
int t_regID
Type for register identifiers.
#define TARGET_REG_ZERO_IS_CONST
bool isUnconditionalJump(t_instruction *instr)
bool isJumpInstruction(t_instruction *instr)
bool isExitInstruction(t_instruction *instr)
Generation of the output assembly program.
Properties of the target machine.