From: Sean Callanan Date: Thu, 1 Dec 2016 17:46:51 +0000 (+0000) Subject: Handle UTF-16 and UTF-32 constant CFStrings X-Git-Tag: llvmorg-4.0.0-rc1~3254 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cd1eb72bab8539d16d8b5ddb7415d1292d0ce324;p=platform%2Fupstream%2Fllvm.git Handle UTF-16 and UTF-32 constant CFStrings We have a longstanding issue where the expression parser does not handle wide CFStrings (e.g., @"凸凹") correctly, producing the useless error message Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array error: warning: expression result unused error: The expression could not be prepared to run in the target This is just a side effect of the fact that we don't handle wide string constants when converting these to CFStringCreateWithBytes. That function takes the string's encoding as an argument, so I made it work and added a testcase. https://reviews.llvm.org/D27291 llvm-svn: 288386 --- diff --git a/lldb/packages/Python/lldbsuite/test/lang/objc/unicode-string/TestUnicodeString.py b/lldb/packages/Python/lldbsuite/test/lang/objc/unicode-string/TestUnicodeString.py new file mode 100644 index 0000000..c9986aa --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/objc/unicode-string/TestUnicodeString.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest( + __file__, globals(), [ + decorators.skipUnlessDarwin]) diff --git a/lldb/packages/Python/lldbsuite/test/lang/objc/unicode-string/main.m b/lldb/packages/Python/lldbsuite/test/lang/objc/unicode-string/main.m new file mode 100644 index 0000000..e55eb1e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/objc/unicode-string/main.m @@ -0,0 +1,5 @@ +#import + +int main() { + NSLog(@"凸"); //% self.expect("po @\"凹\"", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["凹"]) +} diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index ac6e93c..53c57e9 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -498,42 +498,60 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) : Constant::getNullValue(i8_ptr_ty); Constant *numBytes_arg = ConstantInt::get( - m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false); - Constant *encoding_arg = ConstantInt::get( - i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */ - Constant *isExternal_arg = - ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ - - Value *argument_array[5]; - - argument_array[0] = alloc_arg; - argument_array[1] = bytes_arg; - argument_array[2] = numBytes_arg; - argument_array[3] = encoding_arg; - argument_array[4] = isExternal_arg; - - ArrayRef CFSCWB_arguments(argument_array, 5); - - FunctionValueCache CFSCWB_Caller( - [this, &CFSCWB_arguments](llvm::Function *function) -> llvm::Value * { - return CallInst::Create( - m_CFStringCreateWithBytes, CFSCWB_arguments, - "CFStringCreateWithBytes", - llvm::cast( - m_entry_instruction_finder.GetValue(function))); - }); - - if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, - m_entry_instruction_finder, m_error_stream)) { - if (log) - log->PutCString( - "Couldn't replace the NSString with the result of the call"); - - m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an " - "Objective-C constant string with a dynamic " - "string\n"); - - return false; + m_intptr_ty, cstr ? (string_array->getNumElements() - 1) * string_array->getElementByteSize() : 0, false); + int encoding_flags = 0; + switch (string_array->getElementByteSize()) { + case 1: + encoding_flags = 0x08000100; /* 0x08000100 is kCFStringEncodingUTF8 */ + break; + case 2: + encoding_flags = 0x0100; /* 0x0100 is kCFStringEncodingUTF16 */ + break; + case 4: + encoding_flags = 0x0c000100; /* 0x0c000100 is kCFStringEncodingUTF32 */ + break; + default: + encoding_flags = 0x0600; /* fall back to 0x0600, kCFStringEncodingASCII */ + if (log) { + log->Printf("Encountered an Objective-C constant string with unusual " + "element size %llu", + string_array->getElementByteSize()); + } + } + Constant *encoding_arg = ConstantInt::get(i32_ty, encoding_flags, false); + Constant *isExternal_arg = + ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ + + Value *argument_array[5]; + + argument_array[0] = alloc_arg; + argument_array[1] = bytes_arg; + argument_array[2] = numBytes_arg; + argument_array[3] = encoding_arg; + argument_array[4] = isExternal_arg; + + ArrayRef CFSCWB_arguments(argument_array, 5); + + FunctionValueCache CFSCWB_Caller( + [this, &CFSCWB_arguments](llvm::Function *function) -> llvm::Value * { + return CallInst::Create( + m_CFStringCreateWithBytes, CFSCWB_arguments, + "CFStringCreateWithBytes", + llvm::cast( + m_entry_instruction_finder.GetValue(function))); + }); + + if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, m_entry_instruction_finder, + m_error_stream)) { + if (log) + log->PutCString( + "Couldn't replace the NSString with the result of the call"); + + m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an " + "Objective-C constant string with a dynamic " + "string\n"); + + return false; } ns_str->eraseFromParent(); @@ -642,31 +660,23 @@ bool IRForTarget::RewriteObjCConstStrings() { return false; } - if (nsstring_expr->getOpcode() != Instruction::GetElementPtr) { - if (log) - log->Printf("NSString initializer's str element is not a " - "GetElementPtr expression, it's a %s", - nsstring_expr->getOpcodeName()); - - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " - "constant string's string initializer is not an " - "array\n"); + GlobalVariable *cstr_global = nullptr; - return false; + if (nsstring_expr->getOpcode() == Instruction::GetElementPtr) { + Constant *nsstring_cstr = nsstring_expr->getOperand(0); + cstr_global = dyn_cast(nsstring_cstr); + } else if (nsstring_expr->getOpcode() == Instruction::BitCast) { + Constant *nsstring_cstr = nsstring_expr->getOperand(0); + cstr_global = dyn_cast(nsstring_cstr); } - Constant *nsstring_cstr = nsstring_expr->getOperand(0); - - GlobalVariable *cstr_global = dyn_cast(nsstring_cstr); - if (!cstr_global) { if (log) log->PutCString( "NSString initializer's str element is not a GlobalVariable"); - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " - "constant string's string initializer doesn't " - "point to a global\n"); + m_error_stream.Printf("Internal error [IRForTarget]: Unhandled" + "constant string initializer\n"); return false; }