summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunyan He <junyan.he@linux.intel.com>2014-06-20 17:41:13 +0800
committerZhigang Gong <zhigang.gong@intel.com>2014-06-23 10:33:44 +0800
commitaed86199bded8478070010386aea321b865e21a8 (patch)
tree33c8497c60867313dec7da2f40e8232ee4f4ebfb
parent369518b08e58668d8d2b8047dfcca9c4d16d26a6 (diff)
downloadbeignet-aed86199bded8478070010386aea321b865e21a8.tar.gz
Add %f and %c support for printf.
Add the %c and %f support for printf. Also add the int to float and int to char conversion. Some minor errors such as wrong index flags have been fixed. Signed-off-by: Junyan He <junyan.he@linux.intel.com> Reviewed-by: Yang Rong <rong.r.yang@intel.com>
-rw-r--r--backend/src/ir/printf.cpp69
-rw-r--r--backend/src/ir/printf.hpp5
-rw-r--r--backend/src/llvm/llvm_printf_parser.cpp72
3 files changed, 94 insertions, 52 deletions
diff --git a/backend/src/ir/printf.cpp b/backend/src/ir/printf.cpp
index 0a943ac1..d59b990b 100644
--- a/backend/src/ir/printf.cpp
+++ b/backend/src/ir/printf.cpp
@@ -17,18 +17,18 @@
*/
/**
- * \file sampler.cpp
+ * \file printf.cpp
*
*/
#include <stdarg.h>
#include "printf.hpp"
-#include "ocl_common_defines.h"
namespace gbe
{
namespace ir
{
+
pthread_mutex_t PrintfSet::lock = PTHREAD_MUTEX_INITIALIZER;
uint32_t PrintfSet::append(PrintfFmt* fmt, Unit& unit)
@@ -43,35 +43,21 @@ namespace gbe
}
/* Update the total size of size. */
- sizeOfSize = slots.back()->state->out_buf_sizeof_offset
- + getPrintfBufferElementSize(slots.size() - 1);
+ if (slots.size() > 0)
+ sizeOfSize = slots.back()->state->out_buf_sizeof_offset
+ + getPrintfBufferElementSize(slots.size() - 1);
return (uint32_t)fmts.size();
}
- /* ugly here. We can not build the va_list dynamically:(
- And I have tried
- va_list arg; arg = some_ptr;
- This works very OK on 32bits platform but can not even
- pass the compiling in the 64bits platform.
- sizeof(arg) = 4 in 32bits platform but
- sizeof(arg) = 24 in 64bits platform.
- We can not assume the platform here. */
- void vfprintf_wrap(std::string& fmt, vector<int>& contents)
- {
- int* ptr = NULL;
- size_t num = contents.size() < 32 ? contents.size() : 32;
- ptr = (int *)calloc(32, sizeof(int)); //should be enough
- for (size_t i = 0; i < num; i++) {
- ptr[i] = contents[i];
- }
-
- printf(fmt.c_str(), ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7],
- ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], ptr[16],
- ptr[17], ptr[18], ptr[19], ptr[20], ptr[21], ptr[22], ptr[23], ptr[24], ptr[25],
- ptr[26], ptr[27], ptr[28], ptr[29], ptr[30], ptr[31]);
- free(ptr);
- }
+#define PRINT_SOMETHING(target_ty, conv) do { \
+ pf_str = pf_str + std::string(#conv); \
+ printf(pf_str.c_str(), \
+ ((target_ty *)((char *)buf_addr + slot.state->out_buf_sizeof_offset * \
+ global_wk_sz0 * global_wk_sz1 * global_wk_sz2)) \
+ [k*global_wk_sz0*global_wk_sz1 + j*global_wk_sz0 + i]); \
+ pf_str = ""; \
+ } while (0)
void PrintfSet::outputPrintf(void* index_addr, void* buf_addr, size_t global_wk_sz0,
size_t global_wk_sz1, size_t global_wk_sz2)
@@ -79,15 +65,15 @@ namespace gbe
LockOutput lock;
size_t i, j, k;
std::string pf_str;
- vector<int>* contents = NULL;
+ int stmt = 0;
+
for (auto &pf : fmts) {
for (i = 0; i < global_wk_sz0; i++) {
for (j = 0; j < global_wk_sz1; j++) {
for (k = 0; k < global_wk_sz2; k++) {
- int flag = ((int *)index_addr)[k*global_wk_sz0*global_wk_sz1 + j*global_wk_sz0 + i];
+ int flag = ((int *)index_addr)[stmt*global_wk_sz0*global_wk_sz1*global_wk_sz2 + k*global_wk_sz0*global_wk_sz1 + j*global_wk_sz0 + i];
if (flag) {
pf_str = "";
- contents = new vector<int>();
for (auto &slot : pf) {
if (slot.type == PRINTF_SLOT_TYPE_STRING) {
pf_str = pf_str + std::string(slot.str);
@@ -98,23 +84,34 @@ namespace gbe
switch (slot.state->conversion_specifier) {
case PRINTF_CONVERSION_D:
case PRINTF_CONVERSION_I:
- contents->push_back(((int *)((char *)buf_addr + slot.state->out_buf_sizeof_offset
- * global_wk_sz0 * global_wk_sz1 * global_wk_sz2))
- [k*global_wk_sz0*global_wk_sz1 + j*global_wk_sz0 + i]);
- pf_str = pf_str + std::string("%d");
+ PRINT_SOMETHING(int, %d);
break;
+ case PRINTF_CONVERSION_C:
+ PRINT_SOMETHING(char, %c);
+ break;
+
+ case PRINTF_CONVERSION_F:
+ case PRINTF_CONVERSION_f:
+ if (slot.state->conversion_specifier == PRINTF_CONVERSION_F)
+ PRINT_SOMETHING(float, %F);
+ else
+ PRINT_SOMETHING(float, %f);
+ break;
+
default:
assert(0);
return;
}
}
- vfprintf_wrap(pf_str, *contents);
- delete contents;
+ if (pf_str != "") {
+ printf("%s", pf_str.c_str());
+ }
}
}
}
}
+ stmt++;
}
}
} /* namespace ir */
diff --git a/backend/src/ir/printf.hpp b/backend/src/ir/printf.hpp
index b49ad0da..18452238 100644
--- a/backend/src/ir/printf.hpp
+++ b/backend/src/ir/printf.hpp
@@ -196,7 +196,12 @@ namespace gbe
switch (slot->state->conversion_specifier) {
case PRINTF_CONVERSION_I:
case PRINTF_CONVERSION_D:
+ /* Char will be aligned to sizeof(int) here. */
+ case PRINTF_CONVERSION_C:
return (uint32_t)sizeof(int);
+ case PRINTF_CONVERSION_F:
+ case PRINTF_CONVERSION_f:
+ return (uint32_t)sizeof(float);
default:
break;
}
diff --git a/backend/src/llvm/llvm_printf_parser.cpp b/backend/src/llvm/llvm_printf_parser.cpp
index a40a7a40..1b72e82b 100644
--- a/backend/src/llvm/llvm_printf_parser.cpp
+++ b/backend/src/llvm/llvm_printf_parser.cpp
@@ -224,7 +224,7 @@ namespace gbe
CONVERSION_SPEC_AND_RET('s', A)
CONVERSION_SPEC_AND_RET('p', P)
- // %% has been handled
+ // %% has been handled
default:
return -1;
@@ -328,8 +328,7 @@ error:
static map<CallInst*, PrintfSet::PrintfFmt*> printfs;
int printf_num;
- PrintfParser(void) : FunctionPass(ID)
- {
+ PrintfParser(void) : FunctionPass(ID) {
module = NULL;
builder = NULL;
intTy = NULL;
@@ -340,8 +339,7 @@ error:
printf_num = 0;
}
- ~PrintfParser(void)
- {
+ ~PrintfParser(void) {
for (auto &s : printfs) {
delete s.second;
s.second = NULL;
@@ -351,10 +349,9 @@ error:
bool parseOnePrintfInstruction(CallInst *& call);
- int generateOneParameterInst(PrintfSlot& slot, Value& arg);
+ int generateOneParameterInst(PrintfSlot& slot, Value*& arg, Type*& dst_type);
- virtual const char *getPassName() const
- {
+ virtual const char *getPassName() const {
return "Printf Parser";
}
@@ -473,13 +470,17 @@ error:
assert(i < static_cast<int>(call->getNumOperands()) - 1);
- int sizeof_size = generateOneParameterInst(s, *call->getOperand(i));
+ Value *out_arg = call->getOperand(i);
+ Type *dst_type = NULL;
+ int sizeof_size = generateOneParameterInst(s, out_arg, dst_type);
if (!sizeof_size) {
printf("Printf: %d, parameter %d may have no result because some error\n",
printf_num, i - 1);
continue;
}
+ assert(dst_type);
+
/////////////////////////////////////////////////////
/* Calculate the data address.
data_addr = data_offset + pbuf_ptr + offset * sizeof(specify)
@@ -492,10 +493,10 @@ error:
//data_offset + pbuf_ptr
op0 = builder->CreateAdd(op0, pbuf_ptr);
op0 = builder->CreateAdd(op0, val);
- data_addr = builder->CreateIntToPtr(op0, Type::getInt32PtrTy(module->getContext(), 1));
- builder->CreateStore(call->getOperand(i), data_addr);
+ data_addr = builder->CreateIntToPtr(op0, dst_type);
+ builder->CreateStore(out_arg, data_addr);
s.state->out_buf_sizeof_offset = out_buf_sizeof_offset;
- out_buf_sizeof_offset += sizeof_size;
+ out_buf_sizeof_offset += ((sizeof_size + 3) / 4) * 4;
i++;
}
@@ -604,27 +605,66 @@ error:
return changed;
}
- int PrintfParser::generateOneParameterInst(PrintfSlot& slot, Value& arg)
+ int PrintfParser::generateOneParameterInst(PrintfSlot& slot, Value*& arg, Type*& dst_type)
{
assert(slot.type == PRINTF_SLOT_TYPE_STATE);
assert(builder);
/* Check whether the arg match the format specifer. If needed, some
conversion need to be applied. */
- switch (arg.getType()->getTypeID()) {
+ switch (arg->getType()->getTypeID()) {
case Type::IntegerTyID: {
switch (slot.state->conversion_specifier) {
case PRINTF_CONVERSION_I:
case PRINTF_CONVERSION_D:
/* Int to Int, just store. */
+ dst_type = Type::getInt32PtrTy(module->getContext(), 1);
return sizeof(int);
- break;
+
+ case PRINTF_CONVERSION_C:
+ /* Int to Char, add a conversion. */
+ arg = builder->CreateIntCast(arg, Type::getInt8Ty(module->getContext()), false);
+ dst_type = Type::getInt8PtrTy(module->getContext(), 1);
+ return sizeof(char);
+
+ case PRINTF_CONVERSION_F:
+ case PRINTF_CONVERSION_f:
+ arg = builder->CreateSIToFP(arg, Type::getFloatTy(module->getContext()));
+ dst_type = Type::getFloatPtrTy(module->getContext(), 1);
+ return sizeof(float);
default:
return 0;
}
+
+ break;
+ }
+
+ case Type::DoubleTyID:
+ case Type::FloatTyID: {
+ /* Because the printf is a variable parameter function, it does not have the
+ function prototype, so the compiler will always promote the arg to the
+ longest precise type for float. So here, we can always find it is double. */
+ switch (slot.state->conversion_specifier) {
+ case PRINTF_CONVERSION_I:
+ case PRINTF_CONVERSION_D:
+ /* Float to Int, add a conversion. */
+ arg = builder->CreateFPToSI(arg, Type::getInt32Ty(module->getContext()));
+ dst_type = Type::getInt32PtrTy(module->getContext(), 1);
+ return sizeof(int);
+
+ case PRINTF_CONVERSION_F:
+ case PRINTF_CONVERSION_f:
+ arg = builder->CreateFPCast(arg, Type::getFloatTy(module->getContext()));
+ dst_type = Type::getFloatPtrTy(module->getContext(), 1);
+ return sizeof(float);
+
+ default:
+ return 0;
+ }
+
+ break;
}
- break;
default:
return 0;