Added a check to make special registers immutable
authorBenjamin Segovia <segovia.benjamin@gmail.com>
Wed, 18 Apr 2012 16:05:02 +0000 (16:05 +0000)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:16:37 +0000 (16:16 -0700)
backend/src/backend/gen_context.cpp
backend/src/backend/gen_context.hpp
backend/src/ir/context.cpp
backend/src/ir/instruction.cpp
backend/src/ir/instruction.hpp
backend/src/sys/assert.cpp
backend/src/utest/utest_context.cpp

index 8aaac13..227d414 100644 (file)
@@ -26,6 +26,7 @@
 #include "backend/gen_program.hpp"
 #include "backend/gen_defs.hpp"
 #include "backend/gen_eu.hpp"
+#include "ir/function.hpp"
 #include <cstring>
 
 namespace gbe
@@ -34,6 +35,22 @@ namespace gbe
     Context(unit, name) {}
   GenContext::~GenContext(void) {}
 
+  void GenContext::allocateRegister(void) {
+    GBE_ASSERT(fn.getProfile() == ir::PROFILE_OCL);
+
+    // First we build the set of all used registers
+    set<ir::Register> usedRegs;
+    fn.foreachInstruction([&usedRegs](const ir::Instruction &insn) {
+      const uint32_t srcNum = insn.getSrcNum(), dstNum = insn.getDstNum();
+      for (uint32_t srcID = 0; srcID < srcNum; ++srcID)
+        usedRegs.insert(insn.getSrc(srcID));
+      for (uint32_t dstID = 0; dstID < dstNum; ++dstID)
+        usedRegs.insert(insn.getDst(dstID));
+    });
+
+
+  }
+
   void GenContext::emitCode(void) {
     GenKernel *genKernel = static_cast<GenKernel*>(this->kernel);
     GenEmitter *p = (GenEmitter*) GBE_MALLOC(sizeof(GenEmitter));
@@ -44,6 +61,7 @@ namespace gbe
     std::memcpy(genKernel->insns, p->store, genKernel->insnNum * sizeof(GenInstruction));
     GBE_FREE(p);
   }
+
   Kernel *GenContext::allocateKernel(void) {
     return GBE_NEW(GenKernel, name);
   }
index c769156..6a8b98a 100644 (file)
@@ -27,6 +27,8 @@
 
 #include <string>
 #include "backend/context.hpp"
+#include "backend/gen_eu.hpp"
+#include "sys/set.hpp"
 
 namespace gbe
 {
@@ -46,10 +48,12 @@ namespace gbe
     ~GenContext(void);
     /*! Implements base class */
     virtual void emitCode(void);
+    /*! Very stupid register allocator to start with */
+    void allocateRegister(void);
     /*! Implements base class */
     virtual Kernel *allocateKernel(void);
     /*! Simplistic allocation to start with */
-    //set<ir::Register, GenReg> RA;
+    set<ir::Register, GenReg> RA;
   };
 
 } /* namespace gbe */
