2010-07-03 01:35:46 +00:00
//===-- IRForTarget.cpp -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "lldb/Expression/IRForTarget.h"
# include "llvm/Support/raw_ostream.h"
2011-04-14 02:01:31 +00:00
# include "llvm/Constants.h"
2010-07-03 01:35:46 +00:00
# include "llvm/InstrTypes.h"
2010-07-13 21:41:46 +00:00
# include "llvm/Instructions.h"
2010-09-28 23:55:00 +00:00
# include "llvm/Intrinsics.h"
2010-07-03 01:35:46 +00:00
# include "llvm/Module.h"
2010-07-13 21:41:46 +00:00
# include "llvm/Target/TargetData.h"
2010-08-12 01:56:52 +00:00
# include "llvm/ValueSymbolTable.h"
2010-07-13 21:41:46 +00:00
# include "clang/AST/ASTContext.h"
2010-07-03 01:35:46 +00:00
2010-10-15 22:48:33 +00:00
# include "lldb/Core/ConstString.h"
2010-07-03 01:35:46 +00:00
# include "lldb/Core/dwarf.h"
# include "lldb/Core/Log.h"
# include "lldb/Core/Scalar.h"
# include "lldb/Core/StreamString.h"
# include "lldb/Expression/ClangExpressionDeclMap.h"
# include <map>
using namespace llvm ;
2010-08-18 18:50:51 +00:00
static char ID ;
2010-11-19 01:05:25 +00:00
IRForTarget : : IRForTarget ( lldb_private : : ClangExpressionDeclMap * decl_map ,
bool resolve_vars ,
2010-12-16 03:17:46 +00:00
lldb : : ClangExpressionVariableSP * const_result ,
2011-01-27 01:07:04 +00:00
lldb_private : : Stream * error_stream ,
2010-11-19 01:05:25 +00:00
const char * func_name ) :
2010-09-23 03:01:22 +00:00
ModulePass ( ID ) ,
2011-04-11 19:41:40 +00:00
m_resolve_vars ( resolve_vars ) ,
m_func_name ( func_name ) ,
2010-07-13 21:41:46 +00:00
m_decl_map ( decl_map ) ,
2010-11-17 23:00:36 +00:00
m_CFStringCreateWithBytes ( NULL ) ,
2010-08-27 01:01:44 +00:00
m_sel_registerName ( NULL ) ,
2010-12-16 03:17:46 +00:00
m_const_result ( const_result ) ,
2011-04-11 19:41:40 +00:00
m_error_stream ( error_stream ) ,
2011-01-13 08:53:35 +00:00
m_has_side_effects ( false ) ,
2011-04-11 19:41:40 +00:00
m_result_is_pointer ( false )
2010-07-03 01:35:46 +00:00
{
}
2010-09-30 21:18:25 +00:00
/* Handy utility functions used at several places in the code */
2010-08-11 03:57:18 +00:00
static std : : string
2010-11-19 01:05:25 +00:00
PrintValue ( const Value * value , bool truncate = false )
2010-08-11 03:57:18 +00:00
{
std : : string s ;
raw_string_ostream rso ( s ) ;
2010-11-19 01:05:25 +00:00
value - > print ( rso ) ;
2010-08-11 03:57:18 +00:00
rso . flush ( ) ;
if ( truncate )
s . resize ( s . length ( ) - 1 ) ;
return s ;
}
2010-09-30 21:18:25 +00:00
static std : : string
2010-11-19 01:05:25 +00:00
PrintType ( const Type * type , bool truncate = false )
2010-09-30 21:18:25 +00:00
{
std : : string s ;
raw_string_ostream rso ( s ) ;
2010-11-19 01:05:25 +00:00
type - > print ( rso ) ;
2010-09-30 21:18:25 +00:00
rso . flush ( ) ;
if ( truncate )
s . resize ( s . length ( ) - 1 ) ;
return s ;
}
2010-07-03 01:35:46 +00:00
IRForTarget : : ~ IRForTarget ( )
{
}
2010-12-16 03:17:46 +00:00
bool
IRForTarget : : HasSideEffects ( llvm : : Module & llvm_module ,
llvm : : Function & llvm_function )
{
llvm : : Function : : iterator bbi ;
BasicBlock : : iterator ii ;
for ( bbi = llvm_function . begin ( ) ;
bbi ! = llvm_function . end ( ) ;
+ + bbi )
{
BasicBlock & basic_block = * bbi ;
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
+ + ii )
{
switch ( ii - > getOpcode ( ) )
{
default :
return true ;
case Instruction : : Store :
{
StoreInst * store_inst = dyn_cast < StoreInst > ( ii ) ;
Value * store_ptr = store_inst - > getPointerOperand ( ) ;
if ( ! isa < AllocaInst > ( store_ptr ) )
return true ;
else
break ;
}
case Instruction : : Load :
case Instruction : : Alloca :
case Instruction : : GetElementPtr :
case Instruction : : Ret :
break ;
}
}
}
return false ;
}
void
IRForTarget : : MaybeSetConstantResult ( llvm : : Constant * initializer ,
const lldb_private : : ConstString & name ,
lldb_private : : TypeFromParser type )
{
if ( ! m_const_result )
return ;
if ( llvm : : ConstantInt * init_int = dyn_cast < llvm : : ConstantInt > ( initializer ) )
{
* m_const_result = m_decl_map - > BuildIntegerVariable ( name , type , init_int - > getValue ( ) ) ;
}
}
2010-08-12 01:56:52 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : CreateResultVariable ( llvm : : Module & llvm_module , llvm : : Function & llvm_function )
2010-08-12 01:56:52 +00:00
{
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-08-12 01:56:52 +00:00
2010-09-13 21:34:21 +00:00
if ( ! m_resolve_vars )
return true ;
// Find the result variable. If it doesn't exist, we can give up right here.
2010-09-21 00:44:12 +00:00
2010-10-15 22:48:33 +00:00
ValueSymbolTable & value_symbol_table = llvm_module . getValueSymbolTable ( ) ;
2010-09-21 00:44:12 +00:00
const char * result_name = NULL ;
for ( ValueSymbolTable : : iterator vi = value_symbol_table . begin ( ) , ve = value_symbol_table . end ( ) ;
vi ! = ve ;
+ + vi )
{
2011-01-13 08:53:35 +00:00
if ( strstr ( vi - > first ( ) , " $__lldb_expr_result_ptr " ) & &
! strstr ( vi - > first ( ) , " GV " ) )
{
result_name = vi - > first ( ) ;
m_result_is_pointer = true ;
break ;
}
2010-10-15 22:48:33 +00:00
if ( strstr ( vi - > first ( ) , " $__lldb_expr_result " ) & &
2010-09-28 21:13:03 +00:00
! strstr ( vi - > first ( ) , " GV " ) )
{
2010-09-21 00:44:12 +00:00
result_name = vi - > first ( ) ;
2011-01-13 08:53:35 +00:00
m_result_is_pointer = false ;
2010-09-28 21:13:03 +00:00
break ;
}
2010-09-21 00:44:12 +00:00
}
if ( ! result_name )
{
if ( log )
log - > PutCString ( " Couldn't find result variable " ) ;
return true ;
}
2010-09-28 21:13:03 +00:00
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Result name: \" %s \" " , result_name ) ;
2010-09-28 21:13:03 +00:00
2010-10-15 22:48:33 +00:00
Value * result_value = llvm_module . getNamedValue ( result_name ) ;
2010-08-12 01:56:52 +00:00
if ( ! result_value )
{
if ( log )
2010-09-21 00:44:12 +00:00
log - > PutCString ( " Result variable had no data " ) ;
2011-01-13 08:53:35 +00:00
2011-01-27 01:07:04 +00: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 ) ;
2010-09-21 00:44:12 +00:00
return false ;
2010-08-12 01:56:52 +00:00
}
2010-09-13 21:34:21 +00:00
2010-08-12 01:56:52 +00:00
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Found result in the IR: \" %s \" " , PrintValue ( result_value , false ) . c_str ( ) ) ;
2010-08-12 01:56:52 +00:00
GlobalVariable * result_global = dyn_cast < GlobalVariable > ( result_value ) ;
if ( ! result_global )
{
if ( log )
log - > PutCString ( " Result variable isn't a GlobalVariable " ) ;
2011-01-27 01:07:04 +00: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 ) ;
2010-08-12 01:56:52 +00:00
return false ;
}
// Find the metadata and follow it to the VarDecl
2010-10-15 22:48:33 +00:00
NamedMDNode * named_metadata = llvm_module . getNamedMetadata ( " clang.global.decl.ptrs " ) ;
2010-08-12 01:56:52 +00:00
if ( ! named_metadata )
{
if ( log )
log - > PutCString ( " No global metadata " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: No metadata \n " ) ;
2010-08-12 01:56:52 +00:00
return false ;
}
unsigned num_nodes = named_metadata - > getNumOperands ( ) ;
unsigned node_index ;
MDNode * metadata_node = NULL ;
for ( node_index = 0 ;
node_index < num_nodes ;
+ + node_index )
{
metadata_node = named_metadata - > getOperand ( node_index ) ;
if ( metadata_node - > getNumOperands ( ) ! = 2 )
continue ;
if ( metadata_node - > getOperand ( 0 ) = = result_global )
break ;
}
if ( ! metadata_node )
{
if ( log )
log - > PutCString ( " Couldn't find result metadata " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Result variable (%s) is a global variable, but has no metadata \n " , result_name ) ;
2010-08-12 01:56:52 +00:00
return false ;
}
ConstantInt * constant_int = dyn_cast < ConstantInt > ( metadata_node - > getOperand ( 1 ) ) ;
2010-11-15 01:47:11 +00:00
lldb : : addr_t result_decl_intptr = constant_int - > getZExtValue ( ) ;
2010-08-12 01:56:52 +00:00
clang : : VarDecl * result_decl = reinterpret_cast < clang : : VarDecl * > ( result_decl_intptr ) ;
// Get the next available result name from m_decl_map and create the persistent
// variable for it
2011-01-13 08:53:35 +00:00
lldb_private : : TypeFromParser result_decl_type ;
if ( m_result_is_pointer )
{
clang : : QualType pointer_qual_type = result_decl - > getType ( ) ;
2011-01-27 04:42:51 +00:00
const clang : : Type * pointer_type = pointer_qual_type . getTypePtr ( ) ;
const clang : : PointerType * pointer_pointertype = dyn_cast < clang : : PointerType > ( pointer_type ) ;
2011-01-13 08:53:35 +00:00
if ( ! pointer_pointertype )
{
if ( log )
log - > PutCString ( " Expected result to have pointer type, but it did not " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable \n " , result_name ) ;
2011-01-13 08:53:35 +00:00
return false ;
}
clang : : QualType element_qual_type = pointer_pointertype - > getPointeeType ( ) ;
result_decl_type = lldb_private : : TypeFromParser ( element_qual_type . getAsOpaquePtr ( ) ,
& result_decl - > getASTContext ( ) ) ;
}
else
{
result_decl_type = lldb_private : : TypeFromParser ( result_decl - > getType ( ) . getAsOpaquePtr ( ) ,
& result_decl - > getASTContext ( ) ) ;
}
m_result_name = m_decl_map - > GetPersistentResultName ( ) ;
// If the result is an Lvalue, it is emitted as a pointer; see
// ASTResultSynthesizer::SynthesizeBodyResult.
m_decl_map - > AddPersistentVariable ( result_decl ,
m_result_name ,
result_decl_type ,
true ,
m_result_is_pointer ) ;
2010-08-12 01:56:52 +00:00
if ( log )
2011-01-13 08:53:35 +00:00
log - > Printf ( " Creating a new result global: \" %s \" " , m_result_name . GetCString ( ) ) ;
2010-08-12 01:56:52 +00:00
// Construct a new result global and set up its metadata
2010-10-15 22:48:33 +00:00
GlobalVariable * new_result_global = new GlobalVariable ( llvm_module ,
2010-08-12 01:56:52 +00:00
result_global - > getType ( ) - > getElementType ( ) ,
false , /* not constant */
GlobalValue : : ExternalLinkage ,
NULL , /* no initializer */
2011-01-13 08:53:35 +00:00
m_result_name . GetCString ( ) ) ;
2010-08-12 01:56:52 +00: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-15 22:48:33 +00:00
// Decl whose name is $__lldb_expr_result. This condition is handled in
2010-08-12 01:56:52 +00:00
// ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
// fixed up.
ConstantInt * new_constant_int = ConstantInt : : get ( constant_int - > getType ( ) ,
result_decl_intptr ,
false ) ;
llvm : : Value * values [ 2 ] ;
values [ 0 ] = new_result_global ;
values [ 1 ] = new_constant_int ;
2010-10-15 22:48:33 +00:00
MDNode * persistent_global_md = MDNode : : get ( llvm_module . getContext ( ) , values , 2 ) ;
2010-08-12 01:56:52 +00:00
named_metadata - > addOperand ( persistent_global_md ) ;
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Replacing \" %s \" with \" %s \" " ,
2010-09-07 22:43:19 +00:00
PrintValue ( result_global ) . c_str ( ) ,
2010-08-12 01:56:52 +00:00
PrintValue ( new_result_global ) . c_str ( ) ) ;
2010-09-07 22:43:19 +00:00
if ( result_global - > hasNUses ( 0 ) )
{
// We need to synthesize a store for this variable, because otherwise
// there's nothing to put into its equivalent persistent variable.
2010-10-15 22:48:33 +00:00
BasicBlock & entry_block ( llvm_function . getEntryBlock ( ) ) ;
2010-09-07 22:43:19 +00:00
Instruction * first_entry_instruction ( entry_block . getFirstNonPHIOrDbg ( ) ) ;
if ( ! first_entry_instruction )
return false ;
if ( ! result_global - > hasInitializer ( ) )
{
if ( log )
log - > Printf ( " Couldn't find initializer for unused variable " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer \n " , result_name ) ;
2010-09-07 22:43:19 +00:00
return false ;
}
Constant * initializer = result_global - > getInitializer ( ) ;
2010-12-16 03:17:46 +00:00
// Here we write the initializer into a result variable assuming it
// can be computed statically.
if ( ! m_has_side_effects )
{
MaybeSetConstantResult ( initializer ,
2011-01-13 08:53:35 +00:00
m_result_name ,
2010-12-16 03:17:46 +00:00
result_decl_type ) ;
}
2010-09-07 22:43:19 +00:00
2011-02-05 02:28:58 +00:00
StoreInst * synthesized_store = new StoreInst ( initializer ,
new_result_global ,
first_entry_instruction ) ;
2010-09-07 22:43:19 +00:00
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Synthesized result store \" %s \" \n " , PrintValue ( synthesized_store ) . c_str ( ) ) ;
2010-09-07 22:43:19 +00:00
}
else
{
result_global - > replaceAllUsesWith ( new_result_global ) ;
}
2010-08-12 01:56:52 +00:00
result_global - > eraseFromParent ( ) ;
return true ;
}
2010-11-19 01:05:25 +00:00
static void DebugUsers ( lldb : : LogSP & log , Value * value , uint8_t depth )
2010-11-17 23:00:36 +00:00
{
if ( ! depth )
return ;
depth - - ;
2010-11-19 01:05:25 +00:00
log - > Printf ( " <Begin %d users> " , value - > getNumUses ( ) ) ;
2010-11-17 23:00:36 +00:00
2010-11-19 01:05:25 +00:00
for ( Value : : use_iterator ui = value - > use_begin ( ) , ue = value - > use_end ( ) ;
2010-11-17 23:00:36 +00:00
ui ! = ue ;
+ + ui )
{
log - > Printf ( " <Use %p> %s " , * ui , PrintValue ( * ui ) . c_str ( ) ) ;
DebugUsers ( log , * ui , depth ) ;
}
log - > Printf ( " <End uses> " ) ;
}
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : RewriteObjCConstString ( llvm : : Module & llvm_module ,
llvm : : GlobalVariable * ns_str ,
llvm : : GlobalVariable * cstr ,
Instruction * FirstEntryInstruction )
2010-11-17 23:00:36 +00:00
{
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-11-19 01:05:25 +00:00
const Type * i8_ptr_ty = Type : : getInt8PtrTy ( llvm_module . getContext ( ) ) ;
const IntegerType * intptr_ty = Type : : getIntNTy ( llvm_module . getContext ( ) ,
( llvm_module . getPointerSize ( ) = = Module : : Pointer64 ) ? 64 : 32 ) ;
const Type * i32_ty = Type : : getInt32Ty ( llvm_module . getContext ( ) ) ;
const Type * i8_ty = Type : : getInt8Ty ( llvm_module . getContext ( ) ) ;
2010-11-17 23:00:36 +00:00
if ( ! m_CFStringCreateWithBytes )
{
lldb : : addr_t CFStringCreateWithBytes_addr ;
static lldb_private : : ConstString g_CFStringCreateWithBytes_str ( " CFStringCreateWithBytes " ) ;
if ( ! m_decl_map - > GetFunctionAddress ( g_CFStringCreateWithBytes_str , CFStringCreateWithBytes_addr ) )
{
if ( log )
log - > PutCString ( " Couldn't find CFStringCreateWithBytes in the target " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes \n " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
if ( log )
log - > Printf ( " Found CFStringCreateWithBytes at 0x%llx " , CFStringCreateWithBytes_addr ) ;
// Build the function type:
//
// CFStringRef CFStringCreateWithBytes (
// CFAllocatorRef alloc,
// const UInt8 *bytes,
// CFIndex numBytes,
// CFStringEncoding encoding,
// Boolean isExternalRepresentation
// );
//
// We make the following substitutions:
//
// CFStringRef -> i8*
// CFAllocatorRef -> i8*
// UInt8 * -> i8*
// CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now)
// CFStringEncoding -> i32
// Boolean -> i8
std : : vector < const Type * > CFSCWB_arg_types ;
CFSCWB_arg_types . push_back ( i8_ptr_ty ) ;
CFSCWB_arg_types . push_back ( i8_ptr_ty ) ;
CFSCWB_arg_types . push_back ( intptr_ty ) ;
CFSCWB_arg_types . push_back ( i32_ty ) ;
CFSCWB_arg_types . push_back ( i8_ty ) ;
llvm : : Type * CFSCWB_ty = FunctionType : : get ( i8_ptr_ty , CFSCWB_arg_types , false ) ;
// Build the constant containing the pointer to the function
PointerType * CFSCWB_ptr_ty = PointerType : : getUnqual ( CFSCWB_ty ) ;
Constant * CFSCWB_addr_int = ConstantInt : : get ( intptr_ty , CFStringCreateWithBytes_addr , false ) ;
m_CFStringCreateWithBytes = ConstantExpr : : getIntToPtr ( CFSCWB_addr_int , CFSCWB_ptr_ty ) ;
}
2011-02-10 22:17:53 +00:00
ConstantArray * string_array ;
if ( cstr )
string_array = dyn_cast < ConstantArray > ( cstr - > getInitializer ( ) ) ;
else
string_array = NULL ;
2010-11-17 23:00:36 +00:00
SmallVector < Value * , 5 > CFSCWB_arguments ;
Constant * alloc_arg = Constant : : getNullValue ( i8_ptr_ty ) ;
2011-02-10 22:17:53 +00:00
Constant * bytes_arg = cstr ? ConstantExpr : : getBitCast ( cstr , i8_ptr_ty ) : Constant : : getNullValue ( i8_ptr_ty ) ;
Constant * numBytes_arg = ConstantInt : : get ( intptr_ty , cstr ? string_array - > getType ( ) - > getNumElements ( ) - 1 : 0 , false ) ;
2010-11-17 23:00:36 +00: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 */
CFSCWB_arguments . push_back ( alloc_arg ) ;
CFSCWB_arguments . push_back ( bytes_arg ) ;
CFSCWB_arguments . push_back ( numBytes_arg ) ;
CFSCWB_arguments . push_back ( encoding_arg ) ;
CFSCWB_arguments . push_back ( isExternal_arg ) ;
CallInst * CFSCWB_call = CallInst : : Create ( m_CFStringCreateWithBytes ,
CFSCWB_arguments . begin ( ) ,
CFSCWB_arguments . end ( ) ,
" CFStringCreateWithBytes " ,
FirstEntryInstruction ) ;
2010-11-18 22:21:58 +00:00
2010-11-19 01:05:25 +00:00
if ( ! UnfoldConstant ( ns_str , CFSCWB_call , FirstEntryInstruction ) )
2010-11-17 23:00:36 +00:00
{
if ( log )
log - > PutCString ( " Couldn't replace the NSString with the result of the call " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Couldn't replace an Objective-C constant string with a dynamic string \n " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
2010-11-19 01:05:25 +00:00
ns_str - > eraseFromParent ( ) ;
2010-11-17 23:00:36 +00:00
return true ;
}
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : RewriteObjCConstStrings ( Module & llvm_module , Function & llvm_function )
2010-11-17 23:00:36 +00:00
{
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-11-19 01:05:25 +00:00
ValueSymbolTable & value_symbol_table = llvm_module . getValueSymbolTable ( ) ;
2010-11-17 23:00:36 +00:00
2010-11-19 01:05:25 +00:00
BasicBlock & entry_block ( llvm_function . getEntryBlock ( ) ) ;
2010-11-17 23:00:36 +00:00
Instruction * FirstEntryInstruction ( entry_block . getFirstNonPHIOrDbg ( ) ) ;
if ( ! FirstEntryInstruction )
{
if ( log )
log - > PutCString ( " Couldn't find first instruction for rewritten Objective-C strings " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't find the location for calls to CFStringCreateWithBytes \n " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
for ( ValueSymbolTable : : iterator vi = value_symbol_table . begin ( ) , ve = value_symbol_table . end ( ) ;
vi ! = ve ;
+ + vi )
{
if ( strstr ( vi - > first ( ) , " _unnamed_cfstring_ " ) )
{
Value * nsstring_value = vi - > second ;
GlobalVariable * nsstring_global = dyn_cast < GlobalVariable > ( nsstring_value ) ;
if ( ! nsstring_global )
{
if ( log )
log - > PutCString ( " NSString variable is not a GlobalVariable " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string is not a global variable \n " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
if ( ! nsstring_global - > hasInitializer ( ) )
{
if ( log )
log - > PutCString ( " NSString variable does not have an initializer " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string does not have an initializer \n " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
ConstantStruct * nsstring_struct = dyn_cast < ConstantStruct > ( nsstring_global - > getInitializer ( ) ) ;
if ( ! nsstring_struct )
{
if ( log )
log - > PutCString ( " NSString variable's initializer is not a ConstantStruct " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string is not a structure constant \n " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
// We expect the following structure:
//
// struct {
// int *isa;
// int flags;
// char *str;
// long length;
// };
if ( nsstring_struct - > getNumOperands ( ) ! = 4 )
{
if ( log )
log - > Printf ( " NSString variable's initializer structure has an unexpected number of members. Should be 4, is %d " , nsstring_struct - > getNumOperands ( ) ) ;
2011-01-27 01:07:04 +00: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 " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
Constant * nsstring_member = nsstring_struct - > getOperand ( 2 ) ;
if ( ! nsstring_member )
{
if ( log )
log - > PutCString ( " NSString initializer's str element was empty " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer \n " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
ConstantExpr * nsstring_expr = dyn_cast < ConstantExpr > ( nsstring_member ) ;
if ( ! nsstring_expr )
{
if ( log )
log - > PutCString ( " NSString initializer's str element is not a ConstantExpr " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant \n " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
if ( nsstring_expr - > getOpcode ( ) ! = Instruction : : GetElementPtr )
{
if ( log )
log - > Printf ( " NSString initializer's str element is not a GetElementPtr expression, it's a %s " , nsstring_expr - > getOpcodeName ( ) ) ;
2011-01-27 01:07:04 +00: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 " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
Constant * nsstring_cstr = nsstring_expr - > getOperand ( 0 ) ;
GlobalVariable * cstr_global = dyn_cast < GlobalVariable > ( nsstring_cstr ) ;
if ( ! cstr_global )
{
if ( log )
log - > PutCString ( " NSString initializer's str element is not a GlobalVariable " ) ;
2011-01-27 01:07:04 +00: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 " ) ;
2010-11-20 02:06:01 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
if ( ! cstr_global - > hasInitializer ( ) )
{
if ( log )
log - > PutCString ( " NSString initializer's str element does not have an initializer " ) ;
2011-01-27 01:07:04 +00: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 " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
2011-02-10 22:17:53 +00:00
/*
2010-11-17 23:00:36 +00:00
if (!cstr_array)
{
if (log)
log->PutCString("NSString initializer's str element is not a ConstantArray");
2011-01-27 01:07:04 +00: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");
2010-11-17 23:00:36 +00:00
return false;
}
if (!cstr_array->isCString())
{
if (log)
log->PutCString("NSString initializer's str element is not a C string array");
2011-01-27 01:07:04 +00: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");
2010-11-17 23:00:36 +00:00
return false;
}
2011-02-10 22:17:53 +00:00
*/
ConstantArray * cstr_array = dyn_cast < ConstantArray > ( cstr_global - > getInitializer ( ) ) ;
2010-11-17 23:00:36 +00:00
if ( log )
2011-02-10 22:17:53 +00:00
{
if ( cstr_array )
log - > Printf ( " Found NSString constant %s, which contains \" %s \" " , vi - > first ( ) , cstr_array - > getAsString ( ) . c_str ( ) ) ;
else
log - > Printf ( " Found NSString constant %s, which contains \" \" " , vi - > first ( ) ) ;
}
if ( ! cstr_array )
cstr_global = NULL ;
2010-11-17 23:00:36 +00:00
2010-11-19 01:05:25 +00:00
if ( ! RewriteObjCConstString ( llvm_module , nsstring_global , cstr_global , FirstEntryInstruction ) )
2011-01-27 01:07:04 +00:00
{
2010-11-17 23:00:36 +00:00
if ( log )
log - > PutCString ( " Error rewriting the constant string " ) ;
2011-01-27 01:07:04 +00:00
// We don't print an error message here because RewriteObjCConstString has done so for us.
2010-11-17 23:00:36 +00:00
return false ;
}
}
}
for ( ValueSymbolTable : : iterator vi = value_symbol_table . begin ( ) , ve = value_symbol_table . end ( ) ;
vi ! = ve ;
+ + vi )
{
if ( ! strcmp ( vi - > first ( ) , " __CFConstantStringClassReference " ) )
{
GlobalVariable * gv = dyn_cast < GlobalVariable > ( vi - > second ) ;
if ( ! gv )
{
if ( log )
log - > PutCString ( " __CFConstantStringClassReference is not a global variable " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object \n " ) ;
2010-11-17 23:00:36 +00:00
return false ;
}
gv - > eraseFromParent ( ) ;
break ;
}
}
return true ;
}
2010-11-19 01:05:25 +00:00
static bool IsObjCSelectorRef ( Value * value )
2010-07-31 01:32:05 +00:00
{
2010-11-19 01:05:25 +00:00
GlobalVariable * global_variable = dyn_cast < GlobalVariable > ( value ) ;
2010-07-31 01:32:05 +00:00
2010-11-19 01:05:25 +00:00
if ( ! global_variable | | ! global_variable - > hasName ( ) | | ! global_variable - > getName ( ) . startswith ( " \01 L_OBJC_SELECTOR_REFERENCES_ " ) )
2010-07-31 01:32:05 +00:00
return false ;
return true ;
}
2011-01-27 01:07:04 +00:00
// This function does not report errors; its callers are responsible.
2010-07-31 01:32:05 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : RewriteObjCSelector ( Instruction * selector_load , Module & llvm_module )
2010-07-31 01:32:05 +00:00
{
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-31 01:32:05 +00:00
LoadInst * load = dyn_cast < LoadInst > ( selector_load ) ;
if ( ! load )
return false ;
// Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as
//
// %tmp = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_" ; <i8*>
// %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*>
//
// where %obj is the object pointer and %tmp is the selector.
//
2010-11-19 01:05:25 +00:00
// @"\01L_OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_".
// @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string.
2010-07-31 01:32:05 +00:00
// Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target
GlobalVariable * _objc_selector_references_ = dyn_cast < GlobalVariable > ( load - > getPointerOperand ( ) ) ;
if ( ! _objc_selector_references_ | | ! _objc_selector_references_ - > hasInitializer ( ) )
return false ;
Constant * osr_initializer = _objc_selector_references_ - > getInitializer ( ) ;
ConstantExpr * osr_initializer_expr = dyn_cast < ConstantExpr > ( osr_initializer ) ;
if ( ! osr_initializer_expr | | osr_initializer_expr - > getOpcode ( ) ! = Instruction : : GetElementPtr )
return false ;
Value * osr_initializer_base = osr_initializer_expr - > getOperand ( 0 ) ;
if ( ! osr_initializer_base )
return false ;
// Find the string's initializer (a ConstantArray) and get the string from it
GlobalVariable * _objc_meth_var_name_ = dyn_cast < GlobalVariable > ( osr_initializer_base ) ;
if ( ! _objc_meth_var_name_ | | ! _objc_meth_var_name_ - > hasInitializer ( ) )
return false ;
Constant * omvn_initializer = _objc_meth_var_name_ - > getInitializer ( ) ;
ConstantArray * omvn_initializer_array = dyn_cast < ConstantArray > ( omvn_initializer ) ;
if ( ! omvn_initializer_array - > isString ( ) )
return false ;
std : : string omvn_initializer_string = omvn_initializer_array - > getAsString ( ) ;
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Found Objective-C selector reference \" %s \" " , omvn_initializer_string . c_str ( ) ) ;
2010-07-31 01:32:05 +00:00
// Construct a call to sel_registerName
if ( ! m_sel_registerName )
{
2010-11-15 01:47:11 +00:00
lldb : : addr_t sel_registerName_addr ;
2010-07-31 01:32:05 +00:00
2010-10-15 22:48:33 +00:00
static lldb_private : : ConstString g_sel_registerName_str ( " sel_registerName " ) ;
2010-11-15 01:47:11 +00:00
if ( ! m_decl_map - > GetFunctionAddress ( g_sel_registerName_str , sel_registerName_addr ) )
2010-07-31 01:32:05 +00:00
return false ;
2010-10-26 00:31:56 +00:00
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Found sel_registerName at 0x%llx " , sel_registerName_addr ) ;
2010-10-26 00:31:56 +00:00
2010-07-31 01:32:05 +00:00
// Build the function type: struct objc_selector *sel_registerName(uint8_t*)
// The below code would be "more correct," but in actuality what's required is uint8_t*
2010-11-19 01:05:25 +00:00
//Type *sel_type = StructType::get(llvm_module.getContext());
2010-07-31 01:32:05 +00:00
//Type *sel_ptr_type = PointerType::getUnqual(sel_type);
2010-11-19 01:05:25 +00:00
const Type * sel_ptr_type = Type : : getInt8PtrTy ( llvm_module . getContext ( ) ) ;
2010-07-31 01:32:05 +00:00
std : : vector < const Type * > srN_arg_types ;
2010-11-19 01:05:25 +00:00
srN_arg_types . push_back ( Type : : getInt8PtrTy ( llvm_module . getContext ( ) ) ) ;
2010-07-31 01:32:05 +00:00
llvm : : Type * srN_type = FunctionType : : get ( sel_ptr_type , srN_arg_types , false ) ;
// Build the constant containing the pointer to the function
2010-11-19 01:05:25 +00:00
const IntegerType * intptr_ty = Type : : getIntNTy ( llvm_module . getContext ( ) ,
( llvm_module . getPointerSize ( ) = = Module : : Pointer64 ) ? 64 : 32 ) ;
2010-07-31 01:32:05 +00:00
PointerType * srN_ptr_ty = PointerType : : getUnqual ( srN_type ) ;
2010-11-15 01:47:11 +00:00
Constant * srN_addr_int = ConstantInt : : get ( intptr_ty , sel_registerName_addr , false ) ;
2010-07-31 01:32:05 +00:00
m_sel_registerName = ConstantExpr : : getIntToPtr ( srN_addr_int , srN_ptr_ty ) ;
}
SmallVector < Value * , 1 > srN_arguments ;
2010-11-19 01:05:25 +00:00
Constant * omvn_pointer = ConstantExpr : : getBitCast ( _objc_meth_var_name_ , Type : : getInt8PtrTy ( llvm_module . getContext ( ) ) ) ;
2010-07-31 01:32:05 +00:00
srN_arguments . push_back ( omvn_pointer ) ;
CallInst * srN_call = CallInst : : Create ( m_sel_registerName ,
srN_arguments . begin ( ) ,
srN_arguments . end ( ) ,
2010-11-17 23:00:36 +00:00
" sel_registerName " ,
2010-07-31 01:32:05 +00:00
selector_load ) ;
// Replace the load with the call in all users
selector_load - > replaceAllUsesWith ( srN_call ) ;
selector_load - > eraseFromParent ( ) ;
return true ;
}
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : RewriteObjCSelectors ( Module & llvm_module , BasicBlock & basic_block )
2010-07-31 01:32:05 +00:00
{
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-31 01:32:05 +00:00
BasicBlock : : iterator ii ;
typedef SmallVector < Instruction * , 2 > InstrList ;
typedef InstrList : : iterator InstrIterator ;
InstrList selector_loads ;
2010-11-19 01:05:25 +00:00
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
2010-07-31 01:32:05 +00:00
+ + ii )
{
Instruction & inst = * ii ;
if ( LoadInst * load = dyn_cast < LoadInst > ( & inst ) )
2010-11-19 01:05:25 +00:00
if ( IsObjCSelectorRef ( load - > getPointerOperand ( ) ) )
2010-07-31 01:32:05 +00:00
selector_loads . push_back ( & inst ) ;
}
InstrIterator iter ;
for ( iter = selector_loads . begin ( ) ;
iter ! = selector_loads . end ( ) ;
+ + iter )
{
2010-11-19 01:05:25 +00:00
if ( ! RewriteObjCSelector ( * iter , llvm_module ) )
2010-07-31 01:32:05 +00:00
{
2011-01-27 01:07:04 +00: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 " ) ;
2010-07-31 01:32:05 +00:00
if ( log )
log - > PutCString ( " Couldn't rewrite a reference to an Objective-C selector " ) ;
2011-01-27 01:07:04 +00:00
2010-07-31 01:32:05 +00:00
return false ;
}
}
return true ;
}
2011-01-27 01:07:04 +00:00
// This function does not report errors; its callers are responsible.
2010-08-11 03:57:18 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : RewritePersistentAlloc ( llvm : : Instruction * persistent_alloc ,
llvm : : Module & llvm_module )
2010-08-11 03:57:18 +00:00
{
2011-01-13 21:23:32 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-08-11 03:57:18 +00:00
AllocaInst * alloc = dyn_cast < AllocaInst > ( persistent_alloc ) ;
MDNode * alloc_md = alloc - > getMetadata ( " clang.decl.ptr " ) ;
if ( ! alloc_md | | ! alloc_md - > getNumOperands ( ) )
return false ;
ConstantInt * constant_int = dyn_cast < ConstantInt > ( alloc_md - > getOperand ( 0 ) ) ;
if ( ! constant_int )
return false ;
// We attempt to register this as a new persistent variable with the DeclMap.
uintptr_t ptr = constant_int - > getZExtValue ( ) ;
2010-08-12 01:56:52 +00:00
clang : : VarDecl * decl = reinterpret_cast < clang : : VarDecl * > ( ptr ) ;
2010-08-11 03:57:18 +00:00
2010-08-12 01:56:52 +00:00
lldb_private : : TypeFromParser result_decl_type ( decl - > getType ( ) . getAsOpaquePtr ( ) ,
& decl - > getASTContext ( ) ) ;
2010-10-15 22:48:33 +00:00
StringRef decl_name ( decl - > getName ( ) ) ;
lldb_private : : ConstString persistent_variable_name ( decl_name . data ( ) , decl_name . size ( ) ) ;
2011-01-13 08:53:35 +00:00
if ( ! m_decl_map - > AddPersistentVariable ( decl , persistent_variable_name , result_decl_type , false , false ) )
2010-08-11 03:57:18 +00:00
return false ;
2011-01-13 21:23:32 +00:00
GlobalVariable * persistent_global = new GlobalVariable ( llvm_module ,
alloc - > getType ( ) ,
2010-08-11 03:57:18 +00:00
false , /* not constant */
GlobalValue : : ExternalLinkage ,
NULL , /* no initializer */
alloc - > getName ( ) . str ( ) . c_str ( ) ) ;
// What we're going to do here is make believe this was a regular old external
// variable. That means we need to make the metadata valid.
2010-10-15 22:48:33 +00:00
NamedMDNode * named_metadata = llvm_module . getNamedMetadata ( " clang.global.decl.ptrs " ) ;
2010-08-11 03:57:18 +00:00
llvm : : Value * values [ 2 ] ;
values [ 0 ] = persistent_global ;
values [ 1 ] = constant_int ;
2010-10-15 22:48:33 +00:00
MDNode * persistent_global_md = MDNode : : get ( llvm_module . getContext ( ) , values , 2 ) ;
2010-08-11 03:57:18 +00:00
named_metadata - > addOperand ( persistent_global_md ) ;
2011-01-13 21:23:32 +00:00
// Now, since the variable is a pointer variable, we will drop in a load of that
// pointer variable.
LoadInst * persistent_load = new LoadInst ( persistent_global , " " , alloc ) ;
if ( log )
log - > Printf ( " Replacing \" %s \" with \" %s \" " ,
PrintValue ( alloc ) . c_str ( ) ,
PrintValue ( persistent_load ) . c_str ( ) ) ;
alloc - > replaceAllUsesWith ( persistent_load ) ;
2010-08-11 03:57:18 +00:00
alloc - > eraseFromParent ( ) ;
return true ;
}
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : RewritePersistentAllocs ( llvm : : Module & llvm_module , llvm : : BasicBlock & basic_block )
2010-08-11 03:57:18 +00:00
{
2010-09-13 21:34:21 +00:00
if ( ! m_resolve_vars )
return true ;
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-08-11 03:57:18 +00:00
BasicBlock : : iterator ii ;
typedef SmallVector < Instruction * , 2 > InstrList ;
typedef InstrList : : iterator InstrIterator ;
InstrList pvar_allocs ;
2010-11-19 01:05:25 +00:00
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
2010-08-11 03:57:18 +00:00
+ + ii )
{
Instruction & inst = * ii ;
if ( AllocaInst * alloc = dyn_cast < AllocaInst > ( & inst ) )
2011-01-21 22:30:25 +00:00
{
llvm : : StringRef alloc_name = alloc - > getName ( ) ;
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. " ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names \n " ) ;
2011-01-21 22:30:25 +00:00
return false ;
}
2010-08-11 03:57:18 +00:00
pvar_allocs . push_back ( alloc ) ;
2011-01-21 22:30:25 +00:00
}
}
2010-08-11 03:57:18 +00:00
}
InstrIterator iter ;
for ( iter = pvar_allocs . begin ( ) ;
iter ! = pvar_allocs . end ( ) ;
+ + iter )
{
2010-11-19 01:05:25 +00:00
if ( ! RewritePersistentAlloc ( * iter , llvm_module ) )
2010-08-11 03:57:18 +00:00
{
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable \n " ) ;
2010-08-11 03:57:18 +00:00
if ( log )
log - > PutCString ( " Couldn't rewrite the creation of a persistent variable " ) ;
2011-01-27 01:07:04 +00:00
2010-08-11 03:57:18 +00:00
return false ;
}
}
return true ;
}
2010-07-13 21:41:46 +00:00
static clang : : NamedDecl *
2010-11-19 01:05:25 +00:00
DeclForGlobalValue ( Module & module , GlobalValue * global_value )
2010-07-13 21:41:46 +00:00
{
NamedMDNode * named_metadata = module . getNamedMetadata ( " clang.global.decl.ptrs " ) ;
if ( ! named_metadata )
return NULL ;
unsigned num_nodes = named_metadata - > getNumOperands ( ) ;
unsigned node_index ;
for ( node_index = 0 ;
node_index < num_nodes ;
+ + node_index )
{
MDNode * metadata_node = named_metadata - > getOperand ( node_index ) ;
if ( ! metadata_node )
return NULL ;
if ( metadata_node - > getNumOperands ( ) ! = 2 )
2010-08-11 03:57:18 +00:00
continue ;
2010-07-13 21:41:46 +00:00
if ( metadata_node - > getOperand ( 0 ) ! = global_value )
continue ;
ConstantInt * constant_int = dyn_cast < ConstantInt > ( metadata_node - > getOperand ( 1 ) ) ;
if ( ! constant_int )
return NULL ;
uintptr_t ptr = constant_int - > getZExtValue ( ) ;
return reinterpret_cast < clang : : NamedDecl * > ( ptr ) ;
}
return NULL ;
}
2011-01-27 01:07:04 +00:00
// This function does not report errors; its callers are responsible.
2010-07-13 21:41:46 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : MaybeHandleVariable ( Module & llvm_module , Value * llvm_value_ptr )
2010-07-03 01:35:46 +00:00
{
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-12-02 19:47:57 +00:00
if ( log )
2010-12-06 22:16:55 +00:00
log - > Printf ( " MaybeHandleVariable (%s) " , PrintValue ( llvm_value_ptr ) . c_str ( ) ) ;
2010-07-31 01:32:05 +00:00
2010-10-15 22:48:33 +00:00
if ( ConstantExpr * constant_expr = dyn_cast < ConstantExpr > ( llvm_value_ptr ) )
2010-08-03 00:23:29 +00:00
{
2010-08-04 01:02:13 +00:00
switch ( constant_expr - > getOpcode ( ) )
2010-08-03 00:23:29 +00:00
{
2010-08-04 01:02:13 +00:00
default :
break ;
case Instruction : : GetElementPtr :
case Instruction : : BitCast :
2010-08-03 00:23:29 +00:00
Value * s = constant_expr - > getOperand ( 0 ) ;
2010-12-02 19:47:57 +00:00
if ( ! MaybeHandleVariable ( llvm_module , s ) )
return false ;
2010-08-03 00:23:29 +00:00
}
}
2010-12-03 19:51:05 +00:00
else if ( GlobalVariable * global_variable = dyn_cast < GlobalVariable > ( llvm_value_ptr ) )
2010-07-31 01:32:05 +00:00
{
2010-10-15 22:48:33 +00:00
clang : : NamedDecl * named_decl = DeclForGlobalValue ( llvm_module , global_variable ) ;
2010-07-03 01:35:46 +00:00
2010-07-31 01:32:05 +00:00
if ( ! named_decl )
{
2010-11-19 01:05:25 +00:00
if ( IsObjCSelectorRef ( llvm_value_ptr ) )
2010-07-31 01:32:05 +00:00
return true ;
2010-12-06 00:56:39 +00:00
if ( ! global_variable - > hasExternalLinkage ( ) )
return true ;
2010-07-31 01:32:05 +00:00
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Found global variable \" %s \" without metadata " , global_variable - > getName ( ) . str ( ) . c_str ( ) ) ;
2011-01-27 01:07:04 +00:00
2010-07-31 01:32:05 +00:00
return false ;
}
2010-10-15 22:48:33 +00:00
std : : string name ( named_decl - > getName ( ) . str ( ) ) ;
2010-07-16 00:09:46 +00:00
2010-09-30 21:18:25 +00:00
void * opaque_type = NULL ;
2010-07-20 23:31:16 +00:00
clang : : ASTContext * ast_context = NULL ;
2010-07-16 00:09:46 +00:00
if ( clang : : ValueDecl * value_decl = dyn_cast < clang : : ValueDecl > ( named_decl ) )
2010-07-20 23:31:16 +00:00
{
2010-09-30 21:18:25 +00:00
opaque_type = value_decl - > getType ( ) . getAsOpaquePtr ( ) ;
2010-07-20 23:31:16 +00:00
ast_context = & value_decl - > getASTContext ( ) ;
}
2010-07-16 00:09:46 +00:00
else
2010-07-20 23:31:16 +00:00
{
2010-07-16 00:09:46 +00:00
return false ;
2010-07-20 23:31:16 +00:00
}
2010-09-30 21:18:25 +00:00
2011-01-13 08:53:35 +00:00
clang : : QualType qual_type ;
const Type * value_type ;
2011-01-13 21:23:32 +00:00
if ( name [ 0 ] = = ' $ ' )
2011-01-13 08:53:35 +00: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-13 21:23:32 +00:00
//
// We also do this for any user-declared persistent variables.
2010-07-20 23:31:16 +00:00
2011-01-13 08:53:35 +00:00
qual_type = ast_context - > getPointerType ( clang : : QualType : : getFromOpaquePtr ( opaque_type ) ) ;
value_type = PointerType : : get ( global_variable - > getType ( ) , 0 ) ;
}
else
{
qual_type = clang : : QualType : : getFromOpaquePtr ( opaque_type ) ;
value_type = global_variable - > getType ( ) ;
}
2010-09-30 21:18:25 +00:00
size_t value_size = ( ast_context - > getTypeSize ( qual_type ) + 7 ) / 8 ;
off_t value_alignment = ( ast_context - > getTypeAlign ( qual_type ) + 7 ) / 8 ;
2010-12-13 22:46:15 +00:00
2010-09-30 21:18:25 +00:00
if ( log )
2011-01-13 21:23:32 +00:00
log - > Printf ( " Type of \" %s \" is [clang \" %s \" , llvm \" %s \" ] [size %d, align %d] " ,
2010-09-30 21:18:25 +00:00
name . c_str ( ) ,
qual_type . getAsString ( ) . c_str ( ) ,
PrintType ( value_type ) . c_str ( ) ,
value_size ,
value_alignment ) ;
2010-12-13 22:46:15 +00:00
2010-07-13 21:41:46 +00:00
2010-08-23 23:09:38 +00:00
if ( named_decl & & ! m_decl_map - > AddValueToStruct ( named_decl ,
2010-10-15 22:48:33 +00:00
lldb_private : : ConstString ( name . c_str ( ) ) ,
llvm_value_ptr ,
2010-07-27 02:07:53 +00:00
value_size ,
value_alignment ) )
2010-07-13 21:41:46 +00:00
return false ;
}
2010-12-03 03:02:31 +00:00
else if ( dyn_cast < llvm : : Function > ( llvm_value_ptr ) )
2010-12-02 19:47:57 +00:00
{
if ( log )
log - > Printf ( " Function pointers aren't handled right now " ) ;
return false ;
}
2010-07-13 21:41:46 +00:00
return true ;
}
2011-01-27 01:07:04 +00:00
// This function does not report errors; its callers are responsible.
2011-01-17 23:42:46 +00:00
bool
IRForTarget : : HandleSymbol ( Module & llvm_module ,
Value * symbol )
{
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
lldb_private : : ConstString name ( symbol - > getName ( ) . str ( ) . c_str ( ) ) ;
uint64_t symbol_addr ;
if ( ! m_decl_map - > GetSymbolAddress ( name , symbol_addr ) )
{
if ( log )
log - > Printf ( " Symbol \" %s \" had no address " , name . GetCString ( ) ) ;
return false ;
}
if ( log )
log - > Printf ( " Found \" %s \" at 0x%llx " , name . GetCString ( ) , symbol_addr ) ;
const Type * symbol_type = symbol - > getType ( ) ;
const IntegerType * intptr_ty = Type : : getIntNTy ( llvm_module . getContext ( ) ,
( llvm_module . getPointerSize ( ) = = Module : : Pointer64 ) ? 64 : 32 ) ;
Constant * symbol_addr_int = ConstantInt : : get ( intptr_ty , symbol_addr , false ) ;
Value * symbol_addr_ptr = ConstantExpr : : getIntToPtr ( symbol_addr_int , symbol_type ) ;
if ( log )
log - > Printf ( " Replacing %s with %s " , PrintValue ( symbol ) . c_str ( ) , PrintValue ( symbol_addr_ptr ) . c_str ( ) ) ;
symbol - > replaceAllUsesWith ( symbol_addr_ptr ) ;
return true ;
}
2010-10-05 22:26:43 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : MaybeHandleCallArguments ( Module & llvm_module , CallInst * Old )
2010-10-05 22:26:43 +00:00
{
2010-12-02 19:47:57 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
if ( log )
log - > Printf ( " MaybeHandleCallArguments(%s) " , PrintValue ( Old ) . c_str ( ) ) ;
2010-10-05 22:26:43 +00:00
2010-11-17 23:00:36 +00:00
for ( unsigned op_index = 0 , num_ops = Old - > getNumArgOperands ( ) ;
2010-10-05 22:26:43 +00:00
op_index < num_ops ;
+ + op_index )
2010-11-19 01:05:25 +00:00
if ( ! MaybeHandleVariable ( llvm_module , Old - > getArgOperand ( op_index ) ) ) // conservatively believe that this is a store
2011-01-27 01:07:04 +00:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call. \n " ) ;
2010-10-05 22:26:43 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-10-05 22:26:43 +00:00
return true ;
}
2010-07-27 02:07:53 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : MaybeHandleCall ( Module & llvm_module , CallInst * llvm_call_inst )
2010-07-27 02:07:53 +00:00
{
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-27 02:07:53 +00:00
2010-10-15 22:48:33 +00:00
Function * fun = llvm_call_inst - > getCalledFunction ( ) ;
2010-07-27 02:07:53 +00:00
if ( fun = = NULL )
2010-09-08 20:04:08 +00:00
{
2010-10-15 22:48:33 +00:00
Value * val = llvm_call_inst - > getCalledValue ( ) ;
2010-09-08 20:04:08 +00:00
ConstantExpr * const_expr = dyn_cast < ConstantExpr > ( val ) ;
2011-01-27 04:42:51 +00:00
LoadInst * load_inst = dyn_cast < LoadInst > ( val ) ;
2010-09-08 20:04:08 +00:00
if ( const_expr & & const_expr - > getOpcode ( ) = = Instruction : : BitCast )
{
fun = dyn_cast < Function > ( const_expr - > getOperand ( 0 ) ) ;
if ( ! fun )
2011-01-27 01:07:04 +00:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Called entity is a cast of something not a function \n " ) ;
2010-12-02 19:47:57 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-09-08 20:04:08 +00:00
}
2010-12-06 23:53:20 +00:00
else if ( const_expr & & const_expr - > getOpcode ( ) = = Instruction : : IntToPtr )
{
return true ; // already resolved
}
2011-01-27 04:42:51 +00:00
else if ( load_inst )
{
return true ; // virtual method call
}
2010-09-08 20:04:08 +00:00
else
{
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Called entity is not a function \n " ) ;
2010-12-02 19:47:57 +00:00
return false ;
2010-09-08 20:04:08 +00:00
}
}
2010-07-27 02:07:53 +00:00
2010-10-15 22:48:33 +00:00
lldb_private : : ConstString str ;
2010-09-28 21:13:03 +00:00
2010-09-28 23:55:00 +00:00
if ( fun - > isIntrinsic ( ) )
2010-09-28 21:13:03 +00:00
{
2010-09-28 23:55:00 +00:00
Intrinsic : : ID intrinsic_id = ( Intrinsic : : ID ) fun - > getIntrinsicID ( ) ;
2010-09-28 21:13:03 +00:00
2010-09-28 23:55:00 +00:00
switch ( intrinsic_id )
{
default :
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Unresolved intrinsic \" %s \" " , Intrinsic : : getName ( intrinsic_id ) . c_str ( ) ) ;
2011-01-27 01:07:04 +00: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 ( ) ) ;
2010-09-28 23:55:00 +00:00
return false ;
case Intrinsic : : memcpy :
2010-10-15 22:48:33 +00:00
{
static lldb_private : : ConstString g_memcpy_str ( " memcpy " ) ;
str = g_memcpy_str ;
}
2010-09-28 23:55:00 +00:00
break ;
}
2010-09-28 21:13:03 +00:00
2010-10-15 22:48:33 +00:00
if ( log & & str )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Resolved intrinsic name \" %s \" " , str . GetCString ( ) ) ;
2010-09-28 23:55:00 +00:00
}
else
{
2010-10-15 22:48:33 +00:00
str . SetCStringWithLength ( fun - > getName ( ) . data ( ) , fun - > getName ( ) . size ( ) ) ;
2010-09-28 21:13:03 +00:00
}
2010-10-15 22:48:33 +00:00
clang : : NamedDecl * fun_decl = DeclForGlobalValue ( llvm_module , fun ) ;
2010-11-15 01:47:11 +00:00
lldb : : addr_t fun_addr = LLDB_INVALID_ADDRESS ;
2010-07-31 01:32:05 +00:00
Value * * fun_value_ptr = NULL ;
2010-07-27 02:07:53 +00:00
2010-07-31 01:32:05 +00:00
if ( fun_decl )
2010-07-27 02:07:53 +00:00
{
2010-10-15 22:48:33 +00:00
if ( ! m_decl_map - > GetFunctionInfo ( fun_decl , fun_value_ptr , fun_addr ) )
2010-07-31 01:32:05 +00:00
{
2010-09-07 21:49:41 +00:00
fun_value_ptr = NULL ;
2010-10-15 22:48:33 +00:00
if ( ! m_decl_map - > GetFunctionAddress ( str , fun_addr ) )
2010-09-07 21:49:41 +00:00
{
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Function \" %s \" had no address " , str . GetCString ( ) ) ;
2010-09-07 21:49:41 +00:00
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Call to a function '%s' that is not present in the target \n " , str . GetCString ( ) ) ;
2010-09-07 21:49:41 +00:00
return false ;
}
2010-07-31 01:32:05 +00:00
}
}
else
{
2010-10-15 22:48:33 +00:00
if ( ! m_decl_map - > GetFunctionAddress ( str , fun_addr ) )
2010-07-31 01:32:05 +00:00
{
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Metadataless function \" %s \" had no address " , str . GetCString ( ) ) ;
2011-01-27 01:07:04 +00: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 " , str . GetCString ( ) ) ;
return false ;
2010-07-31 01:32:05 +00:00
}
2010-07-27 02:07:53 +00:00
}
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Found \" %s \" at 0x%llx " , str . GetCString ( ) , fun_addr ) ;
2010-07-27 02:07:53 +00:00
2010-07-31 01:32:05 +00:00
Value * fun_addr_ptr ;
if ( ! fun_value_ptr | | ! * fun_value_ptr )
2010-07-27 21:39:39 +00:00
{
2010-10-15 22:48:33 +00:00
const IntegerType * intptr_ty = Type : : getIntNTy ( llvm_module . getContext ( ) ,
( llvm_module . getPointerSize ( ) = = Module : : Pointer64 ) ? 64 : 32 ) ;
2010-09-07 21:49:41 +00:00
const FunctionType * fun_ty = fun - > getFunctionType ( ) ;
2010-07-27 21:39:39 +00:00
PointerType * fun_ptr_ty = PointerType : : getUnqual ( fun_ty ) ;
Constant * fun_addr_int = ConstantInt : : get ( intptr_ty , fun_addr , false ) ;
2010-07-31 01:32:05 +00:00
fun_addr_ptr = ConstantExpr : : getIntToPtr ( fun_addr_int , fun_ptr_ty ) ;
if ( fun_value_ptr )
* fun_value_ptr = fun_addr_ptr ;
2010-07-27 21:39:39 +00:00
}
2010-07-31 01:32:05 +00:00
if ( fun_value_ptr )
fun_addr_ptr = * fun_value_ptr ;
2010-07-27 21:39:39 +00:00
2010-10-15 22:48:33 +00:00
llvm_call_inst - > setCalledFunction ( fun_addr_ptr ) ;
2010-07-27 21:39:39 +00:00
2010-10-15 22:48:33 +00:00
ConstantArray * func_name = ( ConstantArray * ) ConstantArray : : get ( llvm_module . getContext ( ) , str . GetCString ( ) ) ;
2010-09-13 21:34:21 +00:00
Value * values [ 1 ] ;
values [ 0 ] = func_name ;
2010-10-15 22:48:33 +00:00
MDNode * func_metadata = MDNode : : get ( llvm_module . getContext ( ) , values , 1 ) ;
2010-09-13 21:34:21 +00:00
2010-10-15 22:48:33 +00:00
llvm_call_inst - > setMetadata ( " lldb.call.realName " , func_metadata ) ;
2010-09-13 21:34:21 +00:00
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Set metadata for %p [%d, \" %s \" ] " , llvm_call_inst , func_name - > isString ( ) , func_name - > getAsString ( ) . c_str ( ) ) ;
2010-09-13 21:34:21 +00:00
2010-07-27 02:07:53 +00:00
return true ;
}
2010-07-13 21:41:46 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : ResolveCalls ( Module & llvm_module , BasicBlock & basic_block )
2010-07-13 21:41:46 +00:00
{
2010-07-03 01:35:46 +00:00
/////////////////////////////////////////////////////////////////////////
// Prepare the current basic block for execution in the remote process
//
2010-07-27 21:39:39 +00:00
BasicBlock : : iterator ii ;
2010-07-13 21:41:46 +00:00
2010-11-19 01:05:25 +00:00
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
2010-07-13 21:41:46 +00:00
+ + ii )
2010-07-03 01:35:46 +00:00
{
2010-07-13 21:41:46 +00:00
Instruction & inst = * ii ;
2010-07-03 01:35:46 +00:00
2010-11-08 00:31:32 +00:00
CallInst * call = dyn_cast < CallInst > ( & inst ) ;
2010-07-27 02:07:53 +00:00
2011-01-27 01:07:04 +00:00
// MaybeHandleCall handles error reporting; we are silent here
2010-11-19 01:05:25 +00:00
if ( call & & ! MaybeHandleCall ( llvm_module , call ) )
2010-11-08 00:31:32 +00:00
return false ;
2010-12-02 19:47:57 +00:00
2011-01-27 01:07:04 +00:00
// MaybeHandleCallArguments handles error reporting; we are silent here
2010-12-02 19:47:57 +00:00
if ( call & & ! MaybeHandleCallArguments ( llvm_module , call ) )
return false ;
2010-07-03 01:35:46 +00:00
}
return true ;
}
2010-11-08 00:31:32 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : ResolveExternals ( Module & llvm_module , Function & llvm_function )
2010-11-08 00:31:32 +00:00
{
2010-11-18 22:21:58 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-11-19 01:05:25 +00:00
for ( Module : : global_iterator global = llvm_module . global_begin ( ) , end = llvm_module . global_end ( ) ;
2010-11-08 00:31:32 +00:00
global ! = end ;
+ + global )
{
2010-11-19 01:05:25 +00:00
if ( log )
log - > Printf ( " Examining %s, DeclForGlobalValue returns %p " ,
( * global ) . getName ( ) . str ( ) . c_str ( ) ,
DeclForGlobalValue ( llvm_module , global ) ) ;
2011-01-17 23:42:46 +00:00
if ( ( * global ) . getName ( ) . str ( ) . find ( " OBJC_IVAR " ) = = 0 )
{
if ( ! HandleSymbol ( llvm_module , global ) )
2011-01-27 01:07:04 +00:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s \n " , ( * global ) . getName ( ) . str ( ) . c_str ( ) ) ;
2011-01-17 23:42:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2011-01-17 23:42:46 +00:00
}
else if ( DeclForGlobalValue ( llvm_module , global ) )
{
if ( ! MaybeHandleVariable ( llvm_module , global ) )
2011-01-27 01:07:04 +00:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't rewrite external variable %s \n " , ( * global ) . getName ( ) . str ( ) . c_str ( ) ) ;
2011-01-17 23:42:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2011-01-17 23:42:46 +00:00
}
2010-11-08 00:31:32 +00:00
}
return true ;
}
2010-07-27 21:39:39 +00:00
static bool isGuardVariableRef ( Value * V )
2010-07-24 01:37:44 +00:00
{
2010-11-17 23:00:36 +00:00
Constant * Old ;
2010-07-24 01:37:44 +00:00
2010-11-17 23:00:36 +00:00
if ( ! ( Old = dyn_cast < Constant > ( V ) ) )
2010-07-24 01:37:44 +00:00
return false ;
2010-09-23 03:01:22 +00:00
ConstantExpr * CE ;
if ( ( CE = dyn_cast < ConstantExpr > ( V ) ) )
{
if ( CE - > getOpcode ( ) ! = Instruction : : BitCast )
return false ;
2010-11-17 23:00:36 +00:00
Old = CE - > getOperand ( 0 ) ;
2010-09-23 03:01:22 +00:00
}
2010-11-17 23:00:36 +00:00
GlobalVariable * GV = dyn_cast < GlobalVariable > ( Old ) ;
2010-07-24 01:37:44 +00:00
if ( ! GV | | ! GV - > hasName ( ) | | ! GV - > getName ( ) . startswith ( " _ZGV " ) )
return false ;
return true ;
}
2010-11-19 01:05:25 +00:00
static void TurnGuardLoadIntoZero ( Instruction * guard_load , Module & llvm_module )
2010-07-24 01:37:44 +00:00
{
2010-11-19 01:05:25 +00:00
Constant * zero ( ConstantInt : : get ( Type : : getInt8Ty ( llvm_module . getContext ( ) ) , 0 , true ) ) ;
2010-07-24 01:37:44 +00:00
Value : : use_iterator ui ;
for ( ui = guard_load - > use_begin ( ) ;
ui ! = guard_load - > use_end ( ) ;
+ + ui )
2010-07-27 01:17:28 +00:00
{
2010-07-30 20:30:44 +00:00
if ( isa < Constant > ( * ui ) )
2010-07-27 01:17:28 +00:00
{
// do nothing for the moment
}
else
{
ui - > replaceUsesOfWith ( guard_load , zero ) ;
}
}
2010-07-24 01:37:44 +00:00
guard_load - > eraseFromParent ( ) ;
}
static void ExciseGuardStore ( Instruction * guard_store )
{
guard_store - > eraseFromParent ( ) ;
}
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : RemoveGuards ( Module & llvm_module , BasicBlock & basic_block )
2010-07-24 01:37:44 +00:00
{
///////////////////////////////////////////////////////
// Eliminate any reference to guard variables found.
//
2010-07-27 21:39:39 +00:00
BasicBlock : : iterator ii ;
2010-07-24 01:37:44 +00:00
2010-07-27 21:39:39 +00:00
typedef SmallVector < Instruction * , 2 > InstrList ;
2010-07-24 01:37:44 +00:00
typedef InstrList : : iterator InstrIterator ;
InstrList guard_loads ;
InstrList guard_stores ;
2010-11-19 01:05:25 +00:00
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
2010-07-24 01:37:44 +00:00
+ + ii )
{
Instruction & inst = * ii ;
if ( LoadInst * load = dyn_cast < LoadInst > ( & inst ) )
if ( isGuardVariableRef ( load - > getPointerOperand ( ) ) )
guard_loads . push_back ( & inst ) ;
if ( StoreInst * store = dyn_cast < StoreInst > ( & inst ) )
if ( isGuardVariableRef ( store - > getPointerOperand ( ) ) )
guard_stores . push_back ( & inst ) ;
}
InstrIterator iter ;
for ( iter = guard_loads . begin ( ) ;
iter ! = guard_loads . end ( ) ;
+ + iter )
2010-11-19 01:05:25 +00:00
TurnGuardLoadIntoZero ( * iter , llvm_module ) ;
2010-07-24 01:37:44 +00:00
for ( iter = guard_stores . begin ( ) ;
iter ! = guard_stores . end ( ) ;
+ + iter )
ExciseGuardStore ( * iter ) ;
return true ;
}
2011-01-27 01:07:04 +00:00
// This function does not report errors; its callers are responsible.
2010-11-17 23:00:36 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : UnfoldConstant ( Constant * old_constant , Value * new_constant , Instruction * first_entry_inst )
2010-07-14 23:40:29 +00:00
{
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-14 23:40:29 +00:00
Value : : use_iterator ui ;
2010-08-11 03:57:18 +00:00
SmallVector < User * , 16 > users ;
// We do this because the use list might change, invalidating our iterator.
// Much better to keep a work list ourselves.
2010-11-19 01:05:25 +00:00
for ( ui = old_constant - > use_begin ( ) ;
ui ! = old_constant - > use_end ( ) ;
2010-07-14 23:40:29 +00:00
+ + ui )
2010-08-11 03:57:18 +00:00
users . push_back ( * ui ) ;
2010-07-14 23:40:29 +00:00
2010-08-11 03:57:18 +00:00
for ( int i = 0 ;
i < users . size ( ) ;
+ + i )
{
User * user = users [ i ] ;
2010-07-14 23:40:29 +00:00
if ( Constant * constant = dyn_cast < Constant > ( user ) )
{
// synthesize a new non-constant equivalent of the constant
if ( ConstantExpr * constant_expr = dyn_cast < ConstantExpr > ( constant ) )
{
switch ( constant_expr - > getOpcode ( ) )
{
default :
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Unhandled constant expression type: \" %s \" " , PrintValue ( constant_expr ) . c_str ( ) ) ;
2010-07-14 23:40:29 +00:00
return false ;
case Instruction : : BitCast :
{
// UnaryExpr
// OperandList[0] is value
Value * s = constant_expr - > getOperand ( 0 ) ;
2010-11-19 01:05:25 +00:00
if ( s = = old_constant )
s = new_constant ;
2010-07-14 23:40:29 +00:00
2010-11-19 01:05:25 +00:00
BitCastInst * bit_cast ( new BitCastInst ( s , old_constant - > getType ( ) , " " , first_entry_inst ) ) ;
2010-07-14 23:40:29 +00:00
2010-11-19 01:05:25 +00:00
UnfoldConstant ( constant_expr , bit_cast , first_entry_inst ) ;
2010-07-14 23:40:29 +00:00
}
break ;
case Instruction : : GetElementPtr :
{
// GetElementPtrConstantExpr
// OperandList[0] is base
// OperandList[1]... are indices
Value * ptr = constant_expr - > getOperand ( 0 ) ;
2010-11-19 01:05:25 +00:00
if ( ptr = = old_constant )
ptr = new_constant ;
2010-07-14 23:40:29 +00:00
SmallVector < Value * , 16 > indices ;
unsigned operand_index ;
unsigned num_operands = constant_expr - > getNumOperands ( ) ;
for ( operand_index = 1 ;
operand_index < num_operands ;
+ + operand_index )
{
Value * operand = constant_expr - > getOperand ( operand_index ) ;
2010-11-19 01:05:25 +00:00
if ( operand = = old_constant )
operand = new_constant ;
2010-07-14 23:40:29 +00:00
indices . push_back ( operand ) ;
}
2010-11-19 01:05:25 +00:00
GetElementPtrInst * get_element_ptr ( GetElementPtrInst : : Create ( ptr , indices . begin ( ) , indices . end ( ) , " " , first_entry_inst ) ) ;
2010-07-14 23:40:29 +00:00
2010-11-19 01:05:25 +00:00
UnfoldConstant ( constant_expr , get_element_ptr , first_entry_inst ) ;
2010-07-14 23:40:29 +00:00
}
break ;
}
}
else
{
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Unhandled constant type: \" %s \" " , PrintValue ( constant ) . c_str ( ) ) ;
2010-07-14 23:40:29 +00:00
return false ;
}
}
else
{
// simple fall-through case for non-constants
2010-11-19 01:05:25 +00:00
user - > replaceUsesOfWith ( old_constant , new_constant ) ;
2010-07-14 23:40:29 +00:00
}
}
return true ;
}
2010-07-13 21:41:46 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : ReplaceVariables ( Module & llvm_module , Function & llvm_function )
2010-07-13 21:41:46 +00:00
{
2010-09-13 21:34:21 +00:00
if ( ! m_resolve_vars )
return true ;
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-13 21:41:46 +00:00
m_decl_map - > DoStructLayout ( ) ;
if ( log )
log - > Printf ( " Element arrangement: " ) ;
uint32_t num_elements ;
uint32_t element_index ;
size_t size ;
off_t alignment ;
if ( ! m_decl_map - > GetStructInfo ( num_elements , size , alignment ) )
return false ;
2010-11-19 01:05:25 +00:00
Function : : arg_iterator iter ( llvm_function . getArgumentList ( ) . begin ( ) ) ;
2010-07-13 21:41:46 +00:00
2010-11-19 01:05:25 +00:00
if ( iter = = llvm_function . getArgumentList ( ) . end ( ) )
2011-01-27 01:07:04 +00:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer) " ) ;
2010-07-13 21:41:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-07-27 21:39:39 +00:00
Argument * argument = iter ;
2010-07-13 21:41:46 +00:00
2010-09-21 00:44:12 +00:00
if ( argument - > getName ( ) . equals ( " this " ) )
{
+ + iter ;
2010-11-19 01:05:25 +00:00
if ( iter = = llvm_function . getArgumentList ( ) . end ( ) )
2011-01-27 01:07:04 +00:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too) " ) ;
2010-09-21 00:44:12 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-09-21 00:44:12 +00:00
argument = iter ;
}
2010-12-13 22:46:15 +00:00
else if ( argument - > getName ( ) . equals ( " self " ) )
{
+ + iter ;
if ( iter = = llvm_function . getArgumentList ( ) . end ( ) )
2011-01-27 01:07:04 +00: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) " ) ;
2010-12-13 22:46:15 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-12-13 22:46:15 +00:00
if ( ! iter - > getName ( ) . equals ( " _cmd " ) )
2011-01-27 01:07:04 +00: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 ( ) ) ;
2010-12-13 22:46:15 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-12-13 22:46:15 +00:00
+ + iter ;
if ( iter = = llvm_function . getArgumentList ( ) . end ( ) )
2011-01-27 01:07:04 +00: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) " ) ;
2010-12-13 22:46:15 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-12-13 22:46:15 +00:00
argument = iter ;
}
2010-09-21 00:44:12 +00:00
2010-10-15 22:48:33 +00:00
if ( ! argument - > getName ( ) . equals ( " $__lldb_arg " ) )
2011-01-27 01:07:04 +00: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 ( ) ) ;
2010-07-13 21:41:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-07-13 21:41:46 +00:00
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Arg: \" %s \" " , PrintValue ( argument ) . c_str ( ) ) ;
2010-07-13 21:41:46 +00:00
2010-11-19 01:05:25 +00:00
BasicBlock & entry_block ( llvm_function . getEntryBlock ( ) ) ;
2010-11-17 23:00:36 +00:00
Instruction * FirstEntryInstruction ( entry_block . getFirstNonPHIOrDbg ( ) ) ;
2010-07-13 21:41:46 +00:00
2010-11-17 23:00:36 +00:00
if ( ! FirstEntryInstruction )
2011-01-27 01:07:04 +00: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 " ) ;
2010-07-13 21:41:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-07-13 21:41:46 +00:00
2010-11-19 01:05:25 +00:00
LLVMContext & context ( llvm_module . getContext ( ) ) ;
2010-07-13 21:41:46 +00:00
const IntegerType * offset_type ( Type : : getInt32Ty ( context ) ) ;
if ( ! offset_type )
2011-01-27 01:07:04 +00:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't produce an offset type " ) ;
2010-07-13 21:41:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-07-13 21:41:46 +00:00
for ( element_index = 0 ; element_index < num_elements ; + + element_index )
{
const clang : : NamedDecl * decl ;
2010-07-27 21:39:39 +00:00
Value * value ;
2010-07-13 21:41:46 +00:00
off_t offset ;
2010-10-15 22:48:33 +00:00
lldb_private : : ConstString name ;
2010-07-13 21:41:46 +00:00
2010-08-30 22:17:16 +00:00
if ( ! m_decl_map - > GetStructElement ( decl , value , offset , name , element_index ) )
2011-01-27 01:07:04 +00:00
{
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Structure information is incomplete " ) ;
2010-07-13 21:41:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2010-07-13 21:41:46 +00:00
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " \" %s \" [ \" %s \" ] ( \" %s \" ) placed at %d " ,
2010-08-12 01:56:52 +00:00
value - > getName ( ) . str ( ) . c_str ( ) ,
2010-10-15 22:48:33 +00:00
name . GetCString ( ) ,
2010-07-13 21:41:46 +00:00
PrintValue ( value , true ) . c_str ( ) ,
offset ) ;
ConstantInt * offset_int ( ConstantInt : : getSigned ( offset_type , offset ) ) ;
2010-11-17 23:00:36 +00:00
GetElementPtrInst * get_element_ptr = GetElementPtrInst : : Create ( argument , offset_int , " " , FirstEntryInstruction ) ;
2011-01-13 08:53:35 +00:00
Value * replacement ;
2010-07-13 21:41:46 +00:00
2011-01-13 08:53:35 +00:00
// 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.
if ( name = = m_result_name & & ! m_result_is_pointer )
{
BitCastInst * bit_cast = new BitCastInst ( get_element_ptr , value - > getType ( ) - > getPointerTo ( ) , " " , FirstEntryInstruction ) ;
LoadInst * load = new LoadInst ( bit_cast , " " , FirstEntryInstruction ) ;
replacement = load ;
}
2010-07-14 23:40:29 +00:00
else
2011-01-13 08:53:35 +00:00
{
BitCastInst * bit_cast = new BitCastInst ( get_element_ptr , value - > getType ( ) , " " , FirstEntryInstruction ) ;
replacement = bit_cast ;
}
if ( Constant * constant = dyn_cast < Constant > ( value ) )
UnfoldConstant ( constant , replacement , FirstEntryInstruction ) ;
else
value - > replaceAllUsesWith ( replacement ) ;
2010-11-02 23:51:17 +00:00
if ( GlobalVariable * var = dyn_cast < GlobalVariable > ( value ) )
var - > eraseFromParent ( ) ;
2010-07-13 21:41:46 +00:00
}
if ( log )
log - > Printf ( " Total structure [align %d, size %d] " , alignment , size ) ;
return true ;
}
2010-07-03 01:35:46 +00:00
bool
2010-11-19 01:05:25 +00:00
IRForTarget : : runOnModule ( Module & llvm_module )
2010-07-03 01:35:46 +00:00
{
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-03 01:35:46 +00:00
2010-11-19 01:05:25 +00:00
Function * function = llvm_module . getFunction ( StringRef ( m_func_name . c_str ( ) ) ) ;
2010-07-03 01:35:46 +00:00
if ( ! function )
{
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Couldn't find \" %s() \" in the module " , m_func_name . c_str ( ) ) ;
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't find wrapper '%s' in the mdoule " , m_func_name . c_str ( ) ) ;
2011-01-13 08:53:35 +00:00
2010-07-03 01:35:46 +00:00
return false ;
}
2010-07-27 21:39:39 +00:00
Function : : iterator bbi ;
2010-07-03 01:35:46 +00:00
2010-12-16 03:17:46 +00:00
m_has_side_effects = HasSideEffects ( llvm_module , * function ) ;
2010-08-12 01:56:52 +00:00
////////////////////////////////////////////////////////////
2010-10-15 22:48:33 +00:00
// Replace $__lldb_expr_result with a persistent variable
2010-08-12 01:56:52 +00:00
//
2010-11-19 01:05:25 +00:00
if ( ! CreateResultVariable ( llvm_module , * function ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " CreateResultVariable() failed " ) ;
2011-01-27 01:07:04 +00:00
// CreateResultVariable() reports its own errors, so we don't do so here
2010-08-12 01:56:52 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2010-08-12 01:56:52 +00:00
2010-11-17 23:00:36 +00:00
///////////////////////////////////////////////////////////////////////////////
// Fix all Objective-C constant strings to use NSStringWithCString:encoding:
//
2010-11-19 01:05:25 +00:00
if ( ! RewriteObjCConstStrings ( llvm_module , * function ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " RewriteObjCConstStrings() failed " ) ;
2011-01-27 01:07:04 +00:00
// RewriteObjCConstStrings() reports its own errors, so we don't do so here
2010-11-17 23:00:36 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2010-11-17 23:00:36 +00:00
2010-07-31 01:32:05 +00:00
//////////////////////////////////
// Run basic-block level passes
//
2010-07-03 01:35:46 +00:00
for ( bbi = function - > begin ( ) ;
bbi ! = function - > end ( ) ;
+ + bbi )
{
2010-11-19 01:05:25 +00:00
if ( ! RemoveGuards ( llvm_module , * bbi ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " RemoveGuards() failed " ) ;
2011-01-27 01:07:04 +00:00
// RemoveGuards() reports its own errors, so we don't do so here
2010-08-23 23:09:38 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2010-08-23 23:09:38 +00:00
2010-11-19 01:05:25 +00:00
if ( ! RewritePersistentAllocs ( llvm_module , * bbi ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " RewritePersistentAllocs() failed " ) ;
2011-01-27 01:07:04 +00:00
// RewritePersistentAllocs() reports its own errors, so we don't do so here
2010-07-31 01:32:05 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2010-07-31 01:32:05 +00:00
2010-11-19 01:05:25 +00:00
if ( ! RewriteObjCSelectors ( llvm_module , * bbi ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " RewriteObjCSelectors() failed " ) ;
2011-01-27 01:07:04 +00:00
// RewriteObjCSelectors() reports its own errors, so we don't do so here
2010-08-11 03:57:18 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2010-08-11 03:57:18 +00:00
2010-11-19 01:05:25 +00:00
if ( ! ResolveCalls ( llvm_module , * bbi ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " ResolveCalls() failed " ) ;
2011-01-27 01:07:04 +00:00
// ResolveCalls() reports its own errors, so we don't do so here
2010-07-13 21:41:46 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2010-07-13 21:41:46 +00:00
}
2010-09-30 21:18:25 +00:00
///////////////////////////////
// Run function-level passes
//
2010-11-19 01:05:25 +00:00
if ( ! ResolveExternals ( llvm_module , * function ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " ResolveExternals() failed " ) ;
2011-01-27 01:07:04 +00:00
// ResolveExternals() reports its own errors, so we don't do so here
2010-11-08 00:31:32 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2010-11-08 00:31:32 +00:00
2010-11-19 01:05:25 +00:00
if ( ! ReplaceVariables ( llvm_module , * function ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " ReplaceVariables() failed " ) ;
2011-01-27 01:07:04 +00:00
// ReplaceVariables() reports its own errors, so we don't do so here
2010-09-30 21:18:25 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2010-09-30 21:18:25 +00:00
2010-07-13 21:41:46 +00:00
if ( log )
{
2010-07-28 01:00:59 +00:00
std : : string s ;
raw_string_ostream oss ( s ) ;
2010-07-13 21:41:46 +00:00
2010-11-19 01:05:25 +00:00
llvm_module . print ( oss , NULL ) ;
2010-07-28 01:00:59 +00:00
oss . flush ( ) ;
2010-11-15 01:47:11 +00:00
log - > Printf ( " Module after preparing for execution: \n \" %s \" " , s . c_str ( ) ) ;
2010-07-03 01:35:46 +00:00
}
return true ;
}
void
2010-11-19 01:05:25 +00:00
IRForTarget : : assignPassManager ( PMStack & pass_mgr_stack , PassManagerType pass_mgr_type )
2010-07-03 01:35:46 +00:00
{
}
PassManagerType
IRForTarget : : getPotentialPassManagerType ( ) const
{
return PMT_ModulePassManager ;
}