set (GBE_SRC
${GBE_SRC}
utest/utest_test_utest.cpp
+ utest/utest_context.cpp
utest/utest.cpp
utest/utest.hpp)
endif (GBE_COMPILE_UTEST)
BasicBlock::BasicBlock(Function &fn) : fn(fn) {}
BasicBlock::~BasicBlock(void) {
for (auto it = instructions.begin(); it != instructions.end(); ++it)
- GBE_DELETE(*it);
+ fn.deleteInstruction(*it);
}
} /* namespace ir */
*/
class BasicBlock
{
- public:
- /*! Empty basic block */
- BasicBlock(Function &fn);
- /*! Releases all the instructions */
- ~BasicBlock(void);
- /*! Append a new instruction in the stream */
- void append(Instruction &insn) {
- instructions.push_back(&insn);
- }
- /*! Return the number of instruction in the block */
- INLINE uint32_t insnNum(void) { return instructions.size(); }
- private:
- friend class Function; //!< Owns the basic blocks
- list<Instruction*> instructions; //!< Sequence of instructions in the block
- Function &fn; //!< Function the block belongs to
+ public:
+ /*! Empty basic block */
+ BasicBlock(Function &fn);
+ /*! Releases all the instructions */
+ ~BasicBlock(void);
+ /*! Append a new instruction in the stream */
+ void append(Instruction &insn) {
+ instructions.push_back(&insn);
+ }
+ /*! Return the number of instruction in the block */
+ INLINE uint32_t insnNum(void) { return instructions.size(); }
+ private:
+ friend class Function; //!< Owns the basic blocks
+ list<Instruction*> instructions; //!< Sequence of instructions in the block
+ Function &fn; //!< Function the block belongs to
};
/*! A function is no more that a set of declared registers and a set of
return file.get(ID, which);
}
/*! Get the given value ie immediate from the function */
- INLINE Value getValue(uint32_t ID) const {
- GBE_ASSERT(ID < values.size());
- return values[ID];
+ INLINE Immediate getImmediate(uint32_t ID) const {
+ GBE_ASSERT(ID < immediates.size());
+ return immediates[ID];
}
/*! Allocate a new instruction (with the growing pool) */
INLINE Instruction *newInstruction(void) {
/*! Number of labels in the function */
INLINE uint32_t labelNum(void) const { return labels.size(); }
/*! Number of immediate values in the function */
- INLINE uint32_t valueNum(void) const { return values.size(); }
+ INLINE uint32_t immediateNum(void) const { return immediates.size(); }
private:
- friend class Context; //!< Can freely modify a function
- vector<RegisterIndex> input; //!< Input registers of the function
- vector<RegisterIndex> output; //!< Output registers of the function
- vector<BasicBlock*> labels; //!< Each label points to a basic block
- vector<Value> values; //!< All immediate values in the function
- vector<BasicBlock*> blocks; //!< All chained basic blocks
- RegisterFile file; //!< Registers used by the instructions
+ friend class Context; //!< Can freely modify a function
+ vector<RegisterIndex> input; //!< Input registers of the function
+ vector<RegisterIndex> output; //!< Output registers of the function
+ vector<BasicBlock*> labels; //!< Each label points to a basic block
+ vector<Immediate> immediates; //!< All immediate values in the function
+ vector<BasicBlock*> blocks; //!< All chained basic blocks
+ RegisterFile file; //!< Registers used by the instructions
GrowingPool<Instruction> insnPool; //!< For fast instruction allocation
GBE_CLASS(Function);
};
class LoadImmInstruction : public BasePolicy, public NoSrcPolicy
{
public:
- INLINE LoadImmInstruction(Type type, RegisterIndex dst, ValueIndex valueIndex) {
+ INLINE LoadImmInstruction(Type type,
+ RegisterIndex dst,
+ ImmediateIndex immediateIndex)
+ {
this->dst = dst;
this->opcode = OP_LOADI;
- this->valueIndex = valueIndex;
+ this->immediateIndex = immediateIndex;
this->type = type;
}
- INLINE Value getValue(const Function &fn) const {
- return fn.getValue(valueIndex);
+ INLINE Immediate getImmediate(const Function &fn) const {
+ return fn.getImmediate(immediateIndex);
}
INLINE uint32_t getDstNum(void) const{ return 1; }
INLINE RegisterIndex getDstIndex(const Function &fn, uint32_t ID) const {
}
INLINE Type getType(void) const { return this->type; }
bool wellFormed(const Function &fn, std::string &why) const;
- RegisterIndex dst; //!< Register to store into
- ValueIndex valueIndex;//!< Index in the vector of immediates
- Type type; //!< Type of the immediate
+ RegisterIndex dst; //!< Register to store into
+ ImmediateIndex immediateIndex; //!< Index in the vector of immediates
+ Type type; //!< Type of the immediate
};
class FenceInstruction : public BasePolicy, public NoSrcPolicy, public NoDstPolicy
// Ensure that types and register family match
INLINE bool LoadImmInstruction::wellFormed(const Function &fn, std::string &whyNot) const
{
- if (UNLIKELY(valueIndex >= fn.valueNum())) {
+ if (UNLIKELY(immediateIndex >= fn.immediateNum())) {
whyNot = "Out-of-bound immediate value index";
return false;
}
- if (UNLIKELY(type != fn.getValue(valueIndex).type)) {
+ if (UNLIKELY(type != fn.getImmediate(immediateIndex).type)) {
whyNot = "Inconsistant type for the immediate value to load";
return false;
}
DECL_MEM_FN(LoadInstruction, Type, getValueType(void), getValueType())
DECL_MEM_FN(LoadInstruction, uint32_t, 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, Immediate, getImmediate(const Function &fn), getImmediate(fn))
DECL_MEM_FN(LoadImmInstruction, Type, getType(void), getType())
DECL_MEM_FN(BranchInstruction, bool, isPredicated(void), isPredicated())
}
// LOADI
- Instruction LOADI(Type type, RegisterIndex dst, ValueIndex value) {
+ Instruction LOADI(Type type, RegisterIndex dst, ImmediateIndex value) {
internal::LoadImmInstruction insn(type, dst, value);
return insn.convert();
}
/**
* \file instruction.hpp
- *
* \author Benjamin Segovia <benjamin.segovia@intel.com>
*/
#ifndef __GBE_IR_INSTRUCTION_HPP__
};
/*! A label is identified with an unsigned short */
- typedef uint16_t LabelIndex;
+ TYPE_SAFE(LabelIndex, uint16_t)
/*! A value is stored in a per-function vector. This is the index to it */
- typedef uint16_t ValueIndex;
+ TYPE_SAFE(ImmediateIndex, uint16_t)
/*! Function class contains the register file and the register tuple. Any
* information related to the registers may therefore require a function
class LoadImmInstruction : public Instruction {
public:
/*! Return the value stored in the instruction */
- Value getValue(const Function &fn) const;
+ Immediate getImmediate(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 */
/*! (pred) bra labelIndex */
Instruction BRA(LabelIndex labelIndex, RegisterIndex pred);
/*! loadi.type dst value */
- Instruction LOADI(Type type, RegisterIndex dst, ValueIndex value);
+ Instruction LOADI(Type type, RegisterIndex dst, ImmediateIndex value);
/*! load.type.space {dst1,...,dst_valueNum} offset value */
Instruction LOAD(Type type, TupleIndex dst, RegisterIndex offset, MemorySpace space, uint16_t valueNum);
/*! store.type.space offset {src1,...,src_valueNum} value */
/*! 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;
- };
+ TYPE_SAFE(RegisterIndex, uint16_t)
/*! 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;
- };
+ TYPE_SAFE(TupleIndex, uint16_t)
/*! A register file allocates and destroys registers. Basically, we will have
* one register file per function
namespace ir {
/*! The value as stored in the instruction */
- class Value
+ class Immediate
{
public:
#define DECL_CONSTRUCTOR(TYPE, FIELD) \
- Value(TYPE FIELD) { this->data.u64 = 0llu; this->data.FIELD = FIELD; }
- DECL_CONSTRUCTOR(int8_t, s8);
- DECL_CONSTRUCTOR(uint8_t, u8);
+ Immediate(TYPE FIELD) { this->data.u64 = 0llu; this->data.FIELD = FIELD; }
+ DECL_CONSTRUCTOR(int8_t, s8)
+ DECL_CONSTRUCTOR(uint8_t, u8)
+#undef DECL_CONSTRUCTOR
union {
int8_t s8;
uint8_t u8;
double f64;
} data; //!< Value to store
Type type; //!< Type of the value
-#undef DECL_CONSTRUCTOR
};
} /* namespace ir */
delete _debug;
}
- /*! Use this to serialize multiple starts of the debugger */
- static MutexSys startMemDebuggerMutex;
+ /*! Bring up the debugger at pre-main */
+ static struct ForceMemDebugger {
+ ForceMemDebugger(void) {
+ doesnotmatter = GBE_NEW(int);
+ GBE_DELETE(doesnotmatter);
+ }
+ int *doesnotmatter;
+ } forceMemDebugger;
/*! Start the memory debugger */
static void MemDebuggerStart(void) {
- Lock<MutexSys> lock(startMemDebuggerMutex);
if (memDebugger == NULL) {
atexit(MemDebuggerEnd);
memDebugger = new MemDebugger;
if (ptr) {
const size_t size = ((uintptr_t*)ptr)[-2];
MemDebuggerInitializeMem(ptr, size);
- free(((void**)ptr)[-2]);
+ free(((void**)ptr)[-1]);
}
}
} /* namespace gbe */
-#else
+#else /* GBE_DEBUG_MEMORY */
////////////////////////////////////////////////////////////////////////////////
/// Windows Platform
{
friend class GrowingPool;
GrowingPoolElem(size_t elemNum) {
- const size_t sz = min(sizeof(T), 2 * sizeof(void*));
+ const size_t sz = min(sizeof(T), sizeof(void*));
this->data = (T*) GBE_ALIGNED_MALLOC(elemNum * sz, AlignOf<T>::value);
this->next = NULL;
this->maxElemNum = elemNum;
this->allocated = 0;
}
~GrowingPoolElem(void) {
- GBE_ASSERT(this->data);
- GBE_DELETE_ARRAY(this->data);
+ GBE_ALIGNED_FREE(this->data);
if (this->next) GBE_DELETE(this->next);
}
T *data;
/*! Produce a string from the macro locatiom */
#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; \
+};
+
/*! Portable AlignOf */
template <typename T>
struct AlignOf
using namespace gbe;
// Run the unit tests specified by the user
- if (argc > 2)
- for (int i = 2; i < argc; ++i)
+ if (argc >= 2)
+ for (int i = 1; i < argc; ++i)
UTest::run(argv[i]);
else
UTest::runAll();