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 /backend/src/llvm/llvm_printf_parser.cpp | |
parent | 369518b08e58668d8d2b8047dfcca9c4d16d26a6 (diff) |
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>
Diffstat (limited to 'backend/src/llvm/llvm_printf_parser.cpp')
-rw-r--r-- | backend/src/llvm/llvm_printf_parser.cpp | 72 |
1 files changed, 56 insertions, 16 deletions
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; |