Add global optimizer for parameter/return optimizations
This commit is contained in:
parent
c7f919e22e
commit
9d8c6991e8
|
@ -559,7 +559,11 @@ This sample fills a single screen column with a given color, by generating 25 as
|
||||||
|
|
||||||
This sample initially assigns the value 0 to the pre processor macro ry and increments it each time the loop body is replicated. The loop generates 25 copies of the body, each with a different value for ry.
|
This sample initially assigns the value 0 to the pre processor macro ry and increments it each time the loop body is replicated. The loop generates 25 copies of the body, each with a different value for ry.
|
||||||
|
|
||||||
A simpler loop with only a single line template expansion is provided with the #for(iterator, count) preprocessor command:
|
A simpler loop with only a single line template expansion is provided with the for preprocessor command:
|
||||||
|
|
||||||
|
#for(<iterator>, <count>) <text>
|
||||||
|
|
||||||
|
This sample generates an array with pointers to screen rows:
|
||||||
|
|
||||||
char * const ScreenRows2[] = {
|
char * const ScreenRows2[] = {
|
||||||
#for(i,SCREEN_HEIGHT) Screen + SCREEN_WIDTH * i,
|
#for(i,SCREEN_HEIGHT) Screen + SCREEN_WIDTH * i,
|
||||||
|
|
|
@ -9,7 +9,7 @@ class ios
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ios(void);
|
constexpr ios(void);
|
||||||
virtual ~ios(void);
|
virtual ~ios(void);
|
||||||
|
|
||||||
char fill() const;
|
char fill() const;
|
||||||
|
@ -85,7 +85,7 @@ typedef ostream & (* manip)(ostream &);
|
||||||
class ostream : public ios
|
class ostream : public ios
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ostream(void);
|
constexpr ostream(void);
|
||||||
|
|
||||||
ostream & put(char c);
|
ostream & put(char c);
|
||||||
ostream & write(const char * s, int n);
|
ostream & write(const char * s, int n);
|
||||||
|
@ -150,7 +150,7 @@ protected:
|
||||||
class costream : public ostream
|
class costream : public ostream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
costream(void);
|
constexpr costream(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void bput(char ch);
|
void bput(char ch);
|
||||||
|
|
|
@ -33,6 +33,7 @@ Compiler::Compiler(void)
|
||||||
mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker, mCompilationUnits->mSectionCode);
|
mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker, mCompilationUnits->mSectionCode);
|
||||||
mInterCodeModule = new InterCodeModule(mErrors, mLinker);
|
mInterCodeModule = new InterCodeModule(mErrors, mLinker);
|
||||||
mGlobalAnalyzer = new GlobalAnalyzer(mErrors, mLinker);
|
mGlobalAnalyzer = new GlobalAnalyzer(mErrors, mLinker);
|
||||||
|
mGlobalOptimizer = new GlobalOptimizer(mErrors, mLinker);
|
||||||
|
|
||||||
mCartridgeID = 0x0000;
|
mCartridgeID = 0x0000;
|
||||||
}
|
}
|
||||||
|
@ -835,8 +836,6 @@ bool Compiler::GenerateCode(void)
|
||||||
|
|
||||||
dcrtstart->mSection = sectionStartup;
|
dcrtstart->mSection = sectionStartup;
|
||||||
|
|
||||||
mGlobalAnalyzer->mCompilerOptions = mCompilerOptions;
|
|
||||||
|
|
||||||
if (mCompilerOptions & COPT_CPLUSPLUS)
|
if (mCompilerOptions & COPT_CPLUSPLUS)
|
||||||
{
|
{
|
||||||
if (mCompilerOptions & COPT_VERBOSE)
|
if (mCompilerOptions & COPT_VERBOSE)
|
||||||
|
@ -845,6 +844,32 @@ bool Compiler::GenerateCode(void)
|
||||||
BuildVTables();
|
BuildVTables();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mCompilerOptions & COPT_OPTIMIZE_GLOBAL)
|
||||||
|
{
|
||||||
|
mGlobalOptimizer->mCompilerOptions = mCompilerOptions;
|
||||||
|
|
||||||
|
if (mCompilerOptions & COPT_VERBOSE)
|
||||||
|
printf("Global optimizer\n");
|
||||||
|
|
||||||
|
do {
|
||||||
|
mGlobalOptimizer->Reset();
|
||||||
|
|
||||||
|
mGlobalOptimizer->AnalyzeAssembler(dcrtstart->mValue, nullptr);
|
||||||
|
|
||||||
|
for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++)
|
||||||
|
{
|
||||||
|
Declaration* dec = mCompilationUnits->mReferenced[i];
|
||||||
|
if (dec->mType == DT_CONST_FUNCTION)
|
||||||
|
mGlobalOptimizer->AnalyzeProcedure(dec->mValue, dec);
|
||||||
|
else
|
||||||
|
mGlobalOptimizer->AnalyzeGlobalVariable(dec);
|
||||||
|
}
|
||||||
|
} while (mGlobalOptimizer->Optimize());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mGlobalAnalyzer->mCompilerOptions = mCompilerOptions;
|
||||||
|
|
||||||
if (mCompilerOptions & COPT_VERBOSE)
|
if (mCompilerOptions & COPT_VERBOSE)
|
||||||
printf("Global analyzer\n");
|
printf("Global analyzer\n");
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "NativeCodeGenerator.h"
|
#include "NativeCodeGenerator.h"
|
||||||
#include "InterCodeGenerator.h"
|
#include "InterCodeGenerator.h"
|
||||||
#include "GlobalAnalyzer.h"
|
#include "GlobalAnalyzer.h"
|
||||||
|
#include "GlobalOptimizer.h"
|
||||||
#include "Linker.h"
|
#include "Linker.h"
|
||||||
#include "CompilerTypes.h"
|
#include "CompilerTypes.h"
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ public:
|
||||||
InterCodeGenerator* mInterCodeGenerator;
|
InterCodeGenerator* mInterCodeGenerator;
|
||||||
InterCodeModule* mInterCodeModule;
|
InterCodeModule* mInterCodeModule;
|
||||||
GlobalAnalyzer* mGlobalAnalyzer;
|
GlobalAnalyzer* mGlobalAnalyzer;
|
||||||
|
GlobalOptimizer* mGlobalOptimizer;
|
||||||
|
|
||||||
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
|
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
|
||||||
ExpandingArray<NativeCodeProcedure*> mNativeProcedures;
|
ExpandingArray<NativeCodeProcedure*> mNativeProcedures;
|
||||||
|
|
|
@ -13,6 +13,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_CONST_PARAMS = 1ULL << 9;
|
||||||
static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10;
|
static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10;
|
||||||
|
static const uint64 COPT_OPTIMIZE_GLOBAL = 1ULL << 11;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_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;
|
||||||
|
@ -44,11 +45,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 | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS;
|
static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS;
|
static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_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 | COPT_OPTIMIZE_MERGE_CALLS;
|
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 | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;
|
||||||
|
|
||||||
enum TargetMachine
|
enum TargetMachine
|
||||||
{
|
{
|
||||||
|
|
|
@ -434,6 +434,7 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
|
||||||
{
|
{
|
||||||
case DT_TYPE_INTEGER:
|
case DT_TYPE_INTEGER:
|
||||||
case DT_TYPE_BOOL:
|
case DT_TYPE_BOOL:
|
||||||
|
case DT_TYPE_ENUM:
|
||||||
dec = new Declaration(mLocation, DT_CONST_INTEGER);
|
dec = new Declaration(mLocation, DT_CONST_INTEGER);
|
||||||
dec->mBase = type;
|
dec->mBase = type;
|
||||||
dec->mFlags = type->mFlags & DTF_SIGNED;
|
dec->mFlags = type->mFlags & DTF_SIGNED;
|
||||||
|
@ -454,20 +455,25 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
|
||||||
dec->mSection = dataSection;
|
dec->mSection = dataSection;
|
||||||
dec->mOffset = offset;
|
dec->mOffset = offset;
|
||||||
|
|
||||||
Declaration* ldec = nullptr;
|
|
||||||
while (type)
|
while (type)
|
||||||
{
|
{
|
||||||
for (Declaration* mdec = type->mParams; mdec; mdec = mdec->mNext)
|
for (Declaration* mdec = type->mParams; mdec; mdec = mdec->mNext)
|
||||||
{
|
{
|
||||||
Declaration* cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection);
|
Declaration* cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection);
|
||||||
cdec->mOffset = mdec->mOffset;
|
cdec->mOffset = mdec->mOffset;
|
||||||
|
cdec->mNext = dec->mParams;
|
||||||
if (ldec)
|
|
||||||
ldec->mNext = cdec;
|
|
||||||
else
|
|
||||||
dec->mParams = cdec;
|
dec->mParams = cdec;
|
||||||
|
}
|
||||||
|
|
||||||
ldec = cdec;
|
if (type->mVTable)
|
||||||
|
{
|
||||||
|
Declaration * cdec = new Declaration(mLocation, DT_CONST_INTEGER);
|
||||||
|
cdec->mBase = TheConstCharTypeDeclaration;
|
||||||
|
cdec->mSize = 1;
|
||||||
|
cdec->mInteger = type->mVTable->mDefaultConstructor->mInteger;
|
||||||
|
cdec->mOffset = offset + type->mVTable->mOffset;
|
||||||
|
cdec->mNext = dec->mParams;
|
||||||
|
dec->mParams = cdec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type->mBase)
|
if (type->mBase)
|
||||||
|
@ -587,6 +593,29 @@ void ConstexprInterpreter::DeleteValue(Value* v)
|
||||||
mErrors->Error(v->mLocation, EERR_DOUBLE_FREE, "Freeing not allocated memory");
|
mErrors->Error(v->mLocation, EERR_DOUBLE_FREE, "Freeing not allocated memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expression* ConstexprInterpreter::EvalConstructor(Expression* exp)
|
||||||
|
{
|
||||||
|
mProcType = exp->mLeft->mDecType;
|
||||||
|
|
||||||
|
Declaration* cdec = exp->mLeft->mDecType->mParams;
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
mResult = Value(exp->mLocation, cdec->mBase->mBase);
|
||||||
|
mParams[pos] = Value(exp->mLocation, cdec->mBase);
|
||||||
|
mParams[pos].PutPtr(Value(&mResult));
|
||||||
|
pos = 2;
|
||||||
|
|
||||||
|
mHeap = new ExpandingArray<Value*>();
|
||||||
|
|
||||||
|
Execute(exp->mLeft->mDecValue->mValue);
|
||||||
|
|
||||||
|
if (mHeap->Size() > 0)
|
||||||
|
mErrors->Error(exp->mLocation, EERR_UNBALANCED_HEAP_USE, "Unbalanced heap use in constexpr");
|
||||||
|
delete mHeap;
|
||||||
|
|
||||||
|
return mResult.ToExpression(mDataSection);
|
||||||
|
}
|
||||||
|
|
||||||
Expression* ConstexprInterpreter::EvalCall(Expression* exp)
|
Expression* ConstexprInterpreter::EvalCall(Expression* exp)
|
||||||
{
|
{
|
||||||
mProcType = exp->mLeft->mDecType;
|
mProcType = exp->mLeft->mDecType;
|
||||||
|
@ -1118,6 +1147,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
|
||||||
}
|
}
|
||||||
|
|
||||||
case EX_LIST:
|
case EX_LIST:
|
||||||
|
case EX_COMMA:
|
||||||
Eval(exp->mLeft);
|
Eval(exp->mLeft);
|
||||||
return Eval(exp->mRight);
|
return Eval(exp->mRight);
|
||||||
|
|
||||||
|
@ -1191,6 +1221,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
|
||||||
Value v = Eval(exp->mLeft);
|
Value v = Eval(exp->mLeft);
|
||||||
if (v.mBaseValue)
|
if (v.mBaseValue)
|
||||||
return Value(exp->mLocation, v.mBaseValue, exp->mDecType, v.mOffset + exp->mDecValue->mOffset);
|
return Value(exp->mLocation, v.mBaseValue, exp->mDecType, v.mOffset + exp->mDecValue->mOffset);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EX_INDEX:
|
case EX_INDEX:
|
||||||
|
@ -1208,6 +1239,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
|
||||||
Value p = v.GetPtr();
|
Value p = v.GetPtr();
|
||||||
return Value(exp->mLocation, p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt()));
|
return Value(exp->mLocation, p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt()));
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EX_RESULT:
|
case EX_RESULT:
|
||||||
|
@ -1256,6 +1288,7 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp)
|
||||||
case EX_PREFIX:
|
case EX_PREFIX:
|
||||||
case EX_TYPECAST:
|
case EX_TYPECAST:
|
||||||
case EX_CALL:
|
case EX_CALL:
|
||||||
|
case EX_COMMA:
|
||||||
case EX_LIST:
|
case EX_LIST:
|
||||||
case EX_CONDITIONAL:
|
case EX_CONDITIONAL:
|
||||||
case EX_LOGICAL_AND:
|
case EX_LOGICAL_AND:
|
||||||
|
|
|
@ -9,6 +9,7 @@ public:
|
||||||
~ConstexprInterpreter(void);
|
~ConstexprInterpreter(void);
|
||||||
|
|
||||||
Expression* EvalCall(Expression* exp);
|
Expression* EvalCall(Expression* exp);
|
||||||
|
Expression* EvalConstructor(Expression* exp);
|
||||||
protected:
|
protected:
|
||||||
struct Value;
|
struct Value;
|
||||||
|
|
||||||
|
|
|
@ -222,6 +222,9 @@ void Expression::Dump(int ident) const
|
||||||
case EX_LIST:
|
case EX_LIST:
|
||||||
printf("LIST");
|
printf("LIST");
|
||||||
break;
|
break;
|
||||||
|
case EX_COMMA:
|
||||||
|
printf("COMMA");
|
||||||
|
break;
|
||||||
case EX_RETURN:
|
case EX_RETURN:
|
||||||
printf("RETURN");
|
printf("RETURN");
|
||||||
break;
|
break;
|
||||||
|
@ -523,6 +526,10 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
ex->mDecType = mDecType;
|
ex->mDecType = mDecType;
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
|
else if (mType == EX_PREFIX && mToken == TK_BINARY_AND && mLeft->mType == EX_PREFIX && mLeft->mToken == TK_MUL)
|
||||||
|
{
|
||||||
|
return mLeft->mLeft;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (mType == EX_TYPECAST && mLeft->mType == EX_CONSTANT)
|
else if (mType == EX_TYPECAST && mLeft->mType == EX_CONSTANT)
|
||||||
{
|
{
|
||||||
|
@ -888,7 +895,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_CONSTEXPR))
|
else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_CONSTEXPR) && dataSection)
|
||||||
{
|
{
|
||||||
ConstexprInterpreter cinter(mLocation, errors, dataSection);
|
ConstexprInterpreter cinter(mLocation, errors, dataSection);
|
||||||
return cinter.EvalCall(this);
|
return cinter.EvalCall(this);
|
||||||
|
@ -900,7 +907,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
Declaration::Declaration(const Location& loc, DecType type)
|
Declaration::Declaration(const Location& loc, DecType type)
|
||||||
: mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mMangleIdent(nullptr),
|
: mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mMangleIdent(nullptr),
|
||||||
mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mNumVars(0),
|
mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mNumVars(0),
|
||||||
mBase(nullptr), mParams(nullptr), mParamPack(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr),
|
mBase(nullptr), mParams(nullptr), mParamPack(nullptr), mValue(nullptr), mReturn(nullptr), mNext(nullptr), mPrev(nullptr),
|
||||||
mConst(nullptr), mMutable(nullptr),
|
mConst(nullptr), mMutable(nullptr),
|
||||||
mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr),
|
mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr),
|
||||||
mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr),
|
mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr),
|
||||||
|
@ -908,7 +915,7 @@ Declaration::Declaration(const Location& loc, DecType type)
|
||||||
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr),
|
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr),
|
||||||
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), mTokens(nullptr), mParser(nullptr),
|
mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr),
|
||||||
mShift(0), mBits(0)
|
mShift(0), mBits(0), mOptFlags(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Declaration::~Declaration(void)
|
Declaration::~Declaration(void)
|
||||||
|
@ -960,6 +967,71 @@ Declaration* Declaration::BuildArrayPointer(void)
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Declaration* Declaration::ConstCast(Declaration* ntype)
|
||||||
|
{
|
||||||
|
if (ntype == mBase)
|
||||||
|
return this;
|
||||||
|
else if (ntype->mType == DT_TYPE_POINTER)
|
||||||
|
{
|
||||||
|
if (mBase->mType == DT_TYPE_POINTER)
|
||||||
|
{
|
||||||
|
if (mBase->mBase->IsSame(ntype->mBase))
|
||||||
|
return this;
|
||||||
|
|
||||||
|
Declaration* pdec = this->Clone();
|
||||||
|
pdec->mBase = ntype;
|
||||||
|
return pdec;
|
||||||
|
}
|
||||||
|
else if (mType == DT_TYPE_INTEGER)
|
||||||
|
{
|
||||||
|
Declaration* pdec = this->Clone();
|
||||||
|
pdec->mType = DT_CONST_ADDRESS;
|
||||||
|
pdec->mBase = ntype;
|
||||||
|
pdec->mSize = 2;
|
||||||
|
return pdec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
else if (ntype->mType == DT_TYPE_INTEGER || ntype->mType == DT_TYPE_BOOL || ntype->mType == DT_TYPE_ENUM)
|
||||||
|
{
|
||||||
|
if (mType == DT_TYPE_FLOAT)
|
||||||
|
{
|
||||||
|
Declaration* pdec = this->Clone();
|
||||||
|
pdec->mInteger = int64(mNumber);
|
||||||
|
pdec->mBase = ntype;
|
||||||
|
pdec->mSize = ntype->mSize;
|
||||||
|
return pdec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Declaration* pdec = this->Clone();
|
||||||
|
pdec->mBase = ntype;
|
||||||
|
pdec->mSize = ntype->mSize;
|
||||||
|
return pdec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ntype->mType == DT_TYPE_FLOAT)
|
||||||
|
{
|
||||||
|
if (mType == DT_TYPE_FLOAT)
|
||||||
|
{
|
||||||
|
Declaration* pdec = this->Clone();
|
||||||
|
pdec->mBase = ntype;
|
||||||
|
return pdec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Declaration* pdec = this->Clone();
|
||||||
|
pdec->mNumber = float(mInteger);
|
||||||
|
pdec->mBase = ntype;
|
||||||
|
pdec->mSize = ntype->mSize;
|
||||||
|
return pdec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
Declaration* Declaration::BuildPointer(const Location& loc)
|
Declaration* Declaration::BuildPointer(const Location& loc)
|
||||||
{
|
{
|
||||||
Declaration* pdec = new Declaration(loc, DT_TYPE_POINTER);
|
Declaration* pdec = new Declaration(loc, DT_TYPE_POINTER);
|
||||||
|
@ -2263,6 +2335,7 @@ Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheConstVoidPo
|
||||||
Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration;
|
Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration;
|
||||||
Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration;
|
Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration;
|
||||||
Expression* TheVoidExpression;
|
Expression* TheVoidExpression;
|
||||||
|
Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration;
|
||||||
|
|
||||||
void InitDeclarations(void)
|
void InitDeclarations(void)
|
||||||
{
|
{
|
||||||
|
@ -2345,4 +2418,16 @@ void InitDeclarations(void)
|
||||||
TheVoidExpression = new Expression(noloc, EX_CONSTANT);
|
TheVoidExpression = new Expression(noloc, EX_CONSTANT);
|
||||||
TheVoidExpression->mDecType = TheConstVoidTypeDeclaration;
|
TheVoidExpression->mDecType = TheConstVoidTypeDeclaration;
|
||||||
TheVoidExpression->mDecValue = TheConstVoidValueDeclaration;
|
TheVoidExpression->mDecValue = TheConstVoidValueDeclaration;
|
||||||
|
|
||||||
|
|
||||||
|
TheNullptrConstDeclaration = new Declaration(noloc, DT_CONST_ADDRESS);
|
||||||
|
TheNullptrConstDeclaration->mBase = TheVoidPointerTypeDeclaration;
|
||||||
|
TheNullptrConstDeclaration->mSize = 2;
|
||||||
|
TheZeroIntegerConstDeclaration = new Declaration(noloc, DT_CONST_INTEGER);
|
||||||
|
TheZeroIntegerConstDeclaration->mBase = TheSignedIntTypeDeclaration;
|
||||||
|
TheZeroIntegerConstDeclaration->mSize = 2;
|
||||||
|
TheZeroFloatConstDeclaration = new Declaration(noloc, DT_CONST_FLOAT);
|
||||||
|
TheZeroFloatConstDeclaration->mBase = TheFloatTypeDeclaration;
|
||||||
|
TheZeroFloatConstDeclaration->mSize = 4;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,7 @@ static const uint64 DTF_VAR_ADDRESS = (1ULL << 46);
|
||||||
static const uint64 DTF_FUNC_THIS = (1ULL << 47);
|
static const uint64 DTF_FUNC_THIS = (1ULL << 47);
|
||||||
|
|
||||||
static const uint64 DTF_VAR_ALIASING = (1ULL << 48);
|
static const uint64 DTF_VAR_ALIASING = (1ULL << 48);
|
||||||
|
static const uint64 DTF_FPARAM_UNUSED = (1ULL << 49);
|
||||||
|
|
||||||
|
|
||||||
class Declaration;
|
class Declaration;
|
||||||
|
@ -196,6 +197,7 @@ enum ExpressionType
|
||||||
EX_VCALL,
|
EX_VCALL,
|
||||||
EX_DISPATCH,
|
EX_DISPATCH,
|
||||||
EX_LIST,
|
EX_LIST,
|
||||||
|
EX_COMMA,
|
||||||
EX_RETURN,
|
EX_RETURN,
|
||||||
EX_SEQUENCE,
|
EX_SEQUENCE,
|
||||||
EX_WHILE,
|
EX_WHILE,
|
||||||
|
@ -267,13 +269,13 @@ public:
|
||||||
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment;
|
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment;
|
||||||
Declaration * mVTable, * mClass, * mTemplate;
|
Declaration * mVTable, * mClass, * mTemplate;
|
||||||
|
|
||||||
Expression* mValue;
|
Expression* mValue, * mReturn;
|
||||||
DeclarationScope* mScope;
|
DeclarationScope* mScope;
|
||||||
int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe;
|
int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe;
|
||||||
uint8 mShift, mBits;
|
uint8 mShift, mBits;
|
||||||
int64 mInteger, mMinValue, mMaxValue;
|
int64 mInteger, mMinValue, mMaxValue;
|
||||||
double mNumber;
|
double mNumber;
|
||||||
uint64 mFlags, mCompilerOptions;
|
uint64 mFlags, mCompilerOptions, mOptFlags;
|
||||||
const Ident * mIdent, * mQualIdent, * mMangleIdent;
|
const Ident * mIdent, * mQualIdent, * mMangleIdent;
|
||||||
LinkerSection * mSection;
|
LinkerSection * mSection;
|
||||||
const uint8 * mData;
|
const uint8 * mData;
|
||||||
|
@ -322,6 +324,7 @@ public:
|
||||||
Declaration* NonRefBase(void);
|
Declaration* NonRefBase(void);
|
||||||
Declaration* BuildArrayPointer(void);
|
Declaration* BuildArrayPointer(void);
|
||||||
Declaration* DeduceAuto(Declaration* dec);
|
Declaration* DeduceAuto(Declaration* dec);
|
||||||
|
Declaration* ConstCast(Declaration* ntype);
|
||||||
bool IsAuto(void) const;
|
bool IsAuto(void) const;
|
||||||
|
|
||||||
DecType ValueType(void) const;
|
DecType ValueType(void) const;
|
||||||
|
@ -343,5 +346,6 @@ extern Declaration* TheVoidTypeDeclaration, * TheConstVoidTypeDeclaration, * The
|
||||||
extern Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheConstVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration;
|
extern Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheConstVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration;
|
||||||
extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration;
|
extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration;
|
||||||
extern Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration;
|
extern Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration;
|
||||||
|
extern Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration;
|
||||||
extern Expression* TheVoidExpression;
|
extern Expression* TheVoidExpression;
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,8 @@ void GlobalAnalyzer::AutoInline(void)
|
||||||
{
|
{
|
||||||
if (pdec->mFlags & DTF_FPARAM_CONST)
|
if (pdec->mFlags & DTF_FPARAM_CONST)
|
||||||
{
|
{
|
||||||
|
pdec->mFlags |= DTF_FPARAM_UNUSED;
|
||||||
|
|
||||||
pdec->mVarIndex = dec->mNumVars++;
|
pdec->mVarIndex = dec->mNumVars++;
|
||||||
|
|
||||||
Expression* aexp = new Expression(pdec->mLocation, EX_INITIALIZATION);
|
Expression* aexp = new Expression(pdec->mLocation, EX_INITIALIZATION);
|
||||||
|
@ -897,6 +899,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EX_LIST:
|
case EX_LIST:
|
||||||
|
case EX_COMMA:
|
||||||
RegisterProc(Analyze(exp->mLeft, procDec, false));
|
RegisterProc(Analyze(exp->mLeft, procDec, false));
|
||||||
return Analyze(exp->mRight, procDec, false);
|
return Analyze(exp->mRight, procDec, false);
|
||||||
case EX_RETURN:
|
case EX_RETURN:
|
||||||
|
|
|
@ -0,0 +1,925 @@
|
||||||
|
#include "GlobalOptimizer.h"
|
||||||
|
#include "Constexpr.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DUMP_OPTS 0
|
||||||
|
|
||||||
|
|
||||||
|
static const uint64 OPTF_ANALYZED = (1ULL << 0);
|
||||||
|
static const uint64 OPTF_ANALYZING = (1ULL << 1);
|
||||||
|
static const uint64 OPTF_RECURSIVE = (1ULL << 2);
|
||||||
|
static const uint64 OPTF_FUNC_VARIABLE = (1ULL << 3);
|
||||||
|
static const uint64 OPTF_CALLED = (1ULL << 4);
|
||||||
|
static const uint64 OPTF_CALLING = (1ULL << 5);
|
||||||
|
static const uint64 OPTF_VAR_MODIFIED = (1ULL << 6);
|
||||||
|
static const uint64 OPTF_VAR_ADDRESS = (1ULL << 7);
|
||||||
|
static const uint64 OPTF_VAR_USED = (1ULL << 8);
|
||||||
|
static const uint64 OPTF_VAR_CONST = (1ULL << 9);
|
||||||
|
static const uint64 OPTF_VAR_NOCONST = (1ULL << 10);
|
||||||
|
static const uint64 OPTF_SINGLE_RETURN = (1ULL << 11);
|
||||||
|
static const uint64 OPTF_MULTI_RETURN = (1ULL << 12);
|
||||||
|
|
||||||
|
|
||||||
|
GlobalOptimizer::GlobalOptimizer(Errors* errors, Linker* linker)
|
||||||
|
: mErrors(errors), mLinker(linker)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalOptimizer::~GlobalOptimizer(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalOptimizer::Reset(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mFunctions.Size(); i++)
|
||||||
|
{
|
||||||
|
Declaration* func = mFunctions[i];
|
||||||
|
Declaration* ftype = func->mBase;
|
||||||
|
func->mOptFlags = 0;
|
||||||
|
ftype->mOptFlags = 0;
|
||||||
|
func->mReturn = nullptr;
|
||||||
|
|
||||||
|
Declaration* pdec = ftype->mParams;
|
||||||
|
while (pdec)
|
||||||
|
{
|
||||||
|
pdec->mOptFlags = 0;
|
||||||
|
pdec = pdec->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < mGlobalVariables.Size(); i++)
|
||||||
|
{
|
||||||
|
mGlobalVariables[i]->mOptFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFunctions.SetSize(0);
|
||||||
|
mGlobalVariables.SetSize(0);
|
||||||
|
mCalledFunctions.SetSize(0);
|
||||||
|
mCalledFunctions.SetSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalOptimizer::PropagateParamCommas(Expression*& fexp, Expression*& exp)
|
||||||
|
{
|
||||||
|
PropagateCommas(exp);
|
||||||
|
if (exp->mType == EX_COMMA)
|
||||||
|
{
|
||||||
|
Expression* cexp = exp;
|
||||||
|
exp = cexp->mRight;
|
||||||
|
cexp->mRight = fexp;
|
||||||
|
fexp = cexp;
|
||||||
|
fexp->mDecType = cexp->mRight->mDecType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalOptimizer::PropagateCommas(Expression*& exp)
|
||||||
|
{
|
||||||
|
if (exp->mType == EX_PREFIX && exp->mLeft->mType == EX_COMMA)
|
||||||
|
{
|
||||||
|
Expression* cexp = exp->mLeft;
|
||||||
|
exp->mLeft = cexp->mRight;
|
||||||
|
cexp->mDecType = exp->mDecType;
|
||||||
|
cexp->mRight = exp->ConstantFold(mErrors, nullptr);
|
||||||
|
exp = cexp;
|
||||||
|
}
|
||||||
|
else if (exp->mType == EX_CALL)
|
||||||
|
{
|
||||||
|
Expression* pexp = exp;
|
||||||
|
Expression* rexp = pexp->mRight;
|
||||||
|
if (rexp)
|
||||||
|
{
|
||||||
|
while (rexp && rexp->mType == EX_LIST)
|
||||||
|
{
|
||||||
|
PropagateParamCommas(exp, rexp->mLeft);
|
||||||
|
if (rexp->mLeft-> mType == EX_COMMA)
|
||||||
|
pexp = rexp;
|
||||||
|
rexp = rexp->mRight;
|
||||||
|
}
|
||||||
|
if (rexp)
|
||||||
|
PropagateParamCommas(exp, pexp->mRight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (exp->mLeft)
|
||||||
|
PropagateCommas(exp->mLeft);
|
||||||
|
if (exp->mRight)
|
||||||
|
PropagateCommas(exp->mRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GlobalOptimizer::CheckConstReturns(Expression*& exp)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (exp->mType == EX_CALL && exp->mDecType && exp->mDecType->mType != DT_TYPE_VOID)
|
||||||
|
{
|
||||||
|
if (exp->mLeft->mType == EX_CONSTANT)
|
||||||
|
{
|
||||||
|
Declaration* pcall = exp->mLeft->mDecValue;
|
||||||
|
if ((pcall->mOptFlags & OPTF_SINGLE_RETURN) && pcall->mReturn->mLeft)
|
||||||
|
{
|
||||||
|
Expression * rexp = pcall->mReturn->mLeft;
|
||||||
|
if (rexp->mType == EX_CONSTANT)
|
||||||
|
{
|
||||||
|
#if DUMP_OPTS
|
||||||
|
printf("Extract const return\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Expression* lexp = new Expression(exp->mLocation, EX_COMMA);
|
||||||
|
lexp->mLeft = exp;
|
||||||
|
lexp->mRight = new Expression(pcall->mReturn->mLocation, EX_CONSTANT);
|
||||||
|
lexp->mRight->mDecValue = pcall->mReturn->mLeft->mDecValue;
|
||||||
|
lexp->mRight->mDecType = exp->mDecType;
|
||||||
|
lexp->mDecType = exp->mDecType;
|
||||||
|
exp->mDecType = TheVoidTypeDeclaration;
|
||||||
|
exp = lexp;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (rexp->mType == EX_PREFIX && rexp->mToken == TK_MUL && rexp->mLeft->mType == EX_VARIABLE && rexp->mLeft->mDecValue->mType == DT_ARGUMENT)
|
||||||
|
{
|
||||||
|
Declaration* pdec = rexp->mLeft->mDecValue;
|
||||||
|
if (pdec->mVarIndex == 0 && !(pdec->mOptFlags & OPTF_VAR_ADDRESS))
|
||||||
|
{
|
||||||
|
Expression* pex = exp->mRight;
|
||||||
|
if (pex->mType == EX_LIST)
|
||||||
|
pex = pex->mLeft;
|
||||||
|
if (pex->mType == EX_CONSTANT)
|
||||||
|
{
|
||||||
|
#if DUMP_OPTS
|
||||||
|
printf("Forward this pointer\n");
|
||||||
|
#endif
|
||||||
|
Expression* lexp = new Expression(exp->mLocation, EX_COMMA);
|
||||||
|
lexp->mLeft = exp;
|
||||||
|
lexp->mRight = new Expression(pcall->mReturn->mLocation, EX_PREFIX);
|
||||||
|
lexp->mRight->mToken = TK_MUL;
|
||||||
|
lexp->mRight->mLeft = pex;
|
||||||
|
lexp->mRight->mDecType = pcall->mBase->mBase;
|
||||||
|
exp->mDecType = TheVoidTypeDeclaration;
|
||||||
|
exp = lexp;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp->mLeft && CheckConstReturns(exp->mLeft))
|
||||||
|
changed = true;
|
||||||
|
if (exp->mRight && CheckConstReturns(exp->mRight))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GlobalOptimizer::CheckUnusedLocals(Expression*& exp)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (exp->mType == EX_INITIALIZATION)
|
||||||
|
{
|
||||||
|
Expression* vexp = exp->mLeft;
|
||||||
|
if (vexp->mType == EX_VARIABLE)
|
||||||
|
{
|
||||||
|
Declaration* vdec = vexp->mDecValue;
|
||||||
|
if (vdec->mType == DT_VARIABLE && !(vdec->mFlags & (DTF_GLOBAL | DTF_STATIC)) && !(vdec->mOptFlags & OPTF_VAR_USED))
|
||||||
|
{
|
||||||
|
exp = exp->mRight;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp->mLeft && CheckUnusedLocals(exp->mLeft))
|
||||||
|
changed = true;
|
||||||
|
if (exp->mRight && CheckUnusedLocals(exp->mRight))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalOptimizer::RemoveValueReturn(Expression* exp)
|
||||||
|
{
|
||||||
|
if (exp->mType == EX_RETURN && exp->mLeft)
|
||||||
|
{
|
||||||
|
if (exp->mLeft->HasSideEffects())
|
||||||
|
{
|
||||||
|
exp->mType = EX_SEQUENCE;
|
||||||
|
exp->mRight = new Expression(exp->mLocation, EX_RETURN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
exp->mLeft = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp->mLeft)
|
||||||
|
RemoveValueReturn(exp->mLeft);
|
||||||
|
if (exp->mRight)
|
||||||
|
RemoveValueReturn(exp->mRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalOptimizer::UndoParamReference(Expression* exp, Declaration* param)
|
||||||
|
{
|
||||||
|
if (exp)
|
||||||
|
{
|
||||||
|
if (exp->mType == EX_VARIABLE && exp->mDecValue == param)
|
||||||
|
{
|
||||||
|
exp->mDecType = param->mBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
UndoParamReference(exp->mLeft, param);
|
||||||
|
UndoParamReference(exp->mRight, param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GlobalOptimizer::ReplaceParamConst(Expression* exp, Declaration* param)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
if (exp)
|
||||||
|
{
|
||||||
|
if (exp->mType == EX_VARIABLE && exp->mDecValue == param)
|
||||||
|
{
|
||||||
|
exp->mType = EX_CONSTANT;
|
||||||
|
exp->mDecType = param->mBase;
|
||||||
|
exp->mDecValue = param->mValue->mDecValue->ConstCast(param->mBase);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReplaceParamConst(exp->mLeft, param))
|
||||||
|
changed = true;
|
||||||
|
if (ReplaceParamConst(exp->mRight, param))
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GlobalOptimizer::Optimize(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
#if DUMP_OPTS
|
||||||
|
printf("OPT---\n");
|
||||||
|
#endif
|
||||||
|
for (int i = 0; i < mFunctions.Size(); i++)
|
||||||
|
{
|
||||||
|
Declaration* func = mFunctions[i];
|
||||||
|
Declaration* ftype = func->mBase;
|
||||||
|
|
||||||
|
if (func->mValue && func->mValue->mType != EX_DISPATCH)
|
||||||
|
{
|
||||||
|
#if DUMP_OPTS
|
||||||
|
printf("%s %08llx\n", mFunctions[i]->mQualIdent->mString, mFunctions[i]->mOptFlags);
|
||||||
|
#endif
|
||||||
|
if (CheckUnusedLocals(func->mValue))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
if (CheckConstReturns(func->mValue))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
if (!(func->mOptFlags & OPTF_FUNC_VARIABLE) && !(func->mBase->mFlags & DTF_VIRTUAL))
|
||||||
|
{
|
||||||
|
if (!(func->mOptFlags & OPTF_VAR_USED) && func->mBase->mBase && (func->mBase->mBase->IsSimpleType() || func->mBase->mBase->IsReference()))
|
||||||
|
{
|
||||||
|
#if DUMP_OPTS
|
||||||
|
printf("Remove return value\n");
|
||||||
|
#endif
|
||||||
|
RemoveValueReturn(func->mValue);
|
||||||
|
func->mBase->mBase = TheVoidTypeDeclaration;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (!(func->mOptFlags & OPTF_VAR_ADDRESS) && func->mBase->mBase && func->mBase->mBase->IsReference() && func->mBase->mBase->mBase->IsSimpleType())
|
||||||
|
{
|
||||||
|
#if DUMP_OPTS
|
||||||
|
printf("Demote reference return\n");
|
||||||
|
#endif
|
||||||
|
func->mBase->mBase = func->mBase->mBase->mBase;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Declaration* pdec = ftype->mParams;
|
||||||
|
int vi = 0;
|
||||||
|
while (pdec)
|
||||||
|
{
|
||||||
|
pdec->mVarIndex += vi;
|
||||||
|
if (!(pdec->mOptFlags & OPTF_VAR_USED) && !(pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||||
|
{
|
||||||
|
if (!pdec->mBase->IsReference() || !(pdec->mOptFlags & OPTF_VAR_ADDRESS))
|
||||||
|
{
|
||||||
|
#if DUMP_OPTS
|
||||||
|
printf("Unused parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||||
|
#endif
|
||||||
|
vi -= pdec->mSize;
|
||||||
|
|
||||||
|
pdec->mFlags |= DTF_FPARAM_UNUSED;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!(pdec->mOptFlags & OPTF_VAR_ADDRESS) && pdec->mBase->IsReference() && pdec->mBase->mBase->IsSimpleType())
|
||||||
|
{
|
||||||
|
#if DUMP_OPTS
|
||||||
|
printf("Reference parameter %s to value\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||||
|
#endif
|
||||||
|
vi += pdec->mSize - 2;
|
||||||
|
|
||||||
|
pdec->mBase = pdec->mBase->mBase;
|
||||||
|
pdec->mSize = pdec->mBase->mSize;
|
||||||
|
|
||||||
|
UndoParamReference(func->mValue, pdec);
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if ((pdec->mOptFlags & OPTF_VAR_CONST) && !(pdec->mOptFlags & OPTF_VAR_ADDRESS))
|
||||||
|
{
|
||||||
|
if (ReplaceParamConst(func->mValue, pdec))
|
||||||
|
{
|
||||||
|
#if DUMP_OPTS
|
||||||
|
printf("Const parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||||
|
#endif
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pdec->mOptFlags = 0;
|
||||||
|
pdec = pdec->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PropagateCommas(func->mValue);
|
||||||
|
}
|
||||||
|
else if (func->mValue && func->mValue->mType == EX_DISPATCH)
|
||||||
|
{
|
||||||
|
if (!(func->mOptFlags & OPTF_FUNC_VARIABLE))
|
||||||
|
{
|
||||||
|
Declaration* pdec = ftype->mParams;
|
||||||
|
while (pdec)
|
||||||
|
{
|
||||||
|
if ((pdec->mOptFlags & OPTF_VAR_CONST) && !(pdec->mOptFlags & OPTF_VAR_ADDRESS))
|
||||||
|
{
|
||||||
|
if (ReplaceParamConst(func->mValue, pdec))
|
||||||
|
{
|
||||||
|
#if DUMP_OPTS
|
||||||
|
printf("Const parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||||
|
#endif
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pdec->mOptFlags = 0;
|
||||||
|
pdec = pdec->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalOptimizer::AnalyzeProcedure(Expression* exp, Declaration* procDec)
|
||||||
|
{
|
||||||
|
if (procDec->mOptFlags & OPTF_ANALYZING)
|
||||||
|
{
|
||||||
|
procDec->mOptFlags |= OPTF_RECURSIVE;
|
||||||
|
}
|
||||||
|
else if (!(procDec->mOptFlags & OPTF_ANALYZED))
|
||||||
|
{
|
||||||
|
procDec->mOptFlags |= OPTF_ANALYZING | OPTF_ANALYZED;
|
||||||
|
|
||||||
|
mFunctions.Push(procDec);
|
||||||
|
|
||||||
|
if ((procDec->mFlags & DTF_INTRINSIC) && !procDec->mValue)
|
||||||
|
;
|
||||||
|
else if (procDec->mFlags & DTF_DEFINED)
|
||||||
|
{
|
||||||
|
Analyze(exp, procDec, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mErrors->Error(procDec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", procDec->mQualIdent);
|
||||||
|
|
||||||
|
procDec->mOptFlags &= ~OPTF_ANALYZING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalOptimizer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
|
||||||
|
{
|
||||||
|
while (exp)
|
||||||
|
{
|
||||||
|
if (exp->mLeft && exp->mLeft->mDecValue)
|
||||||
|
{
|
||||||
|
Declaration* adec = exp->mLeft->mDecValue;
|
||||||
|
if (adec->mType == DT_LABEL_REF)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_VARIABLE_REF)
|
||||||
|
{
|
||||||
|
if (adec->mBase->mFlags & DTF_GLOBAL)
|
||||||
|
AnalyzeGlobalVariable(adec->mBase);
|
||||||
|
else
|
||||||
|
adec->mBase->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS;
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_LABEL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_VARIABLE)
|
||||||
|
{
|
||||||
|
if (adec->mFlags & DTF_GLOBAL)
|
||||||
|
AnalyzeGlobalVariable(adec);
|
||||||
|
else
|
||||||
|
adec->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS;
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_ARGUMENT)
|
||||||
|
{
|
||||||
|
adec->mOptFlags |= OPTF_VAR_USED;
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_FUNCTION_REF)
|
||||||
|
{
|
||||||
|
adec->mBase->mOptFlags |= OPTF_VAR_USED;
|
||||||
|
AnalyzeProcedure(adec->mBase->mValue, adec->mBase);
|
||||||
|
RegisterProc(adec->mBase);
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
adec->mOptFlags |= OPTF_VAR_USED;
|
||||||
|
AnalyzeProcedure(adec->mValue, adec);
|
||||||
|
RegisterCall(procDec, adec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exp = exp->mRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalOptimizer::AnalyzeGlobalVariable(Declaration* dec)
|
||||||
|
{
|
||||||
|
while (dec->mType == DT_VARIABLE_REF)
|
||||||
|
dec = dec->mBase;
|
||||||
|
|
||||||
|
if (!(dec->mOptFlags & OPTF_ANALYZED))
|
||||||
|
{
|
||||||
|
dec->mOptFlags |= OPTF_ANALYZED;
|
||||||
|
|
||||||
|
if (dec->mValue && dec->mValue->mType == EX_CONSTRUCT)
|
||||||
|
{
|
||||||
|
if (dec->mValue->mLeft->mLeft->mType == EX_CALL && (dec->mValue->mLeft->mLeft->mLeft->mDecValue->mFlags & DTF_CONSTEXPR))
|
||||||
|
{
|
||||||
|
ConstexprInterpreter cinter(dec->mLocation, mErrors, dec->mSection);
|
||||||
|
dec->mValue = cinter.EvalConstructor(dec->mValue->mLeft->mLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mGlobalVariables.Push(dec);
|
||||||
|
|
||||||
|
if (dec->mValue)
|
||||||
|
{
|
||||||
|
Analyze(dec->mValue, dec, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalOptimizer::AnalyzeInit(Declaration* mdec)
|
||||||
|
{
|
||||||
|
while (mdec)
|
||||||
|
{
|
||||||
|
if (mdec->mValue)
|
||||||
|
RegisterProc(Analyze(mdec->mValue, mdec, false));
|
||||||
|
else if (mdec->mParams)
|
||||||
|
AnalyzeInit(mdec->mParams);
|
||||||
|
mdec = mdec->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GlobalOptimizer::RegisterCall(Declaration* from, Declaration* to)
|
||||||
|
{
|
||||||
|
if (from)
|
||||||
|
{
|
||||||
|
if (to->mType == DT_VARIABLE || to->mType == DT_ARGUMENT)
|
||||||
|
to = to->mBase;
|
||||||
|
|
||||||
|
if (to->mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
if (!(to->mOptFlags & OPTF_CALLED))
|
||||||
|
{
|
||||||
|
to->mOptFlags |= OPTF_CALLED;
|
||||||
|
mCalledFunctions.Push(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(from->mOptFlags & OPTF_CALLING))
|
||||||
|
{
|
||||||
|
from->mOptFlags |= OPTF_CALLING;
|
||||||
|
mCallingFunctions.Push(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (to->mType == DT_TYPE_FUNCTION)
|
||||||
|
{
|
||||||
|
if (!(from->mOptFlags & OPTF_CALLING))
|
||||||
|
{
|
||||||
|
from->mOptFlags |= OPTF_CALLING;
|
||||||
|
mCallingFunctions.Push(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (to->mType == DT_TYPE_POINTER && to->mBase->mType == DT_TYPE_FUNCTION)
|
||||||
|
{
|
||||||
|
if (!(from->mOptFlags & OPTF_CALLING))
|
||||||
|
{
|
||||||
|
from->mOptFlags |= OPTF_CALLING;
|
||||||
|
mCallingFunctions.Push(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalOptimizer::RegisterProc(Declaration* to)
|
||||||
|
{
|
||||||
|
if (to->mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
if (to->mBase->mFlags & DTF_VIRTUAL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (!(to->mOptFlags & OPTF_FUNC_VARIABLE))
|
||||||
|
{
|
||||||
|
to->mOptFlags |= OPTF_FUNC_VARIABLE;
|
||||||
|
mVariableFunctions.Push(to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint32 ANAFL_LHS = (1U << 0);
|
||||||
|
static const uint32 ANAFL_RHS = (1U << 1);
|
||||||
|
|
||||||
|
Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uint32 flags)
|
||||||
|
{
|
||||||
|
Declaration* ldec, * rdec;
|
||||||
|
|
||||||
|
switch (exp->mType)
|
||||||
|
{
|
||||||
|
case EX_ERROR:
|
||||||
|
case EX_VOID:
|
||||||
|
break;
|
||||||
|
case EX_CONSTANT:
|
||||||
|
if (exp->mDecValue->mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
AnalyzeProcedure(exp->mDecValue->mValue, exp->mDecValue);
|
||||||
|
}
|
||||||
|
else if (exp->mDecValue->mType == DT_CONST_STRUCT)
|
||||||
|
{
|
||||||
|
AnalyzeInit(exp->mDecValue->mParams);
|
||||||
|
}
|
||||||
|
else if (exp->mDecValue->mType == DT_CONST_POINTER)
|
||||||
|
{
|
||||||
|
ldec = Analyze(exp->mDecValue->mValue, procDec, ANAFL_LHS | ANAFL_RHS);
|
||||||
|
RegisterProc(ldec);
|
||||||
|
}
|
||||||
|
else if (exp->mDecValue->mType == DT_CONST_ADDRESS)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (exp->mDecValue->mType == DT_CONST_ASSEMBLER)
|
||||||
|
{
|
||||||
|
AnalyzeAssembler(exp->mDecValue->mValue, procDec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return exp->mDecValue;
|
||||||
|
case EX_VARIABLE:
|
||||||
|
if ((exp->mDecValue->mFlags & DTF_STATIC) || (exp->mDecValue->mFlags & DTF_GLOBAL))
|
||||||
|
{
|
||||||
|
Declaration* type = exp->mDecValue->mBase;
|
||||||
|
while (type->mType == DT_TYPE_ARRAY)
|
||||||
|
type = type->mBase;
|
||||||
|
|
||||||
|
AnalyzeGlobalVariable(exp->mDecValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (flags & ANAFL_RHS)
|
||||||
|
exp->mDecValue->mOptFlags |= OPTF_VAR_USED;
|
||||||
|
if (flags & ANAFL_LHS)
|
||||||
|
exp->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS;
|
||||||
|
}
|
||||||
|
return exp->mDecValue;
|
||||||
|
case EX_INITIALIZATION:
|
||||||
|
case EX_ASSIGNMENT:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | flags);
|
||||||
|
rdec = Analyze(exp->mRight, procDec, ANAFL_RHS);
|
||||||
|
RegisterProc(rdec);
|
||||||
|
return ldec;
|
||||||
|
|
||||||
|
case EX_BINARY:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, flags);
|
||||||
|
rdec = Analyze(exp->mRight, procDec, flags);
|
||||||
|
return ldec;
|
||||||
|
|
||||||
|
case EX_RELATIONAL:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, flags);
|
||||||
|
rdec = Analyze(exp->mRight, procDec, flags);
|
||||||
|
return TheBoolTypeDeclaration;
|
||||||
|
|
||||||
|
case EX_PREINCDEC:
|
||||||
|
return Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS);
|
||||||
|
case EX_PREFIX:
|
||||||
|
if (exp->mToken == TK_BINARY_AND)
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS);
|
||||||
|
else if (exp->mToken == TK_MUL)
|
||||||
|
{
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
return exp->mDecType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Analyze(exp->mLeft, procDec, flags);
|
||||||
|
break;
|
||||||
|
case EX_POSTFIX:
|
||||||
|
break;
|
||||||
|
case EX_POSTINCDEC:
|
||||||
|
return Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS);
|
||||||
|
case EX_INDEX:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
if (ldec->mType == DT_VARIABLE || ldec->mType == DT_ARGUMENT)
|
||||||
|
ldec = ldec->mBase;
|
||||||
|
rdec = Analyze(exp->mRight, procDec, ANAFL_RHS);
|
||||||
|
if (ldec->mBase)
|
||||||
|
return ldec->mBase;
|
||||||
|
break;
|
||||||
|
case EX_QUALIFY:
|
||||||
|
Analyze(exp->mLeft, procDec, flags);
|
||||||
|
return exp->mDecValue->mBase;
|
||||||
|
case EX_DISPATCH:
|
||||||
|
Analyze(exp->mLeft, procDec, flags);
|
||||||
|
break;
|
||||||
|
case EX_VCALL:
|
||||||
|
exp->mType = EX_CALL;
|
||||||
|
exp->mLeft->mDecValue = exp->mLeft->mDecValue->mVTable;
|
||||||
|
// intentional fall through
|
||||||
|
case EX_CALL:
|
||||||
|
case EX_INLINE:
|
||||||
|
if (exp->mLeft->mType == EX_CONSTANT)
|
||||||
|
{
|
||||||
|
if (flags & ANAFL_RHS)
|
||||||
|
exp->mLeft->mDecValue->mOptFlags |= OPTF_VAR_USED;
|
||||||
|
if (flags & ANAFL_LHS)
|
||||||
|
exp->mLeft->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RegisterCall(procDec, ldec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp->mRight)
|
||||||
|
{
|
||||||
|
// Check for struct to struct forwarding
|
||||||
|
|
||||||
|
Expression* rex = exp->mRight;
|
||||||
|
if (rex)
|
||||||
|
{
|
||||||
|
Expression* prex = exp;
|
||||||
|
while (rex && rex->mType == EX_LIST)
|
||||||
|
{
|
||||||
|
rex->mLeft = rex->mLeft->ConstantFold(mErrors, nullptr);
|
||||||
|
prex = rex;
|
||||||
|
rex = rex->mRight;
|
||||||
|
}
|
||||||
|
if (rex)
|
||||||
|
prex->mRight = rex->ConstantFold(mErrors, nullptr);
|
||||||
|
rex = exp->mRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
Declaration* pdec = ldec->mBase->mParams;
|
||||||
|
while (rex)
|
||||||
|
{
|
||||||
|
Expression* pex = rex->mType == EX_LIST ? rex->mLeft : rex;
|
||||||
|
|
||||||
|
if (pdec)
|
||||||
|
{
|
||||||
|
if ((pdec->mFlags & DTF_FPARAM_UNUSED) && !pex->HasSideEffects() && pex->mType != EX_CONSTANT)
|
||||||
|
{
|
||||||
|
if (pdec->mBase->IsSimpleType())
|
||||||
|
{
|
||||||
|
pex->mType = EX_CONSTANT;
|
||||||
|
pex->mLeft = nullptr;
|
||||||
|
pex->mRight = nullptr;
|
||||||
|
switch (pex->mDecType->mType)
|
||||||
|
{
|
||||||
|
case DT_TYPE_INTEGER:
|
||||||
|
case DT_TYPE_ENUM:
|
||||||
|
case DT_TYPE_BOOL:
|
||||||
|
pex->mDecValue = TheZeroIntegerConstDeclaration;
|
||||||
|
break;
|
||||||
|
case DT_TYPE_FLOAT:
|
||||||
|
pex->mDecValue = TheZeroFloatConstDeclaration;
|
||||||
|
break;
|
||||||
|
case DT_TYPE_POINTER:
|
||||||
|
pex->mDecValue = TheNullptrConstDeclaration;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(pdec->mFlags & DTF_FPARAM_UNUSED) && !(pdec->mOptFlags & OPTF_VAR_NOCONST))
|
||||||
|
{
|
||||||
|
if (pex->mType == EX_CONSTANT && pdec->mBase->IsSimpleType())
|
||||||
|
{
|
||||||
|
if (pdec->mOptFlags & OPTF_VAR_CONST)
|
||||||
|
{
|
||||||
|
if (!pex->mDecValue->IsSameValue(pdec->mValue->mDecValue))
|
||||||
|
{
|
||||||
|
pdec->mOptFlags |= OPTF_VAR_NOCONST;
|
||||||
|
pdec->mOptFlags &= ~OPTF_VAR_CONST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdec->mValue = pex;
|
||||||
|
pdec->mOptFlags |= OPTF_VAR_CONST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdec->mOptFlags |= OPTF_VAR_NOCONST;
|
||||||
|
pdec->mOptFlags &= ~OPTF_VAR_CONST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdec->mBase->mType == DT_TYPE_STRUCT && pdec->mBase->mCopyConstructor)
|
||||||
|
{
|
||||||
|
if (pdec->mBase->mMoveConstructor)
|
||||||
|
{
|
||||||
|
AnalyzeProcedure(pdec->mBase->mMoveConstructor->mValue, pdec->mBase->mMoveConstructor);
|
||||||
|
RegisterCall(procDec, pdec->mBase->mMoveConstructor);
|
||||||
|
}
|
||||||
|
AnalyzeProcedure(pdec->mBase->mCopyConstructor->mValue, pdec->mBase->mCopyConstructor);
|
||||||
|
RegisterCall(procDec, pdec->mBase->mCopyConstructor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdec && (pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||||
|
RegisterProc(Analyze(pex, procDec, 0));
|
||||||
|
else if (pdec && pdec->mBase->IsReference())
|
||||||
|
RegisterProc(Analyze(pex, procDec, ANAFL_LHS | ANAFL_RHS));
|
||||||
|
else
|
||||||
|
RegisterProc(Analyze(pex, procDec, ANAFL_RHS));
|
||||||
|
|
||||||
|
if (pdec)
|
||||||
|
pdec = pdec->mNext;
|
||||||
|
|
||||||
|
if (rex->mType == EX_LIST)
|
||||||
|
rex = rex->mRight;
|
||||||
|
else
|
||||||
|
rex = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EX_LIST:
|
||||||
|
case EX_COMMA:
|
||||||
|
{
|
||||||
|
RegisterProc(Analyze(exp->mLeft, procDec, 0));
|
||||||
|
Declaration* dec = Analyze(exp->mRight, procDec, flags);
|
||||||
|
RegisterProc(dec);
|
||||||
|
return dec;
|
||||||
|
}
|
||||||
|
case EX_RETURN:
|
||||||
|
if (exp->mLeft)
|
||||||
|
{
|
||||||
|
exp->mLeft = exp->mLeft->ConstantFold(mErrors, nullptr);
|
||||||
|
|
||||||
|
if (procDec->mOptFlags & OPTF_SINGLE_RETURN)
|
||||||
|
{
|
||||||
|
procDec->mOptFlags &= ~OPTF_SINGLE_RETURN;
|
||||||
|
procDec->mOptFlags |= OPTF_MULTI_RETURN;
|
||||||
|
}
|
||||||
|
else if (!(procDec->mOptFlags & OPTF_MULTI_RETURN))
|
||||||
|
{
|
||||||
|
procDec->mOptFlags |= OPTF_SINGLE_RETURN;
|
||||||
|
procDec->mReturn = exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (procDec->mBase->mBase->IsReference())
|
||||||
|
RegisterProc(Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS));
|
||||||
|
else
|
||||||
|
RegisterProc(Analyze(exp->mLeft, procDec, ANAFL_RHS));
|
||||||
|
|
||||||
|
if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor)
|
||||||
|
{
|
||||||
|
if (procDec->mBase->mBase->mMoveConstructor)
|
||||||
|
{
|
||||||
|
AnalyzeProcedure(procDec->mBase->mBase->mMoveConstructor->mValue, procDec->mBase->mBase->mMoveConstructor);
|
||||||
|
RegisterCall(procDec, procDec->mBase->mBase->mMoveConstructor);
|
||||||
|
}
|
||||||
|
AnalyzeProcedure(procDec->mBase->mBase->mCopyConstructor->mValue, procDec->mBase->mBase->mCopyConstructor);
|
||||||
|
RegisterCall(procDec, procDec->mBase->mBase->mCopyConstructor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EX_SEQUENCE:
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (exp->mType == EX_SEQUENCE)
|
||||||
|
{
|
||||||
|
if (exp->mLeft)
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
|
exp = exp->mRight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Analyze(exp, procDec, 0);
|
||||||
|
|
||||||
|
} while (exp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EX_SCOPE:
|
||||||
|
Analyze(exp->mLeft, procDec, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EX_CONSTRUCT:
|
||||||
|
if (exp->mLeft->mLeft)
|
||||||
|
Analyze(exp->mLeft->mLeft, procDec, 0);
|
||||||
|
if (exp->mLeft->mRight)
|
||||||
|
Analyze(exp->mLeft->mRight, procDec, 0);
|
||||||
|
if (exp->mRight)
|
||||||
|
return Analyze(exp->mRight, procDec, ANAFL_RHS);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EX_CLEANUP:
|
||||||
|
Analyze(exp->mRight, procDec, 0);
|
||||||
|
return Analyze(exp->mLeft, procDec, flags);
|
||||||
|
|
||||||
|
case EX_WHILE:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
rdec = Analyze(exp->mRight, procDec, 0);
|
||||||
|
break;
|
||||||
|
case EX_IF:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
rdec = Analyze(exp->mRight->mLeft, procDec, 0);
|
||||||
|
if (exp->mRight->mRight)
|
||||||
|
rdec = Analyze(exp->mRight->mRight, procDec, 0);
|
||||||
|
break;
|
||||||
|
case EX_ELSE:
|
||||||
|
break;
|
||||||
|
case EX_FOR:
|
||||||
|
if (exp->mLeft->mRight)
|
||||||
|
ldec = Analyze(exp->mLeft->mRight, procDec, 0);
|
||||||
|
if (exp->mLeft->mLeft->mLeft)
|
||||||
|
ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec, ANAFL_RHS);
|
||||||
|
rdec = Analyze(exp->mRight, procDec, 0);
|
||||||
|
if (exp->mLeft->mLeft->mRight)
|
||||||
|
ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, 0);
|
||||||
|
break;
|
||||||
|
case EX_DO:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
|
rdec = Analyze(exp->mRight, procDec, ANAFL_RHS);
|
||||||
|
break;
|
||||||
|
case EX_BREAK:
|
||||||
|
case EX_CONTINUE:
|
||||||
|
case EX_ASSUME:
|
||||||
|
break;
|
||||||
|
case EX_TYPE:
|
||||||
|
break;
|
||||||
|
case EX_TYPECAST:
|
||||||
|
return Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
break;
|
||||||
|
case EX_LOGICAL_AND:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
rdec = Analyze(exp->mRight, procDec, ANAFL_RHS);
|
||||||
|
break;
|
||||||
|
case EX_LOGICAL_OR:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
rdec = Analyze(exp->mRight, procDec, ANAFL_RHS);
|
||||||
|
break;
|
||||||
|
case EX_LOGICAL_NOT:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
break;
|
||||||
|
case EX_ASSEMBLER:
|
||||||
|
AnalyzeAssembler(exp, procDec);
|
||||||
|
break;
|
||||||
|
case EX_UNDEFINED:
|
||||||
|
break;
|
||||||
|
case EX_SWITCH:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
exp = exp->mRight;
|
||||||
|
while (exp)
|
||||||
|
{
|
||||||
|
if (exp->mLeft->mRight)
|
||||||
|
rdec = Analyze(exp->mLeft->mRight, procDec, 0);
|
||||||
|
exp = exp->mRight;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EX_CASE:
|
||||||
|
break;
|
||||||
|
case EX_DEFAULT:
|
||||||
|
break;
|
||||||
|
case EX_CONDITIONAL:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
|
RegisterProc(Analyze(exp->mRight->mLeft, procDec, flags));
|
||||||
|
RegisterProc(Analyze(exp->mRight->mRight, procDec, flags));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TheVoidTypeDeclaration;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Declaration.h"
|
||||||
|
#include "Linker.h"
|
||||||
|
#include "CompilerTypes.h"
|
||||||
|
|
||||||
|
class GlobalOptimizer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GlobalOptimizer(Errors* errors, Linker* linker);
|
||||||
|
~GlobalOptimizer(void);
|
||||||
|
|
||||||
|
void Reset(void);
|
||||||
|
bool Optimize(void);
|
||||||
|
|
||||||
|
void AnalyzeProcedure(Expression* exp, Declaration* dec);
|
||||||
|
void AnalyzeAssembler(Expression* exp, Declaration* dec);
|
||||||
|
void AnalyzeGlobalVariable(Declaration* dec);
|
||||||
|
|
||||||
|
uint64 mCompilerOptions;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Errors* mErrors;
|
||||||
|
Linker* mLinker;
|
||||||
|
|
||||||
|
ExpandingArray<Declaration*> mCalledFunctions, mCallingFunctions, mVariableFunctions, mFunctions;
|
||||||
|
ExpandingArray<Declaration*> mGlobalVariables;
|
||||||
|
|
||||||
|
void AnalyzeInit(Declaration* mdec);
|
||||||
|
Declaration* Analyze(Expression* exp, Declaration* procDec, uint32 flags);
|
||||||
|
|
||||||
|
void RegisterCall(Declaration* from, Declaration* to);
|
||||||
|
void RegisterProc(Declaration* to);
|
||||||
|
|
||||||
|
void RemoveValueReturn(Expression* exp);
|
||||||
|
bool CheckConstReturns(Expression*& exp);
|
||||||
|
bool CheckUnusedLocals(Expression*& exp);
|
||||||
|
void UndoParamReference(Expression* exp, Declaration* param);
|
||||||
|
bool ReplaceParamConst(Expression* exp, Declaration* param);
|
||||||
|
void PropagateCommas(Expression*& exp);
|
||||||
|
void PropagateParamCommas(Expression *& fexp, Expression*& exp);
|
||||||
|
|
||||||
|
};
|
|
@ -4379,7 +4379,12 @@ void InterOperand::Disassemble(FILE* file, InterCodeProcedure* proc)
|
||||||
else if (mMemory == IM_GLOBAL)
|
else if (mMemory == IM_GLOBAL)
|
||||||
{
|
{
|
||||||
if (mVarIndex < 0)
|
if (mVarIndex < 0)
|
||||||
|
{
|
||||||
|
if (mLinkerObject && mLinkerObject->mIdent)
|
||||||
|
vname = mLinkerObject->mIdent->mString;
|
||||||
|
else
|
||||||
vname = "";
|
vname = "";
|
||||||
|
}
|
||||||
else if (!proc->mModule->mGlobalVars[mVarIndex])
|
else if (!proc->mModule->mGlobalVars[mVarIndex])
|
||||||
vname = "null";
|
vname = "null";
|
||||||
else if (!proc->mModule->mGlobalVars[mVarIndex]->mIdent)
|
else if (!proc->mModule->mGlobalVars[mVarIndex]->mIdent)
|
||||||
|
@ -4563,7 +4568,12 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc)
|
||||||
else if (mConst.mMemory == IM_GLOBAL)
|
else if (mConst.mMemory == IM_GLOBAL)
|
||||||
{
|
{
|
||||||
if (mConst.mVarIndex < 0)
|
if (mConst.mVarIndex < 0)
|
||||||
|
{
|
||||||
|
if (mConst.mLinkerObject && mConst.mLinkerObject->mIdent)
|
||||||
|
vname = mConst.mLinkerObject->mIdent->mString;
|
||||||
|
else
|
||||||
vname = "";
|
vname = "";
|
||||||
|
}
|
||||||
else if (!proc->mModule->mGlobalVars[mConst.mVarIndex])
|
else if (!proc->mModule->mGlobalVars[mConst.mVarIndex])
|
||||||
vname = "null";
|
vname = "null";
|
||||||
else if (!proc->mModule->mGlobalVars[mConst.mVarIndex]->mIdent)
|
else if (!proc->mModule->mGlobalVars[mConst.mVarIndex]->mIdent)
|
||||||
|
@ -6415,7 +6425,10 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(bool initial, const Growin
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < mLocalValueRange.Size(); i++)
|
for (int i = 0; i < mLocalValueRange.Size(); i++)
|
||||||
|
{
|
||||||
|
if (this != from || IsTempModified(i))
|
||||||
mLocalValueRange[i].Merge(range[i], mLoopHead, initial);
|
mLocalValueRange[i].Merge(range[i], mLoopHead, initial);
|
||||||
|
}
|
||||||
for (int i = 0; i < mLocalParamValueRange.Size(); i++)
|
for (int i = 0; i < mLocalParamValueRange.Size(); i++)
|
||||||
mLocalParamValueRange[i].Merge(prange[i], mLoopHead, initial);
|
mLocalParamValueRange[i].Merge(prange[i], mLoopHead, initial);
|
||||||
}
|
}
|
||||||
|
@ -12262,6 +12275,45 @@ static InterInstruction * FindSourceInstruction(InterCodeBasicBlock* block, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InterCodeBasicBlock::MoveLoopHeadCheckToTail(void)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
if (mLoopHead && mEntryBlocks.Size() == 2 && mInstructions.Size() == 2)
|
||||||
|
{
|
||||||
|
if (mInstructions[0]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[1]->mCode == IC_BRANCH &&
|
||||||
|
mInstructions[1]->mSrc[0].mTemp == mInstructions[0]->mDst.mTemp)
|
||||||
|
{
|
||||||
|
if (mFalseJump != this && mTrueJump->mTrueJump == this && !mTrueJump->mFalseJump)
|
||||||
|
{
|
||||||
|
mTrueJump->mInstructions.SetSize(mTrueJump->mInstructions.Size() - 1);
|
||||||
|
mTrueJump->mInstructions.Push(mInstructions[0]->Clone());
|
||||||
|
mTrueJump->mInstructions.Push(mInstructions[1]->Clone());
|
||||||
|
mTrueJump->mTrueJump = mTrueJump;
|
||||||
|
mTrueJump->mFalseJump = mFalseJump;
|
||||||
|
mTrueJump->mEntryBlocks.Push(mTrueJump);
|
||||||
|
mTrueJump->mNumEntries++;
|
||||||
|
mFalseJump->mEntryBlocks.Push(mTrueJump);
|
||||||
|
mFalseJump->mNumEntries++;
|
||||||
|
mNumEntries--;
|
||||||
|
mEntryBlocks.Remove(mEntryBlocks.IndexOf(mTrueJump));
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->MoveLoopHeadCheckToTail())
|
||||||
|
modified = true;
|
||||||
|
if (mFalseJump && mFalseJump->MoveLoopHeadCheckToTail())
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
bool InterCodeBasicBlock::SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars)
|
bool InterCodeBasicBlock::SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars)
|
||||||
{
|
{
|
||||||
bool modified = false;
|
bool modified = false;
|
||||||
|
@ -17606,6 +17658,12 @@ void InterCodeProcedure::Close(void)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
ResetVisited();
|
||||||
|
mEntryBlock->MoveLoopHeadCheckToTail();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
BuildLoopPrefix();
|
BuildLoopPrefix();
|
||||||
DisassembleDebug("added dominators");
|
DisassembleDebug("added dominators");
|
||||||
|
@ -18110,7 +18168,7 @@ void InterCodeProcedure::Close(void)
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
case IC_CONSTANT:
|
case IC_CONSTANT:
|
||||||
if (ins->mConst.mType == IT_POINTER && (ins->mConst.mMemory == IM_FPARAM || ins->mConst.mMemory == IM_PARAM || ins->mConst.mMemory == IM_LOCAL))
|
if (ins->mDst.mType == IT_POINTER && (ins->mConst.mMemory == IM_FPARAM || ins->mConst.mMemory == IM_PARAM || ins->mConst.mMemory == IM_LOCAL))
|
||||||
nother++;
|
nother++;
|
||||||
else
|
else
|
||||||
nconst++;
|
nconst++;
|
||||||
|
|
|
@ -543,6 +543,7 @@ public:
|
||||||
void PeepholeOptimization(const GrowingVariableArray& staticVars);
|
void PeepholeOptimization(const GrowingVariableArray& staticVars);
|
||||||
bool PeepholeReplaceOptimization(const GrowingVariableArray& staticVars);
|
bool PeepholeReplaceOptimization(const GrowingVariableArray& staticVars);
|
||||||
|
|
||||||
|
bool MoveLoopHeadCheckToTail(void);
|
||||||
void SingleBlockLoopOptimisation(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars);
|
void SingleBlockLoopOptimisation(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars);
|
||||||
void SingleBlockLoopUnrolling(void);
|
void SingleBlockLoopUnrolling(void);
|
||||||
bool SingleBlockLoopPointerSplit(int& spareTemps);
|
bool SingleBlockLoopPointerSplit(int& spareTemps);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "InterCodeGenerator.h"
|
#include "InterCodeGenerator.h"
|
||||||
|
#include "Constexpr.h"
|
||||||
|
|
||||||
InterCodeGenerator::InterCodeGenerator(Errors* errors, Linker* linker)
|
InterCodeGenerator::InterCodeGenerator(Errors* errors, Linker* linker)
|
||||||
: mErrors(errors), mLinker(linker), mCompilerOptions(COPT_DEFAULT)
|
: mErrors(errors), mLinker(linker), mCompilerOptions(COPT_DEFAULT)
|
||||||
|
@ -1200,7 +1201,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro
|
||||||
|
|
||||||
if (pdec)
|
if (pdec)
|
||||||
{
|
{
|
||||||
if (!(pdec->mFlags & DTF_FPARAM_CONST))
|
if (!(pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||||
nmapper.mParams[pdec->mVarIndex] = nindex;
|
nmapper.mParams[pdec->mVarIndex] = nindex;
|
||||||
|
|
||||||
vdec->mVarIndex = nindex;
|
vdec->mVarIndex = nindex;
|
||||||
|
@ -1317,7 +1318,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro
|
||||||
else
|
else
|
||||||
wins->mSrc[1].mOperandSize = 2;
|
wins->mSrc[1].mOperandSize = 2;
|
||||||
|
|
||||||
if (!pdec || !(pdec->mFlags & DTF_FPARAM_CONST))
|
if (!pdec || !(pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||||
block->Append(wins);
|
block->Append(wins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1444,7 +1445,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I
|
||||||
ains->mConst.mMemory = IM_LOCAL;
|
ains->mConst.mMemory = IM_LOCAL;
|
||||||
ains->mConst.mVarIndex = nindex;
|
ains->mConst.mVarIndex = nindex;
|
||||||
|
|
||||||
if (!(pdec->mFlags & DTF_FPARAM_CONST))
|
if (!(pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||||
nmapper.mParams[pdec->mVarIndex] = nindex;
|
nmapper.mParams[pdec->mVarIndex] = nindex;
|
||||||
|
|
||||||
vdec->mVarIndex = nindex;
|
vdec->mVarIndex = nindex;
|
||||||
|
@ -1463,7 +1464,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I
|
||||||
wins->mSrc[1].mType = IT_POINTER;
|
wins->mSrc[1].mType = IT_POINTER;
|
||||||
wins->mSrc[1].mTemp = ains->mDst.mTemp;
|
wins->mSrc[1].mTemp = ains->mDst.mTemp;
|
||||||
wins->mSrc[1].mOperandSize = 2;
|
wins->mSrc[1].mOperandSize = 2;
|
||||||
if (!(pdec->mFlags & DTF_FPARAM_CONST))
|
if (!(pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||||
block->Append(wins);
|
block->Append(wins);
|
||||||
|
|
||||||
pdec = pdec->mNext;
|
pdec = pdec->mNext;
|
||||||
|
@ -1479,7 +1480,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I
|
||||||
ains->mConst.mMemory = IM_LOCAL;
|
ains->mConst.mMemory = IM_LOCAL;
|
||||||
ains->mConst.mVarIndex = nindex;
|
ains->mConst.mVarIndex = nindex;
|
||||||
|
|
||||||
if (!(pdec->mFlags & DTF_FPARAM_CONST))
|
if (!(pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||||
nmapper.mParams[pdec->mVarIndex] = nindex;
|
nmapper.mParams[pdec->mVarIndex] = nindex;
|
||||||
|
|
||||||
vdec->mVarIndex = nindex;
|
vdec->mVarIndex = nindex;
|
||||||
|
@ -1498,7 +1499,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I
|
||||||
wins->mSrc[1].mType = IT_POINTER;
|
wins->mSrc[1].mType = IT_POINTER;
|
||||||
wins->mSrc[1].mTemp = ains->mDst.mTemp;
|
wins->mSrc[1].mTemp = ains->mDst.mTemp;
|
||||||
wins->mSrc[1].mOperandSize = 2;
|
wins->mSrc[1].mOperandSize = 2;
|
||||||
if (!(pdec->mFlags & DTF_FPARAM_CONST))
|
if (!(pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||||
block->Append(wins);
|
block->Append(wins);
|
||||||
|
|
||||||
TranslateExpression(ftype, proc, block, fexp, destack, BranchTarget(), BranchTarget(), &nmapper);
|
TranslateExpression(ftype, proc, block, fexp, destack, BranchTarget(), BranchTarget(), &nmapper);
|
||||||
|
@ -1620,6 +1621,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
|
|
||||||
case EX_SEQUENCE:
|
case EX_SEQUENCE:
|
||||||
case EX_LIST:
|
case EX_LIST:
|
||||||
|
case EX_COMMA:
|
||||||
if (exp->mLeft)
|
if (exp->mLeft)
|
||||||
vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
|
vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
|
||||||
exp = exp->mRight;
|
exp = exp->mRight;
|
||||||
|
@ -1948,7 +1950,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
int ref = 1;
|
int ref = 1;
|
||||||
if (dec->mType == DT_ARGUMENT)
|
if (dec->mType == DT_ARGUMENT)
|
||||||
{
|
{
|
||||||
if (dec->mFlags & DTF_FPARAM_CONST)
|
if (dec->mFlags & DTF_FPARAM_UNUSED)
|
||||||
{
|
{
|
||||||
ins->mConst.mMemory = IM_LOCAL;
|
ins->mConst.mMemory = IM_LOCAL;
|
||||||
if (inlineMapper)
|
if (inlineMapper)
|
||||||
|
@ -3543,7 +3545,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
|
|
||||||
if (pdec)
|
if (pdec)
|
||||||
{
|
{
|
||||||
if (!pdec->mBase->CanAssign(vr.mType))
|
if (!(pdec->mFlags & DTF_FPARAM_UNUSED) && !pdec->mBase->CanAssign(vr.mType))
|
||||||
{
|
{
|
||||||
pdec->mBase->CanAssign(vr.mType);
|
pdec->mBase->CanAssign(vr.mType);
|
||||||
mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
|
mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
|
||||||
|
@ -3577,7 +3579,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
else
|
else
|
||||||
wins->mSrc[1].mOperandSize = 2;
|
wins->mSrc[1].mOperandSize = 2;
|
||||||
|
|
||||||
if (!pdec || !(pdec->mFlags & DTF_FPARAM_CONST))
|
if (!pdec || !(pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||||
{
|
{
|
||||||
if (ftype->mFlags & DTF_FASTCALL)
|
if (ftype->mFlags & DTF_FASTCALL)
|
||||||
defins.Push(wins);
|
defins.Push(wins);
|
||||||
|
@ -3702,7 +3704,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
if (vdec->mType == DT_ARGUMENT)
|
if (vdec->mType == DT_ARGUMENT)
|
||||||
{
|
{
|
||||||
vins->mConst.mVarIndex = vdec->mVarIndex;
|
vins->mConst.mVarIndex = vdec->mVarIndex;
|
||||||
if (vdec->mFlags & DTF_FPARAM_CONST)
|
if (vdec->mFlags & DTF_FPARAM_UNUSED)
|
||||||
{
|
{
|
||||||
vins->mConst.mMemory = IM_LOCAL;
|
vins->mConst.mMemory = IM_LOCAL;
|
||||||
if (inlineMapper)
|
if (inlineMapper)
|
||||||
|
@ -5016,10 +5018,15 @@ void InterCodeGenerator::TranslateLogic(Declaration* procType, InterCodeProcedur
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
ExValue vr = TranslateExpression(procType, proc, block, exp, destack, BranchTarget(), BranchTarget(), inlineMapper);
|
ExValue vr = TranslateExpression(procType, proc, block, exp, destack, BranchTarget(), BranchTarget(), inlineMapper);
|
||||||
vr = Dereference(proc, exp, block, vr);
|
|
||||||
|
|
||||||
|
if (vr.mType->mType == DT_TYPE_ARRAY)
|
||||||
|
vr = Dereference(proc, exp, block, vr, 1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vr = Dereference(proc, exp, block, vr);
|
||||||
if (!vr.mType->IsSimpleType())
|
if (!vr.mType->IsSimpleType())
|
||||||
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Not a valid condition value");
|
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Not a valid condition value");
|
||||||
|
}
|
||||||
|
|
||||||
InterInstruction* ins = new InterInstruction(exp->mLocation, IC_BRANCH);
|
InterInstruction* ins = new InterInstruction(exp->mLocation, IC_BRANCH);
|
||||||
ins->mSrc[0].mType = InterTypeOf(vr.mType);
|
ins->mSrc[0].mType = InterTypeOf(vr.mType);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "Assembler.h"
|
#include "Assembler.h"
|
||||||
#include "MachineTypes.h"
|
#include "MachineTypes.h"
|
||||||
|
#include "Constexpr.h"
|
||||||
|
|
||||||
Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUnits)
|
Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUnits)
|
||||||
: mErrors(errors), mScanner(scanner), mCompilationUnits(compilationUnits)
|
: mErrors(errors), mScanner(scanner), mCompilationUnits(compilationUnits)
|
||||||
|
@ -3455,13 +3456,10 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
|
||||||
// A simple constant is passed by const ref
|
// A simple constant is passed by const ref
|
||||||
if (pex->mDecValue->mType == DT_CONST_INTEGER || pex->mDecValue->mType == DT_CONST_FLOAT || pex->mDecValue->mType == DT_CONST_POINTER || pex->mDecValue->mType == DT_CONST_ADDRESS)
|
if (pex->mDecValue->mType == DT_CONST_INTEGER || pex->mDecValue->mType == DT_CONST_FLOAT || pex->mDecValue->mType == DT_CONST_POINTER || pex->mDecValue->mType == DT_CONST_ADDRESS)
|
||||||
{
|
{
|
||||||
int nindex = mLocalIndex++;
|
if (pdec->mType == DT_TYPE_REFERENCE && !(pdec->mBase->mFlags & DTF_CONST))
|
||||||
|
mErrors->Error(pex->mLocation, EERR_INCOMPATIBLE_TYPES, "Can't pass constant as non constante reference");
|
||||||
|
|
||||||
Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE);
|
Declaration* vdec = AllocTempVar(pdec->mBase->mBase);
|
||||||
|
|
||||||
vdec->mVarIndex = nindex;
|
|
||||||
vdec->mBase = pdec->mBase->mBase;
|
|
||||||
vdec->mSize = pdec->mBase->mBase->mSize;
|
|
||||||
|
|
||||||
Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE);
|
Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE);
|
||||||
vexp->mDecType = pdec->mBase->mBase;
|
vexp->mDecType = pdec->mBase->mBase;
|
||||||
|
@ -3771,7 +3769,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
||||||
cdec->mBase = ctdec;
|
cdec->mBase = ctdec;
|
||||||
|
|
||||||
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
||||||
ctdec->mFlags |= storageFlags & DTF_VIRTUAL;
|
ctdec->mFlags |= storageFlags & (DTF_REQUEST_INLINE | DTF_CONSTEXPR | DTF_VIRTUAL);
|
||||||
|
|
||||||
cdec->mSection = mCodeSection;
|
cdec->mSection = mCodeSection;
|
||||||
cdec->mBase->mFlags |= typeFlags;
|
cdec->mBase->mFlags |= typeFlags;
|
||||||
|
@ -3821,7 +3819,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
||||||
cdec->mBase = ctdec;
|
cdec->mBase = ctdec;
|
||||||
|
|
||||||
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
||||||
ctdec->mFlags |= storageFlags & DTF_VIRTUAL;
|
ctdec->mFlags |= storageFlags & (DTF_REQUEST_INLINE | DTF_CONSTEXPR | DTF_VIRTUAL);
|
||||||
|
|
||||||
cdec->mSection = mCodeSection;
|
cdec->mSection = mCodeSection;
|
||||||
cdec->mBase->mFlags |= typeFlags;
|
cdec->mBase->mFlags |= typeFlags;
|
||||||
|
@ -3866,6 +3864,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
||||||
cdec->mBase = ctdec;
|
cdec->mBase = ctdec;
|
||||||
|
|
||||||
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
||||||
|
cdec->mFlags |= storageFlags & (DTF_INLINE | DTF_CONSTEXPR);
|
||||||
|
|
||||||
cdec->mSection = mCodeSection;
|
cdec->mSection = mCodeSection;
|
||||||
cdec->mBase->mFlags |= typeFlags;
|
cdec->mBase->mFlags |= typeFlags;
|
||||||
|
@ -3964,7 +3963,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
||||||
|
|
||||||
if (cdec)
|
if (cdec)
|
||||||
{
|
{
|
||||||
cdec->mFlags |= storageFlags & DTF_REQUEST_INLINE;
|
cdec->mFlags |= storageFlags & (DTF_REQUEST_INLINE | DTF_CONSTEXPR);
|
||||||
|
|
||||||
// Initializer list
|
// Initializer list
|
||||||
if (mScanner->mToken == TK_COLON)
|
if (mScanner->mToken == TK_COLON)
|
||||||
|
@ -4042,7 +4041,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
||||||
|
|
||||||
if (bdec->mDestructor)
|
if (bdec->mDestructor)
|
||||||
{
|
{
|
||||||
bdec->mDestructor->mFlags |= storageFlags & DTF_REQUEST_INLINE;
|
bdec->mDestructor->mFlags |= storageFlags & (DTF_REQUEST_INLINE | DTF_CONSTEXPR);
|
||||||
|
|
||||||
Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
|
Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
|
||||||
bthis->mFlags |= DTF_CONST | DTF_DEFINED;
|
bthis->mFlags |= DTF_CONST | DTF_DEFINED;
|
||||||
|
@ -4411,7 +4410,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
||||||
{
|
{
|
||||||
ParseVariableInit(ndec);
|
ParseVariableInit(ndec);
|
||||||
}
|
}
|
||||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mType == DT_VARIABLE && !pthis)
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mType == DT_VARIABLE && !pthis && !(storageFlags & DTF_EXTERN))
|
||||||
{
|
{
|
||||||
// Find default constructor
|
// Find default constructor
|
||||||
|
|
||||||
|
@ -4445,6 +4444,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
||||||
fexp->mLeft = cexp;
|
fexp->mLeft = cexp;
|
||||||
fexp->mRight = texp;
|
fexp->mRight = texp;
|
||||||
|
|
||||||
|
if (bdec->mDefaultConstructor->mFlags & DTF_CONSTEXPR)
|
||||||
|
ndec->mSection = mDataSection;
|
||||||
|
|
||||||
Expression* dexp = nullptr;
|
Expression* dexp = nullptr;
|
||||||
if (ndec->mBase->mDestructor)
|
if (ndec->mBase->mDestructor)
|
||||||
{
|
{
|
||||||
|
|
|
@ -205,6 +205,8 @@ int main2(int argc, const char** argv)
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_ZEROPAGE;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_ZEROPAGE;
|
||||||
else if (arg[2] == 'p')
|
else if (arg[2] == 'p')
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS;
|
||||||
|
else if (arg[2] == 'g')
|
||||||
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL;
|
||||||
}
|
}
|
||||||
else if (arg[1] == 'e')
|
else if (arg[1] == 'e')
|
||||||
{
|
{
|
||||||
|
@ -276,6 +278,11 @@ int main2(int argc, const char** argv)
|
||||||
compiler->AddDefine(Ident::Unique("OSCAR_NATIVE_ALL"), "1");
|
compiler->AddDefine(Ident::Unique("OSCAR_NATIVE_ALL"), "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// REMOVE ME
|
||||||
|
// compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL;
|
||||||
|
// REMOVE ME
|
||||||
|
|
||||||
char basicStart[10];
|
char basicStart[10];
|
||||||
strcpy_s(basicStart, "0x0801");
|
strcpy_s(basicStart, "0x0801");
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,7 @@
|
||||||
<ClCompile Include="Emulator.cpp" />
|
<ClCompile Include="Emulator.cpp" />
|
||||||
<ClCompile Include="Errors.cpp" />
|
<ClCompile Include="Errors.cpp" />
|
||||||
<ClCompile Include="GlobalAnalyzer.cpp" />
|
<ClCompile Include="GlobalAnalyzer.cpp" />
|
||||||
|
<ClCompile Include="GlobalOptimizer.cpp" />
|
||||||
<ClCompile Include="Ident.cpp" />
|
<ClCompile Include="Ident.cpp" />
|
||||||
<ClCompile Include="InterCode.cpp" />
|
<ClCompile Include="InterCode.cpp" />
|
||||||
<ClCompile Include="InterCodeGenerator.cpp" />
|
<ClCompile Include="InterCodeGenerator.cpp" />
|
||||||
|
@ -192,6 +193,7 @@
|
||||||
<ClInclude Include="Emulator.h" />
|
<ClInclude Include="Emulator.h" />
|
||||||
<ClInclude Include="Errors.h" />
|
<ClInclude Include="Errors.h" />
|
||||||
<ClInclude Include="GlobalAnalyzer.h" />
|
<ClInclude Include="GlobalAnalyzer.h" />
|
||||||
|
<ClInclude Include="GlobalOptimizer.h" />
|
||||||
<ClInclude Include="Ident.h" />
|
<ClInclude Include="Ident.h" />
|
||||||
<ClInclude Include="InterCode.h" />
|
<ClInclude Include="InterCode.h" />
|
||||||
<ClInclude Include="InterCodeGenerator.h" />
|
<ClInclude Include="InterCodeGenerator.h" />
|
||||||
|
|
|
@ -81,6 +81,9 @@
|
||||||
<ClCompile Include="Constexpr.cpp">
|
<ClCompile Include="Constexpr.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="GlobalOptimizer.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Array.h">
|
<ClInclude Include="Array.h">
|
||||||
|
@ -158,6 +161,9 @@
|
||||||
<ClInclude Include="Constexpr.h">
|
<ClInclude Include="Constexpr.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="GlobalOptimizer.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="oscar64.rc">
|
<ResourceCompile Include="oscar64.rc">
|
||||||
|
|
Loading…
Reference in New Issue