From 09a7b01ae3dea17f090bb51c3e1f0386b5727c78 Mon Sep 17 00:00:00 2001 From: bsegovia Date: Sun, 5 Feb 2012 11:15:24 -0800 Subject: [PATCH] Keep on implementing instruction class implementation. This basically a set of classes that implements the opaque public instruction classes --- backend/src/CMakeLists.txt | 4 +- backend/src/ir/ir_function.hpp | 10 ++ backend/src/ir/ir_instruction.cpp | 337 ++++++++++++++++++++++++++++++++++++-- backend/src/ir/ir_instruction.hpp | 190 +++++++++++++-------- backend/src/ir/ir_register.hpp | 30 +++- backend/src/sys/alloc.hpp | 22 +-- backend/src/utest/utest.hpp | 6 +- 7 files changed, 495 insertions(+), 104 deletions(-) diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt index f26cf5c..41972a8 100644 --- a/backend/src/CMakeLists.txt +++ b/backend/src/CMakeLists.txt @@ -28,7 +28,9 @@ set (GBE_SRC ir/ir_instruction.cpp ir/ir_instruction.hpp ir/ir_register.cpp - ir/ir_register.hpp) + ir/ir_register.hpp + ir/ir_function.cpp + ir/ir_function.hpp) set (COMPILE_UTEST false CACHE bool "Compile or not the unit tests") if (COMPILE_UTEST) diff --git a/backend/src/ir/ir_function.hpp b/backend/src/ir/ir_function.hpp index 187d6e1..3954991 100644 --- a/backend/src/ir/ir_function.hpp +++ b/backend/src/ir/ir_function.hpp @@ -20,6 +20,11 @@ #ifndef __GBE_IR_FUNCTION_HPP__ #define __GBE_IR_FUNCTION_HPP__ +#include "ir_value.hpp" +#include "ir_register.hpp" +#include "ir_instruction.hpp" +#include "sys/vector.hpp" + namespace gbe { /*! A function is no more that a set of declared registers and a set of @@ -49,12 +54,17 @@ namespace gbe /*! Extract the register from the register file */ INLINE Register getRegister(uint32 ID) const { return file.get(ID); } + /*! Get the register index from the tuple vector */ + INLINE RegisterIndex getRegisterIndex(TupleIndex ID, uint32 which) const { + return file.get(ID, which); + } private: /*! Create a function by sequential appending of instructions and registers */ friend class FunctionContext; vector input; //!< Input registers of the function vector output; //!< Output registers of the function + vector immediate; //!< All immediate values stored in the function vector insn; //!< All the basic blocks one after the others RegisterFile file; //!< All the registers used in the instructions }; diff --git a/backend/src/ir/ir_instruction.cpp b/backend/src/ir/ir_instruction.cpp index ba0d0ef..0db1e81 100644 --- a/backend/src/ir/ir_instruction.cpp +++ b/backend/src/ir/ir_instruction.cpp @@ -22,41 +22,43 @@ namespace gbe { + /////////////////////////////////////////////////////////////////////////// + // Implements the concrete implementations of the instruction classes + /////////////////////////////////////////////////////////////////////////// namespace internal { +#define ALIGNED_INSTRUCTION ALIGNED(AlignOf::value) + /*! All unary and binary arithmetic instructions */ template // 1 or 2 - class ALIGNED(AlignOf::value) NaryInstruction + class ALIGNED_INSTRUCTION NaryInstruction { public: INLINE uint32 getSrcNum(void) const { return srcNum; } INLINE uint32 getDstNum(void) const { return 1; } - INLINE uint32 getDstIndex(const Function &fn, uint32 ID) const { + INLINE RegisterIndex getDstIndex(const Function &fn, uint32 ID) const { assert(ID == 0); return dst; } - INLINE uint32 getSrcIndex(const Function &fn, uint32 ID) const { + INLINE RegisterIndex getSrcIndex(const Function &fn, uint32 ID) const { assert(ID <= srcNum); return src[ID]; } - INLINE Register getDst(const Function &fn, uint32 ID) const { - return fn.getRegister(this->getDstIndex(fn, ID)); - } - INLINE Register getSrc(const Function &fn, uint32 ID) const { - return fn.getRegister(this->getSrcIndex(fn, ID)); - } - protected: - uint8 opcode; //!< Instruction opcode + 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 }; /*! All 1-source arithmetic instructions */ - class UnaryInstruction : public NaryInstruction<1> + class ALIGNED_INSTRUCTION UnaryInstruction : public NaryInstruction<1> { public: - UnaryInstruction(uint32 opcode, uint32 type, uint32 dst, uint32 src) { + UnaryInstruction(Opcode opcode, + Type type, + RegisterIndex dst, + RegisterIndex src) { this->opcode = opcode; this->type = type; this->dst = dst; @@ -65,10 +67,14 @@ namespace gbe }; /*! All 2-source arithmetic instructions */ - class BinaryInstruction : public NaryInstruction<2> + class ALIGNED_INSTRUCTION BinaryInstruction : public NaryInstruction<2> { public: - BinaryInstruction(uint32 opcode, uint32 type, uint32 dst, uint32 src0, uint32 src1) { + BinaryInstruction(Opcode opcode, + Type type, + RegisterIndex dst, + RegisterIndex src0, + RegisterIndex src1) { this->opcode = opcode; this->type = type; this->dst = dst; @@ -77,9 +83,306 @@ namespace gbe } }; - STATIC_ASSERT(sizeof(UnaryInstruction) <= sizeof(Instruction)); - STATIC_ASSERT(sizeof(BinaryInstruction) <= sizeof(Instruction)); + /*! This is for MADs mostly. Since three sources cannot be encoded in 64 + * bytes, we use tuples of registers + */ + class ALIGNED_INSTRUCTION TernaryInstruction + { + public: + TernaryInstruction(Opcode opcode, + Type type, + RegisterIndex dst, + TupleIndex src) + { + this->opcode = opcode; + this->type = type; + this->dst = dst; + this->src = src; + } + INLINE uint32 getSrcNum(void) const { return 3; } + INLINE uint32 getDstNum(void) const { return 1; } + INLINE RegisterIndex getDstIndex(const Function &fn, uint32 ID) const { + assert(ID == 0); + return dst; + } + INLINE RegisterIndex getSrcIndex(const Function &fn, uint32 ID) const { + assert(ID <= 3); + return fn.getRegisterIndex(src, ID); + } + INLINE Type getType(void) const { return this->type; } + Opcode opcode; //!< Opcode of the instruction + Type type; //!< Type of the instruction + RegisterIndex dst; //!< Dst is the register index + TupleIndex src; //!< 3 sources do not fit in 8 bytes -> use a tuple + }; + + class ALIGNED_INSTRUCTION ConvertInstruction + { + public: + ConvertInstruction(RegisterIndex dst, + RegisterIndex src, + Type dstType, + Type srcType) + { + this->opcode = OP_CVT; + this->dst = dst; + this->src = src; + this->dstType = dstType; + this->srcType = srcType; + } + INLINE Type getSrcType(void) const { return this->srcType; } + INLINE Type getDstType(void) const { return this->dstType; } + INLINE RegisterIndex getDstIndex(const Function &fn, uint32 ID) const { + assert(ID == 0); + return dst; + } + INLINE RegisterIndex getSrcIndex(const Function &fn, uint32 ID) const { + assert(ID == 0); + return src; + } + Opcode opcode; //!< Opcode of the instruction + RegisterIndex dst; //!< Converted value + RegisterIndex src; //!< To convert + Type dstType; //!< Type to convert to + Type srcType; //!< Type to convert from + }; + + class ALIGNED_INSTRUCTION BranchInstruction + { + public: + INLINE BranchInstruction(LabelIndex labelIndex, RegisterIndex predicate) + { + this->opcode = OP_BRA; + this->predicate = predicate; + this->labelIndex = labelIndex; + this->hasPredicate = true; + } + INLINE BranchInstruction(LabelIndex labelIndex) + { + this->opcode = OP_BRA; + this->labelIndex = labelIndex; + this->hasPredicate = false; + } + INLINE bool isPredicated(void) const { return hasPredicate; } + Opcode opcode; //!< Opcode of the instruction + RegisterIndex predicate; //!< Predication means conditional branch + LabelIndex labelIndex; //!< Index of the label the branch targets + bool hasPredicate; //!< Is it predicated? + }; + + class ALIGNED_INSTRUCTION LoadInstruction + { + public: + LoadInstruction(Type type, + RegisterIndex offset, + TupleIndex values, + MemorySpace memSpace, + uint16 valueNum) + { + this->opcode = OP_STORE; + this->type = type; + this->offset = offset; + this->values = values; + this->memSpace = memSpace; + this->valueNum = valueNum; + } + INLINE RegisterIndex getSrcIndex(const Function &fn, uint32 ID) const { + assert(ID == 0u); + return offset; + } + INLINE RegisterIndex getDstIndex(const Function &fn, uint32 ID) const { + assert(ID < valueNum); + return fn.getRegisterIndex(values, ID); + } + INLINE uint32 getValueNum(void) const { return valueNum; } + INLINE MemorySpace getAddressSpace(void) const { return memSpace; } + Opcode opcode; //!< Opcode of the instruction + Type type; //!< Type to store + RegisterIndex offset; //!< First source is the offset where to store + TupleIndex values; //!< Values to load + MemorySpace memSpace; //!< Where to store + uint16 valueNum; //!< Number of values to store + }; + + class ALIGNED_INSTRUCTION StoreInstruction + { + public: + StoreInstruction(Type type, + RegisterIndex offset, + TupleIndex values, + MemorySpace memSpace, + uint16 valueNum) + { + this->opcode = OP_STORE; + this->type = type; + this->offset = offset; + this->values = values; + this->memSpace = memSpace; + this->valueNum = valueNum; + } + INLINE RegisterIndex getSrcIndex(const Function &fn, uint32 ID) { + 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 getValueNum(void) const { return valueNum; } + INLINE MemorySpace getAddressSpace(void) const { return memSpace; } + Opcode opcode; //!< Opcode of the instruction + Type type; //!< Type to store + RegisterIndex offset; //!< First source is the offset where to store + TupleIndex values; //!< Values to store + MemorySpace memSpace; //!< Where to store + uint16 valueNum; //!< Number of values to store + }; + + class ALIGNED_INSTRUCTION TextureInstruction + { + public: + INLINE TextureInstruction(void) { this->opcode = OP_TEX; } + Opcode opcode; //!< Opcode of the instruction + }; + + class ALIGNED_INSTRUCTION LoadImmInstruction + { + public: + INLINE LoadImmInstruction(ValueIndex valueIndex, Type type) { + this->opcode = OP_LOADI; + this->valueIndex = valueIndex; + this->type = type; + } + INLINE Type getType(void) const { return this->type; } + Opcode opcode; //!< Opcode of the instruction + ValueIndex valueIndex;//!< Index in the vector of immediates + Type type; //!< Type of the immediate + }; + + class ALIGNED_INSTRUCTION FenceInstruction + { + public: + INLINE FenceInstruction(MemorySpace memSpace) { + this->opcode = OP_FENCE; + this->memSpace = memSpace; + } + Opcode opcode; //!< Opcode of the instruction + MemorySpace memSpace; //!< The loads and stores to order + }; + + class ALIGNED_INSTRUCTION LabelInstruction + { + public: + INLINE LabelInstruction(LabelIndex labelIndex) { + this->opcode = OP_LABEL; + this->labelIndex = labelIndex; + } + Opcode opcode; //!< Opcode of the instruction + LabelIndex labelIndex; //!< Index of the label + }; } /* namespace internal */ + + /////////////////////////////////////////////////////////////////////////// + // Implements the various instrospection functions + /////////////////////////////////////////////////////////////////////////// + template struct HelperIntrospection { + enum { value = 0 }; + }; + template struct HelperIntrospection { + enum { value = 1 }; + }; + + Register Instruction::getDst(const Function &fn, uint32 ID) const { + return fn.getRegister(this->getDstIndex(fn, ID)); + } + Register Instruction::getSrc(const Function &fn, uint32 ID) const { + return fn.getRegister(this->getSrcIndex(fn, ID)); + } + +#define DECL_INSN(OPCODE, CLASS) \ + case OP_##OPCODE: \ + return HelperIntrospection::value == 1; + +#define START_INTROSPECTION(CLASS) \ + STATIC_ASSERT(sizeof(CLASS) == sizeof(Instruction));\ + bool CLASS::isClassOf(const Instruction &insn) { \ + const Opcode op = insn.getOpcode(); \ + typedef CLASS RefClass; \ + switch (op) { + +#define END_INTROSPECTION(CLASS) \ + default: return false; \ + }; \ + } \ + STATIC_ASSERT(offsetof(internal::CLASS, opcode) == 0); + +START_INTROSPECTION(UnaryInstruction) +#include "ir_instruction.hxx" +END_INTROSPECTION(UnaryInstruction) + +START_INTROSPECTION(BinaryInstruction) +#include "ir_instruction.hxx" +END_INTROSPECTION(BinaryInstruction) + +START_INTROSPECTION(TernaryInstruction) +#include "ir_instruction.hxx" +END_INTROSPECTION(TernaryInstruction) + +START_INTROSPECTION(ConvertInstruction) +#include "ir_instruction.hxx" +END_INTROSPECTION(ConvertInstruction) + +START_INTROSPECTION(BranchInstruction) +#include "ir_instruction.hxx" +END_INTROSPECTION(BranchInstruction) + +START_INTROSPECTION(TextureInstruction) +#include "ir_instruction.hxx" +END_INTROSPECTION(TextureInstruction) + +START_INTROSPECTION(LoadImmInstruction) +#include "ir_instruction.hxx" +END_INTROSPECTION(LoadImmInstruction) + +START_INTROSPECTION(LoadInstruction) +#include "ir_instruction.hxx" +END_INTROSPECTION(LoadInstruction) + +START_INTROSPECTION(StoreInstruction) +#include "ir_instruction.hxx" +END_INTROSPECTION(StoreInstruction) + +START_INTROSPECTION(FenceInstruction) +#include "ir_instruction.hxx" +END_INTROSPECTION(FenceInstruction) + +START_INTROSPECTION(LabelInstruction) +#include "ir_instruction.hxx" +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 + /////////////////////////////////////////////////////////////////////////// +#define DECL_INSN(OPCODE, CLASS) \ + case OP_##OPCODE: return cast(this)->getSrcNum(); + + uint32 Instruction::getSrcNum(void) const { + const Opcode op = this->getOpcode(); + switch (op) { + #include "ir_instruction.hxx" + }; + return 0; + } +#endif } /* namespace gbe */ diff --git a/backend/src/ir/ir_instruction.hpp b/backend/src/ir/ir_instruction.hpp index 0938f49..edd6fba 100644 --- a/backend/src/ir/ir_instruction.hpp +++ b/backend/src/ir/ir_instruction.hpp @@ -22,37 +22,30 @@ #include "sys/platform.hpp" #include "ir_register.hpp" +#include "ir_value.hpp" +#include "ir_type.hpp" namespace gbe { /*! All opcodes */ - enum { + enum Opcode : uint8 { #define DECL_INSN(INSN, FAMILY) OP_##INSN, #include "ir_instruction.hxx" #undef DECL_INSN - OP_INVALID }; /*! Different memory spaces */ - enum { - MEM_GLOBAL = 0, /*! Global memory (a la OCL) */ - MEM_LOCAL, /*! Local memory (thread group memory) */ - MEM_PRIVATE /*! Per thread private memory */ + enum MemorySpace : uint8 { + MEM_GLOBAL = 0, //!< Global memory (a la OCL) + MEM_LOCAL, //!< Local memory (thread group memory) + MEM_PRIVATE //!< Per thread private memory }; - /*! All types possibly supported by the instruction */ - enum { - TYPE_S8 = 0, /*! signed 8 bits integer */ - TYPE_U8, /*! unsigned 8 bits integer */ - TYPE_S16, /*! signed 16 bits integer */ - TYPE_U16, /*! unsigned 16 bits integer */ - TYPE_S32, /*! signed 32 bits integer */ - TYPE_U32, /*! unsigned 32 bits integer */ - TYPE_S64, /*! signed 64 bits integer */ - TYPE_U64, /*! unsigned 64 bits integer */ - TYPE_FLOAT, /*! 32 bits floating point value */ - TYPE_DOUBLE /*! 64 bits floating point value */ - }; + /*! A label is identified with an unsigned short */ + typedef uint16 LabelIndex; + + /*! A value is stored in a per-function vector. This is the index to it */ + typedef uint16 ValueIndex; /*! Function class contains the register file and the register tuple. Any * information related to the registers may therefore require a function @@ -64,88 +57,105 @@ namespace gbe { public: /*! Get the instruction opcode */ - INLINE uint32 getOpcode(void) const { return op; } + INLINE Opcode getOpcode(void) const { return opcode; } /*! Get the number of sources for this instruction */ uint32 getSrcNum(void) const; /*! Get the number of destination for this instruction */ uint32 getDstNum(void) const; /*! Get the register index of the given source */ - uint32 getSrcIndex(const Function &fn, uint32 ID) const; + RegisterIndex getSrcIndex(const Function &fn, uint32 ID = 0u) const; /*! Get the register index of the given destination */ - uint32 getDstIndex(const Function &fn, uint32 ID) const; + RegisterIndex getDstIndex(const Function &fn, uint32 ID = 0u) const; /*! Get the register of the given source */ - Register getSrc(const Function &fn, uint32 ID) const; + Register getDst(const Function &fn, uint32 ID = 0u) const; /*! Get the register of the given destination */ - Register getDst(const Function &fn, uint32 ID) const; + Register getSrc(const Function &fn, uint32 ID = 0u) const; /*! Check that the instruction is well formed. Return true if well formed. + * j * Otherwise, fill the string with a help message */ bool check(void) const; /*! Indicates if the instruction belongs to instruction type T. Typically, T * can be BinaryInstruction, UnaryInstruction, LoadInstruction and so on */ - template bool isTypeOf(void) const; + template INLINE bool isMemberOf(void) const { + return T::isClassOf(*this); + } protected: - uint8 op; //!< Idendifies the instruction - uint8 opaque[sizeof(uint64)-sizeof(uint8)]; //!< Remainder of it + Opcode opcode; //!< Idendifies the instruction + uint8 opaque[sizeof(uint64)-sizeof(uint8)];//!< Remainder of it }; // Check that the instruction is properly formed by the compiler STATIC_ASSERT(sizeof(Instruction) == sizeof(uint64)); + /*! Unary instructions are typed. dst and sources share the same type */ + class UnaryInstruction : public Instruction { + public: + /*! Get the type manipulated by the instruction */ + Type getType(void) const; + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); + }; + /*! Binary instructions are typed. dst and sources share the same type */ - class BinaryInstruction : public Instruction - { + class BinaryInstruction : public Instruction { public: /*! Get the type manipulated by the instruction */ - uint32 getType(void) const; + Type getType(void) const; + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); }; /*! Ternary instructions is mostly for MADs */ - class TernaryInstruction : public Instruction - { + class TernaryInstruction : public Instruction { public: /*! Get the type manipulated by the instruction */ - uint32 getType(void) const; + Type getType(void) const; + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); }; /*! Conversion instruction converts from one type to another */ - class ConvertInstruction : public Instruction - { + class ConvertInstruction : public Instruction { public: /*! Get the type of the source */ - uint32 getSrcType(void) const; + Type getSrcType(void) const; /*! Get the type of the destination */ - uint32 getDstType(void) const; + Type getDstType(void) const; + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); }; /*! Store instruction. First source is the address. Next sources are the * values to store contiguously at the given address */ - class StoreInstruction : public Instruction - { + class StoreInstruction : public Instruction { public: /*! Return the types of the values to store */ - uint32 getValueType(void) const; + Type getValueType(void) const; /*! Give the number of values the instruction is storing (srcNum-1) */ uint32 getValueNum(void) const; /*! Address space that is manipulated here */ - uint32 getAddressSpace(void) const; + MemorySpace getAddressSpace(void) const; + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); }; /*! Load instruction. The source is simply the address where to get the data. * The multiple destinations are the contiguous values loaded at the given * address */ - class LoadInstruction : public Instruction - { + class LoadInstruction : public Instruction { public: /*! Type of the loaded values (ie type of all the destinations) */ - uint32 getValueType(void) const; + Type getValueType(void) const; /*! Number of values loaded (ie number of destinations) */ uint32 getValueNum(void) const; /*! Address space that is manipulated here */ - uint32 getAddressSpace(void) const; + MemorySpace getAddressSpace(void) const; + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); }; /*! Load immediate instruction loads an typed immediate value into the given @@ -153,39 +163,83 @@ namespace gbe * the immediate themselves are stored in the function core. Contrary to * regular load instructions, there is only one destination possible */ - class LoadImmInstruction : public Instruction - { - /*! The value as stored in the instruction */ - union Value { - int8 s8; - uint8 u8; - int16 i16; - uint16 u16; - int32 i32; - uint32 u32; - int64 i64; - uint64 u64; - float f32; - double f64; - }; + class LoadImmInstruction : public Instruction { /*! Return the value stored in the instruction */ Value getValue(void) const; /*! Return the type of the stored value */ - uint32 getType(void) const; + Type getType(void) const; + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); }; - /*! Prevents all cast to non-instruction types */ - template INLINE bool Instruction::isTypeOf(void) const { - return false; - } + /*! Branch instruction is the unified way to branch (with or without + * predicate) + */ + class BranchInstruction : public Instruction { + public: + /*! Indicate if the branch is predicated */ + bool isPredicated(void) const; + /*! Return the predicate register (if predicated) */ + Register getPredicate(const Function &fn) const { + assert(this->isPredicated() == true); + return this->getSrc(fn, 0); + } + /*! Return the predicate register index (if predicated) */ + Register getPredicateIndex(const Function &fn) const { + assert(this->isPredicated() == true); + return this->getSrcIndex(fn, 0); + } + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); + }; + + /*! Label instruction are actual no-op but are referenced by branches as their + * targets + */ + class LabelInstruction : public Instruction { + public: + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); + }; + + /*! Texture instruction are used for any texture mapping requests */ + class TextureInstruction : public Instruction { + public: + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); + }; + + /*! Fence instructions are used to order loads and stores for a given memory + * space + */ + class FenceInstruction : public Instruction { + public: + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); + }; /*! Specialize the instruction. Also performs typechecking first based on the * opcode. Crashes if it fails */ template - T *cast(Instruction *insn) - { - + INLINE T *cast(Instruction *insn) { + assert(insn->isMemberOf() == true); + return reinterpret_cast(insn); + } + template + INLINE const T *cast(const Instruction *insn) { + assert(insn->isMemberOf() == true); + return reinterpret_cast(insn); + } + template + INLINE T &cast(Instruction &insn) { + assert(insn.isMemberOf() == true); + return reinterpret_cast(insn); + } + template + INLINE const T &castc(const Instruction &insn) { + assert(insn.isMemberOf() == true); + return reinterpret_cast(insn); } } /* namespace gbe */ diff --git a/backend/src/ir/ir_register.hpp b/backend/src/ir/ir_register.hpp index afcd88e..7a63874 100644 --- a/backend/src/ir/ir_register.hpp +++ b/backend/src/ir/ir_register.hpp @@ -53,6 +53,12 @@ namespace gbe GBE_CLASS(Register); }; + /*! Register index is the position of the register in the register file */ + typedef uint16 RegisterIndex; + + /*! Tuple index is the position of the register index in the tuple vector */ + typedef uint32 TupleIndex; + /*! A register file allocates and destroys registers. Basically, we will have * one register file per function */ @@ -60,23 +66,39 @@ namespace gbe { public: /*! Return the index of a newly allocated register register */ - INLINE uint32 append(uint32 type) { + INLINE RegisterIndex append(uint32 type) { const uint32 index = regs.size(); const Register reg(type); assert(index <= MAX_INDEX); regs.push_back(reg); return index; } + /*! Make a tuple and return the index to the first element of the tuple */ + template + INLINE TupleIndex appendTuple(First first, Rest... rest) { + const TupleIndex index = regTuples.size(); + regTuples.push_back(first); + appendTuple(rest...); + return index; + } + /*! To terminate variadic recursion */ + INLINE void appendTuple(void) {} /*! Return a copy of the register at index */ - INLINE Register get(uint32 index) const { + INLINE Register get(RegisterIndex index) const { assert(index < regs.size() && index <= MAX_INDEX); return regs[index]; } + /*! Get the register index from the tuple */ + INLINE RegisterIndex get(TupleIndex index, uint32 which) const { + assert(index + which < regTuples.size()); + return regTuples[index + which]; + } /*! Number of registers in the register file */ INLINE uint32 regNum(void) const { return regs.size(); } private: - enum { MAX_INDEX = 0xffff }; //!< We encode indices in 2 bytes - vector regs; //!< All the registers together + enum { MAX_INDEX = 0xffff }; //!< We encode indices in 2 bytes + vector regs; //!< All the registers together + vector regTuples; //!< Tuples are used for many src / dst GBE_CLASS(RegisterFile); }; diff --git a/backend/src/sys/alloc.hpp b/backend/src/sys/alloc.hpp index 758aaa1..f856b0e 100644 --- a/backend/src/sys/alloc.hpp +++ b/backend/src/sys/alloc.hpp @@ -64,30 +64,30 @@ namespace gbe } /* namespace gbe */ /*! Declare a structure with custom allocators */ -#define GBE_STRUCT(TYPE) \ +#define GBE_STRUCT(TYPE) \ void* operator new(size_t size) { \ if (AlignOf::value > sizeof(uintptr_t)) \ - return gbe::alignedMalloc(size, AlignOf::value); \ + return gbe::alignedMalloc(size, AlignOf::value); \ else \ - return gbe::malloc(size); \ + return gbe::malloc(size); \ } \ void* operator new[](size_t size) { \ if (AlignOf::value > sizeof(uintptr_t)) \ - return gbe::alignedMalloc(size, AlignOf::value); \ + return gbe::alignedMalloc(size, AlignOf::value); \ else \ - return gbe::malloc(size); \ + return gbe::malloc(size); \ } \ void operator delete(void* ptr) { \ if (AlignOf::value > sizeof(uintptr_t)) \ - return gbe::alignedFree(ptr); \ + return gbe::alignedFree(ptr); \ else \ - return gbe::free(ptr); \ + return gbe::free(ptr); \ } \ void operator delete[](void* ptr) { \ if (AlignOf::value > sizeof(uintptr_t)) \ - return gbe::alignedFree(ptr); \ + return gbe::alignedFree(ptr); \ else \ - return gbe::free(ptr); \ + return gbe::free(ptr); \ } \ /*! Declare a class with custom allocators */ @@ -196,8 +196,8 @@ namespace gbe ~GrowingPool(void) { GBE_ASSERT(current); GBE_DELETE(current); } T *allocate(void) { if (this->freeList != NULL) { - T *data = freeList; - this->freeList = *(void**) free; + T *data = (T*) freeList; + this->freeList = *(void**) freeList; } if (UNLIKELY(current->allocated == current->maxElemNum)) { GrowingPoolElem *elem = GBE_NEW(GrowingPoolElem, 2 * current->maxElemNum); diff --git a/backend/src/utest/utest.hpp b/backend/src/utest/utest.hpp index 9d69095..cdd7df3 100644 --- a/backend/src/utest/utest.hpp +++ b/backend/src/utest/utest.hpp @@ -22,7 +22,7 @@ #include -namespace pf +namespace gbe { /*! Quick and dirty Unit test system with registration */ struct UTest @@ -44,10 +44,10 @@ namespace pf /*! Run all the tests */ static void runAll(void); }; -} /* namespace pf */ +} /* namespace gbe */ /*! Register a new unit test */ -#define UTEST_REGISTER(FN) static const pf::UTest __##NAME##__(FN, #FN); +#define UTEST_REGISTER(FN) static const gbe::UTest __##NAME##__(FN, #FN); #endif /* __GBE_UTEST_HPP__ */ -- 2.7.4