ir/printf.hpp
ir/structural_analysis.cpp
ir/structural_analysis.hpp
+ ir/immediate.hpp
+ ir/immediate.cpp
backend/context.cpp
backend/context.hpp
backend/program.cpp
const Immediate imm(value);
return fn->newImmediate(imm);
}
+ template <typename T> INLINE ImmediateIndex newImmediate(T value, uint32_t num) {
+ const Immediate imm(value, num);
+ return fn->newImmediate(imm);
+ }
+ /*! Create a new immediate value */
+ INLINE ImmediateIndex newImmediate(vector<ImmediateIndex>indexVector) {
+ vector<const Immediate*> immVector;
+ for( uint32_t i = 0; i < indexVector.size(); i++)
+ immVector.push_back(&fn->getImmediate(indexVector[i]));
+ const Immediate imm(immVector);
+ return fn->newImmediate(imm);
+ }
/*! Create an integer immediate value */
INLINE ImmediateIndex newIntegerImmediate(int64_t x, Type type) {
switch (type) {
return this->newImmediate(x);
}
+ INLINE ImmediateIndex processImm(ImmOpCode op, ImmediateIndex src, Type type) {
+ const Immediate &imm = fn->getImmediate(src);
+ const Immediate &dstImm = Immediate(op, imm, type);
+ return fn->newImmediate(dstImm);
+ }
+
+ INLINE ImmediateIndex processImm(ImmOpCode op, ImmediateIndex src0,
+ ImmediateIndex src1, Type type) {
+ const Immediate &imm0 = fn->getImmediate(src0);
+ const Immediate &imm1 = fn->getImmediate(src1);
+ const Immediate &dstImm = Immediate(op, imm0, imm1, type);
+ return fn->newImmediate(dstImm);
+ }
+
/*! Set an immediate value */
template <typename T> INLINE void setImmediate(ImmediateIndex index, T value) {
const Immediate imm(value);
GBE_ASSERTM(fn != NULL, "No function currently defined");
const Immediate imm(value);
const ImmediateIndex index = fn->newImmediate(imm);
- const RegisterFamily family = getFamily(imm.type);
+ const RegisterFamily family = getFamily(imm.getType());
const Register reg = this->reg(family);
- this->LOADI(imm.type, reg, index);
+ this->LOADI(imm.getType(), reg, index);
return reg;
}
/*! Create a new label for the current function */
case TYPE_HALF: out << "half(" << imm.getIntegerValue() << ")"; break;
case TYPE_FLOAT: out << imm.getFloatValue(); break;
case TYPE_DOUBLE: out << imm.getDoubleValue(); break;
+ default:
+ GBE_ASSERT(0 && "unsupported imm type.\n");
}
}
--- /dev/null
+/*
+ * 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/>.
+ *
+ */
+#include "immediate.hpp"
+
+using namespace gbe;
+using namespace ir;
+
+#define SCALAR_SAME_TYPE_ASSERT() \
+ GBE_ASSERT(this->getType() == right.getType() && \
+ this->getElemNum() == right.getElemNum() && \
+ this->getElemNum() == 1 && \
+ this->getType() != TYPE_BOOL);
+
+#define DECLAR_BINARY_ALL_TYPE_OP(OP) \
+ Immediate Immediate::operator OP (const Immediate &right) const { \
+ SCALAR_SAME_TYPE_ASSERT(); \
+ switch (this->getType()) { \
+ default: \
+ GBE_ASSERT(0); \
+ case TYPE_S8: return Immediate(*this->data.s8 OP *right.data.s8); \
+ case TYPE_U8: return Immediate(*this->data.u8 OP *right.data.u8); \
+ case TYPE_S16: return Immediate(*this->data.s16 OP *right.data.s16); \
+ case TYPE_U16: return Immediate(*this->data.u16 OP *right.data.u16); \
+ case TYPE_S32: return Immediate(*this->data.s32 OP *right.data.s32); \
+ case TYPE_U32: return Immediate(*this->data.u32 OP *right.data.u32); \
+ case TYPE_S64: return Immediate(*this->data.s64 OP *right.data.s64); \
+ case TYPE_U64: return Immediate(*this->data.u64 OP *right.data.u64); \
+ case TYPE_FLOAT: return Immediate(*this->data.f32 OP *right.data.f32); \
+ case TYPE_DOUBLE: return Immediate(*this->data.f64 OP *right.data.f64); \
+ }\
+ return *this;\
+ }
+
+ DECLAR_BINARY_ALL_TYPE_OP(+)
+ DECLAR_BINARY_ALL_TYPE_OP(-)
+ DECLAR_BINARY_ALL_TYPE_OP(*)
+ DECLAR_BINARY_ALL_TYPE_OP(/)
+
+#undef DECLAR_BINARY_ALL_TYPE_OP
+
+#define DECLAR_BINARY_INT_TYPE_OP(OP) \
+ Immediate Immediate::operator OP (const Immediate &right) const { \
+ SCALAR_SAME_TYPE_ASSERT(); \
+ switch (this->getType()) { \
+ default: \
+ GBE_ASSERT(0); \
+ case TYPE_S8: return Immediate(*this->data.s8 OP *right.data.s8); \
+ case TYPE_U8: return Immediate(*this->data.u8 OP *right.data.u8); \
+ case TYPE_S16: return Immediate(*this->data.s16 OP *right.data.s16); \
+ case TYPE_U16: return Immediate(*this->data.u16 OP *right.data.u16); \
+ case TYPE_S32: return Immediate(*this->data.s32 OP *right.data.s32); \
+ case TYPE_U32: return Immediate(*this->data.u32 OP *right.data.u32); \
+ case TYPE_S64: return Immediate(*this->data.s64 OP *right.data.s64); \
+ case TYPE_U64: return Immediate(*this->data.u64 OP *right.data.u64); \
+ }\
+ return *this;\
+ }
+ DECLAR_BINARY_INT_TYPE_OP(%)
+ DECLAR_BINARY_INT_TYPE_OP(&)
+ DECLAR_BINARY_INT_TYPE_OP(|)
+ DECLAR_BINARY_INT_TYPE_OP(^)
+#undef DECLAR_BINARY_INT_TYPE_OP
+
+
+#define DECLAR_BINARY_ASHIFT_OP(OP) \
+ Immediate Immediate::operator OP (const Immediate &right) const { \
+ GBE_ASSERT(this->getType() > TYPE_BOOL && this->getType() <= TYPE_U64); \
+ int32_t shift = right.getIntegerValue(); \
+ if (shift == 0) \
+ return *this; \
+ else \
+ switch (this->getType()) { \
+ default: \
+ GBE_ASSERT(0); \
+ case TYPE_S8: return Immediate((*this->data.s8 OP shift)); \
+ case TYPE_U8: return Immediate((*this->data.u8 OP shift)); \
+ case TYPE_S16: return Immediate((*this->data.s16 OP shift)); \
+ case TYPE_U16: return Immediate((*this->data.u16 OP shift)); \
+ case TYPE_S32: return Immediate((*this->data.s32 OP shift)); \
+ case TYPE_U32: return Immediate((*this->data.u32 OP shift)); \
+ case TYPE_S64: return Immediate((*this->data.s64 OP shift)); \
+ case TYPE_U64: return Immediate((*this->data.u64 OP shift)); \
+ } \
+ }
+
+ DECLAR_BINARY_ASHIFT_OP(>>)
+ DECLAR_BINARY_ASHIFT_OP(<<)
+
+#undef DECLAR_BINARY_ASHIFT_OP
+ Immediate Immediate::lshr (const Immediate &left, const Immediate &right) {
+ GBE_ASSERT(left.getType() > TYPE_BOOL && left.getType() <= TYPE_U64);
+ int32_t shift = right.getIntegerValue();
+ if (shift == 0)
+ return left;
+ else
+ switch (left.getType()) {
+ default:
+ GBE_ASSERT(0);
+ case TYPE_S8:
+ case TYPE_U8: return Immediate((*left.data.u8 >> shift));
+ case TYPE_S16:
+ case TYPE_U16: return Immediate((*left.data.u16 >> shift));
+ case TYPE_S32:
+ case TYPE_U32: return Immediate((*left.data.u32 >> shift));
+ case TYPE_S64:
+ case TYPE_U64: return Immediate((*left.data.u64 >> shift));
+ }
+ }
+
+ Immediate::Immediate(ImmOpCode op, const Immediate &left, const Immediate &right, Type dstType) {
+ switch (op) {
+ default:
+ GBE_ASSERT(0 && "unsupported imm op\n");
+ case IMM_ADD: *this = left + right; break;
+ case IMM_SUB: *this = left - right; break;
+ case IMM_MUL: *this = left * right; break;
+ case IMM_DIV: *this = left / right; break;
+ case IMM_AND: *this = left & right; break;
+ case IMM_OR: *this = left | right; break;
+ case IMM_XOR: *this = left ^ right; break;
+ case IMM_REM:
+ {
+ if (left.getType() > TYPE_BOOL && left.getType() <= TYPE_U64)
+ *this = left % right;
+ else if (left.getType() == TYPE_FLOAT && right.getType() == TYPE_FLOAT) {
+ *this = Immediate(left);
+ *this->data.f32 = fmodf(left.getFloatValue(), right.getFloatValue());
+ }
+ else if (left.getType() == TYPE_DOUBLE && right.getType() == TYPE_DOUBLE) {
+ *this = Immediate(left);
+ *this->data.f64 += fmod(left.getDoubleValue(), right.getDoubleValue());
+ }
+ else
+ GBE_ASSERT(0);
+ break;
+ }
+ case IMM_LSHR:
+ {
+ if (left.getElemNum() == 1)
+ lshr(left, right);
+ else {
+ GBE_ASSERT(right.getIntegerValue() <= (left.getElemNum() * left.getTypeSize() * 8));
+ GBE_ASSERT(right.getIntegerValue() % (left.getTypeSize() * 8) == 0);
+ copy(left, right.getIntegerValue() / (left.getTypeSize() * 8), left.getElemNum());
+ }
+ break;
+ }
+ case IMM_ASHR:
+ {
+ if (left.getElemNum() == 1)
+ *this = left >> right;
+ else {
+ GBE_ASSERT(0 && "Doesn't support ashr on array constant.");
+ copy(left, right.getIntegerValue() / (left.getTypeSize() * 8), left.getElemNum());
+ }
+ break;
+ }
+ case IMM_SHL:
+ {
+ if (left.getElemNum() == 1)
+ *this = left << right;
+ else {
+ GBE_ASSERT(right.getIntegerValue() <= (left.getElemNum() * left.getTypeSize() * 8));
+ GBE_ASSERT(right.getIntegerValue() % (left.getTypeSize() * 8) == 0);
+ copy(left, -right.getIntegerValue() / (left.getTypeSize() * 8), left.getElemNum());
+ }
+ break;
+ }
+ }
+ // If the dst type is large int, we will not change the imm type to large int.
+ GBE_ASSERT(type == (ImmType)dstType || dstType == TYPE_LARGE_INT);
+ }
+
+ Immediate::Immediate(const vector<const Immediate*> immVec) {
+ if (immVec.size() == 1) {
+ *this = *immVec[0];
+ } else if (!(immVec[0]->isCompType()) && immVec[0]->elemNum == 1) {
+ this->type = immVec[0]->type;
+ this->elemNum = immVec.size();
+ if (immVec[0]->getTypeSize() * immVec.size() < 8)
+ this->data.p = &this->defaultData;
+ else
+ this->data.p = malloc(immVec[0]->getTypeSize() * immVec.size());
+ uint8_t *p = (uint8_t*)this->data.p;
+ for(uint32_t i = 0; i < immVec.size(); i++) {
+ GBE_ASSERT(immVec[i]->type == immVec[0]->type && immVec[i]->elemNum == 1);
+ memcpy(p, immVec[i]->data.p, immVec[i]->getTypeSize());
+ p += immVec[i]->getTypeSize();
+ }
+ } else {
+ this->type = IMM_TYPE_COMP;
+ if (immVec.size() * sizeof(Immediate*) < 8)
+ this->data.p = &this->defaultData;
+ else
+ this->data.p = malloc(immVec.size() * sizeof(Immediate*));
+ this->elemNum = immVec.size();
+ for(uint32_t i = 0; i < immVec.size(); i++)
+ this->data.immVec[i] = immVec[i];
+ }
+ }
+
+
+ // operator = and copy() are only called from constructor functions
+ // which this never hold a memory pointer, we don't need to bother
+ // to check the data.p before assignment.
+ Immediate & Immediate::operator= (const Immediate & other) {
+ if (this != &other) {
+ type = other.type;
+ elemNum = other.elemNum;
+ if (other.data.p != &other.defaultData) {
+ data.p = malloc(other.elemNum * other.getTypeSize());
+ memcpy(data.p, other.data.p, other.elemNum * other.getTypeSize());
+ }
+ else {
+ defaultData = other.defaultData;
+ data.p = &defaultData;
+ }
+ }
+ return *this;
+ }
+
+ void Immediate::copy(const Immediate &other, int32_t offset, uint32_t num) {
+ if (this != &other) {
+ if (other.type == IMM_TYPE_COMP && num == 1) {
+ GBE_ASSERT(offset >= 0 && offset <= (int32_t)other.elemNum);
+ *this = *other.data.immVec[offset];
+ return;
+ }
+ type = other.type;
+ elemNum = num;
+ if (num * other.getTypeSize() < 8)
+ data.p = &defaultData;
+ else
+ data.p = malloc(num * other.getTypeSize());
+ uint8_t* datap = (uint8_t*)data.p;
+ memset(datap, 0, num * other.getTypeSize());
+ if (offset < 0) {
+ datap += (-offset) * other.getTypeSize();
+ num -= num < (uint32_t)(-offset) ? num : (-offset);
+ offset = 0;
+ } else if (offset > 0 && num > 1) {
+ GBE_ASSERT((int32_t)num > offset);
+ num -= offset;
+ }
+ memcpy(datap, (uint8_t*)other.data.p + offset * other.getTypeSize(),
+ num * other.getTypeSize());
+ }
+ }
*/
/**
- * \file value.hpp
+ * \file Immediate.hpp
*
* \author Benjamin Segovia <benjamin.segovia@intel.com>
*/
namespace gbe {
namespace ir {
+ typedef enum {
+ IMM_TRUNC = 0,
+ IMM_BITCAST,
+ IMM_ADD,
+ IMM_SUB,
+ IMM_MUL,
+ IMM_DIV,
+ IMM_REM,
+ IMM_SHL,
+ IMM_ASHR,
+ IMM_LSHR,
+ IMM_AND,
+ IMM_OR,
+ IMM_XOR
+ } ImmOpCode;
+
+ typedef enum {
+ IMM_TYPE_BOOL = TYPE_BOOL,
+ IMM_TYPE_S8 = TYPE_S8,
+ IMM_TYPE_U8 = TYPE_U8,
+ IMM_TYPE_S16 = TYPE_S16,
+ IMM_TYPE_U16 = TYPE_U16,
+ IMM_TYPE_S32 = TYPE_S32,
+ IMM_TYPE_U32 = TYPE_U32,
+ IMM_TYPE_S64 = TYPE_S64,
+ IMM_TYPE_U64 = TYPE_U64,
+ IMM_TYPE_FLOAT = TYPE_FLOAT,
+ IMM_TYPE_DOUBLE = TYPE_DOUBLE,
+ IMM_TYPE_COMP // compond immediate which consist many immediates.
+ } ImmType;
+
/*! The value as stored in the instruction */
class Immediate
{
public:
- INLINE Immediate(void) {}
+ INLINE Immediate(void) { }
+
+ INLINE Type getType(void) const {
+ return (Type)type;
+ }
+
+ INLINE bool isCompType(void) const {
+ return type == IMM_TYPE_COMP;
+ }
- Type getType(void) const {
- return type;
+ INLINE uint32_t getElemNum(void) const {
+ return elemNum;
}
uint32_t getTypeSize(void) const {
case TYPE_DOUBLE:
case TYPE_S64:
case TYPE_U64: return 8;
+ case IMM_TYPE_COMP: return sizeof(Immediate*);
}
}
#define DECL_CONSTRUCTOR(TYPE, FIELD, IR_TYPE) \
Immediate(TYPE FIELD) { \
- this->type = IR_TYPE; \
+ this->type = (ImmType)IR_TYPE; \
this->elemNum = 1; \
this->data.p = &defaultData; \
defaultData = 0ull; \
#define DECL_CONSTRUCTOR(TYPE, FIELD, IR_TYPE, ELEMNUM) \
Immediate(TYPE *FIELD, uint32_t ELEMNUM) { \
- this->type = IR_TYPE; \
+ this->type = (ImmType)IR_TYPE; \
this->elemNum = ELEMNUM; \
if (elemNum * ELEMNUM > 8) \
this->data.p = malloc(ELEMNUM * getTypeSize()); \
DECL_CONSTRUCTOR(double, f64, TYPE_DOUBLE, elemNum)
#undef DECL_CONSTRUCTOR
- int64_t getIntegerValue(void) const {
+ Immediate(const vector<const Immediate*> immVec);
+
+ INLINE int64_t getIntegerValue(void) const {
switch (type) {
default:
GBE_ASSERT(0 && "Invalid immediate type.\n");
}
}
- float getFloatValue(void) const {
- GBE_ASSERT(type == TYPE_FLOAT);
+ INLINE float getFloatValue(void) const {
+ GBE_ASSERT(type == IMM_TYPE_FLOAT);
return *data.f32;
}
- float asFloatValue(void) const {
- GBE_ASSERT(type == TYPE_FLOAT || type == TYPE_U32 || type == TYPE_S32);
+ INLINE float asFloatValue(void) const {
+ GBE_ASSERT(type == IMM_TYPE_FLOAT || type == IMM_TYPE_U32 || type == IMM_TYPE_S32);
return *data.f32;
}
- int64_t asIntegerValue(void) const {
+ INLINE int64_t asIntegerValue(void) const {
GBE_ASSERT(elemNum == 1);
return *data.s64;
}
- double getDoubleValue(void) const {
- GBE_ASSERT(type == TYPE_DOUBLE);
+ INLINE double getDoubleValue(void) const {
+ GBE_ASSERT(type == IMM_TYPE_DOUBLE);
return *data.f64;
}
+
+ INLINE Immediate(const Immediate & other) {
+ *this = other;
+ }
- Immediate(const Immediate & other) {
- if (this != &other) {
- this->type = other.type;
- this->elemNum = other.elemNum;
- if (other.data.p != &other.defaultData) {
- this->data.p = malloc(other.elemNum * other.getTypeSize());
- memcpy(this->data.p, other.data.p, other.elemNum * other.getTypeSize());
- }
- else {
- this->defaultData = other.defaultData;
- this->data.p = &this->defaultData;
- }
+ Immediate(ImmOpCode op, const Immediate &other, Type dstType) {
+ if (op == IMM_TRUNC) {
+ copy(other, 0, 1);
+ } else if (op == IMM_BITCAST) {
+ *this = other;
+ type = (ImmType)dstType;
}
}
- Immediate & operator= (const Immediate & other) {
- *this = Immediate(other);
- return *this;
- }
+ Immediate(ImmOpCode op, const Immediate &left, const Immediate &right, Type dstType);
~Immediate() {
if (data.p != &defaultData) {
uint64_t *u64;
float *f32;
double *f64;
+ const Immediate *immVec[];
void *p;
} data; //!< Value to store
- Type type; //!< Type of the value
+ ImmType type; //!< Type of the value
uint32_t elemNum; //!< vector imm data type
uint64_t defaultData;
+ Immediate & operator= (const Immediate &);
+ Immediate operator+ (const Immediate &) const;
+ Immediate operator- (const Immediate &) const;
+ Immediate operator* (const Immediate &) const;
+ Immediate operator/ (const Immediate &) const;
+ Immediate operator% (const Immediate &) const;
+ Immediate operator& (const Immediate &) const;
+ Immediate operator| (const Immediate &) const;
+ Immediate operator^ (const Immediate &) const;
+ Immediate operator<< (const Immediate &) const;
+ Immediate operator>> (const Immediate &) const;
+ static Immediate lshr (const Immediate &left, const Immediate &right);
+
+ void copy(const Immediate &other, int32_t offset, uint32_t num);
GBE_CLASS(Immediate);
};
case TYPE_S8: return imm.getIntegerValue();
case TYPE_BOOL:
case TYPE_HALF: NOT_SUPPORTED; return 0;
+ default:
+ GBE_ASSERT(0 && "Unsupported imm type.\n");
}
return 0;
}
case TYPE_HALF: return out << "half";
case TYPE_FLOAT: return out << "float";
case TYPE_DOUBLE: return out << "double";
+ default :
+ GBE_ASSERT(0 && "Unsupported type\n");
};
return out;
}
TYPE_U64, //!< unsigned 64 bits integer
TYPE_HALF, //!< 16 bits floating point value
TYPE_FLOAT, //!< 32 bits floating point value
- TYPE_DOUBLE //!< 64 bits floating point value
+ TYPE_DOUBLE, //!< 64 bits floating point value
+ TYPE_LARGE_INT //!< integer larger than 64 bits.
};
/*! Output a string for the type in the given stream */
case TYPE_U64:
case TYPE_DOUBLE:
return FAMILY_QWORD;
+ default:
+ return FAMILY_DWORD;
};
- return FAMILY_DWORD;
}
/*! Return a type for each register family */
return ir::TYPE_S32;
if (type == Type::getInt64Ty(type->getContext()))
return ir::TYPE_S64;
- ctx.getUnit().setValid(false);
- return ir::TYPE_S64;
+ return ir::TYPE_LARGE_INT;
}
/*! LLVM IR Type to Gen IR unsigned type translation */
PASS_EMIT_INSTRUCTIONS = 1
} pass;
+ typedef enum {
+ CONST_INT,
+ CONST_FLOAT,
+ CONST_DOUBLE
+ } ConstTypeId;
+
LoopInfo *LI;
const Module *TheModule;
int btiBase;
/*! helper function for parsing global constant data */
void getConstantData(const Constant * c, void* mem, uint32_t& offset) const;
void collectGlobalConstant(void) const;
- ir::ImmediateIndex processConstantImmIndex(Constant *CPV, uint32_t index = 0u);
- const ir::Immediate &processConstantImm(Constant *CPV, uint32_t index = 0u);
+ ir::ImmediateIndex processConstantImmIndex(Constant *CPV, int32_t index = 0u);
+ const ir::Immediate &processConstantImm(Constant *CPV, int32_t index = 0u);
bool runOnFunction(Function &F) {
// Do not codegen any 'available_externally' functions at all, they have
Value *llvmValue, const ir::Register ptr,
const ir::AddressSpace addrSpace, Type * elemType, bool isLoad, ir::BTI bti);
void visitInstruction(Instruction &I) {NOT_SUPPORTED;}
+ private:
+ ir::ImmediateIndex processConstantImmIndexImpl(Constant *CPV, int32_t index = 0u);
+ template <typename T, typename P = T>
+ ir::ImmediateIndex processSeqConstant(ConstantDataSequential *seq,
+ int index, ConstTypeId tid);
+ ir::ImmediateIndex processConstantVector(ConstantVector *cv, int index);
};
char GenWriter::ID = 0;
return false;
}
- ir::ImmediateIndex GenWriter::processConstantImmIndex(Constant *CPV, uint32_t index)
+ #define GET_EFFECT_DATA(_seq, _index, _tid) \
+ ((_tid == CONST_INT) ? _seq->getElementAsInteger(_index) : \
+ ((_tid == CONST_FLOAT) ? _seq->getElementAsFloat(_index) : \
+ _seq->getElementAsDouble(_index)))
+
+ // typename P is for bool only, as c++ set the &vector<bool)vec[0] to void
+ // type. We have to use uint8_t for bool vector.
+ template <typename T, typename P>
+ ir::ImmediateIndex GenWriter::processSeqConstant(ConstantDataSequential *seq,
+ int index, ConstTypeId tid) {
+ if (index >= 0) {
+ const T data = GET_EFFECT_DATA(seq, index, tid);
+ return ctx.newImmediate(data);
+ } else {
+ vector<P> array;
+ for(int i = 0; i < seq->getNumElements(); i++)
+ array.push_back(GET_EFFECT_DATA(seq, i, tid));
+ return ctx.newImmediate((T*)&array[0], array.size());
+ }
+ }
+
+ ir::ImmediateIndex GenWriter::processConstantVector(ConstantVector *cv, int index) {
+ if (index >= 0) {
+ Constant *c = cv->getOperand(index);
+ return processConstantImmIndex(c, -1);
+ } else {
+ vector<ir::ImmediateIndex> immVector;
+ for (uint32_t i = 0; i < cv->getNumOperands(); i++)
+ immVector.push_back(processConstantImmIndex(cv->getOperand(i)));
+ return ctx.newImmediate(immVector);
+ }
+ }
+
+ ir::ImmediateIndex GenWriter::processConstantImmIndexImpl(Constant *CPV, int32_t index)
{
-#if GBE_DEBUG
- GBE_ASSERTM(dyn_cast<ConstantExpr>(CPV) == NULL, "Unsupported constant expression");
- if (isa<UndefValue>(CPV) && CPV->getType()->isSingleValueType())
- GBE_ASSERTM(false, "Unsupported constant expression");
-#endif /* GBE_DEBUG */
+ GBE_ASSERT(dyn_cast<ConstantExpr>(CPV) == NULL);
#if LLVM_VERSION_MINOR > 0
ConstantDataSequential *seq = dyn_cast<ConstantDataSequential>(CPV);
if (seq) {
Type *Ty = seq->getElementType();
if (Ty == Type::getInt1Ty(CPV->getContext())) {
- const uint64_t u64 = seq->getElementAsInteger(index);
- return ctx.newImmediate(bool(u64));
+ return processSeqConstant<bool, uint8_t>(seq, index, CONST_INT);
} else if (Ty == Type::getInt8Ty(CPV->getContext())) {
- const uint64_t u64 = seq->getElementAsInteger(index);
- return ctx.newImmediate(uint8_t(u64));
+ return processSeqConstant<uint8_t>(seq, index, CONST_INT);
} else if (Ty == Type::getInt16Ty(CPV->getContext())) {
- const uint64_t u64 = seq->getElementAsInteger(index);
- return ctx.newImmediate(uint16_t(u64));
+ return processSeqConstant<uint16_t>(seq, index, CONST_INT);
} else if (Ty == Type::getInt32Ty(CPV->getContext())) {
- const uint64_t u64 = seq->getElementAsInteger(index);
- return ctx.newImmediate(uint32_t(u64));
+ return processSeqConstant<uint32_t>(seq, index, CONST_INT);
} else if (Ty == Type::getInt64Ty(CPV->getContext())) {
- const uint64_t u64 = seq->getElementAsInteger(index);
- return ctx.newImmediate(u64);
+ return processSeqConstant<uint64_t>(seq, index, CONST_INT);
} else if (Ty == Type::getFloatTy(CPV->getContext())) {
- const float f32 = seq->getElementAsFloat(index);
- return ctx.newImmediate(f32);
+ return processSeqConstant<float>(seq, index, CONST_FLOAT);
} else if (Ty == Type::getDoubleTy(CPV->getContext())) {
- const double f64 = seq->getElementAsDouble(index);
- return ctx.newImmediate(f64);
+ return processSeqConstant<double>(seq, index, CONST_DOUBLE);
}
} else
#endif /* LLVM_VERSION_MINOR > 0 */
}
} else {
if (dyn_cast<ConstantVector>(CPV))
- CPV = extractConstantElem(CPV, index);
+ return processConstantVector(dyn_cast<ConstantVector>(CPV), index);
GBE_ASSERTM(dyn_cast<ConstantExpr>(CPV) == NULL, "Unsupported constant expression");
// Integers
const uint64_t u64 = CI->getZExtValue();
return ctx.newImmediate(u64);
} else {
- GBE_ASSERTM(false, "Unsupported integer size");
- return ctx.newImmediate(uint64_t(0));
+ return ctx.newImmediate(uint64_t(CI->getZExtValue()));
}
}
return ctx.newImmediate(uint32_t(0));
}
- // Floats and doubles
const Type::TypeID typeID = CPV->getType()->getTypeID();
+ if (isa<UndefValue>(CPV)) {
+ Type* Ty = CPV->getType();
+ if (Ty == Type::getInt1Ty(CPV->getContext())) return ctx.newImmediate(false);
+ if (Ty == Type::getInt8Ty(CPV->getContext())) return ctx.newImmediate((uint8_t)0);
+ if (Ty == Type::getInt16Ty(CPV->getContext())) return ctx.newImmediate((uint16_t)0);
+ if (Ty == Type::getInt32Ty(CPV->getContext())) return ctx.newImmediate((uint32_t)0);
+ if (Ty == Type::getInt64Ty(CPV->getContext())) return ctx.newImmediate((uint64_t)0);
+ if (Ty == Type::getFloatTy(CPV->getContext())) return ctx.newImmediate((float)0);
+ if (Ty == Type::getDoubleTy(CPV->getContext())) return ctx.newImmediate((double)0);
+ GBE_ASSERT(0 && "Unsupported undef value type.\n");
+ }
+
+ // Floats and doubles
switch (typeID) {
case Type::FloatTyID:
case Type::DoubleTyID:
return ctx.newImmediate(uint64_t(0));
}
- const ir::Immediate &GenWriter::processConstantImm(Constant *CPV, uint32_t index) {
+ ir::ImmediateIndex GenWriter::processConstantImmIndex(Constant *CPV, int32_t index) {
+ if (dyn_cast<ConstantExpr>(CPV) == NULL)
+ return processConstantImmIndexImpl(CPV, index);
+
+ if (dyn_cast<ConstantExpr>(CPV)) {
+ ConstantExpr *ce = dyn_cast<ConstantExpr>(CPV);
+ ir::Type type = getType(ctx, ce->getType());
+ switch (ce->getOpcode()) {
+ default:
+ //ce->dump();
+ GBE_ASSERT(0 && "unsupported ce opcode.\n");
+ case Instruction::Trunc:
+ {
+ const ir::ImmediateIndex immIndex = processConstantImmIndex(ce->getOperand(0), -1);
+ return ctx.processImm(ir::IMM_TRUNC, immIndex, type);
+ }
+ case Instruction::BitCast:
+ {
+ const ir::ImmediateIndex immIndex = processConstantImmIndex(ce->getOperand(0), -1);
+ if (type == ir::TYPE_LARGE_INT)
+ return immIndex;
+ return ctx.processImm(ir::IMM_BITCAST, immIndex, type);
+ }
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ case Instruction::SDiv:
+ case Instruction::SRem:
+ case Instruction::Shl:
+ case Instruction::AShr:
+ case Instruction::LShr:
+ case Instruction::And:
+ case Instruction::Or:
+ case Instruction::Xor: {
+ const ir::ImmediateIndex lhs = processConstantImmIndex(ce->getOperand(0), -1);
+ const ir::ImmediateIndex rhs = processConstantImmIndex(ce->getOperand(1), -1);
+ switch (ce->getOpcode()) {
+ default:
+ //ce->dump();
+ GBE_ASSERTM(0, "Unsupported constant expression.\n");
+ case Instruction::Add:
+ return ctx.processImm(ir::IMM_ADD, lhs, rhs, type);
+ case Instruction::Sub:
+ return ctx.processImm(ir::IMM_SUB, lhs, rhs, type);
+ case Instruction::Mul:
+ return ctx.processImm(ir::IMM_MUL, lhs, rhs, type);
+ case Instruction::SDiv:
+ return ctx.processImm(ir::IMM_DIV, lhs, rhs, type);
+ case Instruction::SRem:
+ return ctx.processImm(ir::IMM_REM, lhs, rhs, type);
+ case Instruction::Shl:
+ return ctx.processImm(ir::IMM_SHL, lhs, rhs, type);
+ case Instruction::AShr:
+ return ctx.processImm(ir::IMM_ASHR, lhs, rhs, type);
+ case Instruction::LShr:
+ return ctx.processImm(ir::IMM_LSHR, lhs, rhs, type);
+ case Instruction::And:
+ return ctx.processImm(ir::IMM_AND, lhs, rhs, type);
+ case Instruction::Or:
+ return ctx.processImm(ir::IMM_OR, lhs, rhs, type);
+ case Instruction::Xor:
+ return ctx.processImm(ir::IMM_XOR, lhs, rhs, type);
+ }
+ }
+ }
+ }
+ GBE_ASSERT(0 && "unsupported constant.\n");
+ return ctx.newImmediate((uint32_t)0);
+ }
+
+ const ir::Immediate &GenWriter::processConstantImm(Constant *CPV, int32_t index) {
ir::ImmediateIndex immIndex = processConstantImmIndex(CPV, index);
return ctx.getFunction().getImmediate(immIndex);
}
ir::Register GenWriter::getConstantRegister(Constant *c, uint32_t elemID) {
GBE_ASSERT(c != NULL);
-
if(isa<GlobalValue>(c)) {
return regTranslator.getScalar(c, elemID);
}