Add global optimizer for parameter/return optimizations

This commit is contained in:
drmortalwombat 2023-09-23 14:56:04 +02:00
parent c7f919e22e
commit 9d8c6991e8
19 changed files with 1258 additions and 49 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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
{ {

View File

@ -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:

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;

View File

@ -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:

925
oscar64/GlobalOptimizer.cpp Normal file
View File

@ -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;
}

43
oscar64/GlobalOptimizer.h Normal file
View File

@ -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);
};

View File

@ -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++;

View File

@ -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);

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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");

View File

@ -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" />

View File

@ -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">