Added first support for compilation units Added first support for constant definition...
authorbsegovia <bsegovia@bsegovia-PC>
Wed, 8 Feb 2012 17:55:18 +0000 (09:55 -0800)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:15:13 +0000 (16:15 -0700)
backend/src/CMakeLists.txt
backend/src/ir/ir_constant.cpp [new file with mode: 0644]
backend/src/ir/ir_constant.hpp [new file with mode: 0644]
backend/src/ir/ir_context.hpp [new file with mode: 0644]
backend/src/ir/ir_function.cpp
backend/src/ir/ir_function.hpp
backend/src/ir/ir_instruction.cpp
backend/src/ir/ir_instruction.hpp
backend/src/ir/ir_register.hpp
backend/src/ir/ir_unit.cpp
backend/src/ir/ir_unit.hpp

index 41972a8..0dfb3d6 100644 (file)
@@ -25,6 +25,10 @@ set (GBE_SRC
   sys/logging.hpp
   sys/default_path.cpp
   sys/default_path.hpp
+  ir/ir_unit.cpp
+  ir/ir_unit.hpp
+  ir/ir_constant.cpp
+  ir/ir_constant.hpp
   ir/ir_instruction.cpp
   ir/ir_instruction.hpp
   ir/ir_register.cpp
diff --git a/backend/src/ir/ir_constant.cpp b/backend/src/ir/ir_constant.cpp
new file mode 100644 (file)
index 0000000..0ac2d53
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+ * 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>
+ */
+
+#include "ir_constant.hpp"
+
+namespace gbe
+{
+
+  void ConstantSet::append(const char *data,
+                           const std::string &name,
+                           uint32 size,
+                           uint32 alignment)
+  {
+    const uint32 offset = ALIGN(this->data.size(), alignment);
+    const uint32 padding = offset - this->data.size();
+    const Constant constant(name, size, alignment, offset);
+    constants.push_back(constant);
+    for (uint32 i = 0; i < padding; ++i) this->data.push_back(0);
+    for (uint32 i = 0; i < size; ++i) this->data.push_back(data[i]);
+  }
+
+} /* namespace gbe */
diff --git a/backend/src/ir/ir_constant.hpp b/backend/src/ir/ir_constant.hpp
new file mode 100644 (file)
index 0000000..2b708d4
--- /dev/null
@@ -0,0 +1,70 @@
+/* 
+ * 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>
+ */
+
+#ifndef __GBE_IR_CONSTANT_HPP__
+#define __GBE_IR_CONSTANT_HPP__
+
+#include "sys/vector.hpp"
+
+namespace gbe
+{
+  /*! We */
+  class Constant
+  {
+  public:
+    /*! Build a constant description */
+    INLINE Constant(const std::string &name, uint32 size, uint32 alignment, uint32 offset) :
+      name(name), size(size), alignment(alignment), offset(offset) {}
+    /*! Copy constructor */
+    INLINE Constant(const Constant &other) :
+      name(other.name), size(other.size), alignment(other.alignment), offset(other.offset) {}
+    /*! Copy operator */
+    INLINE Constant& operator= (const Constant &other) {
+      this->name = other.name;
+      this->size = other.size;
+      this->alignment = other.alignment;
+      this->offset = other.offset;
+      return *this;
+    }
+    /*! Nothing happens here */
+    INLINE ~Constant(void) {}
+  private:
+    std::string name; //!< Optional name of the constant
+    uint32 size;      //!< Size of the constant
+    uint32 alignment; //!< Alignment required for each constant
+    uint32 offset;    //!< Offset of the constant in the data segment
+  };
+
+  /*! A constant set is a set of immutable data associated to a compilation
+   *  unit
+   */
+  class ConstantSet
+  {
+  public:
+    /*! Append a new constant in the constant set */
+    void append(const char*, const std::string&, uint32 size, uint32 alignment);
+  private:
+    vector<char> data;         //!< The constant data serialized in one array
+    vector<Constant> constants;//!< Each constant description
+  };
+
+} /* namespace gbe */
+
+#endif /* __GBE_IR_CONSTANT_HPP__ */
+
diff --git a/backend/src/ir/ir_context.hpp b/backend/src/ir/ir_context.hpp
new file mode 100644 (file)
index 0000000..6d04df0
--- /dev/null
@@ -0,0 +1,36 @@
+/* 
+ * 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>
+ */
+
+#ifndef __GBE_IR_CONTEXT_HPP__
+#define __GBE_IR_CONTEXT_HPP__
+
+namespace gbe
+{
+  /*! A context allows an easy creation of the functions (instruction stream and
+   *  the set of immediates and registers needed for it) and constant arrays
+   */
+  class Context
+  {
+    
+  };
+
+} /* namespace gbe */
+
+#endif /* __GBE_IR_CONTEXT_HPP__ */
+
index 41a3657..976968d 100644 (file)
@@ -18,4 +18,8 @@
  */
 
 #include "ir_function.hpp"
+namespace gbe
+{
+  Function::Function(void) {}
+} /* namespace gbe */
 
index 3954991..3699c3f 100644 (file)
@@ -58,13 +58,16 @@ namespace gbe
     INLINE RegisterIndex getRegisterIndex(TupleIndex ID, uint32 which) const {
       return file.get(ID, which);
     }
+    /*! Get the given value ie immediate from the function */
+    INLINE Value getValue(uint32 ID) const {
+      assert(ID < value.size());
+      return value[ID];
+    }
 
   private:
-    /*! Create a function by sequential appending of instructions and registers */
-    friend class FunctionContext;
     vector<uint16> input;    //!< Input registers of the function
     vector<uint16> output;   //!< Output registers of the function
-    vector<Value> immediate; //!< All immediate values stored in the function
+    vector<Value> value;     //!< All immediate values stored in the function
     vector<BasicBlock> insn; //!< All the basic blocks one after the others
     RegisterFile file;       //!< All the registers used in the instructions
   };
