diff --git a/ctx.cpp b/ctx.cpp index fb7ec7f9..1ad5d086 100644 --- a/ctx.cpp +++ b/ctx.cpp @@ -1468,7 +1468,7 @@ FunctionEmitContext::applyVaryingGEP(llvm::Value *basePtr, llvm::Value *index, // Find the scale factor for the index (i.e. the size of the object // that the pointer(s) point(s) to. const Type *scaleType = ptrType->GetBaseType(); - llvm::Value *scale = g->target.SizeOf(scaleType->LLVMType(g->ctx)); + llvm::Value *scale = g->target.SizeOf(scaleType->LLVMType(g->ctx), bblock); bool indexIsVarying = llvm::isa(index->getType()); @@ -1651,7 +1651,8 @@ FunctionEmitContext::AddElementOffset(llvm::Value *basePtr, int elementNum, if (st != NULL) // If the pointer is to a structure, Target::StructOffset() gives // us the offset in bytes to the given element of the structure - offset = g->target.StructOffset(st->LLVMType(g->ctx), elementNum); + offset = g->target.StructOffset(st->LLVMType(g->ctx), elementNum, + bblock); else { // Otherwise we should have a vector or array here and the offset // is given by the element number times the size of the element @@ -1660,7 +1661,7 @@ FunctionEmitContext::AddElementOffset(llvm::Value *basePtr, int elementNum, dynamic_cast(ptrType->GetBaseType()); Assert(st != NULL); llvm::Value *size = - g->target.SizeOf(st->GetElementType()->LLVMType(g->ctx)); + g->target.SizeOf(st->GetElementType()->LLVMType(g->ctx), bblock); llvm::Value *scale = (g->target.is32Bit || g->opt.force32BitAddressing) ? LLVMInt32(elementNum) : LLVMInt64(elementNum); offset = BinaryOperator(llvm::Instruction::Mul, size, scale); @@ -2479,7 +2480,7 @@ FunctionEmitContext::LaunchInst(llvm::Value *callee, llvm::Function *falloc = m->module->getFunction("ISPCAlloc"); Assert(falloc != NULL); - llvm::Value *structSize = g->target.SizeOf(argStructType); + llvm::Value *structSize = g->target.SizeOf(argStructType, bblock); if (structSize->getType() != LLVMTypes::Int64Type) // ISPCAlloc expects the size as an uint64_t, but on 32-bit // targets, SizeOf returns a 32-bit value @@ -2575,7 +2576,7 @@ FunctionEmitContext::addVaryingOffsetsIfNeeded(llvm::Value *ptr, // Find the size of a uniform element of the varying type LLVM_TYPE_CONST llvm::Type *llvmBaseUniformType = baseType->GetAsUniformType()->LLVMType(g->ctx); - llvm::Value *unifSize = g->target.SizeOf(llvmBaseUniformType); + llvm::Value *unifSize = g->target.SizeOf(llvmBaseUniformType, bblock); unifSize = SmearUniform(unifSize); // Compute offset = <0, 1, .. > * unifSize diff --git a/expr.cpp b/expr.cpp index af6acd28..af63de9d 100644 --- a/expr.cpp +++ b/expr.cpp @@ -1106,7 +1106,8 @@ lEmitBinaryArith(BinaryExpr::Op op, llvm::Value *value0, llvm::Value *value1, // points to in order to return the difference in elements. LLVM_TYPE_CONST llvm::Type *llvmElementType = ptrType->GetBaseType()->LLVMType(g->ctx); - llvm::Value *size = g->target.SizeOf(llvmElementType); + llvm::Value *size = g->target.SizeOf(llvmElementType, + ctx->GetCurrentBasicBlock()); if (ptrType->IsVaryingType()) size = ctx->SmearUniform(size); @@ -5875,7 +5876,7 @@ SizeOfExpr::GetValue(FunctionEmitContext *ctx) const { if (llvmType == NULL) return NULL; - return g->target.SizeOf(llvmType); + return g->target.SizeOf(llvmType, ctx->GetCurrentBasicBlock()); } diff --git a/ispc.cpp b/ispc.cpp index 8cc618c3..750e7f9e 100644 --- a/ispc.cpp +++ b/ispc.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -358,7 +359,30 @@ Target::GetISAString() const { llvm::Value * -Target::SizeOf(LLVM_TYPE_CONST llvm::Type *type) { +Target::SizeOf(LLVM_TYPE_CONST llvm::Type *type, + llvm::BasicBlock *insertAtEnd) { + if (isa == Target::GENERIC && type->isPrimitiveType() == false) { + llvm::Value *index[1] = { LLVMInt32(1) }; + LLVM_TYPE_CONST llvm::PointerType *ptrType = llvm::PointerType::get(type, 0); + llvm::Value *voidPtr = llvm::ConstantPointerNull::get(ptrType); +#if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn) + llvm::ArrayRef arrayRef(&index[0], &index[1]); + llvm::Instruction *gep = + llvm::GetElementPtrInst::Create(voidPtr, arrayRef, "sizeof_gep", + insertAtEnd); +#else + llvm::Instruction *gep = + llvm::GetElementPtrInst::Create(voidPtr, &index[0], &index[1], + "sizeof_gep", insertAtEnd); +#endif + if (is32Bit || g->opt.force32BitAddressing) + return new llvm::PtrToIntInst(gep, LLVMTypes::Int32Type, + "sizeof_int", insertAtEnd); + else + return new llvm::PtrToIntInst(gep, LLVMTypes::Int64Type, + "sizeof_int", insertAtEnd); + } + const llvm::TargetData *td = GetTargetMachine()->getTargetData(); Assert(td != NULL); uint64_t byteSize = td->getTypeSizeInBits(type) / 8; @@ -370,7 +394,30 @@ Target::SizeOf(LLVM_TYPE_CONST llvm::Type *type) { llvm::Value * -Target::StructOffset(LLVM_TYPE_CONST llvm::Type *type, int element) { +Target::StructOffset(LLVM_TYPE_CONST llvm::Type *type, int element, + llvm::BasicBlock *insertAtEnd) { + if (isa == Target::GENERIC && type->isPrimitiveType() == false) { + llvm::Value *indices[2] = { LLVMInt32(0), LLVMInt32(element) }; + LLVM_TYPE_CONST llvm::PointerType *ptrType = llvm::PointerType::get(type, 0); + llvm::Value *voidPtr = llvm::ConstantPointerNull::get(ptrType); +#if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn) + llvm::ArrayRef arrayRef(&indices[0], &indices[2]); + llvm::Instruction *gep = + llvm::GetElementPtrInst::Create(voidPtr, arrayRef, "offset_gep", + insertAtEnd); +#else + llvm::Instruction *gep = + llvm::GetElementPtrInst::Create(voidPtr, &indices[0], &indices[2], + "offset_gep", insertAtEnd); +#endif + if (is32Bit || g->opt.force32BitAddressing) + return new llvm::PtrToIntInst(gep, LLVMTypes::Int32Type, + "offset_int", insertAtEnd); + else + return new llvm::PtrToIntInst(gep, LLVMTypes::Int64Type, + "offset_int", insertAtEnd); + } + const llvm::TargetData *td = GetTargetMachine()->getTargetData(); Assert(td != NULL); LLVM_TYPE_CONST llvm::StructType *structType = diff --git a/ispc.h b/ispc.h index 254c8311..507d3328 100644 --- a/ispc.h +++ b/ispc.h @@ -177,12 +177,14 @@ struct Target { const char *GetISAString() const; /** Returns the size of the given type */ - llvm::Value *SizeOf(LLVM_TYPE_CONST llvm::Type *type); + llvm::Value *SizeOf(LLVM_TYPE_CONST llvm::Type *type, + llvm::BasicBlock *insertAtEnd); + /** Given a structure type and an element number in the structure, returns a value corresponding to the number of bytes from the start of the structure where the element is located. */ llvm::Value *StructOffset(LLVM_TYPE_CONST llvm::Type *type, - int element); + int element, llvm::BasicBlock *insertAtEnd); /** llvm Target object representing this target. */ const llvm::Target *target;