2011-09-15 02:13:07 +00:00
//===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===//
2010-07-03 01:35:46 +00: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 12:20:07 +00: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"
2012-09-24 22:25:51 +00:00
# include "llvm/PassManager.h"
# include "llvm/Transforms/IPO.h"
2013-01-02 12:20:07 +00:00
# include "llvm/IR/ValueSymbolTable.h"
2010-07-13 21:41:46 +00:00
# include "clang/AST/ASTContext.h"
2010-07-03 01:35:46 +00:00
# include "lldb/Core/dwarf.h"
2013-03-19 00:10:07 +00:00
# include "lldb/Core/ConstString.h"
# include "lldb/Core/DataBufferHeap.h"
2010-07-03 01:35:46 +00:00
# include "lldb/Core/Log.h"
# include "lldb/Core/Scalar.h"
# include "lldb/Core/StreamString.h"
# include "lldb/Expression/ClangExpressionDeclMap.h"
2013-03-19 00:10:07 +00:00
# include "lldb/Expression/IRExecutionUnit.h"
2011-09-15 02:13:07 +00:00
# include "lldb/Expression/IRInterpreter.h"
2011-05-23 21:40:23 +00:00
# include "lldb/Host/Endian.h"
2011-05-07 01:06:41 +00:00
# include "lldb/Symbol/ClangASTContext.h"
2013-07-11 22:46:58 +00:00
# include "lldb/Symbol/ClangASTType.h"
2010-07-03 01:35:46 +00:00
# include <map>
using namespace llvm ;
2010-08-18 18:50:51 +00:00
static char ID ;
2013-03-19 00:10:07 +00:00
IRForTarget : : StaticDataAllocator : : StaticDataAllocator ( lldb_private : : IRExecutionUnit & execution_unit ) :
m_execution_unit ( execution_unit ) ,
2013-04-18 22:06:33 +00:00
m_stream_string ( lldb_private : : Stream : : eBinary , execution_unit . GetAddressByteSize ( ) , execution_unit . GetByteOrder ( ) ) ,
2013-03-19 00:10:07 +00:00
m_allocation ( LLDB_INVALID_ADDRESS )
2011-05-23 21:40:23 +00:00
{
}
2013-06-28 21:44:15 +00:00
IRForTarget : : FunctionValueCache : : FunctionValueCache ( Maker const & maker ) :
m_maker ( maker ) ,
m_values ( )
{
}
IRForTarget : : FunctionValueCache : : ~ FunctionValueCache ( )
{
}
llvm : : Value * IRForTarget : : FunctionValueCache : : GetValue ( llvm : : Function * function )
2014-07-06 17:54:58 +00:00
{
2013-06-28 21:44:15 +00:00
if ( ! m_values . count ( function ) )
{
llvm : : Value * ret = m_maker ( function ) ;
m_values [ function ] = ret ;
return ret ;
}
return m_values [ function ] ;
}
2013-03-19 00:10:07 +00:00
lldb : : addr_t IRForTarget : : StaticDataAllocator : : Allocate ( )
2011-05-23 21:40:23 +00:00
{
2013-03-19 00:10:07 +00:00
lldb_private : : Error err ;
2014-07-06 17:54:58 +00:00
2013-03-19 00:10:07 +00:00
if ( m_allocation ! = LLDB_INVALID_ADDRESS )
{
m_execution_unit . FreeNow ( m_allocation ) ;
m_allocation = LLDB_INVALID_ADDRESS ;
}
2014-07-06 17:54:58 +00:00
2013-03-19 00:10:07 +00:00
m_allocation = m_execution_unit . WriteNow ( ( const uint8_t * ) m_stream_string . GetData ( ) , m_stream_string . GetSize ( ) , err ) ;
return m_allocation ;
2011-05-23 21:40:23 +00:00
}
2013-06-28 21:44:15 +00:00
static llvm : : Value * FindEntryInstruction ( llvm : : Function * function )
{
if ( function - > empty ( ) )
return NULL ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return function - > getEntryBlock ( ) . getFirstNonPHIOrDbg ( ) ;
}
2010-11-19 01:05:25 +00:00
IRForTarget : : IRForTarget ( lldb_private : : ClangExpressionDeclMap * decl_map ,
bool resolve_vars ,
2013-03-19 00:10:07 +00:00
lldb_private : : IRExecutionUnit & execution_unit ,
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 ) ,
2011-05-23 21:40:23 +00:00
m_module ( NULL ) ,
2011-07-19 19:48:13 +00:00
m_decl_map ( decl_map ) ,
2013-03-19 00:10:07 +00:00
m_data_allocator ( execution_unit ) ,
2010-11-17 23:00:36 +00:00
m_CFStringCreateWithBytes ( NULL ) ,
2010-08-27 01:01:44 +00:00
m_sel_registerName ( NULL ) ,
2013-12-20 19:55:02 +00:00
m_intptr_ty ( NULL ) ,
2011-04-11 19:41:40 +00:00
m_error_stream ( error_stream ) ,
2011-05-07 01:06:41 +00:00
m_result_store ( NULL ) ,
m_result_is_pointer ( false ) ,
2013-06-28 21:44:15 +00:00
m_reloc_placeholder ( NULL ) ,
m_entry_instruction_finder ( FindEntryInstruction )
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
2014-07-06 17:54:58 +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 ;
2012-10-12 17:34:26 +00:00
if ( value )
{
raw_string_ostream rso ( s ) ;
value - > print ( rso ) ;
rso . flush ( ) ;
if ( truncate )
s . resize ( s . length ( ) - 1 ) ;
}
2010-08-11 03:57:18 +00:00
return s ;
}
2010-09-30 21:18:25 +00:00
static std : : string
2013-07-11 22:46:58 +00:00
PrintType ( const llvm : : 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 ( )
{
}
2011-05-23 21:40:23 +00:00
bool
IRForTarget : : FixFunctionLinkage ( llvm : : Function & llvm_function )
{
llvm_function . setLinkage ( GlobalValue : : ExternalLinkage ) ;
2014-07-06 17:54:58 +00:00
2011-11-19 02:54:21 +00:00
std : : string name = llvm_function . getName ( ) . str ( ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
return true ;
}
2014-03-24 23:10:19 +00:00
IRForTarget : : LookupResult
2011-08-04 21:37:47 +00:00
IRForTarget : : GetFunctionAddress ( llvm : : Function * fun ,
uint64_t & fun_addr ,
lldb_private : : ConstString & name ,
Constant * * & value_ptr )
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
fun_addr = LLDB_INVALID_ADDRESS ;
name . Clear ( ) ;
value_ptr = NULL ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
if ( fun - > isIntrinsic ( ) )
{
Intrinsic : : ID intrinsic_id = ( Intrinsic : : ID ) fun - > getIntrinsicID ( ) ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
switch ( intrinsic_id )
{
default :
if ( log )
log - > Printf ( " Unresolved intrinsic \" %s \" " , Intrinsic : : getName ( intrinsic_id ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +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 ( ) ) ;
2014-07-06 17:54:58 +00:00
2014-07-09 01:10:37 +00:00
return LookupResult : : Fail ;
2011-08-04 21:37:47 +00:00
case Intrinsic : : memcpy :
{
static lldb_private : : ConstString g_memcpy_str ( " memcpy " ) ;
name = g_memcpy_str ;
}
break ;
2011-11-16 00:20:50 +00:00
case Intrinsic : : memset :
{
static lldb_private : : ConstString g_memset_str ( " memset " ) ;
name = g_memset_str ;
}
break ;
2014-03-24 23:10:19 +00:00
case Intrinsic : : dbg_declare :
2014-04-09 00:59:41 +00:00
case Intrinsic : : dbg_value :
2014-03-24 23:10:19 +00:00
return LookupResult : : Ignore ;
2011-08-04 21:37:47 +00:00
}
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
if ( log & & name )
log - > Printf ( " Resolved intrinsic name \" %s \" " , name . GetCString ( ) ) ;
}
else
{
name . SetCStringWithLength ( fun - > getName ( ) . data ( ) , fun - > getName ( ) . size ( ) ) ;
}
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
// Find the address of the function.
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
clang : : NamedDecl * fun_decl = DeclForGlobal ( fun ) ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
if ( fun_decl )
{
2014-07-06 17:54:58 +00:00
if ( ! m_decl_map - > GetFunctionInfo ( fun_decl , fun_addr ) )
2011-08-04 21:37:47 +00:00
{
2012-07-18 20:47:40 +00:00
lldb_private : : ConstString altnernate_name ;
2011-10-22 03:33:13 +00:00
bool found_it = m_decl_map - > GetFunctionAddress ( name , fun_addr ) ;
if ( ! found_it )
2011-08-04 21:37:47 +00:00
{
2011-10-22 03:33:13 +00:00
// Check for an alternate mangling for "std::basic_string<char>"
// that is part of the itanium C++ name mangling scheme
const char * name_cstr = name . GetCString ( ) ;
2012-10-12 17:34:26 +00:00
if ( name_cstr & & strncmp ( name_cstr , " _ZNKSbIcE " , strlen ( " _ZNKSbIcE " ) ) = = 0 )
2011-10-22 03:33:13 +00:00
{
std : : string alternate_mangling ( " _ZNKSs " ) ;
alternate_mangling . append ( name_cstr + strlen ( " _ZNKSbIcE " ) ) ;
2012-07-18 20:47:40 +00:00
altnernate_name . SetCString ( alternate_mangling . c_str ( ) ) ;
found_it = m_decl_map - > GetFunctionAddress ( altnernate_name , fun_addr ) ;
2011-10-22 03:33:13 +00:00
}
}
2014-07-06 17:54:58 +00:00
2011-10-22 03:33:13 +00:00
if ( ! found_it )
{
2012-07-18 20:47:40 +00:00
lldb_private : : Mangled mangled_name ( name ) ;
lldb_private : : Mangled alt_mangled_name ( altnernate_name ) ;
2011-08-04 21:37:47 +00:00
if ( log )
2011-10-22 03:33:13 +00:00
{
2012-07-18 20:47:40 +00:00
if ( alt_mangled_name )
log - > Printf ( " Function \" %s \" (alternate name \" %s \" ) has no address " ,
mangled_name . GetName ( ) . GetCString ( ) ,
alt_mangled_name . GetName ( ) . GetCString ( ) ) ;
2011-10-22 03:33:13 +00:00
else
2012-07-18 20:47:40 +00:00
log - > Printf ( " Function \" %s \" had no address " ,
mangled_name . GetName ( ) . GetCString ( ) ) ;
2011-10-22 03:33:13 +00:00
}
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
if ( m_error_stream )
2011-10-22 03:33:13 +00:00
{
2012-07-18 20:47:40 +00:00
if ( alt_mangled_name )
m_error_stream - > Printf ( " error: call to a function '%s' (alternate name '%s') that is not present in the target \n " ,
mangled_name . GetName ( ) . GetCString ( ) ,
alt_mangled_name . GetName ( ) . GetCString ( ) ) ;
2013-04-23 21:48:38 +00:00
else if ( mangled_name . GetMangledName ( ) )
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 03:33:13 +00:00
else
2012-07-18 20:47:40 +00: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 03:33:13 +00:00
}
2014-03-24 23:10:19 +00:00
return LookupResult : : Fail ;
2011-08-04 21:37:47 +00:00
}
}
}
2014-07-06 17:54:58 +00:00
else
2011-08-04 21:37:47 +00:00
{
if ( ! m_decl_map - > GetFunctionAddress ( name , fun_addr ) )
{
if ( log )
log - > Printf ( " Metadataless function \" %s \" had no address " , name . GetCString ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +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 " , name . GetCString ( ) ) ;
2014-07-06 17:54:58 +00:00
2014-03-24 23:10:19 +00:00
return LookupResult : : Fail ;
2011-08-04 21:37:47 +00:00
}
}
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
if ( log )
2012-11-29 21:49:15 +00:00
log - > Printf ( " Found \" %s \" at 0x% " PRIx64 , name . GetCString ( ) , fun_addr ) ;
2014-07-06 17:54:58 +00:00
2014-03-24 23:10:19 +00:00
return LookupResult : : Success ;
2011-08-04 21:37:47 +00:00
}
llvm : : Constant *
IRForTarget : : BuildFunctionPointer ( llvm : : Type * type ,
uint64_t ptr )
{
PointerType * fun_ptr_ty = PointerType : : getUnqual ( type ) ;
2013-12-20 19:55:02 +00:00
Constant * fun_addr_int = ConstantInt : : get ( m_intptr_ty , ptr , false ) ;
2011-08-04 21:37:47 +00:00
return ConstantExpr : : getIntToPtr ( fun_addr_int , fun_ptr_ty ) ;
}
2011-10-31 22:11:40 +00:00
void
IRForTarget : : RegisterFunctionMetadata ( LLVMContext & context ,
2014-07-06 17:54:58 +00:00
llvm : : Value * function_ptr ,
2011-10-31 22:11:40 +00:00
const char * name )
{
2014-03-10 17:24:16 +00:00
for ( llvm : : User * user : function_ptr - > users ( ) )
2011-10-31 22:11:40 +00:00
{
if ( Instruction * user_inst = dyn_cast < Instruction > ( user ) )
{
2013-06-03 20:45:54 +00:00
MDString * md_name = MDString : : get ( context , StringRef ( name ) ) ;
MDNode * metadata = MDNode : : get ( context , md_name ) ;
2011-10-31 22:11:40 +00:00
user_inst - > setMetadata ( " lldb.call.realName " , metadata ) ;
}
else
{
RegisterFunctionMetadata ( context , user , name ) ;
}
}
}
2014-07-06 17:54:58 +00:00
bool
2013-06-28 21:44:15 +00:00
IRForTarget : : ResolveFunctionPointers ( llvm : : Module & llvm_module )
2011-08-04 21:37:47 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
for ( llvm : : Module : : iterator fi = llvm_module . begin ( ) ;
fi ! = llvm_module . end ( ) ;
+ + fi )
{
Function * fun = fi ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
bool is_decl = fun - > isDeclaration ( ) ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
if ( log )
2011-11-19 02:54:21 +00:00
log - > Printf ( " Examining %s function %s " , ( is_decl ? " declaration " : " non-declaration " ) , fun - > getName ( ) . str ( ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
if ( ! is_decl )
continue ;
2014-07-06 17:54:58 +00:00
2014-03-11 19:19:16 +00:00
if ( fun - > use_empty ( ) )
2011-08-04 21:37:47 +00:00
continue ; // ignore
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
uint64_t addr = LLDB_INVALID_ADDRESS ;
lldb_private : : ConstString name ;
Constant * * value_ptr = NULL ;
2014-07-06 17:54:58 +00:00
2014-03-24 23:10:19 +00:00
LookupResult result = GetFunctionAddress ( fun ,
addr ,
name ,
value_ptr ) ;
2014-07-06 17:54:58 +00:00
2014-03-24 23:10:19 +00:00
switch ( result )
{
case LookupResult : : Fail :
2011-08-04 21:37:47 +00:00
return false ; // GetFunctionAddress reports its own errors
2014-07-06 17:54:58 +00:00
2014-03-24 23:10:19 +00:00
case LookupResult : : Ignore :
break ; // Nothing to do
2014-07-06 17:54:58 +00:00
2014-03-24 23:10:19 +00:00
case LookupResult : : Success :
{
Constant * value = BuildFunctionPointer ( fun - > getFunctionType ( ) , addr ) ;
2014-07-06 17:54:58 +00:00
2014-03-24 23:10:19 +00:00
RegisterFunctionMetadata ( llvm_module . getContext ( ) , fun , name . AsCString ( ) ) ;
2014-07-06 17:54:58 +00:00
2014-03-24 23:10:19 +00:00
if ( value_ptr )
* value_ptr = value ;
2013-07-23 21:34:03 +00:00
2014-03-24 23:10:19 +00: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-23 21:34:03 +00:00
2014-03-24 23:10:19 +00:00
for ( auto u : fun - > users ( ) ) {
if ( auto call = dyn_cast < CallInst > ( u ) ) {
call - > removeAttribute ( AttributeSet : : FunctionIndex , builtin ) ;
}
}
2013-07-23 21:34:03 +00:00
}
2014-07-06 17:54:58 +00:00
2014-03-24 23:10:19 +00:00
fun - > replaceAllUsesWith ( value ) ;
2013-07-23 21:34:03 +00:00
}
2014-03-24 23:10:19 +00:00
break ;
2013-07-23 21:34:03 +00:00
}
2011-08-04 21:37:47 +00:00
}
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
return true ;
}
2011-09-15 02:13:07 +00:00
2011-05-07 01:06:41 +00:00
clang : : NamedDecl *
2011-09-15 02:13:07 +00:00
IRForTarget : : DeclForGlobal ( const GlobalValue * global_val , Module * module )
2011-05-07 01:06:41 +00:00
{
2011-09-15 02:13:07 +00:00
NamedMDNode * named_metadata = module - > getNamedMetadata ( " clang.global.decl.ptrs " ) ;
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
if ( ! named_metadata )
return NULL ;
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
unsigned num_nodes = named_metadata - > getNumOperands ( ) ;
unsigned node_index ;
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
for ( node_index = 0 ;
node_index < num_nodes ;
+ + node_index )
{
MDNode * metadata_node = named_metadata - > getOperand ( node_index ) ;
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
if ( ! metadata_node )
return NULL ;
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
if ( metadata_node - > getNumOperands ( ) ! = 2 )
continue ;
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
if ( metadata_node - > getOperand ( 0 ) ! = global_val )
continue ;
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
ConstantInt * constant_int = dyn_cast < ConstantInt > ( metadata_node - > getOperand ( 1 ) ) ;
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
if ( ! constant_int )
return NULL ;
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
uintptr_t ptr = constant_int - > getZExtValue ( ) ;
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
return reinterpret_cast < clang : : NamedDecl * > ( ptr ) ;
}
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
return NULL ;
}
2011-09-15 02:13:07 +00:00
clang : : NamedDecl *
IRForTarget : : DeclForGlobal ( GlobalValue * global_val )
2014-07-06 17:54:58 +00:00
{
2011-09-15 02:13:07 +00:00
return DeclForGlobal ( global_val , m_module ) ;
}
2014-07-06 17:54:58 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : CreateResultVariable ( llvm : : Function & llvm_function )
2010-08-12 01:56:52 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2010-09-13 21:34:21 +00:00
if ( ! m_resolve_vars )
return true ;
2014-07-06 17:54:58 +00:00
2010-09-13 21:34:21 +00:00
// Find the result variable. If it doesn't exist, we can give up right here.
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
ValueSymbolTable & value_symbol_table = m_module - > getValueSymbolTable ( ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
std : : string result_name_str ;
2010-09-21 00:44:12 +00:00
const char * result_name = NULL ;
2014-07-06 17:54:58 +00:00
2010-09-21 00:44:12 +00:00
for ( ValueSymbolTable : : iterator vi = value_symbol_table . begin ( ) , ve = value_symbol_table . end ( ) ;
vi ! = ve ;
+ + vi )
{
2011-07-30 02:42:06 +00:00
result_name_str = vi - > first ( ) . str ( ) ;
const char * value_name = result_name_str . c_str ( ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
if ( strstr ( value_name , " $__lldb_expr_result_ptr " ) & &
2012-11-02 22:28:08 +00:00
strncmp ( value_name , " _ZGV " , 4 ) )
2011-01-13 08:53:35 +00:00
{
2011-07-30 02:42:06 +00:00
result_name = value_name ;
2011-01-13 08:53:35 +00:00
m_result_is_pointer = true ;
break ;
}
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
if ( strstr ( value_name , " $__lldb_expr_result " ) & &
2012-11-02 22:28:08 +00:00
strncmp ( value_name , " _ZGV " , 4 ) )
2010-09-28 21:13:03 +00:00
{
2011-07-30 02:42:06 +00:00
result_name = value_name ;
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
}
2014-07-06 17:54:58 +00:00
2010-09-21 00:44:12 +00:00
if ( ! result_name )
{
if ( log )
log - > PutCString ( " Couldn't find result variable " ) ;
2014-07-06 17:54:58 +00:00
2013-10-11 19:44:23 +00:00
return true ;
2010-09-21 00:44:12 +00:00
}
2014-07-06 17:54:58 +00:00
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 ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
Value * result_value = m_module - > getNamedValue ( result_name ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +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 ) ;
2014-07-06 17:54:58 +00:00
2010-09-21 00:44:12 +00:00
return false ;
2010-08-12 01:56:52 +00:00
}
2014-07-06 17:54:58 +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 ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
GlobalVariable * result_global = dyn_cast < GlobalVariable > ( result_value ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
if ( ! result_global )
{
if ( log )
log - > PutCString ( " Result variable isn't a GlobalVariable " ) ;
2014-07-06 17:54:58 +00:00
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 ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
clang : : NamedDecl * result_decl = DeclForGlobal ( result_global ) ;
2011-05-07 01:06:41 +00:00
if ( ! result_decl )
2010-08-12 01:56:52 +00:00
{
if ( log )
2011-05-07 01:06:41 +00:00
log - > PutCString ( " Result variable doesn't have a corresponding Decl " ) ;
2014-07-06 17:54:58 +00:00
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
2011-05-07 01:06:41 +00:00
m_error_stream - > Printf ( " Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity \n " , result_name ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
if ( log )
2010-08-12 01:56:52 +00:00
{
2011-05-07 01:06:41 +00: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-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
log - > Printf ( " Found result decl: \" %s \" " , decl_desc_str . c_str ( ) ) ;
2010-08-12 01:56:52 +00:00
}
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
clang : : VarDecl * result_var = dyn_cast < clang : : VarDecl > ( result_decl ) ;
if ( ! result_var )
2010-08-12 01:56:52 +00:00
{
if ( log )
2011-05-07 01:06:41 +00:00
log - > PutCString ( " Result variable Decl isn't a VarDecl " ) ;
2014-07-06 17:54:58 +00:00
2011-01-27 01:07:04 +00:00
if ( m_error_stream )
2011-05-07 01:06:41 +00:00
m_error_stream - > Printf ( " Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable \n " , result_name ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
// Get the next available result name from m_decl_map and create the persistent
// variable for it
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
// If the result is an Lvalue, it is emitted as a pointer; see
// ASTResultSynthesizer::SynthesizeBodyResult.
2011-01-13 08:53:35 +00:00
if ( m_result_is_pointer )
{
2011-05-07 01:06:41 +00:00
clang : : QualType pointer_qual_type = result_var - > getType ( ) ;
2011-01-27 04:42:51 +00:00
const clang : : Type * pointer_type = pointer_qual_type . getTypePtr ( ) ;
2014-07-06 17:54:58 +00:00
2011-12-14 01:13:04 +00:00
const clang : : PointerType * pointer_pointertype = pointer_type - > getAs < clang : : PointerType > ( ) ;
const clang : : ObjCObjectPointerType * pointer_objcobjpointertype = pointer_type - > getAs < clang : : ObjCObjectPointerType > ( ) ;
2014-07-06 17:54:58 +00:00
2011-12-08 19:04:34 +00:00
if ( pointer_pointertype )
{
clang : : QualType element_qual_type = pointer_pointertype - > getPointeeType ( ) ;
2014-07-06 17:54:58 +00:00
2011-12-08 19:04:34 +00: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-06 17:54:58 +00:00
2011-12-08 19:04:34 +00:00
m_result_type = lldb_private : : TypeFromParser ( element_qual_type . getAsOpaquePtr ( ) ,
& result_decl - > getASTContext ( ) ) ;
}
else
2011-01-13 08:53:35 +00:00
{
if ( log )
log - > PutCString ( " Expected result to have pointer type, but it did not " ) ;
2014-07-06 17:54:58 +00:00
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 ) ;
2014-07-06 17:54:58 +00:00
2011-01-13 08:53:35 +00:00
return false ;
}
}
else
{
2011-09-15 02:13:07 +00:00
m_result_type = lldb_private : : TypeFromParser ( result_var - > getType ( ) . getAsOpaquePtr ( ) ,
2011-11-18 03:28:09 +00:00
& result_decl - > getASTContext ( ) ) ;
}
2014-07-06 17:54:58 +00:00
2013-07-11 22:46:58 +00:00
if ( m_result_type . GetBitSize ( ) = = 0 )
2011-11-18 03:28:09 +00:00
{
lldb_private : : StreamString type_desc_stream ;
m_result_type . DumpTypeDescription ( & type_desc_stream ) ;
2014-07-06 17:54:58 +00:00
2011-11-18 03:28:09 +00:00
if ( log )
log - > Printf ( " Result type has size 0 " ) ;
2014-07-06 17:54:58 +00:00
2011-11-18 03:28:09 +00:00
if ( m_error_stream )
2014-07-06 17:54:58 +00:00
m_error_stream - > Printf ( " Error [IRForTarget]: Size of result type '%s' couldn't be determined \n " ,
2011-11-18 03:28:09 +00:00
type_desc_stream . GetData ( ) ) ;
2011-12-21 23:44:05 +00:00
return false ;
2011-01-13 08:53:35 +00:00
}
2014-07-06 17:54:58 +00:00
2011-05-07 01:06:41 +00:00
if ( log )
{
lldb_private : : StreamString type_desc_stream ;
2011-09-15 02:13:07 +00:00
m_result_type . DumpTypeDescription ( & type_desc_stream ) ;
2014-07-06 17:54:58 +00:00
2011-11-18 03:28:09 +00:00
log - > Printf ( " Result decl type: \" %s \" " , type_desc_stream . GetData ( ) ) ;
2011-05-07 01:06:41 +00:00
}
2014-07-06 17:54:58 +00:00
2013-04-18 22:06:33 +00:00
m_result_name = lldb_private : : ConstString ( " $RESULT_NAME " ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
if ( log )
2013-03-14 18:31:44 +00:00
log - > Printf ( " Creating a new result global: \" %s \" with size 0x% " PRIx64 ,
2011-11-18 03:28:09 +00:00
m_result_name . GetCString ( ) ,
2013-07-11 22:46:58 +00:00
m_result_type . GetByteSize ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
// Construct a new result global and set up its metadata
2014-07-06 17:54:58 +00:00
GlobalVariable * new_result_global = new GlobalVariable ( ( * m_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 ( ) ) ;
2014-07-06 17:54:58 +00:00
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.
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
ConstantInt * new_constant_int = ConstantInt : : get ( llvm : : Type : : getInt64Ty ( m_module - > getContext ( ) ) ,
2011-05-07 01:06:41 +00:00
reinterpret_cast < uint64_t > ( result_decl ) ,
2010-08-12 01:56:52 +00:00
false ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
llvm : : Value * values [ 2 ] ;
values [ 0 ] = new_result_global ;
values [ 1 ] = new_constant_int ;
2014-07-06 17:54:58 +00:00
2011-05-15 22:34:38 +00:00
ArrayRef < Value * > value_ref ( values , 2 ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00: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 01:56:52 +00:00
named_metadata - > addOperand ( persistent_global_md ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
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 ( ) ) ;
2014-07-06 17:54:58 +00:00
2014-03-11 19:19:16 +00:00
if ( result_global - > use_empty ( ) )
2010-09-07 22:43:19 +00:00
{
// We need to synthesize a store for this variable, because otherwise
// there's nothing to put into its equivalent persistent variable.
2014-07-06 17:54:58 +00:00
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 ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-09-07 22:43:19 +00:00
if ( ! first_entry_instruction )
return false ;
2014-07-06 17:54:58 +00:00
2010-09-07 22:43:19 +00:00
if ( ! result_global - > hasInitializer ( ) )
{
if ( log )
log - > Printf ( " Couldn't find initializer for unused variable " ) ;
2014-07-06 17:54:58 +00:00
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 ) ;
2014-07-06 17:54:58 +00:00
2010-09-07 22:43:19 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-09-07 22:43:19 +00:00
Constant * initializer = result_global - > getInitializer ( ) ;
2014-07-06 17:54:58 +00:00
2011-02-05 02:28:58 +00:00
StoreInst * synthesized_store = new StoreInst ( initializer ,
new_result_global ,
first_entry_instruction ) ;
2014-07-06 17:54:58 +00:00
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 ) ;
}
2014-07-06 17:54:58 +00:00
2013-04-18 22:06:33 +00:00
if ( ! m_decl_map - > AddPersistentVariable ( result_decl ,
2014-07-06 17:54:58 +00:00
m_result_name ,
2013-04-18 22:06:33 +00:00
m_result_type ,
true ,
m_result_is_pointer ) )
return false ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
result_global - > eraseFromParent ( ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
return true ;
}
2013-06-28 21:44:15 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : RewriteObjCConstString ( llvm : : GlobalVariable * ns_str ,
2013-06-28 21:44:15 +00:00
llvm : : GlobalVariable * cstr )
2010-11-17 23:00:36 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
Type * ns_str_ty = ns_str - > getType ( ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00: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-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( ! m_CFStringCreateWithBytes )
{
lldb : : addr_t CFStringCreateWithBytes_addr ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
static lldb_private : : ConstString g_CFStringCreateWithBytes_str ( " CFStringCreateWithBytes " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( ! m_decl_map - > GetFunctionAddress ( g_CFStringCreateWithBytes_str , CFStringCreateWithBytes_addr ) )
{
if ( log )
log - > PutCString ( " Couldn't find CFStringCreateWithBytes in the target " ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( log )
2012-11-29 21:49:15 +00:00
log - > Printf ( " Found CFStringCreateWithBytes at 0x% " PRIx64 , CFStringCreateWithBytes_addr ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00: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-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
Type * arg_type_array [ 5 ] ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
arg_type_array [ 0 ] = i8_ptr_ty ;
arg_type_array [ 1 ] = i8_ptr_ty ;
2013-12-20 19:55:02 +00:00
arg_type_array [ 2 ] = m_intptr_ty ;
2011-07-30 02:42:06 +00:00
arg_type_array [ 3 ] = i32_ty ;
arg_type_array [ 4 ] = i8_ty ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
ArrayRef < Type * > CFSCWB_arg_types ( arg_type_array , 5 ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
llvm : : Type * CFSCWB_ty = FunctionType : : get ( ns_str_ty , CFSCWB_arg_types , false ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
// Build the constant containing the pointer to the function
PointerType * CFSCWB_ptr_ty = PointerType : : getUnqual ( CFSCWB_ty ) ;
2013-12-20 19:55:02 +00:00
Constant * CFSCWB_addr_int = ConstantInt : : get ( m_intptr_ty , CFStringCreateWithBytes_addr , false ) ;
2010-11-17 23:00:36 +00:00
m_CFStringCreateWithBytes = ConstantExpr : : getIntToPtr ( CFSCWB_addr_int , CFSCWB_ptr_ty ) ;
}
2014-07-06 17:54:58 +00:00
2012-02-09 03:22:41 +00:00
ConstantDataSequential * string_array = NULL ;
2014-07-06 17:54:58 +00:00
2011-02-10 22:17:53 +00:00
if ( cstr )
2012-02-09 03:22:41 +00:00
string_array = dyn_cast < ConstantDataSequential > ( cstr - > getInitializer ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
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 ) ;
2013-12-20 19:55:02 +00:00
Constant * numBytes_arg = ConstantInt : : get ( m_intptr_ty , cstr ? string_array - > 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 */
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
Value * argument_array [ 5 ] ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00: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-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
ArrayRef < Value * > CFSCWB_arguments ( argument_array , 5 ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00: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-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! UnfoldConstant ( ns_str , CFSCWB_Caller , m_entry_instruction_finder ) )
2010-11-17 23:00:36 +00:00
{
if ( log )
log - > PutCString ( " Couldn't replace the NSString with the result of the call " ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-19 01:05:25 +00:00
ns_str - > eraseFromParent ( ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return true ;
}
bool
2013-06-28 21:44:15 +00:00
IRForTarget : : RewriteObjCConstStrings ( )
2010-11-17 23:00:36 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
ValueSymbolTable & value_symbol_table = m_module - > getValueSymbolTable ( ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
for ( ValueSymbolTable : : iterator vi = value_symbol_table . begin ( ) , ve = value_symbol_table . end ( ) ;
vi ! = ve ;
+ + vi )
{
2011-07-30 02:42:06 +00:00
std : : string value_name = vi - > first ( ) . str ( ) ;
const char * value_name_cstr = value_name . c_str ( ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
if ( strstr ( value_name_cstr , " _unnamed_cfstring_ " ) )
2010-11-17 23:00:36 +00:00
{
Value * nsstring_value = vi - > second ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
GlobalVariable * nsstring_global = dyn_cast < GlobalVariable > ( nsstring_value ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( ! nsstring_global )
{
if ( log )
log - > PutCString ( " NSString variable is not a GlobalVariable " ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( ! nsstring_global - > hasInitializer ( ) )
{
if ( log )
log - > PutCString ( " NSString variable does not have an initializer " ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
ConstantStruct * nsstring_struct = dyn_cast < ConstantStruct > ( nsstring_global - > getInitializer ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( ! nsstring_struct )
{
if ( log )
log - > PutCString ( " NSString variable's initializer is not a ConstantStruct " ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
// We expect the following structure:
//
// struct {
// int *isa;
// int flags;
// char *str;
// long length;
// };
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00: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-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
Constant * nsstring_member = nsstring_struct - > getOperand ( 2 ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( ! nsstring_member )
{
if ( log )
log - > PutCString ( " NSString initializer's str element was empty " ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
ConstantExpr * nsstring_expr = dyn_cast < ConstantExpr > ( nsstring_member ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( ! nsstring_expr )
{
if ( log )
log - > PutCString ( " NSString initializer's str element is not a ConstantExpr " ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00: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-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
Constant * nsstring_cstr = nsstring_expr - > getOperand ( 0 ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
GlobalVariable * cstr_global = dyn_cast < GlobalVariable > ( nsstring_cstr ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( ! cstr_global )
{
if ( log )
log - > PutCString ( " NSString initializer's str element is not a GlobalVariable " ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( ! cstr_global - > hasInitializer ( ) )
{
if ( log )
log - > PutCString ( " NSString initializer's str element does not have an initializer " ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
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");
2014-07-06 17:54:58 +00:00
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");
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if (!cstr_array->isCString())
{
if (log)
log->PutCString("NSString initializer's str element is not a C string array");
2014-07-06 17:54:58 +00:00
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");
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false;
}
2011-02-10 22:17:53 +00:00
*/
2014-07-06 17:54:58 +00:00
2012-02-09 03:22:41 +00:00
ConstantDataArray * cstr_array = dyn_cast < ConstantDataArray > ( cstr_global - > getInitializer ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( log )
2011-02-10 22:17:53 +00:00
{
if ( cstr_array )
2012-02-09 03:22:41 +00:00
log - > Printf ( " Found NSString constant %s, which contains \" %s \" " , value_name_cstr , cstr_array - > getAsString ( ) . str ( ) . c_str ( ) ) ;
2011-02-10 22:17:53 +00:00
else
2011-07-30 02:42:06 +00:00
log - > Printf ( " Found NSString constant %s, which contains \" \" " , value_name_cstr ) ;
2011-02-10 22:17:53 +00:00
}
2014-07-06 17:54:58 +00:00
2011-02-10 22:17:53 +00:00
if ( ! cstr_array )
cstr_global = NULL ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! RewriteObjCConstString ( nsstring_global , cstr_global ) )
2014-07-06 17:54:58 +00:00
{
2010-11-17 23:00:36 +00:00
if ( log )
log - > PutCString ( " Error rewriting the constant string " ) ;
2014-07-06 17:54:58 +00:00
2011-01-27 01:07:04 +00:00
// We don't print an error message here because RewriteObjCConstString has done so for us.
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
}
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
for ( ValueSymbolTable : : iterator vi = value_symbol_table . begin ( ) , ve = value_symbol_table . end ( ) ;
vi ! = ve ;
+ + vi )
{
2011-07-30 02:42:06 +00:00
std : : string value_name = vi - > first ( ) . str ( ) ;
const char * value_name_cstr = value_name . c_str ( ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
if ( ! strcmp ( value_name_cstr , " __CFConstantStringClassReference " ) )
2010-11-17 23:00:36 +00:00
{
GlobalVariable * gv = dyn_cast < GlobalVariable > ( vi - > second ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
if ( ! gv )
{
if ( log )
log - > PutCString ( " __CFConstantStringClassReference is not a global variable " ) ;
2014-07-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
gv - > eraseFromParent ( ) ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
break ;
}
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
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 ) ;
2014-07-06 17:54:58 +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 ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
return true ;
}
2011-01-27 01:07:04 +00:00
// This function does not report errors; its callers are responsible.
2014-07-06 17:54:58 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : RewriteObjCSelector ( Instruction * selector_load )
2010-07-31 01:32:05 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-31 01:32:05 +00:00
LoadInst * load = dyn_cast < LoadInst > ( selector_load ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
if ( ! load )
return false ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
// 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.
2014-07-06 17:54:58 +00:00
//
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.
2014-07-06 17:54:58 +00:00
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
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
GlobalVariable * _objc_selector_references_ = dyn_cast < GlobalVariable > ( load - > getPointerOperand ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
if ( ! _objc_selector_references_ | | ! _objc_selector_references_ - > hasInitializer ( ) )
return false ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
Constant * osr_initializer = _objc_selector_references_ - > getInitializer ( ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
ConstantExpr * osr_initializer_expr = dyn_cast < ConstantExpr > ( osr_initializer ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
if ( ! osr_initializer_expr | | osr_initializer_expr - > getOpcode ( ) ! = Instruction : : GetElementPtr )
return false ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
Value * osr_initializer_base = osr_initializer_expr - > getOperand ( 0 ) ;
if ( ! osr_initializer_base )
return false ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
// Find the string's initializer (a ConstantArray) and get the string from it
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
GlobalVariable * _objc_meth_var_name_ = dyn_cast < GlobalVariable > ( osr_initializer_base ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
if ( ! _objc_meth_var_name_ | | ! _objc_meth_var_name_ - > hasInitializer ( ) )
return false ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
Constant * omvn_initializer = _objc_meth_var_name_ - > getInitializer ( ) ;
2012-02-09 03:22:41 +00:00
ConstantDataArray * omvn_initializer_array = dyn_cast < ConstantDataArray > ( omvn_initializer ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
if ( ! omvn_initializer_array - > isString ( ) )
return false ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
std : : string omvn_initializer_string = omvn_initializer_array - > getAsString ( ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
if ( log )
2010-11-15 01:47:11 +00:00
log - > Printf ( " Found Objective-C selector reference \" %s \" " , omvn_initializer_string . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
// Construct a call to sel_registerName
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
if ( ! m_sel_registerName )
{
2010-11-15 01:47:11 +00:00
lldb : : addr_t sel_registerName_addr ;
2014-07-06 17:54:58 +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 ;
2014-07-06 17:54:58 +00:00
2010-10-26 00:31:56 +00:00
if ( log )
2012-11-29 21:49:15 +00:00
log - > Printf ( " Found sel_registerName at 0x% " PRIx64 , sel_registerName_addr ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
// Build the function type: struct objc_selector *sel_registerName(uint8_t*)
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
// The below code would be "more correct," but in actuality what's required is uint8_t*
2011-05-23 21:40:23 +00:00
//Type *sel_type = StructType::get(m_module->getContext());
2010-07-31 01:32:05 +00:00
//Type *sel_ptr_type = PointerType::getUnqual(sel_type);
2011-07-30 02:42:06 +00:00
Type * sel_ptr_type = Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
Type * type_array [ 1 ] ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
type_array [ 0 ] = llvm : : Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
ArrayRef < Type * > srN_arg_types ( type_array , 1 ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
llvm : : Type * srN_type = FunctionType : : get ( sel_ptr_type , srN_arg_types , false ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
// Build the constant containing the pointer to the function
PointerType * srN_ptr_ty = PointerType : : getUnqual ( srN_type ) ;
2013-12-20 19:55:02 +00:00
Constant * srN_addr_int = ConstantInt : : get ( m_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 ) ;
}
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
Value * argument_array [ 1 ] ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
Constant * omvn_pointer = ConstantExpr : : getBitCast ( _objc_meth_var_name_ , Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
argument_array [ 0 ] = omvn_pointer ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
ArrayRef < Value * > srN_arguments ( argument_array , 1 ) ;
2014-07-06 17:54:58 +00:00
CallInst * srN_call = CallInst : : Create ( m_sel_registerName ,
2011-07-30 02:42:06 +00:00
srN_arguments ,
2010-11-17 23:00:36 +00:00
" sel_registerName " ,
2010-07-31 01:32:05 +00:00
selector_load ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
// Replace the load with the call in all users
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
selector_load - > replaceAllUsesWith ( srN_call ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
selector_load - > eraseFromParent ( ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
return true ;
}
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : RewriteObjCSelectors ( BasicBlock & basic_block )
2010-07-31 01:32:05 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-31 01:32:05 +00:00
BasicBlock : : iterator ii ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
typedef SmallVector < Instruction * , 2 > InstrList ;
typedef InstrList : : iterator InstrIterator ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
InstrList selector_loads ;
2014-07-06 17:54:58 +00:00
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 ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
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 ) ;
}
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
InstrIterator iter ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
for ( iter = selector_loads . begin ( ) ;
iter ! = selector_loads . end ( ) ;
+ + iter )
{
2011-05-23 21:40:23 +00:00
if ( ! RewriteObjCSelector ( * iter ) )
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 " ) ;
2014-07-06 17:54:58 +00:00
2011-07-19 18:03:25 +00:00
if ( log )
2010-07-31 01:32:05 +00:00
log - > PutCString ( " Couldn't rewrite a reference to an Objective-C selector " ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
return false ;
}
}
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
return true ;
}
2011-01-27 01:07:04 +00:00
// This function does not report errors; its callers are responsible.
2014-07-06 17:54:58 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : RewritePersistentAlloc ( llvm : : Instruction * persistent_alloc )
2010-08-11 03:57:18 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2011-01-13 21:23:32 +00:00
2010-08-11 03:57:18 +00:00
AllocaInst * alloc = dyn_cast < AllocaInst > ( persistent_alloc ) ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
MDNode * alloc_md = alloc - > getMetadata ( " clang.decl.ptr " ) ;
if ( ! alloc_md | | ! alloc_md - > getNumOperands ( ) )
return false ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
ConstantInt * constant_int = dyn_cast < ConstantInt > ( alloc_md - > getOperand ( 0 ) ) ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
if ( ! constant_int )
return false ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
// We attempt to register this as a new persistent variable with the DeclMap.
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
uintptr_t ptr = constant_int - > getZExtValue ( ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
clang : : VarDecl * decl = reinterpret_cast < clang : : VarDecl * > ( ptr ) ;
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
lldb_private : : TypeFromParser result_decl_type ( decl - > getType ( ) . getAsOpaquePtr ( ) ,
& decl - > getASTContext ( ) ) ;
2014-07-06 17:54:58 +00:00
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 ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
GlobalVariable * persistent_global = new GlobalVariable ( ( * m_module ) ,
2011-01-13 21:23:32 +00:00
alloc - > getType ( ) ,
2010-08-11 03:57:18 +00:00
false , /* not constant */
GlobalValue : : ExternalLinkage ,
NULL , /* no initializer */
alloc - > getName ( ) . str ( ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00: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-06 17:54:58 +00:00
2012-07-04 01:26:26 +00:00
NamedMDNode * named_metadata = m_module - > getOrInsertNamedMetadata ( " clang.global.decl.ptrs " ) ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
llvm : : Value * values [ 2 ] ;
values [ 0 ] = persistent_global ;
values [ 1 ] = constant_int ;
2014-07-06 17:54:58 +00:00
2011-05-15 22:34:38 +00:00
ArrayRef < llvm : : Value * > value_ref ( values , 2 ) ;
2010-08-11 03:57:18 +00:00
2011-05-23 21:40:23 +00:00
MDNode * persistent_global_md = MDNode : : get ( m_module - > getContext ( ) , value_ref ) ;
2010-08-11 03:57:18 +00:00
named_metadata - > addOperand ( persistent_global_md ) ;
2014-07-06 17:54:58 +00:00
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.
2014-07-06 17:54:58 +00:00
2011-01-13 21:23:32 +00:00
LoadInst * persistent_load = new LoadInst ( persistent_global , " " , alloc ) ;
2014-07-06 17:54:58 +00:00
2011-01-13 21:23:32 +00:00
if ( log )
log - > Printf ( " Replacing \" %s \" with \" %s \" " ,
PrintValue ( alloc ) . c_str ( ) ,
PrintValue ( persistent_load ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-01-13 21:23:32 +00:00
alloc - > replaceAllUsesWith ( persistent_load ) ;
2010-08-11 03:57:18 +00:00
alloc - > eraseFromParent ( ) ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
return true ;
}
2014-07-06 17:54:58 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : RewritePersistentAllocs ( 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 ;
2014-07-06 17:54:58 +00:00
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
BasicBlock : : iterator ii ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
typedef SmallVector < Instruction * , 2 > InstrList ;
typedef InstrList : : iterator InstrIterator ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
InstrList pvar_allocs ;
2014-07-06 17:54:58 +00:00
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 ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
if ( AllocaInst * alloc = dyn_cast < AllocaInst > ( & inst ) )
2011-01-21 22:30:25 +00:00
{
llvm : : StringRef alloc_name = alloc - > getName ( ) ;
2014-07-06 17:54:58 +00:00
2011-01-21 22:30:25 +00: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-06 17:54:58 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2011-01-21 22:30:25 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
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
}
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
InstrIterator iter ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
for ( iter = pvar_allocs . begin ( ) ;
iter ! = pvar_allocs . end ( ) ;
+ + iter )
{
2011-05-23 21:40:23 +00:00
if ( ! RewritePersistentAlloc ( * iter ) )
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 " ) ;
2014-07-06 17:54:58 +00:00
2011-07-19 18:03:25 +00:00
if ( log )
2010-08-11 03:57:18 +00:00
log - > PutCString ( " Couldn't rewrite the creation of a persistent variable " ) ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
return false ;
}
}
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
return true ;
}
2011-10-25 18:36:40 +00:00
bool
IRForTarget : : MaterializeInitializer ( uint8_t * data , Constant * initializer )
{
if ( ! initializer )
return true ;
2014-07-06 17:54:58 +00:00
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2011-10-25 18:36:40 +00:00
if ( log & & log - > GetVerbose ( ) )
log - > Printf ( " MaterializeInitializer(%p, %s) " , data , PrintValue ( initializer ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
Type * initializer_type = initializer - > getType ( ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00: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 03:22:41 +00:00
else if ( ConstantDataArray * array_initializer = dyn_cast < ConstantDataArray > ( initializer ) )
2011-10-25 18:36:40 +00: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-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
size_t element_size = m_target_data - > getTypeAllocSize ( array_element_type ) ;
2014-07-06 17:54:58 +00:00
2013-06-19 19:04:53 +00:00
for ( unsigned i = 0 ; i < array_initializer - > getNumOperands ( ) ; + + i )
2011-10-25 18:36:40 +00:00
{
2012-02-09 03:22:41 +00:00
Value * operand_value = array_initializer - > getOperand ( i ) ;
Constant * operand_constant = dyn_cast < Constant > ( operand_value ) ;
2014-07-06 17:54:58 +00:00
2012-02-09 03:22:41 +00:00
if ( ! operand_constant )
return false ;
2014-07-06 17:54:58 +00:00
2012-02-09 03:22:41 +00:00
if ( ! MaterializeInitializer ( data + ( i * element_size ) , operand_constant ) )
2011-10-25 18:36:40 +00: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-19 19:04:53 +00:00
for ( unsigned i = 0 ;
2011-10-25 18:36:40 +00:00
i < struct_initializer - > getNumOperands ( ) ;
+ + i )
{
if ( ! MaterializeInitializer ( data + struct_layout - > getElementOffset ( i ) , struct_initializer - > getOperand ( i ) ) )
return false ;
}
return true ;
}
2013-04-24 19:50:12 +00:00
else if ( isa < ConstantAggregateZero > ( initializer ) )
{
memset ( data , 0 , m_target_data - > getTypeStoreSize ( initializer_type ) ) ;
return true ;
}
2011-10-25 18:36:40 +00:00
return false ;
}
bool
IRForTarget : : MaterializeInternalVariable ( GlobalVariable * global_variable )
{
if ( GlobalVariable : : isExternalLinkage ( global_variable - > getLinkage ( ) ) )
return false ;
2014-07-06 17:54:58 +00:00
2011-11-15 19:13:54 +00:00
if ( global_variable = = m_reloc_placeholder )
return true ;
2014-07-06 17:54:58 +00:00
2013-03-19 00:10:07 +00:00
uint64_t offset = m_data_allocator . GetStream ( ) . GetSize ( ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
llvm : : Type * variable_type = global_variable - > getType ( ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
Constant * initializer = global_variable - > getInitializer ( ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
llvm : : Type * initializer_type = initializer - > getType ( ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
size_t size = m_target_data - > getTypeAllocSize ( initializer_type ) ;
2012-06-08 22:20:41 +00:00
size_t align = m_target_data - > getPrefTypeAlignment ( initializer_type ) ;
2014-07-06 17:54:58 +00:00
2012-06-08 22:20:41 +00:00
const size_t mask = ( align - 1 ) ;
uint64_t aligned_offset = ( offset + mask ) & ~ mask ;
2013-03-19 00:10:07 +00:00
m_data_allocator . GetStream ( ) . PutNHex8 ( aligned_offset - offset , 0 ) ;
2012-06-08 22:20:41 +00:00
offset = aligned_offset ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
lldb_private : : DataBufferHeap data ( size , ' \0 ' ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
if ( initializer )
if ( ! MaterializeInitializer ( data . GetBytes ( ) , initializer ) )
return false ;
2014-07-06 17:54:58 +00:00
2013-03-19 00:10:07 +00:00
m_data_allocator . GetStream ( ) . Write ( data . GetBytes ( ) , data . GetByteSize ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
Constant * new_pointer = BuildRelocation ( variable_type , offset ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
global_variable - > replaceAllUsesWith ( new_pointer ) ;
global_variable - > eraseFromParent ( ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
return true ;
}
2011-01-27 01:07:04 +00:00
// This function does not report errors; its callers are responsible.
2014-07-06 17:54:58 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : MaybeHandleVariable ( Value * llvm_value_ptr )
2010-07-03 01:35:46 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
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 ( ) ) ;
2014-07-06 17:54:58 +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 ) ;
2011-05-23 21:40:23 +00:00
if ( ! MaybeHandleVariable ( s ) )
2010-12-02 19:47:57 +00:00
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
{
2011-10-25 18:36:40 +00:00
if ( ! GlobalValue : : isExternalLinkage ( global_variable - > getLinkage ( ) ) )
return MaterializeInternalVariable ( global_variable ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
clang : : NamedDecl * named_decl = DeclForGlobal ( global_variable ) ;
2014-07-06 17:54:58 +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 ;
2014-07-06 17:54:58 +00:00
2010-12-06 00:56:39 +00:00
if ( ! global_variable - > hasExternalLinkage ( ) )
return true ;
2014-07-06 17:54:58 +00:00
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 ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-07-31 01:32:05 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2010-10-15 22:48:33 +00:00
std : : string name ( named_decl - > getName ( ) . str ( ) ) ;
2014-07-06 17:54:58 +00:00
2013-07-11 22:46:58 +00:00
clang : : ValueDecl * value_decl = dyn_cast < clang : : ValueDecl > ( named_decl ) ;
if ( value_decl = = NULL )
2010-07-16 00:09:46 +00:00
return false ;
2013-07-11 22:46:58 +00:00
lldb_private : : ClangASTType clang_type ( & value_decl - > getASTContext ( ) , value_decl - > getType ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-07-08 00:39:14 +00:00
const Type * value_type = NULL ;
2013-07-11 22:46:58 +00:00
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.
2013-07-11 22:46:58 +00:00
clang_type = clang_type . GetPointerType ( ) ;
2011-01-13 08:53:35 +00:00
value_type = PointerType : : get ( global_variable - > getType ( ) , 0 ) ;
}
else
{
value_type = global_variable - > getType ( ) ;
}
2014-07-06 17:54:58 +00:00
2013-07-11 22:46:58 +00:00
const uint64_t value_size = clang_type . GetByteSize ( ) ;
2014-07-02 17:24:07 +00:00
lldb : : offset_t value_alignment = ( clang_type . GetTypeBitAlign ( ) + 7ull ) / 8ull ;
2014-07-06 17:54:58 +00:00
2010-09-30 21:18:25 +00:00
if ( log )
2013-07-11 22:46:58 +00:00
{
2014-07-02 17:24:07 +00:00
log - > Printf ( " Type of \" %s \" is [clang \" %s \" , llvm \" %s \" ] [size % " PRIu64 " , align % " PRIu64 " ] " ,
2014-07-06 17:54:58 +00:00
name . c_str ( ) ,
2013-07-11 22:46:58 +00:00
clang_type . GetQualType ( ) . getAsString ( ) . c_str ( ) ,
PrintType ( value_type ) . c_str ( ) ,
2014-07-06 17:54:58 +00:00
value_size ,
2010-09-30 21:18:25 +00:00
value_alignment ) ;
2013-07-11 22:46:58 +00:00
}
2014-07-06 17:54:58 +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 ,
2014-07-06 17:54:58 +00:00
value_size ,
2010-07-27 02:07:53 +00:00
value_alignment ) )
2011-08-01 17:41:38 +00:00
{
if ( ! global_variable - > hasExternalLinkage ( ) )
return true ;
2013-04-11 17:57:16 +00:00
else if ( HandleSymbol ( global_variable ) )
return true ;
2011-08-01 17:41:38 +00:00
else
return false ;
}
2010-07-13 21:41:46 +00:00
}
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-12-02 19:47:57 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
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
2011-05-23 21:40:23 +00:00
IRForTarget : : HandleSymbol ( Value * symbol )
2014-07-06 17:54:58 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2011-01-17 23:42:46 +00:00
lldb_private : : ConstString name ( symbol - > getName ( ) . str ( ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-12-01 02:04:16 +00:00
lldb : : addr_t symbol_addr = m_decl_map - > GetSymbolAddress ( name , lldb : : eSymbolTypeAny ) ;
2014-07-06 17:54:58 +00:00
2011-06-23 04:25:29 +00:00
if ( symbol_addr = = LLDB_INVALID_ADDRESS )
2011-01-17 23:42:46 +00:00
{
if ( log )
log - > Printf ( " Symbol \" %s \" had no address " , name . GetCString ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-01-17 23:42:46 +00:00
return false ;
}
if ( log )
2012-11-29 21:49:15 +00:00
log - > Printf ( " Found \" %s \" at 0x% " PRIx64 , name . GetCString ( ) , symbol_addr ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
Type * symbol_type = symbol - > getType ( ) ;
2014-07-06 17:54:58 +00:00
2013-12-20 19:55:02 +00:00
Constant * symbol_addr_int = ConstantInt : : get ( m_intptr_ty , symbol_addr , false ) ;
2014-07-06 17:54:58 +00:00
2011-01-17 23:42:46 +00:00
Value * symbol_addr_ptr = ConstantExpr : : getIntToPtr ( symbol_addr_int , symbol_type ) ;
2014-07-06 17:54:58 +00:00
2011-01-17 23:42:46 +00:00
if ( log )
log - > Printf ( " Replacing %s with %s " , PrintValue ( symbol ) . c_str ( ) , PrintValue ( symbol_addr_ptr ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-01-17 23:42:46 +00:00
symbol - > replaceAllUsesWith ( symbol_addr_ptr ) ;
2014-07-06 17:54:58 +00:00
2011-01-17 23:42:46 +00:00
return true ;
}
2010-10-05 22:26:43 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : MaybeHandleCallArguments ( CallInst * Old )
2010-10-05 22:26:43 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2010-12-02 19:47:57 +00:00
if ( log )
log - > Printf ( " MaybeHandleCallArguments(%s) " , PrintValue ( Old ) . c_str ( ) ) ;
2014-07-06 17:54:58 +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 )
2011-05-23 21:40:23 +00:00
if ( ! MaybeHandleVariable ( 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 " ) ;
2014-07-06 17:54:58 +00:00
2010-10-05 22:26:43 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2014-07-06 17:54:58 +00:00
2010-10-05 22:26:43 +00:00
return true ;
}
2011-11-01 23:38:03 +00:00
bool
IRForTarget : : HandleObjCClass ( Value * classlist_reference )
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2011-11-01 23:38:03 +00:00
GlobalVariable * global_variable = dyn_cast < GlobalVariable > ( classlist_reference ) ;
2014-07-06 17:54:58 +00:00
2011-11-01 23:38:03 +00:00
if ( ! global_variable )
return false ;
2014-07-06 17:54:58 +00:00
2011-11-01 23:38:03 +00:00
Constant * initializer = global_variable - > getInitializer ( ) ;
2014-07-06 17:54:58 +00:00
2011-11-01 23:38:03 +00:00
if ( ! initializer )
return false ;
2014-07-06 17:54:58 +00:00
2011-11-01 23:38:03 +00:00
if ( ! initializer - > hasName ( ) )
return false ;
2014-07-06 17:54:58 +00:00
2011-11-01 23:38:03 +00:00
StringRef name ( initializer - > getName ( ) ) ;
lldb_private : : ConstString name_cstr ( name . str ( ) . c_str ( ) ) ;
2011-12-03 20:02:42 +00:00
lldb : : addr_t class_ptr = m_decl_map - > GetSymbolAddress ( name_cstr , lldb : : eSymbolTypeObjCClass ) ;
2014-07-06 17:54:58 +00:00
2011-11-01 23:38:03 +00:00
if ( log )
log - > Printf ( " Found reference to Objective-C class %s (0x%llx) " , name_cstr . AsCString ( ) , ( unsigned long long ) class_ptr ) ;
2014-07-06 17:54:58 +00:00
2011-11-01 23:38:03 +00:00
if ( class_ptr = = LLDB_INVALID_ADDRESS )
return false ;
2014-07-06 17:54:58 +00:00
2014-03-10 17:24:16 +00:00
if ( global_variable - > use_empty ( ) )
2011-11-01 23:38:03 +00:00
return false ;
2014-07-06 17:54:58 +00:00
2013-03-23 01:01:16 +00:00
SmallVector < LoadInst * , 2 > load_instructions ;
2014-07-06 17:54:58 +00:00
2014-03-10 17:24:16 +00:00
for ( llvm : : User * u : global_variable - > users ( ) )
2011-11-01 23:38:03 +00:00
{
2014-03-10 17:24:16 +00:00
if ( LoadInst * load_instruction = dyn_cast < LoadInst > ( u ) )
2013-03-23 01:01:16 +00:00
load_instructions . push_back ( load_instruction ) ;
2011-11-01 23:38:03 +00:00
}
2014-07-06 17:54:58 +00:00
2013-03-23 01:01:16 +00:00
if ( load_instructions . empty ( ) )
2011-11-01 23:38:03 +00:00
return false ;
2014-07-06 17:54:58 +00:00
2013-12-20 19:55:02 +00:00
Constant * class_addr = ConstantInt : : get ( m_intptr_ty , ( uint64_t ) class_ptr ) ;
2014-07-06 17:54:58 +00:00
2013-03-23 01:01:16 +00:00
for ( LoadInst * load_instruction : load_instructions )
{
Constant * class_bitcast = ConstantExpr : : getIntToPtr ( class_addr , load_instruction - > getType ( ) ) ;
2014-07-06 17:54:58 +00:00
2013-03-23 01:01:16 +00:00
load_instruction - > replaceAllUsesWith ( class_bitcast ) ;
2014-07-06 17:54:58 +00:00
2013-03-23 01:01:16 +00:00
load_instruction - > eraseFromParent ( ) ;
}
2014-07-06 17:54:58 +00:00
2011-11-01 23:38:03 +00:00
return true ;
}
2012-07-21 02:02:15 +00:00
bool
IRForTarget : : RemoveCXAAtExit ( BasicBlock & basic_block )
{
BasicBlock : : iterator ii ;
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
std : : vector < CallInst * > calls_to_remove ;
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
for ( ii = basic_block . begin ( ) ;
ii ! = basic_block . end ( ) ;
+ + ii )
{
Instruction & inst = * ii ;
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
CallInst * call = dyn_cast < CallInst > ( & inst ) ;
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
// MaybeHandleCallArguments handles error reporting; we are silent here
if ( ! call )
continue ;
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
bool remove = false ;
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
llvm : : Function * func = call - > getCalledFunction ( ) ;
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
if ( func & & func - > getName ( ) = = " __cxa_atexit " )
remove = true ;
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
llvm : : Value * val = call - > getCalledValue ( ) ;
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
if ( val & & val - > getName ( ) = = " __cxa_atexit " )
remove = true ;
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
if ( remove )
calls_to_remove . push_back ( call ) ;
}
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
for ( std : : vector < CallInst * > : : iterator ci = calls_to_remove . begin ( ) , ce = calls_to_remove . end ( ) ;
ci ! = ce ;
+ + ci )
{
( * ci ) - > eraseFromParent ( ) ;
}
2014-07-06 17:54:58 +00:00
2012-07-21 02:02:15 +00:00
return true ;
}
2010-07-13 21:41:46 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : ResolveCalls ( BasicBlock & basic_block )
2014-07-06 17:54:58 +00:00
{
2010-07-03 01:35:46 +00:00
/////////////////////////////////////////////////////////////////////////
// Prepare the current basic block for execution in the remote process
//
2014-07-06 17:54:58 +00:00
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 ;
2014-07-06 17:54:58 +00:00
2010-11-08 00:31:32 +00:00
CallInst * call = dyn_cast < CallInst > ( & inst ) ;
2014-07-06 17:54:58 +00:00
2011-01-27 01:07:04 +00:00
// MaybeHandleCallArguments handles error reporting; we are silent here
2011-05-23 21:40:23 +00:00
if ( call & & ! MaybeHandleCallArguments ( call ) )
2010-12-02 19:47:57 +00:00
return false ;
2010-07-03 01:35:46 +00:00
}
2014-07-06 17:54:58 +00:00
2010-07-03 01:35:46 +00:00
return true ;
}
2010-11-08 00:31:32 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : ResolveExternals ( Function & llvm_function )
2010-11-08 00:31:32 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-04-04 04:06:10 +00:00
2014-03-11 19:19:16 +00:00
for ( GlobalVariable & global_var : m_module - > globals ( ) )
2010-11-08 00:31:32 +00:00
{
2014-03-11 19:19:16 +00:00
std : : string global_name = global_var . getName ( ) . str ( ) ;
2014-04-04 04:06:10 +00:00
2010-11-19 01:05:25 +00:00
if ( log )
2014-04-04 04:06:10 +00:00
log - > Printf ( " Examining %s, DeclForGlobalValue returns %p " ,
2011-12-22 21:24:49 +00:00
global_name . c_str ( ) ,
2014-04-04 04:06:10 +00:00
static_cast < void * > ( DeclForGlobal ( & global_var ) ) ) ;
2011-11-01 23:38:03 +00:00
if ( global_name . find ( " OBJC_IVAR " ) = = 0 )
2011-01-17 23:42:46 +00:00
{
2014-03-11 19:19:16 +00:00
if ( ! HandleSymbol ( & global_var ) )
2011-01-27 01:07:04 +00:00
{
if ( m_error_stream )
2011-12-22 21:24:49 +00:00
m_error_stream - > Printf ( " Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s \n " , global_name . c_str ( ) ) ;
2014-04-04 04:06:10 +00:00
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
}
2011-11-01 23:38:03 +00:00
else if ( global_name . find ( " OBJC_CLASSLIST_REFERENCES_$ " ) ! = global_name . npos )
{
2014-03-11 19:19:16 +00:00
if ( ! HandleObjCClass ( & global_var ) )
2011-11-01 23:38:03 +00: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 04:06:10 +00:00
2011-11-01 23:38:03 +00:00
return false ;
}
}
2013-04-24 21:25:20 +00:00
else if ( global_name . find ( " OBJC_CLASSLIST_SUP_REFS_$ " ) ! = global_name . npos )
{
2014-03-11 19:19:16 +00:00
if ( ! HandleObjCClass ( & global_var ) )
2013-04-24 21:25:20 +00: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 04:06:10 +00:00
2013-04-24 21:25:20 +00:00
return false ;
}
}
2014-03-11 19:19:16 +00:00
else if ( DeclForGlobal ( & global_var ) )
2011-01-17 23:42:46 +00:00
{
2014-03-11 19:19:16 +00:00
if ( ! MaybeHandleVariable ( & global_var ) )
2011-01-27 01:07:04 +00:00
{
if ( m_error_stream )
2011-12-22 21:24:49 +00:00
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't rewrite external variable %s \n " , global_name . c_str ( ) ) ;
2014-04-04 04:06:10 +00:00
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
}
2014-04-04 04:06:10 +00:00
2010-11-08 00:31:32 +00:00
return true ;
}
2011-05-23 21:40:23 +00:00
bool
IRForTarget : : ReplaceStrings ( )
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
typedef std : : map < GlobalVariable * , size_t > OffsetsTy ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
OffsetsTy offsets ;
2014-07-06 17:54:58 +00:00
2014-03-11 19:19:16 +00:00
for ( GlobalVariable & gv : m_module - > globals ( ) )
2011-05-23 21:40:23 +00:00
{
2014-03-11 19:19:16 +00:00
if ( ! gv . hasInitializer ( ) )
2011-05-23 21:40:23 +00:00
continue ;
2014-07-06 17:54:58 +00:00
2014-03-11 19:19:16 +00:00
Constant * gc = gv . getInitializer ( ) ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
std : : string str ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
if ( gc - > isNullValue ( ) )
{
Type * gc_type = gc - > getType ( ) ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
ArrayType * gc_array_type = dyn_cast < ArrayType > ( gc_type ) ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
if ( ! gc_array_type )
continue ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
Type * gc_element_type = gc_array_type - > getElementType ( ) ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
IntegerType * gc_integer_type = dyn_cast < IntegerType > ( gc_element_type ) ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
if ( gc_integer_type - > getBitWidth ( ) ! = 8 )
continue ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
str = " " ;
}
else
{
2012-02-09 03:22:41 +00:00
ConstantDataArray * gc_array = dyn_cast < ConstantDataArray > ( gc ) ;
2011-08-10 21:05:52 +00:00
if ( ! gc_array )
continue ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
if ( ! gc_array - > isCString ( ) )
continue ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
if ( log )
log - > Printf ( " Found a GlobalVariable with string initializer %s " , PrintValue ( gc ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
str = gc_array - > getAsString ( ) ;
}
2014-07-06 17:54:58 +00:00
2014-03-11 19:19:16 +00:00
offsets [ & gv ] = m_data_allocator . GetStream ( ) . GetSize ( ) ;
2014-07-06 17:54:58 +00:00
2013-03-19 00:10:07 +00:00
m_data_allocator . GetStream ( ) . Write ( str . c_str ( ) , str . length ( ) + 1 ) ;
2011-05-23 21:40:23 +00:00
}
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
Type * char_ptr_ty = Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
for ( OffsetsTy : : iterator oi = offsets . begin ( ) , oe = offsets . end ( ) ;
oi ! = oe ;
+ + oi )
{
GlobalVariable * gv = oi - > first ;
size_t offset = oi - > second ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
Constant * new_initializer = BuildRelocation ( char_ptr_ty , offset ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
if ( log )
log - > Printf ( " Replacing GV %s with %s " , PrintValue ( gv ) . c_str ( ) , PrintValue ( new_initializer ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2014-03-10 17:24:16 +00:00
for ( llvm : : User * u : gv - > users ( ) )
2011-05-23 21:40:23 +00:00
{
if ( log )
2014-03-10 17:24:16 +00:00
log - > Printf ( " Found use %s " , PrintValue ( u ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2014-03-10 17:24:16 +00:00
ConstantExpr * const_expr = dyn_cast < ConstantExpr > ( u ) ;
StoreInst * store_inst = dyn_cast < StoreInst > ( u ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00: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-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
Constant * bit_cast = ConstantExpr : : getBitCast ( new_initializer , const_expr - > getOperand ( 0 ) - > getType ( ) ) ;
Constant * new_gep = const_expr - > getWithOperandReplaced ( 0 , bit_cast ) ;
2014-07-06 17:54:58 +00:00
2011-08-10 21:05:52 +00:00
const_expr - > replaceAllUsesWith ( new_gep ) ;
2011-05-23 21:40:23 +00:00
}
else if ( store_inst )
{
Constant * bit_cast = ConstantExpr : : getBitCast ( new_initializer , store_inst - > getValueOperand ( ) - > getType ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00: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-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
return false ;
}
}
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
gv - > eraseFromParent ( ) ;
}
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
return true ;
}
2014-07-06 17:54:58 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : ReplaceStaticLiterals ( llvm : : BasicBlock & basic_block )
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
typedef SmallVector < Value * , 2 > ConstantList ;
typedef SmallVector < llvm : : Instruction * , 2 > UserList ;
typedef ConstantList : : iterator ConstantIterator ;
typedef UserList : : iterator UserIterator ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
ConstantList static_constants ;
UserList static_users ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
for ( BasicBlock : : iterator ii = basic_block . begin ( ) , ie = basic_block . end ( ) ;
ii ! = ie ;
+ + ii )
{
llvm : : Instruction & inst = * ii ;
2014-07-06 17:54:58 +00:00
2014-03-11 19:19:16 +00:00
for ( Value * operand_val : inst . operand_values ( ) )
2011-05-23 21:40:23 +00:00
{
ConstantFP * operand_constant_fp = dyn_cast < ConstantFP > ( operand_val ) ;
2014-07-06 17:54:58 +00:00
2012-04-26 20:51:20 +00:00
if ( operand_constant_fp /* && operand_constant_fp->getType()->isX86_FP80Ty()*/ )
2011-05-23 21:40:23 +00:00
{
static_constants . push_back ( operand_val ) ;
static_users . push_back ( ii ) ;
}
}
}
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
ConstantIterator constant_iter ;
UserIterator user_iter ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00: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-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
if ( operand_constant_fp )
{
2013-04-18 22:06:33 +00:00
Type * operand_type = operand_constant_fp - > getType ( ) ;
2011-05-23 21:40:23 +00:00
APFloat operand_apfloat = operand_constant_fp - > getValueAPF ( ) ;
APInt operand_apint = operand_apfloat . bitcastToAPInt ( ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
const uint8_t * operand_raw_data = ( const uint8_t * ) operand_apint . getRawData ( ) ;
size_t operand_data_size = operand_apint . getBitWidth ( ) / 8 ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00: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-06 17:54:58 +00:00
2014-03-03 19:15:20 +00:00
log - > Printf ( " Found ConstantFP with size % " PRIu64 " and raw data %s " , ( uint64_t ) operand_data_size , s . c_str ( ) ) ;
2011-05-23 21:40:23 +00:00
}
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
lldb_private : : DataBufferHeap data ( operand_data_size , 0 ) ;
2014-07-06 17:54:58 +00:00
2013-03-19 00:10:07 +00:00
if ( lldb : : endian : : InlHostByteOrder ( ) ! = m_data_allocator . GetStream ( ) . GetByteOrder ( ) )
2011-05-23 21:40:23 +00:00
{
uint8_t * data_bytes = data . GetBytes ( ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00: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-06 17:54:58 +00:00
2013-03-19 00:10:07 +00:00
uint64_t offset = m_data_allocator . GetStream ( ) . GetSize ( ) ;
2014-07-06 17:54:58 +00:00
2012-06-08 22:20:41 +00:00
size_t align = m_target_data - > getPrefTypeAlignment ( operand_type ) ;
2014-07-06 17:54:58 +00:00
2012-06-08 22:20:41 +00:00
const size_t mask = ( align - 1 ) ;
uint64_t aligned_offset = ( offset + mask ) & ~ mask ;
2013-03-19 00:10:07 +00:00
m_data_allocator . GetStream ( ) . PutNHex8 ( aligned_offset - offset , 0 ) ;
2014-07-06 17:54:58 +00:00
2013-03-19 00:10:07 +00:00
m_data_allocator . GetStream ( ) . Write ( data . GetBytes ( ) , operand_data_size ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
llvm : : Type * fp_ptr_ty = operand_constant_fp - > getType ( ) - > getPointerTo ( ) ;
2014-07-06 17:54:58 +00:00
2013-04-18 22:06:33 +00:00
Constant * new_pointer = BuildRelocation ( fp_ptr_ty , aligned_offset ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
llvm : : LoadInst * fp_load = new llvm : : LoadInst ( new_pointer , " fp_load " , inst ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
operand_constant_fp - > replaceAllUsesWith ( fp_load ) ;
}
}
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +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
{
2011-07-08 00:39:14 +00:00
Constant * Old = NULL ;
2014-07-06 17:54:58 +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 ;
2014-07-06 17:54:58 +00:00
2011-07-08 00:39:14 +00:00
ConstantExpr * CE = NULL ;
2014-07-06 17:54:58 +00:00
2010-09-23 03:01:22 +00:00
if ( ( CE = dyn_cast < ConstantExpr > ( V ) ) )
{
if ( CE - > getOpcode ( ) ! = Instruction : : BitCast )
return false ;
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
Old = CE - > getOperand ( 0 ) ;
2010-09-23 03:01:22 +00:00
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
GlobalVariable * GV = dyn_cast < GlobalVariable > ( Old ) ;
2014-07-06 17:54:58 +00:00
2010-07-24 01:37:44 +00:00
if ( ! GV | | ! GV - > hasName ( ) | | ! GV - > getName ( ) . startswith ( " _ZGV " ) )
return false ;
2014-07-06 17:54:58 +00:00
2010-07-24 01:37:44 +00:00
return true ;
}
2014-07-06 17:54:58 +00:00
void
2011-05-23 21:40:23 +00:00
IRForTarget : : TurnGuardLoadIntoZero ( llvm : : Instruction * guard_load )
2010-07-24 01:37:44 +00:00
{
2011-05-23 21:40:23 +00:00
Constant * zero ( ConstantInt : : get ( Type : : getInt8Ty ( m_module - > getContext ( ) ) , 0 , true ) ) ;
2010-07-24 01:37:44 +00:00
2014-03-10 14:23:10 +00:00
for ( llvm : : User * u : guard_load - > users ( ) )
2010-07-27 01:17:28 +00:00
{
2014-03-10 14:23:10 +00:00
if ( isa < Constant > ( u ) )
2010-07-27 01:17:28 +00:00
{
// do nothing for the moment
}
else
{
2014-03-10 14:23:10 +00:00
u - > replaceUsesOfWith ( guard_load , zero ) ;
2010-07-27 01:17:28 +00:00
}
}
2014-07-06 17:54:58 +00:00
2010-07-24 01:37:44 +00:00
guard_load - > eraseFromParent ( ) ;
}
static void ExciseGuardStore ( Instruction * guard_store )
{
guard_store - > eraseFromParent ( ) ;
}
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : RemoveGuards ( BasicBlock & basic_block )
2014-07-06 17:54:58 +00:00
{
2010-07-24 01:37:44 +00:00
///////////////////////////////////////////////////////
// Eliminate any reference to guard variables found.
//
2014-07-06 17:54:58 +00:00
2010-07-27 21:39:39 +00:00
BasicBlock : : iterator ii ;
2014-07-06 17:54:58 +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 ;
2014-07-06 17:54:58 +00:00
2010-07-24 01:37:44 +00:00
InstrList guard_loads ;
InstrList guard_stores ;
2014-07-06 17:54:58 +00:00
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 ;
2014-07-06 17:54:58 +00:00
2010-07-24 01:37:44 +00:00
if ( LoadInst * load = dyn_cast < LoadInst > ( & inst ) )
if ( isGuardVariableRef ( load - > getPointerOperand ( ) ) )
2014-07-06 17:54:58 +00:00
guard_loads . push_back ( & inst ) ;
if ( StoreInst * store = dyn_cast < StoreInst > ( & inst ) )
2010-07-24 01:37:44 +00:00
if ( isGuardVariableRef ( store - > getPointerOperand ( ) ) )
guard_stores . push_back ( & inst ) ;
}
2014-07-06 17:54:58 +00:00
2010-07-24 01:37:44 +00:00
InstrIterator iter ;
2014-07-06 17:54:58 +00:00
2010-07-24 01:37:44 +00:00
for ( iter = guard_loads . begin ( ) ;
iter ! = guard_loads . end ( ) ;
+ + iter )
2011-05-23 21:40:23 +00:00
TurnGuardLoadIntoZero ( * iter ) ;
2014-07-06 17:54:58 +00:00
2010-07-24 01:37:44 +00:00
for ( iter = guard_stores . begin ( ) ;
iter ! = guard_stores . end ( ) ;
+ + iter )
ExciseGuardStore ( * iter ) ;
2014-07-06 17:54:58 +00:00
2010-07-24 01:37:44 +00:00
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
2013-06-28 21:44:15 +00:00
IRForTarget : : UnfoldConstant ( Constant * old_constant ,
FunctionValueCache & value_maker ,
FunctionValueCache & entry_instruction_finder )
2010-07-14 23:40:29 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-14 23:40:29 +00:00
2010-08-11 03:57:18 +00:00
SmallVector < User * , 16 > users ;
2014-07-06 17:54:58 +00:00
2010-08-11 03:57:18 +00:00
// We do this because the use list might change, invalidating our iterator.
// Much better to keep a work list ourselves.
2014-03-10 14:23:10 +00:00
for ( llvm : : User * u : old_constant - > users ( ) )
users . push_back ( u ) ;
2014-07-06 17:54:58 +00:00
2011-07-19 19:48:13 +00:00
for ( size_t i = 0 ;
2010-08-11 03:57:18 +00:00
i < users . size ( ) ;
+ + i )
{
User * user = users [ i ] ;
2014-07-06 17:54:58 +00:00
2010-07-14 23:40:29 +00:00
if ( Constant * constant = dyn_cast < Constant > ( user ) )
{
// synthesize a new non-constant equivalent of the constant
2014-07-06 17:54:58 +00:00
2010-07-14 23:40:29 +00:00
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 :
2014-07-06 17:54:58 +00:00
{
2013-06-28 21:44:15 +00: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-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return new BitCastInst ( value_maker . GetValue ( function ) ,
constant_expr - > getType ( ) ,
" " ,
llvm : : cast < Instruction > ( entry_instruction_finder . GetValue ( function ) ) ) ;
} ) ;
2014-07-06 17:54:58 +00:00
2013-07-15 23:31:47 +00:00
if ( ! UnfoldConstant ( constant_expr , bit_cast_maker , entry_instruction_finder ) )
return false ;
2010-07-14 23:40:29 +00:00
}
break ;
case Instruction : : GetElementPtr :
{
// GetElementPtrConstantExpr
// OperandList[0] is base
// OperandList[1]... are indices
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00: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-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ptr = = old_constant )
ptr = value_maker . GetValue ( function ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
std : : vector < Value * > index_vector ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
unsigned operand_index ;
unsigned num_operands = constant_expr - > getNumOperands ( ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
for ( operand_index = 1 ;
operand_index < num_operands ;
+ + operand_index )
{
Value * operand = constant_expr - > getOperand ( operand_index ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( operand = = old_constant )
operand = value_maker . GetValue ( function ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
index_vector . push_back ( operand ) ;
}
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
ArrayRef < Value * > indices ( index_vector ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return GetElementPtrInst : : Create ( ptr , indices , " " , llvm : : cast < Instruction > ( entry_instruction_finder . GetValue ( function ) ) ) ;
} ) ;
2014-07-06 17:54:58 +00:00
2013-07-15 23:31:47 +00:00
if ( ! UnfoldConstant ( constant_expr , get_element_pointer_maker , entry_instruction_finder ) )
return false ;
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
{
2013-06-28 21:44:15 +00: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-14 23:40:29 +00:00
}
}
2014-07-06 17:54:58 +00:00
2013-07-15 23:31:47 +00:00
if ( ! isa < GlobalValue > ( old_constant ) )
{
old_constant - > destroyConstant ( ) ;
}
2014-07-06 17:54:58 +00:00
2010-07-14 23:40:29 +00:00
return true ;
}
2014-07-06 17:54:58 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : ReplaceVariables ( 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 ;
2014-07-06 17:54:58 +00:00
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-07-13 21:41:46 +00:00
m_decl_map - > DoStructLayout ( ) ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
if ( log )
log - > Printf ( " Element arrangement: " ) ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
uint32_t num_elements ;
uint32_t element_index ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
size_t size ;
2014-07-02 17:24:07 +00:00
lldb : : offset_t alignment ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
if ( ! m_decl_map - > GetStructInfo ( num_elements , size , alignment ) )
return false ;
2014-07-06 17:54:58 +00:00
2010-11-19 01:05:25 +00:00
Function : : arg_iterator iter ( llvm_function . getArgumentList ( ) . begin ( ) ) ;
2014-07-06 17:54:58 +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) " ) ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2014-07-06 17:54:58 +00:00
2010-07-27 21:39:39 +00:00
Argument * argument = iter ;
2014-07-06 17:54:58 +00:00
2010-09-21 00:44:12 +00:00
if ( argument - > getName ( ) . equals ( " this " ) )
{
+ + iter ;
2014-07-06 17:54:58 +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 only 'this' argument (should take a struct pointer too) " ) ;
2014-07-06 17:54:58 +00:00
2010-09-21 00:44:12 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2014-07-06 17:54:58 +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 ;
2014-07-06 17:54:58 +00:00
2010-12-13 22:46:15 +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 'self' argument (should take '_cmd' and a struct pointer too) " ) ;
2014-07-06 17:54:58 +00:00
2010-12-13 22:46:15 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2014-07-06 17:54:58 +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 ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-12-13 22:46:15 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2014-07-06 17:54:58 +00:00
2010-12-13 22:46:15 +00:00
+ + iter ;
2014-07-06 17:54:58 +00:00
2010-12-13 22:46:15 +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 'self' and '_cmd' arguments (should take a struct pointer too) " ) ;
2014-07-06 17:54:58 +00:00
2010-12-13 22:46:15 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2014-07-06 17:54:58 +00:00
2010-12-13 22:46:15 +00:00
argument = iter ;
}
2014-07-06 17:54:58 +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 ( ) ) ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2014-07-06 17:54:58 +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 ( ) ) ;
2014-07-06 17:54:58 +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 ( ) ) ;
2014-07-06 17:54:58 +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 " ) ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
LLVMContext & context ( m_module - > getContext ( ) ) ;
2011-07-30 02:42:06 +00:00
IntegerType * offset_type ( Type : : getInt32Ty ( context ) ) ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
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 " ) ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
for ( element_index = 0 ; element_index < num_elements ; + + element_index )
{
2011-07-08 00:39:14 +00:00
const clang : : NamedDecl * decl = NULL ;
Value * value = NULL ;
2014-07-02 17:24:07 +00:00
lldb : : offset_t offset ;
2010-10-15 22:48:33 +00:00
lldb_private : : ConstString name ;
2014-07-06 17:54:58 +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 " ) ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
return false ;
2011-01-27 01:07:04 +00:00
}
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
if ( log )
2014-07-02 17:24:07 +00:00
log - > Printf ( " \" %s \" ( \" %s \" ) placed at % " PRIu64 ,
2010-10-15 22:48:33 +00:00
name . GetCString ( ) ,
2011-10-25 18:36:40 +00:00
decl - > getNameAsString ( ) . c_str ( ) ,
2010-07-13 21:41:46 +00:00
offset ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
if ( value )
2011-01-13 08:53:35 +00:00
{
2011-10-25 18:36:40 +00:00
if ( log )
log - > Printf ( " Replacing [%s] " , PrintValue ( value ) . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00: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-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
llvm : : Instruction * entry_instruction = llvm : : cast < Instruction > ( m_entry_instruction_finder . GetValue ( function ) ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
ConstantInt * offset_int ( ConstantInt : : get ( offset_type , offset , true ) ) ;
GetElementPtrInst * get_element_ptr = GetElementPtrInst : : Create ( argument ,
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-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
LoadInst * load = new LoadInst ( bit_cast , " " , entry_instruction ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return load ;
}
else
{
BitCastInst * bit_cast = new BitCastInst ( get_element_ptr , value - > getType ( ) , " " , entry_instruction ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return bit_cast ;
}
2014-07-06 17:54:58 +00:00
} ) ;
2011-10-25 18:36:40 +00:00
if ( Constant * constant = dyn_cast < Constant > ( value ) )
2013-06-28 21:44:15 +00:00
{
UnfoldConstant ( constant , body_result_maker , m_entry_instruction_finder ) ;
}
else if ( Instruction * instruction = dyn_cast < Instruction > ( value ) )
{
value - > replaceAllUsesWith ( body_result_maker . GetValue ( instruction - > getParent ( ) - > getParent ( ) ) ) ;
}
2011-10-25 18:36:40 +00:00
else
2013-06-28 21:44:15 +00:00
{
if ( log )
log - > Printf ( " Unhandled non-constant type: \" %s \" " , PrintValue ( value ) . c_str ( ) ) ;
return false ;
}
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
if ( GlobalVariable * var = dyn_cast < GlobalVariable > ( value ) )
var - > eraseFromParent ( ) ;
}
2010-07-13 21:41:46 +00:00
}
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
if ( log )
2014-03-03 19:15:20 +00:00
log - > Printf ( " Total structure [align % " PRId64 " , size % " PRIu64 " ] " , ( int64_t ) alignment , ( uint64_t ) size ) ;
2014-07-06 17:54:58 +00:00
2010-07-13 21:41:46 +00:00
return true ;
}
2011-05-23 21:40:23 +00:00
llvm : : Constant *
2013-03-27 23:08:40 +00:00
IRForTarget : : BuildRelocation ( llvm : : Type * type , uint64_t offset )
2011-05-23 21:40:23 +00:00
{
2013-12-20 19:55:02 +00:00
llvm : : Constant * offset_int = ConstantInt : : get ( m_intptr_ty , offset ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
llvm : : Constant * offset_array [ 1 ] ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
offset_array [ 0 ] = offset_int ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
llvm : : ArrayRef < llvm : : Constant * > offsets ( offset_array , 1 ) ;
2014-07-06 17:54:58 +00:00
2011-07-30 02:42:06 +00:00
llvm : : Constant * reloc_getelementptr = ConstantExpr : : getGetElementPtr ( m_reloc_placeholder , offsets ) ;
2011-05-23 21:40:23 +00:00
llvm : : Constant * reloc_getbitcast = ConstantExpr : : getBitCast ( reloc_getelementptr , type ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
return reloc_getbitcast ;
}
2014-07-06 17:54:58 +00:00
bool
2011-05-23 21:40:23 +00:00
IRForTarget : : CompleteDataAllocation ( )
2014-07-06 17:54:58 +00:00
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2011-05-23 21:40:23 +00:00
2013-03-19 00:10:07 +00:00
if ( ! m_data_allocator . GetStream ( ) . GetSize ( ) )
2011-05-23 21:40:23 +00:00
return true ;
2014-07-06 17:54:58 +00:00
2013-03-19 00:10:07 +00:00
lldb : : addr_t allocation = m_data_allocator . Allocate ( ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00: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-06 17:54:58 +00:00
2013-03-19 00:10:07 +00:00
if ( ! allocation | | allocation = = LLDB_INVALID_ADDRESS )
2011-05-23 21:40:23 +00:00
return false ;
2014-07-06 17:54:58 +00:00
2013-12-20 19:55:02 +00:00
Constant * relocated_addr = ConstantInt : : get ( m_intptr_ty , ( uint64_t ) allocation ) ;
2011-05-23 21:40:23 +00:00
Constant * relocated_bitcast = ConstantExpr : : getIntToPtr ( relocated_addr , llvm : : Type : : getInt8PtrTy ( m_module - > getContext ( ) ) ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
m_reloc_placeholder - > replaceAllUsesWith ( relocated_bitcast ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
m_reloc_placeholder - > eraseFromParent ( ) ;
return true ;
}
2012-09-24 22:25:51 +00:00
bool
IRForTarget : : StripAllGVs ( Module & llvm_module )
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2012-09-24 22:25:51 +00:00
std : : vector < GlobalVariable * > global_vars ;
std : : set < GlobalVariable * > erased_vars ;
2014-07-06 17:54:58 +00:00
2012-09-24 22:25:51 +00:00
bool erased = true ;
2014-07-06 17:54:58 +00:00
2012-09-24 22:25:51 +00:00
while ( erased )
{
erased = false ;
2014-07-06 17:54:58 +00:00
2014-03-11 19:19:16 +00:00
for ( GlobalVariable & global_var : llvm_module . globals ( ) )
2012-09-24 22:25:51 +00:00
{
2014-03-11 19:19:16 +00:00
global_var . removeDeadConstantUsers ( ) ;
2014-07-06 17:54:58 +00:00
2014-03-11 19:19:16 +00:00
if ( global_var . use_empty ( ) )
2012-09-24 22:25:51 +00:00
{
if ( log )
log - > Printf ( " Did remove %s " ,
2014-03-11 19:19:16 +00:00
PrintValue ( & global_var ) . c_str ( ) ) ;
global_var . eraseFromParent ( ) ;
2012-09-24 22:25:51 +00:00
erased = true ;
break ;
}
}
}
2014-07-06 17:54:58 +00:00
2014-03-11 19:19:16 +00:00
for ( GlobalVariable & global_var : llvm_module . globals ( ) )
2012-09-24 22:25:51 +00:00
{
2014-03-11 19:19:16 +00:00
GlobalValue : : user_iterator ui = global_var . user_begin ( ) ;
2014-07-06 17:54:58 +00:00
2012-11-26 19:54:04 +00:00
if ( log )
log - > Printf ( " Couldn't remove %s because of %s " ,
2014-03-11 19:19:16 +00:00
PrintValue ( & global_var ) . c_str ( ) ,
2012-11-26 19:54:04 +00:00
PrintValue ( * ui ) . c_str ( ) ) ;
2012-09-24 22:25:51 +00:00
}
2014-07-06 17:54:58 +00:00
2012-09-24 22:25:51 +00:00
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
{
2013-03-27 23:08:40 +00:00
lldb_private : : Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
m_module = & llvm_module ;
2012-10-08 16:28:57 +00:00
m_target_data . reset ( new DataLayout ( m_module ) ) ;
2013-12-20 19:55:02 +00:00
m_intptr_ty = llvm : : Type : : getIntNTy ( m_module - > getContext ( ) , m_target_data - > getPointerSizeInBits ( ) ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
if ( log )
{
std : : string s ;
raw_string_ostream oss ( s ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
m_module - > print ( oss , NULL ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
oss . flush ( ) ;
2014-07-06 17:54:58 +00:00
2011-10-25 18:36:40 +00:00
log - > Printf ( " Module as passed in to IRForTarget: \n \" %s \" " , s . c_str ( ) ) ;
}
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
Function * main_function = m_module - > getFunction ( StringRef ( m_func_name . c_str ( ) ) ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! main_function )
{
if ( log )
log - > Printf ( " Couldn't find \" %s() \" in the module " , m_func_name . c_str ( ) ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( m_error_stream )
m_error_stream - > Printf ( " Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module " , m_func_name . c_str ( ) ) ;
return false ;
}
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! FixFunctionLinkage ( * main_function ) )
{
if ( log )
log - > Printf ( " Couldn't fix the linkage for the function " ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2013-12-20 19:55:02 +00:00
llvm : : Type * int8_ty = Type : : getInt8Ty ( m_module - > getContext ( ) ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
m_reloc_placeholder = new llvm : : GlobalVariable ( ( * m_module ) ,
2013-12-20 19:55:02 +00:00
int8_ty ,
2012-09-24 22:25:51 +00:00
false /* IsConstant */ ,
2011-05-23 21:40:23 +00:00
GlobalVariable : : InternalLinkage ,
2013-12-20 19:55:02 +00:00
Constant : : getNullValue ( int8_ty ) ,
2011-05-23 21:40:23 +00:00
" reloc_placeholder " ,
NULL /* InsertBefore */ ,
2012-09-24 22:25:51 +00:00
GlobalVariable : : NotThreadLocal /* ThreadLocal */ ,
2011-05-23 21:40:23 +00:00
0 /* AddressSpace */ ) ;
2013-06-28 21:44:15 +00:00
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
//
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! CreateResultVariable ( * main_function ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " CreateResultVariable() failed " ) ;
2014-07-06 17:54:58 +00:00
2011-01-27 01:07:04 +00:00
// CreateResultVariable() reports its own errors, so we don't do so here
2014-07-06 17:54:58 +00:00
2010-08-12 01:56:52 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2012-07-21 02:02:15 +00:00
2011-11-01 17:33:54 +00:00
if ( log & & log - > GetVerbose ( ) )
2011-05-23 21:40:23 +00:00
{
std : : string s ;
raw_string_ostream oss ( s ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
m_module - > print ( oss , NULL ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
oss . flush ( ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
log - > Printf ( " Module after creating the result variable: \n \" %s \" " , s . c_str ( ) ) ;
}
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
for ( Module : : iterator fi = m_module - > begin ( ) , fe = m_module - > end ( ) ;
fi ! = fe ;
+ + fi )
{
llvm : : Function * function = fi ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( function - > begin ( ) = = function - > end ( ) )
continue ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
Function : : iterator bbi ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
for ( bbi = function - > begin ( ) ;
bbi ! = function - > end ( ) ;
+ + bbi )
{
if ( ! RemoveGuards ( * bbi ) )
{
if ( log )
log - > Printf ( " RemoveGuards() failed " ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
// RemoveGuards() reports its own errors, so we don't do so here
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! RewritePersistentAllocs ( * bbi ) )
{
if ( log )
log - > Printf ( " RewritePersistentAllocs() failed " ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
// RewritePersistentAllocs() reports its own errors, so we don't do so here
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! RemoveCXAAtExit ( * bbi ) )
{
if ( log )
log - > Printf ( " RemoveCXAAtExit() failed " ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
// RemoveCXAAtExit() reports its own errors, so we don't do so here
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return false ;
}
}
}
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
///////////////////////////////////////////////////////////////////////////////
// Fix all Objective-C constant strings to use NSStringWithCString:encoding:
//
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! RewriteObjCConstStrings ( ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " RewriteObjCConstStrings() failed " ) ;
2014-07-06 17:54:58 +00:00
2011-01-27 01:07:04 +00:00
// RewriteObjCConstStrings() reports its own errors, so we don't do so here
2014-07-06 17:54:58 +00:00
2010-11-17 23:00:36 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
///////////////////////////////
// Resolve function pointers
//
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! ResolveFunctionPointers ( llvm_module ) )
2011-08-04 21:37:47 +00:00
{
if ( log )
log - > Printf ( " ResolveFunctionPointers() failed " ) ;
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
// ResolveFunctionPointers() reports its own errors, so we don't do so here
2014-07-06 17:54:58 +00:00
2011-08-04 21:37:47 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
for ( Module : : iterator fi = m_module - > begin ( ) , fe = m_module - > end ( ) ;
fi ! = fe ;
+ + fi )
2010-07-03 01:35:46 +00:00
{
2013-06-28 21:44:15 +00:00
llvm : : Function * function = fi ;
for ( llvm : : Function : : iterator bbi = function - > begin ( ) , bbe = function - > end ( ) ;
bbi ! = bbe ;
+ + bbi )
2010-12-13 22:46:15 +00:00
{
2013-06-28 21:44:15 +00:00
if ( ! RewriteObjCSelectors ( * bbi ) )
{
if ( log )
log - > Printf ( " RewriteObjCSelectors() failed " ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
// RewriteObjCSelectors() reports its own errors, so we don't do so here
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return false ;
}
2010-12-13 22:46:15 +00:00
}
2012-07-27 19:25:24 +00:00
}
2010-08-11 03:57:18 +00:00
2013-06-28 21:44:15 +00:00
for ( Module : : iterator fi = m_module - > begin ( ) , fe = m_module - > end ( ) ;
fi ! = fe ;
+ + fi )
2012-07-27 19:25:24 +00:00
{
2013-06-28 21:44:15 +00:00
llvm : : Function * function = fi ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
for ( llvm : : Function : : iterator bbi = function - > begin ( ) , bbe = function - > end ( ) ;
bbi ! = bbe ;
+ + bbi )
2011-05-23 21:40:23 +00:00
{
2013-06-28 21:44:15 +00:00
if ( ! ResolveCalls ( * bbi ) )
{
if ( log )
log - > Printf ( " ResolveCalls() failed " ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
// ResolveCalls() reports its own errors, so we don't do so here
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! ReplaceStaticLiterals ( * bbi ) )
{
if ( log )
log - > Printf ( " ReplaceStaticLiterals() failed " ) ;
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
return false ;
}
2011-05-23 21:40:23 +00:00
}
2010-07-13 21:41:46 +00:00
}
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
////////////////////////////////////////////////////////////////////////
// Run function-level passes that only make sense on the main function
2010-09-30 21:18:25 +00:00
//
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! ResolveExternals ( * main_function ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " ResolveExternals() failed " ) ;
2014-07-06 17:54:58 +00:00
2011-01-27 01:07:04 +00:00
// ResolveExternals() reports its own errors, so we don't do so here
2014-07-06 17:54:58 +00:00
2010-11-08 00:31:32 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2014-07-06 17:54:58 +00:00
2013-06-28 21:44:15 +00:00
if ( ! ReplaceVariables ( * main_function ) )
2010-12-13 22:46:15 +00:00
{
if ( log )
log - > Printf ( " ReplaceVariables() failed " ) ;
2014-07-06 17:54:58 +00:00
2011-01-27 01:07:04 +00:00
// ReplaceVariables() reports its own errors, so we don't do so here
2014-07-06 17:54:58 +00:00
2010-09-30 21:18:25 +00:00
return false ;
2010-12-13 22:46:15 +00:00
}
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
if ( ! ReplaceStrings ( ) )
{
if ( log )
log - > Printf ( " ReplaceStrings() failed " ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
if ( ! CompleteDataAllocation ( ) )
{
if ( log )
log - > Printf ( " CompleteDataAllocation() failed " ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
return false ;
}
2014-07-06 17:54:58 +00:00
2012-09-24 22:25:51 +00:00
if ( ! StripAllGVs ( llvm_module ) )
{
if ( log )
log - > Printf ( " StripAllGVs() failed " ) ;
}
2014-07-06 17:54:58 +00:00
2011-11-01 17:33:54 +00:00
if ( log & & log - > GetVerbose ( ) )
2010-07-13 21:41:46 +00:00
{
2010-07-28 01:00:59 +00:00
std : : string s ;
raw_string_ostream oss ( s ) ;
2014-07-06 17:54:58 +00:00
2011-05-23 21:40:23 +00:00
m_module - > print ( oss , NULL ) ;
2014-07-06 17:54:58 +00:00
2010-07-28 01:00:59 +00:00
oss . flush ( ) ;
2014-07-06 17:54:58 +00:00
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
}
2014-07-06 17:54:58 +00:00
return true ;
2010-07-03 01:35:46 +00:00
}
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 ;
}