Fix return type coercion, region based linker

This commit is contained in:
drmortalwombat 2021-09-21 20:44:19 +02:00
parent 3f5f3ee7ea
commit eebc39e53a
14 changed files with 400 additions and 245 deletions

View File

@ -101,14 +101,14 @@ void * putstrstr(void * handle, const char * str)
struct sinfo struct sinfo
{ {
char fill; char fill;
int width, precision; char width, precision;
unsigned base; unsigned base;
bool sign, left, prefix; bool sign, left, prefix;
}; };
void nformi(const sinfo * si, char * str, int v, bool s) int nformi(const sinfo * si, char * str, int v, bool s)
{ {
char buffer[10]; char * sp = str;
unsigned int u = v; unsigned int u = v;
bool neg = false; bool neg = false;
@ -119,7 +119,7 @@ void nformi(const sinfo * si, char * str, int v, bool s)
u = -v; u = -v;
} }
int i = 0; char i = 10;
while (u > 0) while (u > 0)
{ {
int c = u % si->base; int c = u % si->base;
@ -127,49 +127,53 @@ void nformi(const sinfo * si, char * str, int v, bool s)
c += 'A' - 10; c += 'A' - 10;
else else
c += '0'; c += '0';
buffer[i++] = c; sp[--i] = c;
u /= si->base; u /= si->base;
} }
int digits = si->precision >= 0 ? si->precision : 1; int digits = si->precision != 255 ? 10 - si->precision : 9;
while (i < digits) while (i > digits)
buffer[i++] = '0'; sp[--i] = '0';
if (si->prefix && si->base == 16) if (si->prefix && si->base == 16)
{ {
buffer[i++] = 'X'; sp[--i] = 'X';
buffer[i++] = '0'; sp[--i] = '0';
} }
if (neg) if (neg)
buffer[i++] = '-'; sp[--i] = '-';
else if (si->sign) else if (si->sign)
buffer[i++] = '+'; sp[--i] = '+';
while (i < si->width) while (i > 10 - si->width)
buffer[i++] = si->fill; sp[--i] = si->fill;
while (i > 0) char j = 0;
*str++ = buffer[--i]; while (i < 10)
*str++ = 0; sp[j++] = sp[i++];
return j;
} }
void nformf(const sinfo * si, char * str, float f, char type) int nformf(const sinfo * si, char * str, float f, char type)
{ {
int d = 0; char * sp = str;
char d = 0;
if (f < 0.0) if (f < 0.0)
{ {
f = -f; f = -f;
str[d++] = '-'; sp[d++] = '-';
} }
else if (si->sign) else if (si->sign)
str[d++] = '+'; sp[d++] = '+';
int exp = 0; int exp = 0;
int fdigits = si->precision >= 0 ? si->precision : 6; char fdigits = si->precision != 255 ? si->precision : 6;
if (f != 0.0) if (f != 0.0)
{ {
@ -193,7 +197,7 @@ void nformf(const sinfo * si, char * str, float f, char type)
} }
int digits = fdigits + 1; char digits = fdigits + 1;
bool fexp = type == 'e'; bool fexp = type == 'e';
if (type == 'g') if (type == 'g')
@ -211,10 +215,10 @@ void nformf(const sinfo * si, char * str, float f, char type)
} }
digits = fdigits + exp + 1; digits = fdigits + exp + 1;
float s = 0.5; float r = 0.5;
for(int i=1; i<digits; i++) for(char i=1; i<digits; i++)
s /= 10.0; r /= 10.0;
f += s; f += r;
if (f >= 10.0) if (f >= 10.0)
{ {
f /= 10.0; f /= 10.0;
@ -223,10 +227,10 @@ void nformf(const sinfo * si, char * str, float f, char type)
} }
else else
{ {
float s = 0.5; float r = 0.5;
for(int i=0; i<fdigits; i++) for(char i=0; i<fdigits; i++)
s /= 10.0; r /= 10.0;
f += s; f += r;
if (f >= 10.0) if (f >= 10.0)
{ {
f /= 10.0; f /= 10.0;
@ -234,53 +238,55 @@ void nformf(const sinfo * si, char * str, float f, char type)
} }
} }
int pdigits = digits - fdigits; char pdigits = digits - fdigits;
if (digits > 20) if (digits > 20)
digits = 20; digits = 20;
if (pdigits == 0) if (pdigits == 0)
str[d++] = '0'; sp[d++] = '0';
for(int i=0; i<digits; i++) for(char i=0; i<digits; i++)
{ {
if (i == pdigits) if (i == pdigits)
str[d++] = '.'; sp[d++] = '.';
int c = (int)f; int c = (int)f;
f -= (float)c; f -= (float)c;
f *= 10.0; f *= 10.0;
str[d++] = c + '0'; sp[d++] = c + '0';
} }
if (fexp) if (fexp)
{ {
str[d++] = 'E'; sp[d++] = 'E';
if (exp < 0) if (exp < 0)
{ {
str[d++] = '-'; sp[d++] = '-';
exp = -exp; exp = -exp;
} }
else else
str[d++] = '+'; sp[d++] = '+';
str[d++] = exp / 10 + '0'; sp[d++] = exp / 10 + '0';
str[d++] = exp % 10 + '0'; sp[d++] = exp % 10 + '0';
} }
str[d++] = 0;
if (d < si->width) if (d < si->width)
{ {
for(int i=0; i<=d; i++) for(char i=1; i<=d; i++)
str[si->width - i] = str[d - i]; sp[si->width - i] = sp[d - i];
for(int i=0; i<si->width-d; i++) for(char i=0; i<si->width-d; i++)
str[i] = ' ' sp[i] = ' ';
} d = si->width;
} }
void * sformat(void * data, putstrfn fn, const char * fmt, int * fps) return d;
}
char * sformat(char * buff, const char * fmt, int * fps, bool print)
{ {
const char * p = fmt; const char * p = fmt;
char c, buff[21]; char c;
int bi = 0; int bi = 0;
sinfo si; sinfo si;
@ -289,16 +295,21 @@ void * sformat(void * data, putstrfn fn, const char * fmt, int * fps)
if (c == '%') if (c == '%')
{ {
if (bi) if (bi)
{
if (print)
{ {
buff[bi] = 0; buff[bi] = 0;
data = fn(data, buff); puts(buff);
}
else
buff += bi;
bi = 0; bi = 0;
} }
c = *p++; c = *p++;
si.base = 10; si.base = 10;
si.width = 1; si.width = 1;
si.precision = -1; si.precision = 255;
si.fill = ' '; si.fill = ' ';
si.sign = false; si.sign = false;
si.left = false; si.left = false;
@ -342,32 +353,35 @@ void * sformat(void * data, putstrfn fn, const char * fmt, int * fps)
if (c == 'd') if (c == 'd')
{ {
nformi(&si, buff, *fps++, true); bi = nformi(&si, buff, *fps++, true);
data = fn(data, buff);
} }
else if (c == 'u') else if (c == 'u')
{ {
nformi(&si, buff, *fps++, false); bi = nformi(&si, buff, *fps++, false);
data = fn(data, buff);
} }
else if (c == 'x') else if (c == 'x')
{ {
si.base = 16; si.base = 16;
nformi(&si, buff, *fps++, false); bi = nformi(&si, buff, *fps++, false);
data = fn(data, buff);
} }
#ifndef NOFLOAT #ifndef NOFLOAT
else if (c == 'f' || c == 'g' || c == 'e') else if (c == 'f' || c == 'g' || c == 'e')
{ {
nformf(&si, buff, *(float *)fps, c); bi = nformf(&si, buff, *(float *)fps, c);
data = fn(data, buff);
fps ++; fps ++;
fps ++; fps ++;
} }
#endif #endif
else if (c == 's') else if (c == 's')
{ {
data = fn(data, (char *)*fps++); char * sp = (char *)*fps++;
if (print)
puts(sp);
else
{
while (char c = *sp++)
*buff++ = c;
}
} }
else if (c == 'c') else if (c == 'c')
{ {
@ -381,32 +395,40 @@ void * sformat(void * data, putstrfn fn, const char * fmt, int * fps)
else else
{ {
buff[bi++] = c; buff[bi++] = c;
if (bi == 10) if (bi >= 10)
{
if (print)
{ {
buff[bi] = 0; buff[bi] = 0;
data = fn(data, buff); puts(buff);
}
else
buff += bi;
bi = 0; bi = 0;
} }
} }
} }
buff[bi] = 0;
if (bi) if (bi)
{ {
buff[bi] = 0; if (print)
data = fn(data, buff); puts(buff);
bi = 0; else
buff += bi;
} }
return data; return buff;
} }
void printf(const char * fmt, ...) void printf(const char * fmt, ...)
{ {
sformat(nullptr, putstrio, fmt, (int *)&fmt + 1); char buff[40];
sformat(buff, fmt, (int *)&fmt + 1, true);
} }
int sprintf(char * str, const char * fmt, ...) int sprintf(char * str, const char * fmt, ...)
{ {
char * d = (char *)(sformat(str, putstrstr, fmt, (int *)&fmt + 1)); char * d = sformat(str, fmt, (int *)&fmt + 1, false);
return d - str; return d - str;
} }

View File

@ -2,6 +2,7 @@
#include "Declaration.h" #include "Declaration.h"
#include "Errors.h" #include "Errors.h"
#include "Linker.h"
class CompilationUnit class CompilationUnit
{ {
@ -26,6 +27,8 @@ public:
DeclarationScope* mRuntimeScope; DeclarationScope* mRuntimeScope;
LinkerSection* mSectionCode, * mSectionData, * mSectionBSS, * mSectionHeap, * mSectionStack;
bool AddUnit(Location & location, const char* name, const char * from); bool AddUnit(Location & location, const char* name, const char * from);
CompilationUnit* PendingUnit(void); CompilationUnit* PendingUnit(void);
protected: protected:

View File

@ -19,6 +19,12 @@ Compiler::Compiler(void)
mInterCodeGenerator = new InterCodeGenerator(mErrors, mLinker); mInterCodeGenerator = new InterCodeGenerator(mErrors, mLinker);
mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker); mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker);
mInterCodeModule = new InterCodeModule(); mInterCodeModule = new InterCodeModule();
mCompilationUnits->mSectionCode = mLinker->AddSection(Ident::Unique("code"), 0);
mCompilationUnits->mSectionData = mLinker->AddSection(Ident::Unique("data"), 0);
mCompilationUnits->mSectionBSS = mLinker->AddSection(Ident::Unique("bss"), 0);
mCompilationUnits->mSectionHeap = mLinker->AddSection(Ident::Unique("heap"), 0);
mCompilationUnits->mSectionStack = mLinker->AddSection(Ident::Unique("stack"), 0);
} }
Compiler::~Compiler(void) Compiler::~Compiler(void)
@ -112,13 +118,25 @@ bool Compiler::GenerateCode(void)
return false; return false;
} }
const Ident* sectionStartup = Ident::Unique("startup"); const Ident* identStartup = Ident::Unique("startup");
const Ident* sectionBytecode = Ident::Unique("bytecode"); const Ident* identBytecode = Ident::Unique("bytecode");
const Ident* sectionCode = Ident::Unique("code"); const Ident* identMain = Ident::Unique("main");
const Ident* identCode = Ident::Unique("code");
mLinker->AddSection(sectionStartup, 0x0801, 0x00ff); LinkerRegion * regionStartup = mLinker->AddRegion(identStartup, 0x0801, 0x0900);
mLinker->AddSection(sectionBytecode, 0x0900, 0x0100); LinkerRegion * regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00);
mLinker->AddSection(sectionCode, 0x0a00, 0x8000); LinkerRegion * regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000);
LinkerSection * sectionStartup = mLinker->AddSection(identStartup, 0);
LinkerSection * sectionBytecode = mLinker->AddSection(identBytecode, 0);
regionStartup->mSections.Push(sectionStartup);
regionBytecode->mSections.Push(sectionBytecode);
regionMain->mSections.Push(mCompilationUnits->mSectionCode);
regionMain->mSections.Push(mCompilationUnits->mSectionData);
regionMain->mSections.Push(mCompilationUnits->mSectionBSS);
regionMain->mSections.Push(mCompilationUnits->mSectionHeap);
regionMain->mSections.Push(mCompilationUnits->mSectionStack);
dcrtstart->mSection = sectionStartup; dcrtstart->mSection = sectionStartup;
@ -128,14 +146,6 @@ bool Compiler::GenerateCode(void)
if (mErrors->mErrorCount != 0) if (mErrors->mErrorCount != 0)
return false; return false;
const Ident* imain = Ident::Unique("main");
Declaration* dmain = mCompilationUnits->mScope->Lookup(imain);
if (!dmain)
{
mErrors->Error(loc, EERR_OBJECT_NOT_FOUND, "main function not found");
return false;
}
// Register native runtime functions // Register native runtime functions
RegisterRuntime(loc, Ident::Unique("mul16by8")); RegisterRuntime(loc, Ident::Unique("mul16by8"));
@ -158,8 +168,6 @@ bool Compiler::GenerateCode(void)
// //
InterCodeProcedure* iproc = mInterCodeGenerator->TranslateProcedure(mInterCodeModule, dmain->mValue, dmain);
if (mErrors->mErrorCount != 0) if (mErrors->mErrorCount != 0)
return false; return false;

