diff options
author | Junyan He <junyan.he@linux.intel.com> | 2014-06-20 17:41:13 +0800 |
---|---|---|
committer | Zhigang Gong <zhigang.gong@intel.com> | 2014-06-23 10:33:44 +0800 |
commit | aed86199bded8478070010386aea321b865e21a8 (patch) | |
tree | 33c8497c60867313dec7da2f40e8232ee4f4ebfb | |
parent | 369518b08e58668d8d2b8047dfcca9c4d16d26a6 (diff) | |
download | beignet-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.cpp | 69 | ||||
-rw-r--r-- | backend/src/ir/printf.hpp | 5 | ||||
-rw-r--r-- | backend/src/llvm/llvm_printf_parser.cpp | 72 |
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; |