diff options
Diffstat (limited to 'contrib/llvm/lib/ExecutionEngine')
29 files changed, 2340 insertions, 422 deletions
diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp index a744d0c..05987f2 100644 --- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp @@ -29,7 +29,7 @@ #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/Host.h" #include "llvm/Support/TargetRegistry.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" #include "llvm/Target/TargetMachine.h" #include <cmath> #include <cstring> @@ -91,11 +91,11 @@ class GVMemoryBlock : public CallbackVH { public: /// \brief Returns the address the GlobalVariable should be written into. The /// GVMemoryBlock object prefixes that. - static char *Create(const GlobalVariable *GV, const TargetData& TD) { + static char *Create(const GlobalVariable *GV, const DataLayout& TD) { Type *ElTy = GV->getType()->getElementType(); size_t GVSize = (size_t)TD.getTypeAllocSize(ElTy); void *RawMemory = ::operator new( - TargetData::RoundUpAlignment(sizeof(GVMemoryBlock), + DataLayout::RoundUpAlignment(sizeof(GVMemoryBlock), TD.getPreferredAlignment(GV)) + GVSize); new(RawMemory) GVMemoryBlock(GV); @@ -113,7 +113,7 @@ public: } // anonymous namespace char *ExecutionEngine::getMemoryForGV(const GlobalVariable *GV) { - return GVMemoryBlock::Create(GV, *getTargetData()); + return GVMemoryBlock::Create(GV, *getDataLayout()); } bool ExecutionEngine::removeModule(Module *M) { @@ -267,7 +267,7 @@ public: void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE, const std::vector<std::string> &InputArgv) { clear(); // Free the old contents. - unsigned PtrSize = EE->getTargetData()->getPointerSize(); + unsigned PtrSize = EE->getDataLayout()->getPointerSize(); Array = new char[(InputArgv.size()+1)*PtrSize]; DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array << "\n"); @@ -342,7 +342,7 @@ void ExecutionEngine::runStaticConstructorsDestructors(bool isDtors) { #ifndef NDEBUG /// isTargetNullPtr - Return whether the target pointer stored at Loc is null. static bool isTargetNullPtr(ExecutionEngine *EE, void *Loc) { - unsigned PtrSize = EE->getTargetData()->getPointerSize(); + unsigned PtrSize = EE->getDataLayout()->getPointerSize(); for (unsigned i = 0; i < PtrSize; ++i) if (*(i + (uint8_t*)Loc)) return false; @@ -501,7 +501,8 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { return 0; } - if ((WhichEngine & EngineKind::JIT) && ExecutionEngine::JITCtor == 0) { + if ((WhichEngine & EngineKind::JIT) && ExecutionEngine::JITCtor == 0 && + ExecutionEngine::MCJITCtor == 0) { if (ErrorStr) *ErrorStr = "JIT has not been linked in."; } @@ -643,15 +644,17 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { } case Instruction::PtrToInt: { GenericValue GV = getConstantValue(Op0); - uint32_t PtrWidth = TD->getPointerSizeInBits(); + uint32_t PtrWidth = TD->getTypeSizeInBits(Op0->getType()); + assert(PtrWidth <= 64 && "Bad pointer width"); GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal)); + uint32_t IntWidth = TD->getTypeSizeInBits(CE->getType()); + GV.IntVal = GV.IntVal.zextOrTrunc(IntWidth); return GV; } case Instruction::IntToPtr: { GenericValue GV = getConstantValue(Op0); - uint32_t PtrWidth = TD->getPointerSizeInBits(); - if (PtrWidth != GV.IntVal.getBitWidth()) - GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth); + uint32_t PtrWidth = TD->getTypeSizeInBits(CE->getType()); + GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth); assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width"); GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue())); return GV; @@ -832,7 +835,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, unsigned StoreBytes) { assert((IntVal.getBitWidth()+7)/8 >= StoreBytes && "Integer too small!"); - uint8_t *Src = (uint8_t *)IntVal.getRawData(); + const uint8_t *Src = (const uint8_t *)IntVal.getRawData(); if (sys::isLittleEndianHost()) { // Little-endian host - the source is ordered from LSB to MSB. Order the @@ -855,7 +858,7 @@ static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, GenericValue *Ptr, Type *Ty) { - const unsigned StoreBytes = getTargetData()->getTypeStoreSize(Ty); + const unsigned StoreBytes = getDataLayout()->getTypeStoreSize(Ty); switch (Ty->getTypeID()) { case Type::IntegerTyID: @@ -881,7 +884,7 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, dbgs() << "Cannot store value of type " << *Ty << "!\n"; } - if (sys::isLittleEndianHost() != getTargetData()->isLittleEndian()) + if (sys::isLittleEndianHost() != getDataLayout()->isLittleEndian()) // Host and target are different endian - reverse the stored bytes. std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr); } @@ -917,7 +920,7 @@ static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) { void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, Type *Ty) { - const unsigned LoadBytes = getTargetData()->getTypeStoreSize(Ty); + const unsigned LoadBytes = getDataLayout()->getTypeStoreSize(Ty); switch (Ty->getTypeID()) { case Type::IntegerTyID: @@ -958,20 +961,20 @@ void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) { if (const ConstantVector *CP = dyn_cast<ConstantVector>(Init)) { unsigned ElementSize = - getTargetData()->getTypeAllocSize(CP->getType()->getElementType()); + getDataLayout()->getTypeAllocSize(CP->getType()->getElementType()); for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) InitializeMemory(CP->getOperand(i), (char*)Addr+i*ElementSize); return; } if (isa<ConstantAggregateZero>(Init)) { - memset(Addr, 0, (size_t)getTargetData()->getTypeAllocSize(Init->getType())); + memset(Addr, 0, (size_t)getDataLayout()->getTypeAllocSize(Init->getType())); return; } if (const ConstantArray *CPA = dyn_cast<ConstantArray>(Init)) { unsigned ElementSize = - getTargetData()->getTypeAllocSize(CPA->getType()->getElementType()); + getDataLayout()->getTypeAllocSize(CPA->getType()->getElementType()); for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i) InitializeMemory(CPA->getOperand(i), (char*)Addr+i*ElementSize); return; @@ -979,7 +982,7 @@ void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) { if (const ConstantStruct *CPS = dyn_cast<ConstantStruct>(Init)) { const StructLayout *SL = - getTargetData()->getStructLayout(cast<StructType>(CPS->getType())); + getDataLayout()->getStructLayout(cast<StructType>(CPS->getType())); for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i) InitializeMemory(CPS->getOperand(i), (char*)Addr+SL->getElementOffset(i)); return; @@ -1126,7 +1129,7 @@ void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) { InitializeMemory(GV->getInitializer(), GA); Type *ElTy = GV->getType()->getElementType(); - size_t GVSize = (size_t)getTargetData()->getTypeAllocSize(ElTy); + size_t GVSize = (size_t)getDataLayout()->getTypeAllocSize(ElTy); NumInitBytes += (unsigned)GVSize; ++NumGlobals; } diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp index 75e680a..1e790e7 100644 --- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -239,7 +239,7 @@ void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, LLVMValueRef Fn) } LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { - return wrap(unwrap(EE)->getTargetData()); + return wrap(unwrap(EE)->getDataLayout()); } void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, diff --git a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index c11c17e..4cb0270 100644 --- a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -22,12 +22,12 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/ExecutionEngine/IntelJITEventsWrapper.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Errno.h" #include "llvm/Support/ValueHandle.h" #include "EventListenerCommon.h" +#include "IntelJITEventsWrapper.h" using namespace llvm; using namespace llvm::jitprofiling; @@ -37,13 +37,13 @@ namespace { class IntelJITEventListener : public JITEventListener { typedef DenseMap<void*, unsigned int> MethodIDMap; - IntelJITEventsWrapper& Wrapper; + OwningPtr<IntelJITEventsWrapper> Wrapper; MethodIDMap MethodIDs; FilenameCache Filenames; public: - IntelJITEventListener(IntelJITEventsWrapper& libraryWrapper) - : Wrapper(libraryWrapper) { + IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) { + Wrapper.reset(libraryWrapper); } ~IntelJITEventListener() { @@ -54,6 +54,10 @@ public: const EmittedFunctionDetails &Details); virtual void NotifyFreeingMachineCode(void *OldPtr); + + virtual void NotifyObjectEmitted(const ObjectImage &Obj); + + virtual void NotifyFreeingObject(const ObjectImage &Obj); }; static LineNumberInfo LineStartToIntelJITFormat( @@ -94,7 +98,7 @@ static iJIT_Method_Load FunctionDescToIntelJITFormat( void IntelJITEventListener::NotifyFunctionEmitted( const Function &F, void *FnStart, size_t FnSize, const EmittedFunctionDetails &Details) { - iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(Wrapper, + iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(*Wrapper, F.getName().data(), reinterpret_cast<uint64_t>(FnStart), FnSize); @@ -151,32 +155,36 @@ void IntelJITEventListener::NotifyFunctionEmitted( FunctionMessage.line_number_table = 0; } - Wrapper.iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, - &FunctionMessage); + Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, + &FunctionMessage); MethodIDs[FnStart] = FunctionMessage.method_id; } void IntelJITEventListener::NotifyFreeingMachineCode(void *FnStart) { MethodIDMap::iterator I = MethodIDs.find(FnStart); if (I != MethodIDs.end()) { - Wrapper.iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, &I->second); + Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, &I->second); MethodIDs.erase(I); } } +void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { +} + +void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { +} + } // anonymous namespace. namespace llvm { JITEventListener *JITEventListener::createIntelJITEventListener() { - static OwningPtr<IntelJITEventsWrapper> JITProfilingWrapper( - new IntelJITEventsWrapper); - return new IntelJITEventListener(*JITProfilingWrapper); + return new IntelJITEventListener(new IntelJITEventsWrapper); } // for testing JITEventListener *JITEventListener::createIntelJITEventListener( IntelJITEventsWrapper* TestImpl) { - return new IntelJITEventListener(*TestImpl); + return new IntelJITEventListener(TestImpl); } } // namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h new file mode 100644 index 0000000..7ab08e1 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h @@ -0,0 +1,102 @@ +//===-- IntelJITEventsWrapper.h - Intel JIT Events API Wrapper --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a wrapper for the Intel JIT Events API. It allows for the +// implementation of the jitprofiling library to be swapped with an alternative +// implementation (for testing). To include this file, you must have the +// jitprofiling.h header available; it is available in Intel(R) VTune(TM) +// Amplifier XE 2011. +// +//===----------------------------------------------------------------------===// + +#ifndef INTEL_JIT_EVENTS_WRAPPER_H +#define INTEL_JIT_EVENTS_WRAPPER_H + +#include "jitprofiling.h" + +namespace llvm { + +class IntelJITEventsWrapper { + // Function pointer types for testing implementation of Intel jitprofiling + // library + typedef int (*NotifyEventPtr)(iJIT_JVM_EVENT, void*); + typedef void (*RegisterCallbackExPtr)(void *, iJIT_ModeChangedEx ); + typedef iJIT_IsProfilingActiveFlags (*IsProfilingActivePtr)(void); + typedef void (*FinalizeThreadPtr)(void); + typedef void (*FinalizeProcessPtr)(void); + typedef unsigned int (*GetNewMethodIDPtr)(void); + + NotifyEventPtr NotifyEventFunc; + RegisterCallbackExPtr RegisterCallbackExFunc; + IsProfilingActivePtr IsProfilingActiveFunc; + FinalizeThreadPtr FinalizeThreadFunc; + FinalizeProcessPtr FinalizeProcessFunc; + GetNewMethodIDPtr GetNewMethodIDFunc; + +public: + bool isAmplifierRunning() { + return iJIT_IsProfilingActive() == iJIT_SAMPLING_ON; + } + + IntelJITEventsWrapper() + : NotifyEventFunc(::iJIT_NotifyEvent), + RegisterCallbackExFunc(::iJIT_RegisterCallbackEx), + IsProfilingActiveFunc(::iJIT_IsProfilingActive), + FinalizeThreadFunc(::FinalizeThread), + FinalizeProcessFunc(::FinalizeProcess), + GetNewMethodIDFunc(::iJIT_GetNewMethodID) { + } + + IntelJITEventsWrapper(NotifyEventPtr NotifyEventImpl, + RegisterCallbackExPtr RegisterCallbackExImpl, + IsProfilingActivePtr IsProfilingActiveImpl, + FinalizeThreadPtr FinalizeThreadImpl, + FinalizeProcessPtr FinalizeProcessImpl, + GetNewMethodIDPtr GetNewMethodIDImpl) + : NotifyEventFunc(NotifyEventImpl), + RegisterCallbackExFunc(RegisterCallbackExImpl), + IsProfilingActiveFunc(IsProfilingActiveImpl), + FinalizeThreadFunc(FinalizeThreadImpl), + FinalizeProcessFunc(FinalizeProcessImpl), + GetNewMethodIDFunc(GetNewMethodIDImpl) { + } + + // Sends an event anncouncing that a function has been emitted + // return values are event-specific. See Intel documentation for details. + int iJIT_NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { + if (!NotifyEventFunc) + return -1; + return NotifyEventFunc(EventType, EventSpecificData); + } + + // Registers a callback function to receive notice of profiling state changes + void iJIT_RegisterCallbackEx(void *UserData, + iJIT_ModeChangedEx NewModeCallBackFuncEx) { + if (RegisterCallbackExFunc) + RegisterCallbackExFunc(UserData, NewModeCallBackFuncEx); + } + + // Returns the current profiler mode + iJIT_IsProfilingActiveFlags iJIT_IsProfilingActive(void) { + if (!IsProfilingActiveFunc) + return iJIT_NOTHING_RUNNING; + return IsProfilingActiveFunc(); + } + + // Generates a locally unique method ID for use in code registration + unsigned int iJIT_GetNewMethodID(void) { + if (!GetNewMethodIDFunc) + return -1; + return GetNewMethodIDFunc(); + } +}; + +} //namespace llvm + +#endif //INTEL_JIT_EVENTS_WRAPPER_H diff --git a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/ittnotify_config.h b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/ittnotify_config.h new file mode 100644 index 0000000..1f029fb --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/ittnotify_config.h @@ -0,0 +1,454 @@ +/*===-- ittnotify_config.h - JIT Profiling API internal config-----*- C -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===* + * + * This file provides Intel(R) Performance Analyzer JIT (Just-In-Time) + * Profiling API internal config. + * + * NOTE: This file comes in a style different from the rest of LLVM + * source base since this is a piece of code shared from Intel(R) + * products. Please do not reformat / re-style this code to make + * subsequent merges and contributions from the original source base eaiser. + * + *===----------------------------------------------------------------------===*/ +#ifndef _ITTNOTIFY_CONFIG_H_ +#define _ITTNOTIFY_CONFIG_H_ + +/** @cond exclude_from_documentation */ +#ifndef ITT_OS_WIN +# define ITT_OS_WIN 1 +#endif /* ITT_OS_WIN */ + +#ifndef ITT_OS_LINUX +# define ITT_OS_LINUX 2 +#endif /* ITT_OS_LINUX */ + +#ifndef ITT_OS_MAC +# define ITT_OS_MAC 3 +#endif /* ITT_OS_MAC */ + +#ifndef ITT_OS +# if defined WIN32 || defined _WIN32 +# define ITT_OS ITT_OS_WIN +# elif defined( __APPLE__ ) && defined( __MACH__ ) +# define ITT_OS ITT_OS_MAC +# else +# define ITT_OS ITT_OS_LINUX +# endif +#endif /* ITT_OS */ + +#ifndef ITT_PLATFORM_WIN +# define ITT_PLATFORM_WIN 1 +#endif /* ITT_PLATFORM_WIN */ + +#ifndef ITT_PLATFORM_POSIX +# define ITT_PLATFORM_POSIX 2 +#endif /* ITT_PLATFORM_POSIX */ + +#ifndef ITT_PLATFORM +# if ITT_OS==ITT_OS_WIN +# define ITT_PLATFORM ITT_PLATFORM_WIN +# else +# define ITT_PLATFORM ITT_PLATFORM_POSIX +# endif /* _WIN32 */ +#endif /* ITT_PLATFORM */ + +#if defined(_UNICODE) && !defined(UNICODE) +#define UNICODE +#endif + +#include <stddef.h> +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include <tchar.h> +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include <stdint.h> +#if defined(UNICODE) || defined(_UNICODE) +#include <wchar.h> +#endif /* UNICODE || _UNICODE */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#ifndef CDECL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define CDECL __cdecl +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define CDECL /* not actual on x86_64 platform */ +# else /* _M_X64 || _M_AMD64 || __x86_64__ */ +# define CDECL __attribute__ ((cdecl)) +# endif /* _M_X64 || _M_AMD64 || __x86_64__ */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* CDECL */ + +#ifndef STDCALL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define STDCALL __stdcall +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define STDCALL /* not supported on x86_64 platform */ +# else /* _M_X64 || _M_AMD64 || __x86_64__ */ +# define STDCALL __attribute__ ((stdcall)) +# endif /* _M_X64 || _M_AMD64 || __x86_64__ */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* STDCALL */ + +#define ITTAPI CDECL +#define LIBITTAPI CDECL + +/* TODO: Temporary for compatibility! */ +#define ITTAPI_CALL CDECL +#define LIBITTAPI_CALL CDECL + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +/* use __forceinline (VC++ specific) */ +#define ITT_INLINE __forceinline +#define ITT_INLINE_ATTRIBUTE /* nothing */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +/* + * Generally, functions are not inlined unless optimization is specified. + * For functions declared inline, this attribute inlines the function even + * if no optimization level was specified. + */ +#ifdef __STRICT_ANSI__ +#define ITT_INLINE static +#else /* __STRICT_ANSI__ */ +#define ITT_INLINE static inline +#endif /* __STRICT_ANSI__ */ +#define ITT_INLINE_ATTRIBUTE __attribute__ ((always_inline)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +/** @endcond */ + +#ifndef ITT_ARCH_IA32 +# define ITT_ARCH_IA32 1 +#endif /* ITT_ARCH_IA32 */ + +#ifndef ITT_ARCH_IA32E +# define ITT_ARCH_IA32E 2 +#endif /* ITT_ARCH_IA32E */ + +#ifndef ITT_ARCH_IA64 +# define ITT_ARCH_IA64 3 +#endif /* ITT_ARCH_IA64 */ + +#ifndef ITT_ARCH +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define ITT_ARCH ITT_ARCH_IA32E +# elif defined _M_IA64 || defined __ia64 +# define ITT_ARCH ITT_ARCH_IA64 +# else +# define ITT_ARCH ITT_ARCH_IA32 +# endif +#endif + +#ifdef __cplusplus +# define ITT_EXTERN_C extern "C" +#else +# define ITT_EXTERN_C /* nothing */ +#endif /* __cplusplus */ + +#define ITT_TO_STR_AUX(x) #x +#define ITT_TO_STR(x) ITT_TO_STR_AUX(x) + +#define __ITT_BUILD_ASSERT(expr, suffix) do { \ + static char __itt_build_check_##suffix[(expr) ? 1 : -1]; \ + __itt_build_check_##suffix[0] = 0; \ +} while(0) +#define _ITT_BUILD_ASSERT(expr, suffix) __ITT_BUILD_ASSERT((expr), suffix) +#define ITT_BUILD_ASSERT(expr) _ITT_BUILD_ASSERT((expr), __LINE__) + +#define ITT_MAGIC { 0xED, 0xAB, 0xAB, 0xEC, 0x0D, 0xEE, 0xDA, 0x30 } + +/* Replace with snapshot date YYYYMMDD for promotion build. */ +#define API_VERSION_BUILD 20111111 + +#ifndef API_VERSION_NUM +#define API_VERSION_NUM 0.0.0 +#endif /* API_VERSION_NUM */ + +#define API_VERSION "ITT-API-Version " ITT_TO_STR(API_VERSION_NUM) \ + " (" ITT_TO_STR(API_VERSION_BUILD) ")" + +/* OS communication functions */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include <windows.h> +typedef HMODULE lib_t; +typedef DWORD TIDT; +typedef CRITICAL_SECTION mutex_t; +#define MUTEX_INITIALIZER { 0 } +#define strong_alias(name, aliasname) /* empty for Windows */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include <dlfcn.h> +#if defined(UNICODE) || defined(_UNICODE) +#include <wchar.h> +#endif /* UNICODE */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 /* need for PTHREAD_MUTEX_RECURSIVE */ +#endif /* _GNU_SOURCE */ +#include <pthread.h> +typedef void* lib_t; +typedef pthread_t TIDT; +typedef pthread_mutex_t mutex_t; +#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); +#define strong_alias(name, aliasname) _strong_alias(name, aliasname) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_get_proc(lib, name) GetProcAddress(lib, name) +#define __itt_mutex_init(mutex) InitializeCriticalSection(mutex) +#define __itt_mutex_lock(mutex) EnterCriticalSection(mutex) +#define __itt_mutex_unlock(mutex) LeaveCriticalSection(mutex) +#define __itt_load_lib(name) LoadLibraryA(name) +#define __itt_unload_lib(handle) FreeLibrary(handle) +#define __itt_system_error() (int)GetLastError() +#define __itt_fstrcmp(s1, s2) lstrcmpA(s1, s2) +#define __itt_fstrlen(s) lstrlenA(s) +#define __itt_fstrcpyn(s1, s2, l) lstrcpynA(s1, s2, l) +#define __itt_fstrdup(s) _strdup(s) +#define __itt_thread_id() GetCurrentThreadId() +#define __itt_thread_yield() SwitchToThread() +#ifndef ITT_SIMPLE_INIT +ITT_INLINE long +__itt_interlocked_increment(volatile long* ptr) ITT_INLINE_ATTRIBUTE; +ITT_INLINE long __itt_interlocked_increment(volatile long* ptr) +{ + return InterlockedIncrement(ptr); +} +#endif /* ITT_SIMPLE_INIT */ +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +#define __itt_get_proc(lib, name) dlsym(lib, name) +#define __itt_mutex_init(mutex) {\ + pthread_mutexattr_t mutex_attr; \ + int error_code = pthread_mutexattr_init(&mutex_attr); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutexattr_init", \ + error_code); \ + error_code = pthread_mutexattr_settype(&mutex_attr, \ + PTHREAD_MUTEX_RECURSIVE); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutexattr_settype", \ + error_code); \ + error_code = pthread_mutex_init(mutex, &mutex_attr); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutex_init", \ + error_code); \ + error_code = pthread_mutexattr_destroy(&mutex_attr); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutexattr_destroy", \ + error_code); \ +} +#define __itt_mutex_lock(mutex) pthread_mutex_lock(mutex) +#define __itt_mutex_unlock(mutex) pthread_mutex_unlock(mutex) +#define __itt_load_lib(name) dlopen(name, RTLD_LAZY) +#define __itt_unload_lib(handle) dlclose(handle) +#define __itt_system_error() errno +#define __itt_fstrcmp(s1, s2) strcmp(s1, s2) +#define __itt_fstrlen(s) strlen(s) +#define __itt_fstrcpyn(s1, s2, l) strncpy(s1, s2, l) +#define __itt_fstrdup(s) strdup(s) +#define __itt_thread_id() pthread_self() +#define __itt_thread_yield() sched_yield() +#if ITT_ARCH==ITT_ARCH_IA64 +#ifdef __INTEL_COMPILER +#define __TBB_machine_fetchadd4(addr, val) __fetchadd4_acq((void *)addr, val) +#else /* __INTEL_COMPILER */ +/* TODO: Add Support for not Intel compilers for IA64 */ +#endif /* __INTEL_COMPILER */ +#else /* ITT_ARCH!=ITT_ARCH_IA64 */ +ITT_INLINE long +__TBB_machine_fetchadd4(volatile void* ptr, long addend) ITT_INLINE_ATTRIBUTE; +ITT_INLINE long __TBB_machine_fetchadd4(volatile void* ptr, long addend) +{ + long result; + __asm__ __volatile__("lock\nxadd %0,%1" + : "=r"(result),"=m"(*(long*)ptr) + : "0"(addend), "m"(*(long*)ptr) + : "memory"); + return result; +} +#endif /* ITT_ARCH==ITT_ARCH_IA64 */ +#ifndef ITT_SIMPLE_INIT +ITT_INLINE long +__itt_interlocked_increment(volatile long* ptr) ITT_INLINE_ATTRIBUTE; +ITT_INLINE long __itt_interlocked_increment(volatile long* ptr) +{ + return __TBB_machine_fetchadd4(ptr, 1) + 1L; +} +#endif /* ITT_SIMPLE_INIT */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +typedef enum { + __itt_collection_normal = 0, + __itt_collection_paused = 1 +} __itt_collection_state; + +typedef enum { + __itt_thread_normal = 0, + __itt_thread_ignored = 1 +} __itt_thread_state; + +#pragma pack(push, 8) + +typedef struct ___itt_thread_info +{ + const char* nameA; /*!< Copy of original name in ASCII. */ +#if defined(UNICODE) || defined(_UNICODE) + const wchar_t* nameW; /*!< Copy of original name in UNICODE. */ +#else /* UNICODE || _UNICODE */ + void* nameW; +#endif /* UNICODE || _UNICODE */ + TIDT tid; + __itt_thread_state state; /*!< Thread state (paused or normal) */ + int extra1; /*!< Reserved to the runtime */ + void* extra2; /*!< Reserved to the runtime */ + struct ___itt_thread_info* next; +} __itt_thread_info; + +#include "ittnotify_types.h" /* For __itt_group_id definition */ + +typedef struct ___itt_api_info_20101001 +{ + const char* name; + void** func_ptr; + void* init_func; + __itt_group_id group; +} __itt_api_info_20101001; + +typedef struct ___itt_api_info +{ + const char* name; + void** func_ptr; + void* init_func; + void* null_func; + __itt_group_id group; +} __itt_api_info; + +struct ___itt_domain; +struct ___itt_string_handle; + +typedef struct ___itt_global +{ + unsigned char magic[8]; + unsigned long version_major; + unsigned long version_minor; + unsigned long version_build; + volatile long api_initialized; + volatile long mutex_initialized; + volatile long atomic_counter; + mutex_t mutex; + lib_t lib; + void* error_handler; + const char** dll_path_ptr; + __itt_api_info* api_list_ptr; + struct ___itt_global* next; + /* Joinable structures below */ + __itt_thread_info* thread_list; + struct ___itt_domain* domain_list; + struct ___itt_string_handle* string_list; + __itt_collection_state state; +} __itt_global; + +#pragma pack(pop) + +#define NEW_THREAD_INFO_W(gptr,h,h_tail,t,s,n) { \ + h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \ + if (h != NULL) { \ + h->tid = t; \ + h->nameA = NULL; \ + h->nameW = n ? _wcsdup(n) : NULL; \ + h->state = s; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->thread_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_THREAD_INFO_A(gptr,h,h_tail,t,s,n) { \ + h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \ + if (h != NULL) { \ + h->tid = t; \ + h->nameA = n ? __itt_fstrdup(n) : NULL; \ + h->nameW = NULL; \ + h->state = s; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->thread_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_DOMAIN_W(gptr,h,h_tail,name) { \ + h = (__itt_domain*)malloc(sizeof(__itt_domain)); \ + if (h != NULL) { \ + h->flags = 0; /* domain is disabled by default */ \ + h->nameA = NULL; \ + h->nameW = name ? _wcsdup(name) : NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->domain_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_DOMAIN_A(gptr,h,h_tail,name) { \ + h = (__itt_domain*)malloc(sizeof(__itt_domain)); \ + if (h != NULL) { \ + h->flags = 0; /* domain is disabled by default */ \ + h->nameA = name ? __itt_fstrdup(name) : NULL; \ + h->nameW = NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->domain_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_STRING_HANDLE_W(gptr,h,h_tail,name) { \ + h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \ + if (h != NULL) { \ + h->strA = NULL; \ + h->strW = name ? _wcsdup(name) : NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->string_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_STRING_HANDLE_A(gptr,h,h_tail,name) { \ + h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \ + if (h != NULL) { \ + h->strA = name ? __itt_fstrdup(name) : NULL; \ + h->strW = NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->string_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#endif /* _ITTNOTIFY_CONFIG_H_ */ diff --git a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/ittnotify_types.h b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/ittnotify_types.h new file mode 100644 index 0000000..5df752f --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/ittnotify_types.h @@ -0,0 +1,70 @@ +/*===-- ittnotify_types.h - JIT Profiling API internal types--------*- C -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===* + * + * NOTE: This file comes in a style different from the rest of LLVM + * source base since this is a piece of code shared from Intel(R) + * products. Please do not reformat / re-style this code to make + * subsequent merges and contributions from the original source base eaiser. + * + *===----------------------------------------------------------------------===*/ +#ifndef _ITTNOTIFY_TYPES_H_ +#define _ITTNOTIFY_TYPES_H_ + +typedef enum ___itt_group_id +{ + __itt_group_none = 0, + __itt_group_legacy = 1<<0, + __itt_group_control = 1<<1, + __itt_group_thread = 1<<2, + __itt_group_mark = 1<<3, + __itt_group_sync = 1<<4, + __itt_group_fsync = 1<<5, + __itt_group_jit = 1<<6, + __itt_group_model = 1<<7, + __itt_group_splitter_min = 1<<7, + __itt_group_counter = 1<<8, + __itt_group_frame = 1<<9, + __itt_group_stitch = 1<<10, + __itt_group_heap = 1<<11, + __itt_group_splitter_max = 1<<12, + __itt_group_structure = 1<<12, + __itt_group_suppress = 1<<13, + __itt_group_all = -1 +} __itt_group_id; + +#pragma pack(push, 8) + +typedef struct ___itt_group_list +{ + __itt_group_id id; + const char* name; +} __itt_group_list; + +#pragma pack(pop) + +#define ITT_GROUP_LIST(varname) \ + static __itt_group_list varname[] = { \ + { __itt_group_all, "all" }, \ + { __itt_group_control, "control" }, \ + { __itt_group_thread, "thread" }, \ + { __itt_group_mark, "mark" }, \ + { __itt_group_sync, "sync" }, \ + { __itt_group_fsync, "fsync" }, \ + { __itt_group_jit, "jit" }, \ + { __itt_group_model, "model" }, \ + { __itt_group_counter, "counter" }, \ + { __itt_group_frame, "frame" }, \ + { __itt_group_stitch, "stitch" }, \ + { __itt_group_heap, "heap" }, \ + { __itt_group_structure, "structure" }, \ + { __itt_group_suppress, "suppress" }, \ + { __itt_group_none, NULL } \ + } + +#endif /* _ITTNOTIFY_TYPES_H_ */ diff --git a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/jitprofiling.c b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/jitprofiling.c new file mode 100644 index 0000000..7b507de --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/jitprofiling.c @@ -0,0 +1,481 @@ +/*===-- jitprofiling.c - JIT (Just-In-Time) Profiling API----------*- C -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===* + * + * This file provides Intel(R) Performance Analyzer JIT (Just-In-Time) + * Profiling API implementation. + * + * NOTE: This file comes in a style different from the rest of LLVM + * source base since this is a piece of code shared from Intel(R) + * products. Please do not reformat / re-style this code to make + * subsequent merges and contributions from the original source base eaiser. + * + *===----------------------------------------------------------------------===*/ +#include "ittnotify_config.h" + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include <windows.h> +#pragma optimize("", off) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include <pthread.h> +#include <dlfcn.h> +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include <malloc.h> +#include <stdlib.h> + +#include "jitprofiling.h" + +static const char rcsid[] = "\n@(#) $Revision: 243501 $\n"; + +#define DLL_ENVIRONMENT_VAR "VS_PROFILER" + +#ifndef NEW_DLL_ENVIRONMENT_VAR +#if ITT_ARCH==ITT_ARCH_IA32 +#define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER32" +#else +#define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER64" +#endif +#endif /* NEW_DLL_ENVIRONMENT_VAR */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define DEFAULT_DLLNAME "JitPI.dll" +HINSTANCE m_libHandle = NULL; +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define DEFAULT_DLLNAME "libJitPI.so" +void* m_libHandle = NULL; +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/* default location of JIT profiling agent on Android */ +#define ANDROID_JIT_AGENT_PATH "/data/intel/libittnotify.so" + +/* the function pointers */ +typedef unsigned int(*TPInitialize)(void); +static TPInitialize FUNC_Initialize=NULL; + +typedef unsigned int(*TPNotify)(unsigned int, void*); +static TPNotify FUNC_NotifyEvent=NULL; + +static iJIT_IsProfilingActiveFlags executionMode = iJIT_NOTHING_RUNNING; + +/* end collector dll part. */ + +/* loadiJIT_Funcs() : this function is called just in the beginning + * and is responsible to load the functions from BistroJavaCollector.dll + * result: + * on success: the functions loads, iJIT_DLL_is_missing=0, return value = 1 + * on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 0 + */ +static int loadiJIT_Funcs(void); + +/* global representing whether the BistroJavaCollector can't be loaded */ +static int iJIT_DLL_is_missing = 0; + +/* Virtual stack - the struct is used as a virtual stack for each thread. + * Every thread initializes with a stack of size INIT_TOP_STACK. + * Every method entry decreases from the current stack point, + * and when a thread stack reaches its top of stack (return from the global + * function), the top of stack and the current stack increase. Notice that + * when returning from a function the stack pointer is the address of + * the function return. +*/ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +static DWORD threadLocalStorageHandle = 0; +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +static pthread_key_t threadLocalStorageHandle = (pthread_key_t)0; +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#define INIT_TOP_Stack 10000 + +typedef struct +{ + unsigned int TopStack; + unsigned int CurrentStack; +} ThreadStack, *pThreadStack; + +/* end of virtual stack. */ + +/* + * The function for reporting virtual-machine related events to VTune. + * Note: when reporting iJVM_EVENT_TYPE_ENTER_NIDS, there is no need to fill + * in the stack_id field in the iJIT_Method_NIDS structure, as VTune fills it. + * The return value in iJVM_EVENT_TYPE_ENTER_NIDS && + * iJVM_EVENT_TYPE_LEAVE_NIDS events will be 0 in case of failure. + * in iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event + * it will be -1 if EventSpecificData == 0 otherwise it will be 0. +*/ + +ITT_EXTERN_C int JITAPI +iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData) +{ + int ReturnValue; + + /* + * This section is for debugging outside of VTune. + * It creates the environment variables that indicates call graph mode. + * If running outside of VTune remove the remark. + * + * + * static int firstTime = 1; + * char DoCallGraph[12] = "DoCallGraph"; + * if (firstTime) + * { + * firstTime = 0; + * SetEnvironmentVariable( "BISTRO_COLLECTORS_DO_CALLGRAPH", DoCallGraph); + * } + * + * end of section. + */ + + /* initialization part - the functions have not been loaded yet. This part + * will load the functions, and check if we are in Call Graph mode. + * (for special treatment). + */ + if (!FUNC_NotifyEvent) + { + if (iJIT_DLL_is_missing) + return 0; + + /* load the Function from the DLL */ + if (!loadiJIT_Funcs()) + return 0; + + /* Call Graph initialization. */ + } + + /* If the event is method entry/exit, check that in the current mode + * VTune is allowed to receive it + */ + if ((event_type == iJVM_EVENT_TYPE_ENTER_NIDS || + event_type == iJVM_EVENT_TYPE_LEAVE_NIDS) && + (executionMode != iJIT_CALLGRAPH_ON)) + { + return 0; + } + /* This section is performed when method enter event occurs. + * It updates the virtual stack, or creates it if this is the first + * method entry in the thread. The stack pointer is decreased. + */ + if (event_type == iJVM_EVENT_TYPE_ENTER_NIDS) + { +#if ITT_PLATFORM==ITT_PLATFORM_WIN + pThreadStack threadStack = + (pThreadStack)TlsGetValue (threadLocalStorageHandle); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + pThreadStack threadStack = + (pThreadStack)pthread_getspecific(threadLocalStorageHandle); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + + /* check for use of reserved method IDs */ + if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 ) + return 0; + + if (!threadStack) + { + /* initialize the stack. */ + threadStack = (pThreadStack) calloc (sizeof(ThreadStack), 1); + threadStack->TopStack = INIT_TOP_Stack; + threadStack->CurrentStack = INIT_TOP_Stack; +#if ITT_PLATFORM==ITT_PLATFORM_WIN + TlsSetValue(threadLocalStorageHandle,(void*)threadStack); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + pthread_setspecific(threadLocalStorageHandle,(void*)threadStack); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + } + + /* decrease the stack. */ + ((piJIT_Method_NIDS) EventSpecificData)->stack_id = + (threadStack->CurrentStack)--; + } + + /* This section is performed when method leave event occurs + * It updates the virtual stack. + * Increases the stack pointer. + * If the stack pointer reached the top (left the global function) + * increase the pointer and the top pointer. + */ + if (event_type == iJVM_EVENT_TYPE_LEAVE_NIDS) + { +#if ITT_PLATFORM==ITT_PLATFORM_WIN + pThreadStack threadStack = + (pThreadStack)TlsGetValue (threadLocalStorageHandle); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + pThreadStack threadStack = + (pThreadStack)pthread_getspecific(threadLocalStorageHandle); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + + /* check for use of reserved method IDs */ + if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 ) + return 0; + + if (!threadStack) + { + /* Error: first report in this thread is method exit */ + exit (1); + } + + ((piJIT_Method_NIDS) EventSpecificData)->stack_id = + ++(threadStack->CurrentStack) + 1; + + if (((piJIT_Method_NIDS) EventSpecificData)->stack_id + > threadStack->TopStack) + ((piJIT_Method_NIDS) EventSpecificData)->stack_id = + (unsigned int)-1; + } + + if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED) + { + /* check for use of reserved method IDs */ + if ( ((piJIT_Method_Load) EventSpecificData)->method_id <= 999 ) + return 0; + } + + ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData); + + return ReturnValue; +} + +/* The new mode call back routine */ +ITT_EXTERN_C void JITAPI +iJIT_RegisterCallbackEx(void *userdata, iJIT_ModeChangedEx + NewModeCallBackFuncEx) +{ + /* is it already missing... or the load of functions from the DLL failed */ + if (iJIT_DLL_is_missing || !loadiJIT_Funcs()) + { + /* then do not bother with notifications */ + NewModeCallBackFuncEx(userdata, iJIT_NO_NOTIFICATIONS); + /* Error: could not load JIT functions. */ + return; + } + /* nothing to do with the callback */ +} + +/* + * This function allows the user to query in which mode, if at all, + *VTune is running + */ +ITT_EXTERN_C iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive() +{ + if (!iJIT_DLL_is_missing) + { + loadiJIT_Funcs(); + } + + return executionMode; +} + +/* this function loads the collector dll (BistroJavaCollector) + * and the relevant functions. + * on success: all functions load, iJIT_DLL_is_missing = 0, return value = 1 + * on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0 + */ +static int loadiJIT_Funcs() +{ + static int bDllWasLoaded = 0; + char *dllName = (char*)rcsid; /* !! Just to avoid unused code elimination */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN + DWORD dNameLength = 0; +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + + if(bDllWasLoaded) + { + /* dll was already loaded, no need to do it for the second time */ + return 1; + } + + /* Assumes that the DLL will not be found */ + iJIT_DLL_is_missing = 1; + FUNC_NotifyEvent = NULL; + + if (m_libHandle) + { +#if ITT_PLATFORM==ITT_PLATFORM_WIN + FreeLibrary(m_libHandle); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + dlclose(m_libHandle); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + m_libHandle = NULL; + } + + /* Try to get the dll name from the environment */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN + dNameLength = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, NULL, 0); + if (dNameLength) + { + DWORD envret = 0; + dllName = (char*)malloc(sizeof(char) * (dNameLength + 1)); + envret = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, + dllName, dNameLength); + if (envret) + { + /* Try to load the dll from the PATH... */ + m_libHandle = LoadLibraryExA(dllName, + NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + } + free(dllName); + } else { + /* Try to use old VS_PROFILER variable */ + dNameLength = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, NULL, 0); + if (dNameLength) + { + DWORD envret = 0; + dllName = (char*)malloc(sizeof(char) * (dNameLength + 1)); + envret = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, + dllName, dNameLength); + if (envret) + { + /* Try to load the dll from the PATH... */ + m_libHandle = LoadLibraryA(dllName); + } + free(dllName); + } + } +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + dllName = getenv(NEW_DLL_ENVIRONMENT_VAR); + if (!dllName) + dllName = getenv(DLL_ENVIRONMENT_VAR); +#ifdef ANDROID + if (!dllName) + dllName = ANDROID_JIT_AGENT_PATH; +#endif + if (dllName) + { + /* Try to load the dll from the PATH... */ + m_libHandle = dlopen(dllName, RTLD_LAZY); + } +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + + if (!m_libHandle) + { +#if ITT_PLATFORM==ITT_PLATFORM_WIN + m_libHandle = LoadLibraryA(DEFAULT_DLLNAME); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + m_libHandle = dlopen(DEFAULT_DLLNAME, RTLD_LAZY); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + } + + /* if the dll wasn't loaded - exit. */ + if (!m_libHandle) + { + iJIT_DLL_is_missing = 1; /* don't try to initialize + * JIT agent the second time + */ + return 0; + } + +#if ITT_PLATFORM==ITT_PLATFORM_WIN + FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent"); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + FUNC_NotifyEvent = (TPNotify)dlsym(m_libHandle, "NotifyEvent"); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + if (!FUNC_NotifyEvent) + { + FUNC_Initialize = NULL; + return 0; + } + +#if ITT_PLATFORM==ITT_PLATFORM_WIN + FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize"); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + FUNC_Initialize = (TPInitialize)dlsym(m_libHandle, "Initialize"); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + if (!FUNC_Initialize) + { + FUNC_NotifyEvent = NULL; + return 0; + } + + executionMode = (iJIT_IsProfilingActiveFlags)FUNC_Initialize(); + + bDllWasLoaded = 1; + iJIT_DLL_is_missing = 0; /* DLL is ok. */ + + /* + * Call Graph mode: init the thread local storage + * (need to store the virtual stack there). + */ + if ( executionMode == iJIT_CALLGRAPH_ON ) + { + /* Allocate a thread local storage slot for the thread "stack" */ + if (!threadLocalStorageHandle) +#if ITT_PLATFORM==ITT_PLATFORM_WIN + threadLocalStorageHandle = TlsAlloc(); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + pthread_key_create(&threadLocalStorageHandle, NULL); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + } + + return 1; +} + +/* + * This function should be called by the user whenever a thread ends, + * to free the thread "virtual stack" storage + */ +ITT_EXTERN_C void JITAPI FinalizeThread() +{ + if (threadLocalStorageHandle) + { +#if ITT_PLATFORM==ITT_PLATFORM_WIN + pThreadStack threadStack = + (pThreadStack)TlsGetValue (threadLocalStorageHandle); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + pThreadStack threadStack = + (pThreadStack)pthread_getspecific(threadLocalStorageHandle); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + if (threadStack) + { + free (threadStack); + threadStack = NULL; +#if ITT_PLATFORM==ITT_PLATFORM_WIN + TlsSetValue (threadLocalStorageHandle, threadStack); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + pthread_setspecific(threadLocalStorageHandle, threadStack); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + } + } +} + +/* + * This function should be called by the user when the process ends, + * to free the local storage index +*/ +ITT_EXTERN_C void JITAPI FinalizeProcess() +{ + if (m_libHandle) + { +#if ITT_PLATFORM==ITT_PLATFORM_WIN + FreeLibrary(m_libHandle); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + dlclose(m_libHandle); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + m_libHandle = NULL; + } + + if (threadLocalStorageHandle) +#if ITT_PLATFORM==ITT_PLATFORM_WIN + TlsFree (threadLocalStorageHandle); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + pthread_key_delete(threadLocalStorageHandle); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +} + +/* + * This function should be called by the user for any method once. + * The function will return a unique method ID, the user should maintain + * the ID for each method + */ +ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID() +{ + static unsigned int methodID = 0x100000; + + if (methodID == 0) + return 0; /* ERROR : this is not a valid value */ + + return methodID++; +} diff --git a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/jitprofiling.h b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/jitprofiling.h new file mode 100644 index 0000000..f08e287 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/jitprofiling.h @@ -0,0 +1,259 @@ +/*===-- jitprofiling.h - JIT Profiling API-------------------------*- C -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===* + * + * This file provides Intel(R) Performance Analyzer JIT (Just-In-Time) + * Profiling API declaration. + * + * NOTE: This file comes in a style different from the rest of LLVM + * source base since this is a piece of code shared from Intel(R) + * products. Please do not reformat / re-style this code to make + * subsequent merges and contributions from the original source base eaiser. + * + *===----------------------------------------------------------------------===*/ +#ifndef __JITPROFILING_H__ +#define __JITPROFILING_H__ + +/* + * Various constants used by functions + */ + +/* event notification */ +typedef enum iJIT_jvm_event +{ + + /* shutdown */ + + /* + * Program exiting EventSpecificData NA + */ + iJVM_EVENT_TYPE_SHUTDOWN = 2, + + /* JIT profiling */ + + /* + * issued after method code jitted into memory but before code is executed + * EventSpecificData is an iJIT_Method_Load + */ + iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED=13, + + /* issued before unload. Method code will no longer be executed, but code + * and info are still in memory. The VTune profiler may capture method + * code only at this point EventSpecificData is iJIT_Method_Id + */ + iJVM_EVENT_TYPE_METHOD_UNLOAD_START, + + /* Method Profiling */ + + /* method name, Id and stack is supplied + * issued when a method is about to be entered EventSpecificData is + * iJIT_Method_NIDS + */ + iJVM_EVENT_TYPE_ENTER_NIDS = 19, + + /* method name, Id and stack is supplied + * issued when a method is about to be left EventSpecificData is + * iJIT_Method_NIDS + */ + iJVM_EVENT_TYPE_LEAVE_NIDS +} iJIT_JVM_EVENT; + +typedef enum _iJIT_ModeFlags +{ + /* No need to Notify VTune, since VTune is not running */ + iJIT_NO_NOTIFICATIONS = 0x0000, + + /* when turned on the jit must call + * iJIT_NotifyEvent + * ( + * iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, + * ) + * for all the method already jitted + */ + iJIT_BE_NOTIFY_ON_LOAD = 0x0001, + + /* when turned on the jit must call + * iJIT_NotifyEvent + * ( + * iJVM_EVENT_TYPE_METHOD_UNLOAD_FINISHED, + * ) for all the method that are unloaded + */ + iJIT_BE_NOTIFY_ON_UNLOAD = 0x0002, + + /* when turned on the jit must instrument all + * the currently jited code with calls on + * method entries + */ + iJIT_BE_NOTIFY_ON_METHOD_ENTRY = 0x0004, + + /* when turned on the jit must instrument all + * the currently jited code with calls + * on method exit + */ + iJIT_BE_NOTIFY_ON_METHOD_EXIT = 0x0008 + +} iJIT_ModeFlags; + + + /* Flags used by iJIT_IsProfilingActive() */ +typedef enum _iJIT_IsProfilingActiveFlags +{ + /* No profiler is running. Currently not used */ + iJIT_NOTHING_RUNNING = 0x0000, + + /* Sampling is running. This is the default value + * returned by iJIT_IsProfilingActive() + */ + iJIT_SAMPLING_ON = 0x0001, + + /* Call Graph is running */ + iJIT_CALLGRAPH_ON = 0x0002 + +} iJIT_IsProfilingActiveFlags; + +/* Enumerator for the environment of methods*/ +typedef enum _iJDEnvironmentType +{ + iJDE_JittingAPI = 2 +} iJDEnvironmentType; + +/********************************** + * Data structures for the events * + **********************************/ + +/* structure for the events: + * iJVM_EVENT_TYPE_METHOD_UNLOAD_START + */ + +typedef struct _iJIT_Method_Id +{ + /* Id of the method (same as the one passed in + * the iJIT_Method_Load struct + */ + unsigned int method_id; + +} *piJIT_Method_Id, iJIT_Method_Id; + + +/* structure for the events: + * iJVM_EVENT_TYPE_ENTER_NIDS, + * iJVM_EVENT_TYPE_LEAVE_NIDS, + * iJVM_EVENT_TYPE_EXCEPTION_OCCURRED_NIDS + */ + +typedef struct _iJIT_Method_NIDS +{ + /* unique method ID */ + unsigned int method_id; + + /* NOTE: no need to fill this field, it's filled by VTune */ + unsigned int stack_id; + + /* method name (just the method, without the class) */ + char* method_name; +} *piJIT_Method_NIDS, iJIT_Method_NIDS; + +/* structures for the events: + * iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED + */ + +typedef struct _LineNumberInfo +{ + /* x86 Offset from the begining of the method*/ + unsigned int Offset; + + /* source line number from the begining of the source file */ + unsigned int LineNumber; + +} *pLineNumberInfo, LineNumberInfo; + +typedef struct _iJIT_Method_Load +{ + /* unique method ID - can be any unique value, (except 0 - 999) */ + unsigned int method_id; + + /* method name (can be with or without the class and signature, in any case + * the class name will be added to it) + */ + char* method_name; + + /* virtual address of that method - This determines the method range for the + * iJVM_EVENT_TYPE_ENTER/LEAVE_METHOD_ADDR events + */ + void* method_load_address; + + /* Size in memory - Must be exact */ + unsigned int method_size; + + /* Line Table size in number of entries - Zero if none */ + unsigned int line_number_size; + + /* Pointer to the begining of the line numbers info array */ + pLineNumberInfo line_number_table; + + /* unique class ID */ + unsigned int class_id; + + /* class file name */ + char* class_file_name; + + /* source file name */ + char* source_file_name; + + /* bits supplied by the user for saving in the JIT file */ + void* user_data; + + /* the size of the user data buffer */ + unsigned int user_data_size; + + /* NOTE: no need to fill this field, it's filled by VTune */ + iJDEnvironmentType env; + +} *piJIT_Method_Load, iJIT_Method_Load; + +/* API Functions */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CDECL +# if defined WIN32 || defined _WIN32 +# define CDECL __cdecl +# else /* defined WIN32 || defined _WIN32 */ +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define CDECL /* not actual on x86_64 platform */ +# else /* _M_X64 || _M_AMD64 || __x86_64__ */ +# define CDECL __attribute__ ((cdecl)) +# endif /* _M_X64 || _M_AMD64 || __x86_64__ */ +# endif /* defined WIN32 || defined _WIN32 */ +#endif /* CDECL */ + +#define JITAPI CDECL + +/* called when the settings are changed with new settings */ +typedef void (*iJIT_ModeChangedEx)(void *UserData, iJIT_ModeFlags Flags); + +int JITAPI iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData); + +/* The new mode call back routine */ +void JITAPI iJIT_RegisterCallbackEx(void *userdata, + iJIT_ModeChangedEx NewModeCallBackFuncEx); + +iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive(void); + +void JITAPI FinalizeThread(void); + +void JITAPI FinalizeProcess(void); + +unsigned int JITAPI iJIT_GetNewMethodID(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __JITPROFILING_H__ */ diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp index 7a206eb..e16e2d1 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp @@ -25,7 +25,7 @@ #include "llvm/Config/config.h" // Detect libffi #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/DynamicLibrary.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include <csignal> @@ -180,7 +180,7 @@ static void *ffiValueFor(Type *Ty, const GenericValue &AV, static bool ffiInvoke(RawFunc Fn, Function *F, const std::vector<GenericValue> &ArgVals, - const TargetData *TD, GenericValue &Result) { + const DataLayout *TD, GenericValue &Result) { ffi_cif cif; FunctionType *FTy = F->getFunctionType(); const unsigned NumArgs = F->arg_size(); @@ -276,7 +276,7 @@ GenericValue Interpreter::callExternalFunction(Function *F, FunctionsLock->release(); GenericValue Result; - if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getTargetData(), Result)) + if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result)) return Result; #endif // USE_LIBFFI @@ -376,7 +376,7 @@ GenericValue lle_X_sprintf(FunctionType *FT, case 'x': case 'X': if (HowLong >= 1) { if (HowLong == 1 && - TheInterpreter->getTargetData()->getPointerSizeInBits() == 64 && + TheInterpreter->getDataLayout()->getPointerSizeInBits() == 64 && sizeof(long) < sizeof(int64_t)) { // Make sure we use %lld with a 64 bit argument because we might be // compiling LLI on a 32 bit compiler. diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp index 43e3453..55152db 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp @@ -48,7 +48,7 @@ Interpreter::Interpreter(Module *M) : ExecutionEngine(M), TD(M) { memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped)); - setTargetData(&TD); + setDataLayout(&TD); // Initialize the "backend" initializeExecutionEngine(); initializeExternalFunctions(); diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h index 28c5775..72c42c1 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -17,7 +17,7 @@ #include "llvm/Function.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -82,7 +82,7 @@ struct ExecutionContext { // class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> { GenericValue ExitValue; // The return value of the called function - TargetData TD; + DataLayout TD; IntrinsicLowering *IL; // The runtime stack of executing code. The top of the stack is the current diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp index 97995ad..1ad3382 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp @@ -24,7 +24,7 @@ #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetJITInfo.h" #include "llvm/Support/Dwarf.h" @@ -272,7 +272,7 @@ JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, : ExecutionEngine(M), TM(tm), TJI(tji), JMM(jmm ? jmm : JITMemoryManager::CreateDefaultMemManager()), AllocateGVsWithCode(GVsWithCode), isAlreadyCodeGenerating(false) { - setTargetData(TM.getTargetData()); + setDataLayout(TM.getDataLayout()); jitstate = new JITState(M); @@ -285,7 +285,7 @@ JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, // Add target data MutexGuard locked(lock); FunctionPassManager &PM = jitstate->getPM(locked); - PM.add(new TargetData(*TM.getTargetData())); + PM.add(new DataLayout(*TM.getDataLayout())); // Turn the machine code intermediate representation into bytes in memory that // may be executed. @@ -339,7 +339,7 @@ void JIT::addModule(Module *M) { jitstate = new JITState(M); FunctionPassManager &PM = jitstate->getPM(locked); - PM.add(new TargetData(*TM.getTargetData())); + PM.add(new DataLayout(*TM.getDataLayout())); // Turn the machine code intermediate representation into bytes in memory // that may be executed. @@ -370,7 +370,7 @@ bool JIT::removeModule(Module *M) { jitstate = new JITState(Modules[0]); FunctionPassManager &PM = jitstate->getPM(locked); - PM.add(new TargetData(*TM.getTargetData())); + PM.add(new DataLayout(*TM.getDataLayout())); // Turn the machine code intermediate representation into bytes in memory // that may be executed. @@ -815,8 +815,8 @@ char* JIT::getMemoryForGV(const GlobalVariable* GV) { // through the memory manager which puts them near the code but not in the // same buffer. Type *GlobalType = GV->getType()->getElementType(); - size_t S = getTargetData()->getTypeAllocSize(GlobalType); - size_t A = getTargetData()->getPreferredAlignment(GV); + size_t S = getDataLayout()->getTypeAllocSize(GlobalType); + size_t A = getDataLayout()->getPreferredAlignment(GV); if (GV->isThreadLocal()) { MutexGuard locked(lock); Ptr = TJI.allocateThreadLocalMemory(S); diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp index 42a136e..19c1979 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp @@ -24,7 +24,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" @@ -42,7 +42,7 @@ unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F, assert(MMI && "MachineModuleInfo not registered!"); const TargetMachine& TM = F.getTarget(); - TD = TM.getTargetData(); + TD = TM.getDataLayout(); stackGrowthDirection = TM.getFrameLowering()->getStackGrowthDirection(); RI = TM.getRegisterInfo(); MAI = TM.getMCAsmInfo(); diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h index 8dc99ab..9cdbeac 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h @@ -23,12 +23,12 @@ class MachineFunction; class MachineModuleInfo; class MachineMove; class MCAsmInfo; -class TargetData; +class DataLayout; class TargetMachine; class TargetRegisterInfo; class JITDwarfEmitter { - const TargetData* TD; + const DataLayout* TD; JITCodeEmitter* JCE; const TargetRegisterInfo* RI; const MCAsmInfo *MAI; diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp index ff3a9dc..ecafda7 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -30,7 +30,7 @@ #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetJITInfo.h" #include "llvm/Target/TargetMachine.h" @@ -384,11 +384,6 @@ namespace { delete MemMgr; } - /// classof - Methods for support type inquiry through isa, cast, and - /// dyn_cast: - /// - static inline bool classof(const MachineCodeEmitter*) { return true; } - JITResolver &getJITResolver() { return Resolver; } virtual void startFunction(MachineFunction &F); @@ -763,7 +758,7 @@ void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) { } static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP, - const TargetData *TD) { + const DataLayout *TD) { const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); if (Constants.empty()) return 0; @@ -780,7 +775,7 @@ static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP, void JITEmitter::startFunction(MachineFunction &F) { DEBUG(dbgs() << "JIT: Starting CodeGen of Function " - << F.getFunction()->getName() << "\n"); + << F.getName() << "\n"); uintptr_t ActualSize = 0; // Set the memory writable, if it's not already @@ -929,7 +924,7 @@ bool JITEmitter::finishFunction(MachineFunction &F) { PrevDL = DebugLoc(); DEBUG(dbgs() << "JIT: Finished CodeGen of [" << (void*)FnStart - << "] Function: " << F.getFunction()->getName() + << "] Function: " << F.getName() << ": " << (FnEnd-FnStart) << " bytes of text, " << Relocations.size() << " relocations\n"); @@ -1058,7 +1053,7 @@ void JITEmitter::emitConstantPool(MachineConstantPool *MCP) { const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); if (Constants.empty()) return; - unsigned Size = GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); + unsigned Size = GetConstantPoolSizeInBytes(MCP, TheJIT->getDataLayout()); unsigned Align = MCP->getConstantPoolAlignment(); ConstantPoolBase = allocateSpace(Size, Align); ConstantPool = MCP; @@ -1087,7 +1082,7 @@ void JITEmitter::emitConstantPool(MachineConstantPool *MCP) { dbgs().write_hex(CAddr) << "]\n"); Type *Ty = CPE.Val.ConstVal->getType(); - Offset += TheJIT->getTargetData()->getTypeAllocSize(Ty); + Offset += TheJIT->getDataLayout()->getTypeAllocSize(Ty); } } @@ -1104,14 +1099,14 @@ void JITEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) { for (unsigned i = 0, e = JT.size(); i != e; ++i) NumEntries += JT[i].MBBs.size(); - unsigned EntrySize = MJTI->getEntrySize(*TheJIT->getTargetData()); + unsigned EntrySize = MJTI->getEntrySize(*TheJIT->getDataLayout()); // Just allocate space for all the jump tables now. We will fix up the actual // MBB entries in the tables after we emit the code for each block, since then // we will know the final locations of the MBBs in memory. JumpTable = MJTI; JumpTableBase = allocateSpace(NumEntries * EntrySize, - MJTI->getEntryAlignment(*TheJIT->getTargetData())); + MJTI->getEntryAlignment(*TheJIT->getDataLayout())); } void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { @@ -1128,7 +1123,7 @@ void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { case MachineJumpTableInfo::EK_BlockAddress: { // EK_BlockAddress - Each entry is a plain address of block, e.g.: // .word LBB123 - assert(MJTI->getEntrySize(*TheJIT->getTargetData()) == sizeof(void*) && + assert(MJTI->getEntrySize(*TheJIT->getDataLayout()) == sizeof(void*) && "Cross JIT'ing?"); // For each jump table, map each target in the jump table to the address of @@ -1148,7 +1143,7 @@ void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { case MachineJumpTableInfo::EK_Custom32: case MachineJumpTableInfo::EK_GPRel32BlockAddress: case MachineJumpTableInfo::EK_LabelDifference32: { - assert(MJTI->getEntrySize(*TheJIT->getTargetData()) == 4&&"Cross JIT'ing?"); + assert(MJTI->getEntrySize(*TheJIT->getDataLayout()) == 4&&"Cross JIT'ing?"); // For each jump table, place the offset from the beginning of the table // to the target address. int *SlotPtr = (int*)JumpTableBase; @@ -1224,7 +1219,7 @@ uintptr_t JITEmitter::getJumpTableEntryAddress(unsigned Index) const { const std::vector<MachineJumpTableEntry> &JT = JumpTable->getJumpTables(); assert(Index < JT.size() && "Invalid jump table index!"); - unsigned EntrySize = JumpTable->getEntrySize(*TheJIT->getTargetData()); + unsigned EntrySize = JumpTable->getEntrySize(*TheJIT->getDataLayout()); unsigned Offset = 0; for (unsigned i = 0; i < Index; ++i) @@ -1265,15 +1260,13 @@ void *JIT::getPointerToFunctionOrStub(Function *F) { return Addr; // Get a stub if the target supports it. - assert(isa<JITEmitter>(JCE) && "Unexpected MCE?"); - JITEmitter *JE = cast<JITEmitter>(getCodeEmitter()); + JITEmitter *JE = static_cast<JITEmitter*>(getCodeEmitter()); return JE->getJITResolver().getLazyFunctionStub(F); } void JIT::updateFunctionStub(Function *F) { // Get the empty stub we generated earlier. - assert(isa<JITEmitter>(JCE) && "Unexpected MCE?"); - JITEmitter *JE = cast<JITEmitter>(getCodeEmitter()); + JITEmitter *JE = static_cast<JITEmitter*>(getCodeEmitter()); void *Stub = JE->getJITResolver().getLazyFunctionStub(F); void *Addr = getPointerToGlobalIfAvailable(F); assert(Addr != Stub && "Function must have non-stub address to be updated."); @@ -1294,6 +1287,5 @@ void JIT::freeMachineCodeForFunction(Function *F) { updateGlobalMapping(F, 0); // Free the actual memory for the function body and related stuff. - assert(isa<JITEmitter>(JCE) && "Unexpected MCE?"); - cast<JITEmitter>(JCE)->deallocateMemForFunction(F); + static_cast<JITEmitter*>(JCE)->deallocateMemForFunction(F); } diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 739ffd7d8..752c5b7 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -8,18 +8,20 @@ //===----------------------------------------------------------------------===// #include "MCJIT.h" -#include "MCJITMemoryManager.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/ObjectBuffer.h" +#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MutexGuard.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" using namespace llvm; @@ -44,24 +46,20 @@ ExecutionEngine *MCJIT::createJIT(Module *M, // FIXME: Don't do this here. sys::DynamicLibrary::LoadLibraryPermanently(0, NULL); - // If the target supports JIT code generation, create the JIT. - if (TargetJITInfo *TJ = TM->getJITInfo()) - return new MCJIT(M, TM, *TJ, new MCJITMemoryManager(JMM), GVsWithCode); - - if (ErrorStr) - *ErrorStr = "target does not support JIT code generation"; - return 0; + return new MCJIT(M, TM, JMM, GVsWithCode); } -MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji, - RTDyldMemoryManager *MM, bool AllocateGVsWithCode) - : ExecutionEngine(m), TM(tm), Ctx(0), MemMgr(MM), Dyld(MM), - isCompiled(false), M(m), OS(Buffer) { +MCJIT::MCJIT(Module *m, TargetMachine *tm, RTDyldMemoryManager *MM, + bool AllocateGVsWithCode) + : ExecutionEngine(m), TM(tm), Ctx(0), MemMgr(MM), Dyld(MM), + isCompiled(false), M(m) { - setTargetData(TM->getTargetData()); + setDataLayout(TM->getDataLayout()); } MCJIT::~MCJIT() { + if (LoadedObject) + NotifyFreeingObject(*LoadedObject.get()); delete MemMgr; delete TM; } @@ -69,7 +67,7 @@ MCJIT::~MCJIT() { void MCJIT::emitObject(Module *m) { /// Currently, MCJIT only supports a single module and the module passed to /// this function call is expected to be the contained module. The module - /// is passed as a parameter here to prepare for multiple module support in + /// is passed as a parameter here to prepare for multiple module support in /// the future. assert(M == m); @@ -84,41 +82,65 @@ void MCJIT::emitObject(Module *m) { PassManager PM; - PM.add(new TargetData(*TM->getTargetData())); + PM.add(new DataLayout(*TM->getDataLayout())); + + // The RuntimeDyld will take ownership of this shortly + OwningPtr<ObjectBufferStream> Buffer(new ObjectBufferStream()); // Turn the machine code intermediate representation into bytes in memory // that may be executed. - if (TM->addPassesToEmitMC(PM, Ctx, OS, false)) { + if (TM->addPassesToEmitMC(PM, Ctx, Buffer->getOStream(), false)) { report_fatal_error("Target does not support MC emission!"); } // Initialize passes. - // FIXME: When we support multiple modules, we'll want to move the code - // gen and finalization out of the constructor here and do it more - // on-demand as part of getPointerToFunction(). PM.run(*m); - // Flush the output buffer so the SmallVector gets its data. - OS.flush(); + // Flush the output buffer to get the generated code into memory + Buffer->flush(); // Load the object into the dynamic linker. - MemoryBuffer* MB = MemoryBuffer::getMemBuffer(StringRef(Buffer.data(), - Buffer.size()), - "", false); - if (Dyld.loadObject(MB)) + // handing off ownership of the buffer + LoadedObject.reset(Dyld.loadObject(Buffer.take())); + if (!LoadedObject) report_fatal_error(Dyld.getErrorString()); // Resolve any relocations. Dyld.resolveRelocations(); + // FIXME: Make this optional, maybe even move it to a JIT event listener + LoadedObject->registerWithDebugger(); + + NotifyObjectEmitted(*LoadedObject); + // FIXME: Add support for per-module compilation state isCompiled = true; } +// FIXME: Add a parameter to identify which object is being finalized when +// MCJIT supports multiple modules. +void MCJIT::finalizeObject() { + // If the module hasn't been compiled, just do that. + if (!isCompiled) { + // If the call to Dyld.resolveRelocations() is removed from emitObject() + // we'll need to do that here. + emitObject(M); + return; + } + + // Resolve any relocations. + Dyld.resolveRelocations(); +} + void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) { report_fatal_error("not yet implemented"); } void *MCJIT::getPointerToFunction(Function *F) { + // FIXME: This should really return a uint64_t since it's a pointer in the + // target address space, not our local address space. That's part of the + // ExecutionEngine interface, though. Fix that when the old JIT finally + // dies. + // FIXME: Add support for per-module compilation state if (!isCompiled) emitObject(M); @@ -132,10 +154,13 @@ void *MCJIT::getPointerToFunction(Function *F) { // FIXME: Should the Dyld be retaining module information? Probably not. // FIXME: Should we be using the mangler for this? Probably. + // + // This is the accessor for the target address, so make sure to check the + // load address of the symbol, not the local address. StringRef BaseName = F->getName(); if (BaseName[0] == '\1') - return (void*)Dyld.getSymbolAddress(BaseName.substr(1)); - return (void*)Dyld.getSymbolAddress((TM->getMCAsmInfo()->getGlobalPrefix() + return (void*)Dyld.getSymbolLoadAddress(BaseName.substr(1)); + return (void*)Dyld.getSymbolLoadAddress((TM->getMCAsmInfo()->getGlobalPrefix() + BaseName).str()); } @@ -270,3 +295,33 @@ void *MCJIT::getPointerToNamedFunction(const std::string &Name, } return 0; } + +void MCJIT::RegisterJITEventListener(JITEventListener *L) { + if (L == NULL) + return; + MutexGuard locked(lock); + EventListeners.push_back(L); +} +void MCJIT::UnregisterJITEventListener(JITEventListener *L) { + if (L == NULL) + return; + MutexGuard locked(lock); + SmallVector<JITEventListener*, 2>::reverse_iterator I= + std::find(EventListeners.rbegin(), EventListeners.rend(), L); + if (I != EventListeners.rend()) { + std::swap(*I, EventListeners.back()); + EventListeners.pop_back(); + } +} +void MCJIT::NotifyObjectEmitted(const ObjectImage& Obj) { + MutexGuard locked(lock); + for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { + EventListeners[I]->NotifyObjectEmitted(Obj); + } +} +void MCJIT::NotifyFreeingObject(const ObjectImage& Obj) { + MutexGuard locked(lock); + for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { + EventListeners[I]->NotifyFreeingObject(Obj); + } +} diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h index 1d272e9..571080d 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -11,33 +11,32 @@ #define LLVM_LIB_EXECUTIONENGINE_MCJIT_H #include "llvm/PassManager.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/raw_ostream.h" namespace llvm { +class ObjectImage; + // FIXME: This makes all kinds of horrible assumptions for the time being, // like only having one module, not needing to worry about multi-threading, // blah blah. Purely in get-it-up-and-limping mode for now. class MCJIT : public ExecutionEngine { - MCJIT(Module *M, TargetMachine *tm, TargetJITInfo &tji, - RTDyldMemoryManager *MemMgr, bool AllocateGVsWithCode); + MCJIT(Module *M, TargetMachine *tm, RTDyldMemoryManager *MemMgr, + bool AllocateGVsWithCode); TargetMachine *TM; MCContext *Ctx; RTDyldMemoryManager *MemMgr; RuntimeDyld Dyld; + SmallVector<JITEventListener*, 2> EventListeners; // FIXME: Add support for multiple modules bool isCompiled; Module *M; - - // FIXME: Move these to a single container which manages JITed objects - SmallVector<char, 4096> Buffer; // Working buffer into which we JIT. - raw_svector_ostream OS; + OwningPtr<ObjectImage> LoadedObject; public: ~MCJIT(); @@ -45,6 +44,8 @@ public: /// @name ExecutionEngine interface implementation /// @{ + virtual void finalizeObject(); + virtual void *getPointerToBasicBlock(BasicBlock *BB); virtual void *getPointerToFunction(Function *F); @@ -71,10 +72,14 @@ public: /// Map the address of a JIT section as returned from the memory manager /// to the address in the target process as the running code will see it. /// This is the address which will be used for relocation resolution. - virtual void mapSectionAddress(void *LocalAddress, uint64_t TargetAddress) { + virtual void mapSectionAddress(const void *LocalAddress, + uint64_t TargetAddress) { Dyld.mapSectionAddress(LocalAddress, TargetAddress); } + virtual void RegisterJITEventListener(JITEventListener *L); + virtual void UnregisterJITEventListener(JITEventListener *L); + /// @} /// @name (Private) Registration Interfaces /// @{ @@ -98,6 +103,9 @@ protected: /// is passed as a parameter here to prepare for multiple module support in /// the future. void emitObject(Module *M); + + void NotifyObjectEmitted(const ObjectImage& Obj); + void NotifyFreeingObject(const ObjectImage& Obj); }; } // End llvm namespace diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.cpp b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.cpp deleted file mode 100644 index 457fe5e..0000000 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//==-- MCJITMemoryManager.cpp - Definition for the Memory Manager -*-C++ -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "MCJITMemoryManager.h" - -using namespace llvm; - -void MCJITMemoryManager::anchor() { } diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h deleted file mode 100644 index 441aaeb..0000000 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h +++ /dev/null @@ -1,50 +0,0 @@ -//===-- MCJITMemoryManager.h - Definition for the Memory Manager ---C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_EXECUTIONENGINE_MCJITMEMORYMANAGER_H -#define LLVM_LIB_EXECUTIONENGINE_MCJITMEMORYMANAGER_H - -#include "llvm/Module.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/ExecutionEngine/RuntimeDyld.h" -#include <assert.h> - -namespace llvm { - -// The MCJIT memory manager is a layer between the standard JITMemoryManager -// and the RuntimeDyld interface that maps objects, by name, onto their -// matching LLVM IR counterparts in the module(s) being compiled. -class MCJITMemoryManager : public RTDyldMemoryManager { - virtual void anchor(); - OwningPtr<JITMemoryManager> JMM; - -public: - MCJITMemoryManager(JITMemoryManager *jmm) : - JMM(jmm?jmm:JITMemoryManager::CreateDefaultMemManager()) {} - - uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) { - return JMM->allocateDataSection(Size, Alignment, SectionID); - } - - uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) { - return JMM->allocateCodeSection(Size, Alignment, SectionID); - } - - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) { - return JMM->getPointerToNamedFunction(Name, AbortOnFailure); - } - -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp index 8b50101..50cd072 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp @@ -78,12 +78,12 @@ public: /// Creates an entry in the JIT registry for the buffer @p Object, /// which must contain an object file in executable memory with any /// debug information for the debugger. - void registerObject(const MemoryBuffer &Object); + void registerObject(const ObjectBuffer &Object); /// Removes the internal registration of @p Object, and /// frees associated resources. /// Returns true if @p Object was found in ObjectBufferMap. - bool deregisterObject(const MemoryBuffer &Object); + bool deregisterObject(const ObjectBuffer &Object); private: /// Deregister the debug info for the given object file from the debugger @@ -124,7 +124,7 @@ GDBJITRegistrar::~GDBJITRegistrar() { ObjectBufferMap.clear(); } -void GDBJITRegistrar::registerObject(const MemoryBuffer &Object) { +void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) { const char *Buffer = Object.getBufferStart(); size_t Size = Object.getBufferSize(); @@ -147,7 +147,7 @@ void GDBJITRegistrar::registerObject(const MemoryBuffer &Object) { } } -bool GDBJITRegistrar::deregisterObject(const MemoryBuffer& Object) { +bool GDBJITRegistrar::deregisterObject(const ObjectBuffer& Object) { const char *Buffer = Object.getBufferStart(); RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer); diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h index f964bc6..69e9dbe 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h @@ -10,7 +10,7 @@ #ifndef LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H #define LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H -#include "llvm/Support/MemoryBuffer.h" +#include "llvm/ExecutionEngine/ObjectBuffer.h" namespace llvm { @@ -27,12 +27,12 @@ public: /// Creates an entry in the JIT registry for the buffer @p Object, /// which must contain an object file in executable memory with any /// debug information for the debugger. - virtual void registerObject(const MemoryBuffer &Object) = 0; + virtual void registerObject(const ObjectBuffer &Object) = 0; /// Removes the internal registration of @p Object, and /// frees associated resources. /// Returns true if @p Object was previously registered. - virtual bool deregisterObject(const MemoryBuffer &Object) = 0; + virtual bool deregisterObject(const ObjectBuffer &Object) = 0; /// Returns a reference to a GDB JIT registrar singleton static JITRegistrar& getGDBRegistrar(); diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImage.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h index c3e3572..17f3a21 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImage.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h @@ -1,59 +1,76 @@ -//===---- ObjectImage.h - Format independent executuable object image -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a file format independent ObjectImage class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H -#define LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H - -#include "llvm/Object/ObjectFile.h" - -namespace llvm { - -class ObjectImage { - ObjectImage(); // = delete - ObjectImage(const ObjectImage &other); // = delete -protected: - object::ObjectFile *ObjFile; - -public: - ObjectImage(object::ObjectFile *Obj) { ObjFile = Obj; } - virtual ~ObjectImage() {} - - virtual object::symbol_iterator begin_symbols() const - { return ObjFile->begin_symbols(); } - virtual object::symbol_iterator end_symbols() const - { return ObjFile->end_symbols(); } - - virtual object::section_iterator begin_sections() const - { return ObjFile->begin_sections(); } - virtual object::section_iterator end_sections() const - { return ObjFile->end_sections(); } - - virtual /* Triple::ArchType */ unsigned getArch() const - { return ObjFile->getArch(); } - - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - virtual void updateSectionAddress(const object::SectionRef &Sec, - uint64_t Addr) {} - virtual void updateSymbolAddress(const object::SymbolRef &Sym, uint64_t Addr) - {} - - // Subclasses can override these methods to provide JIT debugging support - virtual void registerWithDebugger() {} - virtual void deregisterWithDebugger() {} -}; - -} // end namespace llvm - -#endif // LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H - +//===-- ObjectImageCommon.h - Format independent executuable object image -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares a file format independent ObjectImage class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_RUNTIMEDYLD_OBJECTIMAGECOMMON_H
+#define LLVM_RUNTIMEDYLD_OBJECTIMAGECOMMON_H
+
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/ExecutionEngine/ObjectImage.h"
+#include "llvm/ExecutionEngine/ObjectBuffer.h"
+
+namespace llvm {
+
+class ObjectImageCommon : public ObjectImage {
+ ObjectImageCommon(); // = delete
+ ObjectImageCommon(const ObjectImageCommon &other); // = delete
+
+protected:
+ object::ObjectFile *ObjFile;
+
+ // This form of the constructor allows subclasses to use
+ // format-specific subclasses of ObjectFile directly
+ ObjectImageCommon(ObjectBuffer *Input, object::ObjectFile *Obj)
+ : ObjectImage(Input), // saves Input as Buffer and takes ownership
+ ObjFile(Obj)
+ {
+ }
+
+public:
+ ObjectImageCommon(ObjectBuffer* Input)
+ : ObjectImage(Input) // saves Input as Buffer and takes ownership
+ {
+ ObjFile = object::ObjectFile::createObjectFile(Buffer->getMemBuffer());
+ }
+ virtual ~ObjectImageCommon() { delete ObjFile; }
+
+ virtual object::symbol_iterator begin_symbols() const
+ { return ObjFile->begin_symbols(); }
+ virtual object::symbol_iterator end_symbols() const
+ { return ObjFile->end_symbols(); }
+
+ virtual object::section_iterator begin_sections() const
+ { return ObjFile->begin_sections(); }
+ virtual object::section_iterator end_sections() const
+ { return ObjFile->end_sections(); }
+
+ virtual /* Triple::ArchType */ unsigned getArch() const
+ { return ObjFile->getArch(); }
+
+ virtual StringRef getData() const { return ObjFile->getData(); }
+
+ // Subclasses can override these methods to update the image with loaded
+ // addresses for sections and common symbols
+ virtual void updateSectionAddress(const object::SectionRef &Sec,
+ uint64_t Addr) {}
+ virtual void updateSymbolAddress(const object::SymbolRef &Sym, uint64_t Addr)
+ {}
+
+ // Subclasses can override these methods to provide JIT debugging support
+ virtual void registerWithDebugger() {}
+ virtual void deregisterWithDebugger() {}
+};
+
+} // end namespace llvm
+
+#endif // LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H
+
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index b464040..f6dccb1 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -12,10 +12,12 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dyld" +#include "ObjectImageCommon.h" #include "RuntimeDyldImpl.h" #include "RuntimeDyldELF.h" #include "RuntimeDyldMachO.h" #include "llvm/Support/Path.h" +#include "llvm/Support/MathExtras.h" using namespace llvm; using namespace llvm::object; @@ -26,16 +28,6 @@ RuntimeDyldImpl::~RuntimeDyldImpl() {} namespace llvm { -namespace { - // Helper for extensive error checking in debug builds. - error_code Check(error_code Err) { - if (Err) { - report_fatal_error(Err.message()); - } - return Err; - } -} // end anonymous namespace - // Resolve the relocations for all symbols we currently know about. void RuntimeDyldImpl::resolveRelocations() { // First, resolve relocations associated with external symbols. @@ -44,11 +36,15 @@ void RuntimeDyldImpl::resolveRelocations() { // Just iterate over the sections we have and resolve all the relocations // in them. Gross overkill, but it gets the job done. for (int i = 0, e = Sections.size(); i != e; ++i) { - reassignSectionAddress(i, Sections[i].LoadAddress); + uint64_t Addr = Sections[i].LoadAddress; + DEBUG(dbgs() << "Resolving relocations Section #" << i + << "\t" << format("%p", (uint8_t *)Addr) + << "\n"); + resolveRelocationList(Relocations[i], Addr); } } -void RuntimeDyldImpl::mapSectionAddress(void *LocalAddress, +void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) { for (unsigned i = 0, e = Sections.size(); i != e; ++i) { if (Sections[i].Address == LocalAddress) { @@ -61,14 +57,11 @@ void RuntimeDyldImpl::mapSectionAddress(void *LocalAddress, // Subclasses can implement this method to create specialized image instances. // The caller owns the pointer that is returned. -ObjectImage *RuntimeDyldImpl::createObjectImage(const MemoryBuffer *InputBuffer) { - ObjectFile *ObjFile = ObjectFile::createObjectFile(const_cast<MemoryBuffer*> - (InputBuffer)); - ObjectImage *Obj = new ObjectImage(ObjFile); - return Obj; +ObjectImage *RuntimeDyldImpl::createObjectImage(ObjectBuffer *InputBuffer) { + return new ObjectImageCommon(InputBuffer); } -bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { +ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer)); if (!obj) report_fatal_error("Unable to create object image from memory buffer!"); @@ -80,9 +73,9 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { // Used sections from the object file ObjSectionToIDMap LocalSections; - // Common symbols requiring allocation, and the total size required to - // allocate all common symbols. + // Common symbols requiring allocation, with their sizes and alignments CommonSymbolMap CommonSymbols; + // Maximum required total memory to allocate all common symbols uint64_t CommonSize = 0; error_code err; @@ -102,13 +95,15 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { bool isCommon = flags & SymbolRef::SF_Common; if (isCommon) { // Add the common symbols to a list. We'll allocate them all below. + uint64_t Align = getCommonSymbolAlignment(*i); uint64_t Size = 0; Check(i->getSize(Size)); - CommonSize += Size; - CommonSymbols[*i] = Size; + CommonSize += Size + Align; + CommonSymbols[*i] = CommonSymbolInfo(Size, Align); } else { if (SymType == object::SymbolRef::ST_Function || - SymType == object::SymbolRef::ST_Data) { + SymType == object::SymbolRef::ST_Data || + SymType == object::SymbolRef::ST_Unknown) { uint64_t FileOffset; StringRef SectionData; section_iterator si = obj->end_sections(); @@ -177,9 +172,7 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { } } - handleObjectLoaded(obj.take()); - - return false; + return obj.take(); } void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, @@ -193,7 +186,7 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; - Sections.push_back(SectionEntry(Addr, TotalSize, TotalSize, 0)); + Sections.push_back(SectionEntry(StringRef(), Addr, TotalSize, TotalSize, 0)); memset(Addr, 0, TotalSize); DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID @@ -204,11 +197,20 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, // Assign the address of each symbol for (CommonSymbolMap::const_iterator it = CommonSymbols.begin(), itEnd = CommonSymbols.end(); it != itEnd; it++) { + uint64_t Size = it->second.first; + uint64_t Align = it->second.second; StringRef Name; it->first.getName(Name); + if (Align) { + // This symbol has an alignment requirement. + uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align); + Addr += AlignOffset; + Offset += AlignOffset; + DEBUG(dbgs() << "Allocating common symbol " << Name << " address " << + format("%p\n", Addr)); + } Obj.updateSymbolAddress(it->first, (uint64_t)Addr); SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset); - uint64_t Size = it->second; Offset += Size; Addr += Size; } @@ -236,10 +238,12 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, bool IsVirtual; bool IsZeroInit; uint64_t DataSize; + StringRef Name; Check(Section.isRequiredForExecution(IsRequired)); Check(Section.isVirtual(IsVirtual)); Check(Section.isZeroInit(IsZeroInit)); Check(Section.getSize(DataSize)); + Check(Section.getName(Name)); unsigned Allocate; unsigned SectionID = Sections.size(); @@ -267,6 +271,7 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, memcpy(Addr, pData, DataSize); DEBUG(dbgs() << "emitSection SectionID: " << SectionID + << " Name: " << Name << " obj addr: " << format("%p", pData) << " new addr: " << format("%p", Addr) << " DataSize: " << DataSize @@ -282,6 +287,7 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, Allocate = 0; Addr = 0; DEBUG(dbgs() << "emitSection SectionID: " << SectionID + << " Name: " << Name << " obj addr: " << format("%p", data.data()) << " new addr: 0" << " DataSize: " << DataSize @@ -290,7 +296,8 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, << "\n"); } - Sections.push_back(SectionEntry(Addr, Allocate, DataSize,(uintptr_t)pData)); + Sections.push_back(SectionEntry(Name, Addr, Allocate, DataSize, + (uintptr_t)pData)); return SectionID; } @@ -333,15 +340,49 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE, } uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) { - // TODO: There is only ARM far stub now. We should add the Thumb stub, - // and stubs for branches Thumb - ARM and ARM - Thumb. if (Arch == Triple::arm) { + // TODO: There is only ARM far stub now. We should add the Thumb stub, + // and stubs for branches Thumb - ARM and ARM - Thumb. uint32_t *StubAddr = (uint32_t*)Addr; *StubAddr = 0xe51ff004; // ldr pc,<label> return (uint8_t*)++StubAddr; - } - else + } else if (Arch == Triple::mipsel) { + uint32_t *StubAddr = (uint32_t*)Addr; + // 0: 3c190000 lui t9,%hi(addr). + // 4: 27390000 addiu t9,t9,%lo(addr). + // 8: 03200008 jr t9. + // c: 00000000 nop. + const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000; + const unsigned JrT9Instr = 0x03200008, NopInstr = 0x0; + + *StubAddr = LuiT9Instr; + StubAddr++; + *StubAddr = AdduiT9Instr; + StubAddr++; + *StubAddr = JrT9Instr; + StubAddr++; + *StubAddr = NopInstr; return Addr; + } else if (Arch == Triple::ppc64) { + // PowerPC64 stub: the address points to a function descriptor + // instead of the function itself. Load the function address + // on r11 and sets it to control register. Also loads the function + // TOC in r2 and environment pointer to r11. + writeInt32BE(Addr, 0x3D800000); // lis r12, highest(addr) + writeInt32BE(Addr+4, 0x618C0000); // ori r12, higher(addr) + writeInt32BE(Addr+8, 0x798C07C6); // sldi r12, r12, 32 + writeInt32BE(Addr+12, 0x658C0000); // oris r12, r12, h(addr) + writeInt32BE(Addr+16, 0x618C0000); // ori r12, r12, l(addr) + writeInt32BE(Addr+20, 0xF8410028); // std r2, 40(r1) + writeInt32BE(Addr+24, 0xE96C0000); // ld r11, 0(r12) + writeInt32BE(Addr+28, 0xE84C0008); // ld r2, 0(r12) + writeInt32BE(Addr+32, 0x7D6903A6); // mtctr r11 + writeInt32BE(Addr+36, 0xE96C0010); // ld r11, 16(r2) + writeInt32BE(Addr+40, 0x4E800420); // bctr + + return Addr; + } + return Addr; } // Assign an address to a symbol name and resolve all the relocations @@ -350,32 +391,30 @@ void RuntimeDyldImpl::reassignSectionAddress(unsigned SectionID, uint64_t Addr) { // The address to use for relocation resolution is not // the address of the local section buffer. We must be doing - // a remote execution environment of some sort. Re-apply any - // relocations referencing this section with the given address. + // a remote execution environment of some sort. Relocations can't + // be applied until all the sections have been moved. The client must + // trigger this with a call to MCJIT::finalize() or + // RuntimeDyld::resolveRelocations(). // // Addr is a uint64_t because we can't assume the pointer width // of the target is the same as that of the host. Just use a generic // "big enough" type. Sections[SectionID].LoadAddress = Addr; - DEBUG(dbgs() << "Resolving relocations Section #" << SectionID - << "\t" << format("%p", (uint8_t *)Addr) - << "\n"); - resolveRelocationList(Relocations[SectionID], Addr); } void RuntimeDyldImpl::resolveRelocationEntry(const RelocationEntry &RE, uint64_t Value) { - // Ignore relocations for sections that were not loaded - if (Sections[RE.SectionID].Address != 0) { - uint8_t *Target = Sections[RE.SectionID].Address + RE.Offset; - DEBUG(dbgs() << "\tSectionID: " << RE.SectionID - << " + " << RE.Offset << " (" << format("%p", Target) << ")" - << " RelType: " << RE.RelType - << " Addend: " << RE.Addend - << "\n"); + // Ignore relocations for sections that were not loaded + if (Sections[RE.SectionID].Address != 0) { + DEBUG(dbgs() << "\tSectionID: " << RE.SectionID + << " + " << RE.Offset << " (" + << format("%p", Sections[RE.SectionID].Address + RE.Offset) << ")" + << " RelType: " << RE.RelType + << " Addend: " << RE.Addend + << "\n"); - resolveRelocation(Target, Sections[RE.SectionID].LoadAddress + RE.Offset, - Value, RE.RelType, RE.Addend); + resolveRelocation(Sections[RE.SectionID], RE.Offset, + Value, RE.RelType, RE.Addend); } } @@ -420,7 +459,7 @@ RuntimeDyld::~RuntimeDyld() { delete Dyld; } -bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) { +ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) { if (!Dyld) { sys::LLVMFileType type = sys::IdentifyFileType( InputBuffer->getBufferStart(), @@ -462,6 +501,10 @@ void *RuntimeDyld::getSymbolAddress(StringRef Name) { return Dyld->getSymbolAddress(Name); } +uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) { + return Dyld->getSymbolLoadAddress(Name); +} + void RuntimeDyld::resolveRelocations() { Dyld->resolveRelocations(); } @@ -471,7 +514,7 @@ void RuntimeDyld::reassignSectionAddress(unsigned SectionID, Dyld->reassignSectionAddress(SectionID, Addr); } -void RuntimeDyld::mapSectionAddress(void *LocalAddress, +void RuntimeDyld::mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) { Dyld->mapSectionAddress(LocalAddress, TargetAddress); } diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 75bb586..1ebcaf7 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -12,21 +12,32 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dyld" +#include "RuntimeDyldELF.h" +#include "JITRegistrar.h" +#include "ObjectImageCommon.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/IntervalMap.h" -#include "RuntimeDyldELF.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/Support/ELF.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/ELF.h" -#include "JITRegistrar.h" using namespace llvm; using namespace llvm::object; namespace { +static inline +error_code check(error_code Err) { + if (Err) { + report_fatal_error(Err.message()); + } + return Err; +} + template<support::endianness target_endianness, bool is64Bits> class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> { LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) @@ -36,25 +47,17 @@ class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> { typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; - typedef typename ELFObjectFile<target_endianness, is64Bits>:: - Elf_Ehdr Elf_Ehdr; + typedef Elf_Ehdr_Impl<target_endianness, is64Bits> Elf_Ehdr; typedef typename ELFDataTypeTypedefHelper< target_endianness, is64Bits>::value_type addr_type; -protected: - // This duplicates the 'Data' member in the 'Binary' base class - // but it is necessary to workaround a bug in gcc 4.2 - MemoryBuffer *InputData; - public: - DyldELFObject(MemoryBuffer *Object, error_code &ec); + DyldELFObject(MemoryBuffer *Wrapper, error_code &ec); void updateSectionAddress(const SectionRef &Sec, uint64_t Addr); void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr); - const MemoryBuffer& getBuffer() const { return *InputData; } - // Methods for type inquiry through isa, cast and dyn_cast static inline bool classof(const Binary *v) { return (isa<ELFObjectFile<target_endianness, is64Bits> >(v) @@ -64,20 +67,18 @@ public: const ELFObjectFile<target_endianness, is64Bits> *v) { return v->isDyldType(); } - static inline bool classof(const DyldELFObject *v) { - return true; - } }; template<support::endianness target_endianness, bool is64Bits> -class ELFObjectImage : public ObjectImage { +class ELFObjectImage : public ObjectImageCommon { protected: DyldELFObject<target_endianness, is64Bits> *DyldObj; bool Registered; public: - ELFObjectImage(DyldELFObject<target_endianness, is64Bits> *Obj) - : ObjectImage(Obj), + ELFObjectImage(ObjectBuffer *Input, + DyldELFObject<target_endianness, is64Bits> *Obj) + : ObjectImageCommon(Input, Obj), DyldObj(Obj), Registered(false) {} @@ -100,20 +101,22 @@ class ELFObjectImage : public ObjectImage { virtual void registerWithDebugger() { - JITRegistrar::getGDBRegistrar().registerObject(DyldObj->getBuffer()); + JITRegistrar::getGDBRegistrar().registerObject(*Buffer); Registered = true; } virtual void deregisterWithDebugger() { - JITRegistrar::getGDBRegistrar().deregisterObject(DyldObj->getBuffer()); + JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer); } }; +// The MemoryBuffer passed into this constructor is just a wrapper around the +// actual memory. Ultimately, the Binary parent class will take ownership of +// this MemoryBuffer object but not the underlying memory. template<support::endianness target_endianness, bool is64Bits> -DyldELFObject<target_endianness, is64Bits>::DyldELFObject(MemoryBuffer *Object, +DyldELFObject<target_endianness, is64Bits>::DyldELFObject(MemoryBuffer *Wrapper, error_code &ec) - : ELFObjectFile<target_endianness, is64Bits>(Object, ec), - InputData(Object) { + : ELFObjectFile<target_endianness, is64Bits>(Wrapper, ec) { this->isDyldELFObject = true; } @@ -149,50 +152,43 @@ void DyldELFObject<target_endianness, is64Bits>::updateSymbolAddress( namespace llvm { -ObjectImage *RuntimeDyldELF::createObjectImage( - const MemoryBuffer *ConstInputBuffer) { - MemoryBuffer *InputBuffer = const_cast<MemoryBuffer*>(ConstInputBuffer); - std::pair<unsigned char, unsigned char> Ident = getElfArchType(InputBuffer); +ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) { + if (Buffer->getBufferSize() < ELF::EI_NIDENT) + llvm_unreachable("Unexpected ELF object size"); + std::pair<unsigned char, unsigned char> Ident = std::make_pair( + (uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS], + (uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]); error_code ec; if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) { DyldELFObject<support::little, false> *Obj = - new DyldELFObject<support::little, false>(InputBuffer, ec); - return new ELFObjectImage<support::little, false>(Obj); + new DyldELFObject<support::little, false>(Buffer->getMemBuffer(), ec); + return new ELFObjectImage<support::little, false>(Buffer, Obj); } else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) { DyldELFObject<support::big, false> *Obj = - new DyldELFObject<support::big, false>(InputBuffer, ec); - return new ELFObjectImage<support::big, false>(Obj); + new DyldELFObject<support::big, false>(Buffer->getMemBuffer(), ec); + return new ELFObjectImage<support::big, false>(Buffer, Obj); } else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) { DyldELFObject<support::big, true> *Obj = - new DyldELFObject<support::big, true>(InputBuffer, ec); - return new ELFObjectImage<support::big, true>(Obj); + new DyldELFObject<support::big, true>(Buffer->getMemBuffer(), ec); + return new ELFObjectImage<support::big, true>(Buffer, Obj); } else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { DyldELFObject<support::little, true> *Obj = - new DyldELFObject<support::little, true>(InputBuffer, ec); - return new ELFObjectImage<support::little, true>(Obj); + new DyldELFObject<support::little, true>(Buffer->getMemBuffer(), ec); + return new ELFObjectImage<support::little, true>(Buffer, Obj); } else llvm_unreachable("Unexpected ELF format"); } -void RuntimeDyldELF::handleObjectLoaded(ObjectImage *Obj) -{ - Obj->registerWithDebugger(); - // Save the loaded object. It will deregister itself when deleted - LoadedObject = Obj; -} - RuntimeDyldELF::~RuntimeDyldELF() { - if (LoadedObject) - delete LoadedObject; } -void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress, - uint64_t FinalAddress, +void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend) { @@ -201,8 +197,10 @@ void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress, llvm_unreachable("Relocation type not implemented yet!"); break; case ELF::R_X86_64_64: { - uint64_t *Target = (uint64_t*)(LocalAddress); + uint64_t *Target = reinterpret_cast<uint64_t*>(Section.Address + Offset); *Target = Value + Addend; + DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) + << " at " << format("%p\n",Target)); break; } case ELF::R_X86_64_32: @@ -212,37 +210,52 @@ void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress, (Type == ELF::R_X86_64_32S && ((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN))); uint32_t TruncatedAddr = (Value & 0xFFFFFFFF); - uint32_t *Target = reinterpret_cast<uint32_t*>(LocalAddress); + uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset); *Target = TruncatedAddr; + DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) + << " at " << format("%p\n",Target)); break; } case ELF::R_X86_64_PC32: { - uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress); + // Get the placeholder value from the generated object since + // a previous relocation attempt may have overwritten the loaded version + uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress + + Offset); + uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset); + uint64_t FinalAddress = Section.LoadAddress + Offset; int64_t RealOffset = *Placeholder + Value + Addend - FinalAddress; assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN); int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); - *Placeholder = TruncOffset; + *Target = TruncOffset; break; } } } -void RuntimeDyldELF::resolveX86Relocation(uint8_t *LocalAddress, - uint32_t FinalAddress, +void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section, + uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend) { switch (Type) { case ELF::R_386_32: { - uint32_t *Target = (uint32_t*)(LocalAddress); - uint32_t Placeholder = *Target; - *Target = Placeholder + Value + Addend; + // Get the placeholder value from the generated object since + // a previous relocation attempt may have overwritten the loaded version + uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress + + Offset); + uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset); + *Target = *Placeholder + Value + Addend; break; } case ELF::R_386_PC32: { - uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress); + // Get the placeholder value from the generated object since + // a previous relocation attempt may have overwritten the loaded version + uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress + + Offset); + uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset); + uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress; - *Placeholder = RealOffset; + *Target = RealOffset; break; } default: @@ -253,16 +266,18 @@ void RuntimeDyldELF::resolveX86Relocation(uint8_t *LocalAddress, } } -void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress, - uint32_t FinalAddress, +void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, + uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend) { // TODO: Add Thumb relocations. - uint32_t* TargetPtr = (uint32_t*)LocalAddress; + uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset); + uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); Value += Addend; - DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: " << LocalAddress + DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: " + << Section.Address + Offset << " FinalAddress: " << format("%p",FinalAddress) << " Value: " << format("%x",Value) << " Type: " << format("%x",Type) @@ -273,14 +288,19 @@ void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress, default: llvm_unreachable("Not implemented relocation type!"); - // Just write 32bit value to relocation address + // Write a 32bit value to relocation address, taking into account the + // implicit addend encoded in the target. case ELF::R_ARM_ABS32 : - *TargetPtr = Value; + *TargetPtr += Value; break; // Write first 16 bit of 32 bit value to the mov instruction. // Last 4 bit should be shifted. case ELF::R_ARM_MOVW_ABS_NC : + // We are not expecting any other addend in the relocation address. + // Using 0x000F0FFF because MOVW has its 16 bit immediate split into 2 + // non-contiguous fields. + assert((*TargetPtr & 0x000F0FFF) == 0); Value = Value & 0xFFFF; *TargetPtr |= Value & 0xFFF; *TargetPtr |= ((Value >> 12) & 0xF) << 16; @@ -289,6 +309,9 @@ void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress, // Write last 16 bit of 32 bit value to the mov instruction. // Last 4 bit should be shifted. case ELF::R_ARM_MOVT_ABS : + // We are not expecting any other addend in the relocation address. + // Use 0x000F0FFF for the same reason as R_ARM_MOVW_ABS_NC. + assert((*TargetPtr & 0x000F0FFF) == 0); Value = (Value >> 16) & 0xFFFF; *TargetPtr |= Value & 0xFFF; *TargetPtr |= ((Value >> 12) & 0xF) << 16; @@ -306,26 +329,250 @@ void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress, } } -void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress, - uint64_t FinalAddress, +void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, + uint64_t Offset, + uint32_t Value, + uint32_t Type, + int32_t Addend) { + uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset); + Value += Addend; + + DEBUG(dbgs() << "resolveMipselocation, LocalAddress: " + << Section.Address + Offset + << " FinalAddress: " + << format("%p",Section.LoadAddress + Offset) + << " Value: " << format("%x",Value) + << " Type: " << format("%x",Type) + << " Addend: " << format("%x",Addend) + << "\n"); + + switch(Type) { + default: + llvm_unreachable("Not implemented relocation type!"); + break; + case ELF::R_MIPS_32: + *TargetPtr = Value + (*TargetPtr); + break; + case ELF::R_MIPS_26: + *TargetPtr = ((*TargetPtr) & 0xfc000000) | (( Value & 0x0fffffff) >> 2); + break; + case ELF::R_MIPS_HI16: + // Get the higher 16-bits. Also add 1 if bit 15 is 1. + Value += ((*TargetPtr) & 0x0000ffff) << 16; + *TargetPtr = ((*TargetPtr) & 0xffff0000) | + (((Value + 0x8000) >> 16) & 0xffff); + break; + case ELF::R_MIPS_LO16: + Value += ((*TargetPtr) & 0x0000ffff); + *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff); + break; + } +} + +// Return the .TOC. section address to R_PPC64_TOC relocations. +uint64_t RuntimeDyldELF::findPPC64TOC() const { + // The TOC consists of sections .got, .toc, .tocbss, .plt in that + // order. The TOC starts where the first of these sections starts. + SectionList::const_iterator it = Sections.begin(); + SectionList::const_iterator ite = Sections.end(); + for (; it != ite; ++it) { + if (it->Name == ".got" || + it->Name == ".toc" || + it->Name == ".tocbss" || + it->Name == ".plt") + break; + } + if (it == ite) { + // This may happen for + // * references to TOC base base (sym@toc, .odp relocation) without + // a .toc directive. + // In this case just use the first section (which is usually + // the .odp) since the code won't reference the .toc base + // directly. + it = Sections.begin(); + } + assert (it != ite); + // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 + // thus permitting a full 64 Kbytes segment. + return it->LoadAddress + 0x8000; +} + +// Returns the sections and offset associated with the ODP entry referenced +// by Symbol. +void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, + ObjSectionToIDMap &LocalSections, + RelocationValueRef &Rel) { + // Get the ELF symbol value (st_value) to compare with Relocation offset in + // .opd entries + + error_code err; + for (section_iterator si = Obj.begin_sections(), + se = Obj.end_sections(); si != se; si.increment(err)) { + StringRef SectionName; + check(si->getName(SectionName)); + if (SectionName != ".opd") + continue; + + for (relocation_iterator i = si->begin_relocations(), + e = si->end_relocations(); i != e;) { + check(err); + + // The R_PPC64_ADDR64 relocation indicates the first field + // of a .opd entry + uint64_t TypeFunc; + check(i->getType(TypeFunc)); + if (TypeFunc != ELF::R_PPC64_ADDR64) { + i.increment(err); + continue; + } + + SymbolRef TargetSymbol; + uint64_t TargetSymbolOffset; + int64_t TargetAdditionalInfo; + check(i->getSymbol(TargetSymbol)); + check(i->getOffset(TargetSymbolOffset)); + check(i->getAdditionalInfo(TargetAdditionalInfo)); + + i = i.increment(err); + if (i == e) + break; + check(err); + + // Just check if following relocation is a R_PPC64_TOC + uint64_t TypeTOC; + check(i->getType(TypeTOC)); + if (TypeTOC != ELF::R_PPC64_TOC) + continue; + + // Finally compares the Symbol value and the target symbol offset + // to check if this .opd entry refers to the symbol the relocation + // points to. + if (Rel.Addend != (intptr_t)TargetSymbolOffset) + continue; + + section_iterator tsi(Obj.end_sections()); + check(TargetSymbol.getSection(tsi)); + Rel.SectionID = findOrEmitSection(Obj, (*tsi), true, LocalSections); + Rel.Addend = (intptr_t)TargetAdditionalInfo; + return; + } + } + llvm_unreachable("Attempting to get address of ODP entry!"); +} + +// Relocation masks following the #lo(value), #hi(value), #higher(value), +// and #highest(value) macros defined in section 4.5.1. Relocation Types +// in PPC-elf64abi document. +// +static inline +uint16_t applyPPClo (uint64_t value) +{ + return value & 0xffff; +} + +static inline +uint16_t applyPPChi (uint64_t value) +{ + return (value >> 16) & 0xffff; +} + +static inline +uint16_t applyPPChigher (uint64_t value) +{ + return (value >> 32) & 0xffff; +} + +static inline +uint16_t applyPPChighest (uint64_t value) +{ + return (value >> 48) & 0xffff; +} + +void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, + uint64_t Offset, + uint64_t Value, + uint32_t Type, + int64_t Addend) { + uint8_t* LocalAddress = Section.Address + Offset; + switch (Type) { + default: + llvm_unreachable("Relocation type not implemented yet!"); + break; + case ELF::R_PPC64_ADDR16_LO : + writeInt16BE(LocalAddress, applyPPClo (Value + Addend)); + break; + case ELF::R_PPC64_ADDR16_HI : + writeInt16BE(LocalAddress, applyPPChi (Value + Addend)); + break; + case ELF::R_PPC64_ADDR16_HIGHER : + writeInt16BE(LocalAddress, applyPPChigher (Value + Addend)); + break; + case ELF::R_PPC64_ADDR16_HIGHEST : + writeInt16BE(LocalAddress, applyPPChighest (Value + Addend)); + break; + case ELF::R_PPC64_ADDR14 : { + assert(((Value + Addend) & 3) == 0); + // Preserve the AA/LK bits in the branch instruction + uint8_t aalk = *(LocalAddress+3); + writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc)); + } break; + case ELF::R_PPC64_REL24 : { + uint64_t FinalAddress = (Section.LoadAddress + Offset); + int32_t delta = static_cast<int32_t>(Value - FinalAddress + Addend); + if (SignExtend32<24>(delta) != delta) + llvm_unreachable("Relocation R_PPC64_REL24 overflow"); + // Generates a 'bl <address>' instruction + writeInt32BE(LocalAddress, 0x48000001 | (delta & 0x03FFFFFC)); + } break; + case ELF::R_PPC64_ADDR64 : + writeInt64BE(LocalAddress, Value + Addend); + break; + case ELF::R_PPC64_TOC : + writeInt64BE(LocalAddress, findPPC64TOC()); + break; + case ELF::R_PPC64_TOC16 : { + uint64_t TOCStart = findPPC64TOC(); + Value = applyPPClo((Value + Addend) - TOCStart); + writeInt16BE(LocalAddress, applyPPClo(Value)); + } break; + case ELF::R_PPC64_TOC16_DS : { + uint64_t TOCStart = findPPC64TOC(); + Value = ((Value + Addend) - TOCStart); + writeInt16BE(LocalAddress, applyPPClo(Value)); + } break; + } +} + + +void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend) { switch (Arch) { case Triple::x86_64: - resolveX86_64Relocation(LocalAddress, FinalAddress, Value, Type, Addend); + resolveX86_64Relocation(Section, Offset, Value, Type, Addend); break; case Triple::x86: - resolveX86Relocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL), + resolveX86Relocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); break; case Triple::arm: // Fall through. case Triple::thumb: - resolveARMRelocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL), + resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); break; + case Triple::mips: // Fall through. + case Triple::mipsel: + resolveMIPSRelocation(Section, Offset, + (uint32_t)(Value & 0xffffffffL), Type, + (uint32_t)(Addend & 0xffffffffL)); + break; + case Triple::ppc64: + resolvePPC64Relocation(Section, Offset, Value, Type, Addend); + break; default: llvm_unreachable("Unsupported CPU type!"); } } @@ -350,6 +597,8 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel, RelocationValueRef Value; // First search for the symbol in the local symbol table SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data()); + SymbolRef::Type SymType; + Symbol.getType(SymType); if (lsi != Symbols.end()) { Value.SectionID = lsi->second.first; Value.Addend = lsi->second.second; @@ -361,8 +610,6 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel, Value.SectionID = gsi->second.first; Value.Addend = gsi->second.second; } else { - SymbolRef::Type SymType; - Symbol.getType(SymType); switch (SymType) { case SymbolRef::ST_Debug: { // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously @@ -373,7 +620,13 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel, if (si == Obj.end_sections()) llvm_unreachable("Symbol section not found, bad object file format!"); DEBUG(dbgs() << "\t\tThis is section symbol\n"); - Value.SectionID = findOrEmitSection(Obj, (*si), true, ObjSectionToID); + // Default to 'true' in case isText fails (though it never does). + bool isCode = true; + si->isText(isCode); + Value.SectionID = findOrEmitSection(Obj, + (*si), + isCode, + ObjSectionToID); Value.Addend = Addend; break; } @@ -398,13 +651,12 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel, // This is an ARM branch relocation, need to use a stub function. DEBUG(dbgs() << "\t\tThis is an ARM branch relocation."); SectionEntry &Section = Sections[Rel.SectionID]; - uint8_t *Target = Section.Address + Rel.Offset; - // Look up for existing stub. + // Look for an existing stub. StubMap::const_iterator i = Stubs.find(Value); if (i != Stubs.end()) { - resolveRelocation(Target, (uint64_t)Target, (uint64_t)Section.Address + - i->second, RelType, 0); + resolveRelocation(Section, Rel.Offset, + (uint64_t)Section.Address + i->second, RelType, 0); DEBUG(dbgs() << " Stub function found\n"); } else { // Create a new stub function. @@ -419,10 +671,145 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel, else addRelocationForSection(RE, Value.SectionID); - resolveRelocation(Target, (uint64_t)Target, (uint64_t)Section.Address + - Section.StubOffset, RelType, 0); + resolveRelocation(Section, Rel.Offset, + (uint64_t)Section.Address + Section.StubOffset, + RelType, 0); Section.StubOffset += getMaxStubSize(); } + } else if (Arch == Triple::mipsel && RelType == ELF::R_MIPS_26) { + // This is an Mips branch relocation, need to use a stub function. + DEBUG(dbgs() << "\t\tThis is a Mips branch relocation."); + SectionEntry &Section = Sections[Rel.SectionID]; + uint8_t *Target = Section.Address + Rel.Offset; + uint32_t *TargetAddress = (uint32_t *)Target; + + // Extract the addend from the instruction. + uint32_t Addend = ((*TargetAddress) & 0x03ffffff) << 2; + + Value.Addend += Addend; + + // Look up for existing stub. + StubMap::const_iterator i = Stubs.find(Value); + if (i != Stubs.end()) { + resolveRelocation(Section, Rel.Offset, + (uint64_t)Section.Address + i->second, RelType, 0); + DEBUG(dbgs() << " Stub function found\n"); + } else { + // Create a new stub function. + DEBUG(dbgs() << " Create a new stub function\n"); + Stubs[Value] = Section.StubOffset; + uint8_t *StubTargetAddr = createStubFunction(Section.Address + + Section.StubOffset); + + // Creating Hi and Lo relocations for the filled stub instructions. + RelocationEntry REHi(Rel.SectionID, + StubTargetAddr - Section.Address, + ELF::R_MIPS_HI16, Value.Addend); + RelocationEntry RELo(Rel.SectionID, + StubTargetAddr - Section.Address + 4, + ELF::R_MIPS_LO16, Value.Addend); + + if (Value.SymbolName) { + addRelocationForSymbol(REHi, Value.SymbolName); + addRelocationForSymbol(RELo, Value.SymbolName); + } else { + addRelocationForSection(REHi, Value.SectionID); + addRelocationForSection(RELo, Value.SectionID); + } + + resolveRelocation(Section, Rel.Offset, + (uint64_t)Section.Address + Section.StubOffset, + RelType, 0); + Section.StubOffset += getMaxStubSize(); + } + } else if (Arch == Triple::ppc64) { + if (RelType == ELF::R_PPC64_REL24) { + // A PPC branch relocation will need a stub function if the target is + // an external symbol (Symbol::ST_Unknown) or if the target address + // is not within the signed 24-bits branch address. + SectionEntry &Section = Sections[Rel.SectionID]; + uint8_t *Target = Section.Address + Rel.Offset; + bool RangeOverflow = false; + if (SymType != SymbolRef::ST_Unknown) { + // A function call may points to the .opd entry, so the final symbol value + // in calculated based in the relocation values in .opd section. + findOPDEntrySection(Obj, ObjSectionToID, Value); + uint8_t *RelocTarget = Sections[Value.SectionID].Address + Value.Addend; + int32_t delta = static_cast<int32_t>(Target - RelocTarget); + // If it is within 24-bits branch range, just set the branch target + if (SignExtend32<24>(delta) == delta) { + RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend); + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); + } else { + RangeOverflow = true; + } + } + if (SymType == SymbolRef::ST_Unknown || RangeOverflow == true) { + // It is an external symbol (SymbolRef::ST_Unknown) or within a range + // larger than 24-bits. + StubMap::const_iterator i = Stubs.find(Value); + if (i != Stubs.end()) { + // Symbol function stub already created, just relocate to it + resolveRelocation(Section, Rel.Offset, + (uint64_t)Section.Address + i->second, RelType, 0); + DEBUG(dbgs() << " Stub function found\n"); + } else { + // Create a new stub function. + DEBUG(dbgs() << " Create a new stub function\n"); + Stubs[Value] = Section.StubOffset; + uint8_t *StubTargetAddr = createStubFunction(Section.Address + + Section.StubOffset); + RelocationEntry RE(Rel.SectionID, StubTargetAddr - Section.Address, + ELF::R_PPC64_ADDR64, Value.Addend); + + // Generates the 64-bits address loads as exemplified in section + // 4.5.1 in PPC64 ELF ABI. + RelocationEntry REhst(Rel.SectionID, + StubTargetAddr - Section.Address + 2, + ELF::R_PPC64_ADDR16_HIGHEST, Value.Addend); + RelocationEntry REhr(Rel.SectionID, + StubTargetAddr - Section.Address + 6, + ELF::R_PPC64_ADDR16_HIGHER, Value.Addend); + RelocationEntry REh(Rel.SectionID, + StubTargetAddr - Section.Address + 14, + ELF::R_PPC64_ADDR16_HI, Value.Addend); + RelocationEntry REl(Rel.SectionID, + StubTargetAddr - Section.Address + 18, + ELF::R_PPC64_ADDR16_LO, Value.Addend); + + if (Value.SymbolName) { + addRelocationForSymbol(REhst, Value.SymbolName); + addRelocationForSymbol(REhr, Value.SymbolName); + addRelocationForSymbol(REh, Value.SymbolName); + addRelocationForSymbol(REl, Value.SymbolName); + } else { + addRelocationForSection(REhst, Value.SectionID); + addRelocationForSection(REhr, Value.SectionID); + addRelocationForSection(REh, Value.SectionID); + addRelocationForSection(REl, Value.SectionID); + } + + resolveRelocation(Section, Rel.Offset, + (uint64_t)Section.Address + Section.StubOffset, + RelType, 0); + if (SymType == SymbolRef::ST_Unknown) + // Restore the TOC for external calls + writeInt32BE(Target+4, 0xE8410028); // ld r2,40(r1) + Section.StubOffset += getMaxStubSize(); + } + } + } else { + RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend); + // Extra check to avoid relocation againt empty symbols (usually + // the R_PPC64_TOC). + if (Value.SymbolName && !TargetName.empty()) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); + } } else { RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend); if (Value.SymbolName) @@ -432,8 +819,16 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel, } } -bool RuntimeDyldELF::isCompatibleFormat(const MemoryBuffer *InputBuffer) const { - StringRef Magic = InputBuffer->getBuffer().slice(0, ELF::EI_NIDENT); - return (memcmp(Magic.data(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; +unsigned RuntimeDyldELF::getCommonSymbolAlignment(const SymbolRef &Sym) { + // In ELF, the value of an SHN_COMMON symbol is its alignment requirement. + uint64_t Align; + Check(Sym.getValue(Align)); + return Align; +} + +bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const { + if (Buffer->getBufferSize() < strlen(ELF::ElfMagic)) + return false; + return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; } } // namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index e413f78..07e704b 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -18,32 +18,52 @@ using namespace llvm; - namespace llvm { + +namespace { + // Helper for extensive error checking in debug builds. + error_code Check(error_code Err) { + if (Err) { + report_fatal_error(Err.message()); + } + return Err; + } +} // end anonymous namespace + class RuntimeDyldELF : public RuntimeDyldImpl { protected: - ObjectImage *LoadedObject; - - void resolveX86_64Relocation(uint8_t *LocalAddress, - uint64_t FinalAddress, + void resolveX86_64Relocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend); - void resolveX86Relocation(uint8_t *LocalAddress, - uint32_t FinalAddress, + void resolveX86Relocation(const SectionEntry &Section, + uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend); - void resolveARMRelocation(uint8_t *LocalAddress, - uint32_t FinalAddress, + void resolveARMRelocation(const SectionEntry &Section, + uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend); - virtual void resolveRelocation(uint8_t *LocalAddress, - uint64_t FinalAddress, + void resolveMIPSRelocation(const SectionEntry &Section, + uint64_t Offset, + uint32_t Value, + uint32_t Type, + int32_t Addend); + + void resolvePPC64Relocation(const SectionEntry &Section, + uint64_t Offset, + uint64_t Value, + uint32_t Type, + int64_t Addend); + + virtual void resolveRelocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend); @@ -54,16 +74,22 @@ protected: const SymbolTableMap &Symbols, StubMap &Stubs); - virtual ObjectImage *createObjectImage(const MemoryBuffer *InputBuffer); - virtual void handleObjectLoaded(ObjectImage *Obj); + unsigned getCommonSymbolAlignment(const SymbolRef &Sym); + + virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer); + + uint64_t findPPC64TOC() const; + void findOPDEntrySection(ObjectImage &Obj, + ObjSectionToIDMap &LocalSections, + RelocationValueRef &Rel); public: RuntimeDyldELF(RTDyldMemoryManager *mm) - : RuntimeDyldImpl(mm), LoadedObject(0) {} + : RuntimeDyldImpl(mm) {} virtual ~RuntimeDyldELF(); - bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const; + bool isCompatibleFormat(const ObjectBuffer *Buffer) const; }; } // end namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index c38ca69..829fd6c 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -14,8 +14,8 @@ #ifndef LLVM_RUNTIME_DYLD_IMPL_H #define LLVM_RUNTIME_DYLD_IMPL_H -#include "ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" @@ -24,6 +24,8 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" #include <map> @@ -33,7 +35,7 @@ using namespace llvm::object; namespace llvm { -class MemoryBuffer; +class ObjectBuffer; class Twine; @@ -41,6 +43,9 @@ class Twine; /// linker. class SectionEntry { public: + /// Name - section name. + StringRef Name; + /// Address - address in the linker's memory where the section resides. uint8_t *Address; @@ -61,9 +66,9 @@ public: /// for calculating relocations in some object formats (like MachO). uintptr_t ObjAddress; - SectionEntry(uint8_t *address, size_t size, uintptr_t stubOffset, - uintptr_t objAddress) - : Address(address), Size(size), LoadAddress((uintptr_t)address), + SectionEntry(StringRef name, uint8_t *address, size_t size, + uintptr_t stubOffset, uintptr_t objAddress) + : Name(name), Address(address), Size(size), LoadAddress((uintptr_t)address), StubOffset(stubOffset), ObjAddress(objAddress) {} }; @@ -135,8 +140,10 @@ protected: typedef StringMap<SymbolLoc> SymbolTableMap; SymbolTableMap GlobalSymbolTable; - // Keep a map of common symbols to their sizes - typedef std::map<SymbolRef, unsigned> CommonSymbolMap; + // Pair representing the size and alignment requirement for a common symbol. + typedef std::pair<unsigned, unsigned> CommonSymbolInfo; + // Keep a map of common symbols to their info pairs + typedef std::map<SymbolRef, CommonSymbolInfo> CommonSymbolMap; // For each symbol, keep a list of relocations based on it. Anytime // its address is reassigned (the JIT re-compiled the function, e.g.), @@ -161,6 +168,10 @@ protected: inline unsigned getMaxStubSize() { if (Arch == Triple::arm || Arch == Triple::thumb) return 8; // 32-bit instruction and 32-bit address + else if (Arch == Triple::mipsel) + return 16; + else if (Arch == Triple::ppc64) + return 44; else return 0; } @@ -175,10 +186,50 @@ protected: return true; } + uint64_t getSectionLoadAddress(unsigned SectionID) { + return Sections[SectionID].LoadAddress; + } + uint8_t *getSectionAddress(unsigned SectionID) { return (uint8_t*)Sections[SectionID].Address; } + // Subclasses can override this method to get the alignment requirement of + // a common symbol. Returns no alignment requirement if not implemented. + virtual unsigned getCommonSymbolAlignment(const SymbolRef &Sym) { + return 0; + } + + + void writeInt16BE(uint8_t *Addr, uint16_t Value) { + if (sys::isLittleEndianHost()) + Value = sys::SwapByteOrder(Value); + *Addr = (Value >> 8) & 0xFF; + *(Addr+1) = Value & 0xFF; + } + + void writeInt32BE(uint8_t *Addr, uint32_t Value) { + if (sys::isLittleEndianHost()) + Value = sys::SwapByteOrder(Value); + *Addr = (Value >> 24) & 0xFF; + *(Addr+1) = (Value >> 16) & 0xFF; + *(Addr+2) = (Value >> 8) & 0xFF; + *(Addr+3) = Value & 0xFF; + } + + void writeInt64BE(uint8_t *Addr, uint64_t Value) { + if (sys::isLittleEndianHost()) + Value = sys::SwapByteOrder(Value); + *Addr = (Value >> 56) & 0xFF; + *(Addr+1) = (Value >> 48) & 0xFF; + *(Addr+2) = (Value >> 40) & 0xFF; + *(Addr+3) = (Value >> 32) & 0xFF; + *(Addr+4) = (Value >> 24) & 0xFF; + *(Addr+5) = (Value >> 16) & 0xFF; + *(Addr+6) = (Value >> 8) & 0xFF; + *(Addr+7) = Value & 0xFF; + } + /// \brief Given the common symbols discovered in the object file, emit a /// new section for them and update the symbol mappings in the object and /// symbol table. @@ -221,13 +272,14 @@ protected: void resolveRelocationEntry(const RelocationEntry &RE, uint64_t Value); /// \brief A object file specific relocation resolver - /// \param Address Address to apply the relocation action + /// \param Section The section where the relocation is being applied + /// \param Offset The offset into the section for this relocation /// \param Value Target symbol address to apply the relocation action /// \param Type object file specific relocation type /// \param Addend A constant addend used to compute the value to be stored /// into the relocatable field - virtual void resolveRelocation(uint8_t *LocalAddress, - uint64_t FinalAddress, + virtual void resolveRelocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend) = 0; @@ -242,19 +294,13 @@ protected: /// \brief Resolve relocations to external symbols. void resolveExternalSymbols(); - virtual ObjectImage *createObjectImage(const MemoryBuffer *InputBuffer); - virtual void handleObjectLoaded(ObjectImage *Obj) - { - // Subclasses may choose to retain this image if they have a use for it - delete Obj; - } - + virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer); public: RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {} virtual ~RuntimeDyldImpl(); - bool loadObject(const MemoryBuffer *InputBuffer); + ObjectImage *loadObject(ObjectBuffer *InputBuffer); void *getSymbolAddress(StringRef Name) { // FIXME: Just look up as a function for now. Overly simple of course. @@ -265,11 +311,20 @@ public: return getSectionAddress(Loc.first) + Loc.second; } + uint64_t getSymbolLoadAddress(StringRef Name) { + // FIXME: Just look up as a function for now. Overly simple of course. + // Work in progress. + if (GlobalSymbolTable.find(Name) == GlobalSymbolTable.end()) + return 0; + SymbolLoc Loc = GlobalSymbolTable.lookup(Name); + return getSectionLoadAddress(Loc.first) + Loc.second; + } + void resolveRelocations(); void reassignSectionAddress(unsigned SectionID, uint64_t Addr); - void mapSectionAddress(void *LocalAddress, uint64_t TargetAddress); + void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); // Is the linker in an error state? bool hasError() { return HasError; } @@ -280,8 +335,7 @@ public: // Get the error message. StringRef getErrorString() { return ErrorStr; } - virtual bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const = 0; - + virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0; }; } // end namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 0e3a9d4..987c0c3 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -21,11 +21,13 @@ using namespace llvm::object; namespace llvm { -void RuntimeDyldMachO::resolveRelocation(uint8_t *LocalAddress, - uint64_t FinalAddress, +void RuntimeDyldMachO::resolveRelocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend) { + uint8_t *LocalAddress = Section.Address + Offset; + uint64_t FinalAddress = Section.LoadAddress + Offset; bool isPCRel = (Type >> 24) & 1; unsigned MachoType = (Type >> 28) & 0xf; unsigned Size = 1 << ((Type >> 25) & 3); @@ -57,7 +59,7 @@ void RuntimeDyldMachO::resolveRelocation(uint8_t *LocalAddress, FinalAddress, (uintptr_t)Value, isPCRel, - Type, + MachoType, Size, Addend); break; @@ -211,7 +213,6 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel, uint32_t RelType = (uint32_t) (Rel.Type & 0xffffffffL); RelocationValueRef Value; SectionEntry &Section = Sections[Rel.SectionID]; - uint8_t *Target = Section.Address + Rel.Offset; bool isExtern = (RelType >> 27) & 1; if (isExtern) { @@ -246,7 +247,12 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel, } assert(si != se && "No section containing relocation!"); Value.SectionID = findOrEmitSection(Obj, *si, true, ObjSectionToID); - Value.Addend = *(const intptr_t *)Target; + Value.Addend = 0; + // FIXME: The size and type of the relocation determines if we can + // encode an Addend in the target location itself, and if so, how many + // bytes we should read in order to get it. We don't yet support doing + // that, and just assuming it's sizeof(intptr_t) is blatantly wrong. + //Value.Addend = *(const intptr_t *)Target; if (Value.Addend) { // The MachO addend is an offset from the current section. We need it // to be an offset from the destination section @@ -254,13 +260,13 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel, } } - if (Arch == Triple::arm && RelType == macho::RIT_ARM_Branch24Bit) { + if (Arch == Triple::arm && (RelType & 0xf) == macho::RIT_ARM_Branch24Bit) { // This is an ARM branch relocation, need to use a stub function. // Look up for existing stub. StubMap::const_iterator i = Stubs.find(Value); if (i != Stubs.end()) - resolveRelocation(Target, (uint64_t)Target, + resolveRelocation(Section, Rel.Offset, (uint64_t)Section.Address + i->second, RelType, 0); else { @@ -274,7 +280,7 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel, addRelocationForSymbol(RE, Value.SymbolName); else addRelocationForSection(RE, Value.SectionID); - resolveRelocation(Target, (uint64_t)Target, + resolveRelocation(Section, Rel.Offset, (uint64_t)Section.Address + Section.StubOffset, RelType, 0); Section.StubOffset += getMaxStubSize(); @@ -290,8 +296,10 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel, bool RuntimeDyldMachO::isCompatibleFormat( - const MemoryBuffer *InputBuffer) const { - StringRef Magic = InputBuffer->getBuffer().slice(0, 4); + const ObjectBuffer *InputBuffer) const { + if (InputBuffer->getBufferSize() < 4) + return false; + StringRef Magic(InputBuffer->getBufferStart(), 4); if (Magic == "\xFE\xED\xFA\xCE") return true; if (Magic == "\xCE\xFA\xED\xFE") return true; if (Magic == "\xFE\xED\xFA\xCF") return true; diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index 707664c..fe3539d 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -55,15 +55,15 @@ protected: StubMap &Stubs); public: - virtual void resolveRelocation(uint8_t *LocalAddress, - uint64_t FinalAddress, + virtual void resolveRelocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend); RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} - bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const; + bool isCompatibleFormat(const ObjectBuffer *Buffer) const; }; } // end namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp b/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp index 7cdd669..8b6104f 100644 --- a/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp +++ b/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp @@ -26,7 +26,14 @@ using namespace llvm; TargetMachine *EngineBuilder::selectTarget() { - Triple TT(LLVM_HOSTTRIPLE); + Triple TT; + + // MCJIT can generate code for remote targets, but the old JIT and Interpreter + // must use the host architecture. + if (UseMCJIT && WhichEngine != EngineKind::Interpreter && M) + TT.setTriple(M->getTargetTriple()); + else + TT.setTriple(LLVM_HOSTTRIPLE); return selectTarget(TT, MArch, MCPU, MAttrs); } |