Added virtual functions
This commit is contained in:
parent
0b6a9c3584
commit
ed9aa3503b
|
@ -62,6 +62,7 @@ Supported Features:
|
|||
* single inheritance of class and struct
|
||||
* const member functions
|
||||
* new, delete, new[] and delete[]
|
||||
* virtual member functions
|
||||
|
||||
## 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)
|
||||
* -Oa : optimize inline assembler (part of O2/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
|
||||
* -tf : target format, may be prg, crt or bin
|
||||
* -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
|
||||
* autoinline : auto inline of small or only once used functions
|
||||
* maxinline : inline any function suitable
|
||||
* constparams : enable constant parameter folding into called functions
|
||||
* noconstparams : disable constant parameter folding into called functions
|
||||
* 0 : no optimization
|
||||
* 1 : default optimizations
|
||||
* 2 : aggressive optimizations
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
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
|
||||
@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);
|
||||
break;
|
||||
case IC_CALL:
|
||||
case IC_DISPATCH:
|
||||
CallFunction(iproc, ins);
|
||||
break;
|
||||
case IC_CALL_NATIVE:
|
||||
|
|
|
@ -14,6 +14,7 @@ CompilationUnits::CompilationUnits(Errors * errors)
|
|||
mPendingUnits = nullptr;
|
||||
mScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
||||
mRuntimeScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
||||
mVTableScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
||||
mStartup = nullptr;
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
CompilationUnits(Errors * errors);
|
||||
~CompilationUnits(void);
|
||||
|
||||
DeclarationScope* mScope;
|
||||
DeclarationScope* mScope, * mVTableScope;
|
||||
CompilationUnit* mCompilationUnits, * mPendingUnits;
|
||||
|
||||
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)
|
||||
{
|
||||
if (!proc->mCompiled)
|
||||
|
@ -591,6 +737,14 @@ bool Compiler::GenerateCode(void)
|
|||
|
||||
mGlobalAnalyzer->mCompilerOptions = mCompilerOptions;
|
||||
|
||||
if (mCompilerOptions & COPT_CPLUSPLUS)
|
||||
{
|
||||
if (mCompilerOptions & COPT_VERBOSE)
|
||||
printf("Build VTables\n");
|
||||
|
||||
BuildVTables();
|
||||
}
|
||||
|
||||
if (mCompilerOptions & COPT_VERBOSE)
|
||||
printf("Global analyzer\n");
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
void RegisterRuntime(const Location& loc, const Ident* ident);
|
||||
|
||||
void CompileProcedure(InterCodeProcedure* proc);
|
||||
void BuildVTables(void);
|
||||
|
||||
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_CONST_EXPRESSIONS = 1ULL << 7;
|
||||
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_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_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
|
||||
{
|
||||
|
|
|
@ -192,6 +192,12 @@ void Expression::Dump(int ident) const
|
|||
case EX_INLINE:
|
||||
printf("INLINE");
|
||||
break;
|
||||
case EX_VCALL:
|
||||
printf("VCALL");
|
||||
break;
|
||||
case EX_DISPATCH:
|
||||
printf("DISPATCH");
|
||||
break;
|
||||
case EX_LIST:
|
||||
printf("LIST");
|
||||
break;
|
||||
|
@ -788,6 +794,7 @@ Declaration::Declaration(const Location& loc, DecType type)
|
|||
mConst(nullptr), mMutable(nullptr),
|
||||
mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr),
|
||||
mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr),
|
||||
mVTable(nullptr),
|
||||
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),
|
||||
mCompilerOptions(0), mUseCount(0)
|
||||
|
@ -852,6 +859,7 @@ Declaration* Declaration::Clone(void)
|
|||
ndec->mLinkerObject = mLinkerObject;
|
||||
ndec->mAlignment = mAlignment;
|
||||
ndec->mSection = mSection;
|
||||
ndec->mVTable = mVTable;
|
||||
|
||||
return ndec;
|
||||
}
|
||||
|
@ -930,6 +938,10 @@ Declaration* Declaration::ToStriped(int stripe)
|
|||
p = p->mNext;
|
||||
}
|
||||
}
|
||||
else if (mType == DT_TYPE_FUNCTION)
|
||||
{
|
||||
ndec->mParams = mParams;
|
||||
}
|
||||
else if (mType == DT_TYPE_ARRAY)
|
||||
{
|
||||
ndec->mStride = stripe;
|
||||
|
@ -965,6 +977,7 @@ Declaration* Declaration::ToConstType(void)
|
|||
ndec->mCopyConstructor = mCopyConstructor;
|
||||
ndec->mVectorConstructor = mVectorConstructor;
|
||||
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
||||
ndec->mVTable = mVTable;
|
||||
|
||||
ndec->mMutable = this;
|
||||
mConst = ndec;
|
||||
|
@ -994,6 +1007,7 @@ Declaration* Declaration::ToMutableType(void)
|
|||
ndec->mCopyConstructor = mCopyConstructor;
|
||||
ndec->mVectorConstructor = mVectorConstructor;
|
||||
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
||||
ndec->mVTable = mVTable;
|
||||
|
||||
ndec->mConst = this;
|
||||
mMutable = ndec;
|
||||
|
@ -1011,7 +1025,7 @@ bool Declaration::IsSubType(const Declaration* dec) const
|
|||
if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -49,7 +49,9 @@ enum DecType
|
|||
DT_FUNCTION_REF,
|
||||
DT_LABEL_REF,
|
||||
DT_NAMESPACE,
|
||||
DT_BASECLASS
|
||||
DT_BASECLASS,
|
||||
|
||||
DT_VTABLE
|
||||
};
|
||||
|
||||
// TypeFlags
|
||||
|
@ -82,6 +84,7 @@ static const uint64 DTF_STRIPED = (1ULL << 24);
|
|||
static const uint64 DTF_DYNSTACK = (1ULL << 25);
|
||||
static const uint64 DTF_PRIVATE = (1ULL << 26);
|
||||
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_ASSEMBLER = (1ULL << 33);
|
||||
|
@ -129,6 +132,8 @@ public:
|
|||
|
||||
void UseScope(DeclarationScope* scope);
|
||||
|
||||
template<typename F> void Iterate(F && f);
|
||||
|
||||
ScopeLevel mLevel;
|
||||
const Ident * mName;
|
||||
|
||||
|
@ -144,6 +149,15 @@ protected:
|
|||
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
|
||||
{
|
||||
EX_ERROR,
|
||||
|
@ -162,6 +176,8 @@ enum ExpressionType
|
|||
EX_QUALIFY,
|
||||
EX_CALL,
|
||||
EX_INLINE,
|
||||
EX_VCALL,
|
||||
EX_DISPATCH,
|
||||
EX_LIST,
|
||||
EX_RETURN,
|
||||
EX_SEQUENCE,
|
||||
|
@ -227,6 +243,7 @@ public:
|
|||
Declaration * mBase, * mParams, * mNext, * mPrev, * mConst, * mMutable;
|
||||
Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment;
|
||||
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment;
|
||||
Declaration * mVTable, * mClass;
|
||||
|
||||
Expression* mValue;
|
||||
DeclarationScope* mScope;
|
||||
|
|
|
@ -656,6 +656,13 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
case EX_QUALIFY:
|
||||
Analyze(exp->mLeft, procDec, lhs);
|
||||
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_INLINE:
|
||||
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 1
|
||||
if (mCompilerOptions & COPT_OPTIMIZE_BASIC)
|
||||
if (mCompilerOptions & COPT_OPTIMIZE_CONST_PARAMS)
|
||||
{
|
||||
if (!(pdec->mFlags & DTF_FPARAM_NOCONST))
|
||||
{
|
||||
|
@ -922,6 +929,13 @@ void GlobalAnalyzer::RegisterProc(Declaration* to)
|
|||
{
|
||||
if (to->mType == DT_CONST_FUNCTION)
|
||||
{
|
||||
#if 0
|
||||
if (to->mBase->mFlags & DTF_VIRTUAL)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!(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
|
||||
{
|
||||
// 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;
|
||||
|
||||
// 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)
|
||||
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 true;
|
||||
|
@ -2945,6 +2945,7 @@ InterInstruction::InterInstruction(const Location& loc, InterCode code)
|
|||
case IC_RETURN_VALUE:
|
||||
case IC_RETURN_STRUCT:
|
||||
case IC_CONVERSION_OPERATOR:
|
||||
case IC_DISPATCH:
|
||||
mNumOperands = 1;
|
||||
break;
|
||||
|
||||
|
@ -3141,7 +3142,7 @@ void InterInstruction::FilterStaticVarsUsage(const GrowingVariableArray& staticV
|
|||
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);
|
||||
}
|
||||
|
@ -3509,7 +3510,7 @@ void InterInstruction::BuildCallerSaveTempSet(NumberSet& requiredTemps, NumberSe
|
|||
if (mDst.mTemp >= 0)
|
||||
requiredTemps -= mDst.mTemp;
|
||||
|
||||
if (mCode == IC_CALL || mCode == IC_CALL_NATIVE)
|
||||
if (mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_DISPATCH)
|
||||
callerSaveTemps |= requiredTemps;
|
||||
|
||||
for (int i = 0; i < mNumOperands; i++)
|
||||
|
@ -3700,7 +3701,7 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(InterCodeBasicBlock*
|
|||
requiredVars.Fill();
|
||||
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();
|
||||
storeIns.SetSize(0);
|
||||
|
@ -4322,6 +4323,9 @@ void InterInstruction::Disassemble(FILE* file)
|
|||
case IC_ASSEMBLER:
|
||||
fprintf(file, "JSR");
|
||||
break;
|
||||
case IC_DISPATCH:
|
||||
fprintf(file, "DISPATCH");
|
||||
break;
|
||||
case IC_RETURN_VALUE:
|
||||
assert(mNumOperands == 1);
|
||||
fprintf(file, "RETV");
|
||||
|
@ -9640,6 +9644,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray&
|
|||
{
|
||||
ins->mCode = IC_LOAD_TEMPORARY;
|
||||
ins->mSrc[0] = lins->mSrc[0];
|
||||
ins->mDst.mRange.Limit(ins->mSrc[0].mRange);
|
||||
ins->mNumOperands = 1;
|
||||
assert(ins->mSrc[0].mTemp >= 0);
|
||||
changed = true;
|
||||
|
@ -9702,6 +9707,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray&
|
|||
assert(lins->mDst.mTemp >= 0);
|
||||
ins->mCode = IC_LOAD_TEMPORARY;
|
||||
ins->mSrc[0] = lins->mDst;
|
||||
ins->mDst.mRange.Limit(ins->mSrc[0].mRange);
|
||||
ins->mNumOperands = 1;
|
||||
changed = true;
|
||||
}
|
||||
|
@ -10091,7 +10097,7 @@ bool InterCodeBasicBlock::CanMoveInstructionDown(int si, int ti) const
|
|||
|
||||
#if 1
|
||||
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;
|
||||
|
||||
for (int i = si + 1; i < ti; i++)
|
||||
|
@ -10153,7 +10159,7 @@ bool InterCodeBasicBlock::CanMoveInstructionBeforeBlock(int ii, const InterInstr
|
|||
|
||||
#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 ||
|
||||
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;
|
||||
|
||||
for (int i = 0; i < ii; i++)
|
||||
|
@ -10919,7 +10925,7 @@ bool InterCodeBasicBlock::IsLeafProcedure(void)
|
|||
mVisited = true;
|
||||
|
||||
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;
|
||||
|
||||
if (mTrueJump && !mTrueJump->IsLeafProcedure())
|
||||
|
@ -11080,6 +11086,8 @@ bool InterCodeBasicBlock::CheckStaticStack(void)
|
|||
else if (!(mInstructions[i]->mSrc[0].mLinkerObject->mFlags & LOBJF_STATIC_STACK))
|
||||
return false;
|
||||
}
|
||||
else if (mInstructions[i]->mCode == IC_DISPATCH)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mTrueJump && !mTrueJump->CheckStaticStack())
|
||||
|
@ -14899,7 +14907,7 @@ void InterCodeBasicBlock::CheckValueReturn(void)
|
|||
for (int i = 0; i < mInstructions.Size(); i++)
|
||||
{
|
||||
InterInstruction* ins = mInstructions[i];
|
||||
if (ins->mCode == IC_ASSEMBLER)
|
||||
if (ins->mCode == IC_ASSEMBLER || ins->mCode == IC_DISPATCH)
|
||||
return;
|
||||
else if (ins->mCode == IC_RETURN)
|
||||
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)
|
||||
{
|
||||
if (mNumEntries == 0)
|
||||
if (mNumEntries == 0 && mProc->mCheckUnreachable)
|
||||
{
|
||||
int i = 0;
|
||||
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),
|
||||
mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false),
|
||||
mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false),
|
||||
mCheckUnreachable(true),
|
||||
mDeclaration(nullptr)
|
||||
{
|
||||
mID = mModule->mProcedures.Size();
|
||||
|
@ -16106,7 +16115,7 @@ void InterCodeProcedure::Close(void)
|
|||
{
|
||||
GrowingTypeArray tstack(IT_NONE);
|
||||
|
||||
CheckFunc = !strcmp(mIdent->mString, "print");
|
||||
CheckFunc = !strcmp(mIdent->mString, "setspr");
|
||||
|
||||
mEntryBlock = mBlocks[0];
|
||||
|
||||
|
@ -16373,6 +16382,9 @@ void InterCodeProcedure::Close(void)
|
|||
|
||||
BuildDataFlowSets();
|
||||
|
||||
TempForwarding();
|
||||
RemoveUnusedInstructions();
|
||||
|
||||
#if 1
|
||||
ResetVisited();
|
||||
mEntryBlock->BuildLocalIntegerRangeSets(mTemporaries.Size(), mLocalVars, mParamVars);
|
||||
|
@ -16383,6 +16395,9 @@ void InterCodeProcedure::Close(void)
|
|||
ResetVisited();
|
||||
} while (mEntryBlock->BuildGlobalIntegerRangeSets(true, mLocalVars, mParamVars));
|
||||
|
||||
TempForwarding();
|
||||
RemoveUnusedInstructions();
|
||||
|
||||
do {
|
||||
DisassembleDebug("tq");
|
||||
|
||||
|
@ -16392,6 +16407,7 @@ void InterCodeProcedure::Close(void)
|
|||
|
||||
DisassembleDebug("Estimated value range");
|
||||
|
||||
|
||||
GrowingInstructionPtrArray pipa(nullptr);
|
||||
ResetVisited();
|
||||
mEntryBlock->LinkerObjectForwarding(pipa);
|
||||
|
|
|
@ -40,6 +40,7 @@ enum InterCode
|
|||
IC_ASSEMBLER,
|
||||
IC_JUMPF,
|
||||
IC_SELECT,
|
||||
IC_DISPATCH,
|
||||
IC_UNREACHABLE
|
||||
};
|
||||
|
||||
|
@ -588,6 +589,7 @@ public:
|
|||
int mTempSize, mCommonFrameSize, mCallerSavedTemps, mFreeCallerSavedTemps, mFastCallBase;
|
||||
bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure;
|
||||
bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack;
|
||||
bool mCheckUnreachable;
|
||||
GrowingInterCodeProcedurePtrArray mCalledFunctions;
|
||||
|
||||
InterCodeModule * mModule;
|
||||
|
|
|
@ -894,6 +894,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro
|
|||
Expression* fexp = fdec->mValue;
|
||||
Declaration* ftype = fdec->mBase;
|
||||
|
||||
proc->mCheckUnreachable = false;
|
||||
|
||||
InlineMapper nmapper;
|
||||
nmapper.mReturn = new InterCodeBasicBlock(proc);
|
||||
nmapper.mVarIndex = proc->mNumLocals;
|
||||
|
@ -1610,6 +1612,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
if (inlineMapper)
|
||||
ins->mConst.mVarIndex += inlineMapper->mVarIndex;
|
||||
InitLocalVariable(proc, dec, ins->mConst.mVarIndex);
|
||||
proc->mCheckUnreachable = false;
|
||||
}
|
||||
else if (inlineMapper)
|
||||
{
|
||||
|
@ -2665,6 +2668,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
return ExValue(TheBoolTypeDeclaration, ins->mDst.mTemp);
|
||||
}
|
||||
|
||||
case EX_VCALL:
|
||||
case EX_CALL:
|
||||
case EX_INLINE:
|
||||
{
|
||||
|
@ -2854,7 +2858,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
bool canInline = exp->mLeft->mType == EX_CONSTANT &&
|
||||
exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION &&
|
||||
(mCompilerOptions & COPT_OPTIMIZE_INLINE) &&
|
||||
!(inlineMapper && inlineMapper->mDepth > 10);
|
||||
!(inlineMapper && inlineMapper->mDepth > 10) &&
|
||||
exp->mType != EX_VCALL;
|
||||
bool doInline = false, inlineConstexpr = false;
|
||||
|
||||
if (canInline)
|
||||
|
@ -2902,7 +2907,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
}
|
||||
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);
|
||||
|
||||
int atotal = 0;
|
||||
|
@ -2992,8 +3000,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
atotal = 2;
|
||||
}
|
||||
|
||||
if (exp->mLeft->mDecValue && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION)
|
||||
proc->AddCalledFunction(proc->mModule->mProcedures[exp->mLeft->mDecValue->mVarIndex]);
|
||||
if (funcexp->mDecValue && funcexp->mDecValue->mType == DT_CONST_FUNCTION)
|
||||
proc->AddCalledFunction(proc->mModule->mProcedures[funcexp->mDecValue->mVarIndex]);
|
||||
else
|
||||
proc->CallsFunctionPointer();
|
||||
|
||||
|
@ -3187,15 +3195,15 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
block->Append(defins[i]);
|
||||
|
||||
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;
|
||||
else
|
||||
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;
|
||||
|
||||
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->mSrc[0].mType = IT_POINTER;
|
||||
|
@ -4059,6 +4067,30 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
|
||||
} 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:
|
||||
{
|
||||
DestructStack* odestack = destack;
|
||||
|
|
|
@ -27069,11 +27069,6 @@ bool NativeCodeBasicBlock::ReverseBitfieldForwarding(void)
|
|||
return changed;
|
||||
}
|
||||
|
||||
struct NativeCodeLoadStorePair
|
||||
{
|
||||
NativeCodeInstruction mLoad, mStore;
|
||||
};
|
||||
|
||||
bool NativeCodeBasicBlock::RemoveLocalUnusedLinkerObjects(void)
|
||||
{
|
||||
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;
|
||||
|
||||
|
@ -27133,6 +27128,8 @@ bool NativeCodeBasicBlock::AbsoluteValueForwarding(void)
|
|||
mVisited = true;
|
||||
|
||||
ExpandingArray<NativeCodeLoadStorePair> pairs;
|
||||
if (mNumEntries == 1)
|
||||
pairs = npairs;
|
||||
|
||||
int ains = -1;
|
||||
|
||||
|
@ -27205,9 +27202,9 @@ bool NativeCodeBasicBlock::AbsoluteValueForwarding(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (mTrueJump && mTrueJump->AbsoluteValueForwarding())
|
||||
if (mTrueJump && mTrueJump->AbsoluteValueForwarding(pairs))
|
||||
changed = true;
|
||||
if (mFalseJump && mFalseJump->AbsoluteValueForwarding())
|
||||
if (mFalseJump && mFalseJump->AbsoluteValueForwarding(pairs))
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
@ -28674,6 +28671,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
|
|||
mIns[1].mType = ASMIT_LDA; mIns[1].mLive |= LIVE_CPU_REG_A;
|
||||
mIns[0].mType = ASMIT_CMP; mIns[0].mLive |= LIVE_CPU_REG_Z;
|
||||
prevBlock->mIns.Push(mIns[1]);
|
||||
prevBlock->mExitRequiredRegs += CPU_REG_A;
|
||||
mEntryRequiredRegs += CPU_REG_A;
|
||||
mIns.Remove(1);
|
||||
|
||||
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 + 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 + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
|
||||
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 + 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 + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
|
||||
progress = true;
|
||||
|
@ -40878,7 +40877,8 @@ void NativeCodeProcedure::Optimize(void)
|
|||
if (step == 9)
|
||||
{
|
||||
ResetVisited();
|
||||
if (mEntryBlock->AbsoluteValueForwarding())
|
||||
ExpandingArray<NativeCodeLoadStorePair> pairs;
|
||||
if (mEntryBlock->AbsoluteValueForwarding(pairs))
|
||||
{
|
||||
changed = true;
|
||||
|
||||
|
@ -41889,6 +41889,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
|
|||
case IC_CONSTANT:
|
||||
block->LoadConstant(iproc, ins);
|
||||
break;
|
||||
case IC_DISPATCH:
|
||||
case IC_CALL:
|
||||
block->CallFunction(iproc, this, ins);
|
||||
break;
|
||||
|
|
|
@ -207,6 +207,12 @@ public:
|
|||
uint32 NeedsLive(void) const;
|
||||
};
|
||||
|
||||
struct NativeCodeLoadStorePair
|
||||
{
|
||||
NativeCodeInstruction mLoad, mStore;
|
||||
};
|
||||
|
||||
|
||||
class NativeCodeBasicBlock
|
||||
{
|
||||
public:
|
||||
|
@ -474,7 +480,7 @@ public:
|
|||
bool BitFieldForwarding(const NativeRegisterDataSet& data);
|
||||
bool ReverseBitfieldForwarding(void);
|
||||
bool OffsetValueForwarding(const ValueNumberingDataSet & data);
|
||||
bool AbsoluteValueForwarding(void);
|
||||
bool AbsoluteValueForwarding(const ExpandingArray<NativeCodeLoadStorePair>& npairs);
|
||||
|
||||
void MarkLocalUsedLinkerObjects(void);
|
||||
bool RemoveLocalUnusedLinkerObjects(void);
|
||||
|
|
|
@ -64,6 +64,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
|||
|
||||
Declaration * dec = new Declaration(mScanner->mLocation, dt);
|
||||
|
||||
bool needVTable = false;
|
||||
|
||||
mScanner->NextToken();
|
||||
if (mScanner->mToken == TK_IDENT)
|
||||
{
|
||||
|
@ -119,6 +121,9 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
|||
bcdec->mBase = pdec;
|
||||
bcdec->mFlags = pflags;
|
||||
|
||||
if (pdec->mVTable)
|
||||
needVTable = true;
|
||||
|
||||
dec->mSize = pdec->mSize;
|
||||
|
||||
dec->mBase = bcdec;
|
||||
|
@ -141,109 +146,205 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
|||
}
|
||||
|
||||
mScanner->NextToken();
|
||||
Declaration* mlast = nullptr;
|
||||
for (;;)
|
||||
if (ConsumeTokenIf(TK_CLOSE_BRACE))
|
||||
{
|
||||
if (ConsumeTokenIf(TK_PUBLIC))
|
||||
dec->mParams = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
Declaration* mlast = nullptr;
|
||||
for (;;)
|
||||
{
|
||||
flags &= ~(DTF_PRIVATE | DTF_PROTECTED);
|
||||
ConsumeToken(TK_COLON);
|
||||
}
|
||||
else if (ConsumeTokenIf(TK_PROTECTED))
|
||||
{
|
||||
flags &= ~DTF_PRIVATE;
|
||||
flags |= DTF_PROTECTED;
|
||||
ConsumeToken(TK_COLON);
|
||||
}
|
||||
else if (ConsumeTokenIf(TK_PRIVATE))
|
||||
{
|
||||
flags |= DTF_PRIVATE | DTF_PROTECTED;
|
||||
ConsumeToken(TK_COLON);
|
||||
}
|
||||
else
|
||||
{
|
||||
Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis);
|
||||
|
||||
mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED);
|
||||
|
||||
mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent);
|
||||
|
||||
int offset = dec->mSize;
|
||||
if (dt == DT_TYPE_UNION)
|
||||
offset = 0;
|
||||
|
||||
if (mdec->mBase->mType == DT_TYPE_FUNCTION)
|
||||
if (ConsumeTokenIf(TK_PUBLIC))
|
||||
{
|
||||
mdec->mType = DT_CONST_FUNCTION;
|
||||
mdec->mSection = mCodeSection;
|
||||
mdec->mFlags |= DTF_GLOBAL;
|
||||
mdec->mBase->mFlags |= DTF_FUNC_THIS;
|
||||
|
||||
if (mCompilerOptions & COPT_NATIVE)
|
||||
mdec->mFlags |= DTF_NATIVE;
|
||||
|
||||
if (!(mdec->mFlags & DTF_DEFINED))
|
||||
ConsumeToken(TK_SEMICOLON);
|
||||
|
||||
AddMemberFunction(dec, mdec);
|
||||
flags &= ~(DTF_PRIVATE | DTF_PROTECTED);
|
||||
ConsumeToken(TK_COLON);
|
||||
}
|
||||
else if (ConsumeTokenIf(TK_PROTECTED))
|
||||
{
|
||||
flags &= ~DTF_PRIVATE;
|
||||
flags |= DTF_PROTECTED;
|
||||
ConsumeToken(TK_COLON);
|
||||
}
|
||||
else if (ConsumeTokenIf(TK_PRIVATE))
|
||||
{
|
||||
flags |= DTF_PRIVATE | DTF_PROTECTED;
|
||||
ConsumeToken(TK_COLON);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (mdec)
|
||||
Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis);
|
||||
|
||||
mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED);
|
||||
|
||||
mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent);
|
||||
|
||||
int offset = dec->mSize;
|
||||
if (dt == DT_TYPE_UNION)
|
||||
offset = 0;
|
||||
|
||||
if (mdec->mBase->mType == DT_TYPE_FUNCTION)
|
||||
{
|
||||
if (!(mdec->mBase->mFlags & DTF_DEFINED))
|
||||
mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration");
|
||||
if (mdec->mBase->mFlags & DTF_VIRTUAL)
|
||||
needVTable = true;
|
||||
|
||||
if (mdec->mType != DT_VARIABLE)
|
||||
{
|
||||
mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected");
|
||||
break;
|
||||
}
|
||||
mdec->mType = DT_CONST_FUNCTION;
|
||||
mdec->mSection = mCodeSection;
|
||||
mdec->mFlags |= DTF_GLOBAL;
|
||||
mdec->mBase->mFlags |= DTF_FUNC_THIS;
|
||||
|
||||
mdec->mType = DT_ELEMENT;
|
||||
mdec->mOffset = offset;
|
||||
if (mCompilerOptions & COPT_NATIVE)
|
||||
mdec->mFlags |= DTF_NATIVE;
|
||||
|
||||
offset += mdec->mBase->mSize;
|
||||
if (offset > dec->mSize)
|
||||
dec->mSize = offset;
|
||||
if (!(mdec->mFlags & DTF_DEFINED))
|
||||
ConsumeToken(TK_SEMICOLON);
|
||||
|
||||
if (dec->mScope->Insert(mdec->mIdent, mdec))
|
||||
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent);
|
||||
|
||||
if (mlast)
|
||||
mlast->mNext = mdec;
|
||||
else
|
||||
dec->mParams = mdec;
|
||||
mlast = mdec;
|
||||
mdec = mdec->mNext;
|
||||
AddMemberFunction(dec, mdec);
|
||||
}
|
||||
|
||||
if (mScanner->mToken == TK_SEMICOLON)
|
||||
mScanner->NextToken();
|
||||
else
|
||||
{
|
||||
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected");
|
||||
while (mdec)
|
||||
{
|
||||
if (!(mdec->mBase->mFlags & DTF_DEFINED))
|
||||
mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration");
|
||||
|
||||
if (mdec->mType != DT_VARIABLE)
|
||||
{
|
||||
mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected");
|
||||
break;
|
||||
}
|
||||
|
||||
mdec->mType = DT_ELEMENT;
|
||||
mdec->mOffset = offset;
|
||||
|
||||
offset += mdec->mBase->mSize;
|
||||
if (offset > dec->mSize)
|
||||
dec->mSize = offset;
|
||||
|
||||
if (dec->mScope->Insert(mdec->mIdent, mdec))
|
||||
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent);
|
||||
|
||||
if (mlast)
|
||||
mlast->mNext = mdec;
|
||||
else
|
||||
dec->mParams = mdec;
|
||||
mlast = mdec;
|
||||
mdec = mdec->mNext;
|
||||
}
|
||||
|
||||
if (mScanner->mToken == TK_SEMICOLON)
|
||||
mScanner->NextToken();
|
||||
else
|
||||
{
|
||||
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mScanner->mToken == TK_CLOSE_BRACE)
|
||||
{
|
||||
mScanner->NextToken();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mScanner->mToken == TK_CLOSE_BRACE)
|
||||
{
|
||||
mScanner->NextToken();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mlast)
|
||||
mlast->mNext = nullptr;
|
||||
else
|
||||
dec->mParams = nullptr;
|
||||
if (mlast)
|
||||
mlast->mNext = nullptr;
|
||||
else
|
||||
dec->mParams = nullptr;
|
||||
}
|
||||
|
||||
dec->SetDefined();
|
||||
|
||||
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);
|
||||
|
||||
// Lookup constructors, have same name as class
|
||||
|
@ -256,6 +357,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
|||
}
|
||||
|
||||
AppendMemberDestructor(pthis);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1409,6 +1511,31 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc)
|
|||
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)
|
||||
|
@ -1492,6 +1619,7 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc)
|
|||
void Parser::AddDefaultConstructors(Declaration* pthis)
|
||||
{
|
||||
bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true;
|
||||
bool inlineConstructor = true;
|
||||
|
||||
char dname[100];
|
||||
strcpy_s(dname, "~");
|
||||
|
@ -1537,7 +1665,11 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
|
|||
if (bcdec->mBase->mDestructor)
|
||||
simpleDestructor = false;
|
||||
if (bcdec->mBase->mDefaultConstructor)
|
||||
{
|
||||
simpleConstructor = false;
|
||||
if (!(bcdec->mBase->mDefaultConstructor->mBase->mFlags & DTF_REQUEST_INLINE))
|
||||
inlineConstructor = false;
|
||||
}
|
||||
if (bcdec->mBase->mCopyConstructor)
|
||||
simpleCopy = false;
|
||||
if (bcdec->mBase->mCopyAssignment)
|
||||
|
@ -1545,6 +1677,9 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
|
|||
bcdec = bcdec->mNext;
|
||||
}
|
||||
|
||||
if (pthis->mBase->mVTable)
|
||||
simpleConstructor = false;
|
||||
|
||||
Declaration* dec = pthis->mBase->mParams;
|
||||
while (dec)
|
||||
{
|
||||
|
@ -1561,7 +1696,11 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
|
|||
if (bdec->mDestructor)
|
||||
simpleDestructor = false;
|
||||
if (bdec->mDefaultConstructor)
|
||||
{
|
||||
simpleConstructor = false;
|
||||
if (!(bdec->mDefaultConstructor->mBase->mFlags & DTF_REQUEST_INLINE))
|
||||
inlineConstructor = false;
|
||||
}
|
||||
if (bdec->mCopyConstructor)
|
||||
simpleCopy = false;
|
||||
if (bdec->mCopyAssignment)
|
||||
|
@ -1616,6 +1755,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
|
|||
{
|
||||
Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION);
|
||||
ctdec->mSize = 0;
|
||||
|
||||
Declaration* pdec = nullptr;
|
||||
ctdec->mBase = TheVoidTypeDeclaration;
|
||||
ctdec->mFlags |= DTF_DEFINED;
|
||||
|
@ -1626,6 +1766,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
|
|||
cdec->mBase = ctdec;
|
||||
|
||||
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
||||
if (inlineConstructor)
|
||||
cdec->mFlags |= DTF_REQUEST_INLINE;
|
||||
|
||||
cdec->mSection = mCodeSection;
|
||||
|
||||
|
@ -2782,7 +2924,12 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
|||
{
|
||||
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;
|
||||
mScanner->NextToken();
|
||||
|
@ -3120,7 +3267,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -3850,9 +3997,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
|
|||
mScanner->NextToken();
|
||||
break;
|
||||
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)
|
||||
{
|
||||
Expression * texp = new Expression(mScanner->mLocation, EX_VARIABLE);
|
||||
|
@ -4115,6 +4265,9 @@ Expression* Parser::ParseQualify(Expression* exp)
|
|||
ResolveOverloadCall(nexp->mLeft, nexp->mRight);
|
||||
nexp->mDecType = nexp->mLeft->mDecType->mBase;
|
||||
|
||||
if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL)
|
||||
nexp->mType = EX_VCALL;
|
||||
|
||||
exp = nexp;
|
||||
}
|
||||
}
|
||||
|
@ -4408,6 +4561,9 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
|
|||
ResolveOverloadCall(exp, nexp->mRight);
|
||||
nexp->mDecType = exp->mDecType->mBase;
|
||||
|
||||
if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL)
|
||||
nexp->mType = EX_VCALL;
|
||||
|
||||
exp = nexp;
|
||||
}
|
||||
}
|
||||
|
@ -4593,6 +4749,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
|
|||
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
sexp->mLeft = iexp;
|
||||
sexp->mRight = coexp;
|
||||
sexp->mDecType = coexp->mDecType;
|
||||
|
||||
nexp = sexp;
|
||||
}
|
||||
|
@ -4653,6 +4810,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
|
|||
|
||||
sexp->mLeft = dexp;
|
||||
sexp->mRight = vexp;
|
||||
sexp->mDecType = vexp->mDecType;
|
||||
|
||||
Expression * coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL);
|
||||
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->mLeft = iexp;
|
||||
nexp->mRight = coexp;
|
||||
nexp->mDecType = coexp->mDecType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7337,6 +7496,10 @@ void Parser::ParsePragma(void)
|
|||
mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE;
|
||||
else if (ConsumeIdentIf("maxinline"))
|
||||
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
|
||||
mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid option");
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ const char* TokenNames[] =
|
|||
"'private'",
|
||||
"'new'",
|
||||
"'delete'",
|
||||
"'virtual'",
|
||||
};
|
||||
|
||||
|
||||
|
@ -1412,6 +1413,8 @@ void Scanner::NextRawToken(void)
|
|||
mToken = TK_NEW;
|
||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "delete"))
|
||||
mToken = TK_DELETE;
|
||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "virtual"))
|
||||
mToken = TK_VIRTUAL;
|
||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator"))
|
||||
{
|
||||
NextRawToken();
|
||||
|
|
|
@ -159,6 +159,7 @@ enum Token
|
|||
TK_PRIVATE,
|
||||
TK_NEW,
|
||||
TK_DELETE,
|
||||
TK_VIRTUAL,
|
||||
|
||||
NUM_TOKENS
|
||||
};
|
||||
|
|
|
@ -74,7 +74,7 @@ int main2(int argc, const char** argv)
|
|||
|
||||
#else
|
||||
strcpy(strProductName, "oscar64");
|
||||
strcpy(strProductVersion, "1.21.209");
|
||||
strcpy(strProductVersion, "1.22.210");
|
||||
|
||||
#ifdef __APPLE__
|
||||
uint32_t length = sizeof(basePath);
|
||||
|
@ -202,6 +202,8 @@ int main2(int argc, const char** argv)
|
|||
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE;
|
||||
else if (arg[2] == 'z')
|
||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_ZEROPAGE;
|
||||
else if (arg[2] == 'p')
|
||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS;
|
||||
}
|
||||
else if (arg[1] == 'e')
|
||||
{
|
||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,21,209,0
|
||||
PRODUCTVERSION 1,21,209,0
|
||||
FILEVERSION 1,22,210,0
|
||||
PRODUCTVERSION 1,22,210,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -43,12 +43,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "oscar64"
|
||||
VALUE "FileDescription", "oscar64 compiler"
|
||||
VALUE "FileVersion", "1.21.209.0"
|
||||
VALUE "FileVersion", "1.22.210.0"
|
||||
VALUE "InternalName", "oscar64.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||
VALUE "OriginalFilename", "oscar64.exe"
|
||||
VALUE "ProductName", "oscar64"
|
||||
VALUE "ProductVersion", "1.21.209.0"
|
||||
VALUE "ProductVersion", "1.22.210.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -5296,15 +5296,15 @@
|
|||
{
|
||||
"Name" = "8:Microsoft Visual Studio"
|
||||
"ProductName" = "8:oscar64"
|
||||
"ProductCode" = "8:{30BEED33-B5ED-4443-B82C-B365168D7780}"
|
||||
"PackageCode" = "8:{46BC17E9-3B6D-4E1E-A1E7-42B0AD7512D8}"
|
||||
"ProductCode" = "8:{9E7AB7F5-BA83-4377-B177-3D121EF176EB}"
|
||||
"PackageCode" = "8:{2B7BCA1C-B5B7-47D2-8A8A-A8C694463BE0}"
|
||||
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
||||
"AspNetVersion" = "8:2.0.50727.0"
|
||||
"RestartWWWService" = "11:FALSE"
|
||||
"RemovePreviousVersions" = "11:TRUE"
|
||||
"DetectNewerInstalledVersion" = "11:TRUE"
|
||||
"InstallAllUsers" = "11:FALSE"
|
||||
"ProductVersion" = "8:1.21.209"
|
||||
"ProductVersion" = "8:1.22.210"
|
||||
"Manufacturer" = "8:oscar64"
|
||||
"ARPHELPTELEPHONE" = "8:"
|
||||
"ARPHELPLINK" = "8:"
|
||||
|
|
|
@ -100,7 +100,7 @@ __interrupt void setspr(void)
|
|||
// Wait for end of current sprite, xpos will take effect
|
||||
// at start of line, so we need to patch it after the last
|
||||
// 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
|
||||
if (phase & 0x80)
|
||||
|
|
Loading…
Reference in New Issue