Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove libstdc++ dependency from NativeAOT #76705

Merged
merged 3 commits into from Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/coreclr/gc/gc.cpp
Expand Up @@ -11488,6 +11488,8 @@ bool gc_heap::is_region_demoted (uint8_t* obj)
return demoted_p;
}

static GCSpinLock write_barrier_spin_lock;

inline
void gc_heap::set_region_gen_num (heap_segment* region, int gen_num)
{
Expand All @@ -11510,8 +11512,6 @@ void gc_heap::set_region_gen_num (heap_segment* region, int gen_num)
{
if ((region_start < ephemeral_low) || (ephemeral_high < region_end))
{
static GCSpinLock write_barrier_spin_lock;

while (true)
{
if (Interlocked::CompareExchange(&write_barrier_spin_lock.lock, 0, -1) < 0)
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/gc/gc.h
Expand Up @@ -253,9 +253,9 @@ struct alloc_context : gc_alloc_context

class IGCHeapInternal : public IGCHeap {
public:
virtual int GetNumberOfHeaps () = 0;
virtual int GetHomeHeapNumber () = 0;
virtual size_t GetPromotedBytes(int heap_index) = 0;
virtual int GetNumberOfHeaps () PURE_VIRTUAL
virtual int GetHomeHeapNumber () PURE_VIRTUAL
virtual size_t GetPromotedBytes(int heap_index) PURE_VIRTUAL

unsigned GetMaxGeneration()
{
Expand Down
221 changes: 114 additions & 107 deletions src/coreclr/gc/gcinterface.h

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/coreclr/gc/handletablecache.cpp
Expand Up @@ -56,7 +56,7 @@ void SpinUntil(void *pCond, BOOL fNonZero)
#endif //_DEBUG

// on MP machines, allow ourselves some spin time before sleeping
static uint32_t uNonSleepSpins = 8 * (GCToEEInterface::GetCurrentProcessCpuCount() - 1);
uint32_t uNonSleepSpins = 8 * (GCToEEInterface::GetCurrentProcessCpuCount() - 1);

// spin until the specified condition is met
while ((*(uintptr_t *)pCond != 0) != (fNonZero != 0))
Expand Down
16 changes: 6 additions & 10 deletions src/coreclr/gc/unix/events.cpp
@@ -1,11 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#include <cstdint>
#include <cstddef>
#include <cassert>
#include <memory>
#include <mutex>
#include <pthread.h>
#include <errno.h>
#include "config.gc.h"
Expand Down Expand Up @@ -280,36 +275,37 @@ bool GCEvent::CreateManualEventNoThrow(bool initialState)
bool GCEvent::CreateOSAutoEventNoThrow(bool initialState)
{
assert(m_impl == nullptr);
std::unique_ptr<GCEvent::Impl> event(new (std::nothrow) GCEvent::Impl(false, initialState));
GCEvent::Impl* event(new (nothrow) GCEvent::Impl(false, initialState));
if (!event)
{
return false;
}

if (!event->Initialize())
{
delete event;
return false;
}

m_impl = event.release();
m_impl = event;
return true;
}

bool GCEvent::CreateOSManualEventNoThrow(bool initialState)
{
assert(m_impl == nullptr);
std::unique_ptr<GCEvent::Impl> event(new (std::nothrow) GCEvent::Impl(true, initialState));
GCEvent::Impl* event(new (nothrow) GCEvent::Impl(true, initialState));
if (!event)
{
return false;
}

if (!event->Initialize())
{
delete event;
return false;
}

m_impl = event.release();
m_impl = event;
return true;
}

3 changes: 3 additions & 0 deletions src/coreclr/nativeaot/Bootstrap/base/CMakeLists.txt
Expand Up @@ -12,4 +12,7 @@ if (CLR_CMAKE_TARGET_WIN32)
add_library(bootstrapper.GuardCF STATIC ${SOURCES})
install_static_library(bootstrapper.GuardCF aotsdk nativeaot)
target_compile_options(bootstrapper.GuardCF PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:/guard:cf>)
else()
add_library(stdc++compat STATIC ../stdcppshim.cpp)
install_static_library(stdc++compat aotsdk nativeaot)
endif()
30 changes: 30 additions & 0 deletions src/coreclr/nativeaot/Bootstrap/stdcppshim.cpp
@@ -0,0 +1,30 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#include <stdlib.h>

namespace std
{
struct nothrow_t {};
extern const nothrow_t nothrow = {};
}

void* operator new(size_t n, const std::nothrow_t&) noexcept
{
return malloc(n);
}

void* operator new[](size_t n, const std::nothrow_t&) noexcept
{
return malloc(n);
}

void operator delete(void *p) noexcept
{
free(p);
}

void operator delete[](void *p) noexcept
{
free(p);
}
Expand Up @@ -49,6 +49,7 @@ The .NET Foundation licenses this file to you under the MIT license.
<NativeLibrary Condition="$(NativeLib) == ''" Include="$(IlcSdkPath)libbootstrapper.a" />
<NativeLibrary Condition="$(NativeLib) != ''" Include="$(IlcSdkPath)libbootstrapperdll.a" />
<NativeLibrary Include="$(IlcSdkPath)$(FullRuntimeName).a" />
<NativeLibrary Condition="'$(LinkStandardCPlusPlusLibrary)' != 'true'" Include="$(IlcSdkPath)libstdc++compat.a" />
</ItemGroup>

<ItemGroup>
Expand Down Expand Up @@ -96,7 +97,7 @@ The .NET Foundation licenses this file to you under the MIT license.
<LinkerArg Include="-Wl,--as-needed" Condition="'$(TargetOS)' != 'OSX'" />
<LinkerArg Include="-Wl,-e0x0" Condition="'$(NativeLib)' == 'Shared' and '$(TargetOS)' != 'OSX'" />
<LinkerArg Include="-pthread" Condition="'$(TargetOS)' != 'OSX'" />
<LinkerArg Include="-lstdc++" />
am11 marked this conversation as resolved.
Show resolved Hide resolved
<LinkerArg Include="-lstdc++" Condition="'$(LinkStandardCPlusPlusLibrary)' == 'true'" />
<LinkerArg Include="-ldl" />
<LinkerArg Include="-lm" />
<LinkerArg Include="-lobjc" Condition="'$(TargetOS)' == 'OSX'" />
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/nativeaot/CMakeLists.txt
Expand Up @@ -30,6 +30,7 @@ if(CLR_CMAKE_HOST_UNIX)

add_compile_options(-fno-rtti) # Native AOT runtime doesn't use RTTI
add_compile_options(-fno-exceptions) # Native AOT runtime doesn't use C++ exception handling
add_compile_options(-nostdlib)
am11 marked this conversation as resolved.
Show resolved Hide resolved

if(CLR_CMAKE_TARGET_OSX)
add_definitions(-D_XOPEN_SOURCE)
Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/nativeaot/Runtime/CMakeLists.txt
Expand Up @@ -105,9 +105,6 @@ if (WIN32)
${GC_DIR}/handletablepriv.h
${GC_DIR}/objecthandle.h
${GC_DIR}/softwarewritewatch.h)
endif(WIN32)

if(WIN32)

include_directories(windows)

Expand Down
32 changes: 16 additions & 16 deletions src/coreclr/nativeaot/Runtime/ICodeManager.h
Expand Up @@ -165,50 +165,50 @@ enum class AssociatedDataFlags : unsigned char
class ICodeManager
{
public:
virtual bool IsSafePoint(PTR_VOID pvAddress) = 0;
virtual bool IsSafePoint(PTR_VOID pvAddress) PURE_VIRTUAL

virtual bool FindMethodInfo(PTR_VOID ControlPC,
MethodInfo * pMethodInfoOut) = 0;
MethodInfo * pMethodInfoOut) PURE_VIRTUAL

virtual bool IsFunclet(MethodInfo * pMethodInfo) = 0;
virtual bool IsFunclet(MethodInfo * pMethodInfo) PURE_VIRTUAL

virtual PTR_VOID GetFramePointer(MethodInfo * pMethodInfo,
REGDISPLAY * pRegisterSet) = 0;
REGDISPLAY * pRegisterSet) PURE_VIRTUAL

virtual void EnumGcRefs(MethodInfo * pMethodInfo,
PTR_VOID safePointAddress,
REGDISPLAY * pRegisterSet,
GCEnumContext * hCallback,
bool isActiveStackFrame) = 0;
bool isActiveStackFrame) PURE_VIRTUAL

virtual bool UnwindStackFrame(MethodInfo * pMethodInfo,
REGDISPLAY * pRegisterSet, // in/out
PInvokeTransitionFrame** ppPreviousTransitionFrame) = 0; // out
PInvokeTransitionFrame** ppPreviousTransitionFrame) PURE_VIRTUAL // out

virtual uintptr_t GetConservativeUpperBoundForOutgoingArgs(MethodInfo * pMethodInfo,
REGDISPLAY * pRegisterSet) = 0;
REGDISPLAY * pRegisterSet) PURE_VIRTUAL

virtual bool IsUnwindable(PTR_VOID pvAddress) = 0;
virtual bool IsUnwindable(PTR_VOID pvAddress) PURE_VIRTUAL

virtual bool GetReturnAddressHijackInfo(MethodInfo * pMethodInfo,
REGDISPLAY * pRegisterSet, // in
PTR_PTR_VOID * ppvRetAddrLocation, // out
GCRefKind * pRetValueKind) = 0; // out
GCRefKind * pRetValueKind) PURE_VIRTUAL // out

