From 0c94df24a1a2b62200a774f5b46ae6478ad7f7e4 Mon Sep 17 00:00:00 2001 From: Benjamin Segovia Date: Fri, 17 Feb 2012 08:27:01 +0000 Subject: [PATCH] Added type safety for all uint* Added one more test --- backend/src/CMakeLists.txt | 1 + backend/src/ir/function.cpp | 2 +- backend/src/ir/function.hpp | 52 +++++++++++++++++++++--------------------- backend/src/ir/instruction.cpp | 25 +++++++++++--------- backend/src/ir/instruction.hpp | 9 ++++---- backend/src/ir/register.hpp | 22 ++---------------- backend/src/ir/value.hpp | 10 ++++---- backend/src/sys/alloc.cpp | 15 ++++++++---- backend/src/sys/alloc.hpp | 5 ++-- backend/src/sys/platform.hpp | 13 +++++++++++ backend/src/utest/tester.cpp | 4 ++-- 11 files changed, 80 insertions(+), 78 deletions(-) diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt index 87f2107..3b61e1e 100644 --- a/backend/src/CMakeLists.txt +++ b/backend/src/CMakeLists.txt @@ -38,6 +38,7 @@ else (GBE_USE_BLOB) set (GBE_SRC ${GBE_SRC} utest/utest_test_utest.cpp + utest/utest_context.cpp utest/utest.cpp utest/utest.hpp) endif (GBE_COMPILE_UTEST) diff --git a/backend/src/ir/function.cpp b/backend/src/ir/function.cpp index 7dd1588..a319dba 100644 --- a/backend/src/ir/function.cpp +++ b/backend/src/ir/function.cpp @@ -35,7 +35,7 @@ namespace ir { 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 */ diff --git a/backend/src/ir/function.hpp b/backend/src/ir/function.hpp index ed7be14..2c1d02a 100644 --- a/backend/src/ir/function.hpp +++ b/backend/src/ir/function.hpp @@ -41,21 +41,21 @@ 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 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 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 @@ -75,9 +75,9 @@ namespace ir { 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) { @@ -94,16 +94,16 @@ namespace ir { /*! 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 input; //!< Input registers of the function - vector output; //!< Output registers of the function - vector labels; //!< Each label points to a basic block - vector values; //!< All immediate values in the function - vector blocks; //!< All chained basic blocks - RegisterFile file; //!< Registers used by the instructions + friend class Context; //!< Can freely modify a function + vector input; //!< Input registers of the function + vector output; //!< Output registers of the function + vector labels; //!< Each label points to a basic block + vector immediates; //!< All immediate values in the function + vector blocks; //!< All chained basic blocks + RegisterFile file; //!< Registers used by the instructions GrowingPool insnPool; //!< For fast instruction allocation GBE_CLASS(Function); }; diff --git a/backend/src/ir/instruction.cpp b/backend/src/ir/instruction.cpp index f16975a..31bb874 100644 --- a/backend/src/ir/instruction.cpp +++ b/backend/src/ir/instruction.cpp @@ -313,14 +313,17 @@ namespace ir { 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 { @@ -329,9 +332,9 @@ namespace ir { } 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 @@ -479,11 +482,11 @@ namespace ir { // 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; } @@ -679,7 +682,7 @@ DECL_MEM_FN(StoreInstruction, MemorySpace, getAddressSpace(void), getAddressSpac 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()) @@ -765,7 +768,7 @@ 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(); } diff --git a/backend/src/ir/instruction.hpp b/backend/src/ir/instruction.hpp index 2977e13..3190f25 100644 --- a/backend/src/ir/instruction.hpp +++ b/backend/src/ir/instruction.hpp @@ -19,7 +19,6 @@ /** * \file instruction.hpp - * * \author Benjamin Segovia */ #ifndef __GBE_IR_INSTRUCTION_HPP__ @@ -49,10 +48,10 @@ namespace ir { }; /*! 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 @@ -209,7 +208,7 @@ namespace ir { 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 */ @@ -343,7 +342,7 @@ namespace ir { /*! (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 */ diff --git a/backend/src/ir/register.hpp b/backend/src/ir/register.hpp index c2dd066..0123dad 100644 --- a/backend/src/ir/register.hpp +++ b/backend/src/ir/register.hpp @@ -61,30 +61,12 @@ namespace ir { /*! 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 diff --git a/backend/src/ir/value.hpp b/backend/src/ir/value.hpp index a66081c..f5aa72e 100644 --- a/backend/src/ir/value.hpp +++ b/backend/src/ir/value.hpp @@ -32,13 +32,14 @@ namespace gbe { 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; @@ -52,7 +53,6 @@ namespace ir { double f64; } data; //!< Value to store Type type; //!< Type of the value -#undef DECL_CONSTRUCTOR }; } /* namespace ir */ diff --git a/backend/src/sys/alloc.cpp b/backend/src/sys/alloc.cpp index 55a315e..af4d390 100644 --- a/backend/src/sys/alloc.cpp +++ b/backend/src/sys/alloc.cpp @@ -146,12 +146,17 @@ namespace gbe 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 lock(startMemDebuggerMutex); if (memDebugger == NULL) { atexit(MemDebuggerEnd); memDebugger = new MemDebugger; @@ -223,12 +228,12 @@ namespace gbe 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 diff --git a/backend/src/sys/alloc.hpp b/backend/src/sys/alloc.hpp index 58aa8a4..ed1e346 100644 --- a/backend/src/sys/alloc.hpp +++ b/backend/src/sys/alloc.hpp @@ -214,15 +214,14 @@ namespace gbe { 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::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; diff --git a/backend/src/sys/platform.hpp b/backend/src/sys/platform.hpp index d4c451e..88f217e 100644 --- a/backend/src/sys/platform.hpp +++ b/backend/src/sys/platform.hpp @@ -237,6 +237,19 @@ do { \ /*! 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 struct AlignOf diff --git a/backend/src/utest/tester.cpp b/backend/src/utest/tester.cpp index 5fcb947..ffbb915 100644 --- a/backend/src/utest/tester.cpp +++ b/backend/src/utest/tester.cpp @@ -30,8 +30,8 @@ int main(int argc, char *argv[]) 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(); -- 2.7.4