index 7de50ec..8504b46 100644 (file)
@@ -131,11 +131,11 @@ namespace ir {
 
     // Append the instruction in the stream
     Instruction *insnPtr = fn->newInstruction(insn);
+    bb->append(*insnPtr);
 #if GBE_DEBUG
     std::string whyNot;
-    GBE_ASSERTM(insn.wellFormed(*fn, whyNot), whyNot.c_str());
+    GBE_ASSERTM(insnPtr->wellFormed(whyNot), whyNot.c_str());
 #endif /* GBE_DEBUG */
-    bb->append(*insnPtr);
 
     // Close the current block if this is a branch
     if (insn.isMemberOf<BranchInstruction>() == true) {
index 7b04bd2..bd649f2 100644 (file)
@@ -462,7 +462,7 @@ namespace ir {
      *  defined (i.e. not out-of-bound)
      */
     static INLINE bool checkRegisterData(RegisterFamily family,
-                                         const Register ID,
+                                         const Register &ID,
                                          const Function &fn,
                                          std::string &whyNot)
     {
@@ -478,11 +478,25 @@ namespace ir {
       return true;
     }
 
+    /*! Special registers are *not* writeable */
+    static INLINE bool checkSpecialRegForWrite(const Register &reg,
+                                               const Function &fn,
+                                               std::string &whyNot)
+    {
+      if (fn.isSpecialReg(reg) == true) {
+        whyNot = "Special registers are not writeable";
+        return false;
+      }
+      return true;
+    }
+
     // Unary and binary instructions share the same rules
     template <uint32_t srcNum>
     INLINE bool NaryInstruction<srcNum>::wellFormed(const Function &fn, std::string &whyNot) const
     {
       const RegisterFamily family = getFamily(this->type);
+      if (UNLIKELY(checkSpecialRegForWrite(dst, fn, whyNot) == false))
+        return false;
       if (UNLIKELY(checkRegisterData(family, dst, fn, whyNot) == false))
         return false;
       for (uint32_t srcID = 0; srcID < srcNum; ++srcID)
@@ -495,6 +509,8 @@ namespace ir {
     INLINE bool TernaryInstruction::wellFormed(const Function &fn, std::string &whyNot) const
     {
       const RegisterFamily family = getFamily(this->type);
+      if (UNLIKELY(checkSpecialRegForWrite(dst, fn, whyNot) == false))
+        return false;
       if (UNLIKELY(checkRegisterData(family, dst, fn, whyNot) == false))
         return false;
       if (UNLIKELY(src + 3u > fn.tupleNum())) {
@@ -513,6 +529,8 @@ namespace ir {
     INLINE bool SelectInstruction::wellFormed(const Function &fn, std::string &whyNot) const
     {
       const RegisterFamily family = getFamily(this->type);
+      if (UNLIKELY(checkSpecialRegForWrite(dst, fn, whyNot) == false))
+        return false;
       if (UNLIKELY(checkRegisterData(family, dst, fn, whyNot) == false))
         return false;
       if (UNLIKELY(src + 3u > fn.tupleNum())) {
@@ -534,6 +552,8 @@ namespace ir {
     // boolean
     INLINE bool CompareInstruction::wellFormed(const Function &fn, std::string &whyNot) const
     {
+      if (UNLIKELY(checkSpecialRegForWrite(dst, fn, whyNot) == false))
+        return false;
       if (UNLIKELY(checkRegisterData(FAMILY_BOOL, dst, fn, whyNot) == false))
         return false;
       const RegisterFamily family = getFamily(this->type);
@@ -548,6 +568,8 @@ namespace ir {
     {
       const RegisterFamily dstFamily = getFamily(dstType);
       const RegisterFamily srcFamily = getFamily(srcType);
+      if (UNLIKELY(checkSpecialRegForWrite(dst, fn, whyNot) == false))
+        return false;
       if (UNLIKELY(checkRegisterData(dstFamily, dst, fn, whyNot) == false))
         return false;
       if (UNLIKELY(checkRegisterData(srcFamily, src, fn, whyNot) == false))
@@ -579,6 +601,12 @@ namespace ir {
 
     INLINE bool LoadInstruction::wellFormed(const Function &fn, std::string &whyNot) const
     {
+      const uint32_t dstNum = this->getDstNum();
+      for (uint32_t dstID = 0; dstID < dstNum; ++dstID) {
+        const Register reg = this->getDst(fn, dstID);
+        const bool isOK = checkSpecialRegForWrite(reg, fn, whyNot);
+        if (UNLIKELY(isOK == false)) return false;
+      }
       return wellFormedLoadStore(*this, fn, whyNot);
     }
 
@@ -605,6 +633,8 @@ namespace ir {
         return false;
       }
       const RegisterFamily family = getFamily(type);
+      if (UNLIKELY(checkSpecialRegForWrite(dst, fn, whyNot) == false))
+        return false;
       if (UNLIKELY(checkRegisterData(family, dst, fn, whyNot) == false))
         return false;
       return true;
@@ -848,12 +878,6 @@ START_FUNCTION(Instruction, uint32_t, getDstNum(void))
 END_FUNCTION(Instruction, uint32_t)
 #undef CALL
 
-#define CALL wellFormed(fn, whyNot)
-START_FUNCTION(Instruction, bool, wellFormed(const Function &fn, std::string &whyNot))
-#include "ir/instruction.hxx"
-END_FUNCTION(Instruction, bool)
-#undef CALL
-
 #undef DECL_INSN
 
 #define DECL_INSN(OPCODE, CLASS)                                  \
@@ -863,6 +887,12 @@ END_FUNCTION(Instruction, bool)
     return reinterpret_cast<const internal::CLASS*>(this)->CALL;  \
   }
 
+#define CALL wellFormed(fn, whyNot)
+START_FUNCTION(Instruction, bool, wellFormed(std::string &whyNot))
+#include "ir/instruction.hxx"
+END_FUNCTION(Instruction, bool)
+#undef CALL
+
 #define CALL getDst(fn, ID)
 START_FUNCTION(Instruction, Register, getDst(uint32_t ID))
 #include "ir/instruction.hxx"
index 5a485ab..4d7ca41 100644 (file)
@@ -114,7 +114,7 @@ namespace ir {
      *  registers not of bound and so on). If not well formed, provide a reason
      *  in string why
      */
-    bool wellFormed(const Function &fn, std::string &why) const;
+    bool wellFormed(std::string &why) const;
     /*! Replace other by this instruction */
     void replace(Instruction *other);
     /*! Indicates if the instruction belongs to instruction type T. Typically, T
index ea3d34c..d13017c 100644 (file)
@@ -39,7 +39,7 @@ namespace gbe
                           + std::string(file)
                           + ", function " + std::string(fn)
                           + ", line " + std::string(lineString);
-    assert(0);
+    // assert(0);
     throw Exception(str);
   }
 } /* namespace gbe */
index 8265519..6b4b4cf 100644 (file)
@@ -87,6 +87,14 @@ namespace gbe
       ctx.BRA(label);
     ctx.endFunction();
   }
+  static void writeSpecialReg(void) {
+    Unit unit;
+    Context ctx(unit);
+    ctx.startFunction("hop");
+      const ImmediateIndex imm = ctx.newImmediate(2);
+      ctx.LOADI(TYPE_U32, ocl::lid0, imm);
+    ctx.endFunction();
+  }
 } /* namespace gbe */
 
 static void utestContext(void)
@@ -97,6 +105,7 @@ static void utestContext(void)
   UTEST_EXPECT_SUCCESS(gbe::recursiveDefinition());
   UTEST_EXPECT_FAILED(gbe::labelUsedTwice());
   UTEST_EXPECT_FAILED(gbe::labelNotDefined());
+  UTEST_EXPECT_FAILED(gbe::writeSpecialReg());
 }
 
 UTEST_REGISTER(utestContext)