View File

@ -6,6 +6,7 @@
#include "Assembler.h" #include "Assembler.h"
class LinkerObject; class LinkerObject;
class LinkerSection;
enum DecType enum DecType
{ {
@ -156,7 +157,8 @@ public:
__int64 mInteger; __int64 mInteger;
double mNumber; double mNumber;
uint32 mFlags; uint32 mFlags;
const Ident * mIdent, * mSection; const Ident * mIdent;
LinkerSection * mSection;
const uint8 * mData; const uint8 * mData;
LinkerObject * mLinkerObject; LinkerObject * mLinkerObject;

View File

@ -582,7 +582,7 @@ int Emulator::Emulate(int startIP)
int accu = mMemory[BC_REG_ACCU] + 256 * mMemory[BC_REG_ACCU + 1]; int accu = mMemory[BC_REG_ACCU] + 256 * mMemory[BC_REG_ACCU + 1];
int ptr = mMemory[BC_REG_ADDR] + 256 * mMemory[BC_REG_ADDR + 1]; int ptr = mMemory[BC_REG_ADDR] + 256 * mMemory[BC_REG_ADDR + 1];
int sp = mMemory[BC_REG_STACK] + 256 * mMemory[BC_REG_STACK + 1]; int sp = mMemory[BC_REG_STACK] + 256 * mMemory[BC_REG_STACK + 1];
printf("%04x (A:%04x P:%04x S:%04x) %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n", addr, accu, ptr, sp, printf("%04x (A:%04x P:%04x S:%04x) %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x : %04x\n", addr, accu, ptr, sp,
mMemory[BC_REG_TMP + 0] + 256 * mMemory[BC_REG_TMP + 1], mMemory[BC_REG_TMP + 0] + 256 * mMemory[BC_REG_TMP + 1],
mMemory[BC_REG_TMP + 2] + 256 * mMemory[BC_REG_TMP + 3], mMemory[BC_REG_TMP + 2] + 256 * mMemory[BC_REG_TMP + 3],
mMemory[BC_REG_TMP + 4] + 256 * mMemory[BC_REG_TMP + 5], mMemory[BC_REG_TMP + 4] + 256 * mMemory[BC_REG_TMP + 5],
@ -601,7 +601,11 @@ int Emulator::Emulate(int startIP)
mMemory[BC_REG_TMP + 24] + 256 * mMemory[BC_REG_TMP + 25], mMemory[BC_REG_TMP + 24] + 256 * mMemory[BC_REG_TMP + 25],
mMemory[BC_REG_TMP + 26] + 256 * mMemory[BC_REG_TMP + 27], mMemory[BC_REG_TMP + 26] + 256 * mMemory[BC_REG_TMP + 27],
mMemory[BC_REG_TMP + 28] + 256 * mMemory[BC_REG_TMP + 29], mMemory[BC_REG_TMP + 28] + 256 * mMemory[BC_REG_TMP + 29],
mMemory[BC_REG_TMP + 30] + 256 * mMemory[BC_REG_TMP + 31] mMemory[BC_REG_TMP + 30] + 256 * mMemory[BC_REG_TMP + 31],
mMemory[0x9f9e] + 256 * mMemory[0x9f9f]
); );
} }