virtual PTR_VOID RemapHardwareFaultToGCSafePoint(MethodInfo * pMethodInfo, PTR_VOID controlPC) = 0;
virtual PTR_VOID RemapHardwareFaultToGCSafePoint(MethodInfo * pMethodInfo, PTR_VOID controlPC) PURE_VIRTUAL

virtual bool EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMethodStartAddress, EHEnumState * pEHEnumState) = 0;
virtual bool EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMethodStartAddress, EHEnumState * pEHEnumState) PURE_VIRTUAL

virtual bool EHEnumNext(EHEnumState * pEHEnumState, EHClause * pEHClause) = 0;
virtual bool EHEnumNext(EHEnumState * pEHEnumState, EHClause * pEHClause) PURE_VIRTUAL

virtual PTR_VOID GetMethodStartAddress(MethodInfo * pMethodInfo) = 0;
virtual PTR_VOID GetMethodStartAddress(MethodInfo * pMethodInfo) PURE_VIRTUAL

virtual PTR_VOID GetOsModuleHandle() = 0;
virtual PTR_VOID GetOsModuleHandle() PURE_VIRTUAL

virtual void * GetClasslibFunction(ClasslibFunctionId functionId) = 0;
virtual void * GetClasslibFunction(ClasslibFunctionId functionId) PURE_VIRTUAL

