#include "compiler.h" #include "compiler/CompilerTools.h" #include "compiler/PCode.h" #include "compiler/PCodeInfo.h" PCodeBlock *pcbasicblocks; PCodeBlock *pclastblock; void *prologue; void *epilogue; PCodeBlock **depthfirstordering; int pcblockcount; int pcloopweight; static unsigned short pclabelcount; void initpcode() { pclastblock = 0; pcbasicblocks = 0; pcblockcount = 0; pclabelcount = 0; pcloopweight = 1; initialize_aliases(); } PCode *makepcode(short op, ...) { PCode *pcode; va_list list; va_start(list, op); pcode = vformatpcode(op, list); pcode->sourceoffset = current_statement ? current_statement->sourceoffset : -1; return pcode; } void emitpcode(short op, ...) { PCode *pcode; va_list list; va_start(list, op); pcode = vformatpcode(op, list); pcode->sourceoffset = current_statement ? current_statement->sourceoffset : -1; appendpcode(pclastblock, pcode); } PCode *copypcode(PCode *pcode) { PCode *newpc; int extra_arg; int i; extra_arg = 0; if ((PCODE_FLAG_SET_F(pcode) & fPCodeFlag8000000) && !(PCODE_FLAG_SET_F(pcode) & fPCodeFlag20000000)) extra_arg = 1; newpc = lalloc(sizeof(PCode) + sizeof(PCodeArg) * (pcode->argCount + extra_arg)); memclrw(newpc, sizeof(PCode) + sizeof(PCodeArg) * (pcode->argCount + extra_arg)); newpc->op = pcode->op; newpc->flags = pcode->flags; newpc->argCount = pcode->argCount; newpc->_18 = pcode->_18; for (i = 0; i < pcode->argCount; i++) { newpc->args[i] = pcode->args[i]; } if (extra_arg) newpc->args[pcode->argCount].kind = PCOp_PLACEHOLDEROPERAND; return newpc; } PCodeLabel *makepclabel() { PCodeLabel *label; label = (PCodeLabel *) lalloc(sizeof(PCodeLabel)); memclrw(label, sizeof(PCodeLabel)); label->index = pclabelcount++; return label; } PCodeBlock *makepcblock() { PCodeBlock *block; block = (PCodeBlock *) lalloc(sizeof(PCodeBlock)); memclrw(block, sizeof(PCodeBlock)); block->loopWeight = pcloopweight; block->blockIndex = pcblockcount++; if (pclastblock) { pclastblock->nextBlock = block; block->prevBlock = pclastblock; } else { pcbasicblocks = block; } pclastblock = block; return block; } void pclabel(PCodeBlock *block, PCodeLabel *label) { PCLink *iter; PCLink *next; iter = (PCLink *) label->block; while (iter) { next = (PCLink *) iter->block; iter->block = block; iter = next; } label->block = block; label->resolved = 1; label->nextLabel = block->labels; block->labels = label; } void pcbranch(PCodeBlock *block, PCodeLabel *label) { PCLink *link; link = (PCLink *) lalloc(sizeof(PCLink)); memclrw(link, sizeof(PCLink)); link->block = label->block; if (!label->resolved) label->block = (PCodeBlock *) link; link->nextLink = block->successors; block->successors = link; } void pccomputepredecessors() { PCodeBlock *block; PCLink *succ; PCLink *pred; for (block = pcbasicblocks; block; block = block->nextBlock) { for (succ = block->successors; succ; succ = succ->nextLink) { pred = (PCLink *) lalloc(sizeof(PCLink)); memclrw(pred, sizeof(PCLink)); pred->block = block; pred->nextLink = succ->block->predecessors; succ->block->predecessors = pred; } } } void deleteblock(PCodeBlock *block) { block->prevBlock->nextBlock = block->nextBlock; if (block->nextBlock) block->nextBlock->prevBlock = block->prevBlock; block->flags |= fPCBlockFlag20; } void deleteunreachableblocks() { PCodeBlock *block; computedepthfirstordering(); for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) { if (!(block->flags & fPCBlockFlag4)) deleteblock(block); } } void appendpcode(PCodeBlock *block, PCode *pcode) { if (block->firstPCode) { pcode->nextPCode = 0; pcode->prevPCode = block->lastPCode; block->lastPCode->nextPCode = pcode; block->lastPCode = pcode; } else { block->lastPCode = pcode; block->firstPCode = pcode; pcode->prevPCode = 0; pcode->nextPCode = 0; } pcode->block = block; block->pcodeCount++; } void deletepcode(PCode *pcode) { PCodeBlock *block; block = pcode->block; if (pcode->prevPCode) pcode->prevPCode->nextPCode = pcode->nextPCode; else block->firstPCode = pcode->nextPCode; if (pcode->nextPCode) pcode->nextPCode->prevPCode = pcode->prevPCode; else block->lastPCode = pcode->prevPCode; pcode->block = 0; block->pcodeCount--; block->flags &= ~fPCBlockFlag8; } void insertpcodebefore(PCode *anchor, PCode *newpcode) { PCodeBlock *block; block = anchor->block; if (anchor->prevPCode) anchor->prevPCode->nextPCode = newpcode; else block->firstPCode = newpcode; newpcode->nextPCode = anchor; newpcode->prevPCode = anchor->prevPCode; anchor->prevPCode = newpcode; newpcode->sourceoffset = anchor->sourceoffset; newpcode->block = block; block->pcodeCount++; block->flags &= ~fPCBlockFlag8; } void insertpcodeafter(PCode *anchor, PCode *newpcode) { PCodeBlock *block; block = anchor->block; if (anchor->nextPCode) anchor->nextPCode->prevPCode = newpcode; else block->lastPCode = newpcode; newpcode->prevPCode = anchor; newpcode->nextPCode = anchor->nextPCode; anchor->nextPCode = newpcode; newpcode->sourceoffset = anchor->sourceoffset; newpcode->block = block; block->pcodeCount++; block->flags &= ~fPCBlockFlag8; } void setpcodeflags(int flags) { pclastblock->lastPCode->flags |= flags; if (flags & fSideEffects) pclastblock->lastPCode->flags &= ~(fIsCSE | fCommutative | fPCodeFlag10); } void clearpcodeflags(int flags) { pclastblock->lastPCode->flags &= ~flags; } int pccomputeoffsets() { int offset; PCodeBlock *block; offset = 0; for (block = pcbasicblocks; block; block = block->nextBlock) { block->codeOffset = offset; offset += block->pcodeCount * 4; } return offset; } typedef struct _DFO { PCodeBlock *block; PCLink *link; } DFO; static int depthfirstorder; void computedepthfirstordering() { PCodeBlock *block; PCLink *link; DFO *dfo; int index; depthfirstordering = (PCodeBlock **) lalloc(sizeof(PCodeBlock *) * pcblockcount); memclrw(depthfirstordering, sizeof(PCodeBlock *) * pcblockcount); depthfirstorder = pcblockcount; for (block = pcbasicblocks; block; block = block->nextBlock) { block->flags &= ~fPCBlockFlag4; } dfo = (DFO *) oalloc(sizeof(DFO) * pcblockcount); pcbasicblocks->flags |= fPCBlockFlag4; dfo->block = pcbasicblocks; dfo->link = pcbasicblocks->successors; index = 1; while (index) { if ((link = dfo[index - 1].link)) { dfo[index - 1].link = link->nextLink; block = link->block; if (!(block->flags & fPCBlockFlag4)) { block->flags |= fPCBlockFlag4; dfo[index].block = block; dfo[index].link = block->successors; index++; } } else { depthfirstordering[--depthfirstorder] = dfo[--index].block; } } while (depthfirstorder) { depthfirstordering[--depthfirstorder] = 0; } }