From 1972355558eb8c1bba0567cc0c6897cd681edd27 Mon Sep 17 00:00:00 2001 From: bsegovia Date: Wed, 8 Feb 2012 09:55:18 -0800 Subject: [PATCH] Added first support for compilation units Added first support for constant definition Finished a first version of instruction definitions --- backend/src/CMakeLists.txt | 4 + backend/src/ir/ir_constant.cpp | 38 +++++ backend/src/ir/ir_constant.hpp | 70 +++++++++ backend/src/ir/ir_context.hpp | 36 +++++ backend/src/ir/ir_function.cpp | 4 + backend/src/ir/ir_function.hpp | 9 +- backend/src/ir/ir_instruction.cpp | 288 +++++++++++++++++++++++++++++++------- backend/src/ir/ir_instruction.hpp | 45 +++++- backend/src/ir/ir_register.hpp | 8 +- backend/src/ir/ir_unit.cpp | 32 +++++ backend/src/ir/ir_unit.hpp | 31 +++- 11 files changed, 502 insertions(+), 63 deletions(-) create mode 100644 backend/src/ir/ir_constant.cpp create mode 100644 backend/src/ir/ir_constant.hpp create mode 100644 backend/src/ir/ir_context.hpp diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt index 41972a8..0dfb3d6 100644 --- a/backend/src/CMakeLists.txt +++ b/backend/src/CMakeLists.txt @@ -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 index 0000000..0ac2d53 --- /dev/null +++ b/backend/src/ir/ir_constant.cpp @@ -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 . + * + * Author: Benjamin Segovia + */ + +#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 index 0000000..2b708d4 --- /dev/null +++ b/backend/src/ir/ir_constant.hpp @@ -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 . + * + * Author: Benjamin Segovia + */ + +#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 data; //!< The constant data serialized in one array + vector 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 index 0000000..6d04df0 --- /dev/null +++ b/backend/src/ir/ir_context.hpp @@ -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 . + * + * Author: Benjamin Segovia + */ + +#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__ */ + diff --git a/backend/src/ir/ir_function.cpp b/backend/src/ir/ir_function.cpp index 41a3657..976968d 100644 --- a/backend/src/ir/ir_function.cpp +++ b/backend/src/ir/ir_function.cpp @@ -18,4 +18,8 @@ */ #include "ir_function.hpp" +namespace gbe +{ + Function::Function(void) {} +} /* namespace gbe */ diff --git a/backend/src/ir/ir_function.hpp b/backend/src/ir/ir_function.hpp index 3954991..3699c3f 100644 --- a/backend/src/ir/ir_function.hpp +++ b/backend/src/ir/ir_function.hpp @@ -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 input; //!< Input registers of the function vector output; //!< Output registers of the function - vector immediate; //!< All immediate values stored in the function + vector value; //!< 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 0db1e81..1239f3c 100644 --- a/backend/src/ir/ir_instruction.cpp +++ b/backend/src/ir/ir_instruction.cpp @@ -23,16 +23,34 @@ 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::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 // 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(this)->getSrcNum(); - uint32 Instruction::getSrcNum(void) const { - const Opcode op = this->getOpcode(); +#define DECL_INSN(OPCODE, CLASS) \ + case OP_##OPCODE: reinterpret_cast(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(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(&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(&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(&insn); + } + + // CVT + Instruction cvt(Type dstType, Type srcType, RegisterIndex dst, TupleIndex src) { + internal::ConvertInstruction insn(dstType, srcType, dst, src); + return *reinterpret_cast(&insn); + } + + // BRA + Instruction bra(RegisterIndex dst, LabelIndex labelIndex) { + internal::BranchInstruction insn(labelIndex); + return *reinterpret_cast(&insn); + } + Instruction bra(RegisterIndex dst, LabelIndex labelIndex, RegisterIndex pred) { + internal::BranchInstruction insn(labelIndex, pred); + return *reinterpret_cast(&insn); + } + + // LOADI + Instruction loadi(Type type, RegisterIndex dst, ValueIndex value) { + internal::LoadImmInstruction insn(type, dst, value); + return *reinterpret_cast(&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(&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(&insn); + } + + // LABEL + Instruction label(LabelIndex labelIndex) { + internal::LabelInstruction insn(labelIndex); + return *reinterpret_cast(&insn); + } + } /* namespace gbe */ diff --git a/backend/src/ir/ir_instruction.hpp b/backend/src/ir/ir_instruction.hpp index edd6fba..3d23c50 100644 --- a/backend/src/ir/ir_instruction.hpp +++ b/backend/src/ir/ir_instruction.hpp @@ -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(insn); } template - INLINE const T &castc(const Instruction &insn) { + INLINE const T &cast(const Instruction &insn) { assert(insn.isMemberOf() == true); return reinterpret_cast(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__ */ diff --git a/backend/src/ir/ir_register.hpp b/backend/src/ir/ir_register.hpp index 7a63874..a0dd90e 100644 --- a/backend/src/ir/ir_register.hpp +++ b/backend/src/ir/ir_register.hpp @@ -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); }; diff --git a/backend/src/ir/ir_unit.cpp b/backend/src/ir/ir_unit.cpp index 1ff8523..4735a5c 100644 --- a/backend/src/ir/ir_unit.cpp +++ b/backend/src/ir/ir_unit.cpp @@ -18,4 +18,36 @@ */ #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 */ diff --git a/backend/src/ir/ir_unit.hpp b/backend/src/ir/ir_unit.hpp index ba6d711..2f5a2dd 100644 --- a/backend/src/ir/ir_unit.hpp +++ b/backend/src/ir/ir_unit.hpp @@ -20,6 +20,35 @@ #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 functions; //!< All the defined functions + ConstantSet constantSet; //!< All the constants defined in the unit + }; +} /* namespace gbe */ + +#endif /* __GBE_IR_UNIT_HPP__ */ -- 2.7.4