Skip to content

Commit

Permalink
Remove libstdc++ dependency from NativeAOT (#76705)
Browse files Browse the repository at this point in the history
Fixes #76655
  • Loading branch information
am11 authored Oct 13, 2022
1 parent d337cba commit 546fad9
Show file tree
Hide file tree
Showing 16 changed files with 217 additions and 171 deletions.
4 changes: 2 additions & 2 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
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++" />
<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
Original file line number Diff line number Diff line change
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)

if(CLR_CMAKE_TARGET_OSX)
add_definitions(-D_XOPEN_SOURCE)
Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/nativeaot/Runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
// 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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)
Original file line number Diff line number Diff line change
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

0 comments on commit 546fad9

Please sign in to comment.