// Returns any custom data attached to the method. Format:
// AssociatedDataFlags // 1 byte. Flags describing the data stored
// Data (stream of bytes) // Variable size (depending on flags). Custom data associated with method
virtual PTR_VOID GetAssociatedData(PTR_VOID ControlPC) = 0;
virtual PTR_VOID GetAssociatedData(PTR_VOID ControlPC) PURE_VIRTUAL
};
12 changes: 11 additions & 1 deletion src/coreclr/nativeaot/Runtime/inc/CommonTypes.h
Expand Up @@ -6,9 +6,19 @@

#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <stdlib.h>
#include <stdio.h>
#include <new>

// Implement pure virtual for Unix (for -p:LinkStandardCPlusPlusLibrary=false the default),
// to avoid linker requiring __cxa_pure_virtual.
#ifdef TARGET_WINDOWS
#define PURE_VIRTUAL = 0;
#else
// `while(true);` is to satisfy the missing `return` statement. It will be optimized away by the compiler.
#define PURE_VIRTUAL { assert(!"pure virtual function called"); while(true); }
#endif

using std::nothrow;
using std::size_t;
using std::uintptr_t;
Expand Down
38 changes: 22 additions & 16 deletions src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp
Expand Up @@ -20,6 +20,7 @@
#include "UnixContext.h"
#include "HardwareExceptions.h"
#include "cgroupcpu.h"
#include "threadstore.h"

#define _T(s) s
#include "RhConfig.h"
Expand Down Expand Up @@ -346,11 +347,6 @@ class EventUnixHandle : public UnixHandle<UnixHandleType::Event, UnixEvent>

