Started constant_push handling Started to revamp the custom allocators
authorBenjamin Segovia <devnull@localhost>
Sun, 20 May 2012 19:57:32 +0000 (19:57 +0000)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:17:46 +0000 (16:17 -0700)
13 files changed:
backend/src/CMakeLists.txt
backend/src/ir/constant_push.cpp [new file with mode: 0644]
backend/src/ir/constant_push.hpp [new file with mode: 0644]
backend/src/ir/context.cpp
backend/src/ir/context.hpp
backend/src/ir/function.cpp
backend/src/ir/function.hpp
backend/src/ir/lowering.cpp
backend/src/ir/register.hpp
backend/src/ir/unit.hpp
backend/src/ir/value.cpp
backend/src/sys/alloc.hpp
backend/src/sys/platform.hpp

index c6c71d2..a87279f 100644 (file)
@@ -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 (file)
index 0000000..f708cd3
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+/**
+ * \file constant_push.cpp
+ * \author Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#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 (file)
index 0000000..4c01561
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+/**
+ * \file constant_push.hpp
+ * \author Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+#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<Register, ArgLocation> constantMap;
+    GBE_CLASS(ConstantPush); // Uses GBE allocators
+  };
+
+} /* namespace ir */
+} /* namespace gbe */
+
+#endif /* __GBE_IR_CONSTANT_PUSH_HPP__ */
index d6000b4..d30feee 100644 (file)
@@ -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);
index 5809545..33c1407 100644 (file)
@@ -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 <typename... Args> INLINE Tuple tuple(Args...args) {
       GBE_ASSERTM(fn != NULL, "No function currently defined");
index 662ba2a..59f8ab6 100644 (file)
@@ -22,6 +22,7 @@
  * \author Benjamin Segovia <benjamin.segovia@intel.com>
  */
 #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) {
index a74a02b..0e633d5 100644 (file)
@@ -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<BasicBlock*> 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
   };
 
index 6c65eae..7567bac 100644 (file)
@@ -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<const Instruction*> &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<LoadInstruction>(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<ArgLocation> inserted;
+    for (const auto &loadAddImm : seq) {
+      LoadInstruction *load = cast<LoadInstruction>(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<LoadInstruction>(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<const Instruction*> 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. "
index 70caab3..b3dfef9 100644 (file)
@@ -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<RegisterData> regs;   //!< All the registers together
     vector<Register> 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);
 
index 7473020..f8b2a72 100644 (file)
@@ -77,6 +77,7 @@ namespace ir {
         return FAMILY_QWORD;
     }
   private:
+    friend class ContextInterface; //!< Can free modify the unit
     hash_map<std::string, Function*> functions; //!< All the defined functions
     ConstantSet constantSet; //!< All the constants defined in the unit
     PointerSize pointerSize; //!< Size shared by all pointers
index 895720c..73fa5d6 100644 (file)
@@ -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 &reg) const {
     return this->getUse(ValueDef(reg));
index ba00aff..bc155c6 100644 (file)
@@ -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<TYPE>::value > sizeof(uintptr_t))            \
-      return gbe::alignedMalloc(size, AlignOf<TYPE>::value); \
-    else                                                     \
-      return gbe::memAlloc(size);                            \
-  }                                                          \
-  void* operator new[](size_t size)   {                      \
-    if (AlignOf<TYPE>::value > sizeof(uintptr_t))            \
-      return gbe::alignedMalloc(size, AlignOf<TYPE>::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<TYPE>::value > sizeof(uintptr_t))            \
-      return gbe::alignedFree(ptr);                          \
-    else                                                     \
-      return gbe::memFree(ptr);                              \
-  }                                                          \
-  void  operator delete[](void* ptr) {                       \
-    if (AlignOf<TYPE>::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<TYPE> POOL;                         \
-  template <typename... Args>                     \
-  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<TYPE> POOL; \
+  template <typename... Args> \
+  TYPE *new##TYPE(Args... args) { \
+    return new (POOL.allocate()) TYPE(args...); \
+  } \
+  void delete##TYPE(TYPE *ptr) { \
+    ptr->~TYPE(); \
+    POOL.deallocate(ptr); \
   }
 } /* namespace gbe */
 
index 78768c3..4f3b300 100644 (file)
 
 /*! 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)
 #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 <typename T>
-struct AlignOf
-{
+struct AlignOf {
   struct Helper { char x; T t; };
   enum { value = offsetof(Helper, t) };
 };