This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
llvm-svn: 139772
2011-09-15 10:13:07 +08:00
//===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===//
2010-07-03 09:35:46 +08:00
//
// 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"
2013-01-02 20:20:07 +08:00
# include "llvm/IR/Constants.h"
# include "llvm/IR/DataLayout.h"
# include "llvm/IR/InstrTypes.h"
# include "llvm/IR/Instructions.h"
# include "llvm/IR/Intrinsics.h"
# include "llvm/IR/Module.h"
2015-02-13 18:49:18 +08:00
# include "llvm/IR/LegacyPassManager.h"
2012-09-25 06:25:51 +08:00
# include "llvm/Transforms/IPO.h"
2014-12-10 06:29:47 +08:00
# include "llvm/IR/Metadata.h"
2013-01-02 20:20:07 +08:00
# include "llvm/IR/ValueSymbolTable.h"
2010-07-14 05:41:46 +08:00
# include "clang/AST/ASTContext.h"
2010-07-03 09:35:46 +08:00
# include "lldb/Core/dwarf.h"
2013-03-19 08:10:07 +08:00
# include "lldb/Core/ConstString.h"
# include "lldb/Core/DataBufferHeap.h"
2010-07-03 09:35:46 +08:00
# include "lldb/Core/Log.h"
# include "lldb/Core/Scalar.h"
# include "lldb/Core/StreamString.h"
# include "lldb/Expression/ClangExpressionDeclMap.h"
2013-03-19 08:10:07 +08:00
# include "lldb/Expression/IRExecutionUnit.h"
This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
llvm-svn: 139772
2011-09-15 10:13:07 +08:00
# include "lldb/Expression/IRInterpreter.h"
2011-05-24 05:40:23 +08:00
# include "lldb/Host/Endian.h"
2011-05-07 09:06:41 +08:00
# include "lldb/Symbol/ClangASTContext.h"
2013-07-12 06:46:58 +08:00
# include "lldb/Symbol/ClangASTType.h"
[IRForTarget] Strenghten handling of alternate mangling.
Summary:
This fixes an issue with GCC generated binaries wherein an expression
with method invocations on std::string variables was failing. Such use
cases are tested in TestSTL (albeit, in a test marked with
@unittest2.expectedFailure because of other reasons).
The reason for this particular failure with GCC is that the generated
DWARF for std::basic_string<...> is incomplete, which makes clang not
to use the alternate mangling scheme. GCC correctly generates the name
of basic_string<...>:
DW_AT_name "basic_string<char, std::char_traits<char>, std::allocator<char> >"
It also lists the template parameters of basic_string correctly:
DW_TAG_template_type_parameter
DW_AT_name "_CharT"
DW_AT_type <0x0000009c>
DW_TAG_template_type_parameter
DW_AT_name "_Traits"
DW_AT_type <0x00000609>
DW_TAG_template_type_parameter
DW_AT_name "_Alloc"
DW_AT_type <0x000007fb>
However, it does not list the template parameters of std::char_traits<>.
This makes Clang feel (while parsing the expression) that the string
variable is not actually a basic_string instance, and consequently does
not use the alternate mangling scheme.
Test Plan:
dotest.py -C gcc -p TestSTL
-- See it go past the "for" loop expression successfully.
Reviewers: clayborg, spyffe
Reviewed By: clayborg, spyffe
Subscribers: tberghammer, zturner, lldb-commits
Differential Revision: http://reviews.llvm.org/D8846
llvm-svn: 234522
2015-04-10 02:48:34 +08:00
# include "lldb/Target/CPPLanguageRuntime.h"
2010-07-03 09:35:46 +08:00
# include <map>
using namespace llvm ;
2010-08-19 02:50:51 +08:00
static char ID ;
2013-03-19 08:10:07 +08:00
IRForTarget : : StaticDataAllocator : : StaticDataAllocator ( lldb_private : : IRExecutionUnit & execution_unit ) :
m_execution_unit ( execution_unit ) ,
This commit changes the way LLDB executes user
expressions.
Previously, ClangUserExpression assumed that if
there was a constant result for an expression
then it could be determined during parsing. In
particular, the IRInterpreter ran while parser
state (in particular, ClangExpressionDeclMap)
was present. This approach is flawed, because
the IRInterpreter actually is capable of using
external variables, and hence the result might
be different each run. Until now, we papered
over this flaw by re-parsing the expression each
time we ran it.
I have rewritten the IRInterpreter to be
completely independent of the ClangExpressionDeclMap.
Instead of special-casing external variable lookup,
which ties the IRInterpreter closely to LLDB,
we now interpret the exact same IR that the JIT
would see. This IR assumes that materialization
has occurred; hence the recent implementation of the
Materializer, which does not require parser state
(in the form of ClangExpressionDeclMap) to be
present.
Materialization, interpretation, and dematerialization
are now all independent of parsing. This means that
in theory we can parse expressions once and run them
many times. I have three outstanding tasks before
shutting this down:
- First, I will ensure that all of this works with
core files. Core files have a Process but do not
allow allocating memory, which currently confuses
materialization.
- Second, I will make expression breakpoint
conditions remember their ClangUserExpression and
re-use it.
- Third, I will tear out all the redundant code
(for example, materialization logic in
ClangExpressionDeclMap) that is no longer used.
While implementing this fix, I also found a bug in
IRForTarget's handling of floating-point constants.
This should be fixed.
llvm-svn: 179801
2013-04-19 06:06:33 +08:00
m_stream_string ( lldb_private : : Stream : : eBinary , execution_unit . GetAddressByteSize ( ) , execution_unit . GetByteOrder ( ) ) ,
2013-03-19 08:10:07 +08:00
m_allocation ( LLDB_INVALID_ADDRESS )
2011-05-24 05:40:23 +08:00
{
}
2013-06-29 05:44:15 +08:00
IRForTarget : : FunctionValueCache : : FunctionValueCache ( Maker const & maker ) :
m_maker ( maker ) ,
m_values ( )
{
}
IRForTarget : : FunctionValueCache : : ~ FunctionValueCache ( )
{
}
2015-02-12 08:34:25 +08:00
llvm : : Value *
IRForTarget : : FunctionValueCache : : GetValue ( llvm : : Function * function )
2014-07-07 01:54:58 +08:00
{
2013-06-29 05:44:15 +08:00
if ( ! m_values . count ( function ) )
{
llvm : : Value * ret = m_maker ( function ) ;
m_values [ function ] = ret ;
return ret ;
}
return m_values [ function ] ;
}
2015-02-12 08:34:25 +08:00
lldb : : addr_t
IRForTarget : : StaticDataAllocator : : Allocate ( )
2011-05-24 05:40:23 +08:00
{
2013-03-19 08:10:07 +08:00
lldb_private : : Error err ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( m_allocation ! = LLDB_INVALID_ADDRESS )
{
m_execution_unit . FreeNow ( m_allocation ) ;
m_allocation = LLDB_INVALID_ADDRESS ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
m_allocation = m_execution_unit . WriteNow ( ( const uint8_t * ) m_stream_string . GetData ( ) , m_stream_string . GetSize ( ) , err ) ;
return m_allocation ;
2011-05-24 05:40:23 +08:00
}
2015-02-12 08:34:25 +08:00
lldb : : TargetSP
IRForTarget : : StaticDataAllocator : : GetTarget ( )
{
return m_execution_unit . GetTarget ( ) ;
}
static llvm : : Value *
FindEntryInstruction ( llvm : : Function * function )
2013-06-29 05:44:15 +08:00
{
if ( function - > empty ( ) )
return NULL ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
return function - > getEntryBlock ( ) . getFirstNonPHIOrDbg ( ) ;
}
2010-11-19 09:05:25 +08:00
IRForTarget : : IRForTarget ( lldb_private : : ClangExpressionDeclMap * decl_map ,
bool resolve_vars ,
2013-03-19 08:10:07 +08:00
lldb_private : : IRExecutionUnit & execution_unit ,
2011-01-27 09:07:04 +08:00
lldb_private : : Stream * error_stream ,
2010-11-19 09:05:25 +08:00
const char * func_name ) :
2010-09-23 11:01:22 +08:00
ModulePass ( ID ) ,
2011-04-12 03:41:40 +08:00
m_resolve_vars ( resolve_vars ) ,
m_func_name ( func_name ) ,
2011-05-24 05:40:23 +08:00
m_module ( NULL ) ,
2011-07-20 03:48:13 +08:00
m_decl_map ( decl_map ) ,
2013-03-19 08:10:07 +08:00
m_data_allocator ( execution_unit ) ,
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 ) ,
2013-12-21 03:55:02 +08:00
m_intptr_ty ( NULL ) ,
2011-04-12 03:41:40 +08:00
m_error_stream ( error_stream ) ,
2011-05-07 09:06:41 +08:00
m_result_store ( NULL ) ,
m_result_is_pointer ( false ) ,
2013-06-29 05:44:15 +08:00
m_reloc_placeholder ( NULL ) ,
m_entry_instruction_finder ( FindEntryInstruction )
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
2014-07-07 01:54:58 +08:00
static std : : string
2010-11-19 09:05:25 +08:00
PrintValue ( const Value * value , bool truncate = false )
2010-08-11 11:57:18 +08:00
{
std : : string s ;
2012-10-13 01:34:26 +08:00
if ( value )
{
raw_string_ostream rso ( s ) ;
value - > print ( rso ) ;
rso . flush ( ) ;
if ( truncate )
s . resize ( s . length ( ) - 1 ) ;
}
2010-08-11 11:57:18 +08:00
return s ;
}
2010-10-01 05:18:25 +08:00
static std : : string
2013-07-12 06:46:58 +08:00
PrintType ( const llvm : : Type * type , bool truncate = false )
2010-10-01 05:18:25 +08:00
{
std : : string s ;
raw_string_ostream rso ( s ) ;
2010-11-19 09:05:25 +08:00
type - > print ( rso ) ;
2010-10-01 05:18:25 +08:00
rso . flush ( ) ;
if ( truncate )
s . resize ( s . length ( ) - 1 ) ;
return s ;
}
2010-07-03 09:35:46 +08:00
IRForTarget : : ~ IRForTarget ( )
{
}
2011-05-24 05:40:23 +08:00
bool
IRForTarget : : FixFunctionLinkage ( llvm : : Function & llvm_function )
{
llvm_function . setLinkage ( GlobalValue : : ExternalLinkage ) ;
2014-07-07 01:54:58 +08:00
2011-11-19 10:54:21 +08:00
std : : string name = llvm_function . getName ( ) . str ( ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
return true ;
}
2014-03-25 07:10:19 +08:00
IRForTarget : : LookupResult
2011-08-05 05:37:47 +08:00
IRForTarget : : GetFunctionAddress ( llvm : : Function * fun ,
uint64_t & fun_addr ,
lldb_private : : ConstString & name ,
Constant * * & value_ptr )
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
fun_addr = LLDB_INVALID_ADDRESS ;
name . Clear ( ) ;
value_ptr = NULL ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
if ( fun - > isIntrinsic ( ) )
{
Intrinsic : : ID intrinsic_id = ( Intrinsic : : ID ) fun - > getIntrinsicID ( ) ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
switch ( intrinsic_id )
{
default :
if ( log )
log - > Printf ( " Unresolved intrinsic \" %s \" " , Intrinsic : : getName ( intrinsic_id ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s' \n " , Intrinsic : : getName ( intrinsic_id ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2014-07-09 09:10:37 +08:00
return LookupResult : : Fail ;
2011-08-05 05:37:47 +08:00
case Intrinsic : : memcpy :
{
static lldb_private : : ConstString g_memcpy_str ( " memcpy " ) ;
name = g_memcpy_str ;
}
break ;
2011-11-16 08:20:50 +08:00
case Intrinsic : : memset :
{
static lldb_private : : ConstString g_memset_str ( " memset " ) ;
name = g_memset_str ;
}
break ;
2014-03-25 07:10:19 +08:00
case Intrinsic : : dbg_declare :
2014-04-09 08:59:41 +08:00
case Intrinsic : : dbg_value :
2014-03-25 07:10:19 +08:00
return LookupResult : : Ignore ;
2011-08-05 05:37:47 +08:00
}
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
if ( log & & name )
log - > Printf ( " Resolved intrinsic name \" %s \" " , name . GetCString ( ) ) ;
}
else
{
name . SetCStringWithLength ( fun - > getName ( ) . data ( ) , fun - > getName ( ) . size ( ) ) ;
}
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
// Find the address of the function.
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
clang : : NamedDecl * fun_decl = DeclForGlobal ( fun ) ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
if ( fun_decl )
{
2014-07-07 01:54:58 +08:00
if ( ! m_decl_map - > GetFunctionInfo ( fun_decl , fun_addr ) )
2011-08-05 05:37:47 +08:00
{
[IRForTarget] Strenghten handling of alternate mangling.
Summary:
This fixes an issue with GCC generated binaries wherein an expression
with method invocations on std::string variables was failing. Such use
cases are tested in TestSTL (albeit, in a test marked with
@unittest2.expectedFailure because of other reasons).
The reason for this particular failure with GCC is that the generated
DWARF for std::basic_string<...> is incomplete, which makes clang not
to use the alternate mangling scheme. GCC correctly generates the name
of basic_string<...>:
DW_AT_name "basic_string<char, std::char_traits<char>, std::allocator<char> >"
It also lists the template parameters of basic_string correctly:
DW_TAG_template_type_parameter
DW_AT_name "_CharT"
DW_AT_type <0x0000009c>
DW_TAG_template_type_parameter
DW_AT_name "_Traits"
DW_AT_type <0x00000609>
DW_TAG_template_type_parameter
DW_AT_name "_Alloc"
DW_AT_type <0x000007fb>
However, it does not list the template parameters of std::char_traits<>.
This makes Clang feel (while parsing the expression) that the string
variable is not actually a basic_string instance, and consequently does
not use the alternate mangling scheme.
Test Plan:
dotest.py -C gcc -p TestSTL
-- See it go past the "for" loop expression successfully.
Reviewers: clayborg, spyffe
Reviewed By: clayborg, spyffe
Subscribers: tberghammer, zturner, lldb-commits
Differential Revision: http://reviews.llvm.org/D8846
llvm-svn: 234522
2015-04-10 02:48:34 +08:00
std : : vector < lldb_private : : ConstString > alternates ;
2011-10-22 11:33:13 +08:00
bool found_it = m_decl_map - > GetFunctionAddress ( name , fun_addr ) ;
if ( ! found_it )
{
[IRForTarget] Strenghten handling of alternate mangling.
Summary:
This fixes an issue with GCC generated binaries wherein an expression
with method invocations on std::string variables was failing. Such use
cases are tested in TestSTL (albeit, in a test marked with
@unittest2.expectedFailure because of other reasons).
The reason for this particular failure with GCC is that the generated
DWARF for std::basic_string<...> is incomplete, which makes clang not
to use the alternate mangling scheme. GCC correctly generates the name
of basic_string<...>:
DW_AT_name "basic_string<char, std::char_traits<char>, std::allocator<char> >"
It also lists the template parameters of basic_string correctly:
DW_TAG_template_type_parameter
DW_AT_name "_CharT"
DW_AT_type <0x0000009c>
DW_TAG_template_type_parameter
DW_AT_name "_Traits"
DW_AT_type <0x00000609>
DW_TAG_template_type_parameter
DW_AT_name "_Alloc"
DW_AT_type <0x000007fb>
However, it does not list the template parameters of std::char_traits<>.
This makes Clang feel (while parsing the expression) that the string
variable is not actually a basic_string instance, and consequently does
not use the alternate mangling scheme.
Test Plan:
dotest.py -C gcc -p TestSTL
-- See it go past the "for" loop expression successfully.
Reviewers: clayborg, spyffe
Reviewed By: clayborg, spyffe
Subscribers: tberghammer, zturner, lldb-commits
Differential Revision: http://reviews.llvm.org/D8846
llvm-svn: 234522
2015-04-10 02:48:34 +08:00
if ( log )
log - > Printf ( " Address of function \" %s \" not found. \n " , name . GetCString ( ) ) ;
// Check for an alternate mangling for names from the standard library.
// For example, "std::basic_string<...>" has an alternate mangling scheme per
// the Itanium C++ ABI.
lldb : : ProcessSP process_sp = m_data_allocator . GetTarget ( ) - > GetProcessSP ( ) ;
2015-05-29 04:06:40 +08:00
if ( process_sp )
2011-10-22 11:33:13 +08:00
{
2015-05-29 04:06:40 +08:00
lldb_private : : CPPLanguageRuntime * cpp_runtime = process_sp - > GetCPPLanguageRuntime ( ) ;
if ( cpp_runtime & & cpp_runtime - > GetAlternateManglings ( name , alternates ) )
[IRForTarget] Strenghten handling of alternate mangling.
Summary:
This fixes an issue with GCC generated binaries wherein an expression
with method invocations on std::string variables was failing. Such use
cases are tested in TestSTL (albeit, in a test marked with
@unittest2.expectedFailure because of other reasons).
The reason for this particular failure with GCC is that the generated
DWARF for std::basic_string<...> is incomplete, which makes clang not
to use the alternate mangling scheme. GCC correctly generates the name
of basic_string<...>:
DW_AT_name "basic_string<char, std::char_traits<char>, std::allocator<char> >"
It also lists the template parameters of basic_string correctly:
DW_TAG_template_type_parameter
DW_AT_name "_CharT"
DW_AT_type <0x0000009c>
DW_TAG_template_type_parameter
DW_AT_name "_Traits"
DW_AT_type <0x00000609>
DW_TAG_template_type_parameter
DW_AT_name "_Alloc"
DW_AT_type <0x000007fb>
However, it does not list the template parameters of std::char_traits<>.
This makes Clang feel (while parsing the expression) that the string
variable is not actually a basic_string instance, and consequently does
not use the alternate mangling scheme.
Test Plan:
dotest.py -C gcc -p TestSTL
-- See it go past the "for" loop expression successfully.
Reviewers: clayborg, spyffe
Reviewed By: clayborg, spyffe
Subscribers: tberghammer, zturner, lldb-commits
Differential Revision: http://reviews.llvm.org/D8846
llvm-svn: 234522
2015-04-10 02:48:34 +08:00
{
2015-05-29 04:06:40 +08:00
for ( size_t i = 0 ; i < alternates . size ( ) ; + + i )
[IRForTarget] Strenghten handling of alternate mangling.
Summary:
This fixes an issue with GCC generated binaries wherein an expression
with method invocations on std::string variables was failing. Such use
cases are tested in TestSTL (albeit, in a test marked with
@unittest2.expectedFailure because of other reasons).
The reason for this particular failure with GCC is that the generated
DWARF for std::basic_string<...> is incomplete, which makes clang not
to use the alternate mangling scheme. GCC correctly generates the name
of basic_string<...>:
DW_AT_name "basic_string<char, std::char_traits<char>, std::allocator<char> >"
It also lists the template parameters of basic_string correctly:
DW_TAG_template_type_parameter
DW_AT_name "_CharT"
DW_AT_type <0x0000009c>
DW_TAG_template_type_parameter
DW_AT_name "_Traits"
DW_AT_type <0x00000609>
DW_TAG_template_type_parameter
DW_AT_name "_Alloc"
DW_AT_type <0x000007fb>
However, it does not list the template parameters of std::char_traits<>.
This makes Clang feel (while parsing the expression) that the string
variable is not actually a basic_string instance, and consequently does
not use the alternate mangling scheme.
Test Plan:
dotest.py -C gcc -p TestSTL
-- See it go past the "for" loop expression successfully.
Reviewers: clayborg, spyffe
Reviewed By: clayborg, spyffe
Subscribers: tberghammer, zturner, lldb-commits
Differential Revision: http://reviews.llvm.org/D8846
llvm-svn: 234522
2015-04-10 02:48:34 +08:00
{
2015-05-29 04:06:40 +08:00
const lldb_private : : ConstString & alternate_name = alternates [ i ] ;
[IRForTarget] Strenghten handling of alternate mangling.
Summary:
This fixes an issue with GCC generated binaries wherein an expression
with method invocations on std::string variables was failing. Such use
cases are tested in TestSTL (albeit, in a test marked with
@unittest2.expectedFailure because of other reasons).
The reason for this particular failure with GCC is that the generated
DWARF for std::basic_string<...> is incomplete, which makes clang not
to use the alternate mangling scheme. GCC correctly generates the name
of basic_string<...>:
DW_AT_name "basic_string<char, std::char_traits<char>, std::allocator<char> >"
It also lists the template parameters of basic_string correctly:
DW_TAG_template_type_parameter
DW_AT_name "_CharT"
DW_AT_type <0x0000009c>
DW_TAG_template_type_parameter
DW_AT_name "_Traits"
DW_AT_type <0x00000609>
DW_TAG_template_type_parameter
DW_AT_name "_Alloc"
DW_AT_type <0x000007fb>
However, it does not list the template parameters of std::char_traits<>.
This makes Clang feel (while parsing the expression) that the string
variable is not actually a basic_string instance, and consequently does
not use the alternate mangling scheme.
Test Plan:
dotest.py -C gcc -p TestSTL
-- See it go past the "for" loop expression successfully.
Reviewers: clayborg, spyffe
Reviewed By: clayborg, spyffe
Subscribers: tberghammer, zturner, lldb-commits
Differential Revision: http://reviews.llvm.org/D8846
llvm-svn: 234522
2015-04-10 02:48:34 +08:00
if ( log )
2015-05-29 04:06:40 +08:00
log - > Printf ( " Looking up address of function \" %s \" with alternate name \" %s \" " ,
[IRForTarget] Strenghten handling of alternate mangling.
Summary:
This fixes an issue with GCC generated binaries wherein an expression
with method invocations on std::string variables was failing. Such use
cases are tested in TestSTL (albeit, in a test marked with
@unittest2.expectedFailure because of other reasons).
The reason for this particular failure with GCC is that the generated
DWARF for std::basic_string<...> is incomplete, which makes clang not
to use the alternate mangling scheme. GCC correctly generates the name
of basic_string<...>:
DW_AT_name "basic_string<char, std::char_traits<char>, std::allocator<char> >"
It also lists the template parameters of basic_string correctly:
DW_TAG_template_type_parameter
DW_AT_name "_CharT"
DW_AT_type <0x0000009c>
DW_TAG_template_type_parameter
DW_AT_name "_Traits"
DW_AT_type <0x00000609>
DW_TAG_template_type_parameter
DW_AT_name "_Alloc"
DW_AT_type <0x000007fb>
However, it does not list the template parameters of std::char_traits<>.
This makes Clang feel (while parsing the expression) that the string
variable is not actually a basic_string instance, and consequently does
not use the alternate mangling scheme.
Test Plan:
dotest.py -C gcc -p TestSTL
-- See it go past the "for" loop expression successfully.
Reviewers: clayborg, spyffe
Reviewed By: clayborg, spyffe
Subscribers: tberghammer, zturner, lldb-commits
Differential Revision: http://reviews.llvm.org/D8846
llvm-svn: 234522
2015-04-10 02:48:34 +08:00
name . GetCString ( ) , alternate_name . GetCString ( ) ) ;
2015-05-29 04:06:40 +08:00
if ( ( found_it = m_decl_map - > GetFunctionAddress ( alternate_name , fun_addr ) ) )
{
if ( log )
log - > Printf ( " Found address of function \" %s \" with alternate name \" %s \" " ,
name . GetCString ( ) , alternate_name . GetCString ( ) ) ;
break ;
}
[IRForTarget] Strenghten handling of alternate mangling.
Summary:
This fixes an issue with GCC generated binaries wherein an expression
with method invocations on std::string variables was failing. Such use
cases are tested in TestSTL (albeit, in a test marked with
@unittest2.expectedFailure because of other reasons).
The reason for this particular failure with GCC is that the generated
DWARF for std::basic_string<...> is incomplete, which makes clang not
to use the alternate mangling scheme. GCC correctly generates the name
of basic_string<...>:
DW_AT_name "basic_string<char, std::char_traits<char>, std::allocator<char> >"
It also lists the template parameters of basic_string correctly:
DW_TAG_template_type_parameter
DW_AT_name "_CharT"
DW_AT_type <0x0000009c>
DW_TAG_template_type_parameter
DW_AT_name "_Traits"
DW_AT_type <0x00000609>
DW_TAG_template_type_parameter
DW_AT_name "_Alloc"
DW_AT_type <0x000007fb>
However, it does not list the template parameters of std::char_traits<>.
This makes Clang feel (while parsing the expression) that the string
variable is not actually a basic_string instance, and consequently does
not use the alternate mangling scheme.
Test Plan:
dotest.py -C gcc -p TestSTL
-- See it go past the "for" loop expression successfully.
Reviewers: clayborg, spyffe
Reviewed By: clayborg, spyffe
Subscribers: tberghammer, zturner, lldb-commits
Differential Revision: http://reviews.llvm.org/D8846
llvm-svn: 234522
2015-04-10 02:48:34 +08:00
}
}
2011-10-22 11:33:13 +08:00
}
}
2014-07-07 01:54:58 +08:00
2011-10-22 11:33:13 +08:00
if ( ! found_it )
2011-08-05 05:37:47 +08:00
{
2012-07-19 04:47:40 +08:00
lldb_private : : Mangled mangled_name ( name ) ;
2011-08-05 05:37:47 +08:00
if ( m_error_stream )
2011-10-22 11:33:13 +08:00
{
[IRForTarget] Strenghten handling of alternate mangling.
Summary:
This fixes an issue with GCC generated binaries wherein an expression
with method invocations on std::string variables was failing. Such use
cases are tested in TestSTL (albeit, in a test marked with
@unittest2.expectedFailure because of other reasons).
The reason for this particular failure with GCC is that the generated
DWARF for std::basic_string<...> is incomplete, which makes clang not
to use the alternate mangling scheme. GCC correctly generates the name
of basic_string<...>:
DW_AT_name "basic_string<char, std::char_traits<char>, std::allocator<char> >"
It also lists the template parameters of basic_string correctly:
DW_TAG_template_type_parameter
DW_AT_name "_CharT"
DW_AT_type <0x0000009c>
DW_TAG_template_type_parameter
DW_AT_name "_Traits"
DW_AT_type <0x00000609>
DW_TAG_template_type_parameter
DW_AT_name "_Alloc"
DW_AT_type <0x000007fb>
However, it does not list the template parameters of std::char_traits<>.
This makes Clang feel (while parsing the expression) that the string
variable is not actually a basic_string instance, and consequently does
not use the alternate mangling scheme.
Test Plan:
dotest.py -C gcc -p TestSTL
-- See it go past the "for" loop expression successfully.
Reviewers: clayborg, spyffe
Reviewed By: clayborg, spyffe
Subscribers: tberghammer, zturner, lldb-commits
Differential Revision: http://reviews.llvm.org/D8846
llvm-svn: 234522
2015-04-10 02:48:34 +08:00
if ( mangled_name . GetMangledName ( ) )
2013-04-24 05:48:38 +08:00
m_error_stream - > Printf ( " error: call to a function '%s' ('%s') that is not present in the target \n " ,
mangled_name . GetName ( ) . GetCString ( ) ,
mangled_name . GetMangledName ( ) . GetCString ( ) ) ;
2011-10-22 11:33:13 +08:00
else
2012-07-19 04:47:40 +08:00
m_error_stream - > Printf ( " error: call to a function '%s' that is not present in the target \n " ,
mangled_name . GetName ( ) . GetCString ( ) ) ;
2011-10-22 11:33:13 +08:00
}
2014-03-25 07:10:19 +08:00
return LookupResult : : Fail ;
2011-08-05 05:37:47 +08:00
}
}
}
2014-07-07 01:54:58 +08:00
else
2011-08-05 05:37:47 +08:00
{
if ( ! m_decl_map - > GetFunctionAddress ( name , fun_addr ) )
{
if ( log )
log - > Printf ( " Metadataless function \" %s \" had no address " , name . GetCString ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target \n " , name . GetCString ( ) ) ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
return LookupResult : : Fail ;
2011-08-05 05:37:47 +08:00
}
}
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Found \" %s \" at 0x% " PRIx64 , name . GetCString ( ) , fun_addr ) ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
return LookupResult : : Success ;
2011-08-05 05:37:47 +08:00
}
llvm : : Constant *
IRForTarget : : BuildFunctionPointer ( llvm : : Type * type ,
uint64_t ptr )
{
PointerType * fun_ptr_ty = PointerType : : getUnqual ( type ) ;
2013-12-21 03:55:02 +08:00
Constant * fun_addr_int = ConstantInt : : get ( m_intptr_ty , ptr , false ) ;
2011-08-05 05:37:47 +08:00
return ConstantExpr : : getIntToPtr ( fun_addr_int , fun_ptr_ty ) ;
}
2011-11-01 06:11:40 +08:00
void
IRForTarget : : RegisterFunctionMetadata ( LLVMContext & context ,
2014-07-07 01:54:58 +08:00
llvm : : Value * function_ptr ,
2011-11-01 06:11:40 +08:00
const char * name )
{
2014-03-11 01:24:16 +08:00
for ( llvm : : User * user : function_ptr - > users ( ) )
2011-11-01 06:11:40 +08:00
{
if ( Instruction * user_inst = dyn_cast < Instruction > ( user ) )
{
2013-06-04 04:45:54 +08:00
MDString * md_name = MDString : : get ( context , StringRef ( name ) ) ;
MDNode * metadata = MDNode : : get ( context , md_name ) ;
2011-11-01 06:11:40 +08:00
user_inst - > setMetadata ( " lldb.call.realName " , metadata ) ;
}
else
{
RegisterFunctionMetadata ( context , user , name ) ;
}
}
}
2014-07-07 01:54:58 +08:00
bool
2013-06-29 05:44:15 +08:00
IRForTarget : : ResolveFunctionPointers ( llvm : : Module & llvm_module )
2011-08-05 05:37:47 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
for ( llvm : : Module : : iterator fi = llvm_module . begin ( ) ;
fi ! = llvm_module . end ( ) ;
+ + fi )
{
Function * fun = fi ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
bool is_decl = fun - > isDeclaration ( ) ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
if ( log )
2011-11-19 10:54:21 +08:00
log - > Printf ( " Examining %s function %s " , ( is_decl ? " declaration " : " non-declaration " ) , fun - > getName ( ) . str ( ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
if ( ! is_decl )
continue ;
2014-07-07 01:54:58 +08:00
2014-03-12 03:19:16 +08:00
if ( fun - > use_empty ( ) )
2011-08-05 05:37:47 +08:00
continue ; // ignore
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
uint64_t addr = LLDB_INVALID_ADDRESS ;
lldb_private : : ConstString name ;
Constant * * value_ptr = NULL ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
LookupResult result = GetFunctionAddress ( fun ,
addr ,
name ,
value_ptr ) ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
switch ( result )
{
case LookupResult : : Fail :
return false ; // GetFunctionAddress reports its own errors
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
case LookupResult : : Ignore :
break ; // Nothing to do
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
case LookupResult : : Success :
{
Constant * value = BuildFunctionPointer ( fun - > getFunctionType ( ) , addr ) ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
RegisterFunctionMetadata ( llvm_module . getContext ( ) , fun , name . AsCString ( ) ) ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
if ( value_ptr )
* value_ptr = value ;
2013-07-24 05:34:03 +08:00
2014-03-25 07:10:19 +08:00
// If we are replacing a function with the nobuiltin attribute, it may
// be called with the builtin attribute on call sites. Remove any such
// attributes since it's illegal to have a builtin call to something
// other than a nobuiltin function.
if ( fun - > hasFnAttribute ( llvm : : Attribute : : NoBuiltin ) ) {
llvm : : Attribute builtin = llvm : : Attribute : : get ( fun - > getContext ( ) , llvm : : Attribute : : Builtin ) ;
2013-07-24 05:34:03 +08:00
2014-03-25 07:10:19 +08:00
for ( auto u : fun - > users ( ) ) {
if ( auto call = dyn_cast < CallInst > ( u ) ) {
call - > removeAttribute ( AttributeSet : : FunctionIndex , builtin ) ;
}
}
2013-07-24 05:34:03 +08:00
}
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
fun - > replaceAllUsesWith ( value ) ;
2013-07-24 05:34:03 +08:00
}
2014-03-25 07:10:19 +08:00
break ;
2013-07-24 05:34:03 +08:00
}
2011-08-05 05:37:47 +08:00
}
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
return true ;
}
This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
llvm-svn: 139772
2011-09-15 10:13:07 +08:00
2011-05-07 09:06:41 +08:00
clang : : NamedDecl *
This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
llvm-svn: 139772
2011-09-15 10:13:07 +08:00
IRForTarget : : DeclForGlobal ( const GlobalValue * global_val , Module * module )
2011-05-07 09:06:41 +08:00
{
This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
llvm-svn: 139772
2011-09-15 10:13:07 +08:00
NamedMDNode * named_metadata = module - > getNamedMetadata ( " clang.global.decl.ptrs " ) ;
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
if ( ! named_metadata )
return NULL ;
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
unsigned num_nodes = named_metadata - > getNumOperands ( ) ;
unsigned node_index ;
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
for ( node_index = 0 ;
node_index < num_nodes ;
+ + node_index )
{
2014-11-06 02:37:53 +08:00
llvm : : MDNode * metadata_node = dyn_cast < llvm : : MDNode > ( named_metadata - > getOperand ( node_index ) ) ;
2011-05-07 09:06:41 +08:00
if ( ! metadata_node )
return NULL ;
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
if ( metadata_node - > getNumOperands ( ) ! = 2 )
continue ;
2014-07-07 01:54:58 +08:00
2014-12-10 06:29:47 +08:00
if ( mdconst : : dyn_extract_or_null < GlobalValue > ( metadata_node - > getOperand ( 0 ) ) ! = global_val )
2011-05-07 09:06:41 +08:00
continue ;
2014-07-07 01:54:58 +08:00
2014-12-10 06:29:47 +08:00
ConstantInt * constant_int = mdconst : : dyn_extract < ConstantInt > ( metadata_node - > getOperand ( 1 ) ) ;
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
if ( ! constant_int )
return NULL ;
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
uintptr_t ptr = constant_int - > getZExtValue ( ) ;
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
return reinterpret_cast < clang : : NamedDecl * > ( ptr ) ;
}
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
return NULL ;
}
This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
llvm-svn: 139772
2011-09-15 10:13:07 +08:00
clang : : NamedDecl *
IRForTarget : : DeclForGlobal ( GlobalValue * global_val )
2014-07-07 01:54:58 +08:00
{
This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
llvm-svn: 139772
2011-09-15 10:13:07 +08:00
return DeclForGlobal ( global_val , m_module ) ;
}
2014-07-07 01:54:58 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : CreateResultVariable ( llvm : : Function & llvm_function )
2010-08-12 09:56:52 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2010-09-14 05:34:21 +08:00
if ( ! m_resolve_vars )
return true ;
2014-07-07 01:54:58 +08:00
2010-09-14 05:34:21 +08:00
// Find the result variable. If it doesn't exist, we can give up right here.
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
ValueSymbolTable & value_symbol_table = m_module - > getValueSymbolTable ( ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
std : : string result_name_str ;
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 ;
2014-07-07 01:54:58 +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
for ( ValueSymbolTable : : iterator vi = value_symbol_table . begin ( ) , ve = value_symbol_table . end ( ) ;
vi ! = ve ;
+ + vi )
{
2011-07-30 10:42:06 +08:00
result_name_str = vi - > first ( ) . str ( ) ;
const char * value_name = result_name_str . c_str ( ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
if ( strstr ( value_name , " $__lldb_expr_result_ptr " ) & &
2012-11-03 06:28:08 +08:00
strncmp ( value_name , " _ZGV " , 4 ) )
2011-01-13 16:53:35 +08:00
{
2011-07-30 10:42:06 +08:00
result_name = value_name ;
2011-01-13 16:53:35 +08:00
m_result_is_pointer = true ;
break ;
}
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
if ( strstr ( value_name , " $__lldb_expr_result " ) & &
2012-11-03 06:28:08 +08:00
strncmp ( value_name , " _ZGV " , 4 ) )
2010-09-29 05:13:03 +08:00
{
2011-07-30 10:42:06 +08:00
result_name = value_name ;
2011-01-13 16:53:35 +08:00
m_result_is_pointer = false ;
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
}
2014-07-07 01:54:58 +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 ( ! result_name )
2010-08-12 09:56:52 +08:00
{
if ( log )
log - > PutCString ( " Couldn't find result variable " ) ;
2014-07-07 01:54:58 +08:00
2013-10-12 03:44:23 +08:00
return true ;
2010-08-12 09:56:52 +08:00
}
2014-07-07 01:54:58 +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 ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
Value * result_value = m_module - > getNamedValue ( result_name ) ;
2014-07-07 01:54:58 +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 ( ! result_value )
{
if ( log )
log - > PutCString ( " Result variable had no data " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Result variable's name (%s) exists, but not its definition \n " , result_name ) ;
2014-07-07 01:54:58 +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
return false ;
}
2014-07-07 01:54:58 +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 ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
GlobalVariable * result_global = dyn_cast < GlobalVariable > ( result_value ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
if ( ! result_global )
{
if ( log )
log - > PutCString ( " Result variable isn't a GlobalVariable " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Result variable (%s) is defined, but is not a global variable \n " , result_name ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
clang : : NamedDecl * result_decl = DeclForGlobal ( result_global ) ;
2011-05-07 09:06:41 +08:00
if ( ! result_decl )
2010-08-12 09:56:52 +08:00
{
if ( log )
2011-05-07 09:06:41 +08:00
log - > PutCString ( " Result variable doesn't have a corresponding Decl " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
2011-05-07 09:06:41 +08:00
m_error_stream - > Printf ( " Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity \n " , result_name ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
if ( log )
2010-08-12 09:56:52 +08:00
{
2011-05-07 09:06:41 +08:00
std : : string decl_desc_str ;
raw_string_ostream decl_desc_stream ( decl_desc_str ) ;
result_decl - > print ( decl_desc_stream ) ;
decl_desc_stream . flush ( ) ;
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
log - > Printf ( " Found result decl: \" %s \" " , decl_desc_str . c_str ( ) ) ;
2010-08-12 09:56:52 +08:00
}
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
clang : : VarDecl * result_var = dyn_cast < clang : : VarDecl > ( result_decl ) ;
if ( ! result_var )
2010-08-12 09:56:52 +08:00
{
if ( log )
2011-05-07 09:06:41 +08:00
log - > PutCString ( " Result variable Decl isn't a VarDecl " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
2011-05-07 09:06:41 +08:00
m_error_stream - > Printf ( " Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable \n " , result_name ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
// Get the next available result name from m_decl_map and create the persistent
// variable for it
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
// If the result is an Lvalue, it is emitted as a pointer; see
// ASTResultSynthesizer::SynthesizeBodyResult.
2011-01-13 16:53:35 +08:00
if ( m_result_is_pointer )
{
2011-05-07 09:06:41 +08:00
clang : : QualType pointer_qual_type = result_var - > getType ( ) ;
2011-01-27 12:42:51 +08:00
const clang : : Type * pointer_type = pointer_qual_type . getTypePtr ( ) ;
2014-07-07 01:54:58 +08:00
2011-12-14 09:13:04 +08:00
const clang : : PointerType * pointer_pointertype = pointer_type - > getAs < clang : : PointerType > ( ) ;
const clang : : ObjCObjectPointerType * pointer_objcobjpointertype = pointer_type - > getAs < clang : : ObjCObjectPointerType > ( ) ;
2014-07-07 01:54:58 +08:00
2011-12-09 03:04:34 +08:00
if ( pointer_pointertype )
{
clang : : QualType element_qual_type = pointer_pointertype - > getPointeeType ( ) ;
2014-07-07 01:54:58 +08:00
2011-12-09 03:04:34 +08:00
m_result_type = lldb_private : : TypeFromParser ( element_qual_type . getAsOpaquePtr ( ) ,
& result_decl - > getASTContext ( ) ) ;
}
else if ( pointer_objcobjpointertype )
{
clang : : QualType element_qual_type = clang : : QualType ( pointer_objcobjpointertype - > getObjectType ( ) , 0 ) ;
2014-07-07 01:54:58 +08:00
2011-12-09 03:04:34 +08:00
m_result_type = lldb_private : : TypeFromParser ( element_qual_type . getAsOpaquePtr ( ) ,
& result_decl - > getASTContext ( ) ) ;
}
else
2011-01-13 16:53:35 +08:00
{
if ( log )
log - > PutCString ( " Expected result to have pointer type, but it did not " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable \n " , result_name ) ;
2014-07-07 01:54:58 +08:00
2011-01-13 16:53:35 +08:00
return false ;
}
}
else
{
This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
llvm-svn: 139772
2011-09-15 10:13:07 +08:00
m_result_type = lldb_private : : TypeFromParser ( result_var - > getType ( ) . getAsOpaquePtr ( ) ,
2011-11-18 11:28:09 +08:00
& result_decl - > getASTContext ( ) ) ;
}
2014-07-07 01:54:58 +08:00
2015-02-12 08:34:25 +08:00
lldb : : TargetSP target_sp ( m_data_allocator . GetTarget ( ) ) ;
2015-02-27 08:12:22 +08:00
lldb_private : : ExecutionContext exe_ctx ( target_sp , true ) ;
2015-02-12 08:34:25 +08:00
if ( m_result_type . GetBitSize ( exe_ctx . GetBestExecutionContextScope ( ) ) = = 0 )
2011-11-18 11:28:09 +08:00
{
lldb_private : : StreamString type_desc_stream ;
m_result_type . DumpTypeDescription ( & type_desc_stream ) ;
2014-07-07 01:54:58 +08:00
2011-11-18 11:28:09 +08:00
if ( log )
log - > Printf ( " Result type has size 0 " ) ;
2014-07-07 01:54:58 +08:00
2011-11-18 11:28:09 +08:00
if ( m_error_stream )
2014-07-07 01:54:58 +08:00
m_error_stream - > Printf ( " Error [IRForTarget]: Size of result type '%s' couldn't be determined \n " ,
2011-11-18 11:28:09 +08:00
type_desc_stream . GetData ( ) ) ;
2011-12-22 07:44:05 +08:00
return false ;
2011-01-13 16:53:35 +08:00
}
2014-07-07 01:54:58 +08:00
2011-05-07 09:06:41 +08:00
if ( log )
{
lldb_private : : StreamString type_desc_stream ;
This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
llvm-svn: 139772
2011-09-15 10:13:07 +08:00
m_result_type . DumpTypeDescription ( & type_desc_stream ) ;
2014-07-07 01:54:58 +08:00
2011-11-18 11:28:09 +08:00
log - > Printf ( " Result decl type: \" %s \" " , type_desc_stream . GetData ( ) ) ;
2011-05-07 09:06:41 +08:00
}
2014-07-07 01:54:58 +08:00
This commit changes the way LLDB executes user
expressions.
Previously, ClangUserExpression assumed that if
there was a constant result for an expression
then it could be determined during parsing. In
particular, the IRInterpreter ran while parser
state (in particular, ClangExpressionDeclMap)
was present. This approach is flawed, because
the IRInterpreter actually is capable of using
external variables, and hence the result might
be different each run. Until now, we papered
over this flaw by re-parsing the expression each
time we ran it.
I have rewritten the IRInterpreter to be
completely independent of the ClangExpressionDeclMap.
Instead of special-casing external variable lookup,
which ties the IRInterpreter closely to LLDB,
we now interpret the exact same IR that the JIT
would see. This IR assumes that materialization
has occurred; hence the recent implementation of the
Materializer, which does not require parser state
(in the form of ClangExpressionDeclMap) to be
present.
Materialization, interpretation, and dematerialization
are now all independent of parsing. This means that
in theory we can parse expressions once and run them
many times. I have three outstanding tasks before
shutting this down:
- First, I will ensure that all of this works with
core files. Core files have a Process but do not
allow allocating memory, which currently confuses
materialization.
- Second, I will make expression breakpoint
conditions remember their ClangUserExpression and
re-use it.
- Third, I will tear out all the redundant code
(for example, materialization logic in
ClangExpressionDeclMap) that is no longer used.
While implementing this fix, I also found a bug in
IRForTarget's handling of floating-point constants.
This should be fixed.
llvm-svn: 179801
2013-04-19 06:06:33 +08:00
m_result_name = lldb_private : : ConstString ( " $RESULT_NAME " ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
if ( log )
2013-03-15 02:31:44 +08:00
log - > Printf ( " Creating a new result global: \" %s \" with size 0x% " PRIx64 ,
2011-11-18 11:28:09 +08:00
m_result_name . GetCString ( ) ,
2015-01-28 08:07:51 +08:00
m_result_type . GetByteSize ( nullptr ) ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
// Construct a new result global and set up its metadata
2014-07-07 01:54:58 +08:00
GlobalVariable * new_result_global = new GlobalVariable ( ( * m_module ) ,
2010-08-12 09:56:52 +08:00
result_global - > getType ( ) - > getElementType ( ) ,
false , /* not constant */
GlobalValue : : ExternalLinkage ,
NULL , /* no initializer */
2011-01-13 16:53:35 +08:00
m_result_name . GetCString ( ) ) ;
2014-07-07 01:54:58 +08:00
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.
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
ConstantInt * new_constant_int = ConstantInt : : get ( llvm : : Type : : getInt64Ty ( m_module - > getContext ( ) ) ,
2011-05-07 09:06:41 +08:00
reinterpret_cast < uint64_t > ( result_decl ) ,
2010-08-12 09:56:52 +08:00
false ) ;
2014-07-07 01:54:58 +08:00
2014-12-10 06:29:47 +08:00
llvm : : Metadata * values [ 2 ] ;
values [ 0 ] = ConstantAsMetadata : : get ( new_result_global ) ;
values [ 1 ] = ConstantAsMetadata : : get ( new_constant_int ) ;
2014-07-07 01:54:58 +08:00
2014-12-10 06:29:47 +08:00
ArrayRef < Metadata * > value_ref ( values , 2 ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
MDNode * persistent_global_md = MDNode : : get ( m_module - > getContext ( ) , value_ref ) ;
NamedMDNode * named_metadata = m_module - > getNamedMetadata ( " clang.global.decl.ptrs " ) ;
2010-08-12 09:56:52 +08:00
named_metadata - > addOperand ( persistent_global_md ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
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 ( ) ) ;
2014-07-07 01:54:58 +08:00
2014-03-12 03:19:16 +08:00
if ( result_global - > use_empty ( ) )
2010-09-08 06:43:19 +08:00
{
// We need to synthesize a store for this variable, because otherwise
// there's nothing to put into its equivalent persistent variable.
2014-07-07 01:54:58 +08:00
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 ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-09-08 06:43:19 +08:00
if ( ! first_entry_instruction )
return false ;
2014-07-07 01:54:58 +08:00
2010-09-08 06:43:19 +08:00
if ( ! result_global - > hasInitializer ( ) )
{
if ( log )
log - > Printf ( " Couldn't find initializer for unused variable " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer \n " , result_name ) ;
2014-07-07 01:54:58 +08:00
2010-09-08 06:43:19 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-09-08 06:43:19 +08:00
Constant * initializer = result_global - > getInitializer ( ) ;
2014-07-07 01:54:58 +08:00
2011-02-05 10:28:58 +08:00
StoreInst * synthesized_store = new StoreInst ( initializer ,
new_result_global ,
first_entry_instruction ) ;
2014-07-07 01:54:58 +08:00
2010-09-08 06:43:19 +08:00
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 ) ;
}
2014-07-07 01:54:58 +08:00
This commit changes the way LLDB executes user
expressions.
Previously, ClangUserExpression assumed that if
there was a constant result for an expression
then it could be determined during parsing. In
particular, the IRInterpreter ran while parser
state (in particular, ClangExpressionDeclMap)
was present. This approach is flawed, because
the IRInterpreter actually is capable of using
external variables, and hence the result might
be different each run. Until now, we papered
over this flaw by re-parsing the expression each
time we ran it.
I have rewritten the IRInterpreter to be
completely independent of the ClangExpressionDeclMap.
Instead of special-casing external variable lookup,
which ties the IRInterpreter closely to LLDB,
we now interpret the exact same IR that the JIT
would see. This IR assumes that materialization
has occurred; hence the recent implementation of the
Materializer, which does not require parser state
(in the form of ClangExpressionDeclMap) to be
present.
Materialization, interpretation, and dematerialization
are now all independent of parsing. This means that
in theory we can parse expressions once and run them
many times. I have three outstanding tasks before
shutting this down:
- First, I will ensure that all of this works with
core files. Core files have a Process but do not
allow allocating memory, which currently confuses
materialization.
- Second, I will make expression breakpoint
conditions remember their ClangUserExpression and
re-use it.
- Third, I will tear out all the redundant code
(for example, materialization logic in
ClangExpressionDeclMap) that is no longer used.
While implementing this fix, I also found a bug in
IRForTarget's handling of floating-point constants.
This should be fixed.
llvm-svn: 179801
2013-04-19 06:06:33 +08:00
if ( ! m_decl_map - > AddPersistentVariable ( result_decl ,
2014-07-07 01:54:58 +08:00
m_result_name ,
This commit changes the way LLDB executes user
expressions.
Previously, ClangUserExpression assumed that if
there was a constant result for an expression
then it could be determined during parsing. In
particular, the IRInterpreter ran while parser
state (in particular, ClangExpressionDeclMap)
was present. This approach is flawed, because
the IRInterpreter actually is capable of using
external variables, and hence the result might
be different each run. Until now, we papered
over this flaw by re-parsing the expression each
time we ran it.
I have rewritten the IRInterpreter to be
completely independent of the ClangExpressionDeclMap.
Instead of special-casing external variable lookup,
which ties the IRInterpreter closely to LLDB,
we now interpret the exact same IR that the JIT
would see. This IR assumes that materialization
has occurred; hence the recent implementation of the
Materializer, which does not require parser state
(in the form of ClangExpressionDeclMap) to be
present.
Materialization, interpretation, and dematerialization
are now all independent of parsing. This means that
in theory we can parse expressions once and run them
many times. I have three outstanding tasks before
shutting this down:
- First, I will ensure that all of this works with
core files. Core files have a Process but do not
allow allocating memory, which currently confuses
materialization.
- Second, I will make expression breakpoint
conditions remember their ClangUserExpression and
re-use it.
- Third, I will tear out all the redundant code
(for example, materialization logic in
ClangExpressionDeclMap) that is no longer used.
While implementing this fix, I also found a bug in
IRForTarget's handling of floating-point constants.
This should be fixed.
llvm-svn: 179801
2013-04-19 06:06:33 +08:00
m_result_type ,
true ,
m_result_is_pointer ) )
return false ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
result_global - > eraseFromParent ( ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
return true ;
}
2013-06-29 05:44:15 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : RewriteObjCConstString ( llvm : : GlobalVariable * ns_str ,
2013-06-29 05:44:15 +08:00
llvm : : GlobalVariable * cstr )
2010-11-18 07:00:36 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
Type * ns_str_ty = ns_str - > getType ( ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
Type * i8_ptr_ty = Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ;
Type * i32_ty = Type : : getInt32Ty ( m_module - > getContext ( ) ) ;
Type * i8_ty = Type : : getInt8Ty ( m_module - > getContext ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! m_CFStringCreateWithBytes )
{
lldb : : addr_t CFStringCreateWithBytes_addr ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
static lldb_private : : ConstString g_CFStringCreateWithBytes_str ( " CFStringCreateWithBytes " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! m_decl_map - > GetFunctionAddress ( g_CFStringCreateWithBytes_str , CFStringCreateWithBytes_addr ) )
{
if ( log )
log - > PutCString ( " Couldn't find CFStringCreateWithBytes in the target " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Found CFStringCreateWithBytes at 0x% " PRIx64 , CFStringCreateWithBytes_addr ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
// 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
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
Type * arg_type_array [ 5 ] ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
arg_type_array [ 0 ] = i8_ptr_ty ;
arg_type_array [ 1 ] = i8_ptr_ty ;
2013-12-21 03:55:02 +08:00
arg_type_array [ 2 ] = m_intptr_ty ;
2011-07-30 10:42:06 +08:00
arg_type_array [ 3 ] = i32_ty ;
arg_type_array [ 4 ] = i8_ty ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
ArrayRef < Type * > CFSCWB_arg_types ( arg_type_array , 5 ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
llvm : : Type * CFSCWB_ty = FunctionType : : get ( ns_str_ty , CFSCWB_arg_types , false ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
// Build the constant containing the pointer to the function
PointerType * CFSCWB_ptr_ty = PointerType : : getUnqual ( CFSCWB_ty ) ;
2013-12-21 03:55:02 +08:00
Constant * CFSCWB_addr_int = ConstantInt : : get ( m_intptr_ty , CFStringCreateWithBytes_addr , false ) ;
2010-11-18 07:00:36 +08:00
m_CFStringCreateWithBytes = ConstantExpr : : getIntToPtr ( CFSCWB_addr_int , CFSCWB_ptr_ty ) ;
}
2014-07-07 01:54:58 +08:00
2012-02-09 11:22:41 +08:00
ConstantDataSequential * string_array = NULL ;
2014-07-07 01:54:58 +08:00
2011-02-11 06:17:53 +08:00
if ( cstr )
2012-02-09 11:22:41 +08:00
string_array = dyn_cast < ConstantDataSequential > ( cstr - > getInitializer ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
Constant * alloc_arg = Constant : : getNullValue ( i8_ptr_ty ) ;
2011-02-11 06:17:53 +08:00
Constant * bytes_arg = cstr ? ConstantExpr : : getBitCast ( cstr , i8_ptr_ty ) : Constant : : getNullValue ( i8_ptr_ty ) ;
2013-12-21 03:55:02 +08:00
Constant * numBytes_arg = ConstantInt : : get ( m_intptr_ty , cstr ? string_array - > getNumElements ( ) - 1 : 0 , false ) ;
2010-11-18 07:00:36 +08:00
Constant * encoding_arg = ConstantInt : : get ( i32_ty , 0x0600 , false ) ; /* 0x0600 is kCFStringEncodingASCII */
Constant * isExternal_arg = ConstantInt : : get ( i8_ty , 0x0 , false ) ; /* 0x0 is false */
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
Value * argument_array [ 5 ] ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
argument_array [ 0 ] = alloc_arg ;
argument_array [ 1 ] = bytes_arg ;
argument_array [ 2 ] = numBytes_arg ;
argument_array [ 3 ] = encoding_arg ;
argument_array [ 4 ] = isExternal_arg ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
ArrayRef < Value * > CFSCWB_arguments ( argument_array , 5 ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
FunctionValueCache CFSCWB_Caller ( [ this , & CFSCWB_arguments ] ( llvm : : Function * function ) - > llvm : : Value * {
return CallInst : : Create ( m_CFStringCreateWithBytes ,
CFSCWB_arguments ,
" CFStringCreateWithBytes " ,
llvm : : cast < Instruction > ( m_entry_instruction_finder . GetValue ( function ) ) ) ;
} ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! UnfoldConstant ( ns_str , CFSCWB_Caller , m_entry_instruction_finder ) )
2010-11-18 07:00:36 +08:00
{
if ( log )
log - > PutCString ( " Couldn't replace the NSString with the result of the call " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Couldn't replace an Objective-C constant string with a dynamic string \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-19 09:05:25 +08:00
ns_str - > eraseFromParent ( ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return true ;
}
bool
2013-06-29 05:44:15 +08:00
IRForTarget : : RewriteObjCConstStrings ( )
2010-11-18 07:00:36 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
ValueSymbolTable & value_symbol_table = m_module - > getValueSymbolTable ( ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
for ( ValueSymbolTable : : iterator vi = value_symbol_table . begin ( ) , ve = value_symbol_table . end ( ) ;
vi ! = ve ;
+ + vi )
{
2011-07-30 10:42:06 +08:00
std : : string value_name = vi - > first ( ) . str ( ) ;
const char * value_name_cstr = value_name . c_str ( ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
if ( strstr ( value_name_cstr , " _unnamed_cfstring_ " ) )
2010-11-18 07:00:36 +08:00
{
Value * nsstring_value = vi - > second ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
GlobalVariable * nsstring_global = dyn_cast < GlobalVariable > ( nsstring_value ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! nsstring_global )
{
if ( log )
log - > PutCString ( " NSString variable is not a GlobalVariable " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string is not a global variable \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! nsstring_global - > hasInitializer ( ) )
{
if ( log )
log - > PutCString ( " NSString variable does not have an initializer " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string does not have an initializer \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
ConstantStruct * nsstring_struct = dyn_cast < ConstantStruct > ( nsstring_global - > getInitializer ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! nsstring_struct )
{
if ( log )
log - > PutCString ( " NSString variable's initializer is not a ConstantStruct " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string is not a structure constant \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
// We expect the following structure:
//
// struct {
// int *isa;
// int flags;
// char *str;
// long length;
// };
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
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 ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: The struct for an Objective-C constant string is not as expected \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
Constant * nsstring_member = nsstring_struct - > getOperand ( 2 ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! nsstring_member )
{
if ( log )
log - > PutCString ( " NSString initializer's str element was empty " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
ConstantExpr * nsstring_expr = dyn_cast < ConstantExpr > ( nsstring_member ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! nsstring_expr )
{
if ( log )
log - > PutCString ( " NSString initializer's str element is not a ConstantExpr " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
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 ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
Constant * nsstring_cstr = nsstring_expr - > getOperand ( 0 ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
GlobalVariable * cstr_global = dyn_cast < GlobalVariable > ( nsstring_cstr ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! cstr_global )
{
if ( log )
log - > PutCString ( " NSString initializer's str element is not a GlobalVariable " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a global \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! cstr_global - > hasInitializer ( ) )
{
if ( log )
log - > PutCString ( " NSString initializer's str element does not have an initializer " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to initialized data \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2011-02-11 06:17:53 +08:00
/*
2010-11-18 07:00:36 +08:00
if ( ! cstr_array )
{
if ( log )
log - > PutCString ( " NSString initializer's str element is not a ConstantArray " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to an array \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! cstr_array - > isCString ( ) )
{
if ( log )
log - > PutCString ( " NSString initializer's str element is not a C string array " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a C string \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2011-02-11 06:17:53 +08:00
*/
2014-07-07 01:54:58 +08:00
2012-02-09 11:22:41 +08:00
ConstantDataArray * cstr_array = dyn_cast < ConstantDataArray > ( cstr_global - > getInitializer ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( log )
2011-02-11 06:17:53 +08:00
{
if ( cstr_array )
2012-02-09 11:22:41 +08:00
log - > Printf ( " Found NSString constant %s, which contains \" %s \" " , value_name_cstr , cstr_array - > getAsString ( ) . str ( ) . c_str ( ) ) ;
2011-02-11 06:17:53 +08:00
else
2011-07-30 10:42:06 +08:00
log - > Printf ( " Found NSString constant %s, which contains \" \" " , value_name_cstr ) ;
2011-02-11 06:17:53 +08:00
}
2014-07-07 01:54:58 +08:00
2011-02-11 06:17:53 +08:00
if ( ! cstr_array )
cstr_global = NULL ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! RewriteObjCConstString ( nsstring_global , cstr_global ) )
2014-07-07 01:54:58 +08:00
{
2010-11-18 07:00:36 +08:00
if ( log )
log - > PutCString ( " Error rewriting the constant string " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
// We don't print an error message here because RewriteObjCConstString has done so for us.
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
}
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
for ( ValueSymbolTable : : iterator vi = value_symbol_table . begin ( ) , ve = value_symbol_table . end ( ) ;
vi ! = ve ;
+ + vi )
{
2011-07-30 10:42:06 +08:00
std : : string value_name = vi - > first ( ) . str ( ) ;
const char * value_name_cstr = value_name . c_str ( ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
if ( ! strcmp ( value_name_cstr , " __CFConstantStringClassReference " ) )
2010-11-18 07:00:36 +08:00
{
GlobalVariable * gv = dyn_cast < GlobalVariable > ( vi - > second ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! gv )
{
if ( log )
log - > PutCString ( " __CFConstantStringClassReference is not a global variable " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object \n " ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
gv - > eraseFromParent ( ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
break ;
}
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return true ;
}
2010-11-19 09:05:25 +08:00
static bool IsObjCSelectorRef ( Value * value )
2010-07-31 09:32:05 +08:00
{
2010-11-19 09:05:25 +08:00
GlobalVariable * global_variable = dyn_cast < GlobalVariable > ( value ) ;
2014-07-07 01:54:58 +08:00
2014-11-11 05:45:59 +08:00
if ( ! global_variable | | ! global_variable - > hasName ( ) | | ! global_variable - > getName ( ) . startswith ( " OBJC_SELECTOR_REFERENCES_ " ) )
2010-07-31 09:32:05 +08:00
return false ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
return true ;
}
2011-01-27 09:07:04 +08:00
// This function does not report errors; its callers are responsible.
2014-07-07 01:54:58 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : RewriteObjCSelector ( Instruction * selector_load )
2010-07-31 09:32:05 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-31 09:32:05 +08:00
LoadInst * load = dyn_cast < LoadInst > ( selector_load ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
if ( ! load )
return false ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
// Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as
//
2014-11-11 05:48:12 +08:00
// %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*>
2010-07-31 09:32:05 +08:00
// %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*>
//
// where %obj is the object pointer and %tmp is the selector.
2014-07-07 01:54:58 +08:00
//
2014-11-11 05:48:12 +08:00
// @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_".
2010-11-19 09:05:25 +08:00
// @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string.
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
// Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
GlobalVariable * _objc_selector_references_ = dyn_cast < GlobalVariable > ( load - > getPointerOperand ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
if ( ! _objc_selector_references_ | | ! _objc_selector_references_ - > hasInitializer ( ) )
return false ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
Constant * osr_initializer = _objc_selector_references_ - > getInitializer ( ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
ConstantExpr * osr_initializer_expr = dyn_cast < ConstantExpr > ( osr_initializer ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
if ( ! osr_initializer_expr | | osr_initializer_expr - > getOpcode ( ) ! = Instruction : : GetElementPtr )
return false ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
Value * osr_initializer_base = osr_initializer_expr - > getOperand ( 0 ) ;
if ( ! osr_initializer_base )
return false ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
// Find the string's initializer (a ConstantArray) and get the string from it
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
GlobalVariable * _objc_meth_var_name_ = dyn_cast < GlobalVariable > ( osr_initializer_base ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
if ( ! _objc_meth_var_name_ | | ! _objc_meth_var_name_ - > hasInitializer ( ) )
return false ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
Constant * omvn_initializer = _objc_meth_var_name_ - > getInitializer ( ) ;
2012-02-09 11:22:41 +08:00
ConstantDataArray * omvn_initializer_array = dyn_cast < ConstantDataArray > ( omvn_initializer ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
if ( ! omvn_initializer_array - > isString ( ) )
return false ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
std : : string omvn_initializer_string = omvn_initializer_array - > getAsString ( ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
if ( log )
2010-11-15 09:47:11 +08:00
log - > Printf ( " Found Objective-C selector reference \" %s \" " , omvn_initializer_string . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
// Construct a call to sel_registerName
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
if ( ! m_sel_registerName )
{
2010-11-15 09:47:11 +08:00
lldb : : addr_t sel_registerName_addr ;
2014-07-07 01:54:58 +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 ;
2014-07-07 01:54:58 +08:00
2010-10-26 08:31:56 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Found sel_registerName at 0x% " PRIx64 , sel_registerName_addr ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
// Build the function type: struct objc_selector *sel_registerName(uint8_t*)
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
// The below code would be "more correct," but in actuality what's required is uint8_t*
2011-05-24 05:40:23 +08:00
//Type *sel_type = StructType::get(m_module->getContext());
2010-07-31 09:32:05 +08:00
//Type *sel_ptr_type = PointerType::getUnqual(sel_type);
2011-07-30 10:42:06 +08:00
Type * sel_ptr_type = Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
Type * type_array [ 1 ] ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
type_array [ 0 ] = llvm : : Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
ArrayRef < Type * > srN_arg_types ( type_array , 1 ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
llvm : : Type * srN_type = FunctionType : : get ( sel_ptr_type , srN_arg_types , false ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
// Build the constant containing the pointer to the function
PointerType * srN_ptr_ty = PointerType : : getUnqual ( srN_type ) ;
2013-12-21 03:55:02 +08:00
Constant * srN_addr_int = ConstantInt : : get ( m_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 ) ;
}
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
Value * argument_array [ 1 ] ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
Constant * omvn_pointer = ConstantExpr : : getBitCast ( _objc_meth_var_name_ , Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
argument_array [ 0 ] = omvn_pointer ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
ArrayRef < Value * > srN_arguments ( argument_array , 1 ) ;
2014-07-07 01:54:58 +08:00
CallInst * srN_call = CallInst : : Create ( m_sel_registerName ,
2011-07-30 10:42:06 +08:00
srN_arguments ,
2010-11-18 07:00:36 +08:00
" sel_registerName " ,
2010-07-31 09:32:05 +08:00
selector_load ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
// Replace the load with the call in all users
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
selector_load - > replaceAllUsesWith ( srN_call ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
selector_load - > eraseFromParent ( ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
return true ;
}
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : RewriteObjCSelectors ( BasicBlock & basic_block )
2010-07-31 09:32:05 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-31 09:32:05 +08:00
BasicBlock : : iterator ii ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
typedef SmallVector < Instruction * , 2 > InstrList ;
typedef InstrList : : iterator InstrIterator ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
InstrList selector_loads ;
2014-07-07 01:54:58 +08:00
2010-11-19 09:05:25 +08:00
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
2010-07-31 09:32:05 +08:00
+ + ii )
{
Instruction & inst = * ii ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
if ( LoadInst * load = dyn_cast < LoadInst > ( & inst ) )
2010-11-19 09:05:25 +08:00
if ( IsObjCSelectorRef ( load - > getPointerOperand ( ) ) )
2010-07-31 09:32:05 +08:00
selector_loads . push_back ( & inst ) ;
}
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
InstrIterator iter ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
for ( iter = selector_loads . begin ( ) ;
iter ! = selector_loads . end ( ) ;
+ + iter )
{
2011-05-24 05:40:23 +08:00
if ( ! RewriteObjCSelector ( * iter ) )
2010-07-31 09:32:05 +08:00
{
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference \n " ) ;
2014-07-07 01:54:58 +08:00
The implementation of categories is now synchronization safe
Code cleanup:
- The Format Manager implementation is now split between two files: FormatClasses.{h|cpp} where the
actual formatter classes (ValueFormat, SummaryFormat, ...) are implemented and
FormatManager.{h|cpp} where the infrastructure classes (FormatNavigator, FormatManager, ...)
are contained. The wrapper code always remains in Debugger.{h|cpp}
- Several leftover fields, methods and comments from previous design choices have been removed
type category subcommands (enable, disable, delete) now can take a list of category names as input
- for type category enable, saying "enable A B C" is the same as saying
enable C
enable B
enable A
(the ordering is relevant in enabling categories, and it is expected that a user typing
enable A B C wants to look into category A, then into B, then into C and not the other
way round)
- for the other two commands, the order is not really relevant (however, the same inverted ordering
is used for consistency)
llvm-svn: 135494
2011-07-20 02:03:25 +08:00
if ( log )
2010-07-31 09:32:05 +08:00
log - > PutCString ( " Couldn't rewrite a reference to an Objective-C selector " ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
return false ;
}
}
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
return true ;
}
2011-01-27 09:07:04 +08:00
// This function does not report errors; its callers are responsible.
2014-07-07 01:54:58 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : RewritePersistentAlloc ( llvm : : Instruction * persistent_alloc )
2010-08-11 11:57:18 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2011-01-14 05:23:32 +08:00
2010-08-11 11:57:18 +08:00
AllocaInst * alloc = dyn_cast < AllocaInst > ( persistent_alloc ) ;
2014-07-07 01:54:58 +08:00
2014-11-12 09:59:53 +08:00
MDNode * alloc_md = alloc - > getMetadata ( " clang.decl.ptr " ) ;
2010-08-11 11:57:18 +08:00
if ( ! alloc_md | | ! alloc_md - > getNumOperands ( ) )
return false ;
2014-07-07 01:54:58 +08:00
2014-12-10 06:29:47 +08:00
ConstantInt * constant_int = mdconst : : dyn_extract < ConstantInt > ( alloc_md - > getOperand ( 0 ) ) ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
if ( ! constant_int )
return false ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
// We attempt to register this as a new persistent variable with the DeclMap.
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
uintptr_t ptr = constant_int - > getZExtValue ( ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
clang : : VarDecl * decl = reinterpret_cast < clang : : VarDecl * > ( ptr ) ;
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
lldb_private : : TypeFromParser result_decl_type ( decl - > getType ( ) . getAsOpaquePtr ( ) ,
& decl - > getASTContext ( ) ) ;
2014-07-07 01:54:58 +08:00
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 ( ) ) ;
2011-01-13 16:53:35 +08:00
if ( ! m_decl_map - > AddPersistentVariable ( decl , persistent_variable_name , result_decl_type , false , false ) )
2010-08-11 11:57:18 +08:00
return false ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
GlobalVariable * persistent_global = new GlobalVariable ( ( * m_module ) ,
2011-01-14 05:23:32 +08:00
alloc - > getType ( ) ,
2010-08-11 11:57:18 +08:00
false , /* not constant */
GlobalValue : : ExternalLinkage ,
NULL , /* no initializer */
alloc - > getName ( ) . str ( ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
// 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.
2014-07-07 01:54:58 +08:00
2012-07-04 09:26:26 +08:00
NamedMDNode * named_metadata = m_module - > getOrInsertNamedMetadata ( " clang.global.decl.ptrs " ) ;
2014-07-07 01:54:58 +08:00
2014-12-10 06:29:47 +08:00
llvm : : Metadata * values [ 2 ] ;
values [ 0 ] = ConstantAsMetadata : : get ( persistent_global ) ;
values [ 1 ] = ConstantAsMetadata : : get ( constant_int ) ;
2014-07-07 01:54:58 +08:00
2014-12-10 06:29:47 +08:00
ArrayRef < llvm : : Metadata * > value_ref ( values , 2 ) ;
2010-08-11 11:57:18 +08:00
2011-05-24 05:40:23 +08:00
MDNode * persistent_global_md = MDNode : : get ( m_module - > getContext ( ) , value_ref ) ;
2010-08-11 11:57:18 +08:00
named_metadata - > addOperand ( persistent_global_md ) ;
2014-07-07 01:54:58 +08:00
2011-01-14 05:23:32 +08:00
// Now, since the variable is a pointer variable, we will drop in a load of that
// pointer variable.
2014-07-07 01:54:58 +08:00
2011-01-14 05:23:32 +08:00
LoadInst * persistent_load = new LoadInst ( persistent_global , " " , alloc ) ;
2014-07-07 01:54:58 +08:00
2011-01-14 05:23:32 +08:00
if ( log )
log - > Printf ( " Replacing \" %s \" with \" %s \" " ,
PrintValue ( alloc ) . c_str ( ) ,
PrintValue ( persistent_load ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-01-14 05:23:32 +08:00
alloc - > replaceAllUsesWith ( persistent_load ) ;
2010-08-11 11:57:18 +08:00
alloc - > eraseFromParent ( ) ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
return true ;
}
2014-07-07 01:54:58 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : RewritePersistentAllocs ( llvm : : BasicBlock & basic_block )
2010-08-11 11:57:18 +08:00
{
2010-09-14 05:34:21 +08:00
if ( ! m_resolve_vars )
return true ;
2014-07-07 01:54:58 +08:00
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
BasicBlock : : iterator ii ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
typedef SmallVector < Instruction * , 2 > InstrList ;
typedef InstrList : : iterator InstrIterator ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
InstrList pvar_allocs ;
2014-07-07 01:54:58 +08:00
2010-11-19 09:05:25 +08:00
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
2010-08-11 11:57:18 +08:00
+ + ii )
{
Instruction & inst = * ii ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
if ( AllocaInst * alloc = dyn_cast < AllocaInst > ( & inst ) )
2011-01-22 06:30:25 +08:00
{
llvm : : StringRef alloc_name = alloc - > getName ( ) ;
2014-07-07 01:54:58 +08:00
2011-01-22 06:30:25 +08:00
if ( alloc_name . startswith ( " $ " ) & &
! alloc_name . startswith ( " $__lldb " ) )
{
if ( alloc_name . find_first_of ( " 0123456789 " ) = = 1 )
{
if ( log )
log - > Printf ( " Rejecting a numeric persistent variable. " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names \n " ) ;
2014-07-07 01:54:58 +08:00
2011-01-22 06:30:25 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
pvar_allocs . push_back ( alloc ) ;
2011-01-22 06:30:25 +08:00
}
}
2010-08-11 11:57:18 +08:00
}
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
InstrIterator iter ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
for ( iter = pvar_allocs . begin ( ) ;
iter ! = pvar_allocs . end ( ) ;
+ + iter )
{
2011-05-24 05:40:23 +08:00
if ( ! RewritePersistentAlloc ( * iter ) )
2010-08-11 11:57:18 +08:00
{
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable \n " ) ;
2014-07-07 01:54:58 +08:00
The implementation of categories is now synchronization safe
Code cleanup:
- The Format Manager implementation is now split between two files: FormatClasses.{h|cpp} where the
actual formatter classes (ValueFormat, SummaryFormat, ...) are implemented and
FormatManager.{h|cpp} where the infrastructure classes (FormatNavigator, FormatManager, ...)
are contained. The wrapper code always remains in Debugger.{h|cpp}
- Several leftover fields, methods and comments from previous design choices have been removed
type category subcommands (enable, disable, delete) now can take a list of category names as input
- for type category enable, saying "enable A B C" is the same as saying
enable C
enable B
enable A
(the ordering is relevant in enabling categories, and it is expected that a user typing
enable A B C wants to look into category A, then into B, then into C and not the other
way round)
- for the other two commands, the order is not really relevant (however, the same inverted ordering
is used for consistency)
llvm-svn: 135494
2011-07-20 02:03:25 +08:00
if ( log )
2010-08-11 11:57:18 +08:00
log - > PutCString ( " Couldn't rewrite the creation of a persistent variable " ) ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
return false ;
}
}
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
return true ;
}
2011-10-26 02:36:40 +08:00
bool
IRForTarget : : MaterializeInitializer ( uint8_t * data , Constant * initializer )
{
if ( ! initializer )
return true ;
2014-07-07 01:54:58 +08:00
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2011-10-26 02:36:40 +08:00
if ( log & & log - > GetVerbose ( ) )
2015-04-09 04:23:52 +08:00
log - > Printf ( " MaterializeInitializer(%p, %s) " , ( void * ) data , PrintValue ( initializer ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
Type * initializer_type = initializer - > getType ( ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
if ( ConstantInt * int_initializer = dyn_cast < ConstantInt > ( initializer ) )
{
memcpy ( data , int_initializer - > getValue ( ) . getRawData ( ) , m_target_data - > getTypeStoreSize ( initializer_type ) ) ;
return true ;
}
2012-02-09 11:22:41 +08:00
else if ( ConstantDataArray * array_initializer = dyn_cast < ConstantDataArray > ( initializer ) )
2011-10-26 02:36:40 +08:00
{
if ( array_initializer - > isString ( ) )
{
std : : string array_initializer_string = array_initializer - > getAsString ( ) ;
memcpy ( data , array_initializer_string . c_str ( ) , m_target_data - > getTypeStoreSize ( initializer_type ) ) ;
}
else
{
ArrayType * array_initializer_type = array_initializer - > getType ( ) ;
Type * array_element_type = array_initializer_type - > getElementType ( ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
size_t element_size = m_target_data - > getTypeAllocSize ( array_element_type ) ;
2014-07-07 01:54:58 +08:00
2013-06-20 03:04:53 +08:00
for ( unsigned i = 0 ; i < array_initializer - > getNumOperands ( ) ; + + i )
2011-10-26 02:36:40 +08:00
{
2012-02-09 11:22:41 +08:00
Value * operand_value = array_initializer - > getOperand ( i ) ;
Constant * operand_constant = dyn_cast < Constant > ( operand_value ) ;
2014-07-07 01:54:58 +08:00
2012-02-09 11:22:41 +08:00
if ( ! operand_constant )
return false ;
2014-07-07 01:54:58 +08:00
2012-02-09 11:22:41 +08:00
if ( ! MaterializeInitializer ( data + ( i * element_size ) , operand_constant ) )
2011-10-26 02:36:40 +08:00
return false ;
}
}
return true ;
}
else if ( ConstantStruct * struct_initializer = dyn_cast < ConstantStruct > ( initializer ) )
{
StructType * struct_initializer_type = struct_initializer - > getType ( ) ;
const StructLayout * struct_layout = m_target_data - > getStructLayout ( struct_initializer_type ) ;
2013-06-20 03:04:53 +08:00
for ( unsigned i = 0 ;
2011-10-26 02:36:40 +08:00
i < struct_initializer - > getNumOperands ( ) ;
+ + i )
{
if ( ! MaterializeInitializer ( data + struct_layout - > getElementOffset ( i ) , struct_initializer - > getOperand ( i ) ) )
return false ;
}
return true ;
}
2013-04-25 03:50:12 +08:00
else if ( isa < ConstantAggregateZero > ( initializer ) )
{
memset ( data , 0 , m_target_data - > getTypeStoreSize ( initializer_type ) ) ;
return true ;
}
2011-10-26 02:36:40 +08:00
return false ;
}
bool
IRForTarget : : MaterializeInternalVariable ( GlobalVariable * global_variable )
{
if ( GlobalVariable : : isExternalLinkage ( global_variable - > getLinkage ( ) ) )
return false ;
2014-07-07 01:54:58 +08:00
2011-11-16 03:13:54 +08:00
if ( global_variable = = m_reloc_placeholder )
return true ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
uint64_t offset = m_data_allocator . GetStream ( ) . GetSize ( ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
llvm : : Type * variable_type = global_variable - > getType ( ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
Constant * initializer = global_variable - > getInitializer ( ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
llvm : : Type * initializer_type = initializer - > getType ( ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
size_t size = m_target_data - > getTypeAllocSize ( initializer_type ) ;
2012-06-09 06:20:41 +08:00
size_t align = m_target_data - > getPrefTypeAlignment ( initializer_type ) ;
2014-07-07 01:54:58 +08:00
2012-06-09 06:20:41 +08:00
const size_t mask = ( align - 1 ) ;
uint64_t aligned_offset = ( offset + mask ) & ~ mask ;
2013-03-19 08:10:07 +08:00
m_data_allocator . GetStream ( ) . PutNHex8 ( aligned_offset - offset , 0 ) ;
2012-06-09 06:20:41 +08:00
offset = aligned_offset ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
lldb_private : : DataBufferHeap data ( size , ' \0 ' ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
if ( initializer )
if ( ! MaterializeInitializer ( data . GetBytes ( ) , initializer ) )
return false ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
m_data_allocator . GetStream ( ) . Write ( data . GetBytes ( ) , data . GetByteSize ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
Constant * new_pointer = BuildRelocation ( variable_type , offset ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
global_variable - > replaceAllUsesWith ( new_pointer ) ;
global_variable - > eraseFromParent ( ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
return true ;
}
2011-01-27 09:07:04 +08:00
// This function does not report errors; its callers are responsible.
2014-07-07 01:54:58 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : MaybeHandleVariable ( Value * llvm_value_ptr )
2010-07-03 09:35:46 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2010-12-03 03:47:57 +08:00
if ( log )
2010-12-07 06:16:55 +08:00
log - > Printf ( " MaybeHandleVariable (%s) " , PrintValue ( llvm_value_ptr ) . c_str ( ) ) ;
2014-07-07 01:54:58 +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 ) ;
2011-05-24 05:40:23 +08:00
if ( ! MaybeHandleVariable ( s ) )
2010-12-03 03:47:57 +08:00
return false ;
2010-08-03 08:23:29 +08:00
}
}
2010-12-04 03:51:05 +08:00
else if ( GlobalVariable * global_variable = dyn_cast < GlobalVariable > ( llvm_value_ptr ) )
2010-07-31 09:32:05 +08:00
{
2011-10-26 02:36:40 +08:00
if ( ! GlobalValue : : isExternalLinkage ( global_variable - > getLinkage ( ) ) )
return MaterializeInternalVariable ( global_variable ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
clang : : NamedDecl * named_decl = DeclForGlobal ( global_variable ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
if ( ! named_decl )
{
2010-11-19 09:05:25 +08:00
if ( IsObjCSelectorRef ( llvm_value_ptr ) )
2010-07-31 09:32:05 +08:00
return true ;
2014-07-07 01:54:58 +08:00
2010-12-06 08:56:39 +08:00
if ( ! global_variable - > hasExternalLinkage ( ) )
return true ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
if ( log )
2010-11-15 09:47:11 +08:00
log - > Printf ( " Found global variable \" %s \" without metadata " , global_variable - > getName ( ) . str ( ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-07-31 09:32:05 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-10-16 06:48:33 +08:00
std : : string name ( named_decl - > getName ( ) . str ( ) ) ;
2014-07-07 01:54:58 +08:00
2013-07-12 06:46:58 +08:00
clang : : ValueDecl * value_decl = dyn_cast < clang : : ValueDecl > ( named_decl ) ;
if ( value_decl = = NULL )
2010-07-16 08:09:46 +08:00
return false ;
2013-07-12 06:46:58 +08:00
lldb_private : : ClangASTType clang_type ( & value_decl - > getASTContext ( ) , value_decl - > getType ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-07-08 08:39:14 +08:00
const Type * value_type = NULL ;
2013-07-12 06:46:58 +08:00
2011-01-14 05:23:32 +08:00
if ( name [ 0 ] = = ' $ ' )
2011-01-13 16:53:35 +08:00
{
// The $__lldb_expr_result name indicates the the return value has allocated as
// a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
// accesses to this static variable need to be redirected to the result of dereferencing
// a pointer that is passed in as one of the arguments.
//
// Consequently, when reporting the size of the type, we report a pointer type pointing
// to the type of $__lldb_expr_result, not the type itself.
2011-01-14 05:23:32 +08:00
//
// We also do this for any user-declared persistent variables.
2013-07-12 06:46:58 +08:00
clang_type = clang_type . GetPointerType ( ) ;
2011-01-13 16:53:35 +08:00
value_type = PointerType : : get ( global_variable - > getType ( ) , 0 ) ;
}
else
{
value_type = global_variable - > getType ( ) ;
}
2014-07-07 01:54:58 +08:00
2015-01-28 08:07:51 +08:00
const uint64_t value_size = clang_type . GetByteSize ( nullptr ) ;
2014-07-03 01:24:07 +08:00
lldb : : offset_t value_alignment = ( clang_type . GetTypeBitAlign ( ) + 7ull ) / 8ull ;
2014-07-07 01:54:58 +08:00
2010-10-01 05:18:25 +08:00
if ( log )
2013-07-12 06:46:58 +08:00
{
2014-07-03 01:24:07 +08:00
log - > Printf ( " Type of \" %s \" is [clang \" %s \" , llvm \" %s \" ] [size % " PRIu64 " , align % " PRIu64 " ] " ,
2014-07-07 01:54:58 +08:00
name . c_str ( ) ,
2013-07-12 06:46:58 +08:00
clang_type . GetQualType ( ) . getAsString ( ) . c_str ( ) ,
PrintType ( value_type ) . c_str ( ) ,
2014-07-07 01:54:58 +08:00
value_size ,
2010-10-01 05:18:25 +08:00
value_alignment ) ;
2013-07-12 06:46:58 +08:00
}
2014-07-07 01:54:58 +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 ,
2014-07-07 01:54:58 +08:00
value_size ,
2010-07-27 10:07:53 +08:00
value_alignment ) )
2011-08-02 01:41:38 +08:00
{
if ( ! global_variable - > hasExternalLinkage ( ) )
return true ;
2013-04-12 01:57:16 +08:00
else if ( HandleSymbol ( global_variable ) )
return true ;
2011-08-02 01:41:38 +08:00
else
return false ;
}
2010-07-14 05:41:46 +08:00
}
2010-12-03 11:02:31 +08:00
else if ( dyn_cast < llvm : : Function > ( llvm_value_ptr ) )
2010-12-03 03:47:57 +08:00
{
if ( log )
log - > Printf ( " Function pointers aren't handled right now " ) ;
2014-07-07 01:54:58 +08:00
2010-12-03 03:47:57 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
return true ;
}
2011-01-27 09:07:04 +08:00
// This function does not report errors; its callers are responsible.
2011-01-18 07:42:46 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : HandleSymbol ( Value * symbol )
2014-07-07 01:54:58 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2011-01-18 07:42:46 +08:00
lldb_private : : ConstString name ( symbol - > getName ( ) . str ( ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-12-01 10:04:16 +08:00
lldb : : addr_t symbol_addr = m_decl_map - > GetSymbolAddress ( name , lldb : : eSymbolTypeAny ) ;
2014-07-07 01:54:58 +08:00
2011-06-23 12:25:29 +08:00
if ( symbol_addr = = LLDB_INVALID_ADDRESS )
2011-01-18 07:42:46 +08:00
{
if ( log )
log - > Printf ( " Symbol \" %s \" had no address " , name . GetCString ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-01-18 07:42:46 +08:00
return false ;
}
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Found \" %s \" at 0x% " PRIx64 , name . GetCString ( ) , symbol_addr ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
Type * symbol_type = symbol - > getType ( ) ;
2014-07-07 01:54:58 +08:00
2013-12-21 03:55:02 +08:00
Constant * symbol_addr_int = ConstantInt : : get ( m_intptr_ty , symbol_addr , false ) ;
2014-07-07 01:54:58 +08:00
2011-01-18 07:42:46 +08:00
Value * symbol_addr_ptr = ConstantExpr : : getIntToPtr ( symbol_addr_int , symbol_type ) ;
2014-07-07 01:54:58 +08:00
2011-01-18 07:42:46 +08:00
if ( log )
log - > Printf ( " Replacing %s with %s " , PrintValue ( symbol ) . c_str ( ) , PrintValue ( symbol_addr_ptr ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-01-18 07:42:46 +08:00
symbol - > replaceAllUsesWith ( symbol_addr_ptr ) ;
2014-07-07 01:54:58 +08:00
2011-01-18 07:42:46 +08:00
return true ;
}
2010-10-06 06:26:43 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : MaybeHandleCallArguments ( CallInst * Old )
2010-10-06 06:26:43 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2010-12-03 03:47:57 +08:00
if ( log )
log - > Printf ( " MaybeHandleCallArguments(%s) " , PrintValue ( Old ) . c_str ( ) ) ;
2014-07-07 01:54:58 +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 )
2011-05-24 05:40:23 +08:00
if ( ! MaybeHandleVariable ( Old - > getArgOperand ( op_index ) ) ) // conservatively believe that this is a store
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call. \n " ) ;
2014-07-07 01:54:58 +08:00
2010-10-06 06:26:43 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2014-07-07 01:54:58 +08:00
2010-10-06 06:26:43 +08:00
return true ;
}
2011-11-02 07:38:03 +08:00
bool
IRForTarget : : HandleObjCClass ( Value * classlist_reference )
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2011-11-02 07:38:03 +08:00
GlobalVariable * global_variable = dyn_cast < GlobalVariable > ( classlist_reference ) ;
2014-07-07 01:54:58 +08:00
2011-11-02 07:38:03 +08:00
if ( ! global_variable )
return false ;
2014-07-07 01:54:58 +08:00
2011-11-02 07:38:03 +08:00
Constant * initializer = global_variable - > getInitializer ( ) ;
2014-07-07 01:54:58 +08:00
2011-11-02 07:38:03 +08:00
if ( ! initializer )
return false ;
2014-07-07 01:54:58 +08:00
2011-11-02 07:38:03 +08:00
if ( ! initializer - > hasName ( ) )
return false ;
2014-07-07 01:54:58 +08:00
2011-11-02 07:38:03 +08:00
StringRef name ( initializer - > getName ( ) ) ;
lldb_private : : ConstString name_cstr ( name . str ( ) . c_str ( ) ) ;
2011-12-04 04:02:42 +08:00
lldb : : addr_t class_ptr = m_decl_map - > GetSymbolAddress ( name_cstr , lldb : : eSymbolTypeObjCClass ) ;
2014-07-07 01:54:58 +08:00
2011-11-02 07:38:03 +08:00
if ( log )
log - > Printf ( " Found reference to Objective-C class %s (0x%llx) " , name_cstr . AsCString ( ) , ( unsigned long long ) class_ptr ) ;
2014-07-07 01:54:58 +08:00
2011-11-02 07:38:03 +08:00
if ( class_ptr = = LLDB_INVALID_ADDRESS )
return false ;
2014-07-07 01:54:58 +08:00
2014-03-11 01:24:16 +08:00
if ( global_variable - > use_empty ( ) )
2011-11-02 07:38:03 +08:00
return false ;
2014-07-07 01:54:58 +08:00
2013-03-23 09:01:16 +08:00
SmallVector < LoadInst * , 2 > load_instructions ;
2014-07-07 01:54:58 +08:00
2014-03-11 01:24:16 +08:00
for ( llvm : : User * u : global_variable - > users ( ) )
2011-11-02 07:38:03 +08:00
{
2014-03-11 01:24:16 +08:00
if ( LoadInst * load_instruction = dyn_cast < LoadInst > ( u ) )
2013-03-23 09:01:16 +08:00
load_instructions . push_back ( load_instruction ) ;
2011-11-02 07:38:03 +08:00
}
2014-07-07 01:54:58 +08:00
2013-03-23 09:01:16 +08:00
if ( load_instructions . empty ( ) )
2011-11-02 07:38:03 +08:00
return false ;
2014-07-07 01:54:58 +08:00
2013-12-21 03:55:02 +08:00
Constant * class_addr = ConstantInt : : get ( m_intptr_ty , ( uint64_t ) class_ptr ) ;
2014-07-07 01:54:58 +08:00
2013-03-23 09:01:16 +08:00
for ( LoadInst * load_instruction : load_instructions )
{
Constant * class_bitcast = ConstantExpr : : getIntToPtr ( class_addr , load_instruction - > getType ( ) ) ;
2014-07-07 01:54:58 +08:00
2013-03-23 09:01:16 +08:00
load_instruction - > replaceAllUsesWith ( class_bitcast ) ;
2014-07-07 01:54:58 +08:00
2013-03-23 09:01:16 +08:00
load_instruction - > eraseFromParent ( ) ;
}
2014-07-07 01:54:58 +08:00
2011-11-02 07:38:03 +08:00
return true ;
}
2012-07-21 10:02:15 +08:00
bool
IRForTarget : : RemoveCXAAtExit ( BasicBlock & basic_block )
{
BasicBlock : : iterator ii ;
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
std : : vector < CallInst * > calls_to_remove ;
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
+ + ii )
{
Instruction & inst = * ii ;
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
CallInst * call = dyn_cast < CallInst > ( & inst ) ;
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
// MaybeHandleCallArguments handles error reporting; we are silent here
if ( ! call )
continue ;
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
bool remove = false ;
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
llvm : : Function * func = call - > getCalledFunction ( ) ;
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
if ( func & & func - > getName ( ) = = " __cxa_atexit " )
remove = true ;
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
llvm : : Value * val = call - > getCalledValue ( ) ;
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
if ( val & & val - > getName ( ) = = " __cxa_atexit " )
remove = true ;
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
if ( remove )
calls_to_remove . push_back ( call ) ;
}
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
for ( std : : vector < CallInst * > : : iterator ci = calls_to_remove . begin ( ) , ce = calls_to_remove . end ( ) ;
ci ! = ce ;
+ + ci )
{
( * ci ) - > eraseFromParent ( ) ;
}
2014-07-07 01:54:58 +08:00
2012-07-21 10:02:15 +08:00
return true ;
}
2010-07-14 05:41:46 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : ResolveCalls ( BasicBlock & basic_block )
2014-07-07 01:54:58 +08:00
{
2010-07-03 09:35:46 +08:00
/////////////////////////////////////////////////////////////////////////
// Prepare the current basic block for execution in the remote process
//
2014-07-07 01:54:58 +08:00
2010-07-28 05:39:39 +08:00
BasicBlock : : iterator ii ;
2010-07-14 05:41:46 +08:00
2010-11-19 09:05:25 +08:00
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
2010-07-14 05:41:46 +08:00
+ + ii )
{
Instruction & inst = * ii ;
2014-07-07 01:54:58 +08:00
2010-11-08 08:31:32 +08:00
CallInst * call = dyn_cast < CallInst > ( & inst ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
// MaybeHandleCallArguments handles error reporting; we are silent here
2011-05-24 05:40:23 +08:00
if ( call & & ! MaybeHandleCallArguments ( call ) )
2010-12-03 03:47:57 +08:00
return false ;
2010-07-14 05:41:46 +08:00
}
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
return true ;
}
2010-11-08 08:31:32 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : ResolveExternals ( Function & llvm_function )
2010-11-08 08:31:32 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-04-04 12:06:10 +08:00
2014-03-12 03:19:16 +08:00
for ( GlobalVariable & global_var : m_module - > globals ( ) )
2010-11-08 08:31:32 +08:00
{
2014-03-12 03:19:16 +08:00
std : : string global_name = global_var . getName ( ) . str ( ) ;
2014-04-04 12:06:10 +08:00
2010-11-19 09:05:25 +08:00
if ( log )
2014-04-04 12:06:10 +08:00
log - > Printf ( " Examining %s, DeclForGlobalValue returns %p " ,
2011-12-23 05:24:49 +08:00
global_name . c_str ( ) ,
2014-04-04 12:06:10 +08:00
static_cast < void * > ( DeclForGlobal ( & global_var ) ) ) ;
2011-11-02 07:38:03 +08:00
if ( global_name . find ( " OBJC_IVAR " ) = = 0 )
2011-01-18 07:42:46 +08:00
{
2014-03-12 03:19:16 +08:00
if ( ! HandleSymbol ( & global_var ) )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
2011-12-23 05:24:49 +08:00
m_error_stream - > Printf ( " Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s \n " , global_name . c_str ( ) ) ;
2014-04-04 12:06:10 +08:00
2011-01-18 07:42:46 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2011-01-18 07:42:46 +08:00
}
2011-11-02 07:38:03 +08:00
else if ( global_name . find ( " OBJC_CLASSLIST_REFERENCES_$ " ) ! = global_name . npos )
{
2014-03-12 03:19:16 +08:00
if ( ! HandleObjCClass ( & global_var ) )
2011-11-02 07:38:03 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call \n " ) ;
2014-04-04 12:06:10 +08:00
2011-11-02 07:38:03 +08:00
return false ;
}
}
2013-04-25 05:25:20 +08:00
else if ( global_name . find ( " OBJC_CLASSLIST_SUP_REFS_$ " ) ! = global_name . npos )
{
2014-03-12 03:19:16 +08:00
if ( ! HandleObjCClass ( & global_var ) )
2013-04-25 05:25:20 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call \n " ) ;
2014-04-04 12:06:10 +08:00
2013-04-25 05:25:20 +08:00
return false ;
}
}
2014-03-12 03:19:16 +08:00
else if ( DeclForGlobal ( & global_var ) )
2011-01-18 07:42:46 +08:00
{
2014-03-12 03:19:16 +08:00
if ( ! MaybeHandleVariable ( & global_var ) )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
2011-12-23 05:24:49 +08:00
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't rewrite external variable %s \n " , global_name . c_str ( ) ) ;
2014-04-04 12:06:10 +08:00
2011-01-18 07:42:46 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2011-01-18 07:42:46 +08:00
}
2010-11-08 08:31:32 +08:00
}
2014-04-04 12:06:10 +08:00
2010-11-08 08:31:32 +08:00
return true ;
}
2011-05-24 05:40:23 +08:00
bool
IRForTarget : : ReplaceStrings ( )
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
typedef std : : map < GlobalVariable * , size_t > OffsetsTy ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
OffsetsTy offsets ;
2014-07-07 01:54:58 +08:00
2014-03-12 03:19:16 +08:00
for ( GlobalVariable & gv : m_module - > globals ( ) )
2011-05-24 05:40:23 +08:00
{
2014-03-12 03:19:16 +08:00
if ( ! gv . hasInitializer ( ) )
2011-05-24 05:40:23 +08:00
continue ;
2014-07-07 01:54:58 +08:00
2014-03-12 03:19:16 +08:00
Constant * gc = gv . getInitializer ( ) ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
std : : string str ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
if ( gc - > isNullValue ( ) )
{
Type * gc_type = gc - > getType ( ) ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
ArrayType * gc_array_type = dyn_cast < ArrayType > ( gc_type ) ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
if ( ! gc_array_type )
continue ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
Type * gc_element_type = gc_array_type - > getElementType ( ) ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
IntegerType * gc_integer_type = dyn_cast < IntegerType > ( gc_element_type ) ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
if ( gc_integer_type - > getBitWidth ( ) ! = 8 )
continue ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
str = " " ;
}
else
{
2012-02-09 11:22:41 +08:00
ConstantDataArray * gc_array = dyn_cast < ConstantDataArray > ( gc ) ;
2011-08-11 05:05:52 +08:00
if ( ! gc_array )
continue ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
if ( ! gc_array - > isCString ( ) )
continue ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
if ( log )
log - > Printf ( " Found a GlobalVariable with string initializer %s " , PrintValue ( gc ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
str = gc_array - > getAsString ( ) ;
}
2014-07-07 01:54:58 +08:00
2014-03-12 03:19:16 +08:00
offsets [ & gv ] = m_data_allocator . GetStream ( ) . GetSize ( ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
m_data_allocator . GetStream ( ) . Write ( str . c_str ( ) , str . length ( ) + 1 ) ;
2011-05-24 05:40:23 +08:00
}
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
Type * char_ptr_ty = Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
for ( OffsetsTy : : iterator oi = offsets . begin ( ) , oe = offsets . end ( ) ;
oi ! = oe ;
+ + oi )
{
GlobalVariable * gv = oi - > first ;
size_t offset = oi - > second ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
Constant * new_initializer = BuildRelocation ( char_ptr_ty , offset ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
if ( log )
log - > Printf ( " Replacing GV %s with %s " , PrintValue ( gv ) . c_str ( ) , PrintValue ( new_initializer ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2014-03-11 01:24:16 +08:00
for ( llvm : : User * u : gv - > users ( ) )
2011-05-24 05:40:23 +08:00
{
if ( log )
2014-03-11 01:24:16 +08:00
log - > Printf ( " Found use %s " , PrintValue ( u ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2014-03-11 01:24:16 +08:00
ConstantExpr * const_expr = dyn_cast < ConstantExpr > ( u ) ;
StoreInst * store_inst = dyn_cast < StoreInst > ( u ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
if ( const_expr )
{
if ( const_expr - > getOpcode ( ) ! = Instruction : : GetElementPtr )
{
if ( log )
log - > Printf ( " Use (%s) of string variable is not a GetElementPtr constant " , PrintValue ( const_expr ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
Constant * bit_cast = ConstantExpr : : getBitCast ( new_initializer , const_expr - > getOperand ( 0 ) - > getType ( ) ) ;
Constant * new_gep = const_expr - > getWithOperandReplaced ( 0 , bit_cast ) ;
2014-07-07 01:54:58 +08:00
2011-08-11 05:05:52 +08:00
const_expr - > replaceAllUsesWith ( new_gep ) ;
2011-05-24 05:40:23 +08:00
}
else if ( store_inst )
{
Constant * bit_cast = ConstantExpr : : getBitCast ( new_initializer , store_inst - > getValueOperand ( ) - > getType ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
store_inst - > setOperand ( 0 , bit_cast ) ;
}
else
{
if ( log )
log - > Printf ( " Use (%s) of string variable is neither a constant nor a store " , PrintValue ( const_expr ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
return false ;
}
}
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
gv - > eraseFromParent ( ) ;
}
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
return true ;
}
2014-07-07 01:54:58 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : ReplaceStaticLiterals ( llvm : : BasicBlock & basic_block )
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
typedef SmallVector < Value * , 2 > ConstantList ;
typedef SmallVector < llvm : : Instruction * , 2 > UserList ;
typedef ConstantList : : iterator ConstantIterator ;
typedef UserList : : iterator UserIterator ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
ConstantList static_constants ;
UserList static_users ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
for ( BasicBlock : : iterator ii = basic_block . begin ( ) , ie = basic_block . end ( ) ;
ii ! = ie ;
+ + ii )
{
llvm : : Instruction & inst = * ii ;
2014-07-07 01:54:58 +08:00
2014-03-12 03:19:16 +08:00
for ( Value * operand_val : inst . operand_values ( ) )
2011-05-24 05:40:23 +08:00
{
ConstantFP * operand_constant_fp = dyn_cast < ConstantFP > ( operand_val ) ;
2014-07-07 01:54:58 +08:00
2012-04-27 04:51:20 +08:00
if ( operand_constant_fp /* && operand_constant_fp->getType()->isX86_FP80Ty()*/ )
2011-05-24 05:40:23 +08:00
{
static_constants . push_back ( operand_val ) ;
static_users . push_back ( ii ) ;
}
}
}
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
ConstantIterator constant_iter ;
UserIterator user_iter ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
for ( constant_iter = static_constants . begin ( ) , user_iter = static_users . begin ( ) ;
constant_iter ! = static_constants . end ( ) ;
+ + constant_iter , + + user_iter )
{
Value * operand_val = * constant_iter ;
llvm : : Instruction * inst = * user_iter ;
ConstantFP * operand_constant_fp = dyn_cast < ConstantFP > ( operand_val ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
if ( operand_constant_fp )
{
This commit changes the way LLDB executes user
expressions.
Previously, ClangUserExpression assumed that if
there was a constant result for an expression
then it could be determined during parsing. In
particular, the IRInterpreter ran while parser
state (in particular, ClangExpressionDeclMap)
was present. This approach is flawed, because
the IRInterpreter actually is capable of using
external variables, and hence the result might
be different each run. Until now, we papered
over this flaw by re-parsing the expression each
time we ran it.
I have rewritten the IRInterpreter to be
completely independent of the ClangExpressionDeclMap.
Instead of special-casing external variable lookup,
which ties the IRInterpreter closely to LLDB,
we now interpret the exact same IR that the JIT
would see. This IR assumes that materialization
has occurred; hence the recent implementation of the
Materializer, which does not require parser state
(in the form of ClangExpressionDeclMap) to be
present.
Materialization, interpretation, and dematerialization
are now all independent of parsing. This means that
in theory we can parse expressions once and run them
many times. I have three outstanding tasks before
shutting this down:
- First, I will ensure that all of this works with
core files. Core files have a Process but do not
allow allocating memory, which currently confuses
materialization.
- Second, I will make expression breakpoint
conditions remember their ClangUserExpression and
re-use it.
- Third, I will tear out all the redundant code
(for example, materialization logic in
ClangExpressionDeclMap) that is no longer used.
While implementing this fix, I also found a bug in
IRForTarget's handling of floating-point constants.
This should be fixed.
llvm-svn: 179801
2013-04-19 06:06:33 +08:00
Type * operand_type = operand_constant_fp - > getType ( ) ;
2011-05-24 05:40:23 +08:00
APFloat operand_apfloat = operand_constant_fp - > getValueAPF ( ) ;
APInt operand_apint = operand_apfloat . bitcastToAPInt ( ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
const uint8_t * operand_raw_data = ( const uint8_t * ) operand_apint . getRawData ( ) ;
size_t operand_data_size = operand_apint . getBitWidth ( ) / 8 ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
if ( log )
{
std : : string s ;
raw_string_ostream ss ( s ) ;
for ( size_t index = 0 ;
index < operand_data_size ;
+ + index )
{
ss < < ( uint32_t ) operand_raw_data [ index ] ;
ss < < " " ;
}
ss . flush ( ) ;
2014-07-07 01:54:58 +08:00
2014-03-04 03:15:20 +08:00
log - > Printf ( " Found ConstantFP with size % " PRIu64 " and raw data %s " , ( uint64_t ) operand_data_size , s . c_str ( ) ) ;
2011-05-24 05:40:23 +08:00
}
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
lldb_private : : DataBufferHeap data ( operand_data_size , 0 ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( lldb : : endian : : InlHostByteOrder ( ) ! = m_data_allocator . GetStream ( ) . GetByteOrder ( ) )
2011-05-24 05:40:23 +08:00
{
uint8_t * data_bytes = data . GetBytes ( ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
for ( size_t index = 0 ;
index < operand_data_size ;
+ + index )
{
data_bytes [ index ] = operand_raw_data [ operand_data_size - ( 1 + index ) ] ;
}
}
else
{
memcpy ( data . GetBytes ( ) , operand_raw_data , operand_data_size ) ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
uint64_t offset = m_data_allocator . GetStream ( ) . GetSize ( ) ;
2014-07-07 01:54:58 +08:00
2012-06-09 06:20:41 +08:00
size_t align = m_target_data - > getPrefTypeAlignment ( operand_type ) ;
2014-07-07 01:54:58 +08:00
2012-06-09 06:20:41 +08:00
const size_t mask = ( align - 1 ) ;
uint64_t aligned_offset = ( offset + mask ) & ~ mask ;
2013-03-19 08:10:07 +08:00
m_data_allocator . GetStream ( ) . PutNHex8 ( aligned_offset - offset , 0 ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
m_data_allocator . GetStream ( ) . Write ( data . GetBytes ( ) , operand_data_size ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
llvm : : Type * fp_ptr_ty = operand_constant_fp - > getType ( ) - > getPointerTo ( ) ;
2014-07-07 01:54:58 +08:00
This commit changes the way LLDB executes user
expressions.
Previously, ClangUserExpression assumed that if
there was a constant result for an expression
then it could be determined during parsing. In
particular, the IRInterpreter ran while parser
state (in particular, ClangExpressionDeclMap)
was present. This approach is flawed, because
the IRInterpreter actually is capable of using
external variables, and hence the result might
be different each run. Until now, we papered
over this flaw by re-parsing the expression each
time we ran it.
I have rewritten the IRInterpreter to be
completely independent of the ClangExpressionDeclMap.
Instead of special-casing external variable lookup,
which ties the IRInterpreter closely to LLDB,
we now interpret the exact same IR that the JIT
would see. This IR assumes that materialization
has occurred; hence the recent implementation of the
Materializer, which does not require parser state
(in the form of ClangExpressionDeclMap) to be
present.
Materialization, interpretation, and dematerialization
are now all independent of parsing. This means that
in theory we can parse expressions once and run them
many times. I have three outstanding tasks before
shutting this down:
- First, I will ensure that all of this works with
core files. Core files have a Process but do not
allow allocating memory, which currently confuses
materialization.
- Second, I will make expression breakpoint
conditions remember their ClangUserExpression and
re-use it.
- Third, I will tear out all the redundant code
(for example, materialization logic in
ClangExpressionDeclMap) that is no longer used.
While implementing this fix, I also found a bug in
IRForTarget's handling of floating-point constants.
This should be fixed.
llvm-svn: 179801
2013-04-19 06:06:33 +08:00
Constant * new_pointer = BuildRelocation ( fp_ptr_ty , aligned_offset ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
llvm : : LoadInst * fp_load = new llvm : : LoadInst ( new_pointer , " fp_load " , inst ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
operand_constant_fp - > replaceAllUsesWith ( fp_load ) ;
}
}
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
return true ;
}
2010-07-28 05:39:39 +08:00
static bool isGuardVariableRef ( Value * V )
2010-07-24 09:37:44 +08:00
{
2011-07-08 08:39:14 +08:00
Constant * Old = NULL ;
2014-07-07 01:54:58 +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 ;
2014-07-07 01:54:58 +08:00
2011-07-08 08:39:14 +08:00
ConstantExpr * CE = NULL ;
2014-07-07 01:54:58 +08:00
2010-09-23 11:01:22 +08:00
if ( ( CE = dyn_cast < ConstantExpr > ( V ) ) )
{
if ( CE - > getOpcode ( ) ! = Instruction : : BitCast )
return false ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
Old = CE - > getOperand ( 0 ) ;
2010-09-23 11:01:22 +08:00
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
GlobalVariable * GV = dyn_cast < GlobalVariable > ( Old ) ;
2014-07-07 01:54:58 +08:00
2015-01-10 05:12:22 +08:00
if ( ! GV | | ! GV - > hasName ( ) | |
( ! GV - > getName ( ) . startswith ( " _ZGV " ) & & // Itanium ABI guard variable
! GV - > getName ( ) . endswith ( " @4IA " ) ) ) // Microsoft ABI guard variable
{
2010-07-24 09:37:44 +08:00
return false ;
2015-01-10 05:12:22 +08:00
}
2014-07-07 01:54:58 +08:00
2010-07-24 09:37:44 +08:00
return true ;
}
2014-07-07 01:54:58 +08:00
void
2011-05-24 05:40:23 +08:00
IRForTarget : : TurnGuardLoadIntoZero ( llvm : : Instruction * guard_load )
2010-07-24 09:37:44 +08:00
{
2015-01-10 05:12:22 +08:00
Constant * zero ( Constant : : getNullValue ( guard_load - > getType ( ) ) ) ;
guard_load - > replaceAllUsesWith ( zero ) ;
2010-07-24 09:37:44 +08:00
guard_load - > eraseFromParent ( ) ;
}
static void ExciseGuardStore ( Instruction * guard_store )
{
guard_store - > eraseFromParent ( ) ;
}
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : RemoveGuards ( BasicBlock & basic_block )
2014-07-07 01:54:58 +08:00
{
2010-07-24 09:37:44 +08:00
///////////////////////////////////////////////////////
// Eliminate any reference to guard variables found.
//
2014-07-07 01:54:58 +08:00
2010-07-28 05:39:39 +08:00
BasicBlock : : iterator ii ;
2014-07-07 01:54:58 +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 ;
2014-07-07 01:54:58 +08:00
2010-07-24 09:37:44 +08:00
InstrList guard_loads ;
InstrList guard_stores ;
2014-07-07 01:54:58 +08:00
2010-11-19 09:05:25 +08:00
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
2010-07-24 09:37:44 +08:00
+ + ii )
{
Instruction & inst = * ii ;
2014-07-07 01:54:58 +08:00
2010-07-24 09:37:44 +08:00
if ( LoadInst * load = dyn_cast < LoadInst > ( & inst ) )
if ( isGuardVariableRef ( load - > getPointerOperand ( ) ) )
2014-07-07 01:54:58 +08:00
guard_loads . push_back ( & inst ) ;
if ( StoreInst * store = dyn_cast < StoreInst > ( & inst ) )
2010-07-24 09:37:44 +08:00
if ( isGuardVariableRef ( store - > getPointerOperand ( ) ) )
guard_stores . push_back ( & inst ) ;
}
2014-07-07 01:54:58 +08:00
2010-07-24 09:37:44 +08:00
InstrIterator iter ;
2014-07-07 01:54:58 +08:00
2010-07-24 09:37:44 +08:00
for ( iter = guard_loads . begin ( ) ;
iter ! = guard_loads . end ( ) ;
+ + iter )
2011-05-24 05:40:23 +08:00
TurnGuardLoadIntoZero ( * iter ) ;
2014-07-07 01:54:58 +08:00
2010-07-24 09:37:44 +08:00
for ( iter = guard_stores . begin ( ) ;
iter ! = guard_stores . end ( ) ;
+ + iter )
ExciseGuardStore ( * iter ) ;
2014-07-07 01:54:58 +08:00
2010-07-24 09:37:44 +08:00
return true ;
}
2011-01-27 09:07:04 +08:00
// This function does not report errors; its callers are responsible.
2010-11-18 07:00:36 +08:00
bool
2013-06-29 05:44:15 +08:00
IRForTarget : : UnfoldConstant ( Constant * old_constant ,
FunctionValueCache & value_maker ,
FunctionValueCache & entry_instruction_finder )
2010-07-15 07:40:29 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-15 07:40:29 +08:00
2010-08-11 11:57:18 +08:00
SmallVector < User * , 16 > users ;
2014-07-07 01:54:58 +08:00
2010-08-11 11:57:18 +08:00
// We do this because the use list might change, invalidating our iterator.
// Much better to keep a work list ourselves.
2014-03-10 22:23:10 +08:00
for ( llvm : : User * u : old_constant - > users ( ) )
users . push_back ( u ) ;
2014-07-07 01:54:58 +08:00
2011-07-20 03:48:13 +08:00
for ( size_t i = 0 ;
2010-08-11 11:57:18 +08:00
i < users . size ( ) ;
+ + i )
{
User * user = users [ i ] ;
2014-07-07 01:54:58 +08:00
2010-07-15 07:40:29 +08:00
if ( Constant * constant = dyn_cast < Constant > ( user ) )
{
// synthesize a new non-constant equivalent of the constant
2014-07-07 01:54:58 +08:00
2010-07-15 07:40:29 +08:00
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 :
2014-07-07 01:54:58 +08:00
{
2013-06-29 05:44:15 +08:00
FunctionValueCache bit_cast_maker ( [ & value_maker , & entry_instruction_finder , old_constant , constant_expr ] ( llvm : : Function * function ) - > llvm : : Value * {
// UnaryExpr
// OperandList[0] is value
if ( constant_expr - > getOperand ( 0 ) ! = old_constant )
return constant_expr ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
return new BitCastInst ( value_maker . GetValue ( function ) ,
constant_expr - > getType ( ) ,
" " ,
llvm : : cast < Instruction > ( entry_instruction_finder . GetValue ( function ) ) ) ;
} ) ;
2014-07-07 01:54:58 +08:00
2013-07-16 07:31:47 +08:00
if ( ! UnfoldConstant ( constant_expr , bit_cast_maker , entry_instruction_finder ) )
return false ;
2010-07-15 07:40:29 +08:00
}
break ;
case Instruction : : GetElementPtr :
{
// GetElementPtrConstantExpr
// OperandList[0] is base
// OperandList[1]... are indices
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
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 ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ptr = = old_constant )
ptr = value_maker . GetValue ( function ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
std : : vector < Value * > index_vector ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
unsigned operand_index ;
unsigned num_operands = constant_expr - > getNumOperands ( ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
for ( operand_index = 1 ;
operand_index < num_operands ;
+ + operand_index )
{
Value * operand = constant_expr - > getOperand ( operand_index ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( operand = = old_constant )
operand = value_maker . GetValue ( function ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
index_vector . push_back ( operand ) ;
}
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
ArrayRef < Value * > indices ( index_vector ) ;
2014-07-07 01:54:58 +08:00
2015-03-16 11:54:22 +08:00
return GetElementPtrInst : : Create ( nullptr , ptr , indices , " " , llvm : : cast < Instruction > ( entry_instruction_finder . GetValue ( function ) ) ) ;
2013-06-29 05:44:15 +08:00
} ) ;
2014-07-07 01:54:58 +08:00
2013-07-16 07:31:47 +08:00
if ( ! UnfoldConstant ( constant_expr , get_element_pointer_maker , entry_instruction_finder ) )
return false ;
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
{
2013-06-29 05:44:15 +08:00
if ( Instruction * inst = llvm : : dyn_cast < Instruction > ( user ) )
{
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 ;
}
2010-07-15 07:40:29 +08:00
}
}
2014-07-07 01:54:58 +08:00
2013-07-16 07:31:47 +08:00
if ( ! isa < GlobalValue > ( old_constant ) )
{
old_constant - > destroyConstant ( ) ;
}
2014-07-07 01:54:58 +08:00
2010-07-15 07:40:29 +08:00
return true ;
}
2014-07-07 01:54:58 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : ReplaceVariables ( Function & llvm_function )
2010-07-14 05:41:46 +08:00
{
2010-09-14 05:34:21 +08:00
if ( ! m_resolve_vars )
return true ;
2014-07-07 01:54:58 +08:00
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-14 05:41:46 +08:00
m_decl_map - > DoStructLayout ( ) ;
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
if ( log )
log - > Printf ( " Element arrangement: " ) ;
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
uint32_t num_elements ;
uint32_t element_index ;
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
size_t size ;
2014-07-03 01:24:07 +08:00
lldb : : offset_t alignment ;
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
if ( ! m_decl_map - > GetStructInfo ( num_elements , size , alignment ) )
return false ;
2014-07-07 01:54:58 +08:00
2010-11-19 09:05:25 +08:00
Function : : arg_iterator iter ( llvm_function . getArgumentList ( ) . begin ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-11-19 09:05:25 +08:00
if ( iter = = llvm_function . getArgumentList ( ) . end ( ) )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer) " ) ;
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2014-07-07 01:54:58 +08:00
2010-07-28 05:39:39 +08:00
Argument * argument = iter ;
2014-07-07 01:54:58 +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 ;
2014-07-07 01:54:58 +08:00
2010-11-19 09:05:25 +08:00
if ( iter = = llvm_function . getArgumentList ( ) . end ( ) )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too) " ) ;
2014-07-07 01:54:58 +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
return false ;
2011-01-27 09:07:04 +08:00
}
2014-07-07 01:54:58 +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
argument = iter ;
}
2010-12-14 06:46:15 +08:00
else if ( argument - > getName ( ) . equals ( " self " ) )
{
+ + iter ;
2014-07-07 01:54:58 +08:00
2010-12-14 06:46:15 +08:00
if ( iter = = llvm_function . getArgumentList ( ) . end ( ) )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Wrapper takes only 'self' argument (should take '_cmd' and a struct pointer too) " ) ;
2014-07-07 01:54:58 +08:00
2010-12-14 06:46:15 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2014-07-07 01:54:58 +08:00
2010-12-14 06:46:15 +08:00
if ( ! iter - > getName ( ) . equals ( " _cmd " ) )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Wrapper takes '%s' after 'self' argument (should take '_cmd') " , iter - > getName ( ) . str ( ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-12-14 06:46:15 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2014-07-07 01:54:58 +08:00
2010-12-14 06:46:15 +08:00
+ + iter ;
2014-07-07 01:54:58 +08:00
2010-12-14 06:46:15 +08:00
if ( iter = = llvm_function . getArgumentList ( ) . end ( ) )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Wrapper takes only 'self' and '_cmd' arguments (should take a struct pointer too) " ) ;
2014-07-07 01:54:58 +08:00
2010-12-14 06:46:15 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2014-07-07 01:54:58 +08:00
2010-12-14 06:46:15 +08:00
argument = iter ;
}
2014-07-07 01:54:58 +08:00
2010-10-16 06:48:33 +08:00
if ( ! argument - > getName ( ) . equals ( " $__lldb_arg " ) )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Wrapper takes an argument named '%s' instead of the struct pointer " , argument - > getName ( ) . str ( ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2014-07-07 01:54:58 +08:00
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 ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-11-19 09:05:25 +08:00
BasicBlock & entry_block ( llvm_function . getEntryBlock ( ) ) ;
2010-11-18 07:00:36 +08:00
Instruction * FirstEntryInstruction ( entry_block . getFirstNonPHIOrDbg ( ) ) ;
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
if ( ! FirstEntryInstruction )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't find the first instruction in the wrapper for use in rewriting " ) ;
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
LLVMContext & context ( m_module - > getContext ( ) ) ;
2011-07-30 10:42:06 +08:00
IntegerType * offset_type ( Type : : getInt32Ty ( context ) ) ;
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
if ( ! offset_type )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't produce an offset type " ) ;
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
for ( element_index = 0 ; element_index < num_elements ; + + element_index )
2010-07-03 09:35:46 +08:00
{
2011-07-08 08:39:14 +08:00
const clang : : NamedDecl * decl = NULL ;
Value * value = NULL ;
2014-07-03 01:24:07 +08:00
lldb : : offset_t offset ;
2010-10-16 06:48:33 +08:00
lldb_private : : ConstString name ;
2014-07-07 01:54:58 +08:00
2010-08-31 06:17:16 +08:00
if ( ! m_decl_map - > GetStructElement ( decl , value , offset , name , element_index ) )
2011-01-27 09:07:04 +08:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Structure information is incomplete " ) ;
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
return false ;
2011-01-27 09:07:04 +08:00
}
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
if ( log )
2014-07-03 01:24:07 +08:00
log - > Printf ( " \" %s \" ( \" %s \" ) placed at % " PRIu64 ,
2010-10-16 06:48:33 +08:00
name . GetCString ( ) ,
2011-10-26 02:36:40 +08:00
decl - > getNameAsString ( ) . c_str ( ) ,
2010-07-14 05:41:46 +08:00
offset ) ;
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
if ( value )
2011-01-13 16:53:35 +08:00
{
2011-10-26 02:36:40 +08:00
if ( log )
log - > Printf ( " Replacing [%s] " , PrintValue ( value ) . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
FunctionValueCache body_result_maker ( [ this , name , offset_type , offset , argument , value ] ( llvm : : Function * function ) - > llvm : : Value * {
// Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result
// variable is an rvalue, we have to synthesize a dereference of the appropriate structure
// entry in order to produce the static variable that the AST thinks it is accessing.
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
llvm : : Instruction * entry_instruction = llvm : : cast < Instruction > ( m_entry_instruction_finder . GetValue ( function ) ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
ConstantInt * offset_int ( ConstantInt : : get ( offset_type , offset , true ) ) ;
2015-03-16 11:54:22 +08:00
GetElementPtrInst * get_element_ptr = GetElementPtrInst : : Create ( nullptr ,
argument ,
2013-06-29 05:44:15 +08:00
offset_int ,
" " ,
entry_instruction ) ;
if ( name = = m_result_name & & ! m_result_is_pointer )
{
BitCastInst * bit_cast = new BitCastInst ( get_element_ptr ,
value - > getType ( ) - > getPointerTo ( ) ,
" " ,
entry_instruction ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
LoadInst * load = new LoadInst ( bit_cast , " " , entry_instruction ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
return load ;
}
else
{
BitCastInst * bit_cast = new BitCastInst ( get_element_ptr , value - > getType ( ) , " " , entry_instruction ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
return bit_cast ;
}
2014-07-07 01:54:58 +08:00
} ) ;
2013-06-29 05:44:15 +08:00
if ( Constant * constant = dyn_cast < Constant > ( value ) )
{
UnfoldConstant ( constant , body_result_maker , m_entry_instruction_finder ) ;
2011-10-26 02:36:40 +08:00
}
2013-06-29 05:44:15 +08:00
else if ( Instruction * instruction = dyn_cast < Instruction > ( value ) )
2011-10-26 02:36:40 +08:00
{
2013-06-29 05:44:15 +08:00
value - > replaceAllUsesWith ( body_result_maker . GetValue ( instruction - > getParent ( ) - > getParent ( ) ) ) ;
2011-10-26 02:36:40 +08:00
}
else
2013-06-29 05:44:15 +08:00
{
if ( log )
log - > Printf ( " Unhandled non-constant type: \" %s \" " , PrintValue ( value ) . c_str ( ) ) ;
return false ;
}
2014-07-07 01:54:58 +08:00
2011-10-26 02:36:40 +08:00
if ( GlobalVariable * var = dyn_cast < GlobalVariable > ( value ) )
var - > eraseFromParent ( ) ;
}
2010-07-03 09:35:46 +08:00
}
2014-07-07 01:54:58 +08:00
2010-07-14 05:41:46 +08:00
if ( log )
2014-03-04 03:15:20 +08:00
log - > Printf ( " Total structure [align % " PRId64 " , size % " PRIu64 " ] " , ( int64_t ) alignment , ( uint64_t ) size ) ;
2014-07-07 01:54:58 +08:00
2010-07-03 09:35:46 +08:00
return true ;
}
2011-05-24 05:40:23 +08:00
llvm : : Constant *
2013-03-28 07:08:40 +08:00
IRForTarget : : BuildRelocation ( llvm : : Type * type , uint64_t offset )
2011-05-24 05:40:23 +08:00
{
2013-12-21 03:55:02 +08:00
llvm : : Constant * offset_int = ConstantInt : : get ( m_intptr_ty , offset ) ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
llvm : : Constant * offset_array [ 1 ] ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
offset_array [ 0 ] = offset_int ;
2014-07-07 01:54:58 +08:00
2011-07-30 10:42:06 +08:00
llvm : : ArrayRef < llvm : : Constant * > offsets ( offset_array , 1 ) ;
2015-04-15 02:17:35 +08:00
llvm : : Type * char_type = llvm : : Type : : getInt8Ty ( m_module - > getContext ( ) ) ;
llvm : : Type * char_pointer_type = char_type - > getPointerTo ( ) ;
2014-07-07 01:54:58 +08:00
2015-04-15 02:17:35 +08:00
llvm : : Constant * reloc_placeholder_bitcast = ConstantExpr : : getBitCast ( m_reloc_placeholder , char_pointer_type ) ;
llvm : : Constant * reloc_getelementptr = ConstantExpr : : getGetElementPtr ( char_type , reloc_placeholder_bitcast , offsets ) ;
2015-04-07 07:51:08 +08:00
llvm : : Constant * reloc_bitcast = ConstantExpr : : getBitCast ( reloc_getelementptr , type ) ;
2014-07-07 01:54:58 +08:00
2015-04-07 07:51:08 +08:00
return reloc_bitcast ;
2011-05-24 05:40:23 +08:00
}
2014-07-07 01:54:58 +08:00
bool
2011-05-24 05:40:23 +08:00
IRForTarget : : CompleteDataAllocation ( )
2014-07-07 01:54:58 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2011-05-24 05:40:23 +08:00
2013-03-19 08:10:07 +08:00
if ( ! m_data_allocator . GetStream ( ) . GetSize ( ) )
2011-05-24 05:40:23 +08:00
return true ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
lldb : : addr_t allocation = m_data_allocator . Allocate ( ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
if ( log )
{
if ( allocation )
log - > Printf ( " Allocated static data at 0x%llx " , ( unsigned long long ) allocation ) ;
else
log - > Printf ( " Failed to allocate static data " ) ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( ! allocation | | allocation = = LLDB_INVALID_ADDRESS )
2011-05-24 05:40:23 +08:00
return false ;
2014-07-07 01:54:58 +08:00
2013-12-21 03:55:02 +08:00
Constant * relocated_addr = ConstantInt : : get ( m_intptr_ty , ( uint64_t ) allocation ) ;
2011-05-24 05:40:23 +08:00
Constant * relocated_bitcast = ConstantExpr : : getIntToPtr ( relocated_addr , llvm : : Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
m_reloc_placeholder - > replaceAllUsesWith ( relocated_bitcast ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
m_reloc_placeholder - > eraseFromParent ( ) ;
return true ;
}
2012-09-25 06:25:51 +08:00
bool
IRForTarget : : StripAllGVs ( Module & llvm_module )
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2012-09-25 06:25:51 +08:00
std : : vector < GlobalVariable * > global_vars ;
std : : set < GlobalVariable * > erased_vars ;
2014-07-07 01:54:58 +08:00
2012-09-25 06:25:51 +08:00
bool erased = true ;
2014-07-07 01:54:58 +08:00
2012-09-25 06:25:51 +08:00
while ( erased )
{
erased = false ;
2014-07-07 01:54:58 +08:00
2014-03-12 03:19:16 +08:00
for ( GlobalVariable & global_var : llvm_module . globals ( ) )
2012-09-25 06:25:51 +08:00
{
2014-03-12 03:19:16 +08:00
global_var . removeDeadConstantUsers ( ) ;
2014-07-07 01:54:58 +08:00
2014-03-12 03:19:16 +08:00
if ( global_var . use_empty ( ) )
2012-09-25 06:25:51 +08:00
{
if ( log )
log - > Printf ( " Did remove %s " ,
2014-03-12 03:19:16 +08:00
PrintValue ( & global_var ) . c_str ( ) ) ;
global_var . eraseFromParent ( ) ;
2012-09-25 06:25:51 +08:00
erased = true ;
break ;
}
}
}
2014-07-07 01:54:58 +08:00
2014-03-12 03:19:16 +08:00
for ( GlobalVariable & global_var : llvm_module . globals ( ) )
2012-09-25 06:25:51 +08:00
{
2014-03-12 03:19:16 +08:00
GlobalValue : : user_iterator ui = global_var . user_begin ( ) ;
2014-07-07 01:54:58 +08:00
2012-11-27 03:54:04 +08:00
if ( log )
log - > Printf ( " Couldn't remove %s because of %s " ,
2014-03-12 03:19:16 +08:00
PrintValue ( & global_var ) . c_str ( ) ,
2012-11-27 03:54:04 +08:00
PrintValue ( * ui ) . c_str ( ) ) ;
2012-09-25 06:25:51 +08:00
}
2014-07-07 01:54:58 +08:00
2012-09-25 06:25:51 +08:00
return true ;
}
2010-07-03 09:35:46 +08:00
bool
2010-11-19 09:05:25 +08:00
IRForTarget : : runOnModule ( Module & llvm_module )
2010-07-03 09:35:46 +08:00
{
2013-03-28 07:08:40 +08:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
m_module = & llvm_module ;
2012-10-09 00:28:57 +08:00
m_target_data . reset ( new DataLayout ( m_module ) ) ;
2013-12-21 03:55:02 +08:00
m_intptr_ty = llvm : : Type : : getIntNTy ( m_module - > getContext ( ) , m_target_data - > getPointerSizeInBits ( ) ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( log )
{
std : : string s ;
raw_string_ostream oss ( s ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
m_module - > print ( oss , NULL ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
oss . flush ( ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
log - > Printf ( " Module as passed in to IRForTarget: \n \" %s \" " , s . c_str ( ) ) ;
}
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
Function * main_function = m_module - > getFunction ( StringRef ( m_func_name . c_str ( ) ) ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! main_function )
2010-07-03 09:35:46 +08:00
{
if ( log )
2010-11-15 09:47:11 +08:00
log - > Printf ( " Couldn't find \" %s() \" in the module " , m_func_name . c_str ( ) ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
if ( m_error_stream )
2011-05-24 05:40:23 +08:00
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module " , m_func_name . c_str ( ) ) ;
2011-01-13 16:53:35 +08:00
2010-07-03 09:35:46 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! FixFunctionLinkage ( * main_function ) )
2011-05-24 05:40:23 +08:00
{
if ( log )
log - > Printf ( " Couldn't fix the linkage for the function " ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2013-12-21 03:55:02 +08:00
llvm : : Type * int8_ty = Type : : getInt8Ty ( m_module - > getContext ( ) ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
m_reloc_placeholder = new llvm : : GlobalVariable ( ( * m_module ) ,
2013-12-21 03:55:02 +08:00
int8_ty ,
2012-09-25 06:25:51 +08:00
false /* IsConstant */ ,
2011-05-24 05:40:23 +08:00
GlobalVariable : : InternalLinkage ,
2013-12-21 03:55:02 +08:00
Constant : : getNullValue ( int8_ty ) ,
2011-05-24 05:40:23 +08:00
" reloc_placeholder " ,
NULL /* InsertBefore */ ,
2012-09-25 06:25:51 +08:00
GlobalVariable : : NotThreadLocal /* ThreadLocal */ ,
2011-05-24 05:40:23 +08:00
0 /* AddressSpace */ ) ;
2013-06-29 05:44:15 +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
//
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! CreateResultVariable ( * main_function ) )
2010-12-14 06:46:15 +08:00
{
if ( log )
log - > Printf ( " CreateResultVariable() failed " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
// CreateResultVariable() reports its own errors, so we don't do so here
2014-07-07 01:54:58 +08:00
2010-08-12 09:56:52 +08:00
return false ;
2010-12-14 06:46:15 +08:00
}
2012-07-21 10:02:15 +08:00
2011-11-02 01:33:54 +08:00
if ( log & & log - > GetVerbose ( ) )
2011-05-24 05:40:23 +08:00
{
std : : string s ;
raw_string_ostream oss ( s ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
m_module - > print ( oss , NULL ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
oss . flush ( ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
log - > Printf ( " Module after creating the result variable: \n \" %s \" " , s . c_str ( ) ) ;
}
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
for ( Module : : iterator fi = m_module - > begin ( ) , fe = m_module - > end ( ) ;
fi ! = fe ;
+ + fi )
{
llvm : : Function * function = fi ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( function - > begin ( ) = = function - > end ( ) )
continue ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
Function : : iterator bbi ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
for ( bbi = function - > begin ( ) ;
bbi ! = function - > end ( ) ;
+ + bbi )
{
if ( ! RemoveGuards ( * bbi ) )
{
if ( log )
log - > Printf ( " RemoveGuards() failed " ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
// RemoveGuards() reports its own errors, so we don't do so here
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! RewritePersistentAllocs ( * bbi ) )
{
if ( log )
log - > Printf ( " RewritePersistentAllocs() failed " ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
// RewritePersistentAllocs() reports its own errors, so we don't do so here
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! RemoveCXAAtExit ( * bbi ) )
{
if ( log )
log - > Printf ( " RemoveCXAAtExit() failed " ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
// RemoveCXAAtExit() reports its own errors, so we don't do so here
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
return false ;
}
}
}
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
///////////////////////////////////////////////////////////////////////////////
// Fix all Objective-C constant strings to use NSStringWithCString:encoding:
//
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! RewriteObjCConstStrings ( ) )
2010-12-14 06:46:15 +08:00
{
if ( log )
log - > Printf ( " RewriteObjCConstStrings() failed " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
// RewriteObjCConstStrings() reports its own errors, so we don't do so here
2014-07-07 01:54:58 +08:00
2010-11-18 07:00:36 +08:00
return false ;
2010-12-14 06:46:15 +08:00
}
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
///////////////////////////////
// Resolve function pointers
//
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! ResolveFunctionPointers ( llvm_module ) )
2011-08-05 05:37:47 +08:00
{
if ( log )
log - > Printf ( " ResolveFunctionPointers() failed " ) ;
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
// ResolveFunctionPointers() reports its own errors, so we don't do so here
2014-07-07 01:54:58 +08:00
2011-08-05 05:37:47 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
for ( Module : : iterator fi = m_module - > begin ( ) , fe = m_module - > end ( ) ;
fi ! = fe ;
+ + fi )
2010-07-03 09:35:46 +08:00
{
2013-06-29 05:44:15 +08:00
llvm : : Function * function = fi ;
for ( llvm : : Function : : iterator bbi = function - > begin ( ) , bbe = function - > end ( ) ;
bbi ! = bbe ;
+ + bbi )
2010-12-14 06:46:15 +08:00
{
2013-06-29 05:44:15 +08:00
if ( ! RewriteObjCSelectors ( * bbi ) )
{
if ( log )
log - > Printf ( " RewriteObjCSelectors() failed " ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
// RewriteObjCSelectors() reports its own errors, so we don't do so here
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
return false ;
}
2010-12-14 06:46:15 +08:00
}
2012-07-28 03:25:24 +08:00
}
2010-08-11 11:57:18 +08:00
2013-06-29 05:44:15 +08:00
for ( Module : : iterator fi = m_module - > begin ( ) , fe = m_module - > end ( ) ;
fi ! = fe ;
+ + fi )
2012-07-28 03:25:24 +08:00
{
2013-06-29 05:44:15 +08:00
llvm : : Function * function = fi ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
for ( llvm : : Function : : iterator bbi = function - > begin ( ) , bbe = function - > end ( ) ;
bbi ! = bbe ;
+ + bbi )
2011-05-24 05:40:23 +08:00
{
2013-06-29 05:44:15 +08:00
if ( ! ResolveCalls ( * bbi ) )
{
if ( log )
log - > Printf ( " ResolveCalls() failed " ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
// ResolveCalls() reports its own errors, so we don't do so here
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! ReplaceStaticLiterals ( * bbi ) )
{
if ( log )
log - > Printf ( " ReplaceStaticLiterals() failed " ) ;
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
return false ;
}
2011-05-24 05:40:23 +08:00
}
2010-07-14 05:41:46 +08:00
}
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
////////////////////////////////////////////////////////////////////////
// Run function-level passes that only make sense on the main function
2010-10-01 05:18:25 +08:00
//
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! ResolveExternals ( * main_function ) )
2010-12-14 06:46:15 +08:00
{
if ( log )
log - > Printf ( " ResolveExternals() failed " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
// ResolveExternals() reports its own errors, so we don't do so here
2014-07-07 01:54:58 +08:00
2010-11-08 08:31:32 +08:00
return false ;
2010-12-14 06:46:15 +08:00
}
2014-07-07 01:54:58 +08:00
2013-06-29 05:44:15 +08:00
if ( ! ReplaceVariables ( * main_function ) )
2010-12-14 06:46:15 +08:00
{
if ( log )
log - > Printf ( " ReplaceVariables() failed " ) ;
2014-07-07 01:54:58 +08:00
2011-01-27 09:07:04 +08:00
// ReplaceVariables() reports its own errors, so we don't do so here
2014-07-07 01:54:58 +08:00
2010-10-01 05:18:25 +08:00
return false ;
2010-12-14 06:46:15 +08:00
}
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
if ( ! ReplaceStrings ( ) )
{
if ( log )
log - > Printf ( " ReplaceStrings() failed " ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
if ( ! CompleteDataAllocation ( ) )
{
if ( log )
log - > Printf ( " CompleteDataAllocation() failed " ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
return false ;
}
2014-07-07 01:54:58 +08:00
2012-09-25 06:25:51 +08:00
if ( ! StripAllGVs ( llvm_module ) )
{
if ( log )
log - > Printf ( " StripAllGVs() failed " ) ;
}
2014-07-07 01:54:58 +08:00
2011-11-02 01:33:54 +08:00
if ( log & & log - > GetVerbose ( ) )
2010-07-14 05:41:46 +08:00
{
2010-07-28 09:00:59 +08:00
std : : string s ;
raw_string_ostream oss ( s ) ;
2014-07-07 01:54:58 +08:00
2011-05-24 05:40:23 +08:00
m_module - > print ( oss , NULL ) ;
2014-07-07 01:54:58 +08:00
2010-07-28 09:00:59 +08:00
oss . flush ( ) ;
2014-07-07 01:54:58 +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
}
2014-07-07 01:54:58 +08:00
return true ;
2010-07-03 09:35:46 +08:00
}
void
2010-11-19 09:05:25 +08:00
IRForTarget : : assignPassManager ( PMStack & pass_mgr_stack , PassManagerType pass_mgr_type )
2010-07-03 09:35:46 +08:00
{
}
PassManagerType
IRForTarget : : getPotentialPassManagerType ( ) const
{
return PMT_ModulePassManager ;
}