2010-07-03 09:35:46 +08:00
|
|
|
//===-- IRForTarget.cpp -------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "lldb/Expression/IRForTarget.h"
|
|
|
|
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "llvm/InstrTypes.h"
|
2010-07-14 05:41:46 +08:00
|
|
|
#include "llvm/Instructions.h"
|
2010-09-29 07:55:00 +08:00
|
|
|
#include "llvm/Intrinsics.h"
|
2010-07-03 09:35:46 +08:00
|
|
|
#include "llvm/Module.h"
|
2010-07-14 05:41:46 +08:00
|
|
|
#include "llvm/Target/TargetData.h"
|
2010-08-12 09:56:52 +08:00
|
|
|
#include "llvm/ValueSymbolTable.h"
|
2010-07-14 05:41:46 +08:00
|
|
|
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2010-07-03 09:35:46 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
#include "lldb/Core/ConstString.h"
|
2010-07-03 09:35:46 +08:00
|
|
|
#include "lldb/Core/dwarf.h"
|
|
|
|
#include "lldb/Core/Log.h"
|
|
|
|
#include "lldb/Core/Scalar.h"
|
|
|
|
#include "lldb/Core/StreamString.h"
|
|
|
|
#include "lldb/Expression/ClangExpressionDeclMap.h"
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2010-08-19 02:50:51 +08:00
|
|
|
static char ID;
|
|
|
|
|
|
|
|
IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
|
2010-09-14 05:34:21 +08:00
|
|
|
bool resolve_vars,
|
This is a major refactoring of the expression parser.
The goal is to separate the parser's data from the data
belonging to the parser's clients. This allows clients
to use the parser to obtain (for example) a JIT compiled
function or some DWARF code, and then discard the parser
state.
Previously, parser state was held in ClangExpression and
used liberally by ClangFunction, which inherited from
ClangExpression. The main effects of this refactoring
are:
- reducing ClangExpression to an abstract class that
declares methods that any client must expose to the
expression parser,
- moving the code specific to implementing the "expr"
command from ClangExpression and
CommandObjectExpression into ClangUserExpression,
a new class,
- moving the common parser interaction code from
ClangExpression into ClangExpressionParser, a new
class, and
- making ClangFunction rely only on
ClangExpressionParser and not depend on the
internal implementation of ClangExpression.
Side effects include:
- the compiler interaction code has been factored
out of ClangFunction and is now in an AST pass
(ASTStructExtractor),
- the header file for ClangFunction is now fully
documented,
- several bugs that only popped up when Clang was
deallocated (which never happened, since the
lifetime of the compiler was essentially infinite)
are now fixed, and
- the developer-only "call" command has been
disabled.
I have tested the expr command and the Objective-C
step-into code, which use ClangUserExpression and
ClangFunction, respectively, and verified that they
work. Please let me know if you encounter bugs or
poor documentation.
llvm-svn: 112249
2010-08-27 09:01:44 +08:00
|
|
|
const char *func_name) :
|
2010-09-23 11:01:22 +08:00
|
|
|
ModulePass(ID),
|
2010-07-14 05:41:46 +08:00
|
|
|
m_decl_map(decl_map),
|
2010-11-18 07:00:36 +08:00
|
|
|
m_CFStringCreateWithBytes(NULL),
|
This is a major refactoring of the expression parser.
The goal is to separate the parser's data from the data
belonging to the parser's clients. This allows clients
to use the parser to obtain (for example) a JIT compiled
function or some DWARF code, and then discard the parser
state.
Previously, parser state was held in ClangExpression and
used liberally by ClangFunction, which inherited from
ClangExpression. The main effects of this refactoring
are:
- reducing ClangExpression to an abstract class that
declares methods that any client must expose to the
expression parser,
- moving the code specific to implementing the "expr"
command from ClangExpression and
CommandObjectExpression into ClangUserExpression,
a new class,
- moving the common parser interaction code from
ClangExpression into ClangExpressionParser, a new
class, and
- making ClangFunction rely only on
ClangExpressionParser and not depend on the
internal implementation of ClangExpression.
Side effects include:
- the compiler interaction code has been factored
out of ClangFunction and is now in an AST pass
(ASTStructExtractor),
- the header file for ClangFunction is now fully
documented,
- several bugs that only popped up when Clang was
deallocated (which never happened, since the
lifetime of the compiler was essentially infinite)
are now fixed, and
- the developer-only "call" command has been
disabled.
I have tested the expr command and the Objective-C
step-into code, which use ClangUserExpression and
ClangFunction, respectively, and verified that they
work. Please let me know if you encounter bugs or
poor documentation.
llvm-svn: 112249
2010-08-27 09:01:44 +08:00
|
|
|
m_sel_registerName(NULL),
|
2010-09-14 05:34:21 +08:00
|
|
|
m_func_name(func_name),
|
|
|
|
m_resolve_vars(resolve_vars)
|
2010-07-03 09:35:46 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-10-01 05:18:25 +08:00
|
|
|
/* Handy utility functions used at several places in the code */
|
2010-08-11 11:57:18 +08:00
|
|
|
|
|
|
|
static std::string
|
2010-10-01 05:18:25 +08:00
|
|
|
PrintValue(const Value *V, bool truncate = false)
|
2010-08-11 11:57:18 +08:00
|
|
|
{
|
|
|
|
std::string s;
|
|
|
|
raw_string_ostream rso(s);
|
|
|
|
V->print(rso);
|
|
|
|
rso.flush();
|
|
|
|
if (truncate)
|
|
|
|
s.resize(s.length() - 1);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2010-10-01 05:18:25 +08:00
|
|
|
static std::string
|
|
|
|
PrintType(const Type *T, bool truncate = false)
|
|
|
|
{
|
|
|
|
std::string s;
|
|
|
|
raw_string_ostream rso(s);
|
|
|
|
T->print(rso);
|
|
|
|
rso.flush();
|
|
|
|
if (truncate)
|
|
|
|
s.resize(s.length() - 1);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2010-07-03 09:35:46 +08:00
|
|
|
IRForTarget::~IRForTarget()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-08-12 09:56:52 +08:00
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
IRForTarget::createResultVariable (llvm::Module &llvm_module, llvm::Function &llvm_function)
|
2010-08-12 09:56:52 +08:00
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-08-12 09:56:52 +08:00
|
|
|
|
2010-09-14 05:34:21 +08:00
|
|
|
if (!m_resolve_vars)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Find the result variable. If it doesn't exist, we can give up right here.
|
2010-08-12 09:56:52 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
ValueSymbolTable& value_symbol_table = llvm_module.getValueSymbolTable();
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
|
|
|
|
const char *result_name = NULL;
|
|
|
|
|
|
|
|
for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
|
|
|
|
vi != ve;
|
|
|
|
++vi)
|
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
if (strstr(vi->first(), "$__lldb_expr_result") &&
|
2010-09-29 05:13:03 +08:00
|
|
|
!strstr(vi->first(), "GV"))
|
|
|
|
{
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
result_name = vi->first();
|
2010-09-29 05:13:03 +08:00
|
|
|
break;
|
|
|
|
}
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!result_name)
|
2010-08-12 09:56:52 +08:00
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Couldn't find result variable");
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
|
2010-09-14 05:34:21 +08:00
|
|
|
return true;
|
2010-08-12 09:56:52 +08:00
|
|
|
}
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
|
2010-09-29 05:13:03 +08:00
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Result name: \"%s\"", result_name);
|
2010-09-29 05:13:03 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
Value *result_value = llvm_module.getNamedValue(result_name);
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
|
|
|
|
if (!result_value)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Result variable had no data");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2010-09-14 05:34:21 +08:00
|
|
|
|
2010-08-12 09:56:52 +08:00
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Found result in the IR: \"%s\"", PrintValue(result_value, false).c_str());
|
2010-08-12 09:56:52 +08:00
|
|
|
|
|
|
|
GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value);
|
|
|
|
|
|
|
|
if (!result_global)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Result variable isn't a GlobalVariable");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the metadata and follow it to the VarDecl
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
NamedMDNode *named_metadata = llvm_module.getNamedMetadata("clang.global.decl.ptrs");
|
2010-08-12 09:56:52 +08:00
|
|
|
|
|
|
|
if (!named_metadata)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("No global metadata");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned num_nodes = named_metadata->getNumOperands();
|
|
|
|
unsigned node_index;
|
|
|
|
|
|
|
|
MDNode *metadata_node = NULL;
|
|
|
|
|
|
|
|
for (node_index = 0;
|
|
|
|
node_index < num_nodes;
|
|
|
|
++node_index)
|
|
|
|
{
|
|
|
|
metadata_node = named_metadata->getOperand(node_index);
|
|
|
|
|
|
|
|
if (metadata_node->getNumOperands() != 2)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (metadata_node->getOperand(0) == result_global)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!metadata_node)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Couldn't find result metadata");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1));
|
|
|
|
|
2010-11-15 09:47:11 +08:00
|
|
|
lldb::addr_t result_decl_intptr = constant_int->getZExtValue();
|
2010-08-12 09:56:52 +08:00
|
|
|
|
|
|
|
clang::VarDecl *result_decl = reinterpret_cast<clang::VarDecl *>(result_decl_intptr);
|
|
|
|
|
|
|
|
// Get the next available result name from m_decl_map and create the persistent
|
|
|
|
// variable for it
|
|
|
|
|
|
|
|
lldb_private::TypeFromParser result_decl_type (result_decl->getType().getAsOpaquePtr(),
|
|
|
|
&result_decl->getASTContext());
|
2010-10-16 06:48:33 +08:00
|
|
|
|
|
|
|
lldb_private::ConstString new_result_name (m_decl_map->GetPersistentResultName());
|
|
|
|
m_decl_map->AddPersistentVariable(result_decl, new_result_name, result_decl_type);
|
2010-08-12 09:56:52 +08:00
|
|
|
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Creating a new result global: \"%s\"", new_result_name.GetCString());
|
2010-08-12 09:56:52 +08:00
|
|
|
|
|
|
|
// Construct a new result global and set up its metadata
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
GlobalVariable *new_result_global = new GlobalVariable(llvm_module,
|
2010-08-12 09:56:52 +08:00
|
|
|
result_global->getType()->getElementType(),
|
|
|
|
false, /* not constant */
|
|
|
|
GlobalValue::ExternalLinkage,
|
|
|
|
NULL, /* no initializer */
|
2010-10-16 06:48:33 +08:00
|
|
|
new_result_name.GetCString ());
|
2010-08-12 09:56:52 +08:00
|
|
|
|
|
|
|
// It's too late in compilation to create a new VarDecl for this, but we don't
|
|
|
|
// need to. We point the metadata at the old VarDecl. This creates an odd
|
|
|
|
// anomaly: a variable with a Value whose name is something like $0 and a
|
2010-10-16 06:48:33 +08:00
|
|
|
// Decl whose name is $__lldb_expr_result. This condition is handled in
|
2010-08-12 09:56:52 +08:00
|
|
|
// ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
|
|
|
|
// fixed up.
|
|
|
|
|
|
|
|
ConstantInt *new_constant_int = ConstantInt::get(constant_int->getType(),
|
|
|
|
result_decl_intptr,
|
|
|
|
false);
|
|
|
|
|
|
|
|
llvm::Value* values[2];
|
|
|
|
values[0] = new_result_global;
|
|
|
|
values[1] = new_constant_int;
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
MDNode *persistent_global_md = MDNode::get(llvm_module.getContext(), values, 2);
|
2010-08-12 09:56:52 +08:00
|
|
|
named_metadata->addOperand(persistent_global_md);
|
|
|
|
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Replacing \"%s\" with \"%s\"",
|
2010-09-08 06:43:19 +08:00
|
|
|
PrintValue(result_global).c_str(),
|
2010-08-12 09:56:52 +08:00
|
|
|
PrintValue(new_result_global).c_str());
|
2010-09-08 06:43:19 +08:00
|
|
|
|
|
|
|
if (result_global->hasNUses(0))
|
|
|
|
{
|
|
|
|
// We need to synthesize a store for this variable, because otherwise
|
|
|
|
// there's nothing to put into its equivalent persistent variable.
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
BasicBlock &entry_block(llvm_function.getEntryBlock());
|
2010-09-08 06:43:19 +08:00
|
|
|
Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg());
|
|
|
|
|
|
|
|
if (!first_entry_instruction)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!result_global->hasInitializer())
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf("Couldn't find initializer for unused variable");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Constant *initializer = result_global->getInitializer();
|
|
|
|
|
|
|
|
StoreInst *synthesized_store = new StoreInst::StoreInst(initializer,
|
|
|
|
new_result_global,
|
|
|
|
first_entry_instruction);
|
|
|
|
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Synthesized result store \"%s\"\n", PrintValue(synthesized_store).c_str());
|
2010-09-08 06:43:19 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result_global->replaceAllUsesWith(new_result_global);
|
|
|
|
}
|
2010-08-12 09:56:52 +08:00
|
|
|
|
|
|
|
result_global->eraseFromParent();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
static void DebugUsers(lldb::LogSP &log, Value *V, uint8_t depth)
|
|
|
|
{
|
|
|
|
if (!depth)
|
|
|
|
return;
|
|
|
|
|
|
|
|
depth--;
|
|
|
|
|
|
|
|
log->Printf(" <Begin %d users>", V->getNumUses());
|
|
|
|
|
|
|
|
for (Value::use_iterator ui = V->use_begin(), ue = V->use_end();
|
|
|
|
ui != ue;
|
|
|
|
++ui)
|
|
|
|
{
|
|
|
|
log->Printf(" <Use %p> %s", *ui, PrintValue(*ui).c_str());
|
|
|
|
DebugUsers(log, *ui, depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
log->Printf(" <End uses>");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IRForTarget::rewriteObjCConstString(llvm::Module &M,
|
|
|
|
llvm::GlobalVariable *NSStr,
|
|
|
|
llvm::GlobalVariable *CStr,
|
|
|
|
Instruction *FirstEntryInstruction)
|
|
|
|
{
|
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
|
|
|
|
|
|
|
const Type *i8_ptr_ty = Type::getInt8PtrTy(M.getContext());
|
|
|
|
const IntegerType *intptr_ty = Type::getIntNTy(M.getContext(),
|
|
|
|
(M.getPointerSize() == Module::Pointer64) ? 64 : 32);
|
|
|
|
const Type *i32_ty = Type::getInt32Ty(M.getContext());
|
|
|
|
const Type *i8_ty = Type::getInt8Ty(M.getContext());
|
|
|
|
|
|
|
|
if (!m_CFStringCreateWithBytes)
|
|
|
|
{
|
|
|
|
lldb::addr_t CFStringCreateWithBytes_addr;
|
|
|
|
|
|
|
|
static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes");
|
|
|
|
|
|
|
|
if (!m_decl_map->GetFunctionAddress (g_CFStringCreateWithBytes_str, CFStringCreateWithBytes_addr))
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Couldn't find CFStringCreateWithBytes in the target");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf("Found CFStringCreateWithBytes at 0x%llx", CFStringCreateWithBytes_addr);
|
|
|
|
|
|
|
|
// Build the function type:
|
|
|
|
//
|
|
|
|
// CFStringRef CFStringCreateWithBytes (
|
|
|
|
// CFAllocatorRef alloc,
|
|
|
|
// const UInt8 *bytes,
|
|
|
|
// CFIndex numBytes,
|
|
|
|
// CFStringEncoding encoding,
|
|
|
|
// Boolean isExternalRepresentation
|
|
|
|
// );
|
|
|
|
//
|
|
|
|
// We make the following substitutions:
|
|
|
|
//
|
|
|
|
// CFStringRef -> i8*
|
|
|
|
// CFAllocatorRef -> i8*
|
|
|
|
// UInt8 * -> i8*
|
|
|
|
// CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now)
|
|
|
|
// CFStringEncoding -> i32
|
|
|
|
// Boolean -> i8
|
|
|
|
|
|
|
|
std::vector <const Type *> CFSCWB_arg_types;
|
|
|
|
CFSCWB_arg_types.push_back(i8_ptr_ty);
|
|
|
|
CFSCWB_arg_types.push_back(i8_ptr_ty);
|
|
|
|
CFSCWB_arg_types.push_back(intptr_ty);
|
|
|
|
CFSCWB_arg_types.push_back(i32_ty);
|
|
|
|
CFSCWB_arg_types.push_back(i8_ty);
|
|
|
|
llvm::Type *CFSCWB_ty = FunctionType::get(i8_ptr_ty, CFSCWB_arg_types, false);
|
|
|
|
|
|
|
|
// Build the constant containing the pointer to the function
|
|
|
|
PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty);
|
|
|
|
Constant *CFSCWB_addr_int = ConstantInt::get(intptr_ty, CFStringCreateWithBytes_addr, false);
|
|
|
|
m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstantArray *string_array = dyn_cast<ConstantArray>(CStr->getInitializer());
|
|
|
|
|
|
|
|
SmallVector <Value*, 5> CFSCWB_arguments;
|
|
|
|
|
|
|
|
Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty);
|
|
|
|
Constant *bytes_arg = ConstantExpr::getBitCast(CStr, i8_ptr_ty);
|
|
|
|
Constant *numBytes_arg = ConstantInt::get(intptr_ty, string_array->getType()->getNumElements(), 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 */
|
|
|
|
|
|
|
|
CFSCWB_arguments.push_back(alloc_arg);
|
|
|
|
CFSCWB_arguments.push_back(bytes_arg);
|
|
|
|
CFSCWB_arguments.push_back(numBytes_arg);
|
|
|
|
CFSCWB_arguments.push_back(encoding_arg);
|
|
|
|
CFSCWB_arguments.push_back(isExternal_arg);
|
|
|
|
|
|
|
|
CallInst *CFSCWB_call = CallInst::Create(m_CFStringCreateWithBytes,
|
|
|
|
CFSCWB_arguments.begin(),
|
|
|
|
CFSCWB_arguments.end(),
|
|
|
|
"CFStringCreateWithBytes",
|
|
|
|
FirstEntryInstruction);
|
2010-11-19 06:21:58 +08:00
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
if (!UnfoldConstant(NSStr, CFSCWB_call, FirstEntryInstruction))
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Couldn't replace the NSString with the result of the call");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSStr->eraseFromParent();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IRForTarget::rewriteObjCConstStrings(Module &M,
|
|
|
|
Function &F)
|
|
|
|
{
|
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
|
|
|
|
|
|
|
ValueSymbolTable& value_symbol_table = M.getValueSymbolTable();
|
|
|
|
|
|
|
|
BasicBlock &entry_block(F.getEntryBlock());
|
|
|
|
Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg());
|
|
|
|
|
|
|
|
if (!FirstEntryInstruction)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Couldn't find first instruction for rewritten Objective-C strings");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
|
|
|
|
vi != ve;
|
|
|
|
++vi)
|
|
|
|
{
|
|
|
|
if (strstr(vi->first(), "_unnamed_cfstring_"))
|
|
|
|
{
|
|
|
|
Value *nsstring_value = vi->second;
|
|
|
|
|
|
|
|
GlobalVariable *nsstring_global = dyn_cast<GlobalVariable>(nsstring_value);
|
|
|
|
|
|
|
|
if (!nsstring_global)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("NSString variable is not a GlobalVariable");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nsstring_global->hasInitializer())
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("NSString variable does not have an initializer");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstantStruct *nsstring_struct = dyn_cast<ConstantStruct>(nsstring_global->getInitializer());
|
|
|
|
|
|
|
|
if (!nsstring_struct)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("NSString variable's initializer is not a ConstantStruct");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We expect the following structure:
|
|
|
|
//
|
|
|
|
// struct {
|
|
|
|
// int *isa;
|
|
|
|
// int flags;
|
|
|
|
// char *str;
|
|
|
|
// long length;
|
|
|
|
// };
|
|
|
|
|
|
|
|
if (nsstring_struct->getNumOperands() != 4)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf("NSString variable's initializer structure has an unexpected number of members. Should be 4, is %d", nsstring_struct->getNumOperands());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Constant *nsstring_member = nsstring_struct->getOperand(2);
|
|
|
|
|
|
|
|
if (!nsstring_member)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("NSString initializer's str element was empty");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member);
|
|
|
|
|
|
|
|
if (!nsstring_expr)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("NSString initializer's str element is not a ConstantExpr");
|
|
|
|
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());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Constant *nsstring_cstr = nsstring_expr->getOperand(0);
|
|
|
|
|
|
|
|
GlobalVariable *cstr_global = dyn_cast<GlobalVariable>(nsstring_cstr);
|
|
|
|
|
|
|
|
if (!cstr_global)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("NSString initializer's str element is not a GlobalVariable");
|
|
|
|
|
|
|
|
nsstring_cstr->dump();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cstr_global->hasInitializer())
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("NSString initializer's str element does not have an initializer");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstantArray *cstr_array = dyn_cast<ConstantArray>(cstr_global->getInitializer());
|
|
|
|
|
|
|
|
if (!cstr_array)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("NSString initializer's str element is not a ConstantArray");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cstr_array->isCString())
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("NSString initializer's str element is not a C string array");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf("Found NSString constant %s, which contains \"%s\"", vi->first(), cstr_array->getAsString().c_str());
|
|
|
|
|
|
|
|
if (!rewriteObjCConstString(M, nsstring_global, cstr_global, FirstEntryInstruction))
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Error rewriting the constant string");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
|
|
|
|
vi != ve;
|
|
|
|
++vi)
|
|
|
|
{
|
|
|
|
if (!strcmp(vi->first(), "__CFConstantStringClassReference"))
|
|
|
|
{
|
|
|
|
GlobalVariable *gv = dyn_cast<GlobalVariable>(vi->second);
|
|
|
|
|
|
|
|
if (!gv)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("__CFConstantStringClassReference is not a global variable");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
gv->eraseFromParent();
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
static bool isObjCSelectorRef(Value *V)
|
|
|
|
{
|
|
|
|
GlobalVariable *GV = dyn_cast<GlobalVariable>(V);
|
|
|
|
|
|
|
|
if (!GV || !GV->hasName() || !GV->getName().startswith("\01L_OBJC_SELECTOR_REFERENCES_"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IRForTarget::RewriteObjCSelector(Instruction* selector_load,
|
|
|
|
Module &M)
|
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-07-31 09:32:05 +08:00
|
|
|
|
|
|
|
LoadInst *load = dyn_cast<LoadInst>(selector_load);
|
|
|
|
|
|
|
|
if (!load)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as
|
|
|
|
//
|
|
|
|
// %tmp = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_" ; <i8*>
|
|
|
|
// %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*>
|
|
|
|
//
|
|
|
|
// where %obj is the object pointer and %tmp is the selector.
|
|
|
|
//
|
|
|
|
// @"\01L_OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_METH_VAR_NAME_".
|
|
|
|
// @"\01L_OBJC_METH_VAR_NAME_" contains the string.
|
|
|
|
|
|
|
|
// Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target
|
|
|
|
|
|
|
|
GlobalVariable *_objc_selector_references_ = dyn_cast<GlobalVariable>(load->getPointerOperand());
|
|
|
|
|
|
|
|
if (!_objc_selector_references_ || !_objc_selector_references_->hasInitializer())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Constant *osr_initializer = _objc_selector_references_->getInitializer();
|
|
|
|
|
|
|
|
ConstantExpr *osr_initializer_expr = dyn_cast<ConstantExpr>(osr_initializer);
|
|
|
|
|
|
|
|
if (!osr_initializer_expr || osr_initializer_expr->getOpcode() != Instruction::GetElementPtr)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Value *osr_initializer_base = osr_initializer_expr->getOperand(0);
|
|
|
|
|
|
|
|
if (!osr_initializer_base)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Find the string's initializer (a ConstantArray) and get the string from it
|
|
|
|
|
|
|
|
GlobalVariable *_objc_meth_var_name_ = dyn_cast<GlobalVariable>(osr_initializer_base);
|
|
|
|
|
|
|
|
if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Constant *omvn_initializer = _objc_meth_var_name_->getInitializer();
|
|
|
|
|
|
|
|
ConstantArray *omvn_initializer_array = dyn_cast<ConstantArray>(omvn_initializer);
|
|
|
|
|
|
|
|
if (!omvn_initializer_array->isString())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::string omvn_initializer_string = omvn_initializer_array->getAsString();
|
|
|
|
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Found Objective-C selector reference \"%s\"", omvn_initializer_string.c_str());
|
2010-07-31 09:32:05 +08:00
|
|
|
|
|
|
|
// Construct a call to sel_registerName
|
|
|
|
|
|
|
|
if (!m_sel_registerName)
|
|
|
|
{
|
2010-11-15 09:47:11 +08:00
|
|
|
lldb::addr_t sel_registerName_addr;
|
2010-07-31 09:32:05 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
static lldb_private::ConstString g_sel_registerName_str ("sel_registerName");
|
2010-11-15 09:47:11 +08:00
|
|
|
if (!m_decl_map->GetFunctionAddress (g_sel_registerName_str, sel_registerName_addr))
|
2010-07-31 09:32:05 +08:00
|
|
|
return false;
|
|
|
|
|
2010-10-26 08:31:56 +08:00
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Found sel_registerName at 0x%llx", sel_registerName_addr);
|
2010-10-26 08:31:56 +08:00
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
// Build the function type: struct objc_selector *sel_registerName(uint8_t*)
|
|
|
|
|
|
|
|
// The below code would be "more correct," but in actuality what's required is uint8_t*
|
|
|
|
//Type *sel_type = StructType::get(M.getContext());
|
|
|
|
//Type *sel_ptr_type = PointerType::getUnqual(sel_type);
|
|
|
|
const Type *sel_ptr_type = Type::getInt8PtrTy(M.getContext());
|
|
|
|
|
|
|
|
std::vector <const Type *> srN_arg_types;
|
|
|
|
srN_arg_types.push_back(Type::getInt8PtrTy(M.getContext()));
|
|
|
|
llvm::Type *srN_type = FunctionType::get(sel_ptr_type, srN_arg_types, false);
|
|
|
|
|
|
|
|
// Build the constant containing the pointer to the function
|
|
|
|
const IntegerType *intptr_ty = Type::getIntNTy(M.getContext(),
|
|
|
|
(M.getPointerSize() == Module::Pointer64) ? 64 : 32);
|
|
|
|
PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type);
|
2010-11-15 09:47:11 +08:00
|
|
|
Constant *srN_addr_int = ConstantInt::get(intptr_ty, sel_registerName_addr, false);
|
2010-07-31 09:32:05 +08:00
|
|
|
m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
SmallVector <Value*, 1> srN_arguments;
|
|
|
|
|
|
|
|
Constant *omvn_pointer = ConstantExpr::getBitCast(_objc_meth_var_name_, Type::getInt8PtrTy(M.getContext()));
|
|
|
|
|
|
|
|
srN_arguments.push_back(omvn_pointer);
|
|
|
|
|
|
|
|
CallInst *srN_call = CallInst::Create(m_sel_registerName,
|
|
|
|
srN_arguments.begin(),
|
|
|
|
srN_arguments.end(),
|
2010-11-18 07:00:36 +08:00
|
|
|
"sel_registerName",
|
2010-07-31 09:32:05 +08:00
|
|
|
selector_load);
|
|
|
|
|
|
|
|
// Replace the load with the call in all users
|
|
|
|
|
|
|
|
selector_load->replaceAllUsesWith(srN_call);
|
|
|
|
|
|
|
|
selector_load->eraseFromParent();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IRForTarget::rewriteObjCSelectors(Module &M,
|
|
|
|
BasicBlock &BB)
|
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-07-31 09:32:05 +08:00
|
|
|
|
|
|
|
BasicBlock::iterator ii;
|
|
|
|
|
|
|
|
typedef SmallVector <Instruction*, 2> InstrList;
|
|
|
|
typedef InstrList::iterator InstrIterator;
|
|
|
|
|
|
|
|
InstrList selector_loads;
|
|
|
|
|
|
|
|
for (ii = BB.begin();
|
|
|
|
ii != BB.end();
|
|
|
|
++ii)
|
|
|
|
{
|
|
|
|
Instruction &inst = *ii;
|
|
|
|
|
|
|
|
if (LoadInst *load = dyn_cast<LoadInst>(&inst))
|
|
|
|
if (isObjCSelectorRef(load->getPointerOperand()))
|
|
|
|
selector_loads.push_back(&inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
InstrIterator iter;
|
|
|
|
|
|
|
|
for (iter = selector_loads.begin();
|
|
|
|
iter != selector_loads.end();
|
|
|
|
++iter)
|
|
|
|
{
|
|
|
|
if (!RewriteObjCSelector(*iter, M))
|
|
|
|
{
|
|
|
|
if(log)
|
|
|
|
log->PutCString("Couldn't rewrite a reference to an Objective-C selector");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
bool
|
|
|
|
IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc,
|
2010-10-16 06:48:33 +08:00
|
|
|
llvm::Module &llvm_module)
|
2010-08-11 11:57:18 +08:00
|
|
|
{
|
|
|
|
AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc);
|
|
|
|
|
|
|
|
MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr");
|
|
|
|
|
|
|
|
if (!alloc_md || !alloc_md->getNumOperands())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ConstantInt *constant_int = dyn_cast<ConstantInt>(alloc_md->getOperand(0));
|
|
|
|
|
|
|
|
if (!constant_int)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// We attempt to register this as a new persistent variable with the DeclMap.
|
|
|
|
|
|
|
|
uintptr_t ptr = constant_int->getZExtValue();
|
|
|
|
|
2010-08-12 09:56:52 +08:00
|
|
|
clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr);
|
2010-08-11 11:57:18 +08:00
|
|
|
|
2010-08-12 09:56:52 +08:00
|
|
|
lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(),
|
|
|
|
&decl->getASTContext());
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
StringRef decl_name (decl->getName());
|
|
|
|
lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size());
|
|
|
|
if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type))
|
2010-08-11 11:57:18 +08:00
|
|
|
return false;
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
GlobalVariable *persistent_global = new GlobalVariable(llvm_module,
|
2010-08-11 11:57:18 +08:00
|
|
|
alloc->getType()->getElementType(),
|
|
|
|
false, /* not constant */
|
|
|
|
GlobalValue::ExternalLinkage,
|
|
|
|
NULL, /* no initializer */
|
|
|
|
alloc->getName().str().c_str());
|
|
|
|
|
|
|
|
// What we're going to do here is make believe this was a regular old external
|
|
|
|
// variable. That means we need to make the metadata valid.
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
NamedMDNode *named_metadata = llvm_module.getNamedMetadata("clang.global.decl.ptrs");
|
2010-08-11 11:57:18 +08:00
|
|
|
|
|
|
|
llvm::Value* values[2];
|
|
|
|
values[0] = persistent_global;
|
|
|
|
values[1] = constant_int;
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
MDNode *persistent_global_md = MDNode::get(llvm_module.getContext(), values, 2);
|
2010-08-11 11:57:18 +08:00
|
|
|
named_metadata->addOperand(persistent_global_md);
|
|
|
|
|
|
|
|
alloc->replaceAllUsesWith(persistent_global);
|
|
|
|
alloc->eraseFromParent();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IRForTarget::rewritePersistentAllocs(llvm::Module &M,
|
|
|
|
llvm::BasicBlock &BB)
|
|
|
|
{
|
2010-09-14 05:34:21 +08:00
|
|
|
if (!m_resolve_vars)
|
|
|
|
return true;
|
|
|
|
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-08-11 11:57:18 +08:00
|
|
|
|
|
|
|
BasicBlock::iterator ii;
|
|
|
|
|
|
|
|
typedef SmallVector <Instruction*, 2> InstrList;
|
|
|
|
typedef InstrList::iterator InstrIterator;
|
|
|
|
|
|
|
|
InstrList pvar_allocs;
|
|
|
|
|
|
|
|
for (ii = BB.begin();
|
|
|
|
ii != BB.end();
|
|
|
|
++ii)
|
|
|
|
{
|
|
|
|
Instruction &inst = *ii;
|
|
|
|
|
|
|
|
if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst))
|
2010-10-22 06:41:32 +08:00
|
|
|
if (alloc->getName().startswith("$") &&
|
|
|
|
!alloc->getName().startswith("$__lldb"))
|
2010-08-11 11:57:18 +08:00
|
|
|
pvar_allocs.push_back(alloc);
|
|
|
|
}
|
|
|
|
|
|
|
|
InstrIterator iter;
|
|
|
|
|
|
|
|
for (iter = pvar_allocs.begin();
|
|
|
|
iter != pvar_allocs.end();
|
|
|
|
++iter)
|
|
|
|
{
|
|
|
|
if (!RewritePersistentAlloc(*iter, M))
|
|
|
|
{
|
|
|
|
if(log)
|
|
|
|
log->PutCString("Couldn't rewrite the creation of a persistent variable");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
static clang::NamedDecl *
|
2010-07-28 05:39:39 +08:00
|
|
|
DeclForGlobalValue(Module &module,
|
|
|
|
GlobalValue *global_value)
|
2010-07-14 05:41:46 +08:00
|
|
|
{
|
|
|
|
NamedMDNode *named_metadata = module.getNamedMetadata("clang.global.decl.ptrs");
|
|
|
|
|
|
|
|
if (!named_metadata)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
unsigned num_nodes = named_metadata->getNumOperands();
|
|
|
|
unsigned node_index;
|
|
|
|
|
|
|
|
for (node_index = 0;
|
|
|
|
node_index < num_nodes;
|
|
|
|
++node_index)
|
|
|
|
{
|
|
|
|
MDNode *metadata_node = named_metadata->getOperand(node_index);
|
|
|
|
|
|
|
|
if (!metadata_node)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (metadata_node->getNumOperands() != 2)
|
2010-08-11 11:57:18 +08:00
|
|
|
continue;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
|
|
|
if (metadata_node->getOperand(0) != global_value)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1));
|
|
|
|
|
|
|
|
if (!constant_int)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
uintptr_t ptr = constant_int->getZExtValue();
|
|
|
|
|
|
|
|
return reinterpret_cast<clang::NamedDecl *>(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
IRForTarget::MaybeHandleVariable
|
|
|
|
(
|
|
|
|
Module &llvm_module,
|
2010-11-08 08:31:32 +08:00
|
|
|
Value *llvm_value_ptr
|
2010-10-16 06:48:33 +08:00
|
|
|
)
|
2010-07-03 09:35:46 +08:00
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-07-31 09:32:05 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr))
|
2010-08-03 08:23:29 +08:00
|
|
|
{
|
2010-08-04 09:02:13 +08:00
|
|
|
switch (constant_expr->getOpcode())
|
2010-08-03 08:23:29 +08:00
|
|
|
{
|
2010-08-04 09:02:13 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
case Instruction::GetElementPtr:
|
|
|
|
case Instruction::BitCast:
|
2010-08-03 08:23:29 +08:00
|
|
|
Value *s = constant_expr->getOperand(0);
|
2010-11-08 08:31:32 +08:00
|
|
|
MaybeHandleVariable(llvm_module, s);
|
2010-08-03 08:23:29 +08:00
|
|
|
}
|
|
|
|
}
|
2010-10-16 06:48:33 +08:00
|
|
|
if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(llvm_value_ptr))
|
2010-07-31 09:32:05 +08:00
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
clang::NamedDecl *named_decl = DeclForGlobalValue(llvm_module, global_variable);
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
if (!named_decl)
|
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
if (isObjCSelectorRef(llvm_value_ptr))
|
2010-07-31 09:32:05 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Found global variable \"%s\" without metadata", global_variable->getName().str().c_str());
|
2010-07-31 09:32:05 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
std::string name (named_decl->getName().str());
|
2010-07-16 08:09:46 +08:00
|
|
|
|
2010-10-01 05:18:25 +08:00
|
|
|
void *opaque_type = NULL;
|
2010-07-21 07:31:16 +08:00
|
|
|
clang::ASTContext *ast_context = NULL;
|
2010-07-16 08:09:46 +08:00
|
|
|
|
|
|
|
if (clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl))
|
2010-07-21 07:31:16 +08:00
|
|
|
{
|
2010-10-01 05:18:25 +08:00
|
|
|
opaque_type = value_decl->getType().getAsOpaquePtr();
|
2010-07-21 07:31:16 +08:00
|
|
|
ast_context = &value_decl->getASTContext();
|
|
|
|
}
|
2010-07-16 08:09:46 +08:00
|
|
|
else
|
2010-07-21 07:31:16 +08:00
|
|
|
{
|
2010-07-16 08:09:46 +08:00
|
|
|
return false;
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
2010-10-01 05:18:25 +08:00
|
|
|
|
|
|
|
clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_type));
|
2010-07-21 07:31:16 +08:00
|
|
|
|
2010-07-28 05:39:39 +08:00
|
|
|
const Type *value_type = global_variable->getType();
|
2010-10-01 05:18:25 +08:00
|
|
|
|
|
|
|
size_t value_size = (ast_context->getTypeSize(qual_type) + 7) / 8;
|
|
|
|
off_t value_alignment = (ast_context->getTypeAlign(qual_type) + 7) / 8;
|
|
|
|
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Type of \"%s\" is [clang \"%s\", lldb \"%s\"] [size %d, align %d]",
|
2010-10-01 05:18:25 +08:00
|
|
|
name.c_str(),
|
|
|
|
qual_type.getAsString().c_str(),
|
|
|
|
PrintType(value_type).c_str(),
|
|
|
|
value_size,
|
|
|
|
value_alignment);
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
if (named_decl && !m_decl_map->AddValueToStruct(named_decl,
|
2010-10-16 06:48:33 +08:00
|
|
|
lldb_private::ConstString (name.c_str()),
|
|
|
|
llvm_value_ptr,
|
2010-07-27 10:07:53 +08:00
|
|
|
value_size,
|
|
|
|
value_alignment))
|
2010-07-14 05:41:46 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-10-06 06:26:43 +08:00
|
|
|
bool
|
|
|
|
IRForTarget::MaybeHandleCallArguments(Module &M,
|
2010-11-18 07:00:36 +08:00
|
|
|
CallInst *Old)
|
2010-10-06 06:26:43 +08:00
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
// lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-10-06 06:26:43 +08:00
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
for (unsigned op_index = 0, num_ops = Old->getNumArgOperands();
|
2010-10-06 06:26:43 +08:00
|
|
|
op_index < num_ops;
|
|
|
|
++op_index)
|
2010-11-18 07:00:36 +08:00
|
|
|
if (!MaybeHandleVariable(M, Old->getArgOperand(op_index))) // conservatively believe that this is a store
|
2010-10-06 06:26:43 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-27 10:07:53 +08:00
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
IRForTarget::MaybeHandleCall(Module &llvm_module,
|
|
|
|
CallInst *llvm_call_inst)
|
2010-07-27 10:07:53 +08:00
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-07-27 10:07:53 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
Function *fun = llvm_call_inst->getCalledFunction();
|
2010-07-27 10:07:53 +08:00
|
|
|
|
|
|
|
if (fun == NULL)
|
2010-09-09 04:04:08 +08:00
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
Value *val = llvm_call_inst->getCalledValue();
|
2010-09-09 04:04:08 +08:00
|
|
|
|
|
|
|
ConstantExpr *const_expr = dyn_cast<ConstantExpr>(val);
|
|
|
|
|
|
|
|
if (const_expr && const_expr->getOpcode() == Instruction::BitCast)
|
|
|
|
{
|
|
|
|
fun = dyn_cast<Function>(const_expr->getOperand(0));
|
|
|
|
|
|
|
|
if (!fun)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2010-07-27 10:07:53 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
lldb_private::ConstString str;
|
2010-09-29 05:13:03 +08:00
|
|
|
|
2010-09-29 07:55:00 +08:00
|
|
|
if (fun->isIntrinsic())
|
2010-09-29 05:13:03 +08:00
|
|
|
{
|
2010-09-29 07:55:00 +08:00
|
|
|
Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID();
|
2010-09-29 05:13:03 +08:00
|
|
|
|
2010-09-29 07:55:00 +08:00
|
|
|
switch (intrinsic_id)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str());
|
2010-09-29 07:55:00 +08:00
|
|
|
return false;
|
|
|
|
case Intrinsic::memcpy:
|
2010-10-16 06:48:33 +08:00
|
|
|
{
|
|
|
|
static lldb_private::ConstString g_memcpy_str ("memcpy");
|
|
|
|
str = g_memcpy_str;
|
|
|
|
}
|
2010-09-29 07:55:00 +08:00
|
|
|
break;
|
|
|
|
}
|
2010-09-29 05:13:03 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
if (log && str)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Resolved intrinsic name \"%s\"", str.GetCString());
|
2010-09-29 07:55:00 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
str.SetCStringWithLength (fun->getName().data(), fun->getName().size());
|
2010-09-29 05:13:03 +08:00
|
|
|
}
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
clang::NamedDecl *fun_decl = DeclForGlobalValue (llvm_module, fun);
|
2010-11-15 09:47:11 +08:00
|
|
|
lldb::addr_t fun_addr = LLDB_INVALID_ADDRESS;
|
2010-07-31 09:32:05 +08:00
|
|
|
Value **fun_value_ptr = NULL;
|
2010-07-27 10:07:53 +08:00
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
if (fun_decl)
|
2010-07-27 10:07:53 +08:00
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
if (!m_decl_map->GetFunctionInfo (fun_decl, fun_value_ptr, fun_addr))
|
2010-07-31 09:32:05 +08:00
|
|
|
{
|
2010-09-08 05:49:41 +08:00
|
|
|
fun_value_ptr = NULL;
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
if (!m_decl_map->GetFunctionAddress (str, fun_addr))
|
2010-09-08 05:49:41 +08:00
|
|
|
{
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Function \"%s\" had no address", str.GetCString());
|
2010-09-08 05:49:41 +08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2010-07-31 09:32:05 +08:00
|
|
|
}
|
2010-07-27 10:07:53 +08:00
|
|
|
}
|
2010-07-31 09:32:05 +08:00
|
|
|
else
|
2010-07-27 10:07:53 +08:00
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
if (!m_decl_map->GetFunctionAddress (str, fun_addr))
|
2010-07-31 09:32:05 +08:00
|
|
|
{
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf ("Metadataless function \"%s\" had no address", str.GetCString());
|
2010-07-31 09:32:05 +08:00
|
|
|
}
|
2010-07-27 10:07:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Found \"%s\" at 0x%llx", str.GetCString(), fun_addr);
|
2010-07-27 10:07:53 +08:00
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
Value *fun_addr_ptr;
|
|
|
|
|
|
|
|
if (!fun_value_ptr || !*fun_value_ptr)
|
2010-07-28 05:39:39 +08:00
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
const IntegerType *intptr_ty = Type::getIntNTy(llvm_module.getContext(),
|
|
|
|
(llvm_module.getPointerSize() == Module::Pointer64) ? 64 : 32);
|
2010-09-08 05:49:41 +08:00
|
|
|
const FunctionType *fun_ty = fun->getFunctionType();
|
2010-07-28 05:39:39 +08:00
|
|
|
PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
|
|
|
|
Constant *fun_addr_int = ConstantInt::get(intptr_ty, fun_addr, false);
|
2010-07-31 09:32:05 +08:00
|
|
|
fun_addr_ptr = ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
|
|
|
|
|
|
|
|
if (fun_value_ptr)
|
|
|
|
*fun_value_ptr = fun_addr_ptr;
|
2010-07-28 05:39:39 +08:00
|
|
|
}
|
2010-07-31 09:32:05 +08:00
|
|
|
|
|
|
|
if (fun_value_ptr)
|
|
|
|
fun_addr_ptr = *fun_value_ptr;
|
2010-07-28 05:39:39 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
llvm_call_inst->setCalledFunction(fun_addr_ptr);
|
2010-07-28 05:39:39 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
ConstantArray *func_name = (ConstantArray*)ConstantArray::get(llvm_module.getContext(), str.GetCString());
|
2010-09-14 05:34:21 +08:00
|
|
|
|
|
|
|
Value *values[1];
|
|
|
|
values[0] = func_name;
|
2010-10-16 06:48:33 +08:00
|
|
|
MDNode *func_metadata = MDNode::get(llvm_module.getContext(), values, 1);
|
2010-09-14 05:34:21 +08:00
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
llvm_call_inst->setMetadata("lldb.call.realName", func_metadata);
|
2010-09-14 05:34:21 +08:00
|
|
|
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Set metadata for %p [%d, \"%s\"]", llvm_call_inst, func_name->isString(), func_name->getAsString().c_str());
|
2010-09-14 05:34:21 +08:00
|
|
|
|
2010-07-27 10:07:53 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
bool
|
2010-11-08 08:31:32 +08:00
|
|
|
IRForTarget::resolveCalls(Module &M, BasicBlock &BB)
|
2010-07-14 05:41:46 +08:00
|
|
|
{
|
2010-07-03 09:35:46 +08:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
// Prepare the current basic block for execution in the remote process
|
|
|
|
//
|
|
|
|
|
2010-07-28 05:39:39 +08:00
|
|
|
BasicBlock::iterator ii;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
|
|
|
for (ii = BB.begin();
|
|
|
|
ii != BB.end();
|
|
|
|
++ii)
|
|
|
|
{
|
|
|
|
Instruction &inst = *ii;
|
|
|
|
|
2010-11-08 08:31:32 +08:00
|
|
|
CallInst *call = dyn_cast<CallInst>(&inst);
|
2010-07-27 10:07:53 +08:00
|
|
|
|
2010-11-08 08:31:32 +08:00
|
|
|
if (call && !MaybeHandleCall(M, call))
|
|
|
|
return false;
|
2010-07-14 05:41:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-11-08 08:31:32 +08:00
|
|
|
bool
|
|
|
|
IRForTarget::resolveExternals(Module &M,
|
|
|
|
Function &F)
|
|
|
|
{
|
2010-11-19 06:21:58 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
|
|
|
|
2010-11-08 08:31:32 +08:00
|
|
|
for (Module::global_iterator global = M.global_begin(), end = M.global_end();
|
|
|
|
global != end;
|
|
|
|
++global)
|
|
|
|
{
|
2010-11-19 06:21:58 +08:00
|
|
|
if (DeclForGlobalValue(M, global) &&
|
2010-11-08 08:31:32 +08:00
|
|
|
!MaybeHandleVariable (M, global))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-28 05:39:39 +08:00
|
|
|
static bool isGuardVariableRef(Value *V)
|
2010-07-24 09:37:44 +08:00
|
|
|
{
|
2010-11-18 07:00:36 +08:00
|
|
|
Constant *Old;
|
2010-07-24 09:37:44 +08:00
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
if (!(Old = dyn_cast<Constant>(V)))
|
2010-07-24 09:37:44 +08:00
|
|
|
return false;
|
|
|
|
|
2010-09-23 11:01:22 +08:00
|
|
|
ConstantExpr *CE;
|
|
|
|
|
|
|
|
if ((CE = dyn_cast<ConstantExpr>(V)))
|
|
|
|
{
|
|
|
|
if (CE->getOpcode() != Instruction::BitCast)
|
|
|
|
return false;
|
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
Old = CE->getOperand(0);
|
2010-09-23 11:01:22 +08:00
|
|
|
}
|
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
GlobalVariable *GV = dyn_cast<GlobalVariable>(Old);
|
2010-07-24 09:37:44 +08:00
|
|
|
|
|
|
|
if (!GV || !GV->hasName() || !GV->getName().startswith("_ZGV"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TurnGuardLoadIntoZero(Instruction* guard_load, Module &M)
|
|
|
|
{
|
|
|
|
Constant* zero(ConstantInt::get(Type::getInt8Ty(M.getContext()), 0, true));
|
|
|
|
|
|
|
|
Value::use_iterator ui;
|
|
|
|
|
|
|
|
for (ui = guard_load->use_begin();
|
|
|
|
ui != guard_load->use_end();
|
|
|
|
++ui)
|
2010-07-27 09:17:28 +08:00
|
|
|
{
|
2010-07-31 04:30:44 +08:00
|
|
|
if (isa<Constant>(*ui))
|
2010-07-27 09:17:28 +08:00
|
|
|
{
|
|
|
|
// do nothing for the moment
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ui->replaceUsesOfWith(guard_load, zero);
|
|
|
|
}
|
|
|
|
}
|
2010-07-24 09:37:44 +08:00
|
|
|
|
|
|
|
guard_load->eraseFromParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ExciseGuardStore(Instruction* guard_store)
|
|
|
|
{
|
|
|
|
guard_store->eraseFromParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IRForTarget::removeGuards(Module &M, BasicBlock &BB)
|
|
|
|
{
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// Eliminate any reference to guard variables found.
|
|
|
|
//
|
|
|
|
|
2010-07-28 05:39:39 +08:00
|
|
|
BasicBlock::iterator ii;
|
2010-07-24 09:37:44 +08:00
|
|
|
|
2010-07-28 05:39:39 +08:00
|
|
|
typedef SmallVector <Instruction*, 2> InstrList;
|
2010-07-24 09:37:44 +08:00
|
|
|
typedef InstrList::iterator InstrIterator;
|
|
|
|
|
|
|
|
InstrList guard_loads;
|
|
|
|
InstrList guard_stores;
|
|
|
|
|
|
|
|
for (ii = BB.begin();
|
|
|
|
ii != BB.end();
|
|
|
|
++ii)
|
|
|
|
{
|
|
|
|
Instruction &inst = *ii;
|
|
|
|
|
|
|
|
if (LoadInst *load = dyn_cast<LoadInst>(&inst))
|
|
|
|
if (isGuardVariableRef(load->getPointerOperand()))
|
|
|
|
guard_loads.push_back(&inst);
|
|
|
|
|
|
|
|
if (StoreInst *store = dyn_cast<StoreInst>(&inst))
|
|
|
|
if (isGuardVariableRef(store->getPointerOperand()))
|
|
|
|
guard_stores.push_back(&inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
InstrIterator iter;
|
|
|
|
|
|
|
|
for (iter = guard_loads.begin();
|
|
|
|
iter != guard_loads.end();
|
|
|
|
++iter)
|
|
|
|
TurnGuardLoadIntoZero(*iter, M);
|
|
|
|
|
|
|
|
for (iter = guard_stores.begin();
|
|
|
|
iter != guard_stores.end();
|
|
|
|
++iter)
|
|
|
|
ExciseGuardStore(*iter);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
bool
|
|
|
|
IRForTarget::UnfoldConstant(Constant *Old, Value *New, Instruction *FirstEntryInstruction)
|
2010-07-15 07:40:29 +08:00
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-07-15 07:40:29 +08:00
|
|
|
|
|
|
|
Value::use_iterator ui;
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
SmallVector<User*, 16> users;
|
|
|
|
|
|
|
|
// We do this because the use list might change, invalidating our iterator.
|
|
|
|
// Much better to keep a work list ourselves.
|
2010-11-18 07:00:36 +08:00
|
|
|
for (ui = Old->use_begin();
|
|
|
|
ui != Old->use_end();
|
2010-07-15 07:40:29 +08:00
|
|
|
++ui)
|
2010-08-11 11:57:18 +08:00
|
|
|
users.push_back(*ui);
|
2010-07-15 07:40:29 +08:00
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
for (int i = 0;
|
|
|
|
i < users.size();
|
|
|
|
++i)
|
|
|
|
{
|
|
|
|
User *user = users[i];
|
|
|
|
|
2010-07-15 07:40:29 +08:00
|
|
|
if (Constant *constant = dyn_cast<Constant>(user))
|
|
|
|
{
|
|
|
|
// synthesize a new non-constant equivalent of the constant
|
|
|
|
|
|
|
|
if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
|
|
|
|
{
|
|
|
|
switch (constant_expr->getOpcode())
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Unhandled constant expression type: \"%s\"", PrintValue(constant_expr).c_str());
|
2010-07-15 07:40:29 +08:00
|
|
|
return false;
|
|
|
|
case Instruction::BitCast:
|
|
|
|
{
|
|
|
|
// UnaryExpr
|
|
|
|
// OperandList[0] is value
|
|
|
|
|
|
|
|
Value *s = constant_expr->getOperand(0);
|
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
if (s == Old)
|
|
|
|
s = New;
|
2010-07-15 07:40:29 +08:00
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
BitCastInst *bit_cast(new BitCastInst(s, Old->getType(), "", FirstEntryInstruction));
|
2010-07-15 07:40:29 +08:00
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
UnfoldConstant(constant_expr, bit_cast, FirstEntryInstruction);
|
2010-07-15 07:40:29 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Instruction::GetElementPtr:
|
|
|
|
{
|
|
|
|
// GetElementPtrConstantExpr
|
|
|
|
// OperandList[0] is base
|
|
|
|
// OperandList[1]... are indices
|
|
|
|
|
|
|
|
Value *ptr = constant_expr->getOperand(0);
|
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
if (ptr == Old)
|
|
|
|
ptr = New;
|
2010-07-15 07:40:29 +08:00
|
|
|
|
|
|
|
SmallVector<Value*, 16> indices;
|
|
|
|
|
|
|
|
unsigned operand_index;
|
|
|
|
unsigned num_operands = constant_expr->getNumOperands();
|
|
|
|
|
|
|
|
for (operand_index = 1;
|
|
|
|
operand_index < num_operands;
|
|
|
|
++operand_index)
|
|
|
|
{
|
|
|
|
Value *operand = constant_expr->getOperand(operand_index);
|
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
if (operand == Old)
|
|
|
|
operand = New;
|
2010-07-15 07:40:29 +08:00
|
|
|
|
|
|
|
indices.push_back(operand);
|
|
|
|
}
|
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
GetElementPtrInst *get_element_ptr(GetElementPtrInst::Create(ptr, indices.begin(), indices.end(), "", FirstEntryInstruction));
|
2010-07-15 07:40:29 +08:00
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
UnfoldConstant(constant_expr, get_element_ptr, FirstEntryInstruction);
|
2010-07-15 07:40:29 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Unhandled constant type: \"%s\"", PrintValue(constant).c_str());
|
2010-07-15 07:40:29 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// simple fall-through case for non-constants
|
2010-11-18 07:00:36 +08:00
|
|
|
user->replaceUsesOfWith(Old, New);
|
2010-07-15 07:40:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
bool
|
2010-07-31 09:32:05 +08:00
|
|
|
IRForTarget::replaceVariables(Module &M, Function &F)
|
2010-07-14 05:41:46 +08:00
|
|
|
{
|
2010-09-14 05:34:21 +08:00
|
|
|
if (!m_resolve_vars)
|
|
|
|
return true;
|
|
|
|
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-07-14 05:41:46 +08:00
|
|
|
|
|
|
|
m_decl_map->DoStructLayout();
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf("Element arrangement:");
|
|
|
|
|
|
|
|
uint32_t num_elements;
|
|
|
|
uint32_t element_index;
|
|
|
|
|
|
|
|
size_t size;
|
|
|
|
off_t alignment;
|
|
|
|
|
|
|
|
if (!m_decl_map->GetStructInfo (num_elements, size, alignment))
|
|
|
|
return false;
|
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
Function::arg_iterator iter(F.getArgumentList().begin());
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
if (iter == F.getArgumentList().end())
|
2010-07-14 05:41:46 +08:00
|
|
|
return false;
|
|
|
|
|
2010-07-28 05:39:39 +08:00
|
|
|
Argument *argument = iter;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
if (argument->getName().equals("this"))
|
|
|
|
{
|
|
|
|
++iter;
|
|
|
|
|
|
|
|
if (iter == F.getArgumentList().end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
argument = iter;
|
|
|
|
}
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
if (!argument->getName().equals("$__lldb_arg"))
|
2010-07-14 05:41:46 +08:00
|
|
|
return false;
|
|
|
|
|
2010-07-03 09:35:46 +08:00
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Arg: \"%s\"", PrintValue(argument).c_str());
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
BasicBlock &entry_block(F.getEntryBlock());
|
2010-11-18 07:00:36 +08:00
|
|
|
Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg());
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
if (!FirstEntryInstruction)
|
2010-07-14 05:41:46 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
LLVMContext &context(M.getContext());
|
|
|
|
const IntegerType *offset_type(Type::getInt32Ty(context));
|
|
|
|
|
|
|
|
if (!offset_type)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (element_index = 0; element_index < num_elements; ++element_index)
|
2010-07-03 09:35:46 +08:00
|
|
|
{
|
2010-07-14 05:41:46 +08:00
|
|
|
const clang::NamedDecl *decl;
|
2010-07-28 05:39:39 +08:00
|
|
|
Value *value;
|
2010-07-14 05:41:46 +08:00
|
|
|
off_t offset;
|
2010-10-16 06:48:33 +08:00
|
|
|
lldb_private::ConstString name;
|
2010-07-03 09:35:46 +08:00
|
|
|
|
2010-08-31 06:17:16 +08:00
|
|
|
if (!m_decl_map->GetStructElement (decl, value, offset, name, element_index))
|
2010-07-14 05:41:46 +08:00
|
|
|
return false;
|
2010-07-03 09:35:46 +08:00
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf(" \"%s\" [\"%s\"] (\"%s\") placed at %d",
|
2010-08-12 09:56:52 +08:00
|
|
|
value->getName().str().c_str(),
|
2010-10-16 06:48:33 +08:00
|
|
|
name.GetCString(),
|
2010-07-14 05:41:46 +08:00
|
|
|
PrintValue(value, true).c_str(),
|
|
|
|
offset);
|
|
|
|
|
|
|
|
ConstantInt *offset_int(ConstantInt::getSigned(offset_type, offset));
|
2010-11-18 07:00:36 +08:00
|
|
|
GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(argument, offset_int, "", FirstEntryInstruction);
|
|
|
|
BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", FirstEntryInstruction);
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-07-15 07:40:29 +08:00
|
|
|
if (Constant *constant = dyn_cast<Constant>(value))
|
2010-11-18 07:00:36 +08:00
|
|
|
UnfoldConstant(constant, bit_cast, FirstEntryInstruction);
|
2010-07-15 07:40:29 +08:00
|
|
|
else
|
|
|
|
value->replaceAllUsesWith(bit_cast);
|
2010-11-03 07:51:17 +08:00
|
|
|
|
|
|
|
if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
|
|
|
|
var->eraseFromParent();
|
2010-07-03 09:35:46 +08:00
|
|
|
}
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf("Total structure [align %d, size %d]", alignment, size);
|
|
|
|
|
2010-07-03 09:35:46 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IRForTarget::runOnModule(Module &M)
|
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-07-03 09:35:46 +08:00
|
|
|
|
This is a major refactoring of the expression parser.
The goal is to separate the parser's data from the data
belonging to the parser's clients. This allows clients
to use the parser to obtain (for example) a JIT compiled
function or some DWARF code, and then discard the parser
state.
Previously, parser state was held in ClangExpression and
used liberally by ClangFunction, which inherited from
ClangExpression. The main effects of this refactoring
are:
- reducing ClangExpression to an abstract class that
declares methods that any client must expose to the
expression parser,
- moving the code specific to implementing the "expr"
command from ClangExpression and
CommandObjectExpression into ClangUserExpression,
a new class,
- moving the common parser interaction code from
ClangExpression into ClangExpressionParser, a new
class, and
- making ClangFunction rely only on
ClangExpressionParser and not depend on the
internal implementation of ClangExpression.
Side effects include:
- the compiler interaction code has been factored
out of ClangFunction and is now in an AST pass
(ASTStructExtractor),
- the header file for ClangFunction is now fully
documented,
- several bugs that only popped up when Clang was
deallocated (which never happened, since the
lifetime of the compiler was essentially infinite)
are now fixed, and
- the developer-only "call" command has been
disabled.
I have tested the expr command and the Objective-C
step-into code, which use ClangUserExpression and
ClangFunction, respectively, and verified that they
work. Please let me know if you encounter bugs or
poor documentation.
llvm-svn: 112249
2010-08-27 09:01:44 +08:00
|
|
|
Function* function = M.getFunction(StringRef(m_func_name.c_str()));
|
2010-07-03 09:35:46 +08:00
|
|
|
|
|
|
|
if (!function)
|
|
|
|
{
|
|
|
|
if (log)
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str());
|
2010-07-03 09:35:46 +08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-07-28 05:39:39 +08:00
|
|
|
Function::iterator bbi;
|
2010-07-03 09:35:46 +08:00
|
|
|
|
2010-08-12 09:56:52 +08:00
|
|
|
////////////////////////////////////////////////////////////
|
2010-10-16 06:48:33 +08:00
|
|
|
// Replace $__lldb_expr_result with a persistent variable
|
2010-08-12 09:56:52 +08:00
|
|
|
//
|
|
|
|
|
|
|
|
if (!createResultVariable(M, *function))
|
|
|
|
return false;
|
|
|
|
|
2010-11-18 07:00:36 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Fix all Objective-C constant strings to use NSStringWithCString:encoding:
|
|
|
|
//
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
{
|
|
|
|
std::string s;
|
|
|
|
raw_string_ostream oss(s);
|
|
|
|
|
|
|
|
M.print(oss, NULL);
|
|
|
|
|
|
|
|
oss.flush();
|
|
|
|
|
|
|
|
log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rewriteObjCConstStrings(M, *function))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
{
|
|
|
|
std::string s;
|
|
|
|
raw_string_ostream oss(s);
|
|
|
|
|
|
|
|
M.print(oss, NULL);
|
|
|
|
|
|
|
|
oss.flush();
|
|
|
|
|
|
|
|
log->Printf("Module after rewriting Objective-C const strings: \n\"%s\"", s.c_str());
|
|
|
|
}
|
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
//////////////////////////////////
|
|
|
|
// Run basic-block level passes
|
|
|
|
//
|
|
|
|
|
2010-07-03 09:35:46 +08:00
|
|
|
for (bbi = function->begin();
|
|
|
|
bbi != function->end();
|
|
|
|
++bbi)
|
|
|
|
{
|
2010-08-24 07:09:38 +08:00
|
|
|
if (!removeGuards(M, *bbi))
|
|
|
|
return false;
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
if (!rewritePersistentAllocs(M, *bbi))
|
2010-07-31 09:32:05 +08:00
|
|
|
return false;
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
if (!rewriteObjCSelectors(M, *bbi))
|
|
|
|
return false;
|
|
|
|
|
2010-11-08 08:31:32 +08:00
|
|
|
if (!resolveCalls(M, *bbi))
|
2010-07-14 05:41:46 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-10-01 05:18:25 +08:00
|
|
|
///////////////////////////////
|
|
|
|
// Run function-level passes
|
|
|
|
//
|
|
|
|
|
2010-11-08 08:31:32 +08:00
|
|
|
if (!resolveExternals(M, *function))
|
|
|
|
return false;
|
|
|
|
|
2010-10-01 05:18:25 +08:00
|
|
|
if (!replaceVariables(M, *function))
|
|
|
|
return false;
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
if (log)
|
|
|
|
{
|
2010-07-28 09:00:59 +08:00
|
|
|
std::string s;
|
|
|
|
raw_string_ostream oss(s);
|
|
|
|
|
|
|
|
M.print(oss, NULL);
|
|
|
|
|
|
|
|
oss.flush();
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-11-15 09:47:11 +08:00
|
|
|
log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str());
|
2010-07-03 09:35:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
IRForTarget::assignPassManager(PMStack &PMS,
|
2010-07-14 05:41:46 +08:00
|
|
|
PassManagerType T)
|
2010-07-03 09:35:46 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
PassManagerType
|
|
|
|
IRForTarget::getPotentialPassManagerType() const
|
|
|
|
{
|
|
|
|
return PMT_ModulePassManager;
|
|
|
|
}
|