Add experimental native code outliner
This commit is contained in:
parent
9f834c4232
commit
95732265f6
|
@ -293,7 +293,7 @@ const char* AsmInstructionNames[NUM_ASM_INS_TYPES] = {
|
||||||
"INV", "BYT"
|
"INV", "BYT"
|
||||||
};
|
};
|
||||||
|
|
||||||
int AsmInsModeSize[NUM_ASM_INS_MODES] = {
|
int AsmInsModeSize[NUM_ASM_INS_MODES_X] = {
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
|
@ -306,6 +306,8 @@ int AsmInsModeSize[NUM_ASM_INS_MODES] = {
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
|
0,
|
||||||
|
2
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitAssembler(void)
|
void InitAssembler(void)
|
||||||
|
|
|
@ -31,7 +31,9 @@ enum AsmInsMode
|
||||||
|
|
||||||
NUM_ASM_INS_MODES,
|
NUM_ASM_INS_MODES,
|
||||||
|
|
||||||
ASMIM_IMMEDIATE_ADDRESS
|
ASMIM_IMMEDIATE_ADDRESS,
|
||||||
|
|
||||||
|
NUM_ASM_INS_MODES_X,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AsmInsData
|
struct AsmInsData
|
||||||
|
@ -45,6 +47,8 @@ extern AsmInsData DecInsData[256];
|
||||||
|
|
||||||
extern short AsmInsOpcodes[NUM_ASM_INS_TYPES][NUM_ASM_INS_MODES];
|
extern short AsmInsOpcodes[NUM_ASM_INS_TYPES][NUM_ASM_INS_MODES];
|
||||||
|
|
||||||
|
extern int AsmInsModeSize[NUM_ASM_INS_MODES_X];
|
||||||
|
|
||||||
extern const char* AsmInstructionNames[NUM_ASM_INS_TYPES];
|
extern const char* AsmInstructionNames[NUM_ASM_INS_TYPES];
|
||||||
|
|
||||||
AsmInsType FindAsmInstruction(const char * ins);
|
AsmInsType FindAsmInstruction(const char * ins);
|
||||||
|
|
|
@ -466,7 +466,7 @@ void Compiler::CompileProcedure(InterCodeProcedure* proc)
|
||||||
printf("Generate native code <%s>\n", proc->mIdent->mString);
|
printf("Generate native code <%s>\n", proc->mIdent->mString);
|
||||||
|
|
||||||
ncproc->Compile(proc);
|
ncproc->Compile(proc);
|
||||||
mNativeProcedures.Push(ncproc);
|
mNativeCodeGenerator->mProcedures.Push(ncproc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1036,13 +1036,15 @@ bool Compiler::GenerateCode(void)
|
||||||
mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection);
|
mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mNativeCodeGenerator->OutlineFunctions();
|
||||||
|
|
||||||
mNativeCodeGenerator->BuildFunctionProxies();
|
mNativeCodeGenerator->BuildFunctionProxies();
|
||||||
|
|
||||||
for (int i = 0; i < mNativeProcedures.Size(); i++)
|
for (int i = 0; i < mNativeCodeGenerator->mProcedures.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mCompilerOptions & COPT_VERBOSE2)
|
if (mCompilerOptions & COPT_VERBOSE2)
|
||||||
printf("Assemble native code <%s>\n", mNativeProcedures[i]->mInterProc->mIdent->mString);
|
printf("Assemble native code <%s>\n", mNativeCodeGenerator->mProcedures[i]->mInterProc->mIdent->mString);
|
||||||
mNativeProcedures[i]->Assemble();
|
mNativeCodeGenerator->mProcedures[i]->Assemble();
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkerObject* byteCodeObject = nullptr;
|
LinkerObject* byteCodeObject = nullptr;
|
||||||
|
|
|
@ -29,7 +29,6 @@ public:
|
||||||
GlobalOptimizer* mGlobalOptimizer;
|
GlobalOptimizer* mGlobalOptimizer;
|
||||||
|
|
||||||
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
|
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
|
||||||
ExpandingArray<NativeCodeProcedure*> mNativeProcedures;
|
|
||||||
|
|
||||||
TargetMachine mTargetMachine;
|
TargetMachine mTargetMachine;
|
||||||
uint64 mCompilerOptions;
|
uint64 mCompilerOptions;
|
||||||
|
|
|
@ -14,6 +14,7 @@ static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 1ULL << 8;
|
||||||
static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9;
|
static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9;
|
||||||
static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10;
|
static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10;
|
||||||
static const uint64 COPT_OPTIMIZE_GLOBAL = 1ULL << 11;
|
static const uint64 COPT_OPTIMIZE_GLOBAL = 1ULL << 11;
|
||||||
|
static const uint64 COPT_OPTIMIZE_OUTLINE = 1ULL << 12;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16;
|
static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16;
|
||||||
static const uint64 COPT_NATIVE = 1ULL << 17;
|
static const uint64 COPT_NATIVE = 1ULL << 17;
|
||||||
|
@ -50,7 +51,7 @@ static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE |
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS;
|
static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;
|
static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;// | COPT_OPTIMIZE_OUTLINE;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;
|
static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;
|
||||||
|
|
||||||
|
|
|
@ -9533,7 +9533,12 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
|
||||||
else
|
else
|
||||||
mTrueValueRange[s1].LimitMinWeak(0);
|
mTrueValueRange[s1].LimitMinWeak(0);
|
||||||
|
|
||||||
if (mFalseValueRange[s1].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[s1].mMinValue >= 0)
|
if (mInstructions[sz - 2]->mSrc[1].mType == IT_INT8)
|
||||||
|
{
|
||||||
|
mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
|
||||||
|
mFalseValueRange[s1].LimitMax(255);
|
||||||
|
}
|
||||||
|
else if (mFalseValueRange[s1].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[s1].mMinValue >= 0)
|
||||||
{
|
{
|
||||||
mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
|
mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
|
||||||
}
|
}
|
||||||
|
@ -19507,7 +19512,7 @@ void InterCodeBasicBlock::CheckFinalLocal(void)
|
||||||
{
|
{
|
||||||
if (ins->mSrc[j].mTemp >= 0 && !provided[ins->mSrc[j].mTemp])
|
if (ins->mSrc[j].mTemp >= 0 && !provided[ins->mSrc[j].mTemp])
|
||||||
{
|
{
|
||||||
printf("Use of potentially undefined temp %d\n", ins->mSrc[j].mTemp);
|
// printf("Use of potentially undefined temp %d\n", ins->mSrc[j].mTemp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23211,7 +23216,7 @@ void InterCodeProcedure::Close(void)
|
||||||
{
|
{
|
||||||
GrowingTypeArray tstack(IT_NONE);
|
GrowingTypeArray tstack(IT_NONE);
|
||||||
|
|
||||||
CheckFunc = !strcmp(mIdent->mString, "enemies_iterate");
|
CheckFunc = !strcmp(mIdent->mString, "main");
|
||||||
CheckCase = false;
|
CheckCase = false;
|
||||||
|
|
||||||
mEntryBlock = mBlocks[0];
|
mEntryBlock = mBlocks[0];
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "NativeCodeGenerator.h"
|
#include "NativeCodeGenerator.h"
|
||||||
#include "CompilerTypes.h"
|
#include "CompilerTypes.h"
|
||||||
|
#include "NativeCodeOutliner.h"
|
||||||
|
|
||||||
#define JUMP_TO_BRANCH 1
|
#define JUMP_TO_BRANCH 1
|
||||||
#define CHECK_NULLPTR 0
|
#define CHECK_NULLPTR 0
|
||||||
|
@ -539,6 +540,67 @@ NativeCodeInstruction::NativeCodeInstruction(const InterInstruction* ins, AsmIns
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* NativeCodeInstruction::AddrName(char* buffer) const
|
||||||
|
{
|
||||||
|
if (mLinkerObject)
|
||||||
|
{
|
||||||
|
if (mLinkerObject->mIdent)
|
||||||
|
sprintf_s(buffer, 160, "%s + %d", mLinkerObject->mIdent->mString, mAddress);
|
||||||
|
else
|
||||||
|
sprintf_s(buffer, 160, "_lobj%d + %d", mLinkerObject->mID, mAddress);
|
||||||
|
}
|
||||||
|
else if (mAddress < 256)
|
||||||
|
sprintf_s(buffer, 160, "%02x", mAddress);
|
||||||
|
else
|
||||||
|
sprintf_s(buffer, 160, "%04x", mAddress);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeCodeInstruction::Disassemble(FILE* file) const
|
||||||
|
{
|
||||||
|
char buffer[160];
|
||||||
|
|
||||||
|
switch (mMode)
|
||||||
|
{
|
||||||
|
case ASMIM_IMPLIED:
|
||||||
|
fprintf(file, "%s", AsmInstructionNames[mType]);
|
||||||
|
break;
|
||||||
|
case ASMIM_IMMEDIATE:
|
||||||
|
fprintf(file, "%s #$%02x", AsmInstructionNames[mType], mAddress);
|
||||||
|
break;
|
||||||
|
case ASMIM_ZERO_PAGE:
|
||||||
|
fprintf(file, "%s %s", AsmInstructionNames[mType], AddrName(buffer));
|
||||||
|
break;
|
||||||
|
case ASMIM_ZERO_PAGE_X:
|
||||||
|
fprintf(file, "%s %s, x", AsmInstructionNames[mType], AddrName(buffer));
|
||||||
|
break;
|
||||||
|
case ASMIM_ZERO_PAGE_Y:
|
||||||
|
fprintf(file, "%s %s, y", AsmInstructionNames[mType], AddrName(buffer));
|
||||||
|
break;
|
||||||
|
case ASMIM_ABSOLUTE:
|
||||||
|
fprintf(file, "%s %s", AsmInstructionNames[mType], AddrName(buffer));
|
||||||
|
break;
|
||||||
|
case ASMIM_ABSOLUTE_X:
|
||||||
|
fprintf(file, "%s %s, x", AsmInstructionNames[mType], AddrName(buffer));
|
||||||
|
break;
|
||||||
|
case ASMIM_ABSOLUTE_Y:
|
||||||
|
fprintf(file, "%s %s, y", AsmInstructionNames[mType], AddrName(buffer));
|
||||||
|
break;
|
||||||
|
case ASMIM_INDIRECT:
|
||||||
|
fprintf(file, "%s (%s)", AsmInstructionNames[mType], AddrName(buffer));
|
||||||
|
break;
|
||||||
|
case ASMIM_INDIRECT_X:
|
||||||
|
fprintf(file, "%s (%s, x)", AsmInstructionNames[mType], AddrName(buffer));
|
||||||
|
break;
|
||||||
|
case ASMIM_INDIRECT_Y:
|
||||||
|
fprintf(file, "%s (%s), y", AsmInstructionNames[mType], AddrName(buffer));
|
||||||
|
break;
|
||||||
|
case ASMIM_RELATIVE:
|
||||||
|
fprintf(file, "%s %d", AsmInstructionNames[mType], mAddress);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps)
|
bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps)
|
||||||
{
|
{
|
||||||
|
@ -4951,6 +5013,28 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 NativeCodeInstruction::CodeHash(void) const
|
||||||
|
{
|
||||||
|
uint32 hash = mType + 0x20 * mMode + 0x100 * mAddress;
|
||||||
|
if (mLinkerObject)
|
||||||
|
hash += mLinkerObject->mID * 0x1000;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeInstruction::CodeSame(const NativeCodeInstruction& ins)
|
||||||
|
{
|
||||||
|
if (mType != ins.mType || mMode != ins.mMode)
|
||||||
|
return false;
|
||||||
|
if (mMode != ASMIM_IMPLIED && (mAddress != ins.mAddress || mLinkerObject != ins.mLinkerObject))
|
||||||
|
return false;
|
||||||
|
if (mMode == ASMIM_IMMEDIATE_ADDRESS && (mFlags & (NCIF_LOWER | NCIF_UPPER)) != (ins.mFlags & (NCIF_LOWER | NCIF_UPPER)))
|
||||||
|
return false;
|
||||||
|
if ((mFlags & NCIF_USE_ZP_32_X) && mParam != ins.mParam)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void NativeCodeInstruction::CopyMode(const NativeCodeInstruction& ins)
|
void NativeCodeInstruction::CopyMode(const NativeCodeInstruction& ins)
|
||||||
{
|
{
|
||||||
mMode = ins.mMode;
|
mMode = ins.mMode;
|
||||||
|
@ -5019,7 +5103,7 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mType == ASMIT_JSR && (mFlags & NCIF_USE_ZP_32_X))
|
if ((mType == ASMIT_JSR || mType == ASMIT_JMP) && (mFlags & NCIF_USE_ZP_32_X))
|
||||||
{
|
{
|
||||||
block->PutOpcode(AsmInsOpcodes[ASMIT_LDX][ASMIM_IMMEDIATE]);
|
block->PutOpcode(AsmInsOpcodes[ASMIT_LDX][ASMIM_IMMEDIATE]);
|
||||||
block->PutByte(mParam);
|
block->PutByte(mParam);
|
||||||
|
@ -7818,9 +7902,9 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc,
|
||||||
|
|
||||||
if (sstride > 1 || dstride > 1)
|
if (sstride > 1 || dstride > 1)
|
||||||
msize = 32;
|
msize = 32;
|
||||||
else if (nproc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL)
|
else if (nproc->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL)
|
||||||
msize = 8;
|
msize = 8;
|
||||||
else if (nproc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE)
|
else if (nproc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE)
|
||||||
msize = 2;
|
msize = 2;
|
||||||
#if 1
|
#if 1
|
||||||
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp < 0)
|
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp < 0)
|
||||||
|
@ -8314,9 +8398,9 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::FillValue(InterCodeProcedure* proc,
|
||||||
|
|
||||||
if (dstride > 1)
|
if (dstride > 1)
|
||||||
msize = 32;
|
msize = 32;
|
||||||
else if (nproc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL)
|
else if (nproc->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL)
|
||||||
msize = 8;
|
msize = 8;
|
||||||
else if (nproc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE)
|
else if (nproc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE)
|
||||||
msize = 2;
|
msize = 2;
|
||||||
#if 1
|
#if 1
|
||||||
if (ins->mSrc[1].mTemp < 0)
|
if (ins->mSrc[1].mTemp < 0)
|
||||||
|
@ -10604,8 +10688,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
int lcost = 8 + 2 * (nbytes - 1);
|
int lcost = 8 + 2 * (nbytes - 1);
|
||||||
int ucost = shift * (1 + 2 * nbytes);
|
int ucost = shift * (1 + 2 * nbytes);
|
||||||
|
|
||||||
if ((nproc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && lcost < ucost ||
|
if ((nproc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && lcost < ucost ||
|
||||||
!(nproc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL) && 2 * lcost < ucost)
|
!(nproc->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL) && 2 * lcost < ucost)
|
||||||
{
|
{
|
||||||
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_IMMEDIATE, shift));
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_IMMEDIATE, shift));
|
||||||
this->Close(ins, lblock, nullptr, ASMIT_JMP);
|
this->Close(ins, lblock, nullptr, ASMIT_JMP);
|
||||||
|
@ -14015,6 +14099,35 @@ void NativeCodeBasicBlock::CallFunction(InterCodeProcedure* proc, NativeCodeProc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NativeCodeBasicBlock::Disassemble(FILE* file)
|
||||||
|
{
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
fprintf(file, "L%d:\n", mIndex);
|
||||||
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
|
{
|
||||||
|
fprintf(file, "%03d ", i);
|
||||||
|
mIns[i].Disassemble(file);
|
||||||
|
fprintf(file, "\n");
|
||||||
|
}
|
||||||
|
fprintf(file, "%03d %s", mIns.Size(), AsmInstructionNames[mBranch]);
|
||||||
|
if (mTrueJump)
|
||||||
|
{
|
||||||
|
fprintf(file, " L%d", mTrueJump->mIndex);
|
||||||
|
if (mFalseJump)
|
||||||
|
fprintf(file, ", L%d", mFalseJump->mIndex);
|
||||||
|
}
|
||||||
|
fprintf(file, "\n");
|
||||||
|
|
||||||
|
if (mTrueJump) mTrueJump->Disassemble(file);
|
||||||
|
if (mFalseJump) mFalseJump->Disassemble(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NativeCodeInstruction NativeCodeBasicBlock::DecodeNative(const InterInstruction* ins, LinkerObject* lobj, int& offset) const
|
NativeCodeInstruction NativeCodeBasicBlock::DecodeNative(const InterInstruction* ins, LinkerObject* lobj, int& offset) const
|
||||||
{
|
{
|
||||||
uint8 op = lobj->mData[offset++];
|
uint8 op = lobj->mData[offset++];
|
||||||
|
@ -41554,7 +41667,7 @@ static bool CheckBlockCopySequence(const ExpandingArray<NativeCodeInstruction>&
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::BlockSizeCopyReduction(NativeCodeProcedure* proc, int& si, int& di)
|
bool NativeCodeBasicBlock::BlockSizeCopyReduction(NativeCodeProcedure* proc, int& si, int& di)
|
||||||
{
|
{
|
||||||
if ((proc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE))
|
if ((proc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE))
|
||||||
{
|
{
|
||||||
if (si + 1 < mIns.Size() &&
|
if (si + 1 < mIns.Size() &&
|
||||||
mIns[si + 0].mType == ASMIT_LDA && (mIns[si + 0].mMode == ASMIM_ZERO_PAGE || mIns[si + 0].mMode == ASMIM_ABSOLUTE) &&
|
mIns[si + 0].mType == ASMIT_LDA && (mIns[si + 0].mMode == ASMIM_ZERO_PAGE || mIns[si + 0].mMode == ASMIM_ABSOLUTE) &&
|
||||||
|
@ -51378,6 +51491,32 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeCodeBasicBlock::AddToSuffixTree(NativeCodeMapper& mapper, SuffixTree * tree)
|
||||||
|
{
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
if (!mSuffixString)
|
||||||
|
mSuffixString = new int[mIns.Size() + 100];
|
||||||
|
|
||||||
|
bool rel = false;
|
||||||
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
|
{
|
||||||
|
if (mIns[i].mMode == ASMIM_RELATIVE)
|
||||||
|
rel = true;
|
||||||
|
mSuffixString[i] = mapper.MapInstruction(mIns[i], mProc->mLinkerObject->mSection);
|
||||||
|
}
|
||||||
|
mSuffixString[mIns.Size()] = mapper.MapBasicBlock(this);
|
||||||
|
|
||||||
|
if (!rel)
|
||||||
|
tree->AddString(mSuffixString);
|
||||||
|
|
||||||
|
if (mTrueJump) mTrueJump->AddToSuffixTree(mapper, tree);
|
||||||
|
if (mFalseJump) mFalseJump->AddToSuffixTree(mapper, tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NativeCodeBasicBlock::CheckVisited(void)
|
void NativeCodeBasicBlock::CheckVisited(void)
|
||||||
{
|
{
|
||||||
#if _DEBUG
|
#if _DEBUG
|
||||||
|
@ -52063,6 +52202,7 @@ NativeCodeBasicBlock::NativeCodeBasicBlock(NativeCodeProcedure* proc)
|
||||||
mDominator = nullptr;
|
mDominator = nullptr;
|
||||||
mLoopHeadBlock = nullptr;
|
mLoopHeadBlock = nullptr;
|
||||||
mLoopTailBlock = nullptr;
|
mLoopTailBlock = nullptr;
|
||||||
|
mSuffixString = nullptr;
|
||||||
mEntryRegA = false;
|
mEntryRegA = false;
|
||||||
mEntryRegX = false;
|
mEntryRegX = false;
|
||||||
mEntryRegY = false;
|
mEntryRegY = false;
|
||||||
|
@ -52089,6 +52229,22 @@ NativeCodeProcedure::~NativeCodeProcedure(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NativeCodeProcedure::Disassemble(FILE* file)
|
||||||
|
{
|
||||||
|
fprintf(file, "--------------------------------------------------------------------\n");
|
||||||
|
fprintf(file, "%s: %s:%d\n", mIdent->mString, mLocation.mFileName, mLocation.mLine);
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
mEntryBlock->Disassemble(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeCodeProcedure::AddToSuffixTree(NativeCodeMapper& mapper, SuffixTree* tree)
|
||||||
|
{
|
||||||
|
ResetVisited();
|
||||||
|
mEntryBlock->AddToSuffixTree(mapper, tree);
|
||||||
|
}
|
||||||
|
|
||||||
void NativeCodeProcedure::CompressTemporaries(bool singles)
|
void NativeCodeProcedure::CompressTemporaries(bool singles)
|
||||||
{
|
{
|
||||||
if (mInterProc->mTempSize > 0)
|
if (mInterProc->mTempSize > 0)
|
||||||
|
@ -52286,9 +52442,14 @@ void NativeCodeProcedure::LoadTempsFromStack(int tempSave)
|
||||||
void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
mInterProc = proc;
|
mInterProc = proc;
|
||||||
|
mLinkerObject = proc->mLinkerObject;
|
||||||
|
mIdent = proc->mIdent;
|
||||||
|
mLocation = proc->mLocation;
|
||||||
|
mCompilerOptions = proc->mCompilerOptions;
|
||||||
|
|
||||||
mInterProc->mLinkerObject->mNativeProc = this;
|
mInterProc->mLinkerObject->mNativeProc = this;
|
||||||
|
|
||||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "rirq_sort");
|
CheckFunc = !strcmp(mIdent->mString, "rirq_sort");
|
||||||
|
|
||||||
int nblocks = proc->mBlocks.Size();
|
int nblocks = proc->mBlocks.Size();
|
||||||
tblocks = new NativeCodeBasicBlock * [nblocks];
|
tblocks = new NativeCodeBasicBlock * [nblocks];
|
||||||
|
@ -52417,14 +52578,14 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
if (mInterProc->mInterrupt)
|
if (mInterProc->mInterrupt)
|
||||||
{
|
{
|
||||||
if (!mNoFrame || mStackExpand > 0 || commonFrameSize > 0)
|
if (!mNoFrame || mStackExpand > 0 || commonFrameSize > 0)
|
||||||
mGenerator->mErrors->Error(mInterProc->mLocation, ERRR_INTERRUPT_TO_COMPLEX, "Function to complex for interrupt");
|
mGenerator->mErrors->Error(mLocation, ERRR_INTERRUPT_TO_COMPLEX, "Function to complex for interrupt");
|
||||||
|
|
||||||
ZeroPageSet zpLocal, zpGlobal;
|
ZeroPageSet zpLocal, zpGlobal;
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
if (mEntryBlock->CollectZeroPageSet(zpLocal, zpGlobal, true))
|
if (mEntryBlock->CollectZeroPageSet(zpLocal, zpGlobal, true))
|
||||||
zpLocal |= zpGlobal;
|
zpLocal |= zpGlobal;
|
||||||
else
|
else
|
||||||
mGenerator->mErrors->Error(mInterProc->mLocation, ERRR_INTERRUPT_TO_COMPLEX, "No recursive functions in interrupt");
|
mGenerator->mErrors->Error(mLocation, ERRR_INTERRUPT_TO_COMPLEX, "No recursive functions in interrupt");
|
||||||
|
|
||||||
if (proc->mHardwareInterrupt)
|
if (proc->mHardwareInterrupt)
|
||||||
{
|
{
|
||||||
|
@ -52830,7 +52991,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)
|
if (mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->RegisterFunctionCalls();
|
mEntryBlock->RegisterFunctionCalls();
|
||||||
|
@ -52839,9 +53000,9 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
|
|
||||||
void NativeCodeProcedure::Assemble(void)
|
void NativeCodeProcedure::Assemble(void)
|
||||||
{
|
{
|
||||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "fighter_ai");
|
CheckFunc = !strcmp(mIdent->mString, "fighter_ai");
|
||||||
|
|
||||||
if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)
|
if (mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->MergeFunctionCalls();
|
mEntryBlock->MergeFunctionCalls();
|
||||||
|
@ -52891,7 +53052,7 @@ void NativeCodeProcedure::Assemble(void)
|
||||||
for (int i = 0; i < placement.Size(); i++)
|
for (int i = 0; i < placement.Size(); i++)
|
||||||
placement[i]->mAsmFromJump = -1;
|
placement[i]->mAsmFromJump = -1;
|
||||||
|
|
||||||
uint8* data = mInterProc->mLinkerObject->AddSpace(total);
|
uint8* data = mLinkerObject->AddSpace(total);
|
||||||
|
|
||||||
for (int i = 0; i < placement.Size(); i++)
|
for (int i = 0; i < placement.Size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -52905,7 +53066,7 @@ void NativeCodeProcedure::Assemble(void)
|
||||||
range.mIdent = Ident::Unique(buffer);
|
range.mIdent = Ident::Unique(buffer);
|
||||||
range.mOffset = placement[i]->mOffset;
|
range.mOffset = placement[i]->mOffset;
|
||||||
range.mSize = placement[i]->mSize;
|
range.mSize = placement[i]->mSize;
|
||||||
mInterProc->mLinkerObject->mRanges.Push(range);
|
mLinkerObject->mRanges.Push(range);
|
||||||
placement[i]->CopyCode(this, data);
|
placement[i]->CopyCode(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52913,10 +53074,10 @@ void NativeCodeProcedure::Assemble(void)
|
||||||
for (int i = 0; i < mRelocations.Size(); i++)
|
for (int i = 0; i < mRelocations.Size(); i++)
|
||||||
{
|
{
|
||||||
LinkerReference& rl(mRelocations[i]);
|
LinkerReference& rl(mRelocations[i]);
|
||||||
rl.mObject = mInterProc->mLinkerObject;
|
rl.mObject = mLinkerObject;
|
||||||
if (!rl.mRefObject)
|
if (!rl.mRefObject)
|
||||||
rl.mRefObject = mInterProc->mLinkerObject;
|
rl.mRefObject = mLinkerObject;
|
||||||
mInterProc->mLinkerObject->AddReference(rl);
|
mLinkerObject->AddReference(rl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mGenerator->mCompilerOptions & (COPT_DEBUGINFO | COPT_PROFILEINFO))
|
if (mGenerator->mCompilerOptions & (COPT_DEBUGINFO | COPT_PROFILEINFO))
|
||||||
|
@ -52937,7 +53098,7 @@ void NativeCodeProcedure::Assemble(void)
|
||||||
}
|
}
|
||||||
mCodeLocations.SetSize(j + 1);
|
mCodeLocations.SetSize(j + 1);
|
||||||
|
|
||||||
mInterProc->mLinkerObject->AddLocations(mCodeLocations);
|
mLinkerObject->AddLocations(mCodeLocations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53947,7 +54108,7 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (step == 10 && (mInterProc->mCompilerOptions & COPT_OPTIMIZE_BASIC))
|
if (step == 10 && (mCompilerOptions & COPT_OPTIMIZE_BASIC))
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->MarkLocalUsedLinkerObjects();
|
mEntryBlock->MarkLocalUsedLinkerObjects();
|
||||||
|
@ -54051,7 +54212,7 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
|
|
||||||
if (step == 16)
|
if (step == 16)
|
||||||
{
|
{
|
||||||
if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_INLINE)
|
if (mCompilerOptions & COPT_OPTIMIZE_INLINE)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
if (mEntryBlock->SimpleInlineCalls())
|
if (mEntryBlock->SimpleInlineCalls())
|
||||||
|
@ -54061,7 +54222,7 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
|
|
||||||
if (step == 17)
|
if (step == 17)
|
||||||
{
|
{
|
||||||
if (!(mInterProc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE))
|
if (!(mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE))
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
if (mEntryBlock->Expand16BitLoopBranch())
|
if (mEntryBlock->Expand16BitLoopBranch())
|
||||||
|
@ -54100,7 +54261,7 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
if (cnt > 200)
|
if (cnt > 200)
|
||||||
{
|
{
|
||||||
changed = false;
|
changed = false;
|
||||||
mGenerator->mErrors->Error(mInterProc->mLocation, EWARN_OPTIMIZER_LOCKED, "Optimizer locked in infinite loop", mInterProc->mIdent);
|
mGenerator->mErrors->Error(mLocation, EWARN_OPTIMIZER_LOCKED, "Optimizer locked in infinite loop", mIdent);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
@ -55316,6 +55477,144 @@ bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeCodeGenerator::OutlineFunctions(void)
|
||||||
|
{
|
||||||
|
NativeCodeMapper mapper;
|
||||||
|
|
||||||
|
bool progress;
|
||||||
|
|
||||||
|
int k = 0;
|
||||||
|
|
||||||
|
int numOutlines = 0;
|
||||||
|
do {
|
||||||
|
progress = false;
|
||||||
|
|
||||||
|
SuffixTree* tree = new SuffixTree(nullptr, 0, nullptr);
|
||||||
|
|
||||||
|
for (int i = 0; i < mProcedures.Size(); i++)
|
||||||
|
{
|
||||||
|
if (mProcedures[i]->mCompilerOptions & COPT_OPTIMIZE_OUTLINE)
|
||||||
|
mProcedures[i]->AddToSuffixTree(mapper, tree);
|
||||||
|
}
|
||||||
|
tree->AddParents(nullptr);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
FILE* f;
|
||||||
|
|
||||||
|
if (!fopen_s(&f, "r:\\suffix.txt", "w"))
|
||||||
|
{
|
||||||
|
tree->Print(f, mapper, 0);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SuffixTree* ltree = nullptr;
|
||||||
|
int lsize = 6;
|
||||||
|
|
||||||
|
tree->LongestMatch(mapper, 0, 0, lsize, ltree);
|
||||||
|
if (lsize > 6)
|
||||||
|
{
|
||||||
|
SuffixTree* leaf = ltree;
|
||||||
|
while (leaf->mFirst)
|
||||||
|
leaf = leaf->mFirst;
|
||||||
|
NativeCodeBasicBlock* block = mapper.mBlocks[-(1 + leaf->mSeg[leaf->mSize - 1])];
|
||||||
|
|
||||||
|
NativeCodeProcedure* nproc = new NativeCodeProcedure(this);
|
||||||
|
|
||||||
|
NativeCodeBasicBlock* nblock = nproc->AllocateBlock();
|
||||||
|
|
||||||
|
// printf("Suffix %s,%d:%s\n", block->mProc->mIdent->mString, block->mIndex, block->mProc->mLinkerObject->mSection->mIdent->mString);
|
||||||
|
|
||||||
|
nproc->mLocation = block->mIns[0].mIns ? block->mIns[0].mIns->mLocation : block->mProc->mLocation;
|
||||||
|
nproc->mCompilerOptions = block->mProc->mCompilerOptions;
|
||||||
|
nproc->mIdent = Ident::Unique("$outline", numOutlines);
|
||||||
|
nproc->mLinkerObject = mLinker->AddObject(nproc->mLocation, nproc->mIdent, block->mProc->mLinkerObject->mSection, LOT_NATIVE_CODE);
|
||||||
|
nproc->mEntryBlock = nblock;
|
||||||
|
|
||||||
|
bool dojmp = false;
|
||||||
|
|
||||||
|
ltree->ParentCollect(mapper, nblock);
|
||||||
|
if (nblock->mIns[nblock->mIns.Size() - 1].mType == ASMIT_JSR)
|
||||||
|
nblock->mIns[nblock->mIns.Size() - 1].mType = ASMIT_JMP;
|
||||||
|
else if (nblock->mIns[nblock->mIns.Size() - 1].mType == ASMIT_RTS || nblock->mIns[nblock->mIns.Size() - 1].mType == ASMIT_JMP)
|
||||||
|
dojmp = true;
|
||||||
|
else
|
||||||
|
nblock->mIns.Push(NativeCodeInstruction(nblock->mIns[nblock->mIns.Size() - 1].mIns, ASMIT_RTS));
|
||||||
|
|
||||||
|
ExpandingArray<SuffixSegment> segs;
|
||||||
|
ltree->ReplaceCalls(mapper, segs);
|
||||||
|
|
||||||
|
segs.Sort([](const SuffixSegment& l, const SuffixSegment& r)->bool {
|
||||||
|
return l.mBlock == r.mBlock ? l.mStart > r.mStart : ptrdiff_t(l.mBlock) < ptrdiff_t(r.mBlock);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check for complete loop block replacement
|
||||||
|
int k = 0;
|
||||||
|
while (k < segs.Size() && segs[k].mStart == 0 && segs[k].mEnd == segs[k].mBlock->mIns.Size() && segs[k].mBlock->mTrueJump == segs[k].mBlock && segs[k].mBlock->mBranch == segs[0].mBlock->mBranch)
|
||||||
|
k++;
|
||||||
|
|
||||||
|
if (k == segs.Size())
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
||||||
|
|
||||||
|
nblock->mTrueJump = nblock;
|
||||||
|
nblock->mFalseJump = eblock;
|
||||||
|
nblock->mBranch = segs[0].mBlock->mBranch;
|
||||||
|
|
||||||
|
for (int i = 0; i < segs.Size(); i++)
|
||||||
|
{
|
||||||
|
SuffixSegment& s(segs[i]);
|
||||||
|
segs[i].mBlock->mTrueJump = segs[i].mBlock->mFalseJump;
|
||||||
|
segs[i].mBlock->mFalseJump = nullptr;
|
||||||
|
segs[i].mBlock->mBranch = ASMIT_JMP;
|
||||||
|
segs[i].mBlock->mNumEntries = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
eblock->mIns.Push(NativeCodeInstruction(nblock->mIns[nblock->mIns.Size() - 1].mIns, ASMIT_RTS));
|
||||||
|
if (nblock->mIns[nblock->mIns.Size() - 1].mType == ASMIT_JMP)
|
||||||
|
nblock->mIns[nblock->mIns.Size() - 1].mType = ASMIT_JSR;
|
||||||
|
else
|
||||||
|
nblock->mIns.Remove(nblock->mIns.Size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeCodeBasicBlock* pblock = nullptr;
|
||||||
|
int pstart;
|
||||||
|
for (int i = 0; i < segs.Size(); i++)
|
||||||
|
{
|
||||||
|
SuffixSegment& s(segs[i]);
|
||||||
|
// printf("Seg %s,%d\n", segs[i].mBlock->mProc->mIdent->mString, segs[i].mBlock->mIndex);
|
||||||
|
if (s.mBlock != pblock || s.mEnd <= pstart)
|
||||||
|
{
|
||||||
|
s.mBlock->mIns.Remove(s.mStart + 1, s.mEnd - s.mStart - 1);
|
||||||
|
s.mBlock->mIns[s.mStart] = NativeCodeInstruction(s.mBlock->mIns[s.mStart].mIns, dojmp ? ASMIT_JMP : ASMIT_JSR, ASMIM_ABSOLUTE, 0, nproc->mLinkerObject);
|
||||||
|
pblock = s.mBlock;
|
||||||
|
pstart = s.mStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mProcedures.Push(nproc);
|
||||||
|
|
||||||
|
numOutlines++;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
if (!fopen_s(&f, "r:\\lsuffix.txt", "w"))
|
||||||
|
{
|
||||||
|
ltree->ParentPrint(f, mapper);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
delete tree;
|
||||||
|
mapper.Reset();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
k++;
|
||||||
|
if (k == 2)
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
} while (progress);
|
||||||
|
}
|
||||||
|
|
||||||
void NativeCodeGenerator::BuildFunctionProxies(void)
|
void NativeCodeGenerator::BuildFunctionProxies(void)
|
||||||
{
|
{
|
||||||
FunctionCall* cp = mFunctionCalls;
|
FunctionCall* cp = mFunctionCalls;
|
||||||
|
|
|
@ -9,6 +9,9 @@ class NativeCodeBasicBlock;
|
||||||
class NativeCodeGenerator;
|
class NativeCodeGenerator;
|
||||||
class NativeCodeInstruction;
|
class NativeCodeInstruction;
|
||||||
|
|
||||||
|
class NativeCodeMapper;
|
||||||
|
class SuffixTree;
|
||||||
|
|
||||||
enum NativeRegisterDataMode
|
enum NativeRegisterDataMode
|
||||||
{
|
{
|
||||||
NRDM_UNKNOWN,
|
NRDM_UNKNOWN,
|
||||||
|
@ -154,6 +157,9 @@ public:
|
||||||
LinkerObject * mLinkerObject;
|
LinkerObject * mLinkerObject;
|
||||||
const InterInstruction * mIns;
|
const InterInstruction * mIns;
|
||||||
|
|
||||||
|
void Disassemble(FILE* file) const;
|
||||||
|
void DisassembleAddress(FILE* file) const;
|
||||||
|
|
||||||
void CopyMode(const NativeCodeInstruction& ins);
|
void CopyMode(const NativeCodeInstruction& ins);
|
||||||
|
|
||||||
void Assemble(NativeCodeBasicBlock* block);
|
void Assemble(NativeCodeBasicBlock* block);
|
||||||
|
@ -216,6 +222,12 @@ public:
|
||||||
void BuildCollisionTable(NumberSet& liveTemps, NumberSet* collisionSets);
|
void BuildCollisionTable(NumberSet& liveTemps, NumberSet* collisionSets);
|
||||||
|
|
||||||
uint32 NeedsLive(void) const;
|
uint32 NeedsLive(void) const;
|
||||||
|
|
||||||
|
uint32 CodeHash(void) const;
|
||||||
|
bool CodeSame(const NativeCodeInstruction& ins);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char* AddrName(char* buffer) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NativeCodeLoadStorePair
|
struct NativeCodeLoadStorePair
|
||||||
|
@ -264,6 +276,8 @@ public:
|
||||||
|
|
||||||
NativeCodeInstruction mALSIns, mXLSIns, mYLSIns;
|
NativeCodeInstruction mALSIns, mXLSIns, mYLSIns;
|
||||||
|
|
||||||
|
void Disassemble(FILE* file);
|
||||||
|
|
||||||
NativeCodeInstruction DecodeNative(const InterInstruction* ins, LinkerObject * lobj, int& offset) const;
|
NativeCodeInstruction DecodeNative(const InterInstruction* ins, LinkerObject * lobj, int& offset) const;
|
||||||
|
|
||||||
int PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, AsmInsType code, int from, int to);
|
int PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, AsmInsType code, int from, int to);
|
||||||
|
@ -817,6 +831,9 @@ public:
|
||||||
void CheckBlocks(bool sequence = false);
|
void CheckBlocks(bool sequence = false);
|
||||||
void CheckAsmCode(void);
|
void CheckAsmCode(void);
|
||||||
void CheckVisited(void);
|
void CheckVisited(void);
|
||||||
|
|
||||||
|
int* mSuffixString;
|
||||||
|
void AddToSuffixTree(NativeCodeMapper& mapper, SuffixTree * tree);
|
||||||
};
|
};
|
||||||
|
|
||||||
class NativeCodeProcedure
|
class NativeCodeProcedure
|
||||||
|
@ -831,6 +848,10 @@ class NativeCodeProcedure
|
||||||
NativeCodeGenerator* mGenerator;
|
NativeCodeGenerator* mGenerator;
|
||||||
|
|
||||||
InterCodeProcedure* mInterProc;
|
InterCodeProcedure* mInterProc;
|
||||||
|
LinkerObject* mLinkerObject;
|
||||||
|
const Ident* mIdent;
|
||||||
|
Location mLocation;
|
||||||
|
uint64 mCompilerOptions;
|
||||||
|
|
||||||
int mProgStart, mProgSize, mIndex, mFrameOffset, mStackExpand;
|
int mProgStart, mProgSize, mIndex, mFrameOffset, mStackExpand;
|
||||||
int mFastCallBase;
|
int mFastCallBase;
|
||||||
|
@ -842,10 +863,14 @@ class NativeCodeProcedure
|
||||||
ExpandingArray<CodeLocation> mCodeLocations;
|
ExpandingArray<CodeLocation> mCodeLocations;
|
||||||
|
|
||||||
|
|
||||||
|
void Disassemble(FILE* file);
|
||||||
|
|
||||||
void Compile(InterCodeProcedure* proc);
|
void Compile(InterCodeProcedure* proc);
|
||||||
void Optimize(void);
|
void Optimize(void);
|
||||||
void Assemble(void);
|
void Assemble(void);
|
||||||
|
|
||||||
|
void AddToSuffixTree(NativeCodeMapper& mapper, SuffixTree* tree);
|
||||||
|
|
||||||
NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block);
|
NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block);
|
||||||
NativeCodeBasicBlock* AllocateBlock(void);
|
NativeCodeBasicBlock* AllocateBlock(void);
|
||||||
|
|
||||||
|
@ -911,6 +936,8 @@ public:
|
||||||
Linker* mLinker;
|
Linker* mLinker;
|
||||||
LinkerSection* mRuntimeSection;
|
LinkerSection* mRuntimeSection;
|
||||||
|
|
||||||
|
ExpandingArray<NativeCodeProcedure*> mProcedures;
|
||||||
|
|
||||||
ExpandingArray<Runtime> mRuntime;
|
ExpandingArray<Runtime> mRuntime;
|
||||||
ExpandingArray<MulTable> mMulTables;
|
ExpandingArray<MulTable> mMulTables;
|
||||||
ExpandingArray<FloatTable> mFloatTables;
|
ExpandingArray<FloatTable> mFloatTables;
|
||||||
|
@ -929,6 +956,8 @@ public:
|
||||||
|
|
||||||
FunctionCall* mFunctionCalls;
|
FunctionCall* mFunctionCalls;
|
||||||
|
|
||||||
|
void OutlineFunctions(void);
|
||||||
|
|
||||||
void RegisterFunctionCall(NativeCodeBasicBlock* block, int at);
|
void RegisterFunctionCall(NativeCodeBasicBlock* block, int at);
|
||||||
void BuildFunctionProxies(void);
|
void BuildFunctionProxies(void);
|
||||||
bool MergeFunctionCall(NativeCodeBasicBlock* block, int at);
|
bool MergeFunctionCall(NativeCodeBasicBlock* block, int at);
|
||||||
|
|
|
@ -0,0 +1,319 @@
|
||||||
|
#include "NativeCodeOutliner.h"
|
||||||
|
|
||||||
|
|
||||||
|
NativeCodeMapper::NativeCodeMapper(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
mHash[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeCodeMapper::~NativeCodeMapper(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
{
|
||||||
|
InsNode* n = mHash[i];
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
InsNode* m = n;
|
||||||
|
n = n->mNext;
|
||||||
|
delete m;
|
||||||
|
}
|
||||||
|
mHash[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeCodeMapper::Reset(void)
|
||||||
|
{
|
||||||
|
mBlocks.SetSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NativeCodeMapper::MapBasicBlock(NativeCodeBasicBlock* block)
|
||||||
|
{
|
||||||
|
mBlocks.Push(block);
|
||||||
|
return -mBlocks.Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int NativeCodeMapper::MapInstruction(const NativeCodeInstruction& ins, LinkerSection* ls)
|
||||||
|
{
|
||||||
|
int hash = ins.CodeHash() % HashSize;
|
||||||
|
InsNode* n = mHash[hash];
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
if (mIns[n->mIndex].CodeSame(ins) && n->mSection == ls)
|
||||||
|
return n->mIndex;
|
||||||
|
n = n->mNext;
|
||||||
|
}
|
||||||
|
n = new InsNode();
|
||||||
|
n->mIndex = mIns.Size();
|
||||||
|
n->mSection = ls;
|
||||||
|
mIns.Push(ins);
|
||||||
|
n->mNext = mHash[hash];
|
||||||
|
mHash[hash] = n;
|
||||||
|
return n->mIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
SuffixTree::SuffixTree(const int* str, int s, SuffixTree* n)
|
||||||
|
{
|
||||||
|
mSeg = str;
|
||||||
|
mSize = s;
|
||||||
|
mNext = n;
|
||||||
|
mParent = nullptr;
|
||||||
|
mFirst = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::AddParents(SuffixTree* parent)
|
||||||
|
{
|
||||||
|
mParent = parent;
|
||||||
|
SuffixTree* n = mFirst;
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
n->AddParents(this);
|
||||||
|
n = n->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::AddSuffix(const int* str, int s)
|
||||||
|
{
|
||||||
|
SuffixTree* c = mFirst;
|
||||||
|
while (c && c->mSeg[0] != str[0])
|
||||||
|
c = c->mNext;
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
int k = 1;
|
||||||
|
while (k < c->mSize && str[k] == c->mSeg[k])
|
||||||
|
k++;
|
||||||
|
if (k == c->mSize)
|
||||||
|
c->AddSuffix(str + k, s - k);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SuffixTree* t = c->mFirst;
|
||||||
|
c->mFirst = new SuffixTree(c->mSeg + k, c->mSize - k, nullptr);
|
||||||
|
c->mFirst->mFirst = t;
|
||||||
|
c->mFirst = new SuffixTree(str + k, s - k, c->mFirst);
|
||||||
|
c->mSize = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mFirst = new SuffixTree(str, s, mFirst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::AddString(const int* str)
|
||||||
|
{
|
||||||
|
int s = 0;
|
||||||
|
while(str[s] >= 0)
|
||||||
|
s++;
|
||||||
|
s++;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (str[i] >= 0)
|
||||||
|
{
|
||||||
|
AddSuffix(str + i, s - i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
AddSuffix(str + i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::CollectSuffix(NativeCodeMapper& map, int offset, ExpandingArray<SuffixSegment>& segs)
|
||||||
|
{
|
||||||
|
offset += mSize;
|
||||||
|
if (mFirst)
|
||||||
|
{
|
||||||
|
SuffixTree* t = mFirst;
|
||||||
|
while (t)
|
||||||
|
{
|
||||||
|
t->CollectSuffix(map, offset, segs);
|
||||||
|
t = t->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* block = map.mBlocks[-(mSeg[mSize - 1] + 1)];
|
||||||
|
|
||||||
|
SuffixSegment seg;
|
||||||
|
seg.mBlock = block;
|
||||||
|
seg.mStart = offset;
|
||||||
|
seg.mEnd = block->mIns.Size() + 1;
|
||||||
|
segs.Push(seg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SuffixTree::LongestMatch(NativeCodeMapper& map, int size, int isize, int& msize, SuffixTree*& mtree)
|
||||||
|
{
|
||||||
|
if (mFirst)
|
||||||
|
{
|
||||||
|
isize += mSize;
|
||||||
|
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
size += AsmInsModeSize[map.mIns[mSeg[i]].mMode];
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(size < 10000);
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
SuffixTree* t = mFirst;
|
||||||
|
while (t)
|
||||||
|
{
|
||||||
|
cnt += t->LongestMatch(map, size, isize, msize, mtree);
|
||||||
|
t = t->mNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size >= 6 && (size - 3) * (cnt - 1) > msize)
|
||||||
|
{
|
||||||
|
// Second run to cross check for overlaps
|
||||||
|
ExpandingArray<SuffixSegment> segs;
|
||||||
|
SuffixTree* t = mFirst;
|
||||||
|
while (t)
|
||||||
|
{
|
||||||
|
t->CollectSuffix(map, 0, segs);
|
||||||
|
t = t->mNext;
|
||||||
|
}
|
||||||
|
segs.Sort([](const SuffixSegment& l, const SuffixSegment& r)->bool {
|
||||||
|
return l.mBlock == r.mBlock ? l.mStart < r.mStart : ptrdiff_t(l.mBlock) < ptrdiff_t(r.mBlock);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i + 1 < segs.Size(); i++)
|
||||||
|
{
|
||||||
|
if (segs[i].mBlock == segs[i + 1].mBlock && segs[i].mStart + isize > segs[i + 1].mStart)
|
||||||
|
cnt--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnt > 1 && (size - 3) * (cnt - 1) > msize)
|
||||||
|
{
|
||||||
|
msize = (size - 3) * (cnt - 1);
|
||||||
|
mtree = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::Print(FILE * file, NativeCodeMapper& map, int depth)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < depth; i++)
|
||||||
|
fprintf(file, ".");
|
||||||
|
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
fprintf(file, "[");
|
||||||
|
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
map.mIns[mSeg[i]].Disassemble(file);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* block = map.mBlocks[- (mSeg[i] + 1)];
|
||||||
|
fprintf(file, "%s,%d", block->mProc->mInterProc->mIdent->mString, block->mIndex);
|
||||||
|
}
|
||||||
|
fprintf(file, "]");
|
||||||
|
}
|
||||||
|
fprintf(file, "\n");
|
||||||
|
|
||||||
|
SuffixTree* n = mFirst;
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
n->Print(file, map, depth + 1);
|
||||||
|
n = n->mNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::ParentPrint(FILE* file, NativeCodeMapper& map)
|
||||||
|
{
|
||||||
|
if (mParent)
|
||||||
|
mParent->ParentPrint(file, map);
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
map.mIns[mSeg[i]].Disassemble(file);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* block = map.mBlocks[-(mSeg[i] + 1)];
|
||||||
|
fprintf(file, "%s,%d", block->mProc->mInterProc->mIdent->mString, block->mIndex);
|
||||||
|
}
|
||||||
|
fprintf(file, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SuffixTree::ParentCodeSize(NativeCodeMapper& map) const
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
size += AsmInsModeSize[map.mIns[mSeg[i]].mMode];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mParent)
|
||||||
|
size += mParent->ParentCodeSize(map);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::ParentCollect(NativeCodeMapper& map, NativeCodeBasicBlock* block)
|
||||||
|
{
|
||||||
|
if (mParent)
|
||||||
|
mParent->ParentCollect(map, block);
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
block->mIns.Push(map.mIns[mSeg[i]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::ReplaceCalls(NativeCodeMapper& map, ExpandingArray<SuffixSegment>& segs)
|
||||||
|
{
|
||||||
|
SuffixTree* n = mFirst;
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
n->ChildReplaceCalls(map, this, 0, segs);
|
||||||
|
n = n->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::ChildReplaceCalls(NativeCodeMapper& map, SuffixTree* tree, int offset, ExpandingArray<SuffixSegment>& segs)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
offset ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFirst)
|
||||||
|
{
|
||||||
|
SuffixTree* n = mFirst;
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
n->ChildReplaceCalls(map, tree, offset, segs);
|
||||||
|
n = n->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* block = map.mBlocks[-(mSeg[mSize - 1] + 1)];
|
||||||
|
tree->ParentReplaceCalls(map, block, offset, 0, segs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::ParentReplaceCalls(NativeCodeMapper& map, NativeCodeBasicBlock* block, int offset, int size, ExpandingArray<SuffixSegment>& segs)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
size ++;
|
||||||
|
}
|
||||||
|
if (mParent)
|
||||||
|
mParent->ParentReplaceCalls(map, block, offset, size, segs);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int at = block->mIns.Size() - offset - size;
|
||||||
|
|
||||||
|
SuffixSegment seg;
|
||||||
|
seg.mBlock = block;
|
||||||
|
seg.mStart = at;
|
||||||
|
seg.mEnd = at + size;
|
||||||
|
segs.Push(seg);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "NativeCodeGenerator.h"
|
||||||
|
#include "Array.h"
|
||||||
|
|
||||||
|
class NativeCodeMapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NativeCodeMapper(void);
|
||||||
|
~NativeCodeMapper(void);
|
||||||
|
|
||||||
|
void Reset(void);
|
||||||
|
|
||||||
|
int MapInstruction(const NativeCodeInstruction& ins, LinkerSection * ls);
|
||||||
|
int MapBasicBlock(NativeCodeBasicBlock* block);
|
||||||
|
|
||||||
|
ExpandingArray<NativeCodeInstruction> mIns;
|
||||||
|
ExpandingArray<NativeCodeBasicBlock*> mBlocks;
|
||||||
|
protected:
|
||||||
|
static const int HashSize = 256;
|
||||||
|
|
||||||
|
struct InsNode
|
||||||
|
{
|
||||||
|
int mIndex;
|
||||||
|
LinkerSection * mSection;
|
||||||
|
InsNode* mNext;
|
||||||
|
};
|
||||||
|
|
||||||
|
InsNode * mHash[HashSize];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SuffixSegment
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock * mBlock;
|
||||||
|
int mStart, mEnd;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SuffixTree
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const int * mSeg;
|
||||||
|
int mSize;
|
||||||
|
|
||||||
|
SuffixTree* mNext, * mParent, * mFirst;
|
||||||
|
|
||||||
|
SuffixTree(const int* str, int s, SuffixTree* n);
|
||||||
|
void AddParents(SuffixTree* parent);
|
||||||
|
|
||||||
|
void AddSuffix(const int* str, int s);
|
||||||
|
void AddString(const int* str);
|
||||||
|
|
||||||
|
void Print(FILE* file, NativeCodeMapper & map, int depth);
|
||||||
|
void ParentPrint(FILE* file, NativeCodeMapper& map);
|
||||||
|
int LongestMatch(NativeCodeMapper& map, int size, int isize, int & msize, SuffixTree *& mtree);
|
||||||
|
void CollectSuffix(NativeCodeMapper& map, int offset, ExpandingArray<SuffixSegment>& segs);
|
||||||
|
int ParentCodeSize(NativeCodeMapper& map) const;
|
||||||
|
void ParentCollect(NativeCodeMapper& map, NativeCodeBasicBlock * block);
|
||||||
|
void ReplaceCalls(NativeCodeMapper& map, ExpandingArray<SuffixSegment> & segs);
|
||||||
|
void ChildReplaceCalls(NativeCodeMapper& map, SuffixTree * tree, int offset, ExpandingArray<SuffixSegment>& segs);
|
||||||
|
void ParentReplaceCalls(NativeCodeMapper& map, NativeCodeBasicBlock* block, int offset, int size, ExpandingArray<SuffixSegment>& segs);
|
||||||
|
|
||||||
|
};
|
|
@ -13478,6 +13478,10 @@ void Parser::ParsePragma(void)
|
||||||
mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS;
|
mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS;
|
||||||
else if (ConsumeIdentIf("noconstparams"))
|
else if (ConsumeIdentIf("noconstparams"))
|
||||||
mCompilerOptions &= ~COPT_OPTIMIZE_CONST_PARAMS;
|
mCompilerOptions &= ~COPT_OPTIMIZE_CONST_PARAMS;
|
||||||
|
else if (ConsumeIdentIf("outline"))
|
||||||
|
mCompilerOptions |= COPT_OPTIMIZE_OUTLINE;
|
||||||
|
else if (ConsumeIdentIf("nooutline"))
|
||||||
|
mCompilerOptions &= ~COPT_OPTIMIZE_OUTLINE;
|
||||||
else
|
else
|
||||||
mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid option");
|
mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid option");
|
||||||
|
|
||||||
|
|
|
@ -261,6 +261,8 @@ int main2(int argc, const char** argv)
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL;
|
||||||
else if (arg[2] == 'm' && !arg[3])
|
else if (arg[2] == 'm' && !arg[3])
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_MERGE_CALLS;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_MERGE_CALLS;
|
||||||
|
else if (arg[2] == 'o' && !arg[3])
|
||||||
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_OUTLINE;
|
||||||
else
|
else
|
||||||
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid command line argument", arg);
|
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid command line argument", arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,6 +189,7 @@
|
||||||
<ClCompile Include="Linker.cpp" />
|
<ClCompile Include="Linker.cpp" />
|
||||||
<ClCompile Include="MachineTypes.cpp" />
|
<ClCompile Include="MachineTypes.cpp" />
|
||||||
<ClCompile Include="NativeCodeGenerator.cpp" />
|
<ClCompile Include="NativeCodeGenerator.cpp" />
|
||||||
|
<ClCompile Include="NativeCodeOutliner.cpp" />
|
||||||
<ClCompile Include="NumberSet.cpp" />
|
<ClCompile Include="NumberSet.cpp" />
|
||||||
<ClCompile Include="oscar64.cpp" />
|
<ClCompile Include="oscar64.cpp" />
|
||||||
<ClCompile Include="Parser.cpp" />
|
<ClCompile Include="Parser.cpp" />
|
||||||
|
@ -218,6 +219,7 @@
|
||||||
<ClInclude Include="Linker.h" />
|
<ClInclude Include="Linker.h" />
|
||||||
<ClInclude Include="MachineTypes.h" />
|
<ClInclude Include="MachineTypes.h" />
|
||||||
<ClInclude Include="NativeCodeGenerator.h" />
|
<ClInclude Include="NativeCodeGenerator.h" />
|
||||||
|
<ClInclude Include="NativeCodeOutliner.h" />
|
||||||
<ClInclude Include="NumberSet.h" />
|
<ClInclude Include="NumberSet.h" />
|
||||||
<ClInclude Include="Parser.h" />
|
<ClInclude Include="Parser.h" />
|
||||||
<ClInclude Include="Preprocessor.h" />
|
<ClInclude Include="Preprocessor.h" />
|
||||||
|
|
|
@ -87,6 +87,9 @@
|
||||||
<ClCompile Include="Compression.cpp">
|
<ClCompile Include="Compression.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="NativeCodeOutliner.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Array.h">
|
<ClInclude Include="Array.h">
|
||||||
|
@ -170,6 +173,9 @@
|
||||||
<ClInclude Include="Compression.h">
|
<ClInclude Include="Compression.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="NativeCodeOutliner.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="oscar64.rc">
|
<ResourceCompile Include="oscar64.rc">
|
||||||
|
|
Loading…
Reference in New Issue