First shot native code generator

Implements basic load, store compare and add/sub/shift for native compiled functions
This commit is contained in:
drmortalwombat 2021-09-07 22:35:11 +02:00
parent 69a44e90e3
commit 056df56eef
10 changed files with 1589 additions and 185 deletions

View File

@ -405,7 +405,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
ByteCodeRelocation rl; ByteCodeRelocation rl;
rl.mAddr = block->mCode.Size(); rl.mAddr = block->mCode.Size();
rl.mFunction = false; rl.mFunction = mFunction;
rl.mLower = true; rl.mLower = true;
rl.mUpper = true; rl.mUpper = true;
rl.mIndex = mVIndex; rl.mIndex = mVIndex;
@ -1481,6 +1481,7 @@ void ByteCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInst
ByteCodeInstruction bins(BC_JSR); ByteCodeInstruction bins(BC_JSR);
bins.mRelocate = true; bins.mRelocate = true;
bins.mVIndex = ins.mVarIndex; bins.mVIndex = ins.mVarIndex;
bins.mFunction = ins.mMemory == IM_PROCEDURE;
mIns.Push(bins); mIns.Push(bins);
} }
} }
@ -3394,14 +3395,25 @@ void ByteCodeGenerator::WriteAsmFile(FILE* file)
{ {
for (int i = 0; i < mGlobalAddr.Size(); i++) for (int i = 0; i < mGlobalAddr.Size(); i++)
{ {
if (mGlobalAddr[i].mAssembler) WriteAsmFile(file, mGlobalAddr[i]);
}
for (int i = 0; i < mProcedureAddr.Size(); i++)
{
WriteAsmFile(file, mProcedureAddr[i]);
}
}
void ByteCodeGenerator::WriteAsmFile(FILE * file, Address & addr)
{
if (addr.mAssembler)
{ {
fprintf(file, "--------------------------------------------------------------------\n"); fprintf(file, "--------------------------------------------------------------------\n");
if (mGlobalAddr[i].mIdent) if (addr.mIdent)
fprintf(file, "%s:\n", mGlobalAddr[i].mIdent->mString); fprintf(file, "%s:\n", addr.mIdent->mString);
int ip = mGlobalAddr[i].mAddress; int ip = addr.mAddress;
while (ip < mGlobalAddr[i].mAddress + mGlobalAddr[i].mSize) while (ip < addr.mAddress + addr.mSize)
{ {
int iip = ip; int iip = ip;
uint8 opcode = mMemory[ip++]; uint8 opcode = mMemory[ip++];
@ -3411,51 +3423,51 @@ void ByteCodeGenerator::WriteAsmFile(FILE* file)
switch (d.mMode) switch (d.mMode)
{ {
case ASMIM_IMPLIED: case ASMIM_IMPLIED:
fprintf(file, "%04x : %04x %02x __ __ %s\n", iip, ip, mMemory[ip], AsmInstructionNames[d.mType]); fprintf(file, "%04x : %02x __ __ %s\n", iip, mMemory[ip], AsmInstructionNames[d.mType]);
break; break;
case ASMIM_IMMEDIATE: case ASMIM_IMMEDIATE:
addr = mMemory[ip++]; addr = mMemory[ip++];
fprintf(file, "%04x : %04x %02x %02x __ %s #$%02x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x __ %s #$%02x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
break; break;
case ASMIM_ZERO_PAGE: case ASMIM_ZERO_PAGE:
addr = mMemory[ip++]; addr = mMemory[ip++];
fprintf(file, "%04x : %04x %02x %02x __ %s $%02x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x __ %s $%02x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
break; break;
case ASMIM_ZERO_PAGE_X: case ASMIM_ZERO_PAGE_X:
addr = mMemory[ip++]; addr = mMemory[ip++];
fprintf(file, "%04x : %04x %02x %02x __ %s $%02x,x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x __ %s $%02x,x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
break; break;
case ASMIM_ZERO_PAGE_Y: case ASMIM_ZERO_PAGE_Y:
addr = mMemory[ip++]; addr = mMemory[ip++];
fprintf(file, "%04x : %04x %02x %02x __ %s $%02x,y\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x __ %s $%02x,y\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
break; break;
case ASMIM_ABSOLUTE: case ASMIM_ABSOLUTE:
addr = mMemory[ip] + 256 * mMemory[ip + 1]; addr = mMemory[ip] + 256 * mMemory[ip + 1];
fprintf(file, "%04x : %04x %02x %02x %02x %s $%04x\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x %02x %s $%04x\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
ip += 2; ip += 2;
break; break;
case ASMIM_ABSOLUTE_X: case ASMIM_ABSOLUTE_X:
addr = mMemory[ip] + 256 * mMemory[ip + 1]; addr = mMemory[ip] + 256 * mMemory[ip + 1];
fprintf(file, "%04x : %04x %02x %02x %02x %s $%04x,x\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x %02x %s $%04x,x\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
ip += 2; ip += 2;
break; break;
case ASMIM_ABSOLUTE_Y: case ASMIM_ABSOLUTE_Y:
addr = mMemory[ip] + 256 * mMemory[ip + 1]; addr = mMemory[ip] + 256 * mMemory[ip + 1];
fprintf(file, "%04x : %04x %02x %02x %02x %s $%04x,y\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x %02x %s $%04x,y\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
ip += 2; ip += 2;
break; break;
case ASMIM_INDIRECT: case ASMIM_INDIRECT:
addr = mMemory[ip] + 256 * mMemory[ip + 1]; addr = mMemory[ip] + 256 * mMemory[ip + 1];
ip += 2; ip += 2;
fprintf(file, "%04x : %04x %02x %02x %02x %s ($%04x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x %02x %s ($%04x)\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
break; break;
case ASMIM_INDIRECT_X: case ASMIM_INDIRECT_X:
addr = mMemory[ip++]; addr = mMemory[ip++];
fprintf(file, "%04x : %04x %02x %02x __ %s ($%02x,x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x __ %s ($%02x,x)\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
break; break;
case ASMIM_INDIRECT_Y: case ASMIM_INDIRECT_Y:
addr = mMemory[ip++]; addr = mMemory[ip++];
fprintf(file, "%04x : %04x %02x %02x __ %s ($%02x),y\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x __ %s ($%02x),y\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
break; break;
case ASMIM_RELATIVE: case ASMIM_RELATIVE:
addr = mMemory[ip++]; addr = mMemory[ip++];
@ -3463,13 +3475,12 @@ void ByteCodeGenerator::WriteAsmFile(FILE* file)
addr = addr + ip - 256; addr = addr + ip - 256;
else else
addr = addr + ip; addr = addr + ip;
fprintf(file, "%04x : %04x %02x %02x __ %s $%02x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); fprintf(file, "%04x : %02x %02x __ %s $%02x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
break; break;
} }
} }
} }
} }
}
bool ByteCodeGenerator::WriteMapFile(const char* filename) bool ByteCodeGenerator::WriteMapFile(const char* filename)
{ {

View File

@ -253,21 +253,6 @@ public:
ByteCodeGenerator(void); ByteCodeGenerator(void);
~ByteCodeGenerator(void); ~ByteCodeGenerator(void);
void WriteBasicHeader(void);
void WriteByteCodeHeader(void);
void SetBasicEntry(int index);
bool WritePRGFile(const char* filename);
bool WriteMapFile(const char* filename);
void WriteAsmFile(FILE * file);
void ResolveRelocations(void);
int AddGlobal(int index, const Ident* ident, int size, const uint8* data, bool assembler);
void AddAddress(int index, bool function, int address, int size, const Ident * ident, bool assembler);
struct Address struct Address
{ {
int mIndex, mAddress, mSize; int mIndex, mAddress, mSize;
@ -282,4 +267,22 @@ public:
uint8 mMemory[0x10000]; uint8 mMemory[0x10000];
int mProgEnd, mProgStart, mProgEntry; int mProgEnd, mProgStart, mProgEntry;
void WriteBasicHeader(void);
void WriteByteCodeHeader(void);
void SetBasicEntry(int index);
bool WritePRGFile(const char* filename);
bool WriteMapFile(const char* filename);
void WriteAsmFile(FILE * file);
void WriteAsmFile(FILE* file, Address & addr);
void ResolveRelocations(void);
int AddGlobal(int index, const Ident* ident, int size, const uint8* data, bool assembler);
void AddAddress(int index, bool function, int address, int size, const Ident * ident, bool assembler);
}; };

View File

@ -4,6 +4,7 @@
#include "InterCodeGenerator.h" #include "InterCodeGenerator.h"
#include "InterCode.h" #include "InterCode.h"
#include "ByteCodeGenerator.h" #include "ByteCodeGenerator.h"
#include "NativeCodeGenerator.h"
#include "Emulator.h" #include "Emulator.h"
#include <stdio.h> #include <stdio.h>
@ -85,15 +86,25 @@ bool Compiler::GenerateCode(void)
for (int i = 0; i < mInterCodeModule->mProcedures.Size(); i++) for (int i = 0; i < mInterCodeModule->mProcedures.Size(); i++)
{ {
ByteCodeProcedure* bgproc = new ByteCodeProcedure(); InterCodeProcedure* proc = mInterCodeModule->mProcedures[i];
mInterCodeModule->mProcedures[i]->ReduceTemporaries(); proc->ReduceTemporaries();
#if _DEBUG #if _DEBUG
mInterCodeModule->mProcedures[i]->Disassemble("final"); proc->Disassemble("final");
#endif #endif
bgproc->Compile(mByteCodeGenerator, mInterCodeModule->mProcedures[i]);
if (proc->mNativeProcedure)
{
NativeCodeProcedure* ncproc = new NativeCodeProcedure();
ncproc->Compile(mByteCodeGenerator, proc);
}
else
{
ByteCodeProcedure* bgproc = new ByteCodeProcedure();
bgproc->Compile(mByteCodeGenerator, proc);
mByteCodeFunctions.Push(bgproc); mByteCodeFunctions.Push(bgproc);
#if _DEBUG #if _DEBUG
@ -107,6 +118,7 @@ bool Compiler::GenerateCode(void)
} }
#endif #endif
} }
}
for (int i = 0; i < 128; i++) for (int i = 0; i < 128; i++)
{ {

View File

@ -52,6 +52,7 @@ static const uint32 DTF_STATIC = 0x00000020;
static const uint32 DTF_CONST = 0x00000040; static const uint32 DTF_CONST = 0x00000040;
static const uint32 DTF_VOLATILE = 0x00000080; static const uint32 DTF_VOLATILE = 0x00000080;
static const uint32 DTF_EXTERN = 0x00000100; static const uint32 DTF_EXTERN = 0x00000100;
static const uint32 DTF_NATIVE = 0x00000200;
class Declaration; class Declaration;

View File

@ -2554,9 +2554,12 @@ void InterCodeBasicBlock::MapVariables(GrowingVariableArray& globalVars, Growing
switch (mInstructions[i].mCode) switch (mInstructions[i].mCode)
{ {
case IC_CONSTANT:
if (mInstructions[i].mTType != IT_POINTER)
break;
case IC_STORE: case IC_STORE:
case IC_LOAD: case IC_LOAD:
case IC_CONSTANT:
case IC_JSR: case IC_JSR:
if (mInstructions[i].mMemory == IM_GLOBAL) if (mInstructions[i].mMemory == IM_GLOBAL)
{ {
@ -2619,7 +2622,7 @@ bool InterCodeBasicBlock::IsLeafProcedure(void)
mVisited = true; mVisited = true;
for (i = 0; i < mInstructions.Size(); i++) for (i = 0; i < mInstructions.Size(); i++)
if (mInstructions[i].mCode == IC_CALL) if (mInstructions[i].mCode == IC_CALL || mInstructions[i].mCode == IC_JSR)
return false; return false;
if (mTrueJump && !mTrueJump->IsLeafProcedure()) if (mTrueJump && !mTrueJump->IsLeafProcedure())
@ -2631,6 +2634,91 @@ bool InterCodeBasicBlock::IsLeafProcedure(void)
return true; return true;
} }
void InterCodeBasicBlock::PeepholeOptimization(void)
{
int i;
if (!mVisited)
{
mVisited = true;
bool changed;
do
{
int j = 0;
for (i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i].mCode != IC_NONE)
{
mInstructions[j++] = mInstructions[i];
}
}
mInstructions.SetSize(j);
changed = false;
for (i = 0; i < mInstructions.Size(); i++)
{
if (i + 2 < mInstructions.Size())
{
if (mInstructions[i + 0].mTTemp >= 0 &&
mInstructions[i + 1].mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1].mSTemp[0] == mInstructions[i].mTTemp &&
(mInstructions[i + 2].mCode == IC_RELATIONAL_OPERATOR || mInstructions[i + 2].mCode == IC_BINARY_OPERATOR) && mInstructions[i + 2].mSTemp[0] == mInstructions[i].mTTemp && mInstructions[i + 2].mSFinal[0])
{
mInstructions[i + 0].mTTemp = mInstructions[i + 1].mTTemp;
mInstructions[i + 1].mCode = IC_NONE;
mInstructions[i + 2].mSTemp[0] = mInstructions[i + 1].mTTemp;
mInstructions[i + 2].mSFinal[0] = false;
changed = true;
}
else if (mInstructions[i + 0].mTTemp >= 0 &&
mInstructions[i + 1].mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1].mSTemp[0] == mInstructions[i].mTTemp &&
(mInstructions[i + 2].mCode == IC_RELATIONAL_OPERATOR || mInstructions[i + 2].mCode == IC_BINARY_OPERATOR) && mInstructions[i + 2].mSTemp[1] == mInstructions[i].mTTemp && mInstructions[i + 2].mSFinal[1])
{
mInstructions[i + 0].mTTemp = mInstructions[i + 1].mTTemp;
mInstructions[i + 1].mCode = IC_NONE;
mInstructions[i + 2].mSTemp[1] = mInstructions[i + 1].mTTemp;
mInstructions[i + 2].mSFinal[1] = false;
changed = true;
}
// Postincrement artifact
if (mInstructions[i + 0].mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1].mCode == IC_BINARY_OPERATOR &&
mInstructions[i + 1].mSTemp[0] < 0 &&
mInstructions[i + 0].mSTemp[0] == mInstructions[i + 1].mSTemp[1] &&
mInstructions[i + 0].mSTemp[0] == mInstructions[i + 1].mTTemp)
{
InterInstruction ins = mInstructions[i + 1];
int ttemp = mInstructions[i + 1].mTTemp;
int k = i + 1;
while (k + 2 < mInstructions.Size() &&
mInstructions[k + 1].mSTemp[0] != ttemp &&
mInstructions[k + 1].mSTemp[1] != ttemp &&
mInstructions[k + 1].mSTemp[2] != ttemp &&
mInstructions[k + 1].mTTemp != ttemp)
{
mInstructions[k] = mInstructions[k + 1];
k++;
}
if (k > i + 1)
{
mInstructions[k] = ins;
changed = true;
}
}
}
}
} while (changed);
if (mTrueJump) mTrueJump->PeepholeOptimization();
if (mFalseJump) mFalseJump->PeepholeOptimization();
}
}
void InterCodeBasicBlock::CollectVariables(GrowingVariableArray& globalVars, GrowingVariableArray& localVars) void InterCodeBasicBlock::CollectVariables(GrowingVariableArray& globalVars, GrowingVariableArray& localVars)
{ {
int i; int i;
@ -2783,7 +2871,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l
: mTemporaries(IT_NONE), mBlocks(nullptr), mLocation(location), mTempOffset(-1), : mTemporaries(IT_NONE), mBlocks(nullptr), mLocation(location), mTempOffset(-1),
mRenameTable(-1), mRenameUnionTable(-1), mGlobalRenameTable(-1), mRenameTable(-1), mRenameUnionTable(-1), mGlobalRenameTable(-1),
mValueForwardingTable(NULL), mLocalVars(InterVariable()), mModule(mod), mValueForwardingTable(NULL), mLocalVars(InterVariable()), mModule(mod),
mIdent(ident) mIdent(ident), mNativeProcedure(false), mLeafProcedure(false)
{ {
mID = mModule->mProcedures.Size(); mID = mModule->mProcedures.Size();
mModule->mProcedures.Push(this); mModule->mProcedures.Push(this);
@ -2964,6 +3052,27 @@ void InterCodeProcedure::TempForwarding(void)
DisassembleDebug("temp forwarding"); DisassembleDebug("temp forwarding");
} }
void InterCodeProcedure::RemoveUnusedInstructions(void)
{
int numTemps = mTemporaries.Size();
do {
ResetVisited();
mBlocks[0]->BuildLocalTempSets(numTemps, numFixedTemporaries);
ResetVisited();
mBlocks[0]->BuildGlobalProvidedTempSet(NumberSet(numTemps));
NumberSet totalRequired2(numTemps);
do {
ResetVisited();
} while (mBlocks[0]->BuildGlobalRequiredTempSet(totalRequired2));
ResetVisited();
} while (mBlocks[0]->RemoveUnusedResultInstructions(numFixedTemporaries));
}
void InterCodeProcedure::Close(void) void InterCodeProcedure::Close(void)
{ {
int i, j, k, start; int i, j, k, start;
@ -3139,25 +3248,18 @@ void InterCodeProcedure::Close(void)
// Now remove unused instructions // Now remove unused instructions
// //
do { RemoveUnusedInstructions();
ResetVisited();
mBlocks[0]->BuildLocalTempSets(numTemps, numFixedTemporaries);
ResetVisited();
mBlocks[0]->BuildGlobalProvidedTempSet(NumberSet(numTemps));
NumberSet totalRequired2(numTemps);
do {
ResetVisited();
} while (mBlocks[0]->BuildGlobalRequiredTempSet(totalRequired2));
ResetVisited();
} while (mBlocks[0]->RemoveUnusedResultInstructions(numFixedTemporaries));
DisassembleDebug("removed unused instructions 2"); DisassembleDebug("removed unused instructions 2");
ResetVisited();
mBlocks[0]->PeepholeOptimization();
TempForwarding();
RemoveUnusedInstructions();
DisassembleDebug("Peephole optimized");
FastNumberSet activeSet(numTemps); FastNumberSet activeSet(numTemps);
@ -3173,6 +3275,8 @@ void InterCodeProcedure::Close(void)
mTemporaries.SetSize(activeSet.Num()); mTemporaries.SetSize(activeSet.Num());
ResetVisited(); ResetVisited();
mBlocks[0]->ShrinkActiveTemporaries(activeSet, mTemporaries); mBlocks[0]->ShrinkActiveTemporaries(activeSet, mTemporaries);

View File

@ -253,6 +253,9 @@ public:
} }
}; };
typedef GrowingArray<InterVariable::Reference> GrowingInterVariableReferenceArray;
class InterInstruction class InterInstruction
{ {
public: public:
@ -415,6 +418,8 @@ public:
void CollectOuterFrame(int level, int& size); void CollectOuterFrame(int level, int& size);
bool IsLeafProcedure(void); bool IsLeafProcedure(void);
void PeepholeOptimization(void);
}; };
class InterCodeModule; class InterCodeModule;
@ -434,7 +439,7 @@ public:
GrowingTypeArray mTemporaries; GrowingTypeArray mTemporaries;
GrowingIntArray mTempOffset; GrowingIntArray mTempOffset;
int mTempSize, mCommonFrameSize; int mTempSize, mCommonFrameSize;
bool mLeafProcedure; bool mLeafProcedure, mNativeProcedure;
InterCodeModule * mModule; InterCodeModule * mModule;
int mID; int mID;
@ -463,6 +468,7 @@ protected:
void BuildDataFlowSets(void); void BuildDataFlowSets(void);
void RenameTemporaries(void); void RenameTemporaries(void);
void TempForwarding(void); void TempForwarding(void);
void RemoveUnusedInstructions(void);
void DisassembleDebug(const char* name); void DisassembleDebug(const char* name);
}; };

View File

@ -1397,6 +1397,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
mErrors->Error(exp->mLocation, "Not enough arguments for function call"); mErrors->Error(exp->mLocation, "Not enough arguments for function call");
InterInstruction cins; InterInstruction cins;
if (exp->mLeft->mDecValue->mFlags & DTF_NATIVE)
cins.mCode = IC_JSR;
else
cins.mCode = IC_CALL; cins.mCode = IC_CALL;
cins.mSType[0] = IT_POINTER; cins.mSType[0] = IT_POINTER;
cins.mSTemp[0] = vl.mTemp; cins.mSTemp[0] = vl.mTemp;
@ -2210,6 +2213,9 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mIdent); InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mIdent);
dec->mVarIndex = proc->mID; dec->mVarIndex = proc->mID;
if (dec->mFlags & DTF_NATIVE)
proc->mNativeProcedure = true;
InterCodeBasicBlock* entryBlock = new InterCodeBasicBlock(); InterCodeBasicBlock* entryBlock = new InterCodeBasicBlock();
proc->Append(entryBlock); proc->Append(entryBlock);

File diff suppressed because it is too large Load Diff

View File

@ -9,15 +9,15 @@ class NativeCodeBasicBlock;
class NativeCodeInstruction class NativeCodeInstruction
{ {
public: public:
NativeCodeInstruction(AsmInsType type, AsmInsMode mode); NativeCodeInstruction(AsmInsType type = ASMIT_INV, AsmInsMode mode = ASMIM_IMPLIED, int address = 0, int varIndex = -1, bool lower = true, bool upper = true);
AsmInsType mType; AsmInsType mType;
AsmInsMode mMode; AsmInsMode mMode;
int mAddress, mVarIndex; int mAddress, mVarIndex;
bool mGlobal; bool mLower, mUpper;
void Assemble(ByteCodeGenerator* generator, NativeCodeBasicBlock* block); void Assemble(NativeCodeBasicBlock* block);
}; };
class NativeCodeBasicBlock class NativeCodeBasicBlock
@ -36,21 +36,30 @@ public:
GrowingArray<ByteCodeRelocation> mRelocations; GrowingArray<ByteCodeRelocation> mRelocations;
int mOffset, mSize; int mOffset, mSize;
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled; bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame;
int PutBranch(ByteCodeGenerator* generator, AsmInsType code, int offset); int PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset);
int PutJump(NativeCodeProcedure* proc, int offset);
NativeCodeBasicBlock* BypassEmptyBlocks(void); NativeCodeBasicBlock* BypassEmptyBlocks(void);
void CalculateOffset(int& total); void CalculateOffset(int& total);
void CopyCode(ByteCodeGenerator* generator, uint8* target);
void Assemble(ByteCodeGenerator* generator); void CopyCode(NativeCodeProcedure* proc, uint8* target);
void Assemble(void);
void Compile(InterCodeProcedure* iproc, NativeCodeProcedure* proc, InterCodeBasicBlock* block); void Compile(InterCodeProcedure* iproc, NativeCodeProcedure* proc, InterCodeBasicBlock* block);
void Close(NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump, AsmInsType branch); void Close(NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump, AsmInsType branch);
void PutByte(uint8 code); void PutByte(uint8 code);
void PutWord(uint16 code); void PutWord(uint16 code);
void LoadConstant(InterCodeProcedure* proc, const InterInstruction& ins);
void StoreValue(InterCodeProcedure* proc, const InterInstruction& ins);
void LoadValue(InterCodeProcedure* proc, const InterInstruction& ins);
void LoadStoreValue(InterCodeProcedure* proc, const InterInstruction& rins, const InterInstruction& wins);
void BinaryOperator(InterCodeProcedure* proc, const InterInstruction& ins);
void UnaryOperator(InterCodeProcedure* proc, const InterInstruction& ins);
void RelationalOperator(InterCodeProcedure* proc, const InterInstruction& ins, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock * falseJump);
void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction& ins);
}; };
class NativeCodeProcedure class NativeCodeProcedure
@ -62,10 +71,14 @@ class NativeCodeProcedure
NativeCodeBasicBlock* entryBlock, * exitBlock; NativeCodeBasicBlock* entryBlock, * exitBlock;
NativeCodeBasicBlock** tblocks; NativeCodeBasicBlock** tblocks;
int mProgStart, mProgSize; int mProgStart, mProgSize, mIndex;
bool mNoFrame;
GrowingArray<ByteCodeRelocation> mRelocations;
void Compile( ByteCodeGenerator * generator, InterCodeProcedure* proc); void Compile( ByteCodeGenerator * generator, InterCodeProcedure* proc);
NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block); NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block);
NativeCodeBasicBlock* TransientBlock(void);
}; };

View File

@ -2106,6 +2106,21 @@ void Parser::ParsePragma(void)
} }
ConsumeToken(TK_CLOSE_PARENTHESIS); ConsumeToken(TK_CLOSE_PARENTHESIS);
} }
else if (!strcmp(mScanner->mTokenIdent->mString, "native"))
{
mScanner->NextToken();
ConsumeToken(TK_OPEN_PARENTHESIS);
if (mScanner->mToken == TK_IDENT)
{
Declaration* dec = mGlobals->Lookup(mScanner->mTokenIdent);
if (dec && dec->mType == DT_CONST_FUNCTION)
dec->mFlags |= DTF_NATIVE;
else
mErrors->Error(mScanner->mLocation, "Native function not found");
mScanner->NextToken();
}
ConsumeToken(TK_CLOSE_PARENTHESIS);
}
else if (!strcmp(mScanner->mTokenIdent->mString, "startup")) else if (!strcmp(mScanner->mTokenIdent->mString, "startup"))
{ {
if (mCompilationUnits->mStartup) if (mCompilationUnits->mStartup)