From: Benjamin Segovia Date: Sun, 20 May 2012 19:57:32 +0000 (+0000) Subject: Started constant_push handling Started to revamp the custom allocators X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c3e90e6a50ff810fbacda9c960d72d0ee6b6aa22;p=contrib%2Fbeignet.git Started constant_push handling Started to revamp the custom allocators --- diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt index c6c71d2..a87279f 100644 --- a/backend/src/CMakeLists.txt +++ b/backend/src/CMakeLists.txt @@ -62,6 +62,8 @@ else (GBE_USE_BLOB) ir/unit.hpp ir/constant.cpp ir/constant.hpp + ir/constant_push.cpp + ir/constant_push.hpp ir/instruction.cpp ir/instruction.hpp ir/liveness.cpp diff --git a/backend/src/ir/constant_push.cpp b/backend/src/ir/constant_push.cpp new file mode 100644 index 0000000..f708cd3 --- /dev/null +++ b/backend/src/ir/constant_push.cpp @@ -0,0 +1,33 @@ +/* + * Copyright © 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Benjamin Segovia + */ + +/** + * \file constant_push.cpp + * \author Benjamin Segovia + */ + +#include "ir/constant_push.hpp" + +namespace gbe { +namespace ir { + ConstantPush::ConstantPush(void) {} + ConstantPush::~ConstantPush(void) {} +} /* namespace ir */ +} /* namespace gbe */ + diff --git a/backend/src/ir/constant_push.hpp b/backend/src/ir/constant_push.hpp new file mode 100644 index 0000000..4c01561 --- /dev/null +++ b/backend/src/ir/constant_push.hpp @@ -0,0 +1,61 @@ +/* + * Copyright © 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Benjamin Segovia + */ + +/** + * \file constant_push.hpp + * \author Benjamin Segovia + */ +#ifndef __GBE_IR_CONSTANT_PUSH_HPP__ +#define __GBE_IR_CONSTANT_PUSH_HPP__ + +#include "ir/register.hpp" +#include "sys/map.hpp" + +namespace gbe { +namespace ir { + + /*! Maps the register to the function argument */ + struct ArgLocation { + INLINE ArgLocation(void) {} + INLINE ArgLocation(uint32_t argID, uint32_t offset) : + argID(argID), offset(offset) {} + uint32_t argID; //!< Function argument + uint32_t offset; //!< Offset in the function argument + }; + + /*! Structure arguments can be directly pushed to the register file. We store + * here the mapping the function argument and the registers that contains the + * pushed data + */ + class ConstantPush + { + public: + /*! Set the contanst pushing description */ + ConstantPush(void); + /*! Set the contanst pushing description */ + ~ConstantPush(void); + /*! Maps each register with the function argument */ + map constantMap; + GBE_CLASS(ConstantPush); // Uses GBE allocators + }; + +} /* namespace ir */ +} /* namespace gbe */ + +#endif /* __GBE_IR_CONSTANT_PUSH_HPP__ */ diff --git a/backend/src/ir/context.cpp b/backend/src/ir/context.cpp index d6000b4..d30feee 100644 --- a/backend/src/ir/context.cpp +++ b/backend/src/ir/context.cpp @@ -37,6 +37,11 @@ namespace ir { GBE_SAFE_DELETE(usedLabels); } + Function &Context::getFunction(void) { + GBE_ASSERTM(fn != NULL, "No function currently defined"); + return *fn; + } + void Context::startFunction(const std::string &name) { fnStack.push_back(StackElem(fn,bb,usedLabels)); fn = unit.newFunction(name); @@ -49,6 +54,9 @@ namespace ir { GBE_ASSERT(fnStack.size() != 0); GBE_ASSERT(usedLabels != NULL); + // Empty function -> append a return + if (fn->blockNum() == 0) this->RET(); + // Check first that all branch instructions point to valid labels for (auto it = usedLabels->begin(); it != usedLabels->end(); ++it) GBE_ASSERTM(*it != LABEL_IS_POINTED, "A label is used and not defined"); @@ -72,11 +80,6 @@ namespace ir { usedLabels = elem.usedLabels; } - Function &Context::getFunction(void) { - GBE_ASSERTM(fn != NULL, "No function currently defined"); - return *fn; - } - Register Context::reg(RegisterFamily family) { GBE_ASSERTM(fn != NULL, "No function currently defined"); return fn->newRegister(family); diff --git a/backend/src/ir/context.hpp b/backend/src/ir/context.hpp index 5809545..33c1407 100644 --- a/backend/src/ir/context.hpp +++ b/backend/src/ir/context.hpp @@ -35,9 +35,6 @@ namespace gbe { namespace ir { - // We compile a unit - class Unit; - /*! A context allows an easy creation of the functions (instruction stream and * the set of immediates and registers needed for it) and constant arrays */ @@ -47,11 +44,15 @@ namespace ir { /*! Create a new context for this unit */ Context(Unit &unit); /*! Free resources needed by context */ - ~Context(void); + virtual ~Context(void); /*! Create a new function "name" */ void startFunction(const std::string &name); /*! Close the function */ void endFunction(void); + /*! Get the current processed unit */ + INLINE Unit &getUnit(void) { return unit; } + /*! Get the current processed function */ + Function &getFunction(void); /*! Create a new register with the given family for the current function */ Register reg(RegisterFamily family); /*! Create a new immediate value */ @@ -84,10 +85,6 @@ namespace ir { INLINE Immediate getImmediate(ImmediateIndex index) const { return fn->getImmediate(index); } - /*! Get the current processed function */ - Function &getFunction(void); - /*! Get the current processed unit */ - INLINE Unit &getUnit(void) { return unit; } /*! Append a new tuple */ template INLINE Tuple tuple(Args...args) { GBE_ASSERTM(fn != NULL, "No function currently defined"); diff --git a/backend/src/ir/function.cpp b/backend/src/ir/function.cpp index 662ba2a..59f8ab6 100644 --- a/backend/src/ir/function.cpp +++ b/backend/src/ir/function.cpp @@ -22,6 +22,7 @@ * \author Benjamin Segovia */ #include "ir/function.hpp" +#include "ir/constant_push.hpp" #include "sys/string.hpp" #include "sys/map.hpp" @@ -29,12 +30,13 @@ namespace gbe { namespace ir { Function::Function(const std::string &name, Profile profile) : - name(name), profile(profile) + name(name), profile(profile), pushedConstant(NULL) { initProfile(*this); } Function::~Function(void) { for (auto it = blocks.begin(); it != blocks.end(); ++it) GBE_DELETE(*it); for (auto it = args.begin(); it != args.end(); ++it) GBE_DELETE(*it); + GBE_SAFE_DELETE(pushedConstant); } void Function::sortLabels(void) { diff --git a/backend/src/ir/function.hpp b/backend/src/ir/function.hpp index a74a02b..0e633d5 100644 --- a/backend/src/ir/function.hpp +++ b/backend/src/ir/function.hpp @@ -135,6 +135,11 @@ namespace ir { uint32_t size; /*! == sizeof(void*) for pointer, sizeof(elem) for the rest */ }; + /*! Constant values can be pushed into registers by the hardware. This class + * maintains the mapping between virtual registers and pushed values + */ + class ConstantPush; + /*! A function is no more that a set of declared registers and a set of * basic blocks */ @@ -291,6 +296,7 @@ namespace ir { vector blocks; //!< All chained basic blocks RegisterFile file; //!< RegisterDatas used by the instructions Profile profile; //!< Current function profile + ConstantPush *pushedConstant; //!< All constants pushed before function is called GBE_CLASS(Function); //!< Use gbe allocators }; diff --git a/backend/src/ir/lowering.cpp b/backend/src/ir/lowering.cpp index 6c65eae..7567bac 100644 --- a/backend/src/ir/lowering.cpp +++ b/backend/src/ir/lowering.cpp @@ -65,9 +65,8 @@ namespace ir { } void lowerReturn(Unit &unit, const std::string &functionName) { - ContextReturn *ctx = GBE_NEW(ContextReturn, unit); - ctx->lower(functionName); - GBE_DELETE(ctx); + ContextReturn ctx(unit); + ctx.lower(functionName); } /*! Characterizes how the argument is used (directly read, indirectly read, @@ -87,6 +86,7 @@ namespace ir { Instruction *add; //!< Can be NULL if we only have load(arg) Instruction *loadImm; //!< Can also be NULL uint64_t offset; //!< Offset where to load in the structure + uint32_t argID; //!< Associated function argument }; /*! List of direct loads */ @@ -103,16 +103,18 @@ namespace ir { /*! Perform all function arguments substitution if needed */ void lower(const std::string &name); /*! Lower the given function argument accesses */ - void lower(FunctionArgument &arg); + void lower(uint32_t argID); + /*! Build the constant push for the function */ + void buildConstantPush(void); /*! Inspect the given function argument to see how it is used. If this is * direct loads only, we also output the list of instructions used for each * load */ - ArgUse getArgUse(FunctionArgument &arg); + ArgUse getArgUse(uint32_t argID); /*! Recursively look if there is a store in the given use */ bool useStore(const ValueDef &def, set &visited); /*! Look if the pointer use only load with immediate offsets */ - bool matchLoadAddImm(const FunctionArgument &arg); + bool matchLoadAddImm(uint32_t argID); Liveness *liveness; //!< To compute the function graph FunctionDAG *dag; //!< Contains complete dependency information Unit &unit; //!< The unit we process @@ -120,6 +122,48 @@ namespace ir { LoadAddImmSeq seq; //!< All the direct loads }; + INLINE uint64_t getOffsetFromImm(const Immediate &imm) { + switch (imm.type) { + case TYPE_DOUBLE: + case TYPE_FLOAT: + case TYPE_S64: + case TYPE_U64: + case TYPE_U32: + case TYPE_U16: + case TYPE_U8: return imm.data.u64; + case TYPE_S32: return int64_t(imm.data.s32); + case TYPE_S16: return int64_t(imm.data.s16); + case TYPE_S8: return int64_t(imm.data.s8); + case TYPE_BOOL: + case TYPE_HALF: NOT_SUPPORTED; return 0; + } + return 0; + } + + bool matchLoad(Instruction *insn, + Instruction *add, + Instruction *loadImm, + uint64_t offset, + uint32_t argID, + LoadAddImm &loadAddImm) + { + const Opcode opcode = insn->getOpcode(); + + if (opcode == OP_LOAD) { + LoadInstruction *load = cast(insn); + if (load->getAddressSpace() != MEM_PRIVATE) + return false; + loadAddImm.load = insn; + loadAddImm.add = add; + loadAddImm.loadImm = loadImm; + loadAddImm.offset = offset; + loadAddImm.argID = argID; + return true; + } else + return false; + } + + FunctionArgumentLowerer::FunctionArgumentLowerer(Unit &unit) : liveness(NULL), dag(NULL), unit(unit) {} FunctionArgumentLowerer::~FunctionArgumentLowerer(void) { @@ -134,11 +178,43 @@ namespace ir { GBE_SAFE_DELETE(liveness); this->liveness = GBE_NEW(ir::Liveness, *fn); this->dag = GBE_NEW(ir::FunctionDAG, *this->liveness); + + // Process all structure arguments and find all the direct loads we can + // replace const uint32_t argNum = fn->argNum(); for (uint32_t argID = 0; argID < argNum; ++argID) { FunctionArgument &arg = fn->getInput(argID); if (arg.type != FunctionArgument::STRUCTURE) continue; - this->lower(arg); + this->lower(argID); + } + } + + INLINE bool operator< (const ArgLocation &arg0, const ArgLocation &arg1) { + if (arg0.argID != arg1.argID) return arg0.argID < arg1.argID; + return arg0.offset < arg1.offset; + } + + void FunctionArgumentLowerer::buildConstantPush(void) + { + // The argument location we already pushed (since the same argument location + // can be used several times) + set inserted; + for (const auto &loadAddImm : seq) { + LoadInstruction *load = cast(loadAddImm.load); + const uint32_t valueNum = load->getValueNum(); + for (uint32_t valueID = 0; valueID < valueNum; ++valueID) { + const Type type = load->getValueType(); + const RegisterFamily family = getFamily(type); + const uint32_t size = getFamilySize(family); + const uint32_t offset = loadAddImm.offset + valueID * size; + const ArgLocation argLocation(loadAddImm.argID, offset); + if (inserted.contains(argLocation)) + continue; + const Register reg = load->getValue(valueID); + const Register pushed = fn->newRegister(family); + const Instruction mov = MOV(type, reg, pushed); + mov.replace(load); + } } } @@ -167,46 +243,9 @@ namespace ir { return false; } - INLINE uint64_t getOffsetFromImm(const Immediate &imm) { - switch (imm.type) { - case TYPE_DOUBLE: - case TYPE_FLOAT: - case TYPE_S64: - case TYPE_U64: - case TYPE_U32: - case TYPE_U16: - case TYPE_U8: return imm.data.u64; - case TYPE_S32: return int64_t(imm.data.s32); - case TYPE_S16: return int64_t(imm.data.s16); - case TYPE_S8: return int64_t(imm.data.s8); - case TYPE_BOOL: - case TYPE_HALF: NOT_SUPPORTED; return 0; - } - return 0; - } - - bool matchLoad(Instruction *insn, - Instruction *add, - Instruction *loadImm, - uint64_t offset, - LoadAddImm &loadAddImm) + bool FunctionArgumentLowerer::matchLoadAddImm(uint32_t argID) { - const Opcode opcode = insn->getOpcode(); - - if (opcode == OP_LOAD) { - LoadInstruction *load = cast(insn); - if (load->getAddressSpace() != MEM_PRIVATE) - return false; - loadAddImm.load = insn; - loadAddImm.add = add; - loadAddImm.loadImm = loadImm; - loadAddImm.offset = offset; - return true; - } else - return false; - } - - bool FunctionArgumentLowerer::matchLoadAddImm(const FunctionArgument &arg) { + const FunctionArgument &arg = fn->getInput(argID); LoadAddImmSeq tmpSeq; // Inspect all uses of the function argument pointer @@ -217,7 +256,7 @@ namespace ir { // load dst arg LoadAddImm loadAddImm; - if (matchLoad(insn, NULL, NULL, 0, loadAddImm)) { + if (matchLoad(insn, NULL, NULL, 0, argID, loadAddImm)) { tmpSeq.push_back(loadAddImm); continue; } @@ -252,7 +291,7 @@ namespace ir { // We finally find something like load dst arg+imm LoadAddImm loadAddImm; - if (matchLoad(insn, add, loadImm, offset, loadAddImm)) { + if (matchLoad(insn, add, loadImm, offset, argID, loadAddImm)) { tmpSeq.push_back(loadAddImm); continue; } @@ -266,23 +305,25 @@ namespace ir { return true; } - ArgUse FunctionArgumentLowerer::getArgUse(FunctionArgument &arg) + ArgUse FunctionArgumentLowerer::getArgUse(uint32_t argID) { + FunctionArgument &arg = fn->getInput(argID); + // case 1 - we may store something to the structure argument set visited; if (this->useStore(ValueDef(&arg), visited)) return ARG_WRITTEN; // case 2 - we look for the patterns: LOAD(ptr) or LOAD(ptr+imm) - if (this->matchLoadAddImm(arg)) + if (this->matchLoadAddImm(argID)) return ARG_DIRECT_READ; // case 3 - LOAD(ptr+runtime_value) return ARG_INDIRECT_READ; } - void FunctionArgumentLowerer::lower(FunctionArgument &arg) { - const ArgUse argUse = this->getArgUse(arg); + void FunctionArgumentLowerer::lower(uint32_t argID) { + const ArgUse argUse = this->getArgUse(argID); GBE_ASSERTM(argUse != ARG_WRITTEN, "TODO A store to a structure argument " "(i.e. not a char/short/int/float argument) has been found. " diff --git a/backend/src/ir/register.hpp b/backend/src/ir/register.hpp index 70caab3..b3dfef9 100644 --- a/backend/src/ir/register.hpp +++ b/backend/src/ir/register.hpp @@ -39,6 +39,17 @@ namespace ir { FAMILY_QWORD = 4 }; + INLINE uint32_t getFamilySize(RegisterFamily family) { + switch (family) { + case FAMILY_BYTE: return 1; + case FAMILY_WORD: return 2; + case FAMILY_DWORD: return 4; + case FAMILY_QWORD: return 8; + default: NOT_SUPPORTED; + }; + return 0; + } + /*! A register can be either a byte, a word, a dword or a qword. We store this * value into a register data (which makes the register file) */ @@ -70,8 +81,6 @@ namespace ir { INLINE bool operator< (const Register &r0, const Register &r1) { return r0.value() < r1.value(); } - /*! Useful to encode anything special */ - static const Register invalidRegister(0xffff); /*! Tuple is the position of the first register in the tuple vector. We * enforce type safety with this class @@ -86,8 +95,8 @@ namespace ir { public: /*! Return the index of a newly allocated register */ INLINE Register append(RegisterFamily family) { - GBE_ASSERTM(regNum() <= MAX_INDEX, - "Too many defined registers (only 65536 are supported)"); + GBE_ASSERTM(regNum() < MAX_INDEX, + "Too many defined registers (only 65535 are supported)"); const uint16_t index = regNum(); const RegisterData reg(family); regs.push_back(reg); @@ -121,13 +130,17 @@ namespace ir { INLINE uint32_t regNum(void) const { return regs.size(); } /*! Number of tuples in the register file */ INLINE uint32_t tupleNum(void) const { return regTuples.size(); } + /*! register and tuple indices are short */ + enum { MAX_INDEX = 0xffff }; private: vector regs; //!< All the registers together vector regTuples; //!< Tuples are used for many src / dst - enum { MAX_INDEX = 0xffff }; //!< register and tuple indices are short GBE_CLASS(RegisterFile); }; + /*! Useful to encode anything special */ + static const Register invalidRegister(RegisterFile::MAX_INDEX); + /*! Output the register file string in the given stream */ std::ostream &operator<< (std::ostream &out, const RegisterFile &file); diff --git a/backend/src/ir/unit.hpp b/backend/src/ir/unit.hpp index 7473020..f8b2a72 100644 --- a/backend/src/ir/unit.hpp +++ b/backend/src/ir/unit.hpp @@ -77,6 +77,7 @@ namespace ir { return FAMILY_QWORD; } private: + friend class ContextInterface; //!< Can free modify the unit hash_map functions; //!< All the defined functions ConstantSet constantSet; //!< All the constants defined in the unit PointerSize pointerSize; //!< Size shared by all pointers diff --git a/backend/src/ir/value.cpp b/backend/src/ir/value.cpp index 895720c..73fa5d6 100644 --- a/backend/src/ir/value.cpp +++ b/backend/src/ir/value.cpp @@ -28,7 +28,7 @@ namespace gbe { namespace ir { - /*! To build the chains (i.e. basically the DAG of values), we are going to + /*! To build the chains (i.e. basically the graph of values), we are going to * iterate on liveout definitions: for each block and for each variable * (ir::Register) alive at the end of the block (in Block::LiveOut), we are * computing the set of all possible value definitions. Using these value @@ -482,8 +482,8 @@ namespace ir { const UseSet &FunctionDAG::getUse(const Instruction *insn, uint32_t dstID) const { return this->getUse(ValueDef(insn, dstID)); } - const UseSet &FunctionDAG::getUse(const FunctionArgument *input) const { - return this->getUse(ValueDef(input)); + const UseSet &FunctionDAG::getUse(const FunctionArgument *arg) const { + return this->getUse(ValueDef(arg)); } const UseSet &FunctionDAG::getUse(const Register ®) const { return this->getUse(ValueDef(reg)); diff --git a/backend/src/sys/alloc.hpp b/backend/src/sys/alloc.hpp index ba00aff..bc155c6 100644 --- a/backend/src/sys/alloc.hpp +++ b/backend/src/sys/alloc.hpp @@ -63,62 +63,46 @@ namespace gbe /*! Declare a class with custom allocators */ #define GBE_CLASS(TYPE) \ - GBE_STRUCT(TYPE) \ + GBE_STRUCT(TYPE) \ private: /*! Declare a structure with custom allocators */ -#define GBE_STRUCT(TYPE) \ -public: \ - void* operator new(size_t size) { \ - if (AlignOf::value > sizeof(uintptr_t)) \ - return gbe::alignedMalloc(size, AlignOf::value); \ - else \ - return gbe::memAlloc(size); \ - } \ - void* operator new[](size_t size) { \ - if (AlignOf::value > sizeof(uintptr_t)) \ - return gbe::alignedMalloc(size, AlignOf::value); \ - else \ - return gbe::memAlloc(size); \ - } \ - void* operator new(size_t size, void *p) { return p; } \ - void* operator new[](size_t size, void *p) { return p; } \ - void operator delete(void* ptr) { \ - if (AlignOf::value > sizeof(uintptr_t)) \ - return gbe::alignedFree(ptr); \ - else \ - return gbe::memFree(ptr); \ - } \ - void operator delete[](void* ptr) { \ - if (AlignOf::value > sizeof(uintptr_t)) \ - return gbe::alignedFree(ptr); \ - else \ - return gbe::memFree(ptr); \ - } \ +#define GBE_STRUCT(TYPE) \ +public: \ + void* operator new(size_t size) { \ + return gbe::alignedMalloc(size, GBE_DEFAULT_ALIGNMENT); \ + } \ + void* operator new[](size_t size) { \ + return gbe::alignedMalloc(size, GBE_DEFAULT_ALIGNMENT); \ + } \ + void* operator new(size_t size, void *p) { return p; } \ + void* operator new[](size_t size, void *p) { return p; } \ + void operator delete(void* ptr) { return gbe::alignedFree(ptr); } \ + void operator delete[](void* ptr) { return gbe::alignedFree(ptr); } /*! Macros to handle allocation position */ -#define GBE_NEW(T,...) \ +#define GBE_NEW(T,...) \ gbe::_MemDebuggerInsertAlloc(new T(__VA_ARGS__), __FILE__, __FUNCTION__, __LINE__) -#define GBE_NEW_ARRAY(T,N,...) \ +#define GBE_NEW_ARRAY(T,N,...) \ gbe::_MemDebuggerInsertAlloc(new T[N](__VA_ARGS__), __FILE__, __FUNCTION__, __LINE__) -#define GBE_NEW_P(T,X,...) \ +#define GBE_NEW_P(T,X,...) \ gbe::_MemDebuggerInsertAlloc(new (X) T(__VA_ARGS__), __FILE__, __FUNCTION__, __LINE__) -#define GBE_DELETE(X) \ +#define GBE_DELETE(X) \ do { gbe::MemDebuggerRemoveAlloc(X); delete X; } while (0) -#define GBE_DELETE_ARRAY(X) \ +#define GBE_DELETE_ARRAY(X) \ do { gbe::MemDebuggerRemoveAlloc(X); delete[] X; } while (0) -#define GBE_MALLOC(SZ) \ +#define GBE_MALLOC(SZ) \ gbe::MemDebuggerInsertAlloc(gbe::memAlloc(SZ),__FILE__, __FUNCTION__, __LINE__) -#define GBE_FREE(X) \ +#define GBE_FREE(X) \ do { gbe::MemDebuggerRemoveAlloc(X); gbe::memFree(X); } while (0) -#define GBE_ALIGNED_FREE(X) \ +#define GBE_ALIGNED_FREE(X) \ do { gbe::MemDebuggerRemoveAlloc(X); gbe::alignedFree(X); } while (0) #define GBE_ALIGNED_MALLOC(SZ,ALIGN) \ @@ -223,15 +207,15 @@ namespace gbe }; /*! Helper macros to build and destroy objects with a pool */ -#define DECL_POOL(TYPE, POOL) \ - GrowingPool POOL; \ - template \ - TYPE *new##TYPE(Args... args) { \ - return new (POOL.allocate()) TYPE(args...); \ - } \ - void delete##TYPE(TYPE *ptr) { \ - ptr->~TYPE(); \ - POOL.deallocate(ptr); \ +#define DECL_POOL(TYPE, POOL) \ + GrowingPool POOL; \ + template \ + TYPE *new##TYPE(Args... args) { \ + return new (POOL.allocate()) TYPE(args...); \ + } \ + void delete##TYPE(TYPE *ptr) { \ + ptr->~TYPE(); \ + POOL.deallocate(ptr); \ } } /* namespace gbe */ diff --git a/backend/src/sys/platform.hpp b/backend/src/sys/platform.hpp index 78768c3..4f3b300 100644 --- a/backend/src/sys/platform.hpp +++ b/backend/src/sys/platform.hpp @@ -209,13 +209,13 @@ /*! Run-time assertion */ #if GBE_DEBUG -#define GBE_ASSERT(EXPR) do { \ - if (UNLIKELY(!(EXPR))) \ - gbe::onFailedAssertion(#EXPR, __FILE__, __FUNCTION__, __LINE__);\ +#define GBE_ASSERT(EXPR) do { \ + if (UNLIKELY(!(EXPR))) \ + gbe::onFailedAssertion(#EXPR, __FILE__, __FUNCTION__, __LINE__); \ } while (0) -#define GBE_ASSERTM(EXPR, MSG) do { \ - if (UNLIKELY(!(EXPR))) \ - gbe::onFailedAssertion(MSG, __FILE__, __FUNCTION__, __LINE__); \ +#define GBE_ASSERTM(EXPR, MSG) do { \ + if (UNLIKELY(!(EXPR))) \ + gbe::onFailedAssertion(MSG, __FILE__, __FUNCTION__, __LINE__); \ } while (0) #else #define GBE_ASSERT(EXPR) do { } while (0) @@ -226,9 +226,9 @@ #define NOT_SUPPORTED GBE_ASSERTM (false, "Not supported") /*! Fatal error macros */ -#define FATAL_IF(COND, MSG) \ -do { \ - if(UNLIKELY(COND)) FATAL(MSG); \ +#define FATAL_IF(COND, MSG) \ +do { \ + if(UNLIKELY(COND)) FATAL(MSG); \ } while (0) /* Safe deletion macros */ @@ -245,22 +245,24 @@ do { \ #define HERE (STRING(__LINE__) "@" __FILE__) /*! Typesafe encapusalation of a type (mostly for integers) */ -#define TYPE_SAFE(SAFE, UNSAFE) \ -class SAFE \ -{ \ -public: \ - INLINE SAFE(void) {} \ - explicit INLINE SAFE(uint16_t unsafe) : unsafe(unsafe) {} \ - INLINE operator UNSAFE (void) const { return unsafe; } \ - UNSAFE value(void) const { return unsafe; } \ -private: \ - UNSAFE unsafe; \ +#define TYPE_SAFE(SAFE, UNSAFE) \ +class SAFE \ +{ \ +public: \ + INLINE SAFE(void) {} \ + explicit INLINE SAFE(uint16_t unsafe) : unsafe(unsafe) {} \ + INLINE operator UNSAFE (void) const { return unsafe; } \ + UNSAFE value(void) const { return unsafe; } \ +private: \ + UNSAFE unsafe; \ }; +/*! Default alignment for the platform */ +#define GBE_DEFAULT_ALIGNMENT 16 + /*! Portable AlignOf */ template -struct AlignOf -{ +struct AlignOf { struct Helper { char x; T t; }; enum { value = offsetof(Helper, t) }; };