Added virtual functions
This commit is contained in:
parent
0b6a9c3584
commit
ed9aa3503b
|
@ -62,6 +62,7 @@ Supported Features:
|
||||||
* single inheritance of class and struct
|
* single inheritance of class and struct
|
||||||
* const member functions
|
* const member functions
|
||||||
* new, delete, new[] and delete[]
|
* new, delete, new[] and delete[]
|
||||||
|
* virtual member functions
|
||||||
|
|
||||||
## Installation and Usage
|
## Installation and Usage
|
||||||
|
|
||||||
|
@ -97,6 +98,7 @@ The compiler is command line driven, and creates an executable .prg file.
|
||||||
* -Oi : enable auto inline of small functions (part of O2/O3)
|
* -Oi : enable auto inline of small functions (part of O2/O3)
|
||||||
* -Oa : optimize inline assembler (part of O2/O3)
|
* -Oa : optimize inline assembler (part of O2/O3)
|
||||||
* -Oz : enable auto placement of global variables in zero page (part of O3)
|
* -Oz : enable auto placement of global variables in zero page (part of O3)
|
||||||
|
* -Op : optimize constant parameters
|
||||||
* -g : create source level debug info and add source line numbers to asm listing
|
* -g : create source level debug info and add source line numbers to asm listing
|
||||||
* -tf : target format, may be prg, crt or bin
|
* -tf : target format, may be prg, crt or bin
|
||||||
* -tm : target machine
|
* -tm : target machine
|
||||||
|
@ -328,6 +330,8 @@ Set optimizer options that are active for the functions after it
|
||||||
* inline : inline if requesed with inline storage attribute
|
* inline : inline if requesed with inline storage attribute
|
||||||
* autoinline : auto inline of small or only once used functions
|
* autoinline : auto inline of small or only once used functions
|
||||||
* maxinline : inline any function suitable
|
* maxinline : inline any function suitable
|
||||||
|
* constparams : enable constant parameter folding into called functions
|
||||||
|
* noconstparams : disable constant parameter folding into called functions
|
||||||
* 0 : no optimization
|
* 0 : no optimization
|
||||||
* 1 : default optimizations
|
* 1 : default optimizations
|
||||||
* 2 : aggressive optimizations
|
* 2 : aggressive optimizations
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
rem @echo off
|
rem @echo off
|
||||||
|
|
||||||
|
@call :test vcalltest.cpp
|
||||||
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
@call :test vcalltree.cpp
|
||||||
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
@call :test constructortest.cpp
|
@call :test constructortest.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
virtual int f(int x);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B : A
|
||||||
|
{
|
||||||
|
virtual int f(int x);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct C : A
|
||||||
|
{
|
||||||
|
virtual int f(int x);
|
||||||
|
virtual int g(int y, int z);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct D : B
|
||||||
|
{
|
||||||
|
virtual int f(int x);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct E : C
|
||||||
|
{
|
||||||
|
virtual int f(int x);
|
||||||
|
virtual int g(int y, int z);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct F : C
|
||||||
|
{
|
||||||
|
virtual int g(int y, int z);
|
||||||
|
};
|
||||||
|
|
||||||
|
int A::f(int x)
|
||||||
|
{
|
||||||
|
return x * 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int B::f(int x)
|
||||||
|
{
|
||||||
|
return x * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int C::f(int x)
|
||||||
|
{
|
||||||
|
return x * 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int C::g(int y, int z)
|
||||||
|
{
|
||||||
|
return (y + z) * 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int D::f(int x)
|
||||||
|
{
|
||||||
|
return x * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int E::f(int x)
|
||||||
|
{
|
||||||
|
return x * 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
int E::g(int y, int z)
|
||||||
|
{
|
||||||
|
return (y + z) * 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
int F::g(int y, int z)
|
||||||
|
{
|
||||||
|
return (y + z) * 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
B b;
|
||||||
|
C c;
|
||||||
|
D d;
|
||||||
|
E e;
|
||||||
|
F f;
|
||||||
|
|
||||||
|
assert(a.f(3) == c.f(1));
|
||||||
|
assert(b.f(4) == d.f(2));
|
||||||
|
assert(e.f(2) == b.f(5));
|
||||||
|
assert(f.f(5) == e.f(3));
|
||||||
|
|
||||||
|
assert(c.g(3, 2) == e.g(1, 2));
|
||||||
|
assert(c.g(1, 5) == f.g(0, 3));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
virtual float eval(void)
|
||||||
|
{
|
||||||
|
return 1.0e6;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConstNode : Node
|
||||||
|
{
|
||||||
|
float c;
|
||||||
|
|
||||||
|
ConstNode(float c_)
|
||||||
|
: c(c_) {}
|
||||||
|
|
||||||
|
virtual float eval(void)
|
||||||
|
{
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BinopNode : Node
|
||||||
|
{
|
||||||
|
Node * left, * right;
|
||||||
|
|
||||||
|
BinopNode(Node * left_, Node * right_)
|
||||||
|
: left(left_), right(right_)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AddNode : BinopNode
|
||||||
|
{
|
||||||
|
AddNode(Node * left_, Node * right_)
|
||||||
|
: BinopNode(left_, right_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual float eval(void)
|
||||||
|
{
|
||||||
|
return left->eval() + right->eval();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubNode : BinopNode
|
||||||
|
{
|
||||||
|
SubNode(Node * left_, Node * right_)
|
||||||
|
: BinopNode(left_, right_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual float eval(void)
|
||||||
|
{
|
||||||
|
return left->eval() - right->eval();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MulNode : BinopNode
|
||||||
|
{
|
||||||
|
MulNode(Node * left_, Node * right_)
|
||||||
|
: BinopNode(left_, right_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual float eval(void)
|
||||||
|
{
|
||||||
|
return left->eval() * right->eval();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
Node * n =
|
||||||
|
new SubNode(
|
||||||
|
new MulNode(new ConstNode(4), new ConstNode(5)),
|
||||||
|
new AddNode(new ConstNode(12), new ConstNode(7)));
|
||||||
|
|
||||||
|
assert(n->eval() == 1.0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -4384,6 +4384,7 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p
|
||||||
LoadConstant(iproc, ins);
|
LoadConstant(iproc, ins);
|
||||||
break;
|
break;
|
||||||
case IC_CALL:
|
case IC_CALL:
|
||||||
|
case IC_DISPATCH:
|
||||||
CallFunction(iproc, ins);
|
CallFunction(iproc, ins);
|
||||||
break;
|
break;
|
||||||
case IC_CALL_NATIVE:
|
case IC_CALL_NATIVE:
|
||||||
|
|
|
@ -14,6 +14,7 @@ CompilationUnits::CompilationUnits(Errors * errors)
|
||||||
mPendingUnits = nullptr;
|
mPendingUnits = nullptr;
|
||||||
mScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
mScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
||||||
mRuntimeScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
mRuntimeScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
||||||
|
mVTableScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
||||||
mStartup = nullptr;
|
mStartup = nullptr;
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 0; i < 256; i++)
|
||||||
|
|
|
@ -19,7 +19,7 @@ public:
|
||||||
CompilationUnits(Errors * errors);
|
CompilationUnits(Errors * errors);
|
||||||
~CompilationUnits(void);
|
~CompilationUnits(void);
|
||||||
|
|
||||||
DeclarationScope* mScope;
|
DeclarationScope* mScope, * mVTableScope;
|
||||||
CompilationUnit* mCompilationUnits, * mPendingUnits;
|
CompilationUnit* mCompilationUnits, * mPendingUnits;
|
||||||
|
|
||||||
Declaration* mStartup;
|
Declaration* mStartup;
|
||||||
|
|
|
@ -200,6 +200,152 @@ void Compiler::RegisterRuntime(const Location & loc, const Ident* ident)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void IndexVTableTree(Declaration* vdec, int & index)
|
||||||
|
{
|
||||||
|
vdec->mVarIndex = index;
|
||||||
|
vdec->mDefaultConstructor->mInteger = index;
|
||||||
|
index++;
|
||||||
|
Declaration* cvdec = vdec->mParams;
|
||||||
|
while (cvdec)
|
||||||
|
{
|
||||||
|
IndexVTableTree(cvdec, index);
|
||||||
|
cvdec = cvdec->mNext;
|
||||||
|
}
|
||||||
|
vdec->mSize = index - vdec->mVarIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillVTableTree(Declaration* vdec)
|
||||||
|
{
|
||||||
|
Declaration* cdec = vdec->mClass;
|
||||||
|
cdec->mScope->Iterate([=](const Ident* mident, Declaration* mdec)
|
||||||
|
{
|
||||||
|
if (mdec->mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
while (mdec)
|
||||||
|
{
|
||||||
|
if (mdec->mBase->mFlags & DTF_VIRTUAL)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < vdec->mSize; i++)
|
||||||
|
mdec->mVTable->mCalled[vdec->mVarIndex + i - mdec->mVTable->mDefaultConstructor->mVarIndex] = mdec;
|
||||||
|
}
|
||||||
|
mdec = mdec->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Declaration* cvdec = vdec->mParams;
|
||||||
|
while (cvdec)
|
||||||
|
{
|
||||||
|
FillVTableTree(cvdec);
|
||||||
|
cvdec = cvdec->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Compiler::BuildVTables(void)
|
||||||
|
{
|
||||||
|
// Connect vdecs with parents
|
||||||
|
mCompilationUnits->mVTableScope->Iterate([=](const Ident* ident, Declaration* vdec)
|
||||||
|
{
|
||||||
|
if (vdec->mBase)
|
||||||
|
{
|
||||||
|
vdec->mNext = vdec->mBase->mParams;
|
||||||
|
vdec->mBase->mParams = vdec;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Number the child vtables
|
||||||
|
mCompilationUnits->mVTableScope->Iterate([=](const Ident* ident, Declaration* vdec)
|
||||||
|
{
|
||||||
|
if (!vdec->mBase)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
IndexVTableTree(vdec, index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mCompilationUnits->mVTableScope->Iterate([=](const Ident* ident, Declaration* vdec)
|
||||||
|
{
|
||||||
|
if (!vdec->mBase)
|
||||||
|
{
|
||||||
|
FillVTableTree(vdec);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Build vtables for functions
|
||||||
|
mCompilationUnits->mVTableScope->Iterate([=](const Ident* ident, Declaration* vdec)
|
||||||
|
{
|
||||||
|
vdec->mScope->Iterate([=](const Ident* mident, Declaration* mdec)
|
||||||
|
{
|
||||||
|
Declaration* vtabt = new Declaration(mdec->mLocation, DT_TYPE_ARRAY);
|
||||||
|
vtabt->mBase = mdec->mBase->ToStriped(vdec->mSize);
|
||||||
|
vtabt->mSize = vdec->mSize * 2;
|
||||||
|
vtabt->mStride = 1;
|
||||||
|
vtabt->mStripe = 1;
|
||||||
|
vtabt->mFlags |= DTF_CONST | DTF_DEFINED;
|
||||||
|
|
||||||
|
Declaration* vtaba = new Declaration(mdec->mLocation, DT_VARIABLE);
|
||||||
|
vtaba->mFlags = DTF_CONST | DTF_GLOBAL | DTF_DEFINED;
|
||||||
|
vtaba->mBase = vtabt;
|
||||||
|
vtaba->mSize = vtabt->mSize;
|
||||||
|
vtaba->mValue = new Expression(mdec->mLocation, EX_CONSTANT);
|
||||||
|
vtaba->mValue->mDecType = vtabt;
|
||||||
|
vtaba->mValue->mDecValue = new Declaration(mdec->mLocation, DT_CONST_STRUCT);
|
||||||
|
vtaba->mIdent = mdec->mIdent;
|
||||||
|
vtaba->mQualIdent = mdec->mQualIdent->Mangle("$vtable");
|
||||||
|
vtaba->mSection = mdec->mSection;
|
||||||
|
vtaba->mOffset = - vdec->mVarIndex;
|
||||||
|
|
||||||
|
Declaration* last = nullptr;
|
||||||
|
|
||||||
|
for (int i = 0; i < vdec->mSize; i++)
|
||||||
|
{
|
||||||
|
Declaration* vmdec = mdec->mCalled[i];
|
||||||
|
|
||||||
|
Expression* texp = new Expression(vmdec->mLocation, EX_CONSTANT);
|
||||||
|
texp->mDecType = vtabt->mBase;
|
||||||
|
texp->mDecValue = vmdec;
|
||||||
|
|
||||||
|
Declaration* cdec = new Declaration(vmdec->mLocation, DT_CONST_POINTER);
|
||||||
|
cdec->mValue = texp;
|
||||||
|
cdec->mBase = vtabt->mBase;
|
||||||
|
cdec->mOffset = i;
|
||||||
|
|
||||||
|
if (last)
|
||||||
|
last->mNext = cdec;
|
||||||
|
else
|
||||||
|
vtaba->mValue->mDecValue->mParams = cdec;
|
||||||
|
last = cdec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mCompilationUnits->AddReferenced(vtaba);
|
||||||
|
|
||||||
|
Expression* vexp = new Expression(mdec->mLocation, EX_QUALIFY);
|
||||||
|
vexp->mLeft = new Expression(mdec->mLocation, EX_PREFIX);
|
||||||
|
vexp->mLeft->mDecType = mdec->mBase->mParams->mBase->mBase;
|
||||||
|
vexp->mLeft->mToken = TK_MUL;
|
||||||
|
vexp->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE);
|
||||||
|
vexp->mLeft->mLeft->mDecType = mdec->mBase->mParams->mBase;
|
||||||
|
vexp->mLeft->mLeft->mDecValue = mdec->mBase->mParams;
|
||||||
|
|
||||||
|
vexp->mDecValue = new Declaration(mdec->mLocation, DT_ELEMENT);
|
||||||
|
vexp->mDecValue->mBase = TheCharTypeDeclaration;
|
||||||
|
vexp->mDecValue->mOffset = vdec->mOffset;
|
||||||
|
vexp->mDecValue->mSize = 1;
|
||||||
|
vexp->mDecType = TheCharTypeDeclaration;
|
||||||
|
|
||||||
|
Expression* ecall = new Expression(mdec->mLocation, EX_DISPATCH);
|
||||||
|
ecall->mLeft = new Expression(mdec->mLocation, EX_INDEX);
|
||||||
|
ecall->mDecType = vtabt->mBase;
|
||||||
|
ecall->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE);
|
||||||
|
ecall->mLeft->mLeft->mDecType = vtabt;
|
||||||
|
ecall->mLeft->mLeft->mDecValue = vtaba;
|
||||||
|
ecall->mLeft->mRight = vexp;
|
||||||
|
|
||||||
|
mdec->mFlags |= DTF_DEFINED;
|
||||||
|
mdec->mValue = ecall;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Compiler::CompileProcedure(InterCodeProcedure* proc)
|
void Compiler::CompileProcedure(InterCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
if (!proc->mCompiled)
|
if (!proc->mCompiled)
|
||||||
|
@ -591,6 +737,14 @@ bool Compiler::GenerateCode(void)
|
||||||
|
|
||||||
mGlobalAnalyzer->mCompilerOptions = mCompilerOptions;
|
mGlobalAnalyzer->mCompilerOptions = mCompilerOptions;
|
||||||
|
|
||||||
|
if (mCompilerOptions & COPT_CPLUSPLUS)
|
||||||
|
{
|
||||||
|
if (mCompilerOptions & COPT_VERBOSE)
|
||||||
|
printf("Build VTables\n");
|
||||||
|
|
||||||
|
BuildVTables();
|
||||||
|
}
|
||||||
|
|
||||||
if (mCompilerOptions & COPT_VERBOSE)
|
if (mCompilerOptions & COPT_VERBOSE)
|
||||||
printf("Global analyzer\n");
|
printf("Global analyzer\n");
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
void RegisterRuntime(const Location& loc, const Ident* ident);
|
void RegisterRuntime(const Location& loc, const Ident* ident);
|
||||||
|
|
||||||
void CompileProcedure(InterCodeProcedure* proc);
|
void CompileProcedure(InterCodeProcedure* proc);
|
||||||
|
void BuildVTables(void);
|
||||||
|
|
||||||
bool WriteDbjFile(const char* filename);
|
bool WriteDbjFile(const char* filename);
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@ static const uint64 COPT_OPTIMIZE_AUTO_INLINE_ALL = 1ULL << 5;
|
||||||
static const uint64 COPT_OPTIMIZE_AUTO_UNROLL = 1ULL << 6;
|
static const uint64 COPT_OPTIMIZE_AUTO_UNROLL = 1ULL << 6;
|
||||||
static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 1ULL << 7;
|
static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 1ULL << 7;
|
||||||
static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 1ULL << 8;
|
static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 1ULL << 8;
|
||||||
|
static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -42,11 +43,11 @@ 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_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE;
|
static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS;
|
||||||
|
|
||||||
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;
|
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;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_AUTO_ZEROPAGE;
|
static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_AUTO_ZEROPAGE | COPT_OPTIMIZE_CONST_PARAMS;
|
||||||
|
|
||||||
enum TargetMachine
|
enum TargetMachine
|
||||||
{
|
{
|
||||||
|
|
|
@ -192,6 +192,12 @@ void Expression::Dump(int ident) const
|
||||||
case EX_INLINE:
|
case EX_INLINE:
|
||||||
printf("INLINE");
|
printf("INLINE");
|
||||||
break;
|
break;
|
||||||
|
case EX_VCALL:
|
||||||
|
printf("VCALL");
|
||||||
|
break;
|
||||||
|
case EX_DISPATCH:
|
||||||
|
printf("DISPATCH");
|
||||||
|
break;
|
||||||
case EX_LIST:
|
case EX_LIST:
|
||||||
printf("LIST");
|
printf("LIST");
|
||||||
break;
|
break;
|
||||||
|
@ -788,6 +794,7 @@ Declaration::Declaration(const Location& loc, DecType type)
|
||||||
mConst(nullptr), mMutable(nullptr),
|
mConst(nullptr), mMutable(nullptr),
|
||||||
mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr),
|
mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr),
|
||||||
mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr),
|
mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr),
|
||||||
|
mVTable(nullptr),
|
||||||
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1),
|
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1),
|
||||||
mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1),
|
mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1),
|
||||||
mCompilerOptions(0), mUseCount(0)
|
mCompilerOptions(0), mUseCount(0)
|
||||||
|
@ -852,6 +859,7 @@ Declaration* Declaration::Clone(void)
|
||||||
ndec->mLinkerObject = mLinkerObject;
|
ndec->mLinkerObject = mLinkerObject;
|
||||||
ndec->mAlignment = mAlignment;
|
ndec->mAlignment = mAlignment;
|
||||||
ndec->mSection = mSection;
|
ndec->mSection = mSection;
|
||||||
|
ndec->mVTable = mVTable;
|
||||||
|
|
||||||
return ndec;
|
return ndec;
|
||||||
}
|
}
|
||||||
|
@ -930,6 +938,10 @@ Declaration* Declaration::ToStriped(int stripe)
|
||||||
p = p->mNext;
|
p = p->mNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (mType == DT_TYPE_FUNCTION)
|
||||||
|
{
|
||||||
|
ndec->mParams = mParams;
|
||||||
|
}
|
||||||
else if (mType == DT_TYPE_ARRAY)
|
else if (mType == DT_TYPE_ARRAY)
|
||||||
{
|
{
|
||||||
ndec->mStride = stripe;
|
ndec->mStride = stripe;
|
||||||
|
@ -965,6 +977,7 @@ Declaration* Declaration::ToConstType(void)
|
||||||
ndec->mCopyConstructor = mCopyConstructor;
|
ndec->mCopyConstructor = mCopyConstructor;
|
||||||
ndec->mVectorConstructor = mVectorConstructor;
|
ndec->mVectorConstructor = mVectorConstructor;
|
||||||
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
||||||
|
ndec->mVTable = mVTable;
|
||||||
|
|
||||||
ndec->mMutable = this;
|
ndec->mMutable = this;
|
||||||
mConst = ndec;
|
mConst = ndec;
|
||||||
|
@ -994,6 +1007,7 @@ Declaration* Declaration::ToMutableType(void)
|
||||||
ndec->mCopyConstructor = mCopyConstructor;
|
ndec->mCopyConstructor = mCopyConstructor;
|
||||||
ndec->mVectorConstructor = mVectorConstructor;
|
ndec->mVectorConstructor = mVectorConstructor;
|
||||||
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
||||||
|
ndec->mVTable = mVTable;
|
||||||
|
|
||||||
ndec->mConst = this;
|
ndec->mConst = this;
|
||||||
mMutable = ndec;
|
mMutable = ndec;
|
||||||
|
@ -1011,7 +1025,7 @@ bool Declaration::IsSubType(const Declaration* dec) const
|
||||||
if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY)
|
if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY)
|
||||||
{
|
{
|
||||||
if (dec->mType == DT_TYPE_POINTER)
|
if (dec->mType == DT_TYPE_POINTER)
|
||||||
return this->Stride() == dec->Stride() && mBase->IsSubType(dec->mBase);
|
return /*this->Stride() == dec->Stride() &&*/ mBase->IsSubType(dec->mBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mType != dec->mType)
|
if (mType != dec->mType)
|
||||||
|
|
|
@ -49,7 +49,9 @@ enum DecType
|
||||||
DT_FUNCTION_REF,
|
DT_FUNCTION_REF,
|
||||||
DT_LABEL_REF,
|
DT_LABEL_REF,
|
||||||
DT_NAMESPACE,
|
DT_NAMESPACE,
|
||||||
DT_BASECLASS
|
DT_BASECLASS,
|
||||||
|
|
||||||
|
DT_VTABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
// TypeFlags
|
// TypeFlags
|
||||||
|
@ -82,6 +84,7 @@ static const uint64 DTF_STRIPED = (1ULL << 24);
|
||||||
static const uint64 DTF_DYNSTACK = (1ULL << 25);
|
static const uint64 DTF_DYNSTACK = (1ULL << 25);
|
||||||
static const uint64 DTF_PRIVATE = (1ULL << 26);
|
static const uint64 DTF_PRIVATE = (1ULL << 26);
|
||||||
static const uint64 DTF_PROTECTED = (1ULL << 27);
|
static const uint64 DTF_PROTECTED = (1ULL << 27);
|
||||||
|
static const uint64 DTF_VIRTUAL = (1ULL << 28);
|
||||||
|
|
||||||
static const uint64 DTF_FUNC_VARIABLE = (1ULL << 32);
|
static const uint64 DTF_FUNC_VARIABLE = (1ULL << 32);
|
||||||
static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33);
|
static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33);
|
||||||
|
@ -129,6 +132,8 @@ public:
|
||||||
|
|
||||||
void UseScope(DeclarationScope* scope);
|
void UseScope(DeclarationScope* scope);
|
||||||
|
|
||||||
|
template<typename F> void Iterate(F && f);
|
||||||
|
|
||||||
ScopeLevel mLevel;
|
ScopeLevel mLevel;
|
||||||
const Ident * mName;
|
const Ident * mName;
|
||||||
|
|
||||||
|
@ -144,6 +149,15 @@ protected:
|
||||||
ExpandingArray<DeclarationScope*> mUsed;
|
ExpandingArray<DeclarationScope*> mUsed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename F> void DeclarationScope::Iterate(F&& f)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mHashSize; i++)
|
||||||
|
{
|
||||||
|
if (mHash[i].mIdent)
|
||||||
|
f(mHash[i].mIdent, mHash[i].mDec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum ExpressionType
|
enum ExpressionType
|
||||||
{
|
{
|
||||||
EX_ERROR,
|
EX_ERROR,
|
||||||
|
@ -162,6 +176,8 @@ enum ExpressionType
|
||||||
EX_QUALIFY,
|
EX_QUALIFY,
|
||||||
EX_CALL,
|
EX_CALL,
|
||||||
EX_INLINE,
|
EX_INLINE,
|
||||||
|
EX_VCALL,
|
||||||
|
EX_DISPATCH,
|
||||||
EX_LIST,
|
EX_LIST,
|
||||||
EX_RETURN,
|
EX_RETURN,
|
||||||
EX_SEQUENCE,
|
EX_SEQUENCE,
|
||||||
|
@ -227,6 +243,7 @@ public:
|
||||||
Declaration * mBase, * mParams, * mNext, * mPrev, * mConst, * mMutable;
|
Declaration * mBase, * mParams, * mNext, * mPrev, * mConst, * mMutable;
|
||||||
Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment;
|
Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment;
|
||||||
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment;
|
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment;
|
||||||
|
Declaration * mVTable, * mClass;
|
||||||
|
|
||||||
Expression* mValue;
|
Expression* mValue;
|
||||||
DeclarationScope* mScope;
|
DeclarationScope* mScope;
|
||||||
|
|
|
@ -656,6 +656,13 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
case EX_QUALIFY:
|
case EX_QUALIFY:
|
||||||
Analyze(exp->mLeft, procDec, lhs);
|
Analyze(exp->mLeft, procDec, lhs);
|
||||||
return exp->mDecValue->mBase;
|
return exp->mDecValue->mBase;
|
||||||
|
case EX_DISPATCH:
|
||||||
|
Analyze(exp->mLeft, procDec, lhs);
|
||||||
|
break;
|
||||||
|
case EX_VCALL:
|
||||||
|
exp->mType = EX_CALL;
|
||||||
|
exp->mLeft->mDecValue = exp->mLeft->mDecValue->mVTable;
|
||||||
|
// intentional fall through
|
||||||
case EX_CALL:
|
case EX_CALL:
|
||||||
case EX_INLINE:
|
case EX_INLINE:
|
||||||
ldec = Analyze(exp->mLeft, procDec, false);
|
ldec = Analyze(exp->mLeft, procDec, false);
|
||||||
|
@ -688,7 +695,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
if (pdec && !(ldec->mBase->mFlags & DTF_VARIADIC) && !(ldec->mFlags & (DTF_INTRINSIC | DTF_FUNC_ASSEMBLER)))
|
if (pdec && !(ldec->mBase->mFlags & DTF_VARIADIC) && !(ldec->mFlags & (DTF_INTRINSIC | DTF_FUNC_ASSEMBLER)))
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
if (mCompilerOptions & COPT_OPTIMIZE_BASIC)
|
if (mCompilerOptions & COPT_OPTIMIZE_CONST_PARAMS)
|
||||||
{
|
{
|
||||||
if (!(pdec->mFlags & DTF_FPARAM_NOCONST))
|
if (!(pdec->mFlags & DTF_FPARAM_NOCONST))
|
||||||
{
|
{
|
||||||
|
@ -922,6 +929,13 @@ void GlobalAnalyzer::RegisterProc(Declaration* to)
|
||||||
{
|
{
|
||||||
if (to->mType == DT_CONST_FUNCTION)
|
if (to->mType == DT_CONST_FUNCTION)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
if (to->mBase->mFlags & DTF_VIRTUAL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if (!(to->mFlags & DTF_FUNC_VARIABLE))
|
if (!(to->mFlags & DTF_FUNC_VARIABLE))
|
||||||
{
|
{
|
||||||
to->mFlags |= DTF_FUNC_VARIABLE;
|
to->mFlags |= DTF_FUNC_VARIABLE;
|
||||||
|
|
|
@ -626,7 +626,7 @@ static bool SameInstruction(const InterInstruction* ins1, const InterInstruction
|
||||||
bool InterCodeBasicBlock::CanSwapInstructions(const InterInstruction* ins0, const InterInstruction* ins1) const
|
bool InterCodeBasicBlock::CanSwapInstructions(const InterInstruction* ins0, const InterInstruction* ins1) const
|
||||||
{
|
{
|
||||||
// Cannot swap branches
|
// Cannot swap branches
|
||||||
if (ins1->mCode == IC_JUMP || ins1->mCode == IC_BRANCH)
|
if (ins1->mCode == IC_JUMP || ins1->mCode == IC_BRANCH || ins1->mCode == IC_DISPATCH)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check function call
|
// Check function call
|
||||||
|
@ -1180,7 +1180,7 @@ static bool IsMoveable(InterCode code)
|
||||||
{
|
{
|
||||||
if (HasSideEffect(code) || code == IC_COPY || code == IC_STRCPY || code == IC_STORE || code == IC_BRANCH || code == IC_POP_FRAME || code == IC_PUSH_FRAME || code == IC_MALLOC || code == IC_FREE)
|
if (HasSideEffect(code) || code == IC_COPY || code == IC_STRCPY || code == IC_STORE || code == IC_BRANCH || code == IC_POP_FRAME || code == IC_PUSH_FRAME || code == IC_MALLOC || code == IC_FREE)
|
||||||
return false;
|
return false;
|
||||||
if (code == IC_RETURN || code == IC_RETURN_STRUCT || code == IC_RETURN_VALUE)
|
if (code == IC_RETURN || code == IC_RETURN_STRUCT || code == IC_RETURN_VALUE || code == IC_DISPATCH)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2945,6 +2945,7 @@ InterInstruction::InterInstruction(const Location& loc, InterCode code)
|
||||||
case IC_RETURN_VALUE:
|
case IC_RETURN_VALUE:
|
||||||
case IC_RETURN_STRUCT:
|
case IC_RETURN_STRUCT:
|
||||||
case IC_CONVERSION_OPERATOR:
|
case IC_CONVERSION_OPERATOR:
|
||||||
|
case IC_DISPATCH:
|
||||||
mNumOperands = 1;
|
mNumOperands = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3141,7 +3142,7 @@ void InterInstruction::FilterStaticVarsUsage(const GrowingVariableArray& staticV
|
||||||
requiredVars += mSrc[1].mVarIndex;
|
requiredVars += mSrc[1].mVarIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mCode == IC_COPY || mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE || mCode == IC_STRCPY)
|
else if (mCode == IC_COPY || mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE || mCode == IC_STRCPY || mCode == IC_DISPATCH)
|
||||||
{
|
{
|
||||||
requiredVars.OrNot(providedVars);
|
requiredVars.OrNot(providedVars);
|
||||||
}
|
}
|
||||||
|
@ -3509,7 +3510,7 @@ void InterInstruction::BuildCallerSaveTempSet(NumberSet& requiredTemps, NumberSe
|
||||||
if (mDst.mTemp >= 0)
|
if (mDst.mTemp >= 0)
|
||||||
requiredTemps -= mDst.mTemp;
|
requiredTemps -= mDst.mTemp;
|
||||||
|
|
||||||
if (mCode == IC_CALL || mCode == IC_CALL_NATIVE)
|
if (mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_DISPATCH)
|
||||||
callerSaveTemps |= requiredTemps;
|
callerSaveTemps |= requiredTemps;
|
||||||
|
|
||||||
for (int i = 0; i < mNumOperands; i++)
|
for (int i = 0; i < mNumOperands; i++)
|
||||||
|
@ -3700,7 +3701,7 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(InterCodeBasicBlock*
|
||||||
requiredVars.Fill();
|
requiredVars.Fill();
|
||||||
storeIns.SetSize(0);
|
storeIns.SetSize(0);
|
||||||
}
|
}
|
||||||
else if (mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE)
|
else if (mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE || mCode == IC_DISPATCH)
|
||||||
{
|
{
|
||||||
requiredVars.Fill();
|
requiredVars.Fill();
|
||||||
storeIns.SetSize(0);
|
storeIns.SetSize(0);
|
||||||
|
@ -4322,6 +4323,9 @@ void InterInstruction::Disassemble(FILE* file)
|
||||||
case IC_ASSEMBLER:
|
case IC_ASSEMBLER:
|
||||||
fprintf(file, "JSR");
|
fprintf(file, "JSR");
|
||||||
break;
|
break;
|
||||||
|
case IC_DISPATCH:
|
||||||
|
fprintf(file, "DISPATCH");
|
||||||
|
break;
|
||||||
case IC_RETURN_VALUE:
|
case IC_RETURN_VALUE:
|
||||||
assert(mNumOperands == 1);
|
assert(mNumOperands == 1);
|
||||||
fprintf(file, "RETV");
|
fprintf(file, "RETV");
|
||||||
|
@ -9640,6 +9644,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray&
|
||||||
{
|
{
|
||||||
ins->mCode = IC_LOAD_TEMPORARY;
|
ins->mCode = IC_LOAD_TEMPORARY;
|
||||||
ins->mSrc[0] = lins->mSrc[0];
|
ins->mSrc[0] = lins->mSrc[0];
|
||||||
|
ins->mDst.mRange.Limit(ins->mSrc[0].mRange);
|
||||||
ins->mNumOperands = 1;
|
ins->mNumOperands = 1;
|
||||||
assert(ins->mSrc[0].mTemp >= 0);
|
assert(ins->mSrc[0].mTemp >= 0);
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -9702,6 +9707,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray&
|
||||||
assert(lins->mDst.mTemp >= 0);
|
assert(lins->mDst.mTemp >= 0);
|
||||||
ins->mCode = IC_LOAD_TEMPORARY;
|
ins->mCode = IC_LOAD_TEMPORARY;
|
||||||
ins->mSrc[0] = lins->mDst;
|
ins->mSrc[0] = lins->mDst;
|
||||||
|
ins->mDst.mRange.Limit(ins->mSrc[0].mRange);
|
||||||
ins->mNumOperands = 1;
|
ins->mNumOperands = 1;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -10091,7 +10097,7 @@ bool InterCodeBasicBlock::CanMoveInstructionDown(int si, int ti) const
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (ins->mCode == IC_COPY || ins->mCode == IC_PUSH_FRAME || ins->mCode == IC_POP_FRAME ||
|
if (ins->mCode == IC_COPY || ins->mCode == IC_PUSH_FRAME || ins->mCode == IC_POP_FRAME ||
|
||||||
ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE)
|
ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE || ins->mCode == IC_DISPATCH)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int i = si + 1; i < ti; i++)
|
for (int i = si + 1; i < ti; i++)
|
||||||
|
@ -10153,7 +10159,7 @@ bool InterCodeBasicBlock::CanMoveInstructionBeforeBlock(int ii, const InterInstr
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE || ins->mCode == IC_COPY || ins->mCode == IC_PUSH_FRAME || ins->mCode == IC_POP_FRAME ||
|
if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE || ins->mCode == IC_COPY || ins->mCode == IC_PUSH_FRAME || ins->mCode == IC_POP_FRAME ||
|
||||||
ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE)
|
ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE || ins->mCode == IC_DISPATCH)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int i = 0; i < ii; i++)
|
for (int i = 0; i < ii; i++)
|
||||||
|
@ -10919,7 +10925,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 || mInstructions[i]->mCode == IC_CALL_NATIVE)
|
if (mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE || mInstructions[i]->mCode == IC_DISPATCH)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (mTrueJump && !mTrueJump->IsLeafProcedure())
|
if (mTrueJump && !mTrueJump->IsLeafProcedure())
|
||||||
|
@ -11080,6 +11086,8 @@ bool InterCodeBasicBlock::CheckStaticStack(void)
|
||||||
else if (!(mInstructions[i]->mSrc[0].mLinkerObject->mFlags & LOBJF_STATIC_STACK))
|
else if (!(mInstructions[i]->mSrc[0].mLinkerObject->mFlags & LOBJF_STATIC_STACK))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else if (mInstructions[i]->mCode == IC_DISPATCH)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTrueJump && !mTrueJump->CheckStaticStack())
|
if (mTrueJump && !mTrueJump->CheckStaticStack())
|
||||||
|
@ -14899,7 +14907,7 @@ void InterCodeBasicBlock::CheckValueReturn(void)
|
||||||
for (int i = 0; i < mInstructions.Size(); i++)
|
for (int i = 0; i < mInstructions.Size(); i++)
|
||||||
{
|
{
|
||||||
InterInstruction* ins = mInstructions[i];
|
InterInstruction* ins = mInstructions[i];
|
||||||
if (ins->mCode == IC_ASSEMBLER)
|
if (ins->mCode == IC_ASSEMBLER || ins->mCode == IC_DISPATCH)
|
||||||
return;
|
return;
|
||||||
else if (ins->mCode == IC_RETURN)
|
else if (ins->mCode == IC_RETURN)
|
||||||
mProc->mModule->mErrors->Error(ins->mLocation, EWARN_MISSING_RETURN_STATEMENT, "Missing return statement");
|
mProc->mModule->mErrors->Error(ins->mLocation, EWARN_MISSING_RETURN_STATEMENT, "Missing return statement");
|
||||||
|
@ -15242,7 +15250,7 @@ void InterCodeBasicBlock::Disassemble(FILE* file, bool dumpSets)
|
||||||
|
|
||||||
void InterCodeBasicBlock::WarnUnreachable(void)
|
void InterCodeBasicBlock::WarnUnreachable(void)
|
||||||
{
|
{
|
||||||
if (mNumEntries == 0)
|
if (mNumEntries == 0 && mProc->mCheckUnreachable)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < mInstructions.Size() && !IsObservable(mInstructions[i]->mCode))
|
while (i < mInstructions.Size() && !IsObservable(mInstructions[i]->mCode))
|
||||||
|
@ -15262,6 +15270,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l
|
||||||
mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false),
|
mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false),
|
||||||
mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false),
|
mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false),
|
||||||
mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false),
|
mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false),
|
||||||
|
mCheckUnreachable(true),
|
||||||
mDeclaration(nullptr)
|
mDeclaration(nullptr)
|
||||||
{
|
{
|
||||||
mID = mModule->mProcedures.Size();
|
mID = mModule->mProcedures.Size();
|
||||||
|
@ -16106,7 +16115,7 @@ void InterCodeProcedure::Close(void)
|
||||||
{
|
{
|
||||||
GrowingTypeArray tstack(IT_NONE);
|
GrowingTypeArray tstack(IT_NONE);
|
||||||
|
|
||||||
CheckFunc = !strcmp(mIdent->mString, "print");
|
CheckFunc = !strcmp(mIdent->mString, "setspr");
|
||||||
|
|
||||||
mEntryBlock = mBlocks[0];
|
mEntryBlock = mBlocks[0];
|
||||||
|
|
||||||
|
@ -16373,6 +16382,9 @@ void InterCodeProcedure::Close(void)
|
||||||
|
|
||||||
BuildDataFlowSets();
|
BuildDataFlowSets();
|
||||||
|
|
||||||
|
TempForwarding();
|
||||||
|
RemoveUnusedInstructions();
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->BuildLocalIntegerRangeSets(mTemporaries.Size(), mLocalVars, mParamVars);
|
mEntryBlock->BuildLocalIntegerRangeSets(mTemporaries.Size(), mLocalVars, mParamVars);
|
||||||
|
@ -16383,6 +16395,9 @@ void InterCodeProcedure::Close(void)
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
} while (mEntryBlock->BuildGlobalIntegerRangeSets(true, mLocalVars, mParamVars));
|
} while (mEntryBlock->BuildGlobalIntegerRangeSets(true, mLocalVars, mParamVars));
|
||||||
|
|
||||||
|
TempForwarding();
|
||||||
|
RemoveUnusedInstructions();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
DisassembleDebug("tq");
|
DisassembleDebug("tq");
|
||||||
|
|
||||||
|
@ -16392,6 +16407,7 @@ void InterCodeProcedure::Close(void)
|
||||||
|
|
||||||
DisassembleDebug("Estimated value range");
|
DisassembleDebug("Estimated value range");
|
||||||
|
|
||||||
|
|
||||||
GrowingInstructionPtrArray pipa(nullptr);
|
GrowingInstructionPtrArray pipa(nullptr);
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->LinkerObjectForwarding(pipa);
|
mEntryBlock->LinkerObjectForwarding(pipa);
|
||||||
|
|
|
@ -40,6 +40,7 @@ enum InterCode
|
||||||
IC_ASSEMBLER,
|
IC_ASSEMBLER,
|
||||||
IC_JUMPF,
|
IC_JUMPF,
|
||||||
IC_SELECT,
|
IC_SELECT,
|
||||||
|
IC_DISPATCH,
|
||||||
IC_UNREACHABLE
|
IC_UNREACHABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -588,6 +589,7 @@ public:
|
||||||
int mTempSize, mCommonFrameSize, mCallerSavedTemps, mFreeCallerSavedTemps, mFastCallBase;
|
int mTempSize, mCommonFrameSize, mCallerSavedTemps, mFreeCallerSavedTemps, mFastCallBase;
|
||||||
bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure;
|
bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure;
|
||||||
bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack;
|
bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack;
|
||||||
|
bool mCheckUnreachable;
|
||||||
GrowingInterCodeProcedurePtrArray mCalledFunctions;
|
GrowingInterCodeProcedurePtrArray mCalledFunctions;
|
||||||
|
|
||||||
InterCodeModule * mModule;
|
InterCodeModule * mModule;
|
||||||
|
|
|
@ -894,6 +894,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro
|
||||||
Expression* fexp = fdec->mValue;
|
Expression* fexp = fdec->mValue;
|
||||||
Declaration* ftype = fdec->mBase;
|
Declaration* ftype = fdec->mBase;
|
||||||
|
|
||||||
|
proc->mCheckUnreachable = false;
|
||||||
|
|
||||||
InlineMapper nmapper;
|
InlineMapper nmapper;
|
||||||
nmapper.mReturn = new InterCodeBasicBlock(proc);
|
nmapper.mReturn = new InterCodeBasicBlock(proc);
|
||||||
nmapper.mVarIndex = proc->mNumLocals;
|
nmapper.mVarIndex = proc->mNumLocals;
|
||||||
|
@ -1610,6 +1612,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
if (inlineMapper)
|
if (inlineMapper)
|
||||||
ins->mConst.mVarIndex += inlineMapper->mVarIndex;
|
ins->mConst.mVarIndex += inlineMapper->mVarIndex;
|
||||||
InitLocalVariable(proc, dec, ins->mConst.mVarIndex);
|
InitLocalVariable(proc, dec, ins->mConst.mVarIndex);
|
||||||
|
proc->mCheckUnreachable = false;
|
||||||
}
|
}
|
||||||
else if (inlineMapper)
|
else if (inlineMapper)
|
||||||
{
|
{
|
||||||
|
@ -2665,6 +2668,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
return ExValue(TheBoolTypeDeclaration, ins->mDst.mTemp);
|
return ExValue(TheBoolTypeDeclaration, ins->mDst.mTemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EX_VCALL:
|
||||||
case EX_CALL:
|
case EX_CALL:
|
||||||
case EX_INLINE:
|
case EX_INLINE:
|
||||||
{
|
{
|
||||||
|
@ -2854,7 +2858,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
bool canInline = exp->mLeft->mType == EX_CONSTANT &&
|
bool canInline = exp->mLeft->mType == EX_CONSTANT &&
|
||||||
exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION &&
|
exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION &&
|
||||||
(mCompilerOptions & COPT_OPTIMIZE_INLINE) &&
|
(mCompilerOptions & COPT_OPTIMIZE_INLINE) &&
|
||||||
!(inlineMapper && inlineMapper->mDepth > 10);
|
!(inlineMapper && inlineMapper->mDepth > 10) &&
|
||||||
|
exp->mType != EX_VCALL;
|
||||||
bool doInline = false, inlineConstexpr = false;
|
bool doInline = false, inlineConstexpr = false;
|
||||||
|
|
||||||
if (canInline)
|
if (canInline)
|
||||||
|
@ -2902,7 +2907,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
|
Expression * funcexp = exp->mLeft;
|
||||||
|
|
||||||
|
vl = TranslateExpression(procType, proc, block, funcexp, destack, breakBlock, continueBlock, inlineMapper);
|
||||||
|
|
||||||
vl = Dereference(proc, exp, block, vl);
|
vl = Dereference(proc, exp, block, vl);
|
||||||
|
|
||||||
int atotal = 0;
|
int atotal = 0;
|
||||||
|
@ -2992,8 +3000,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
atotal = 2;
|
atotal = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exp->mLeft->mDecValue && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION)
|
if (funcexp->mDecValue && funcexp->mDecValue->mType == DT_CONST_FUNCTION)
|
||||||
proc->AddCalledFunction(proc->mModule->mProcedures[exp->mLeft->mDecValue->mVarIndex]);
|
proc->AddCalledFunction(proc->mModule->mProcedures[funcexp->mDecValue->mVarIndex]);
|
||||||
else
|
else
|
||||||
proc->CallsFunctionPointer();
|
proc->CallsFunctionPointer();
|
||||||
|
|
||||||
|
@ -3187,15 +3195,15 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
block->Append(defins[i]);
|
block->Append(defins[i]);
|
||||||
|
|
||||||
InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CALL);
|
InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CALL);
|
||||||
if (exp->mLeft->mDecValue && (exp->mLeft->mDecValue->mFlags & DTF_NATIVE))
|
if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_NATIVE))
|
||||||
cins->mCode = IC_CALL_NATIVE;
|
cins->mCode = IC_CALL_NATIVE;
|
||||||
else
|
else
|
||||||
cins->mCode = IC_CALL;
|
cins->mCode = IC_CALL;
|
||||||
|
|
||||||
if (exp->mLeft->mDecValue && (exp->mLeft->mDecValue->mFlags & DTF_FUNC_PURE))
|
if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_FUNC_PURE))
|
||||||
cins->mNoSideEffects = true;
|
cins->mNoSideEffects = true;
|
||||||
|
|
||||||
if (exp->mLeft->mType == EX_CONSTANT && (exp->mLeft->mDecValue->mFlags & DTF_FUNC_CONSTEXPR))
|
if (funcexp->mType == EX_CONSTANT && (funcexp->mDecValue->mFlags & DTF_FUNC_CONSTEXPR))
|
||||||
cins->mConstExpr = true;
|
cins->mConstExpr = true;
|
||||||
|
|
||||||
cins->mSrc[0].mType = IT_POINTER;
|
cins->mSrc[0].mType = IT_POINTER;
|
||||||
|
@ -4059,6 +4067,30 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case EX_DISPATCH:
|
||||||
|
{
|
||||||
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
|
||||||
|
vl = Dereference(proc, exp, block, vl);
|
||||||
|
|
||||||
|
InterInstruction* ins = new InterInstruction(exp->mLocation, IC_DISPATCH);
|
||||||
|
ins->mSrc[0].mType = IT_POINTER;
|
||||||
|
ins->mSrc[0].mTemp = vl.mTemp;
|
||||||
|
|
||||||
|
block->Append(ins);
|
||||||
|
|
||||||
|
Declaration* dinit = exp->mLeft->mLeft->mDecValue->mValue->mDecValue->mParams;
|
||||||
|
while (dinit)
|
||||||
|
{
|
||||||
|
proc->AddCalledFunction(proc->mModule->mProcedures[dinit->mValue->mDecValue->mVarIndex]);
|
||||||
|
dinit = dinit->mNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// proc->CallsFunctionPointer();
|
||||||
|
|
||||||
|
return ExValue(TheVoidTypeDeclaration);
|
||||||
|
}
|
||||||
|
|
||||||
case EX_WHILE:
|
case EX_WHILE:
|
||||||
{
|
{
|
||||||
DestructStack* odestack = destack;
|
DestructStack* odestack = destack;
|
||||||
|
|
|
@ -27069,11 +27069,6 @@ bool NativeCodeBasicBlock::ReverseBitfieldForwarding(void)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NativeCodeLoadStorePair
|
|
||||||
{
|
|
||||||
NativeCodeInstruction mLoad, mStore;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::RemoveLocalUnusedLinkerObjects(void)
|
bool NativeCodeBasicBlock::RemoveLocalUnusedLinkerObjects(void)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -27124,7 +27119,7 @@ void NativeCodeBasicBlock::MarkLocalUsedLinkerObjects(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::AbsoluteValueForwarding(void)
|
bool NativeCodeBasicBlock::AbsoluteValueForwarding(const ExpandingArray<NativeCodeLoadStorePair> & npairs)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
|
@ -27133,6 +27128,8 @@ bool NativeCodeBasicBlock::AbsoluteValueForwarding(void)
|
||||||
mVisited = true;
|
mVisited = true;
|
||||||
|
|
||||||
ExpandingArray<NativeCodeLoadStorePair> pairs;
|
ExpandingArray<NativeCodeLoadStorePair> pairs;
|
||||||
|
if (mNumEntries == 1)
|
||||||
|
pairs = npairs;
|
||||||
|
|
||||||
int ains = -1;
|
int ains = -1;
|
||||||
|
|
||||||
|
@ -27205,9 +27202,9 @@ bool NativeCodeBasicBlock::AbsoluteValueForwarding(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTrueJump && mTrueJump->AbsoluteValueForwarding())
|
if (mTrueJump && mTrueJump->AbsoluteValueForwarding(pairs))
|
||||||
changed = true;
|
changed = true;
|
||||||
if (mFalseJump && mFalseJump->AbsoluteValueForwarding())
|
if (mFalseJump && mFalseJump->AbsoluteValueForwarding(pairs))
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28674,6 +28671,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
|
||||||
mIns[1].mType = ASMIT_LDA; mIns[1].mLive |= LIVE_CPU_REG_A;
|
mIns[1].mType = ASMIT_LDA; mIns[1].mLive |= LIVE_CPU_REG_A;
|
||||||
mIns[0].mType = ASMIT_CMP; mIns[0].mLive |= LIVE_CPU_REG_Z;
|
mIns[0].mType = ASMIT_CMP; mIns[0].mLive |= LIVE_CPU_REG_Z;
|
||||||
prevBlock->mIns.Push(mIns[1]);
|
prevBlock->mIns.Push(mIns[1]);
|
||||||
|
prevBlock->mExitRequiredRegs += CPU_REG_A;
|
||||||
|
mEntryRequiredRegs += CPU_REG_A;
|
||||||
mIns.Remove(1);
|
mIns.Remove(1);
|
||||||
|
|
||||||
CheckLive();
|
CheckLive();
|
||||||
|
@ -37703,7 +37702,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
{
|
{
|
||||||
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
|
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
|
||||||
mIns[i + 1].mType = ASMIT_STX; mIns[i + 1].CopyMode(mIns[i + 3]);
|
mIns[i + 1].mType = ASMIT_STX; mIns[i + 1].CopyMode(mIns[i + 3]);
|
||||||
mIns[i + 3].mType = mIns[i + 2].mType;
|
mIns[i + 3].mType = mIns[i + 2].mType; mIns[i + 3].mLive |= LIVE_CPU_REG_A;
|
||||||
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
||||||
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
|
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
|
||||||
progress = true;
|
progress = true;
|
||||||
|
@ -37717,7 +37716,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
{
|
{
|
||||||
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
|
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
|
||||||
mIns[i + 1].mType = ASMIT_STY; mIns[i + 1].CopyMode(mIns[i + 3]);
|
mIns[i + 1].mType = ASMIT_STY; mIns[i + 1].CopyMode(mIns[i + 3]);
|
||||||
mIns[i + 3].mType = mIns[i + 2].mType;
|
mIns[i + 3].mType = mIns[i + 2].mType; mIns[i + 3].mLive |= LIVE_CPU_REG_A;
|
||||||
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
||||||
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
|
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
|
||||||
progress = true;
|
progress = true;
|
||||||
|
@ -40878,7 +40877,8 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
if (step == 9)
|
if (step == 9)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
if (mEntryBlock->AbsoluteValueForwarding())
|
ExpandingArray<NativeCodeLoadStorePair> pairs;
|
||||||
|
if (mEntryBlock->AbsoluteValueForwarding(pairs))
|
||||||
{
|
{
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
|
@ -41889,6 +41889,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
|
||||||
case IC_CONSTANT:
|
case IC_CONSTANT:
|
||||||
block->LoadConstant(iproc, ins);
|
block->LoadConstant(iproc, ins);
|
||||||
break;
|
break;
|
||||||
|
case IC_DISPATCH:
|
||||||
case IC_CALL:
|
case IC_CALL:
|
||||||
block->CallFunction(iproc, this, ins);
|
block->CallFunction(iproc, this, ins);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -207,6 +207,12 @@ public:
|
||||||
uint32 NeedsLive(void) const;
|
uint32 NeedsLive(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NativeCodeLoadStorePair
|
||||||
|
{
|
||||||
|
NativeCodeInstruction mLoad, mStore;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class NativeCodeBasicBlock
|
class NativeCodeBasicBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -474,7 +480,7 @@ public:
|
||||||
bool BitFieldForwarding(const NativeRegisterDataSet& data);
|
bool BitFieldForwarding(const NativeRegisterDataSet& data);
|
||||||
bool ReverseBitfieldForwarding(void);
|
bool ReverseBitfieldForwarding(void);
|
||||||
bool OffsetValueForwarding(const ValueNumberingDataSet & data);
|
bool OffsetValueForwarding(const ValueNumberingDataSet & data);
|
||||||
bool AbsoluteValueForwarding(void);
|
bool AbsoluteValueForwarding(const ExpandingArray<NativeCodeLoadStorePair>& npairs);
|
||||||
|
|
||||||
void MarkLocalUsedLinkerObjects(void);
|
void MarkLocalUsedLinkerObjects(void);
|
||||||
bool RemoveLocalUnusedLinkerObjects(void);
|
bool RemoveLocalUnusedLinkerObjects(void);
|
||||||
|
|
|
@ -64,6 +64,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
||||||
|
|
||||||
Declaration * dec = new Declaration(mScanner->mLocation, dt);
|
Declaration * dec = new Declaration(mScanner->mLocation, dt);
|
||||||
|
|
||||||
|
bool needVTable = false;
|
||||||
|
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
if (mScanner->mToken == TK_IDENT)
|
if (mScanner->mToken == TK_IDENT)
|
||||||
{
|
{
|
||||||
|
@ -119,6 +121,9 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
||||||
bcdec->mBase = pdec;
|
bcdec->mBase = pdec;
|
||||||
bcdec->mFlags = pflags;
|
bcdec->mFlags = pflags;
|
||||||
|
|
||||||
|
if (pdec->mVTable)
|
||||||
|
needVTable = true;
|
||||||
|
|
||||||
dec->mSize = pdec->mSize;
|
dec->mSize = pdec->mSize;
|
||||||
|
|
||||||
dec->mBase = bcdec;
|
dec->mBase = bcdec;
|
||||||
|
@ -141,6 +146,12 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
||||||
}
|
}
|
||||||
|
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
|
if (ConsumeTokenIf(TK_CLOSE_BRACE))
|
||||||
|
{
|
||||||
|
dec->mParams = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Declaration* mlast = nullptr;
|
Declaration* mlast = nullptr;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -174,6 +185,9 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
||||||
|
|
||||||
if (mdec->mBase->mType == DT_TYPE_FUNCTION)
|
if (mdec->mBase->mType == DT_TYPE_FUNCTION)
|
||||||
{
|
{
|
||||||
|
if (mdec->mBase->mFlags & DTF_VIRTUAL)
|
||||||
|
needVTable = true;
|
||||||
|
|
||||||
mdec->mType = DT_CONST_FUNCTION;
|
mdec->mType = DT_CONST_FUNCTION;
|
||||||
mdec->mSection = mCodeSection;
|
mdec->mSection = mCodeSection;
|
||||||
mdec->mFlags |= DTF_GLOBAL;
|
mdec->mFlags |= DTF_GLOBAL;
|
||||||
|
@ -239,11 +253,98 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
||||||
mlast->mNext = nullptr;
|
mlast->mNext = nullptr;
|
||||||
else
|
else
|
||||||
dec->mParams = nullptr;
|
dec->mParams = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
dec->SetDefined();
|
dec->SetDefined();
|
||||||
|
|
||||||
if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mType == DT_TYPE_STRUCT && dec->mIdent)
|
if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mType == DT_TYPE_STRUCT && dec->mIdent)
|
||||||
{
|
{
|
||||||
|
if (needVTable)
|
||||||
|
{
|
||||||
|
Declaration* vdec = mCompilationUnits->mVTableScope->Lookup(dec->mQualIdent);
|
||||||
|
if (!vdec)
|
||||||
|
{
|
||||||
|
vdec = new Declaration(dec->mLocation, DT_VTABLE);
|
||||||
|
|
||||||
|
if (dec->mBase)
|
||||||
|
{
|
||||||
|
vdec->mBase = dec->mBase->mBase->mVTable;
|
||||||
|
vdec->mSize = vdec->mBase->mSize;
|
||||||
|
vdec->mOffset = vdec->mBase->mOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Declaration* mdec = dec->mParams;
|
||||||
|
while (mdec)
|
||||||
|
{
|
||||||
|
mdec->mOffset++;
|
||||||
|
mdec = mdec->mNext;
|
||||||
|
}
|
||||||
|
vdec->mOffset = 0;
|
||||||
|
dec->mSize++;
|
||||||
|
}
|
||||||
|
|
||||||
|
vdec->mDefaultConstructor = new Declaration(dec->mLocation, DT_CONST_INTEGER);
|
||||||
|
vdec->mDefaultConstructor->mBase = TheConstCharTypeDeclaration;
|
||||||
|
vdec->mDefaultConstructor->mSize = 1;
|
||||||
|
vdec->mDefaultConstructor->mInteger = -1;
|
||||||
|
|
||||||
|
vdec->mClass = dec;
|
||||||
|
vdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS);
|
||||||
|
vdec->mIdent = dec->mIdent;
|
||||||
|
vdec->mQualIdent = dec->mQualIdent;
|
||||||
|
mCompilationUnits->mVTableScope->Insert(vdec->mQualIdent, vdec);
|
||||||
|
|
||||||
|
dec->mVTable = vdec;
|
||||||
|
}
|
||||||
|
|
||||||
|
dec->mScope->Iterate([=](const Ident* ident, Declaration* mdec)
|
||||||
|
{
|
||||||
|
if (mdec->mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
while (mdec)
|
||||||
|
{
|
||||||
|
if (mdec->mBase->mFlags & DTF_VIRTUAL)
|
||||||
|
{
|
||||||
|
Declaration* vpdec = vdec;
|
||||||
|
Declaration* vmdec = vpdec->mScope->Lookup(ident);
|
||||||
|
while (!vmdec && vpdec->mBase)
|
||||||
|
{
|
||||||
|
vpdec = vpdec->mBase;
|
||||||
|
vmdec = vpdec->mScope->Lookup(ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
Declaration* vmpdec = nullptr;
|
||||||
|
|
||||||
|
while (vmdec && vmdec->mBase->IsSame(mdec->mBase))
|
||||||
|
{
|
||||||
|
vmpdec = vmdec;
|
||||||
|
vmdec = vmdec->mNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vmdec)
|
||||||
|
{
|
||||||
|
vmdec = mdec->Clone();
|
||||||
|
vmdec->mNext = nullptr;
|
||||||
|
vmdec->mDefaultConstructor = dec->mVTable;
|
||||||
|
vmdec->mFlags |= DTF_NATIVE;
|
||||||
|
|
||||||
|
if (vmpdec)
|
||||||
|
vmpdec->mNext = vmdec;
|
||||||
|
else
|
||||||
|
vdec->mScope->Insert(ident, vmdec);
|
||||||
|
}
|
||||||
|
|
||||||
|
mdec->mVTable = vmdec;
|
||||||
|
}
|
||||||
|
|
||||||
|
mdec = mdec->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
AddDefaultConstructors(pthis);
|
AddDefaultConstructors(pthis);
|
||||||
|
|
||||||
// Lookup constructors, have same name as class
|
// Lookup constructors, have same name as class
|
||||||
|
@ -256,6 +357,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendMemberDestructor(pthis);
|
AppendMemberDestructor(pthis);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1409,6 +1511,31 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc)
|
||||||
dec = dec->mPrev;
|
dec = dec->mPrev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pthis->mBase->mVTable)
|
||||||
|
{
|
||||||
|
Expression* sexp = new Expression(cfunc->mLocation, EX_SEQUENCE);
|
||||||
|
sexp->mLeft = cfunc->mValue;
|
||||||
|
|
||||||
|
Expression* vexp = new Expression(pthis->mLocation, EX_QUALIFY);
|
||||||
|
vexp->mLeft = thisexp;
|
||||||
|
vexp->mDecValue = new Declaration(pthis->mLocation, DT_ELEMENT);
|
||||||
|
vexp->mDecValue->mBase = TheCharTypeDeclaration;
|
||||||
|
vexp->mDecValue->mOffset = pthis->mBase->mVTable->mOffset;
|
||||||
|
vexp->mDecValue->mSize = 1;
|
||||||
|
vexp->mDecType = TheCharTypeDeclaration;
|
||||||
|
|
||||||
|
Expression* nexp = new Expression(cfunc->mLocation, EX_INITIALIZATION);
|
||||||
|
nexp->mToken = TK_ASSIGN;
|
||||||
|
nexp->mDecType = TheCharTypeDeclaration;
|
||||||
|
nexp->mLeft = vexp;
|
||||||
|
nexp->mRight = new Expression(cfunc->mLocation, EX_CONSTANT);
|
||||||
|
nexp->mRight->mDecType = TheCharTypeDeclaration;
|
||||||
|
nexp->mRight->mDecValue = pthis->mBase->mVTable->mDefaultConstructor;
|
||||||
|
|
||||||
|
sexp->mRight = nexp;
|
||||||
|
cfunc->mValue = sexp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc)
|
void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc)
|
||||||
|
@ -1492,6 +1619,7 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc)
|
||||||
void Parser::AddDefaultConstructors(Declaration* pthis)
|
void Parser::AddDefaultConstructors(Declaration* pthis)
|
||||||
{
|
{
|
||||||
bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true;
|
bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true;
|
||||||
|
bool inlineConstructor = true;
|
||||||
|
|
||||||
char dname[100];
|
char dname[100];
|
||||||
strcpy_s(dname, "~");
|
strcpy_s(dname, "~");
|
||||||
|
@ -1537,7 +1665,11 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
|
||||||
if (bcdec->mBase->mDestructor)
|
if (bcdec->mBase->mDestructor)
|
||||||
simpleDestructor = false;
|
simpleDestructor = false;
|
||||||
if (bcdec->mBase->mDefaultConstructor)
|
if (bcdec->mBase->mDefaultConstructor)
|
||||||
|
{
|
||||||
simpleConstructor = false;
|
simpleConstructor = false;
|
||||||
|
if (!(bcdec->mBase->mDefaultConstructor->mBase->mFlags & DTF_REQUEST_INLINE))
|
||||||
|
inlineConstructor = false;
|
||||||
|
}
|
||||||
if (bcdec->mBase->mCopyConstructor)
|
if (bcdec->mBase->mCopyConstructor)
|
||||||
simpleCopy = false;
|
simpleCopy = false;
|
||||||
if (bcdec->mBase->mCopyAssignment)
|
if (bcdec->mBase->mCopyAssignment)
|
||||||
|
@ -1545,6 +1677,9 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
|
||||||
bcdec = bcdec->mNext;
|
bcdec = bcdec->mNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pthis->mBase->mVTable)
|
||||||
|
simpleConstructor = false;
|
||||||
|
|
||||||
Declaration* dec = pthis->mBase->mParams;
|
Declaration* dec = pthis->mBase->mParams;
|
||||||
while (dec)
|
while (dec)
|
||||||
{
|
{
|
||||||
|
@ -1561,7 +1696,11 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
|
||||||
if (bdec->mDestructor)
|
if (bdec->mDestructor)
|
||||||
simpleDestructor = false;
|
simpleDestructor = false;
|
||||||
if (bdec->mDefaultConstructor)
|
if (bdec->mDefaultConstructor)
|
||||||
|
{
|
||||||
simpleConstructor = false;
|
simpleConstructor = false;
|
||||||
|
if (!(bdec->mDefaultConstructor->mBase->mFlags & DTF_REQUEST_INLINE))
|
||||||
|
inlineConstructor = false;
|
||||||
|
}
|
||||||
if (bdec->mCopyConstructor)
|
if (bdec->mCopyConstructor)
|
||||||
simpleCopy = false;
|
simpleCopy = false;
|
||||||
if (bdec->mCopyAssignment)
|
if (bdec->mCopyAssignment)
|
||||||
|
@ -1616,6 +1755,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
|
||||||
{
|
{
|
||||||
Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION);
|
Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION);
|
||||||
ctdec->mSize = 0;
|
ctdec->mSize = 0;
|
||||||
|
|
||||||
Declaration* pdec = nullptr;
|
Declaration* pdec = nullptr;
|
||||||
ctdec->mBase = TheVoidTypeDeclaration;
|
ctdec->mBase = TheVoidTypeDeclaration;
|
||||||
ctdec->mFlags |= DTF_DEFINED;
|
ctdec->mFlags |= DTF_DEFINED;
|
||||||
|
@ -1626,6 +1766,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
|
||||||
cdec->mBase = ctdec;
|
cdec->mBase = ctdec;
|
||||||
|
|
||||||
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
||||||
|
if (inlineConstructor)
|
||||||
|
cdec->mFlags |= DTF_REQUEST_INLINE;
|
||||||
|
|
||||||
cdec->mSection = mCodeSection;
|
cdec->mSection = mCodeSection;
|
||||||
|
|
||||||
|
@ -2782,7 +2924,12 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (mScanner->mToken == TK_STATIC)
|
if (mScanner->mToken == TK_VIRTUAL)
|
||||||
|
{
|
||||||
|
storageFlags |= DTF_VIRTUAL;
|
||||||
|
mScanner->NextToken();
|
||||||
|
}
|
||||||
|
else if (mScanner->mToken == TK_STATIC)
|
||||||
{
|
{
|
||||||
storageFlags |= DTF_STATIC;
|
storageFlags |= DTF_STATIC;
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
|
@ -3120,7 +3267,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
||||||
}
|
}
|
||||||
|
|
||||||
if (npdec->mBase->mType == DT_TYPE_FUNCTION)
|
if (npdec->mBase->mType == DT_TYPE_FUNCTION)
|
||||||
npdec->mBase->mFlags |= storageFlags & (DTF_INTERRUPT | DTF_NATIVE | TK_FASTCALL);
|
npdec->mBase->mFlags |= storageFlags & (DTF_INTERRUPT | DTF_NATIVE | DTF_FASTCALL | DTF_VIRTUAL);
|
||||||
|
|
||||||
if (definingType)
|
if (definingType)
|
||||||
{
|
{
|
||||||
|
@ -3850,9 +3997,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
break;
|
break;
|
||||||
case TK_IDENT:
|
case TK_IDENT:
|
||||||
if (mThisPointer && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION))
|
if (mThisPointer && mThisPointer->mType == DT_ARGUMENT && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION))
|
||||||
{
|
{
|
||||||
dec = mThisPointer->mBase->mBase->mScope->Lookup(mScanner->mTokenIdent);
|
int offset;
|
||||||
|
uint64 flags;
|
||||||
|
|
||||||
|
dec = MemberLookup(mThisPointer->mBase->mBase, mScanner->mTokenIdent, offset, flags);
|
||||||
if (dec)
|
if (dec)
|
||||||
{
|
{
|
||||||
Expression * texp = new Expression(mScanner->mLocation, EX_VARIABLE);
|
Expression * texp = new Expression(mScanner->mLocation, EX_VARIABLE);
|
||||||
|
@ -4115,6 +4265,9 @@ Expression* Parser::ParseQualify(Expression* exp)
|
||||||
ResolveOverloadCall(nexp->mLeft, nexp->mRight);
|
ResolveOverloadCall(nexp->mLeft, nexp->mRight);
|
||||||
nexp->mDecType = nexp->mLeft->mDecType->mBase;
|
nexp->mDecType = nexp->mLeft->mDecType->mBase;
|
||||||
|
|
||||||
|
if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL)
|
||||||
|
nexp->mType = EX_VCALL;
|
||||||
|
|
||||||
exp = nexp;
|
exp = nexp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4408,6 +4561,9 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
|
||||||
ResolveOverloadCall(exp, nexp->mRight);
|
ResolveOverloadCall(exp, nexp->mRight);
|
||||||
nexp->mDecType = exp->mDecType->mBase;
|
nexp->mDecType = exp->mDecType->mBase;
|
||||||
|
|
||||||
|
if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL)
|
||||||
|
nexp->mType = EX_VCALL;
|
||||||
|
|
||||||
exp = nexp;
|
exp = nexp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4593,6 +4749,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
|
||||||
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||||
sexp->mLeft = iexp;
|
sexp->mLeft = iexp;
|
||||||
sexp->mRight = coexp;
|
sexp->mRight = coexp;
|
||||||
|
sexp->mDecType = coexp->mDecType;
|
||||||
|
|
||||||
nexp = sexp;
|
nexp = sexp;
|
||||||
}
|
}
|
||||||
|
@ -4653,6 +4810,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
|
||||||
|
|
||||||
sexp->mLeft = dexp;
|
sexp->mLeft = dexp;
|
||||||
sexp->mRight = vexp;
|
sexp->mRight = vexp;
|
||||||
|
sexp->mDecType = vexp->mDecType;
|
||||||
|
|
||||||
Expression * coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL);
|
Expression * coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL);
|
||||||
coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL);
|
coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL);
|
||||||
|
@ -4670,6 +4828,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
|
||||||
nexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
nexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||||
nexp->mLeft = iexp;
|
nexp->mLeft = iexp;
|
||||||
nexp->mRight = coexp;
|
nexp->mRight = coexp;
|
||||||
|
nexp->mDecType = coexp->mDecType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7337,6 +7496,10 @@ void Parser::ParsePragma(void)
|
||||||
mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE;
|
mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE;
|
||||||
else if (ConsumeIdentIf("maxinline"))
|
else if (ConsumeIdentIf("maxinline"))
|
||||||
mCompilerOptions |= COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL;
|
mCompilerOptions |= COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL;
|
||||||
|
else if (ConsumeIdentIf("constparams"))
|
||||||
|
mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS;
|
||||||
|
else if (ConsumeIdentIf("noconstparams"))
|
||||||
|
mCompilerOptions &= ~COPT_OPTIMIZE_CONST_PARAMS;
|
||||||
else
|
else
|
||||||
mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid option");
|
mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid option");
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,7 @@ const char* TokenNames[] =
|
||||||
"'private'",
|
"'private'",
|
||||||
"'new'",
|
"'new'",
|
||||||
"'delete'",
|
"'delete'",
|
||||||
|
"'virtual'",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1412,6 +1413,8 @@ void Scanner::NextRawToken(void)
|
||||||
mToken = TK_NEW;
|
mToken = TK_NEW;
|
||||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "delete"))
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "delete"))
|
||||||
mToken = TK_DELETE;
|
mToken = TK_DELETE;
|
||||||
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "virtual"))
|
||||||
|
mToken = TK_VIRTUAL;
|
||||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator"))
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator"))
|
||||||
{
|
{
|
||||||
NextRawToken();
|
NextRawToken();
|
||||||
|
|
|
@ -159,6 +159,7 @@ enum Token
|
||||||
TK_PRIVATE,
|
TK_PRIVATE,
|
||||||
TK_NEW,
|
TK_NEW,
|
||||||
TK_DELETE,
|
TK_DELETE,
|
||||||
|
TK_VIRTUAL,
|
||||||
|
|
||||||
NUM_TOKENS
|
NUM_TOKENS
|
||||||
};
|
};
|
||||||
|
|
|
@ -74,7 +74,7 @@ int main2(int argc, const char** argv)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
strcpy(strProductName, "oscar64");
|
strcpy(strProductName, "oscar64");
|
||||||
strcpy(strProductVersion, "1.21.209");
|
strcpy(strProductVersion, "1.22.210");
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
uint32_t length = sizeof(basePath);
|
uint32_t length = sizeof(basePath);
|
||||||
|
@ -202,6 +202,8 @@ int main2(int argc, const char** argv)
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE;
|
||||||
else if (arg[2] == 'z')
|
else if (arg[2] == 'z')
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_ZEROPAGE;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_ZEROPAGE;
|
||||||
|
else if (arg[2] == 'p')
|
||||||
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS;
|
||||||
}
|
}
|
||||||
else if (arg[1] == 'e')
|
else if (arg[1] == 'e')
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,21,209,0
|
FILEVERSION 1,22,210,0
|
||||||
PRODUCTVERSION 1,21,209,0
|
PRODUCTVERSION 1,22,210,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.21.209.0"
|
VALUE "FileVersion", "1.22.210.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.21.209.0"
|
VALUE "ProductVersion", "1.22.210.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -5296,15 +5296,15 @@
|
||||||
{
|
{
|
||||||
"Name" = "8:Microsoft Visual Studio"
|
"Name" = "8:Microsoft Visual Studio"
|
||||||
"ProductName" = "8:oscar64"
|
"ProductName" = "8:oscar64"
|
||||||
"ProductCode" = "8:{30BEED33-B5ED-4443-B82C-B365168D7780}"
|
"ProductCode" = "8:{9E7AB7F5-BA83-4377-B177-3D121EF176EB}"
|
||||||
"PackageCode" = "8:{46BC17E9-3B6D-4E1E-A1E7-42B0AD7512D8}"
|
"PackageCode" = "8:{2B7BCA1C-B5B7-47D2-8A8A-A8C694463BE0}"
|
||||||
"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.21.209"
|
"ProductVersion" = "8:1.22.210"
|
||||||
"Manufacturer" = "8:oscar64"
|
"Manufacturer" = "8:oscar64"
|
||||||
"ARPHELPTELEPHONE" = "8:"
|
"ARPHELPTELEPHONE" = "8:"
|
||||||
"ARPHELPLINK" = "8:"
|
"ARPHELPLINK" = "8:"
|
||||||
|
|
|
@ -100,7 +100,7 @@ __interrupt void setspr(void)
|
||||||
// Wait for end of current sprite, xpos will take effect
|
// Wait for end of current sprite, xpos will take effect
|
||||||
// at start of line, so we need to patch it after the last
|
// at start of line, so we need to patch it after the last
|
||||||
// pixel line has started
|
// pixel line has started
|
||||||
vic_waitLine(yoffset - 4);
|
vic_waitLine(yoffset - 3);
|
||||||
|
|
||||||
// Left to right or right to left to get a matching z order
|
// Left to right or right to left to get a matching z order
|
||||||
if (phase & 0x80)
|
if (phase & 0x80)
|
||||||
|
|
Loading…
Reference in New Issue