From 7858e32d126b986bdf46648f23e35d9e5efaf462 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 15 Oct 2023 20:17:04 +0200 Subject: [PATCH] Improve handling of single member structs --- include/opp/slab.h | 80 ++++++++++ include/opp/static_vector.h | 258 +++++++++++++++++++++++++++++++++ oscar64/InterCode.cpp | 29 ++++ oscar64/InterCodeGenerator.cpp | 124 +++++++++------- oscar64/InterCodeGenerator.h | 1 + oscar64/Parser.cpp | 2 +- 6 files changed, 439 insertions(+), 55 deletions(-) create mode 100644 include/opp/slab.h create mode 100644 include/opp/static_vector.h diff --git a/include/opp/slab.h b/include/opp/slab.h new file mode 100644 index 0000000..1a61d4d --- /dev/null +++ b/include/opp/slab.h @@ -0,0 +1,80 @@ +#ifndef OPP_SLAB_H +#define OPP_SLAB_H + +template +class slabptr +{ +public: + char index; + + slabptr(void) + : index(N) + {} + + slabptr(char i) + : index(i) + {} + + slabptr(const slabptr & i) + : index(i.index) + {} + + auto operator-> (); + auto & operator* (); +}; + +template +class slab +{ +protected: + static __striped T buffer[N]; + static char head; + static char next[N]; + +public: + typedef slabptr ptr; + + static void init(void); + static auto alloc(void); + static void free(ptr p); +}; + + +template +inline auto slabptr::operator-> () +{ + return slab::buffer + index; +} + +template +inline auto & slabptr::operator* () +{ + return slab::buffer[index]; +} + + +template +void slab::init(void) +{ + head = 0; + for(char i=0; i +auto slab::alloc(void) +{ + char i = head; + head = next[head]; + return slabptr(i); +} + +template +void slab::free(slabptr p) +{ + next[p.index] = head; + head = p.index; +} + +#endif + diff --git a/include/opp/static_vector.h b/include/opp/static_vector.h new file mode 100644 index 0000000..c5358c6 --- /dev/null +++ b/include/opp/static_vector.h @@ -0,0 +1,258 @@ +#ifndef OPP_STATIC_VECTOR_H +#define OPP_STATIC_VECTOR_H + +#include +#include +#include + +namespace opp { + +template +class static_vector +{ +protected: + char _space[N * sizeof(T)]; + enum { m = N } _size; +public: + typedef T element_type; + + static_vector(void) : _size(0) {} + + static_vector(size_t n) : _size(n) + { + T * data = (T*)_space; + for(size_t i=0; i + void emplace_back(const P&... p); +}; + + + +template +void static_vector::resize(size_t n) +{ + T * data = (T*)_space; + if (n < _size) + { + for(size_t i=n; i<_size; i++) + data[i].~T(); + _size = n; + } + else + { + for(size_t i=_size; i +void static_vector::push_back(const T & t) +{ + new ((T*)_space + _size++)T(t); +} + +template +void static_vector::push_back(T && t) +{ + new ((T*)_space + _size++)T(t); +} + +template +template +void static_vector::emplace_back(const P&... p) +{ + new ((T*)_space + _size++)T(p...); +} + +template +void static_vector::insert(size_t at, const T & t) +{ + T * data = (T*)_space; + new (data + _size)T; + for(size_t i=_size; i>at; i--) + data[i] = move(data[i - 1]); + data[at] = t; + _size++; +} + +template +void static_vector::erase(size_t at, size_t n) +{ + T * data = (T*)_space; + _size -= n; + for(size_t i=at; i<_size; i++) + data[i] = move(data[i + n]); + for(size_t i=0; i +T * static_vector::insert(T * at, const T & t) +{ + T * data = (T*)_space; + T * dp = data + _size; + new (dp)T; + while (dp != at) + { + dp--; + dp[1] = move(dp[0]); + } + dp[0] = t; + _size++; + return dp + 1; +} + +} +#endif + diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index ef3c474..086b690 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16173,6 +16173,35 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray changed = true; } } +#endif +#if 1 + if (i + 1 < mInstructions.Size()) + { + if (mInstructions[i + 0]->mCode == IC_LEA && mInstructions[i + 0]->mSrc[1].mTemp < 0 && + mInstructions[i + 1]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mTemp < 0 && + mInstructions[i + 1]->mSrc[0].mMemory == IM_ABSOLUTE && mInstructions[i + 1]->mSrc[0].mIntConst == 0) + { + if (mInstructions[i + 0]->mSrc[1].mMemory != IM_ABSOLUTE) + { + if (mInstructions[i + 1]->mOperator == IA_CMPEQ) + { + mInstructions[i + 1]->mNumOperands = 0; + mInstructions[i + 1]->mCode = IC_CONSTANT; + mInstructions[i + 1]->mConst.mType = IT_BOOL; + mInstructions[i + 1]->mConst.mIntConst = 0; + changed = true; + } + else if (mInstructions[i + 1]->mOperator == IA_CMPNE) + { + mInstructions[i + 1]->mNumOperands = 0; + mInstructions[i + 1]->mCode = IC_CONSTANT; + mInstructions[i + 1]->mConst.mType = IT_BOOL; + mInstructions[i + 1]->mConst.mIntConst = 1; + changed = true; + } + } + } + } #endif } diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 28cd27c..e520776 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1252,24 +1252,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); if (vp.mTemp != vr.mTemp) - { - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); - cins->mNumOperands = 2; - - cins->mSrc[0].mType = IT_POINTER; - cins->mSrc[0].mTemp = vr.mTemp; - cins->mSrc[0].mMemory = IM_INDIRECT; - cins->mSrc[0].mOperandSize = vp.mType->mSize; - cins->mSrc[0].mStride = vr.mType->mStripe; - - cins->mSrc[1].mType = IT_POINTER; - cins->mSrc[1].mTemp = ains->mDst.mTemp; - cins->mSrc[1].mMemory = IM_INDIRECT; - cins->mSrc[1].mOperandSize = vp.mType->mSize; - - cins->mConst.mOperandSize = vp.mType->mSize; - block->Append(cins); - } + CopyStructSimple(proc, exp, block, vp, vr); } else { @@ -1390,6 +1373,73 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro return ExValue(TheVoidTypeDeclaration); } +void InterCodeGenerator::CopyStructSimple(InterCodeProcedure* proc, Expression * exp, InterCodeBasicBlock* block, ExValue vl, ExValue vr) +{ + int ne = 0; + Declaration* mdec = nullptr; + if (vl.mType->mType == DT_TYPE_STRUCT) + { + Declaration* dec = vl.mType->mParams; + while (dec) + { + if (dec->mType == DT_ELEMENT && !(dec->mFlags & DTF_STATIC)) + { + mdec = dec->mBase; + ne++; + } + dec = dec->mNext; + } + } + + // Single element structs are copied as individual value + if (ne == 1 && mdec->mSize == vl.mType->mSize) + { + InterInstruction* lins = new InterInstruction(exp->mLocation, IC_LOAD); + lins->mNumOperands = 1; + + lins->mSrc[0].mType = IT_POINTER; + lins->mSrc[0].mTemp = vr.mTemp; + lins->mSrc[0].mMemory = IM_INDIRECT; + lins->mSrc[0].mOperandSize = mdec->mSize; + lins->mSrc[0].mStride = mdec->mStripe; + + lins->mDst.mType = InterTypeOf(mdec); + lins->mDst.mTemp = proc->AddTemporary(lins->mDst.mType); + block->Append(lins); + + InterInstruction* sins = new InterInstruction(exp->mLocation, IC_STORE); + sins->mNumOperands = 2; + + sins->mSrc[1].mType = IT_POINTER; + sins->mSrc[1].mTemp = vl.mTemp; + sins->mSrc[1].mMemory = IM_INDIRECT; + sins->mSrc[1].mOperandSize = mdec->mSize; + sins->mSrc[1].mStride = mdec->mStripe; + + sins->mSrc[0] = lins->mDst; + block->Append(sins); + } + else + { + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + cins->mNumOperands = 2; + + cins->mSrc[0].mType = IT_POINTER; + cins->mSrc[0].mTemp = vr.mTemp; + cins->mSrc[0].mMemory = IM_INDIRECT; + cins->mSrc[0].mOperandSize = vr.mType->mSize; + cins->mSrc[0].mStride = vr.mType->mStripe; + + cins->mSrc[1].mOperandSize = vl.mType->mSize; + cins->mSrc[1].mType = IT_POINTER; + cins->mSrc[1].mTemp = vl.mTemp; + cins->mSrc[1].mMemory = IM_INDIRECT; + + cins->mConst.mOperandSize = vl.mType->mSize; + block->Append(cins); + } +} + void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving) { if (vr.mTemp == vl.mTemp) @@ -1587,24 +1637,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I } } else - { - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); - cins->mNumOperands = 2; - - cins->mSrc[0].mType = IT_POINTER; - cins->mSrc[0].mTemp = vr.mTemp; - cins->mSrc[0].mMemory = IM_INDIRECT; - cins->mSrc[0].mOperandSize = vr.mType->mSize; - cins->mSrc[0].mStride = vr.mType->mStripe; - - cins->mSrc[1].mOperandSize = vl.mType->mSize; - cins->mSrc[1].mType = IT_POINTER; - cins->mSrc[1].mTemp = vl.mTemp; - cins->mSrc[1].mMemory = IM_INDIRECT; - - cins->mConst.mOperandSize = vl.mType->mSize; - block->Append(cins); - } + CopyStructSimple(proc, exp, block, vl, vr); } InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, ExValue* lrexp) @@ -2104,24 +2137,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); if (vr.mTemp != vl.mTemp) - { - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_COPY); - ins->mNumOperands = 2; - - ins->mSrc[0].mType = IT_POINTER; - ins->mSrc[0].mTemp = vr.mTemp; - ins->mSrc[0].mMemory = IM_INDIRECT; - ins->mSrc[0].mOperandSize = vl.mType->mSize; - ins->mSrc[0].mStride = vr.mType->mStripe; - - ins->mSrc[1].mType = IT_POINTER; - ins->mSrc[1].mTemp = vl.mTemp; - ins->mSrc[1].mMemory = IM_INDIRECT; - ins->mSrc[1].mOperandSize = vl.mType->mSize; - ins->mSrc[1].mStride = vl.mType->mStripe; - ins->mConst.mOperandSize = vl.mType->mSize; - block->Append(ins); - } + CopyStructSimple(proc, exp, block, vl, vr); } else { diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 79f9bb0..67d3e2a 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -87,6 +87,7 @@ protected: void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper); ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp); void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving); + void CopyStructSimple(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock * block, ExValue vl, ExValue vr); void StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr); void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom, InlineMapper* inlineMapper); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 7b7e2d8..b191c87 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -5334,7 +5334,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) if (dec) { - if (dec->mType == DT_ELEMENT || dec->mType == DT_CONST_FUNCTION) + if ((dec->mType == DT_ELEMENT || dec->mType == DT_CONST_FUNCTION) && !(dec->mFlags & DTF_STATIC)) { Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE); texp->mDecType = mThisPointer->mBase;