View File

@ -1591,6 +1591,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
else if (!procType->mBase->CanAssign(vr.mType)) else if (!procType->mBase->CanAssign(vr.mType))
mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type"); mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type");
vr = CoerceType(proc, block, vr, procType->mBase);
ins->mSType[0] = InterTypeOf(vr.mType); ins->mSType[0] = InterTypeOf(vr.mType);
ins->mSTemp[0] = vr.mTemp; ins->mSTemp[0] = vr.mTemp;
ins->mCode = IC_RETURN_VALUE; ins->mCode = IC_RETURN_VALUE;

View File

@ -3,6 +3,14 @@
#include <stdio.h> #include <stdio.h>
LinkerRegion::LinkerRegion(void)
: mSections(nullptr)
{}
LinkerSection::LinkerSection(void)
: mObjects(nullptr)
{}
void LinkerObject::AddData(const uint8* data, int size) void LinkerObject::AddData(const uint8* data, int size)
{ {
mSize = size; mSize = size;
@ -19,7 +27,7 @@ uint8* LinkerObject::AddSpace(int size)
} }
Linker::Linker(Errors* errors) Linker::Linker(Errors* errors)
: mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr) : mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr), mRegions(nullptr)
{ {
} }
@ -29,19 +37,39 @@ Linker::~Linker(void)
} }
int Linker::AddSection(const Ident* section, int start, int size)
LinkerRegion* Linker::AddRegion(const Ident* region, int start, int end)
{ {
LinkerSection* lsec = new LinkerSection; LinkerRegion* lrgn = new LinkerRegion();
lsec->mID = mSections.Size(); lrgn->mIdent = region;
lsec->mIdent = section; lrgn->mStart = start;
lsec->mStart = start; lrgn->mEnd = end;
lsec->mSize = size; lrgn->mUsed = 0;
lsec->mUsed = 0; mRegions.Push(lrgn);
mSections.Push(lsec); return lrgn;
return lsec->mID;
} }
LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, const Ident* section, LinkerObjectType type) LinkerSection* Linker::AddSection(const Ident* section, uint32 flags)
{
LinkerSection* lsec = new LinkerSection;
lsec->mIdent = section;
mSections.Push(lsec);
return lsec;
}
LinkerSection* Linker::FindSection(const Ident* section)
{
for (int i = 0; i < mSections.Size(); i++)
{
if (mSections[i]->mIdent == section)
return mSections[i];
}
return nullptr;
}
LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, LinkerSection * section, LinkerObjectType type)
{ {
LinkerObject* obj = new LinkerObject; LinkerObject* obj = new LinkerObject;
obj->mLocation = location; obj->mLocation = location;
@ -53,6 +81,8 @@ LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, c
obj->mSection = section; obj->mSection = section;
obj->mProc = nullptr; obj->mProc = nullptr;
obj->mReferenced = false; obj->mReferenced = false;
obj->mPlaced = false;
section->mObjects.Push(obj);
mObjects.Push(obj); mObjects.Push(obj);
return obj; return obj;
} }
@ -79,54 +109,49 @@ void Linker::ReferenceObject(LinkerObject* obj)
void Linker::Link(void) void Linker::Link(void)
{ {
for (int i = 0; i < mObjects.Size(); i++) if (mErrors->mErrorCount == 0)
{ {
LinkerObject* obj = mObjects[i];
if (obj->mReferenced) // Move objects into regions
for (int i = 0; i < mRegions.Size(); i++)
{ {
LinkerSection* lsec; LinkerRegion* lrgn = mRegions[i];
int j = 0; for (int j = 0; j < lrgn->mSections.Size(); j++)
while (j < mSections.Size() && !(mSections[j]->mIdent == obj->mSection && mSections[j]->mUsed + obj->mSize <= mSections[j]->mSize))
j++;
if (j < mSections.Size())
{ {
LinkerSection* lsec = mSections[j]; LinkerSection* lsec = lrgn->mSections[j];
obj->mLinkerSection = lsec; for (int k = 0; k < lsec->mObjects.Size(); k++)
obj->mAddress = lsec->mUsed; {
lsec->mUsed += obj->mSize; LinkerObject* lobj = lsec->mObjects[k];
if (lobj->mReferenced && !lobj->mPlaced && lrgn->mStart + lrgn->mUsed + lobj->mSize <= lrgn->mEnd)
{
lobj->mPlaced = true;
lobj->mAddress = lrgn->mStart + lrgn->mUsed;
lrgn->mUsed += lobj->mSize;
}
} }
else
mErrors->Error(obj->mLocation, EERR_OUT_OF_MEMORY, "Out of space in section", obj->mSection->mString);
} }
} }
if (mErrors->mErrorCount == 0)
{
mProgramStart = 0x0801; mProgramStart = 0x0801;
mProgramEnd = 0x0801; mProgramEnd = 0x0801;
int address = 0; int address = 0;
for (int i = 0; i < mSections.Size(); i++) for (int i = 0; i < mRegions.Size(); i++)
{ {
LinkerSection* lsec = mSections[i]; LinkerRegion* lrgn = mRegions[i];
if (lsec->mStart == 0) address = lrgn->mStart + lrgn->mUsed;
lsec->mStart = address;
address = lsec->mStart + lsec->mUsed;
if (lsec->mUsed > 0) if (lrgn->mUsed && address > mProgramEnd)
{
if (address > mProgramEnd)
mProgramEnd = address; mProgramEnd = address;
} }
}
for (int i = 0; i < mObjects.Size(); i++) for (int i = 0; i < mObjects.Size(); i++)
{ {
LinkerObject* obj = mObjects[i]; LinkerObject* obj = mObjects[i];
if (obj->mReferenced) if (obj->mReferenced)
{ {
obj->mAddress += obj->mLinkerSection->mStart;
memcpy(mMemory + obj->mAddress, obj->mData, obj->mSize); memcpy(mMemory + obj->mAddress, obj->mData, obj->mSize);
} }
} }
@ -194,9 +219,9 @@ bool Linker::WriteMapFile(const char* filename)
if (obj->mReferenced) if (obj->mReferenced)
{ {
if (obj->mIdent) if (obj->mIdent)
fprintf(file, "%04x - %04x : %s, %s:%s\n", obj->mAddress, obj->mAddress + obj->mSize, obj->mIdent->mString, LinkerObjectTypeNames[obj->mType], obj->mSection->mString); fprintf(file, "%04x - %04x : %s, %s:%s\n", obj->mAddress, obj->mAddress + obj->mSize, obj->mIdent->mString, LinkerObjectTypeNames[obj->mType], obj->mSection->mIdent->mString);
else else
fprintf(file, "%04x - %04x : *, %s:%s\n", obj->mAddress, obj->mAddress + obj->mSize, LinkerObjectTypeNames[obj->mType], obj->mSection->mString); fprintf(file, "%04x - %04x : *, %s:%s\n", obj->mAddress, obj->mAddress + obj->mSize, LinkerObjectTypeNames[obj->mType], obj->mSection->mIdent->mString);
} }
} }

View File

@ -22,6 +22,19 @@ enum LinkerObjectType
}; };
class LinkerObject; class LinkerObject;
class LinkerSection;
class LinkerRegion
{
public:
const Ident* mIdent;
int mStart, mEnd, mUsed;
GrowingArray<LinkerSection*> mSections;
LinkerRegion(void);
};
class LinkerReference class LinkerReference
{ {
@ -35,23 +48,25 @@ class LinkerSection
{ {
public: public:
const Ident* mIdent; const Ident* mIdent;
int mID;
int mStart, mSize, mUsed; GrowingArray <LinkerObject*> mObjects;
LinkerSection(void);
}; };
class LinkerObject class LinkerObject
{ {
public: public:
Location mLocation; Location mLocation;
const Ident* mIdent, * mSection; const Ident* mIdent;
LinkerObjectType mType; LinkerObjectType mType;
int mID; int mID;
int mAddress; int mAddress;
int mSize; int mSize;
LinkerSection* mLinkerSection; LinkerSection* mSection;
uint8* mData; uint8* mData;
InterCodeProcedure* mProc; InterCodeProcedure* mProc;
bool mReferenced; bool mReferenced, mPlaced;
void AddData(const uint8* data, int size); void AddData(const uint8* data, int size);
uint8* AddSpace(int size); uint8* AddSpace(int size);
@ -63,9 +78,11 @@ public:
Linker(Errors * errors); Linker(Errors * errors);
~Linker(void); ~Linker(void);
int AddSection(const Ident* section, int start, int size); LinkerRegion * AddRegion(const Ident* region, int start, int end);
LinkerSection * AddSection(const Ident* section, uint32 flags);
LinkerSection* FindSection(const Ident* section);
LinkerObject * AddObject(const Location & location, const Ident* ident, const Ident* section, LinkerObjectType type); LinkerObject * AddObject(const Location & location, const Ident* ident, LinkerSection * section, LinkerObjectType type);
void AddReference(const LinkerReference& ref); void AddReference(const LinkerReference& ref);
@ -74,6 +91,7 @@ public:
bool WriteAsmFile(const char* filename); bool WriteAsmFile(const char* filename);
GrowingArray<LinkerReference*> mReferences; GrowingArray<LinkerReference*> mReferences;
GrowingArray<LinkerRegion*> mRegions;
GrowingArray<LinkerSection*> mSections; GrowingArray<LinkerSection*> mSections;
GrowingArray<LinkerObject*> mObjects; GrowingArray<LinkerObject*> mObjects;

View File

@ -435,6 +435,15 @@ bool NativeCodeInstruction::LoadsAccu(void) const
return mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA || mType == ASMIT_JSR; return mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA || mType == ASMIT_JSR;
} }
bool NativeCodeInstruction::ChangesAccuAndFlag(void) const
{
return
mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA ||
mType == ASMIT_ORA || mType == ASMIT_AND || mType == ASMIT_EOR ||
mType == ASMIT_SBC || mType == ASMIT_CLC;
}
bool NativeCodeInstruction::ChangesAddress(void) const bool NativeCodeInstruction::ChangesAddress(void) const
{ {
if (mMode != ASMIM_IMPLIED) if (mMode != ASMIM_IMPLIED)
@ -516,6 +525,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
if (data.mRegs[CPU_REG_A].mImmediate && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) if (data.mRegs[CPU_REG_A].mImmediate && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
{ {
mType = ASMIT_NOP; mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
changed = true; changed = true;
} }
else else
@ -613,6 +623,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
if (data.mRegs[CPU_REG_X].mImmediate && data.mRegs[CPU_REG_X].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) if (data.mRegs[CPU_REG_X].mImmediate && data.mRegs[CPU_REG_X].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
{ {
mType = ASMIT_NOP; mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
changed = true; changed = true;
} }
else else
@ -643,6 +654,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
if (data.mRegs[CPU_REG_Y].mImmediate && data.mRegs[CPU_REG_Y].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) if (data.mRegs[CPU_REG_Y].mImmediate && data.mRegs[CPU_REG_Y].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
{ {
mType = ASMIT_NOP; mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
changed = true; changed = true;
} }
else else
@ -718,6 +730,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
if (data.mRegs[CPU_REG_A].mZeroPage && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) if (data.mRegs[CPU_REG_A].mZeroPage && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
{ {
mType = ASMIT_NOP; mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
changed = true; changed = true;
} }
else if (data.mRegs[mAddress].mImmediate) else if (data.mRegs[mAddress].mImmediate)
@ -733,6 +746,18 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
mAddress = data.mRegs[CPU_REG_A].mValue; mAddress = data.mRegs[CPU_REG_A].mValue;
changed = true; changed = true;
} }
else if (data.mRegs[CPU_REG_X].mZeroPage && data.mRegs[CPU_REG_X].mValue == mAddress)
{
mType = ASMIT_TXA;
mMode = ASMIM_IMPLIED;
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
}
else if (data.mRegs[CPU_REG_Y].mZeroPage && data.mRegs[CPU_REG_Y].mValue == mAddress)
{
mType = ASMIT_TYA;
mMode = ASMIM_IMPLIED;
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y];
}
else else
{ {
data.mRegs[CPU_REG_A].Reset(); data.mRegs[CPU_REG_A].Reset();
@ -753,6 +778,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
if (data.mRegs[CPU_REG_X].mZeroPage && data.mRegs[CPU_REG_X].mValue == mAddress) if (data.mRegs[CPU_REG_X].mZeroPage && data.mRegs[CPU_REG_X].mValue == mAddress)
{ {
mType = ASMIT_NOP; mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
changed = true; changed = true;
} }
else if (data.mRegs[mAddress].mImmediate) else if (data.mRegs[mAddress].mImmediate)
@ -782,6 +808,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
if (data.mRegs[CPU_REG_Y].mZeroPage && data.mRegs[CPU_REG_Y].mValue == mAddress) if (data.mRegs[CPU_REG_Y].mZeroPage && data.mRegs[CPU_REG_Y].mValue == mAddress)
{ {
mType = ASMIT_NOP; mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
changed = true; changed = true;
} }
else if (data.mRegs[mAddress].mImmediate) else if (data.mRegs[mAddress].mImmediate)
@ -2753,15 +2780,15 @@ void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, NativeCodePr
{ {
if (sins0) if (sins0)
{ {
insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg); LoadValueToReg(proc, sins0, treg, nullptr, nullptr);
insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg + 1);
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
LoadValueToReg(proc, sins0, treg, &insl, &insh);
} }
else else
{ {
@ -3807,13 +3834,15 @@ bool NativeCodeBasicBlock::RemoveUnusedResultInstructions(void)
for (i = mIns.Size() - 1; i >= 0; i--) for (i = mIns.Size() - 1; i >= 0; i--)
{ {
if (!mIns[i].IsUsedResultInstructions(requiredRegs)) if (mIns[i].mType != ASMIT_NOP && !mIns[i].IsUsedResultInstructions(requiredRegs))
{ {
if (i > 0 && mIns[i - 1].mMode == ASMIM_RELATIVE && mIns[i - 1].mAddress > 0) if (i > 0 && mIns[i - 1].mMode == ASMIM_RELATIVE && mIns[i - 1].mAddress > 0)
{ {
mIns[i - 1].mType = ASMIT_NOP; mIns[i - 1].mType = ASMIT_NOP;
mIns[i - 1].mMode = ASMIM_IMPLIED;
} }
mIns[i].mType = ASMIT_NOP; mIns[i].mType = ASMIT_NOP;
mIns[i].mMode = ASMIM_IMPLIED;
changed = true; changed = true;
} }
} }
@ -3905,6 +3934,101 @@ bool NativeCodeBasicBlock::MoveLoadStoreUp(int at)
return false; return false;
} }
bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
NativeRegisterDataSet ndata(data);
if (mNumEntries != 1)
ndata.Reset();
for (int i = 0; i < mIns.Size(); i++)
{
if (mIns[i].ValueForwarding(ndata))
changed = true;
}
if (mFalseJump)
{
switch (mBranch)
{
case ASMIT_BCS:
if (ndata.mRegs[CPU_REG_C].mImmediate)
{
mBranch = ASMIT_JMP;
if (!ndata.mRegs[CPU_REG_C].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BCC:
if (ndata.mRegs[CPU_REG_C].mImmediate)
{
mBranch = ASMIT_JMP;
if (ndata.mRegs[CPU_REG_C].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BNE:
if (ndata.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if (!ndata.mRegs[CPU_REG_Z].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BEQ:
if (ndata.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if (ndata.mRegs[CPU_REG_Z].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BPL:
if (ndata.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if ((ndata.mRegs[CPU_REG_Z].mValue & 0x80))
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BMI:
if (ndata.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if (!(ndata.mRegs[CPU_REG_Z].mValue & 0x80))
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
}
}
if (this->mTrueJump && this->mTrueJump->ValueForwarding(ndata))
changed = true;
if (this->mFalseJump && this->mFalseJump->ValueForwarding(ndata))
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::PeepHoleOptimizer(void) bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
{ {
if (!mVisited) if (!mVisited)
@ -3913,84 +4037,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
mVisited = true; mVisited = true;
NativeRegisterDataSet data;
for (int i = 0; i < mIns.Size(); i++)
{
mIns[i].ValueForwarding(data);
}
#if 1
if (mFalseJump)
{
switch (mBranch)
{
#if 1
case ASMIT_BCS:
if (data.mRegs[CPU_REG_C].mImmediate)
{
mBranch = ASMIT_JMP;
if (!data.mRegs[CPU_REG_C].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BCC:
if (data.mRegs[CPU_REG_C].mImmediate)
{
mBranch = ASMIT_JMP;
if (data.mRegs[CPU_REG_C].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
#endif
#if 1
case ASMIT_BNE:
if (data.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if (!data.mRegs[CPU_REG_Z].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BEQ:
if (data.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if (data.mRegs[CPU_REG_Z].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
#endif
case ASMIT_BPL:
if (data.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if ((data.mRegs[CPU_REG_Z].mValue & 0x80))
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BMI:
if (data.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if (!(data.mRegs[CPU_REG_Z].mValue & 0x80))
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
}
}
#endif
#if 1 #if 1
// move load store pairs up to initial store // move load store pairs up to initial store
@ -4113,6 +4159,15 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
mIns[i + 1].mType = mIns[i + 2].mType; mIns[i + 1].mType = mIns[i + 2].mType;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mType = ASMIT_NOP;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mType = ASMIT_NOP;
progress = true;
}
else if (
mIns[i + 0].ChangesAccuAndFlag() &&
mIns[i + 1].mType == ASMIT_STA && mIns[i + 2].mType == ASMIT_LDA &&
mIns[i + 1].SameEffectiveAddress(mIns[i + 2]))
{
mIns[i + 2].mType = ASMIT_NOP;
progress = true;
} }
} }
@ -4127,7 +4182,9 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mType = ASMIT_NOP;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mType = ASMIT_NOP;
mIns[i + 3].mType = ASMIT_INC; mIns[i + 3].mType = ASMIT_INC;
progress = true;
} }
} }
@ -4143,6 +4200,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
mIns[i + 3].mType = ASMIT_ADC; mIns[i + 3].mType = ASMIT_ADC;
mIns[i + 2].mMode = ASMIM_ZERO_PAGE; mIns[i + 2].mMode = ASMIM_ZERO_PAGE;
mIns[i + 2].mAddress = mIns[i + 0].mAddress; mIns[i + 2].mAddress = mIns[i + 0].mAddress;
progress = true;
} }
} }
#endif #endif
@ -4555,20 +4613,29 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
bool changed; bool changed;
do do
{ {
BuildDataFlowSets();
ResetVisited();
changed = entryBlock->RemoveUnusedResultInstructions();
ResetVisited();
if (entryBlock->PeepHoleOptimizer())
changed = true;
ResetVisited(); ResetVisited();
for (int i = 0; i < mBlocks.Size(); i++) for (int i = 0; i < mBlocks.Size(); i++)
mBlocks[i]->mNumEntries = 0; mBlocks[i]->mNumEntries = 0;
entryBlock->CountEntries(); entryBlock->CountEntries();
do
{
BuildDataFlowSets();
ResetVisited();
changed = entryBlock->RemoveUnusedResultInstructions();
ResetVisited();
NativeRegisterDataSet data;
if (entryBlock->ValueForwarding(data))
changed = true;
} while (changed);
ResetVisited();
if (entryBlock->PeepHoleOptimizer())
changed = true;
ResetVisited(); ResetVisited();
if (entryBlock->MergeBasicBlocks()) if (entryBlock->MergeBasicBlocks())
changed = true; changed = true;

View File

@ -49,6 +49,7 @@ public:
bool ValueForwarding(NativeRegisterDataSet& data); bool ValueForwarding(NativeRegisterDataSet& data);
bool LoadsAccu(void) const; bool LoadsAccu(void) const;
bool ChangesAccuAndFlag(void) const;
bool ChangesAddress(void) const; bool ChangesAddress(void) const;
bool SameEffectiveAddress(const NativeCodeInstruction& ins) const; bool SameEffectiveAddress(const NativeCodeInstruction& ins) const;
bool IsCommutative(void) const; bool IsCommutative(void) const;
@ -123,6 +124,9 @@ public:
bool MergeBasicBlocks(void); bool MergeBasicBlocks(void);
bool MoveLoadStoreUp(int at); bool MoveLoadStoreUp(int at);
bool ValueForwarding(const NativeRegisterDataSet& data);
}; };
class NativeCodeProcedure class NativeCodeProcedure

View File

@ -9,8 +9,8 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn
mGlobals = new DeclarationScope(compilationUnits->mScope); mGlobals = new DeclarationScope(compilationUnits->mScope);
mScope = mGlobals; mScope = mGlobals;
mCodeSection = Ident::Unique("code"); mCodeSection = compilationUnits->mSectionCode;
mDataSection = Ident::Unique("code"); mDataSection = compilationUnits->mSectionData;
} }
Parser::~Parser(void) Parser::~Parser(void)

View File

@ -14,7 +14,7 @@ public:
int mLocalIndex; int mLocalIndex;
CompilationUnits * mCompilationUnits; CompilationUnits * mCompilationUnits;
const Ident* mCodeSection, * mDataSection; LinkerSection * mCodeSection, * mDataSection;
void Parse(void); void Parse(void);
protected: protected:

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,31,0 FILEVERSION 1,0,32,0
PRODUCTVERSION 1,0,31,0 PRODUCTVERSION 1,0,32,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "oscar64" VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler" VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.0.31.0" VALUE "FileVersion", "1.0.32.0"
VALUE "InternalName", "oscar64.exe" VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe" VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64" VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.0.31.0" VALUE "ProductVersion", "1.0.32.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -564,15 +564,15 @@
{ {
"Name" = "8:Microsoft Visual Studio" "Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64" "ProductName" = "8:oscar64"
"ProductCode" = "8:{62476C9D-FE04-46D6-94CA-6521843D6575}" "ProductCode" = "8:{69C89FCE-CBE7-4824-B039-777CDE9B33FF}"
"PackageCode" = "8:{67130DB4-0306-455D-881B-FCE28C4AB1C9}" "PackageCode" = "8:{025298B2-CAEE-4BDE-AA51-591D0418C086}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0" "AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE" "RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE" "RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE" "InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.0.31" "ProductVersion" = "8:1.0.32"
"Manufacturer" = "8:oscar64" "Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:" "ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:" "ARPHELPLINK" = "8:"