forked from OSchip/llvm-project
Hitherto the IRForTarget infrastructure has mainly
been suitable for preparing a single IR function for operation in the target. However, using blocks and lambdas creates other IR functions that also need to be processed. I have audited IRForTarget to make it process multiple functions. Where IRForTarget would add new instructions at the beginning of the main expression function, it now adds them on-demand in the function where they are needed. This is enabled by a system of FunctionValueCaches, which invoke a lambda to create or derive the values as needed, or report the result of that lambda if it has already been called for the given function. <rdar://problem/14180236> llvm-svn: 185224
This commit is contained in:
parent
e9672d0448
commit
1f9db3ebe3
|
@ -18,6 +18,8 @@
|
||||||
#include "lldb/Symbol/TaggedASTType.h"
|
#include "lldb/Symbol/TaggedASTType.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class BasicBlock;
|
class BasicBlock;
|
||||||
class CallInst;
|
class CallInst;
|
||||||
|
@ -235,8 +237,7 @@ private:
|
||||||
/// be determined); false otherwise.
|
/// be determined); false otherwise.
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
ResolveFunctionPointers (llvm::Module &llvm_module,
|
ResolveFunctionPointers (llvm::Module &llvm_module);
|
||||||
llvm::Function &llvm_function);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
/// A function-level pass to take the generated global value
|
/// A function-level pass to take the generated global value
|
||||||
|
@ -307,7 +308,7 @@ private:
|
||||||
CreateResultVariable (llvm::Function &llvm_function);
|
CreateResultVariable (llvm::Function &llvm_function);
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
/// A function-level pass to find Objective-C constant strings and
|
/// A module-level pass to find Objective-C constant strings and
|
||||||
/// transform them to calls to CFStringCreateWithBytes.
|
/// transform them to calls to CFStringCreateWithBytes.
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -321,32 +322,21 @@ private:
|
||||||
/// The constant C string inside the NSString. This will be
|
/// The constant C string inside the NSString. This will be
|
||||||
/// passed as the bytes argument to CFStringCreateWithBytes.
|
/// passed as the bytes argument to CFStringCreateWithBytes.
|
||||||
///
|
///
|
||||||
/// @param[in] FirstEntryInstruction
|
|
||||||
/// An instruction early in the execution of the function.
|
|
||||||
/// When this function synthesizes a call to
|
|
||||||
/// CFStringCreateWithBytes, it places the call before this
|
|
||||||
/// instruction. The instruction should come before all
|
|
||||||
/// uses of the NSString.
|
|
||||||
///
|
|
||||||
/// @return
|
/// @return
|
||||||
/// True on success; false otherwise
|
/// True on success; false otherwise
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
RewriteObjCConstString (llvm::GlobalVariable *NSStr,
|
RewriteObjCConstString (llvm::GlobalVariable *NSStr,
|
||||||
llvm::GlobalVariable *CStr,
|
llvm::GlobalVariable *CStr);
|
||||||
llvm::Instruction *FirstEntryInstruction);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
/// The top-level pass implementation
|
/// The top-level pass implementation
|
||||||
///
|
///
|
||||||
/// @param[in] llvm_function
|
|
||||||
/// The function currently being processed.
|
|
||||||
///
|
|
||||||
/// @return
|
/// @return
|
||||||
/// True on success; false otherwise
|
/// True on success; false otherwise
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
RewriteObjCConstStrings (llvm::Function &llvm_function);
|
RewriteObjCConstStrings ();
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
/// A basic block-level pass to find all Objective-C method calls and
|
/// A basic block-level pass to find all Objective-C method calls and
|
||||||
|
@ -686,10 +676,26 @@ private:
|
||||||
/// @return
|
/// @return
|
||||||
/// True on success; false otherwise
|
/// True on success; false otherwise
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
class FunctionValueCache {
|
||||||
|
public:
|
||||||
|
typedef std::function <llvm::Value *(llvm::Function *)> Maker;
|
||||||
|
|
||||||
|
FunctionValueCache (Maker const &maker);
|
||||||
|
~FunctionValueCache ();
|
||||||
|
llvm::Value *GetValue (llvm::Function *function);
|
||||||
|
private:
|
||||||
|
Maker const m_maker;
|
||||||
|
typedef std::map<llvm::Function *, llvm::Value *> FunctionValueMap;
|
||||||
|
FunctionValueMap m_values;
|
||||||
|
};
|
||||||
|
|
||||||
|
FunctionValueCache m_entry_instruction_finder;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
UnfoldConstant (llvm::Constant *old_constant,
|
UnfoldConstant (llvm::Constant *old_constant,
|
||||||
llvm::Value *new_constant,
|
FunctionValueCache &value_maker,
|
||||||
llvm::Instruction *first_entry_inst);
|
FunctionValueCache &entry_instruction_finder);
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
/// Construct a reference to m_reloc_placeholder with a given type
|
/// Construct a reference to m_reloc_placeholder with a given type
|
||||||
|
|
|
@ -47,6 +47,27 @@ IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionU
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) :
|
||||||
|
m_maker(maker),
|
||||||
|
m_values()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IRForTarget::FunctionValueCache::~FunctionValueCache()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value *IRForTarget::FunctionValueCache::GetValue(llvm::Function *function)
|
||||||
|
{
|
||||||
|
if (!m_values.count(function))
|
||||||
|
{
|
||||||
|
llvm::Value *ret = m_maker(function);
|
||||||
|
m_values[function] = ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return m_values[function];
|
||||||
|
}
|
||||||
|
|
||||||
lldb::addr_t IRForTarget::StaticDataAllocator::Allocate()
|
lldb::addr_t IRForTarget::StaticDataAllocator::Allocate()
|
||||||
{
|
{
|
||||||
lldb_private::Error err;
|
lldb_private::Error err;
|
||||||
|
@ -62,6 +83,14 @@ lldb::addr_t IRForTarget::StaticDataAllocator::Allocate()
|
||||||
return m_allocation;
|
return m_allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static llvm::Value *FindEntryInstruction (llvm::Function *function)
|
||||||
|
{
|
||||||
|
if (function->empty())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return function->getEntryBlock().getFirstNonPHIOrDbg();
|
||||||
|
}
|
||||||
|
|
||||||
IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
|
IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
|
||||||
bool resolve_vars,
|
bool resolve_vars,
|
||||||
lldb_private::IRExecutionUnit &execution_unit,
|
lldb_private::IRExecutionUnit &execution_unit,
|
||||||
|
@ -78,7 +107,8 @@ IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
|
||||||
m_error_stream(error_stream),
|
m_error_stream(error_stream),
|
||||||
m_result_store(NULL),
|
m_result_store(NULL),
|
||||||
m_result_is_pointer(false),
|
m_result_is_pointer(false),
|
||||||
m_reloc_placeholder(NULL)
|
m_reloc_placeholder(NULL),
|
||||||
|
m_entry_instruction_finder (FindEntryInstruction)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,8 +318,7 @@ IRForTarget::RegisterFunctionMetadata(LLVMContext &context,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module,
|
IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module)
|
||||||
llvm::Function &llvm_function)
|
|
||||||
{
|
{
|
||||||
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||||
|
|
||||||
|
@ -675,8 +704,7 @@ static void DebugUsers(Log *log, Value *value, uint8_t depth)
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str,
|
IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str,
|
||||||
llvm::GlobalVariable *cstr,
|
llvm::GlobalVariable *cstr)
|
||||||
Instruction *FirstEntryInstruction)
|
|
||||||
{
|
{
|
||||||
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||||
|
|
||||||
|
@ -767,12 +795,14 @@ IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str,
|
||||||
|
|
||||||
ArrayRef <Value *> CFSCWB_arguments(argument_array, 5);
|
ArrayRef <Value *> CFSCWB_arguments(argument_array, 5);
|
||||||
|
|
||||||
CallInst *CFSCWB_call = CallInst::Create(m_CFStringCreateWithBytes,
|
FunctionValueCache CFSCWB_Caller ([this, &CFSCWB_arguments] (llvm::Function *function)->llvm::Value * {
|
||||||
CFSCWB_arguments,
|
return CallInst::Create(m_CFStringCreateWithBytes,
|
||||||
"CFStringCreateWithBytes",
|
CFSCWB_arguments,
|
||||||
FirstEntryInstruction);
|
"CFStringCreateWithBytes",
|
||||||
|
llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function)));
|
||||||
|
});
|
||||||
|
|
||||||
if (!UnfoldConstant(ns_str, CFSCWB_call, FirstEntryInstruction))
|
if (!UnfoldConstant(ns_str, CFSCWB_Caller, m_entry_instruction_finder))
|
||||||
{
|
{
|
||||||
if (log)
|
if (log)
|
||||||
log->PutCString("Couldn't replace the NSString with the result of the call");
|
log->PutCString("Couldn't replace the NSString with the result of the call");
|
||||||
|
@ -789,26 +819,12 @@ IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IRForTarget::RewriteObjCConstStrings(Function &llvm_function)
|
IRForTarget::RewriteObjCConstStrings()
|
||||||
{
|
{
|
||||||
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||||
|
|
||||||
ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable();
|
ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable();
|
||||||
|
|
||||||
BasicBlock &entry_block(llvm_function.getEntryBlock());
|
|
||||||
Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg());
|
|
||||||
|
|
||||||
if (!FirstEntryInstruction)
|
|
||||||
{
|
|
||||||
if (log)
|
|
||||||
log->PutCString("Couldn't find first instruction for rewritten Objective-C strings");
|
|
||||||
|
|
||||||
if (m_error_stream)
|
|
||||||
m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find the location for calls to CFStringCreateWithBytes\n");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
|
for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
|
||||||
vi != ve;
|
vi != ve;
|
||||||
++vi)
|
++vi)
|
||||||
|
@ -977,7 +993,7 @@ IRForTarget::RewriteObjCConstStrings(Function &llvm_function)
|
||||||
if (!cstr_array)
|
if (!cstr_array)
|
||||||
cstr_global = NULL;
|
cstr_global = NULL;
|
||||||
|
|
||||||
if (!RewriteObjCConstString(nsstring_global, cstr_global, FirstEntryInstruction))
|
if (!RewriteObjCConstString(nsstring_global, cstr_global))
|
||||||
{
|
{
|
||||||
if (log)
|
if (log)
|
||||||
log->PutCString("Error rewriting the constant string");
|
log->PutCString("Error rewriting the constant string");
|
||||||
|
@ -2151,7 +2167,9 @@ IRForTarget::RemoveGuards(BasicBlock &basic_block)
|
||||||
|
|
||||||
// This function does not report errors; its callers are responsible.
|
// This function does not report errors; its callers are responsible.
|
||||||
bool
|
bool
|
||||||
IRForTarget::UnfoldConstant(Constant *old_constant, Value *new_constant, Instruction *first_entry_inst)
|
IRForTarget::UnfoldConstant(Constant *old_constant,
|
||||||
|
FunctionValueCache &value_maker,
|
||||||
|
FunctionValueCache &entry_instruction_finder)
|
||||||
{
|
{
|
||||||
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||||
|
|
||||||
|
@ -2186,17 +2204,20 @@ IRForTarget::UnfoldConstant(Constant *old_constant, Value *new_constant, Instruc
|
||||||
return false;
|
return false;
|
||||||
case Instruction::BitCast:
|
case Instruction::BitCast:
|
||||||
{
|
{
|
||||||
// UnaryExpr
|
FunctionValueCache bit_cast_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* {
|
||||||
// OperandList[0] is value
|
// UnaryExpr
|
||||||
|
// OperandList[0] is value
|
||||||
|
|
||||||
Value *s = constant_expr->getOperand(0);
|
if (constant_expr->getOperand(0) != old_constant)
|
||||||
|
return constant_expr;
|
||||||
|
|
||||||
if (s == old_constant)
|
return new BitCastInst(value_maker.GetValue(function),
|
||||||
s = new_constant;
|
constant_expr->getType(),
|
||||||
|
"",
|
||||||
|
llvm::cast<Instruction>(entry_instruction_finder.GetValue(function)));
|
||||||
|
});
|
||||||
|
|
||||||
BitCastInst *bit_cast(new BitCastInst(s, constant_expr->getType(), "", first_entry_inst));
|
return UnfoldConstant(constant_expr, bit_cast_maker, entry_instruction_finder);
|
||||||
|
|
||||||
UnfoldConstant(constant_expr, bit_cast, first_entry_inst);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Instruction::GetElementPtr:
|
case Instruction::GetElementPtr:
|
||||||
|
@ -2205,33 +2226,35 @@ IRForTarget::UnfoldConstant(Constant *old_constant, Value *new_constant, Instruc
|
||||||
// OperandList[0] is base
|
// OperandList[0] is base
|
||||||
// OperandList[1]... are indices
|
// OperandList[1]... are indices
|
||||||
|
|
||||||
Value *ptr = constant_expr->getOperand(0);
|
FunctionValueCache get_element_pointer_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* {
|
||||||
|
Value *ptr = constant_expr->getOperand(0);
|
||||||
|
|
||||||
if (ptr == old_constant)
|
if (ptr == old_constant)
|
||||||
ptr = new_constant;
|
ptr = value_maker.GetValue(function);
|
||||||
|
|
||||||
std::vector<Value*> index_vector;
|
std::vector<Value*> index_vector;
|
||||||
|
|
||||||
unsigned operand_index;
|
unsigned operand_index;
|
||||||
unsigned num_operands = constant_expr->getNumOperands();
|
unsigned num_operands = constant_expr->getNumOperands();
|
||||||
|
|
||||||
for (operand_index = 1;
|
for (operand_index = 1;
|
||||||
operand_index < num_operands;
|
operand_index < num_operands;
|
||||||
++operand_index)
|
++operand_index)
|
||||||
{
|
{
|
||||||
Value *operand = constant_expr->getOperand(operand_index);
|
Value *operand = constant_expr->getOperand(operand_index);
|
||||||
|
|
||||||
if (operand == old_constant)
|
if (operand == old_constant)
|
||||||
operand = new_constant;
|
operand = value_maker.GetValue(function);
|
||||||
|
|
||||||
index_vector.push_back(operand);
|
index_vector.push_back(operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef <Value*> indices(index_vector);
|
ArrayRef <Value*> indices(index_vector);
|
||||||
|
|
||||||
GetElementPtrInst *get_element_ptr(GetElementPtrInst::Create(ptr, indices, "", first_entry_inst));
|
return GetElementPtrInst::Create(ptr, indices, "", llvm::cast<Instruction>(entry_instruction_finder.GetValue(function)));
|
||||||
|
});
|
||||||
|
|
||||||
UnfoldConstant(constant_expr, get_element_ptr, first_entry_inst);
|
return UnfoldConstant(constant_expr, get_element_pointer_maker, entry_instruction_finder);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2245,8 +2268,16 @@ IRForTarget::UnfoldConstant(Constant *old_constant, Value *new_constant, Instruc
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// simple fall-through case for non-constants
|
if (Instruction *inst = llvm::dyn_cast<Instruction>(user))
|
||||||
user->replaceUsesOfWith(old_constant, new_constant);
|
{
|
||||||
|
inst->replaceUsesOfWith(old_constant, value_maker.GetValue(inst->getParent()->getParent()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (log)
|
||||||
|
log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(user).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2388,38 +2419,57 @@ IRForTarget::ReplaceVariables (Function &llvm_function)
|
||||||
decl->getNameAsString().c_str(),
|
decl->getNameAsString().c_str(),
|
||||||
offset);
|
offset);
|
||||||
|
|
||||||
ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true));
|
|
||||||
GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(argument, offset_int, "", FirstEntryInstruction);
|
|
||||||
|
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
Value *replacement = NULL;
|
|
||||||
|
|
||||||
if (log)
|
if (log)
|
||||||
log->Printf(" Replacing [%s]", PrintValue(value).c_str());
|
log->Printf(" Replacing [%s]", PrintValue(value).c_str());
|
||||||
|
|
||||||
// Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result
|
FunctionValueCache body_result_maker ([this, name, offset_type, offset, argument, value] (llvm::Function *function)->llvm::Value * {
|
||||||
// variable is an rvalue, we have to synthesize a dereference of the appropriate structure
|
// Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result
|
||||||
// entry in order to produce the static variable that the AST thinks it is accessing.
|
// variable is an rvalue, we have to synthesize a dereference of the appropriate structure
|
||||||
if (name == m_result_name && !m_result_is_pointer)
|
// entry in order to produce the static variable that the AST thinks it is accessing.
|
||||||
{
|
|
||||||
BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType()->getPointerTo(), "", FirstEntryInstruction);
|
|
||||||
|
|
||||||
LoadInst *load = new LoadInst(bit_cast, "", FirstEntryInstruction);
|
llvm::Instruction *entry_instruction = llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function));
|
||||||
|
|
||||||
replacement = load;
|
ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true));
|
||||||
}
|
GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(argument,
|
||||||
else
|
offset_int,
|
||||||
{
|
"",
|
||||||
BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", FirstEntryInstruction);
|
entry_instruction);
|
||||||
|
|
||||||
replacement = bit_cast;
|
if (name == m_result_name && !m_result_is_pointer)
|
||||||
}
|
{
|
||||||
|
BitCastInst *bit_cast = new BitCastInst(get_element_ptr,
|
||||||
|
value->getType()->getPointerTo(),
|
||||||
|
"",
|
||||||
|
entry_instruction);
|
||||||
|
|
||||||
|
LoadInst *load = new LoadInst(bit_cast, "", entry_instruction);
|
||||||
|
|
||||||
|
return load;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", entry_instruction);
|
||||||
|
|
||||||
|
return bit_cast;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (Constant *constant = dyn_cast<Constant>(value))
|
if (Constant *constant = dyn_cast<Constant>(value))
|
||||||
UnfoldConstant(constant, replacement, FirstEntryInstruction);
|
{
|
||||||
|
UnfoldConstant(constant, body_result_maker, m_entry_instruction_finder);
|
||||||
|
}
|
||||||
|
else if (Instruction *instruction = dyn_cast<Instruction>(value))
|
||||||
|
{
|
||||||
|
value->replaceAllUsesWith(body_result_maker.GetValue(instruction->getParent()->getParent()));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
value->replaceAllUsesWith(replacement);
|
{
|
||||||
|
if (log)
|
||||||
|
log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(value).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
|
if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
|
||||||
var->eraseFromParent();
|
var->eraseFromParent();
|
||||||
|
@ -2544,27 +2594,6 @@ IRForTarget::runOnModule (Module &llvm_module)
|
||||||
m_module = &llvm_module;
|
m_module = &llvm_module;
|
||||||
m_target_data.reset(new DataLayout(m_module));
|
m_target_data.reset(new DataLayout(m_module));
|
||||||
|
|
||||||
Function* function = m_module->getFunction(StringRef(m_func_name.c_str()));
|
|
||||||
|
|
||||||
if (!function)
|
|
||||||
{
|
|
||||||
if (log)
|
|
||||||
log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str());
|
|
||||||
|
|
||||||
if (m_error_stream)
|
|
||||||
m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!FixFunctionLinkage (*function))
|
|
||||||
{
|
|
||||||
if (log)
|
|
||||||
log->Printf("Couldn't fix the linkage for the function");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (log)
|
if (log)
|
||||||
{
|
{
|
||||||
std::string s;
|
std::string s;
|
||||||
|
@ -2577,6 +2606,27 @@ IRForTarget::runOnModule (Module &llvm_module)
|
||||||
log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str());
|
log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Function* main_function = m_module->getFunction(StringRef(m_func_name.c_str()));
|
||||||
|
|
||||||
|
if (!main_function)
|
||||||
|
{
|
||||||
|
if (log)
|
||||||
|
log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str());
|
||||||
|
|
||||||
|
if (m_error_stream)
|
||||||
|
m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FixFunctionLinkage (*main_function))
|
||||||
|
{
|
||||||
|
if (log)
|
||||||
|
log->Printf("Couldn't fix the linkage for the function");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
llvm::Type *intptr_ty = Type::getInt8Ty(m_module->getContext());
|
llvm::Type *intptr_ty = Type::getInt8Ty(m_module->getContext());
|
||||||
|
|
||||||
m_reloc_placeholder = new llvm::GlobalVariable((*m_module),
|
m_reloc_placeholder = new llvm::GlobalVariable((*m_module),
|
||||||
|
@ -2589,13 +2639,11 @@ IRForTarget::runOnModule (Module &llvm_module)
|
||||||
GlobalVariable::NotThreadLocal /* ThreadLocal */,
|
GlobalVariable::NotThreadLocal /* ThreadLocal */,
|
||||||
0 /* AddressSpace */);
|
0 /* AddressSpace */);
|
||||||
|
|
||||||
Function::iterator bbi;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Replace $__lldb_expr_result with a persistent variable
|
// Replace $__lldb_expr_result with a persistent variable
|
||||||
//
|
//
|
||||||
|
|
||||||
if (!CreateResultVariable(*function))
|
if (!CreateResultVariable(*main_function))
|
||||||
{
|
{
|
||||||
if (log)
|
if (log)
|
||||||
log->Printf("CreateResultVariable() failed");
|
log->Printf("CreateResultVariable() failed");
|
||||||
|
@ -2605,41 +2653,6 @@ IRForTarget::runOnModule (Module &llvm_module)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bbi = function->begin();
|
|
||||||
bbi != function->end();
|
|
||||||
++bbi)
|
|
||||||
{
|
|
||||||
if (!RemoveGuards(*bbi))
|
|
||||||
{
|
|
||||||
if (log)
|
|
||||||
log->Printf("RemoveGuards() failed");
|
|
||||||
|
|
||||||
// RemoveGuards() reports its own errors, so we don't do so here
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RewritePersistentAllocs(*bbi))
|
|
||||||
{
|
|
||||||
if (log)
|
|
||||||
log->Printf("RewritePersistentAllocs() failed");
|
|
||||||
|
|
||||||
// RewritePersistentAllocs() reports its own errors, so we don't do so here
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RemoveCXAAtExit(*bbi))
|
|
||||||
{
|
|
||||||
if (log)
|
|
||||||
log->Printf("RemoveCXAAtExit() failed");
|
|
||||||
|
|
||||||
// RemoveCXAAtExit() reports its own errors, so we don't do so here
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (log && log->GetVerbose())
|
if (log && log->GetVerbose())
|
||||||
{
|
{
|
||||||
std::string s;
|
std::string s;
|
||||||
|
@ -2652,11 +2665,58 @@ IRForTarget::runOnModule (Module &llvm_module)
|
||||||
log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str());
|
log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Module::iterator fi = m_module->begin(), fe = m_module->end();
|
||||||
|
fi != fe;
|
||||||
|
++fi)
|
||||||
|
{
|
||||||
|
llvm::Function *function = fi;
|
||||||
|
|
||||||
|
if (function->begin() == function->end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Function::iterator bbi;
|
||||||
|
|
||||||
|
for (bbi = function->begin();
|
||||||
|
bbi != function->end();
|
||||||
|
++bbi)
|
||||||
|
{
|
||||||
|
if (!RemoveGuards(*bbi))
|
||||||
|
{
|
||||||
|
if (log)
|
||||||
|
log->Printf("RemoveGuards() failed");
|
||||||
|
|
||||||
|
// RemoveGuards() reports its own errors, so we don't do so here
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RewritePersistentAllocs(*bbi))
|
||||||
|
{
|
||||||
|
if (log)
|
||||||
|
log->Printf("RewritePersistentAllocs() failed");
|
||||||
|
|
||||||
|
// RewritePersistentAllocs() reports its own errors, so we don't do so here
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RemoveCXAAtExit(*bbi))
|
||||||
|
{
|
||||||
|
if (log)
|
||||||
|
log->Printf("RemoveCXAAtExit() failed");
|
||||||
|
|
||||||
|
// RemoveCXAAtExit() reports its own errors, so we don't do so here
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Fix all Objective-C constant strings to use NSStringWithCString:encoding:
|
// Fix all Objective-C constant strings to use NSStringWithCString:encoding:
|
||||||
//
|
//
|
||||||
|
|
||||||
if (!RewriteObjCConstStrings(*function))
|
if (!RewriteObjCConstStrings())
|
||||||
{
|
{
|
||||||
if (log)
|
if (log)
|
||||||
log->Printf("RewriteObjCConstStrings() failed");
|
log->Printf("RewriteObjCConstStrings() failed");
|
||||||
|
@ -2670,7 +2730,7 @@ IRForTarget::runOnModule (Module &llvm_module)
|
||||||
// Resolve function pointers
|
// Resolve function pointers
|
||||||
//
|
//
|
||||||
|
|
||||||
if (!ResolveFunctionPointers(llvm_module, *function))
|
if (!ResolveFunctionPointers(llvm_module))
|
||||||
{
|
{
|
||||||
if (log)
|
if (log)
|
||||||
log->Printf("ResolveFunctionPointers() failed");
|
log->Printf("ResolveFunctionPointers() failed");
|
||||||
|
@ -2680,49 +2740,63 @@ IRForTarget::runOnModule (Module &llvm_module)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bbi = function->begin();
|
for (Module::iterator fi = m_module->begin(), fe = m_module->end();
|
||||||
bbi != function->end();
|
fi != fe;
|
||||||
++bbi)
|
++fi)
|
||||||
{
|
{
|
||||||
if (!RewriteObjCSelectors(*bbi))
|
llvm::Function *function = fi;
|
||||||
|
|
||||||
|
for (llvm::Function::iterator bbi = function->begin(), bbe = function->end();
|
||||||
|
bbi != bbe;
|
||||||
|
++bbi)
|
||||||
{
|
{
|
||||||
if (log)
|
if (!RewriteObjCSelectors(*bbi))
|
||||||
log->Printf("RewriteObjCSelectors() failed");
|
{
|
||||||
|
if (log)
|
||||||
|
log->Printf("RewriteObjCSelectors() failed");
|
||||||
|
|
||||||
// RewriteObjCSelectors() reports its own errors, so we don't do so here
|
// RewriteObjCSelectors() reports its own errors, so we don't do so here
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bbi = function->begin();
|
for (Module::iterator fi = m_module->begin(), fe = m_module->end();
|
||||||
bbi != function->end();
|
fi != fe;
|
||||||
++bbi)
|
++fi)
|
||||||
{
|
{
|
||||||
if (!ResolveCalls(*bbi))
|
llvm::Function *function = fi;
|
||||||
|
|
||||||
|
for (llvm::Function::iterator bbi = function->begin(), bbe = function->end();
|
||||||
|
bbi != bbe;
|
||||||
|
++bbi)
|
||||||
{
|
{
|
||||||
if (log)
|
if (!ResolveCalls(*bbi))
|
||||||
log->Printf("ResolveCalls() failed");
|
{
|
||||||
|
if (log)
|
||||||
|
log->Printf("ResolveCalls() failed");
|
||||||
|
|
||||||
// ResolveCalls() reports its own errors, so we don't do so here
|
// ResolveCalls() reports its own errors, so we don't do so here
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReplaceStaticLiterals(*bbi))
|
if (!ReplaceStaticLiterals(*bbi))
|
||||||
{
|
{
|
||||||
if (log)
|
if (log)
|
||||||
log->Printf("ReplaceStaticLiterals() failed");
|
log->Printf("ReplaceStaticLiterals() failed");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Run function-level passes
|
// Run function-level passes that only make sense on the main function
|
||||||
//
|
//
|
||||||
|
|
||||||
if (!ResolveExternals(*function))
|
if (!ResolveExternals(*main_function))
|
||||||
{
|
{
|
||||||
if (log)
|
if (log)
|
||||||
log->Printf("ResolveExternals() failed");
|
log->Printf("ResolveExternals() failed");
|
||||||
|
@ -2732,7 +2806,7 @@ IRForTarget::runOnModule (Module &llvm_module)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReplaceVariables(*function))
|
if (!ReplaceVariables(*main_function))
|
||||||
{
|
{
|
||||||
if (log)
|
if (log)
|
||||||
log->Printf("ReplaceVariables() failed");
|
log->Printf("ReplaceVariables() failed");
|
||||||
|
|
Loading…
Reference in New Issue