Ensure type safety for tuple and register indices by making specific classes
authorBenjamin Segovia <segovia.benjamin@gmail.com>
Fri, 17 Feb 2012 03:13:18 +0000 (03:13 +0000)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:15:17 +0000 (16:15 -0700)
backend/src/ir/function.hpp
backend/src/ir/instruction.cpp
backend/src/ir/register.hpp
backend/src/sys/alloc.cpp
backend/src/sys/alloc.hpp

index e82f196..45434e8 100644 (file)
@@ -61,7 +61,7 @@ namespace ir {
     };
 
     /*! Extract the register from the register file */
-    INLINE Register getRegister(uint32_t ID) const { return file.get(ID); }
+    INLINE Register getRegister(RegisterIndex ID) const { return file.get(ID); }
     /*! Get the register index from the tuple vector */
     INLINE RegisterIndex getRegisterIndex(TupleIndex ID, uint32_t which) const {
       return file.get(ID, which);
index 1ccc47a..306446d 100644 (file)
@@ -40,7 +40,7 @@ namespace ir {
       INLINE uint32_t getSrcNum(void) const { return 0; }
       INLINE RegisterIndex getSrcIndex(const Function &fn, uint32_t ID) const {
         NOT_IMPLEMENTED;
-        return 0;
+        return RegisterIndex(0);
       }
     };
 
@@ -49,7 +49,7 @@ namespace ir {
       INLINE uint32_t getDstNum(void) const { return 0; }
       INLINE RegisterIndex getDstIndex(const Function &fn, uint32_t ID) const {
         NOT_IMPLEMENTED;
-        return 0;
+        return RegisterIndex(0);
       }
     };
 
@@ -271,8 +271,8 @@ namespace ir {
     {
     public:
       StoreInstruction(Type type,
-                       RegisterIndex offset,
                        TupleIndex values,
+                       RegisterIndex offset,
                        MemorySpace memSpace,
                        uint16_t valueNum)
       {
@@ -369,7 +369,7 @@ namespace ir {
                                      const Function &fn,
                                      std::string &whyNot)
     {
-      if (UNLIKELY(ID >= fn.regNum())) {
+      if (UNLIKELY(uint16_t(ID) >= fn.regNum())) {
         whyNot = "Out-of-bound destination register index";
         return false;
       }
@@ -644,7 +644,7 @@ END_FUNCTION(Instruction, RegisterIndex)
 #define CALL getSrcIndex(fn, ID)
 START_FUNCTION(Instruction, RegisterIndex, getSrcIndex(const Function &fn, uint32_t ID))
 #include "ir/instruction.hxx"
-END_FUNCTION(Instruction, bool)
+END_FUNCTION(Instruction, RegisterIndex)
 #undef CALL
 
 #define CALL wellFormed(fn, whyNot)
@@ -731,7 +731,7 @@ DECL_MEM_FN(BranchInstruction, bool, isPredicated(void), isPredicated())
   }
 
   // CVT
-  Instruction CVT(Type dstType, Type srcType, RegisterIndex dst, TupleIndex src) {
+  Instruction CVT(Type dstType, Type srcType, RegisterIndex dst, RegisterIndex src) {
     internal::ConvertInstruction insn(dstType, srcType, dst, src);
     return insn.convert();
   }
index cf97095..c2dd066 100644 (file)
@@ -19,7 +19,6 @@
 
 /**
  * \file register.hpp
- *
  * \author Benjamin Segovia <benjamin.segovia@intel.com>
  */
 #ifndef __GBE_IR_REGISTER_HPP__
@@ -59,11 +58,33 @@ namespace ir {
     GBE_CLASS(Register);
   };
 
-  /*! Register index is the position of the register in the register file */
-  typedef uint16_t RegisterIndex;
+  /*! Register index is the position of the register in the register file. We
+   *  enforce type safety with this class
+   */
+  class RegisterIndex
+  {
+  public:
+    INLINE RegisterIndex(void) {}
+    explicit INLINE RegisterIndex(uint16_t index) : index(index) {}
+    INLINE operator uint16_t (void) const { return index; }
+    uint16_t value(void) const { return index; }
+  private:
+    uint16_t index;
+  };
 
-  /*! Tuple index is the position of the register index in the tuple vector */
-  typedef uint32_t TupleIndex;
+  /*! Tuple index is the position of the register index in the tuple vector. We
+   *  enforce type safety with this class
+   */
+  class TupleIndex
+  {
+  public:
+    INLINE TupleIndex(void) {}
+    explicit INLINE TupleIndex(uint16_t index) : index(index) {}
+    INLINE operator uint16_t (void) const { return index; }
+    uint16_t value(void) const { return index; }
+  private:
+    uint16_t index;
+  };
 
   /*! A register file allocates and destroys registers. Basically, we will have
    *  one register file per function
@@ -73,16 +94,16 @@ namespace ir {
   public:
     /*! Return the index of a newly allocated register register */
     INLINE RegisterIndex append(Register::Family family) {
-      const uint32_t index = regNum();
+      GBE_ASSERT(regNum() <= MAX_INDEX);
+      const uint16_t index = regNum();
       const Register reg(family);
-      GBE_ASSERT(index <= MAX_INDEX);
       regs.push_back(reg);
-      return index;
+      return RegisterIndex(index);
     }
     /*! Make a tuple and return the index to the first element of the tuple */
     template <typename First, typename... Rest>
     INLINE TupleIndex appendTuple(First first, Rest... rest) {
-      const TupleIndex index = regTuples.size();
+      const TupleIndex index = TupleIndex(regTuples.size());
       GBE_ASSERT(first < regNum());
       regTuples.push_back(first);
       appendTuple(rest...);
@@ -97,8 +118,8 @@ namespace ir {
     }
     /*! Get the register index from the tuple */
     INLINE RegisterIndex get(TupleIndex index, uint32_t which) const {
-      GBE_ASSERT(index + which < regTuples.size());
-      return regTuples[index + which];
+      GBE_ASSERT(uint16_t(index) + which < regTuples.size());
+      return regTuples[uint16_t(index) + which];
     }
     /*! Number of registers in the register file */
     INLINE uint32_t regNum(void) const { return regs.size(); }
@@ -107,6 +128,7 @@ namespace ir {
   private:
     vector<Register> regs;           //!< All the registers together
     vector<RegisterIndex> regTuples; //!< Tuples are used for many src / dst
+    enum { MAX_INDEX = 0xffff };     //!< register and tuple indices are short
     GBE_CLASS(RegisterFile);
   };
 
index 11b91ef..67dcc15 100644 (file)
 ////////////////////////////////////////////////////////////////////////////////
 /// Memory debugger
 ////////////////////////////////////////////////////////////////////////////////
+#if GBE_DEBUG_MEMORY
 namespace gbe
 {
 
-#if GBE_DEBUG_MEMORY
   /*! Store each allocation data */
   struct AllocData {
     INLINE AllocData(void) {}
@@ -182,13 +182,13 @@ namespace gbe
 namespace gbe
 {
 #if GBE_DEBUG_MEMORY
-  void* malloc(size_t size) {
+  void* memAlloc(size_t size) {
     void *ptr = std::malloc(size + sizeof(size_t));
     *(size_t *) ptr = size;
     MemDebuggerInitializeMem((char*) ptr + sizeof(size_t), size);
     return (char *) ptr + sizeof(size_t);
   }
-  void free(void *ptr) {
+  void memFree(void *ptr) {
     if (ptr != NULL) {
       char *toFree = (char*) ptr - sizeof(size_t);
       const size_t size = *(size_t *) toFree;
@@ -197,8 +197,8 @@ namespace gbe
     }
   }
 #else
-  void* malloc(size_t size) { return  std::malloc(size); }
-  void free(void *ptr) { if (ptr != NULL) std::free(ptr); }
+  void* memAlloc(size_t size) { return  std::malloc(size); }
+  void memFree(void *ptr) { if (ptr != NULL) std::free(ptr); }
 #endif /* GBE_DEBUG_MEMORY */
 
 } /* namespace gbe */
@@ -273,7 +273,7 @@ namespace gbe
     return ptr;
   }
 
-  void alignedFree(void *ptr) { if (ptr) free(ptr); }
+  void alignedFree(void *ptr) { if (ptr) std::free(ptr); }
 } /* namespace gbe */
 
 #endif /* __LINUX__ */
index b61efa7..ab587de 100644 (file)
@@ -31,8 +31,8 @@
 namespace gbe
 {
   /*! regular allocation */
-  void* malloc(size_t size);
-  void  free(void *ptr);
+  void* memAlloc(size_t size);
+  void  memFree(void *ptr);
 
   /*! Aligned allocation */
   void* alignedMalloc(size_t size, size_t align = 64);
@@ -67,25 +67,25 @@ namespace gbe
     if (AlignOf<TYPE>::value > sizeof(uintptr_t))            \
       return gbe::alignedMalloc(size, AlignOf<TYPE>::value); \
     else                                                     \
-      return gbe::malloc(size);                              \
+      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::malloc(size);                              \
+      return gbe::memAlloc(size);                            \
   }                                                          \
   void  operator delete(void* ptr) {                         \
     if (AlignOf<TYPE>::value > sizeof(uintptr_t))            \
       return gbe::alignedFree(ptr);                          \
     else                                                     \
-      return gbe::free(ptr);                                 \
+      return gbe::memFree(ptr);                              \
   }                                                          \
   void  operator delete[](void* ptr) {                       \
     if (AlignOf<TYPE>::value > sizeof(uintptr_t))            \
       return gbe::alignedFree(ptr);                          \
     else                                                     \
-      return gbe::free(ptr);                                 \
+      return gbe::memFree(ptr);                              \
   }                                                          \
 
 /*! Declare a class with custom allocators */
@@ -124,10 +124,10 @@ private:
   do { gbe::MemDebuggerRemoveAlloc(X); delete[] X; } while (0)
 
 #define GBE_MALLOC(SZ)               \
-  gbe::MemDebuggerInsertAlloc(gbe::malloc(SZ),__FILE__, __FUNCTION__, __LINE__)
+  gbe::MemDebuggerInsertAlloc(gbe::memAlloc(SZ),__FILE__, __FUNCTION__, __LINE__)
 
 #define GBE_FREE(X)                  \
-  do { gbe::MemDebuggerRemoveAlloc(X); gbe::free(X); } while (0)
+  do { gbe::MemDebuggerRemoveAlloc(X); gbe::memFree(X); } while (0)
 
 #define GBE_ALIGNED_FREE(X)          \
   do { gbe::MemDebuggerRemoveAlloc(X); gbe::alignedFree(X); } while (0)