index 0db1e81..1239f3c 100644 (file)
 namespace gbe
 {
   ///////////////////////////////////////////////////////////////////////////
-  // Implements the concrete implementations of the instruction classes
+  // Implements the concrete implementations of the instruction classes. We just
+  // cast an instruction to an internal class to run the given member function
   ///////////////////////////////////////////////////////////////////////////
   namespace internal
   {
 #define ALIGNED_INSTRUCTION ALIGNED(AlignOf<Instruction>::value) 
 
+    /*! Use this when there is no source */
+    struct NoSrcPolicy {
+      INLINE uint32 getSrcNum(void) const { return 0; }
+      INLINE RegisterIndex getSrcIndex(const Function &fn, uint32 ID) const {
+        NOT_IMPLEMENTED;
+        return 0;
+      }
+    };
+
+    /*! Use this when there is no destination */
+    struct NoDstPolicy {
+      INLINE uint32 getDstNum(void) const { return 0; }
+      INLINE RegisterIndex getDstIndex(const Function &fn, uint32 ID) const {
+        NOT_IMPLEMENTED;
+        return 0;
+      }
+    };
+
     /*! All unary and binary arithmetic instructions */
     template <uint32 srcNum> // 1 or 2
-    class ALIGNED_INSTRUCTION NaryInstruction
-    {
+    class ALIGNED_INSTRUCTION NaryInstruction {
     public:
       INLINE uint32 getSrcNum(void) const { return srcNum; }
       INLINE uint32 getDstNum(void) const { return 1; }
@@ -45,15 +63,14 @@ namespace gbe
         return src[ID];
       }
       INLINE Type getType(void) const { return this->type; }
-      Opcode opcode;      //!< Instruction opcode
-      uint8 type;         //!< Type of the instruction
-      uint16 dst;         //!< Index of the register in the register file
-      uint16 src[srcNum]; //!< Indices of the sources
+      Opcode opcode;     //!< Instruction opcode
+      Type type;         //!< Type of the instruction
+      RegisterIndex dst;        //!< Index of the register in the register file
+      RegisterIndex src[srcNum];//!< Indices of the sources
     };
 
     /*! All 1-source arithmetic instructions */
-    class ALIGNED_INSTRUCTION UnaryInstruction : public NaryInstruction<1>
-    {
+    class ALIGNED_INSTRUCTION UnaryInstruction : public NaryInstruction<1> {
     public:
       UnaryInstruction(Opcode opcode,
                        Type type,
@@ -67,8 +84,7 @@ namespace gbe
     };
 
     /*! All 2-source arithmetic instructions */
-    class ALIGNED_INSTRUCTION BinaryInstruction : public NaryInstruction<2>
-    {
+    class ALIGNED_INSTRUCTION BinaryInstruction : public NaryInstruction<2> {
     public:
       BinaryInstruction(Opcode opcode,
                         Type type,
@@ -86,8 +102,7 @@ namespace gbe
     /*! This is for MADs mostly. Since three sources cannot be encoded in 64
      *  bytes, we use tuples of registers
      */
-    class ALIGNED_INSTRUCTION TernaryInstruction
-    {
+    class ALIGNED_INSTRUCTION TernaryInstruction {
     public:
       TernaryInstruction(Opcode opcode,
                          Type type,
@@ -116,13 +131,12 @@ namespace gbe
       TupleIndex src;     //!< 3 sources do not fit in 8 bytes -> use a tuple
     };
 
-    class ALIGNED_INSTRUCTION ConvertInstruction
-    {
+    class ALIGNED_INSTRUCTION ConvertInstruction {
     public:
-      ConvertInstruction(RegisterIndex dst,
-                         RegisterIndex src,
-                         Type dstType,
-                         Type srcType)
+      ConvertInstruction(Type dstType,
+                         Type srcType,
+                         RegisterIndex dst,
+                         RegisterIndex src)
       {
         this->opcode = OP_CVT;
         this->dst = dst;
@@ -132,6 +146,8 @@ namespace gbe
       }
       INLINE Type getSrcType(void) const { return this->srcType; }
       INLINE Type getDstType(void) const { return this->dstType; }
+      INLINE uint32 getSrcNum(void) const { return 1; }
+      INLINE uint32 getDstNum(void) const { return 1; }
       INLINE RegisterIndex getDstIndex(const Function &fn, uint32 ID) const {
         assert(ID == 0);
         return dst;
@@ -147,22 +163,24 @@ namespace gbe
       Type srcType;       //!< Type to convert from
     };
 
-    class ALIGNED_INSTRUCTION BranchInstruction
-    {
+    class ALIGNED_INSTRUCTION BranchInstruction : public NoDstPolicy {
     public:
-      INLINE BranchInstruction(LabelIndex labelIndex, RegisterIndex predicate)
-      {
+      INLINE BranchInstruction(LabelIndex labelIndex, RegisterIndex predicate) {
         this->opcode = OP_BRA;
         this->predicate = predicate;
         this->labelIndex = labelIndex;
         this->hasPredicate = true;
       }
-      INLINE BranchInstruction(LabelIndex labelIndex)
-      {
+      INLINE BranchInstruction(LabelIndex labelIndex) {
         this->opcode = OP_BRA;
         this->labelIndex = labelIndex;
         this->hasPredicate = false;
       }
+      INLINE uint32 getSrcNum(void) const { return hasPredicate ? 1 : 0; }
+      INLINE RegisterIndex getSrcIndex(const Function &fn, uint32 ID) const {
+        assert(ID == 0 && hasPredicate);
+        return predicate;
+      }
       INLINE bool isPredicated(void) const { return hasPredicate; }
       Opcode opcode;            //!< Opcode of the instruction
       RegisterIndex predicate;  //!< Predication means conditional branch
@@ -170,19 +188,18 @@ namespace gbe
       bool hasPredicate;        //!< Is it predicated?
     };
 
-    class ALIGNED_INSTRUCTION LoadInstruction
-    {
+    class ALIGNED_INSTRUCTION LoadInstruction {
     public:
       LoadInstruction(Type type,
+                      TupleIndex dstValues,
                       RegisterIndex offset,
-                      TupleIndex values,
                       MemorySpace memSpace,
                       uint16 valueNum)
       {
         this->opcode = OP_STORE;
         this->type = type;
         this->offset = offset;
-        this->values = values;
+        this->values = dstValues;
         this->memSpace = memSpace;
         this->valueNum = valueNum;
       }
@@ -190,10 +207,13 @@ namespace gbe
         assert(ID == 0u);
         return offset;
       }
+      INLINE uint32 getSrcNum(void) const { return 1; }
       INLINE RegisterIndex getDstIndex(const Function &fn, uint32 ID) const {
         assert(ID < valueNum);
         return fn.getRegisterIndex(values, ID);
       }
+      INLINE uint32 getDstNum(void) const { return valueNum; }
+      INLINE Type getValueType(void) const { return type; }
       INLINE uint32 getValueNum(void) const { return valueNum; }
       INLINE MemorySpace getAddressSpace(void) const { return memSpace; }
       Opcode opcode;        //!< Opcode of the instruction
@@ -204,8 +224,7 @@ namespace gbe
       uint16 valueNum;      //!< Number of values to store
     };
 
-    class ALIGNED_INSTRUCTION StoreInstruction
-    {
+    class ALIGNED_INSTRUCTION StoreInstruction : public NoDstPolicy {
     public:
       StoreInstruction(Type type,
                        RegisterIndex offset,
@@ -220,17 +239,15 @@ namespace gbe
         this->memSpace = memSpace;
         this->valueNum = valueNum;
       }
-      INLINE RegisterIndex getSrcIndex(const Function &fn, uint32 ID) {
+      INLINE RegisterIndex getSrcIndex(const Function &fn, uint32 ID) const {
         assert(ID < valueNum + 1u); // offset + values to store
         if (ID == 0u)
           return offset;
         else
           return fn.getRegisterIndex(values, ID - 1);
       }
-      INLINE RegisterIndex getDstIndex(const Function &fn, uint32 ID) {
-        NOT_IMPLEMENTED;
-        return 0u;
-      }
+      INLINE uint32 getSrcNum(void) const { return valueNum + 1u; }
+      INLINE Type getValueType(void) const { return type; }
       INLINE uint32 getValueNum(void) const { return valueNum; }
       INLINE MemorySpace getAddressSpace(void) const { return memSpace; }
       Opcode opcode;        //!< Opcode of the instruction
@@ -241,28 +258,39 @@ namespace gbe
       uint16 valueNum;      //!< Number of values to store
     };
 
-    class ALIGNED_INSTRUCTION TextureInstruction
+    class ALIGNED_INSTRUCTION TextureInstruction :
+      public NoDstPolicy, public NoSrcPolicy // TODO REMOVE THIS
     {
     public:
       INLINE TextureInstruction(void) { this->opcode = OP_TEX; }
       Opcode opcode; //!< Opcode of the instruction
     };
 
-    class ALIGNED_INSTRUCTION LoadImmInstruction
-    {
+    class ALIGNED_INSTRUCTION LoadImmInstruction : public NoSrcPolicy {
     public:
-      INLINE LoadImmInstruction(ValueIndex valueIndex, Type type) {
+      INLINE LoadImmInstruction(Type type, RegisterIndex dst, ValueIndex valueIndex) {
+        this->dst = dst;
         this->opcode = OP_LOADI;
         this->valueIndex = valueIndex;
         this->type = type;
       }
+      INLINE Value getValue(const Function &fn) const {
+        return fn.getValue(valueIndex);
+      }
+      INLINE uint32 getDstNum(void) const{ return 1; }
+      INLINE RegisterIndex getDstIndex(const Function &fn, uint32 ID) const {
+        assert(ID == 0);
+        return dst;
+      }
       INLINE Type getType(void) const { return this->type; }
       Opcode opcode;        //!< Opcode of the instruction
+      RegisterIndex dst;    //!< Register to store into
       ValueIndex valueIndex;//!< Index in the vector of immediates
       Type type;            //!< Type of the immediate
     };
 
-    class ALIGNED_INSTRUCTION FenceInstruction
+    class ALIGNED_INSTRUCTION FenceInstruction :
+      public NoSrcPolicy, public NoDstPolicy
     {
     public:
       INLINE FenceInstruction(MemorySpace memSpace) {
@@ -273,7 +301,8 @@ namespace gbe
       MemorySpace memSpace; //!< The loads and stores to order
     };
 
-    class ALIGNED_INSTRUCTION LabelInstruction
+    class ALIGNED_INSTRUCTION LabelInstruction :
+      public NoDstPolicy, public NoSrcPolicy
     {
     public:
       INLINE LabelInstruction(LabelIndex labelIndex) {
@@ -284,6 +313,7 @@ namespace gbe
       LabelIndex labelIndex;  //!< Index of the label
     };
 
+#undef ALIGNED_INSTRUCTION
   } /* namespace internal */
 
   ///////////////////////////////////////////////////////////////////////////
@@ -367,22 +397,174 @@ END_INTROSPECTION(LabelInstruction)
 #undef END_INTROSPECTION
 #undef START_INTROSPECTION
 #undef DECL_INSN
-#undef ALIGNED_INSTRUCTION
 
-#if 0
   ///////////////////////////////////////////////////////////////////////////
-  // Implements the function dispatching from public to internal
+  // Implements the function dispatching from public to internal with some
+  // macro horrors
   ///////////////////////////////////////////////////////////////////////////
-#define DECL_INSN(OPCODE, CLASS)                           \
-  case OP_##OPCODE: return cast<CLASS>(this)->getSrcNum();
 
-  uint32 Instruction::getSrcNum(void) const {
-    const Opcode op = this->getOpcode();
+#define DECL_INSN(OPCODE, CLASS)               \
+  case OP_##OPCODE: reinterpret_cast<const internal::CLASS*>(this)->CALL;
+
+#define START_FUNCTION(CLASS, RET, PROTOTYPE)  \
+  RET CLASS::PROTOTYPE const {                 \
+    const Opcode op = this->getOpcode();       \
     switch (op) {
-      #include "ir_instruction.hxx"
-    };
-    return 0;
+
+#define END_FUNCTION(CLASS, RET)              \
+    };                                        \
+    return RET();                             \
+  }
+
+#define CALL getSrcNum()
+START_FUNCTION(Instruction, uint32, getSrcNum(void))
+#include "ir_instruction.hxx"
+END_FUNCTION(Instruction, uint32)
+#undef CALL
+
+#define CALL getDstNum()
+START_FUNCTION(Instruction, uint32, getDstNum(void))
+#include "ir_instruction.hxx"
+END_FUNCTION(Instruction, uint32)
+#undef CALL
+
+#define CALL getDstIndex(fn, ID)
+START_FUNCTION(Instruction, RegisterIndex, getDstIndex(const Function &fn, uint32 ID))
+#include "ir_instruction.hxx"
+END_FUNCTION(Instruction, RegisterIndex)
+#undef CALL
+
+#define CALL getSrcIndex(fn, ID)
+START_FUNCTION(Instruction, RegisterIndex, getSrcIndex(const Function &fn, uint32 ID))
+#include "ir_instruction.hxx"
+END_FUNCTION(Instruction, RegisterIndex)
+#undef CALL
+
+#undef END_FUNCTION
+#undef START_FUNCTION
+
+#define DECL_MEM_FN(CLASS, RET, PROTOTYPE, CALL)                  \
+  RET CLASS::PROTOTYPE const {                                    \
+    return reinterpret_cast<const internal::CLASS*>(this)->CALL;  \
+  }
+
+DECL_MEM_FN(UnaryInstruction, Type, getType(void), getType())
+DECL_MEM_FN(BinaryInstruction, Type, getType(void), getType())
+DECL_MEM_FN(TernaryInstruction, Type, getType(void), getType())
+DECL_MEM_FN(ConvertInstruction, Type, getSrcType(void), getSrcType())
+DECL_MEM_FN(ConvertInstruction, Type, getDstType(void), getDstType())
+DECL_MEM_FN(StoreInstruction, Type, getValueType(void), getValueType())
+DECL_MEM_FN(StoreInstruction, uint32, getValueNum(void), getValueNum())
+DECL_MEM_FN(StoreInstruction, MemorySpace, getAddressSpace(void), getAddressSpace())
+DECL_MEM_FN(LoadInstruction, Type, getValueType(void), getValueType())
+DECL_MEM_FN(LoadInstruction, uint32, getValueNum(void), getValueNum())
+DECL_MEM_FN(LoadInstruction, MemorySpace, getAddressSpace(void), getAddressSpace())
+DECL_MEM_FN(LoadImmInstruction, Value, getValue(const Function &fn), getValue(fn))
+DECL_MEM_FN(LoadImmInstruction, Type, getType(void), getType())
+DECL_MEM_FN(BranchInstruction, bool, isPredicated(void), isPredicated())
+
+#undef DECL_MEM_FN
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Implements the emission functions
+  ///////////////////////////////////////////////////////////////////////////
+
+  // All unary functions
+#define DECL_EMIT_FUNCTION(NAME, OPCODE)\
+  Instruction NAME(Type type, RegisterIndex dst, RegisterIndex src) {\
+    internal::UnaryInstruction insn(OPCODE, type, dst, src);\
+    return *reinterpret_cast<Instruction*>(&insn);\
   }
-#endif
+
+  DECL_EMIT_FUNCTION(mov, OP_MOV)
+  DECL_EMIT_FUNCTION(cos, OP_COS)
+  DECL_EMIT_FUNCTION(sin, OP_SIN)
+  DECL_EMIT_FUNCTION(tan, OP_TAN)
+  DECL_EMIT_FUNCTION(log, OP_LOG)
+  DECL_EMIT_FUNCTION(sqr, OP_SQR)
+  DECL_EMIT_FUNCTION(rsq, OP_RSQ)
+
+#undef DECL_EMIT_FUNCTION
+
+  // All binary functions
+#define DECL_EMIT_FUNCTION(NAME, OPCODE)\
+  Instruction NAME(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1) {\
+    internal::BinaryInstruction insn(OPCODE, type, dst, src0, src1);\
+    return *reinterpret_cast<Instruction*>(&insn);\
+  }
+
+  DECL_EMIT_FUNCTION(mul, OP_MUL)
+  DECL_EMIT_FUNCTION(add, OP_ADD)
+  DECL_EMIT_FUNCTION(sub, OP_SUB)
+  DECL_EMIT_FUNCTION(div, OP_DIV)
+  DECL_EMIT_FUNCTION(rem, OP_REM)
+  DECL_EMIT_FUNCTION(shl, OP_SHL)
+  DECL_EMIT_FUNCTION(shr, OP_SHR)
+  DECL_EMIT_FUNCTION(asr, OP_ASR)
+  DECL_EMIT_FUNCTION(bsf, OP_BSF)
+  DECL_EMIT_FUNCTION(bsb, OP_BSB)
+  DECL_EMIT_FUNCTION(or$, OP_OR)
+  DECL_EMIT_FUNCTION(xor$, OP_XOR)
+  DECL_EMIT_FUNCTION(and$, OP_AND)
+
+#undef DECL_EMIT_FUNCTION
+
+  // MAD
+  Instruction mad(Type type, RegisterIndex dst, TupleIndex src) {
+    internal::TernaryInstruction insn(OP_MAD, type, dst, src);
+    return *reinterpret_cast<Instruction*>(&insn);
+  }
+
+  // CVT
+  Instruction cvt(Type dstType, Type srcType, RegisterIndex dst, TupleIndex src) {
+    internal::ConvertInstruction insn(dstType, srcType, dst, src);
+    return *reinterpret_cast<Instruction*>(&insn);
+  }
+
+  // BRA
+  Instruction bra(RegisterIndex dst, LabelIndex labelIndex) {
+    internal::BranchInstruction insn(labelIndex);
+    return *reinterpret_cast<Instruction*>(&insn);
+  }
+  Instruction bra(RegisterIndex dst, LabelIndex labelIndex, RegisterIndex pred) {
+    internal::BranchInstruction insn(labelIndex, pred);
+    return *reinterpret_cast<Instruction*>(&insn);
+  }
+
+  // LOADI
+  Instruction loadi(Type type, RegisterIndex dst, ValueIndex value) {
+    internal::LoadImmInstruction insn(type, dst, value);
+    return *reinterpret_cast<Instruction*>(&insn);
+  }
+
+  // LOAD and STORE
+#define DECL_EMIT_FUNCTION(NAME, CLASS)   \
+  Instruction NAME(Type type,             \
+                   TupleIndex tuple,      \
+                   RegisterIndex offset,  \
+                   MemorySpace space,     \
+                   uint16 valueNum)       \
+  {                                       \
+    internal::CLASS insn(type, tuple, offset, space, valueNum); \
+    return *reinterpret_cast<Instruction*>(&insn);              \
+  }
+
+  DECL_EMIT_FUNCTION(load, LoadInstruction)
+  DECL_EMIT_FUNCTION(store, StoreInstruction)
+
+#undef DECL_EMIT_FUNCTION
+
+  // FENCE
+  Instruction fence(MemorySpace space) {
+    internal::FenceInstruction insn(space);
+    return *reinterpret_cast<Instruction*>(&insn);
+  }
+
+  // LABEL
+  Instruction label(LabelIndex labelIndex) {
+    internal::LabelInstruction insn(labelIndex);
+    return *reinterpret_cast<Instruction*>(&insn);
+  }
+
 } /* namespace gbe */
 
index edd6fba..3d23c50 100644 (file)
@@ -38,6 +38,7 @@ namespace gbe
   enum MemorySpace : uint8 {
     MEM_GLOBAL = 0, //!< Global memory (a la OCL)
     MEM_LOCAL,      //!< Local memory (thread group memory)
+    MEM_CONSTANT,   //!< Immutable global memory
     MEM_PRIVATE     //!< Per thread private memory
   };
 
@@ -52,6 +53,10 @@ namespace gbe
    */
   class Function;
 
+  ///////////////////////////////////////////////////////////////////////////
+  /// All public instruction classes as manipulated by all public classes
+  ///////////////////////////////////////////////////////////////////////////
+
   /*! Store the instruction description in 8 bytes */
   class ALIGNED(sizeof(uint64)) Instruction
   {
@@ -164,8 +169,9 @@ namespace gbe
    * regular load instructions, there is only one destination possible
    */
   class LoadImmInstruction : public Instruction {
+  public:
     /*! Return the value stored in the instruction */
-    Value getValue(void) const;
+    Value getValue(const Function &fn) const;
     /*! Return the type of the stored value */
     Type getType(void) const;
     /*! Return true if the given instruction is an instance of this class */
@@ -237,11 +243,46 @@ namespace gbe
     return reinterpret_cast<T&>(insn);
   }
   template <typename T>
-  INLINE const T &castc(const Instruction &insn) {
+  INLINE const T &cast(const Instruction &insn) {
     assert(insn.isMemberOf<T>() == true);
     return reinterpret_cast<const T&>(insn);
   }
 
+  ///////////////////////////////////////////////////////////////////////////
+  /// All emission functions
+  ///////////////////////////////////////////////////////////////////////////
+
+  Instruction mov(Type type, RegisterIndex dst, RegisterIndex src);
+  Instruction cos(Type type, RegisterIndex dst, RegisterIndex src);
+  Instruction sin(Type type, RegisterIndex dst, RegisterIndex src);
+  Instruction tan(Type type, RegisterIndex dst, RegisterIndex src);
+  Instruction log(Type type, RegisterIndex dst, RegisterIndex src);
+  Instruction sqr(Type type, RegisterIndex dst, RegisterIndex src);
+  Instruction rsq(Type type, RegisterIndex dst, RegisterIndex src);
+  Instruction pow(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction mul(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction add(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction sub(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction div(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction rem(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction shl(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction shr(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction asr(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction bsf(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction bsb(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction or$(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction xor$(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction and$(Type type, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction mad(Type type, RegisterIndex dst, TupleIndex src);
+  Instruction cvt(Type dstType, Type srcType, RegisterIndex dst, RegisterIndex src0, RegisterIndex src1);
+  Instruction bra(RegisterIndex dst, LabelIndex labelIndex);
+  Instruction bra(RegisterIndex dst, LabelIndex labelIndex, RegisterIndex pred);
+  Instruction loadi(Type type, RegisterIndex dst, ValueIndex value);
+  Instruction load(Type type, TupleIndex dst, RegisterIndex offset, MemorySpace space, uint16 valueNum);
+  Instruction store(Type type, TupleIndex src, RegisterIndex offset, MemorySpace space, uint16 valueNum);
+  Instruction fence(MemorySpace space);
+  Instruction label(LabelIndex labelIndex);
+
 } /* namespace gbe */
 
 #endif /* __GBE_IR_INSTRUCTION_HPP__ */
index 7a63874..a0dd90e 100644 (file)
@@ -31,12 +31,12 @@ namespace gbe
   {
   public:
     /*! Build a register. All fields will be immutable */
-    INLINE Register(uint8 type) : type(type) {}
+    INLINE Register(uint8 type = 0) : type(type) {}
     /*! Copy constructor */
     INLINE Register(const Register &other) : type(other.type) {}
     /*! Copy operator */
-    Register &operator= (const Register &other) {
-      *this = Register(other.type);
+    INLINE Register &operator= (const Register &other) {
+      this->type = other.type;
       return *this;
     }
     /*! Nothing really happens here */
@@ -49,7 +49,7 @@ namespace gbe
       DWORD = 3,
       QWORD = 4
     };
-    const uint8 type;
+    uint8 type;
     GBE_CLASS(Register);
   };
 
index 1ff8523..4735a5c 100644 (file)
  */
 
 #include "ir_unit.hpp"
+#include "ir_function.hpp"
+
+namespace gbe
+{
+  Unit::Unit(void) {}
+  Unit::~Unit(void) {
+    for (auto it = functions.begin(); it != functions.end(); ++it)
+      GBE_DELETE(it->second);
+  }
+  Function *Unit::getFunction(const std::string &name) const {
+    auto it = functions.find(name);
+    if (it == functions.end())
+      return NULL;
+    return it->second;
+  }
+  Function *Unit::newFunction(const std::string &name) {
+    auto it = functions.find(name);
+    if (it != functions.end())
+      return NULL;
+    Function *fn = GBE_NEW(Function);
+    functions[name] = fn;
+    return fn;
+  }
+  void Unit::newConstant(const char *data,
+                         const std::string &name,
+                         uint32 size,
+                         uint32 alignment)
+  {
+    constantSet.append(data, name, size, alignment);
+  }
+
+} /* namespace gbe */
 
index ba6d711..2f5a2dd 100644 (file)
 #ifndef __GBE_IR_UNIT_HPP__
 #define __GBE_IR_UNIT_HPP__
 
-#endif /* __GBE_IR_UNIT_HPP__ */
+#include "ir_constant.hpp"
+#include "sys/hash_map.hpp"
+
+namespace gbe
+{
+  // A unit contains a set of functions
+  class Function;
 
+  /*! Complete unit of compilation. It contains a set of functions and a set of
+   *  constant the functions may refer to.
+   */
+  class Unit
+  {
+  public:
+    /*! Create an empty unit */
+    Unit(void);
+    /*! Release everything (*including* the function pointers) */
+    ~Unit(void);
+    /*! Retrieve the function by its name */
+    Function *getFunction(const std::string &name) const;
+    /*! Return NULL if the function already exists */
+    Function *newFunction(const std::string &name);
+    /*! Create a new constant in the constant set */
+    void newConstant(const char*, const std::string&, uint32 size, uint32 alignment);
+  private:
+    hash_map<std::string, Function*> functions; //!< All the defined functions
+    ConstantSet constantSet;  //!< All the constants defined in the unit
+  };
+} /* namespace gbe */
+
+#endif /* __GBE_IR_UNIT_HPP__ */