2022-11-07 03:06:21 +00:00
|
|
|
#include "compiler/CompilerTools.h"
|
2022-11-20 05:07:22 +00:00
|
|
|
#include "compiler/CFunc.h"
|
|
|
|
#include "compiler/CodeGen.h"
|
2022-11-07 03:06:21 +00:00
|
|
|
#include "compiler/PCode.h"
|
|
|
|
#include "compiler/PCodeInfo.h"
|
2022-10-07 19:02:27 +00:00
|
|
|
|
2022-11-20 05:07:22 +00:00
|
|
|
// TODO: move me
|
|
|
|
extern void initialize_aliases();
|
|
|
|
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock *pcbasicblocks;
|
|
|
|
PCodeBlock *pclastblock;
|
2022-11-20 05:07:22 +00:00
|
|
|
PCodeBlock *prologue;
|
|
|
|
PCodeBlock *epilogue;
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock **depthfirstordering;
|
2022-10-07 19:02:27 +00:00
|
|
|
int pcblockcount;
|
|
|
|
int pcloopweight;
|
|
|
|
static unsigned short pclabelcount;
|
|
|
|
|
2022-11-20 05:07:22 +00:00
|
|
|
void initpcode(void) {
|
2022-10-07 19:02:27 +00:00
|
|
|
pclastblock = 0;
|
|
|
|
pcbasicblocks = 0;
|
|
|
|
pcblockcount = 0;
|
|
|
|
pclabelcount = 0;
|
|
|
|
pcloopweight = 1;
|
|
|
|
initialize_aliases();
|
|
|
|
}
|
|
|
|
|
2022-11-20 05:07:22 +00:00
|
|
|
PCode *makepcode(Opcode op, ...) {
|
2022-10-07 19:02:27 +00:00
|
|
|
PCode *pcode;
|
|
|
|
va_list list;
|
|
|
|
|
|
|
|
va_start(list, op);
|
|
|
|
pcode = vformatpcode(op, list);
|
2022-11-07 03:06:21 +00:00
|
|
|
pcode->sourceoffset = current_statement ? current_statement->sourceoffset : -1;
|
2022-10-07 19:02:27 +00:00
|
|
|
return pcode;
|
|
|
|
}
|
|
|
|
|
2022-11-20 05:07:22 +00:00
|
|
|
void emitpcode(Opcode op, ...) {
|
2022-10-07 19:02:27 +00:00
|
|
|
PCode *pcode;
|
|
|
|
va_list list;
|
|
|
|
|
|
|
|
va_start(list, op);
|
|
|
|
pcode = vformatpcode(op, list);
|
2022-11-07 03:06:21 +00:00
|
|
|
pcode->sourceoffset = current_statement ? current_statement->sourceoffset : -1;
|
2022-10-07 19:02:27 +00:00
|
|
|
appendpcode(pclastblock, pcode);
|
|
|
|
}
|
|
|
|
|
|
|
|
PCode *copypcode(PCode *pcode) {
|
|
|
|
PCode *newpc;
|
2022-11-07 03:06:21 +00:00
|
|
|
int extra_arg;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
extra_arg = 0;
|
2023-01-11 22:29:53 +00:00
|
|
|
if ((PCODE_FLAG_SET_F(pcode) & fCanSetRecordBit) && !(PCODE_FLAG_SET_F(pcode) & fRecordBit))
|
2022-11-07 03:06:21 +00:00
|
|
|
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;
|
2022-12-14 00:16:59 +00:00
|
|
|
newpc->alias = pcode->alias;
|
2022-11-07 03:06:21 +00:00
|
|
|
for (i = 0; i < pcode->argCount; i++) {
|
|
|
|
newpc->args[i] = pcode->args[i];
|
|
|
|
}
|
2022-10-07 19:02:27 +00:00
|
|
|
|
2022-11-07 03:06:21 +00:00
|
|
|
if (extra_arg)
|
|
|
|
newpc->args[pcode->argCount].kind = PCOp_PLACEHOLDEROPERAND;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
|
|
|
return newpc;
|
|
|
|
}
|
|
|
|
|
2022-11-20 05:07:22 +00:00
|
|
|
PCodeLabel *makepclabel(void) {
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeLabel *label;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
2022-11-07 03:06:21 +00:00
|
|
|
label = (PCodeLabel *) lalloc(sizeof(PCodeLabel));
|
|
|
|
memclrw(label, sizeof(PCodeLabel));
|
2022-10-07 19:02:27 +00:00
|
|
|
label->index = pclabelcount++;
|
|
|
|
return label;
|
|
|
|
}
|
|
|
|
|
2022-11-20 05:07:22 +00:00
|
|
|
PCodeBlock *makepcblock(void) {
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock *block;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
2022-11-07 03:06:21 +00:00
|
|
|
block = (PCodeBlock *) lalloc(sizeof(PCodeBlock));
|
|
|
|
memclrw(block, sizeof(PCodeBlock));
|
2022-10-07 19:02:27 +00:00
|
|
|
block->loopWeight = pcloopweight;
|
|
|
|
block->blockIndex = pcblockcount++;
|
|
|
|
if (pclastblock) {
|
|
|
|
pclastblock->nextBlock = block;
|
|
|
|
block->prevBlock = pclastblock;
|
|
|
|
} else {
|
|
|
|
pcbasicblocks = block;
|
|
|
|
}
|
|
|
|
pclastblock = block;
|
|
|
|
return block;
|
|
|
|
}
|
|
|
|
|
2022-11-07 03:06:21 +00:00
|
|
|
void pclabel(PCodeBlock *block, PCodeLabel *label) {
|
2022-10-07 19:02:27 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-11-07 03:06:21 +00:00
|
|
|
void pcbranch(PCodeBlock *block, PCodeLabel *label) {
|
2022-10-07 19:02:27 +00:00
|
|
|
PCLink *link;
|
|
|
|
|
|
|
|
link = (PCLink *) lalloc(sizeof(PCLink));
|
|
|
|
memclrw(link, sizeof(PCLink));
|
|
|
|
|
|
|
|
link->block = label->block;
|
|
|
|
if (!label->resolved)
|
2022-11-07 03:06:21 +00:00
|
|
|
label->block = (PCodeBlock *) link;
|
2022-10-07 19:02:27 +00:00
|
|
|
link->nextLink = block->successors;
|
|
|
|
block->successors = link;
|
|
|
|
}
|
|
|
|
|
2022-11-20 05:07:22 +00:00
|
|
|
void pccomputepredecessors(void) {
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock *block;
|
2022-10-07 19:02:27 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-07 03:06:21 +00:00
|
|
|
void deleteblock(PCodeBlock *block) {
|
2022-10-07 19:02:27 +00:00
|
|
|
block->prevBlock->nextBlock = block->nextBlock;
|
|
|
|
if (block->nextBlock)
|
|
|
|
block->nextBlock->prevBlock = block->prevBlock;
|
2023-01-11 22:29:53 +00:00
|
|
|
block->flags |= fDeleted;
|
2022-10-07 19:02:27 +00:00
|
|
|
}
|
|
|
|
|
2022-11-20 05:07:22 +00:00
|
|
|
void deleteunreachableblocks(void) {
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock *block;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
|
|
|
computedepthfirstordering();
|
|
|
|
|
|
|
|
for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) {
|
2023-01-11 22:29:53 +00:00
|
|
|
if (!(block->flags & fVisited))
|
2022-10-07 19:02:27 +00:00
|
|
|
deleteblock(block);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-07 03:06:21 +00:00
|
|
|
void appendpcode(PCodeBlock *block, PCode *pcode) {
|
2022-10-07 19:02:27 +00:00
|
|
|
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) {
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock *block;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
|
|
|
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--;
|
2023-01-11 22:29:53 +00:00
|
|
|
block->flags &= ~fScheduled;
|
2022-10-07 19:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void insertpcodebefore(PCode *anchor, PCode *newpcode) {
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock *block;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
|
|
|
block = anchor->block;
|
|
|
|
if (anchor->prevPCode)
|
|
|
|
anchor->prevPCode->nextPCode = newpcode;
|
|
|
|
else
|
|
|
|
block->firstPCode = newpcode;
|
|
|
|
newpcode->nextPCode = anchor;
|
|
|
|
newpcode->prevPCode = anchor->prevPCode;
|
|
|
|
anchor->prevPCode = newpcode;
|
2022-11-07 03:06:21 +00:00
|
|
|
newpcode->sourceoffset = anchor->sourceoffset;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
|
|
|
newpcode->block = block;
|
|
|
|
block->pcodeCount++;
|
2023-01-11 22:29:53 +00:00
|
|
|
block->flags &= ~fScheduled;
|
2022-10-07 19:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void insertpcodeafter(PCode *anchor, PCode *newpcode) {
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock *block;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
|
|
|
block = anchor->block;
|
|
|
|
if (anchor->nextPCode)
|
|
|
|
anchor->nextPCode->prevPCode = newpcode;
|
|
|
|
else
|
|
|
|
block->lastPCode = newpcode;
|
|
|
|
newpcode->prevPCode = anchor;
|
|
|
|
newpcode->nextPCode = anchor->nextPCode;
|
|
|
|
anchor->nextPCode = newpcode;
|
2022-11-07 03:06:21 +00:00
|
|
|
newpcode->sourceoffset = anchor->sourceoffset;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
|
|
|
newpcode->block = block;
|
|
|
|
block->pcodeCount++;
|
2023-01-11 22:29:53 +00:00
|
|
|
block->flags &= ~fScheduled;
|
2022-10-07 19:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setpcodeflags(int flags) {
|
|
|
|
pclastblock->lastPCode->flags |= flags;
|
|
|
|
if (flags & fSideEffects)
|
2023-01-11 22:29:53 +00:00
|
|
|
pclastblock->lastPCode->flags &= ~(fIsCSE | fCommutative | fIsMove);
|
2022-10-07 19:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void clearpcodeflags(int flags) {
|
|
|
|
pclastblock->lastPCode->flags &= ~flags;
|
|
|
|
}
|
|
|
|
|
2022-11-20 05:07:22 +00:00
|
|
|
int pccomputeoffsets(void) {
|
2022-10-07 19:02:27 +00:00
|
|
|
int offset;
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock *block;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
|
|
|
offset = 0;
|
|
|
|
for (block = pcbasicblocks; block; block = block->nextBlock) {
|
|
|
|
block->codeOffset = offset;
|
|
|
|
offset += block->pcodeCount * 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct _DFO {
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock *block;
|
2022-10-07 19:02:27 +00:00
|
|
|
PCLink *link;
|
|
|
|
} DFO;
|
|
|
|
|
|
|
|
static int depthfirstorder;
|
|
|
|
|
2022-11-20 05:07:22 +00:00
|
|
|
void computedepthfirstordering(void) {
|
2022-11-07 03:06:21 +00:00
|
|
|
PCodeBlock *block;
|
2022-10-07 19:02:27 +00:00
|
|
|
PCLink *link;
|
|
|
|
DFO *dfo;
|
|
|
|
int index;
|
|
|
|
|
2022-11-07 03:06:21 +00:00
|
|
|
depthfirstordering = (PCodeBlock **) lalloc(sizeof(PCodeBlock *) * pcblockcount);
|
|
|
|
memclrw(depthfirstordering, sizeof(PCodeBlock *) * pcblockcount);
|
2022-10-07 19:02:27 +00:00
|
|
|
depthfirstorder = pcblockcount;
|
|
|
|
|
|
|
|
for (block = pcbasicblocks; block; block = block->nextBlock) {
|
2023-01-11 22:29:53 +00:00
|
|
|
block->flags &= ~fVisited;
|
2022-10-07 19:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dfo = (DFO *) oalloc(sizeof(DFO) * pcblockcount);
|
2023-01-11 22:29:53 +00:00
|
|
|
pcbasicblocks->flags |= fVisited;
|
2022-10-07 19:02:27 +00:00
|
|
|
|
|
|
|
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;
|
2023-01-11 22:29:53 +00:00
|
|
|
if (!(block->flags & fVisited)) {
|
|
|
|
block->flags |= fVisited;
|
2022-10-07 19:02:27 +00:00
|
|
|
dfo[index].block = block;
|
|
|
|
dfo[index].link = block->successors;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
depthfirstordering[--depthfirstorder] = dfo[--index].block;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while (depthfirstorder) {
|
|
|
|
depthfirstordering[--depthfirstorder] = 0;
|
|
|
|
}
|
|
|
|
}
|