typedef UnixHandle<UnixHandleType::Thread, pthread_t> ThreadUnixHandle;

#if !HAVE_THREAD_LOCAL
extern "C" int __cxa_thread_atexit(void (*)(void*), void*, void *);
extern "C" void *__dso_handle;
#endif

// This functions configures behavior of the signals that are not
// related to hardware exception handling.
void ConfigureSignals()
Expand Down Expand Up @@ -406,6 +402,10 @@ void InitializeCurrentProcessCpuCount()
g_RhNumberOfProcessors = count;
}

#ifdef TARGET_LINUX
static pthread_key_t key;
#endif

// The Redhawk PAL must be initialized before any of its exports can be called. Returns true for a successful
// initialization and false on failure.
REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalInit()
Expand All @@ -430,11 +430,17 @@ REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalInit()

InitializeCurrentProcessCpuCount();

#ifdef TARGET_LINUX
if (pthread_key_create(&key, RuntimeThreadShutdown) != 0)
{
return false;
}
#endif

return true;
}

#if HAVE_THREAD_LOCAL

#ifndef TARGET_LINUX
struct TlsDestructionMonitor
{
void* m_thread = nullptr;
Expand All @@ -456,8 +462,7 @@ struct TlsDestructionMonitor
// This thread local object is used to detect thread shutdown. Its destructor
// is called when a thread is being shut down.
thread_local TlsDestructionMonitor tls_destructionMonitor;

#endif // HAVE_THREAD_LOCAL
#endif

// This thread local variable is used for delegate marshalling
DECLSPEC_THREAD intptr_t tls_thunkData;
Expand All @@ -481,10 +486,14 @@ EXTERN_C intptr_t RhGetCurrentThunkContext()
// thread - thread to attach
extern "C" void PalAttachThread(void* thread)
{
#if HAVE_THREAD_LOCAL
tls_destructionMonitor.SetThread(thread);
#ifdef TARGET_LINUX
if (pthread_setspecific(key, thread) != 0)
{
_ASSERTE(!"pthread_setspecific failed");
RhFailFast();
}
#else
__cxa_thread_atexit(RuntimeThreadShutdown, thread, &__dso_handle);
tls_destructionMonitor.SetThread(thread);
#endif
}

Expand Down Expand Up @@ -943,16 +952,13 @@ extern "C" UInt32_BOOL ResetEvent(HANDLE event)

extern "C" uint32_t GetEnvironmentVariableA(const char * name, char * buffer, uint32_t size)
{
// Using std::getenv instead of getenv since it is guaranteed to be thread safe w.r.t. other
am11 marked this conversation as resolved.
Show resolved Hide resolved
// std::getenv calls in C++11
const char* value = std::getenv(name);
const char* value = getenv(name);
if (value == NULL)
{
return 0;
}

size_t valueLen = strlen(value);

if (valueLen < size)
{
strcpy(buffer, value);
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/config.h.in
Expand Up @@ -27,6 +27,4 @@
#cmakedefine01 HAVE_CLOCK_GETTIME_NSEC_NP
#cmakedefine01 HAVE_SCHED_GETAFFINITY

#cmakedefine01 HAVE_THREAD_LOCAL

#endif
9 changes: 0 additions & 9 deletions src/coreclr/nativeaot/Runtime/unix/configure.cmake
Expand Up @@ -105,13 +105,4 @@ check_symbol_exists(

check_library_exists(c sched_getaffinity "" HAVE_SCHED_GETAFFINITY)

check_cxx_source_compiles("
thread_local int x;

int main(int argc, char **argv)
{
x = 1;
return 0;
}" HAVE_THREAD_LOCAL)

configure_file(${CMAKE_CURRENT_LIST_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
Expand Up @@ -11,6 +11,12 @@
and this only works if presence of code implies presence of reflection metadata.
-->
<IlcTrimMetadata>false</IlcTrimMetadata>

<!--
By default, we link libstdc++compat.a, This property is set to exercise code
with system C++ runtime library (-lstdc++).
-->
<LinkStandardCPlusPlusLibrary>true</LinkStandardCPlusPlusLibrary>
</PropertyGroup>

<ItemGroup>
Expand Down