Initial pass at Windows support.

All tests now pass with the new ABI on x86-64, with the new ABI.  Some
of the code is ugly and other platforms are probably broken.
main
David Chisnall 8 years ago
parent f352f62423
commit 934cd13a7a

@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.1)
project(libobjc)
enable_language(ASM)
project(libobjc C ASM CXX)
INCLUDE (CheckCXXSourceCompiles)
@ -10,13 +9,15 @@ macro(install_symlink filepath sympath)
install(CODE "message(\"-- Symlinking: ${sympath} -> ${filepath}\")")
endmacro(install_symlink)
set(CMAKE_C_FLAGS_DEBUG "-g -O0 -fno-inline ${CMAKE_C_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_DEBUG "/Z7 -O0 -Xclang -fno-inline ${CMAKE_C_FLAGS_DEBUG}")
set(CMAKE_SHARED_LINKER_FLAGS "/DEBUG /INCREMENTAL:NO ${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_C_FLAGS_RELEASE "-O3 ${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_C_FLAGS "-std=gnu99 ${CMAKE_C_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
set(libobjc_VERSION 4.6)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /EHas -Xclang -fexceptions -Xclang -fobjc-exceptions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHas")
# Build configuration
add_definitions( -DGNUSTEP -D__OBJC_RUNTIME_INTERNAL__=1)
@ -37,7 +38,6 @@ set(libobjc_C_SRCS
category_loader.c
class_table.c
dtable.c
eh_personality.c
encoding2.c
hooks.c
ivar.c
@ -68,10 +68,16 @@ set(libobjc_HDRS
objc/objc.h
objc/runtime-deprecated.h
objc/runtime.h
objc/slot.h
)
objc/slot.h)
# Windows does not use DWARF EH
if (WIN32)
list(APPEND libobjc_CXX_SRCS eh_win32_msvc.cc)
else ()
list(APPEND libobjc_C_SRCS eh_personality.c)
set(libobjcxx_CXX_SRCS objcxx_eh.cc)
endif (WIN32)
set(libobjcxx_CXX_SRCS objcxx_eh.cc)
# For release builds, we disable spamming the terminal with warnings about
# selector type mismatches
@ -154,10 +160,26 @@ endif ()
set(INSTALL_TARGETS objc)
# On Windows, CMake adds /TC to the clang-cl flags and doesn't provide a way to
# tell it not to. We fix this by telling clang do disregard that option,
# unconditionally (which means that it still defaults to C for .c files).
set(ENV{CCC_OVERRIDE_OPTIONS} "x/TC x/Gm-")
set_source_files_properties(
${libobjc_ASM_SRCS}
LANGUAGE C
COMPILE_FLAGS "${CMAKE_OBJC_FLAGS} -Xclang -x -Xclang assembler-with-cpp"
)
set_source_files_properties(
${libobjc_CXX_SRCS}
LANGUAGE CXX
COMPILE_FLAGS "${CMAKE_CXX_FLAGS}"
)
set_source_files_properties(
${libobjc_OBJC_SRCS}
PROPERTIES LANGUAGE C
COMPILE_FLAGS "${CMAKE_OBJC_FLAGS}"
COMPILE_FLAGS "${CMAKE_OBJC_FLAGS} -Xclang -x -Xclang objective-c"
)
#
@ -186,40 +208,55 @@ set(ENABLE_OBJCXX true CACHE BOOL
set(CXXRT_IS_STDLIB false)
add_library(objc SHARED ${libobjc_C_SRCS} ${libobjc_ASM_SRCS} ${libobjc_OBJC_SRCS})
add_custom_command(OUTPUT block_trampolines.obj
COMMAND ${CMAKE_C_COMPILER} -c "${CMAKE_SOURCE_DIR}/block_trampolines.S" -o "${CMAKE_BINARY_DIR}/block_trampolines.obj"
MAIN_DEPENDENCY block_trampolines.S
)
add_custom_command(OUTPUT objc_msgSend.obj
COMMAND ${CMAKE_C_COMPILER} -c "${CMAKE_SOURCE_DIR}/objc_msgSend.S" -o "${CMAKE_BINARY_DIR}/objc_msgSend.obj"
MAIN_DEPENDENCY objc_msgSend.S
DEPENDS objc_msgSend.aarch64.S objc_msgSend.arm.S objc_msgSend.mips.S objc_msgSend.x86-32.S objc_msgSend.x86-64.S
)
add_library(objc SHARED ${libobjc_C_SRCS} ${libobjc_ASM_SRCS} ${libobjc_OBJC_SRCS} block_trampolines.obj objc_msgSend.obj)
if (ENABLE_OBJCXX)
message(STATUS "Testing C++ interop")
# Try to find libcxxrt.so. We can link to this to provide the C++ ABI
# layer, if it exists.
test_cxx(cxxrt false)
# If it doesn't, then look for GNU libsupc++.so instead (either works,
# they're ABI compatible).
if (NOT CXX_RUNTIME)
test_cxx(supc++ false)
endif (NOT CXX_RUNTIME)
if (NOT CXX_RUNTIME)
test_cxx(c++abi false)
endif (NOT CXX_RUNTIME)
# If we have a C++ ABI library, then we can produce a single libobjc that
# works for Objective-C and Objective-C++. If not, then we need to provide
# a separate libobjcxx.
if (CXX_RUNTIME)
message(STATUS "Using ${CXX_RUNTIME} as the C++ runtime library")
else()
message(STATUS "Testing C++ standard library")
try_compile(USERUNTIME
"${CMAKE_BINARY_DIR}/CMake"
"${CMAKE_SOURCE_DIR}/CMake"
test_cxx_runtime)
if (${USERUNTIME})
message(STATUS "libobjc will depend on C++ standard library")
set(CXXRT_IS_STDLIB true)
if (WIN32)
message(STATUS "Using MSVC-compatible exception model")
else ()
message(STATUS "Testing C++ interop")
# Try to find libcxxrt.so. We can link to this to provide the C++ ABI
# layer, if it exists.
test_cxx(cxxrt false)
# If it doesn't, then look for GNU libsupc++.so instead (either works,
# they're ABI compatible).
if (NOT CXX_RUNTIME)
test_cxx(supc++ false)
endif (NOT CXX_RUNTIME)
if (NOT CXX_RUNTIME)
test_cxx(c++abi false)
endif (NOT CXX_RUNTIME)
# If we have a C++ ABI library, then we can produce a single libobjc that
# works for Objective-C and Objective-C++. If not, then we need to provide
# a separate libobjcxx.
if (CXX_RUNTIME)
message(STATUS "Using ${CXX_RUNTIME} as the C++ runtime library")
else()
message(STATUS "No useable C++ runtime found")
set(ENABLE_OBJCXX false)
endif()
message(STATUS "Testing C++ standard library")
try_compile(USERUNTIME
"${CMAKE_BINARY_DIR}/CMake"
"${CMAKE_SOURCE_DIR}/CMake"
test_cxx_runtime)
if (${USERUNTIME})
message(STATUS "libobjc will depend on C++ standard library")
set(CXXRT_IS_STDLIB true)
else()
message(STATUS "No useable C++ runtime found")
set(ENABLE_OBJCXX false)
endif()
endif ()
endif ()
endif (ENABLE_OBJCXX)
@ -231,8 +268,8 @@ if (ENABLE_OBJCXX)
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
target_link_libraries(objc ${CXX_RUNTIME})
endif()
set(libobjc_CXX_SRCS ${libobjcxx_CXX_SRCS})
target_sources(objc PRIVATE ${libobjcxx_CXX_SRCS})
list(APPEND libobjc_CXX_SRCS ${libobjcxx_CXX_SRCS})
target_sources(objc PRIVATE ${libobjc_CXX_SRCS})
endif()
@ -264,8 +301,6 @@ if (BUILD_STATIC_LIBOBJC)
list(APPEND INSTALL_TARGETS objc-static)
endif ()
# Explicitly link libgc if we are compiling with gc support.
if (LIBGC)
target_link_libraries(objc ${LIBGC})

@ -1,14 +1,14 @@
#import "objc/runtime.h"
#import "class.h"
#import "loader.h"
#import "lock.h"
#import "objc/blocks_runtime.h"
#import "dtable.h"
#include "objc/runtime.h"
#include "class.h"
#include "loader.h"
#include "lock.h"
#include "objc/blocks_runtime.h"
#include "dtable.h"
#include <assert.h>
struct objc_class _NSConcreteGlobalBlock;
struct objc_class _NSConcreteStackBlock;
struct objc_class _NSConcreteMallocBlock;
PUBLIC struct objc_class _NSConcreteGlobalBlock;
PUBLIC struct objc_class _NSConcreteStackBlock;
PUBLIC struct objc_class _NSConcreteMallocBlock;
static struct objc_class _NSConcreteGlobalBlockMeta;
static struct objc_class _NSConcreteStackBlockMeta;
@ -40,6 +40,7 @@ static void createNSBlockSubclass(Class superclass, Class newClass,
#define NEW_CLASS(super, sub) \
createNSBlockSubclass(super, &sub, &sub ## Meta, #sub)
PUBLIC
BOOL objc_create_block_classes_as_subclasses_of(Class super)
{
if (_NSBlock.super_class != NULL) { return NO; }

@ -3,6 +3,16 @@
# the installed version
# On Windows, CMake adds /TC to the clang-cl flags and doesn't provide a way to
# tell it not to. We fix this by telling clang do disregard that option,
# unconditionally (which means that it still defaults to C for .c files).
set(ENV{CCC_OVERRIDE_OPTIONS} "x/TC x/TP")
set(INCREMENTAL " ")
if (MSVC)
set(CMAKE_EXE_LINKER_FLAGS "/DEBUG /INCREMENTAL:NO ${CMAKE_EXE_LINKER_FLAGS}")
set(INCREMENTAL "/INCREMENTAL:NO")
endif ()
# List of single-file tests.
set(TESTS
alias.m
@ -14,10 +24,8 @@ set(TESTS
BlockImpTest.m
BlockTest_arc.m
ConstantString.m
BoxedForeignException.m
Category.m
ExceptionTest.m
ForeignException.m
Forward.m
ManyManySelectors.m
NestedExceptions.m
@ -43,24 +51,33 @@ set(TESTS
setSuperclass.m
)
if (WIN32)
else ()
list(APPEND TESTS
BoxedForeignException.m
ForeignException.m
)
endif ()
# List of single-file tests that won't work with the legacy ABI and so
# shouldn't be run in legacy mode.
set(NEW_TESTS
category_properties.m
)
remove_definitions(-D__OBJC_RUNTIME_INTERNAL__=1)
add_library(test_runtime_legacy OBJECT Test.m)
set_target_properties(test_runtime_legacy PROPERTIES
INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}"
COMPILE_FLAGS "-fblocks -fobjc-runtime=gnustep-1.7"
COMPILE_FLAGS "-Xclang -fblocks -fobjc-runtime=gnustep-1.7"
LINKER_LANGUAGE C
)
add_library(test_runtime OBJECT Test.m)
set_target_properties(test_runtime PROPERTIES
INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}"
COMPILE_FLAGS "-fblocks -fobjc-runtime=gnustep-2.0"
COMPILE_FLAGS "-Xclang -fblocks -fobjc-runtime=gnustep-2.0"
LINKER_LANGUAGE C
)
@ -71,14 +88,14 @@ function(addtest_flags TEST_NAME FLAGS TEST_SOURCE)
if (${TEST_NAME} MATCHES ".*_arc")
# Only compile the main file with ARC
set_source_files_properties(${TEST_SOURCE}
COMPILE_FLAGS "-fobjc-arc")
COMPILE_FLAGS "-Xclang -fobjc-arc")
endif()
add_executable(${TEST_NAME} ${TEST_SOURCE})
add_test(${TEST_NAME} ${TEST_NAME})
set(ARC "")
set_target_properties(${TEST_NAME} PROPERTIES
INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}"
COMPILE_FLAGS "-fblocks ${FLAGS}"
COMPILE_FLAGS "-Xclang -fblocks ${FLAGS}"
LINKER_LANGUAGE C
)
set_property(TEST ${TEST_NAME} PROPERTY
@ -114,5 +131,5 @@ endforeach()
addtest_variants("CXXExceptions" "CXXException.m;CXXException.cc" true)
addtest_variants("ForwardDeclareProtocolAccess" "ForwardDeclareProtocolAccess.m;ForwardDeclareProtocol.m" true)
if (ENABLE_OBJCXX)
addtest_variants(ObjCXXEHInterop "ObjCXXEHInterop.mm;ObjCXXEHInterop.m" true)
addtest_variants(ObjCXXEHInterop "ObjCXXEHInterop.mm;ObjCXXEHInterop.m" true)
endif()

@ -4,8 +4,6 @@
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
static BOOL methodCalled = NO;

@ -26,6 +26,7 @@ int main(void)
assert(x == e1);
@try {
a = e2;
@throw a;
}
@catch (id y)
{

@ -39,7 +39,7 @@ int main()
assert(strcmp(property_getAttributes(property), "Ti,VvarName") == 0);
free(properties);
objc_property_t *clsproperties = class_copyPropertyList(object_getClass([helloclass class]), &outCount);
properties = class_copyPropertyList(object_getClass([helloclass class]), &outCount);
assert(outCount == 1);
property = properties[0];
assert(strcmp(property_getName(property), "clsProp") == 0);

@ -1,7 +1,11 @@
#include "Test.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifdef _WIN32
# define sleep Sleep
#else
# include <unistd.h>
#endif
static int exitStatus = 0;
@ -125,10 +129,11 @@ id exceptionObj = @"Exception";
@catch (id e)
{
test(e == exceptionObj);
return YES;
}
@finally
@catch(...)
{
return YES;
return NO;
}
return NO;
}

@ -10,7 +10,6 @@
//#define assert(x) if (!(x)) { printf("Failed %d\n", __LINE__); }
id objc_msgSend(id, SEL, ...);
typedef struct { int a,b,c,d,e; } s;
@interface Fake
@ -81,13 +80,14 @@ __attribute__((objc_root_class))
+ (void)printf: (const char*)str, ...
{
va_list ap;
char *s;
char s[100];
va_start(ap, str);
vasprintf(&s, str, ap);
vsnprintf(&s, 100, str, ap);
va_end(ap);
//fprintf(stderr, "String: '%s'\n", s);
fprintf(stderr, "String: '%s'\n", s);
vfprintf(stderr, s, ap);
assert(strcmp(s, "Format string 42 42.000000\n") ==0);
}
+ (void)initialize
@ -174,6 +174,7 @@ struct objc_slot *forward_slot(id o, SEL s)
}
int main(void)
{
__objc_msg_forward2 = forward;

@ -24,4 +24,4 @@
*/
#include "objc/runtime.h"
Class alias_getClass(const char *alias_name);
PUBLIC Class alias_getClass(const char *alias_name);

@ -77,7 +77,7 @@ static Alias alias_table_get_safe(const char *alias_name)
}
Class alias_getClass(const char *alias_name)
PUBLIC Class alias_getClass(const char *alias_name)
{
if (NULL == alias_name)
{
@ -99,7 +99,7 @@ PRIVATE void alias_table_insert(Alias alias)
alias_table_internal_insert(alias_table, alias);
}
BOOL class_registerAlias_np(Class class, const char *alias)
PUBLIC BOOL class_registerAlias_np(Class class, const char *alias)
{
if ((NULL == alias) || (NULL == class))
{

58
arc.m

@ -212,14 +212,14 @@ static const long weak_mask = ((size_t)1)<<((sizeof(size_t)*8)-1);
*/
static const long refcount_mask = ~weak_mask;
size_t object_getRetainCount_np(id obj)
PUBLIC size_t object_getRetainCount_np(id obj)
{
uintptr_t *refCount = ((uintptr_t*)obj) - 1;
uintptr_t refCountVal = __sync_fetch_and_add(refCount, 0);
return (((size_t)refCountVal) & refcount_mask) + 1;
}
id objc_retain_fast_np(id obj)
PUBLIC id objc_retain_fast_np(id obj)
{
uintptr_t *refCount = ((uintptr_t*)obj) - 1;
uintptr_t refCountVal = __sync_fetch_and_add(refCount, 0);
@ -292,7 +292,7 @@ static inline id retain(id obj)
return [obj retain];
}
BOOL objc_release_fast_no_destroy_np(id obj)
PUBLIC BOOL objc_release_fast_no_destroy_np(id obj)
{
uintptr_t *refCount = ((uintptr_t*)obj) - 1;
uintptr_t refCountVal = __sync_fetch_and_add(refCount, 0);
@ -330,7 +330,7 @@ BOOL objc_release_fast_no_destroy_np(id obj)
return NO;
}
void objc_release_fast_np(id obj)
PUBLIC void objc_release_fast_np(id obj)
{
if (objc_release_fast_no_destroy_np(obj))
{
@ -420,7 +420,7 @@ static inline id autorelease(id obj)
return [obj autorelease];
}
unsigned long objc_arc_autorelease_count_np(void)
PUBLIC unsigned long objc_arc_autorelease_count_np(void)
{
struct arc_tls* tls = getARCThreadData();
unsigned long count = 0;
@ -434,7 +434,7 @@ unsigned long objc_arc_autorelease_count_np(void)
}
return count;
}
unsigned long objc_arc_autorelease_count_for_object_np(id obj)
PUBLIC unsigned long objc_arc_autorelease_count_for_object_np(id obj)
{
struct arc_tls* tls = getARCThreadData();
unsigned long count = 0;
@ -488,7 +488,7 @@ void *objc_autoreleasePoolPush(void)
if (0 == NewAutoreleasePool) { return NULL; }
return NewAutoreleasePool(AutoreleasePool, SELECTOR(new));
}
void objc_autoreleasePoolPop(void *pool)
PUBLIC void objc_autoreleasePoolPop(void *pool)
{
if (useARCAutoreleasePool)
{
@ -511,7 +511,7 @@ void objc_autoreleasePoolPop(void *pool)
}
}
id objc_autorelease(id obj)
PUBLIC id objc_autorelease(id obj)
{
if (nil != obj)
{
@ -520,7 +520,7 @@ id objc_autorelease(id obj)
return obj;
}
id objc_autoreleaseReturnValue(id obj)
PUBLIC id objc_autoreleaseReturnValue(id obj)
{
if (!useARCAutoreleasePool)
{
@ -535,7 +535,7 @@ id objc_autoreleaseReturnValue(id obj)
return objc_autorelease(obj);
}
id objc_retainAutoreleasedReturnValue(id obj)
PUBLIC id objc_retainAutoreleasedReturnValue(id obj)
{
// If the previous object was released with objc_autoreleaseReturnValue()
// just before return, then it will not have actually been autoreleased.
@ -567,36 +567,36 @@ id objc_retainAutoreleasedReturnValue(id obj)
return objc_retain(obj);
}
id objc_retain(id obj)
PUBLIC id objc_retain(id obj)
{
if (nil == obj) { return nil; }
return retain(obj);
}
id objc_retainAutorelease(id obj)
PUBLIC id objc_retainAutorelease(id obj)
{
return objc_autorelease(objc_retain(obj));
}
id objc_retainAutoreleaseReturnValue(id obj)
PUBLIC id objc_retainAutoreleaseReturnValue(id obj)
{
if (nil == obj) { return obj; }
return objc_autoreleaseReturnValue(retain(obj));
}
id objc_retainBlock(id b)
PUBLIC id objc_retainBlock(id b)
{
return _Block_copy(b);
}
void objc_release(id obj)
PUBLIC void objc_release(id obj)
{
if (nil == obj) { return; }
release(obj);
}
id objc_storeStrong(id *addr, id value)
PUBLIC id objc_storeStrong(id *addr, id value)
{
value = objc_retain(value);
id oldValue = *addr;
@ -697,7 +697,7 @@ static inline BOOL weakRefRelease(WeakRef *ref)
void* block_load_weak(void *block);
id objc_storeWeak(id *addr, id obj)
PUBLIC id objc_storeWeak(id *addr, id obj)
{
LOCK_FOR_SCOPE(&weakRefLock);
WeakRef *oldRef;
@ -787,7 +787,7 @@ id objc_storeWeak(id *addr, id obj)
return obj;
}
BOOL objc_delete_weak_refs(id obj)
PUBLIC BOOL objc_delete_weak_refs(id obj)
{
LOCK_FOR_SCOPE(&weakRefLock);
if (objc_test_class_flag(classForObject(obj), objc_class_flag_fast_arc))
@ -797,7 +797,7 @@ BOOL objc_delete_weak_refs(id obj)
// have done so in between this thread's decrementing the reference
// count and its acquiring the lock. In this case, report failure.
uintptr_t *refCount = ((uintptr_t*)obj) - 1;
if ((long)((__sync_fetch_and_add(refCount, 0) & refcount_mask)) < 0)
if ((long)((__sync_fetch_and_add(refCount, 0) & refcount_mask)) >= 0)
{
return NO;
}
@ -805,13 +805,15 @@ BOOL objc_delete_weak_refs(id obj)
WeakRef *oldRef = weak_ref_table_get(weakRefs, obj);
if (0 != oldRef)
{
// Zero the object pointer. This prevents any other weak
// accesses from loading from this.
oldRef->obj = nil;
// The address of obj is likely to be reused, so remove it from
// the table so that we don't accidentally alias weak
// references
weak_ref_remove(weakRefs, obj);
// Zero the object pointer. This prevents any other weak
// accesses from loading from this. This must be done after
// removing the ref from the table, because the compare operation
// tests the obj field.
oldRef->obj = nil;
// If the weak reference count is zero, then we should have
// already removed this.
assert(oldRef->weak_count > 0);
@ -819,7 +821,7 @@ BOOL objc_delete_weak_refs(id obj)
return YES;
}
id objc_loadWeakRetained(id* addr)
PUBLIC id objc_loadWeakRetained(id* addr)
{
LOCK_FOR_SCOPE(&weakRefLock);
id obj;
@ -857,12 +859,12 @@ id objc_loadWeakRetained(id* addr)
return objc_retain(obj);
}
id objc_loadWeak(id* object)
PUBLIC id objc_loadWeak(id* object)
{
return objc_autorelease(objc_loadWeakRetained(object));
}
void objc_copyWeak(id *dest, id *src)
PUBLIC void objc_copyWeak(id *dest, id *src)
{
// Don't retain or release. While the weak ref lock is held, we know that
// the object can't be deallocated, so we just move the value and update
@ -884,7 +886,7 @@ void objc_copyWeak(id *dest, id *src)
}
}
void objc_moveWeak(id *dest, id *src)
PUBLIC void objc_moveWeak(id *dest, id *src)
{
// Don't retain or release. While the weak ref lock is held, we know that
// the object can't be deallocated, so we just move the value and update
@ -902,12 +904,12 @@ void objc_moveWeak(id *dest, id *src)
}
}
void objc_destroyWeak(id* obj)
PUBLIC void objc_destroyWeak(id* obj)
{
objc_storeWeak(obj, nil);
}
id objc_initWeak(id *object, id value)
PUBLIC id objc_initWeak(id *object, id value)
{
*object = nil;
return objc_storeWeak(object, value);

@ -4,6 +4,13 @@
#define SHIFT_OFFSET 0
#define DATA_OFFSET 8
#define SLOT_OFFSET 0
#elif defined(_WIN64)
// long is 32 bits on Win64, so struct objc_class is smaller. All other offsets are the same.
#define DTABLE_OFFSET 56
#define SMALLOBJ_BITS 3
#define SHIFT_OFFSET 0
#define DATA_OFFSET 8
#define SLOT_OFFSET 0
#else
#define DTABLE_OFFSET 32
#define SMALLOBJ_BITS 1

@ -388,6 +388,7 @@ PRIVATE void gc_setTypeForClass(Class cls, void *type)
list->gc_type = type;
}
PUBLIC
int objc_sync_enter(id object)
{
if ((object == 0) || isSmallObject(object)) { return 0; }
@ -396,6 +397,7 @@ int objc_sync_enter(id object)
return 0;
}
PUBLIC
int objc_sync_exit(id object)
{
if ((object == 0) || isSmallObject(object)) { return 0; }

@ -8,9 +8,11 @@
#include <string.h>
#include <assert.h>
#include <ctype.h>
#ifndef _WIN32
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#endif
#include "objc/runtime.h"
#include "objc/blocks_runtime.h"
#include "blocks_runtime.h"
@ -108,7 +110,12 @@ static id invalid(id self, SEL _cmd)
static struct trampoline_set *alloc_trampolines(char *start, char *end)
{
struct trampoline_set *metadata = calloc(1, sizeof(struct trampoline_set));
metadata->buffers = valloc(sizeof(struct trampoline_buffers));
metadata->buffers =
#ifdef _WIN32
VirtualAlloc(NULL, sizeof(struct trampoline_buffers), MEM_COMMIT, PAGE_READWRITE);
#else
valloc(sizeof(struct trampoline_buffers));
#endif
for (int i=0 ; i<HEADERS_PER_PAGE ; i++)
{
metadata->buffers->headers[i].fnptr = (void(*)(void))invalid;
@ -117,7 +124,12 @@ static struct trampoline_set *alloc_trampolines(char *start, char *end)
memcpy(block, start, end-start);
}
metadata->buffers->headers[HEADERS_PER_PAGE-1].block = NULL;
#ifdef _WIN32
DWORD ignored;
VirtualProtect(metadata->buffers->rx_buffer, PAGE_SIZE, PAGE_EXECUTE_READ, &ignored);
#else
mprotect(metadata->buffers->rx_buffer, PAGE_SIZE, PROT_READ | PROT_EXEC);
#endif
clear_cache(metadata->buffers->rx_buffer, &metadata->buffers->rx_buffer[PAGE_SIZE]);
return metadata;
}

@ -42,7 +42,7 @@ static void *_HeapBlockByRef = (void*)1;
/**
* Returns the Objective-C type encoding for the block.
*/
const char *block_getType_np(const void *b)
PUBLIC const char *block_getType_np(const void *b)
{
const struct Block_layout *block = b;
if ((NULL == block) || !(block->flags & BLOCK_HAS_SIGNATURE))
@ -111,7 +111,7 @@ static int cas(void *ptr, void *old, void *new)
* the other choices which are mutually exclusive. Only in a Block copy helper
* will one see BLOCK_FIELD_IS_BYREF.
*/
void _Block_object_assign(void *destAddr, const void *object, const int flags)
PUBLIC void _Block_object_assign(void *destAddr, const void *object, const int flags)
{
//printf("Copying %x to %x with flags %x\n", object, destAddr, flags);
// FIXME: Needs to be implemented
@ -190,7 +190,7 @@ void _Block_object_assign(void *destAddr, const void *object, const int flags)
* The same flags used in the copy helper should be used for each call
* generated to this function:
*/
void _Block_object_dispose(const void *object, const int flags)
PUBLIC void _Block_object_dispose(const void *object, const int flags)
{
// FIXME: Needs to be implemented
//if(flags & BLOCK_FIELD_IS_WEAK)
@ -235,7 +235,7 @@ void _Block_object_dispose(const void *object, const int flags)
// Copy a block to the heap if it's still on the stack or increments its retain count.
void *_Block_copy(const void *src)
PUBLIC void *_Block_copy(const void *src)
{
if (NULL == src) { return NULL; }
struct Block_layout *self = (struct Block_layout*)src;
@ -269,7 +269,7 @@ void *_Block_copy(const void *src)
}
// Release a block and frees the memory when the retain count hits zero.
void _Block_release(const void *src)
PUBLIC void _Block_release(const void *src)
{
if (NULL == src) { return; }
struct Block_layout *self = (struct Block_layout*)src;

@ -34,7 +34,7 @@ static const int32_t caps =
#endif
0;
int objc_test_capability(int x)
PUBLIC int objc_test_capability(int x)
{
if (x >= 32) { return 0; }
if (caps & (1<<x)) { return 1; }

@ -46,7 +46,9 @@ static inline int classHasInstalledDtable(struct objc_class *cls)
return (cls->dtable != uninstalled_dtable);
}
PUBLIC
int objc_sync_enter(id object);
PUBLIC
int objc_sync_exit(id object);
/**
* Returns the dtable for a given class. If we are currently in an +initialize

@ -6,6 +6,11 @@
#include "objc/runtime.h"
#include "visibility.h"
#include <windows.h>
#define RtlAddGrowableFunctionTable ClangIsConfusedByTypedefReturnTypes
#include <rtlsupportapi.h>
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
@ -24,33 +29,32 @@ struct _MSVC_TypeDescriptor
struct _MSVC_CatchableType
{
unsigned int flags;
_MSVC_TypeDescriptor* type;
unsigned long type;
int mdisp;
int pdisp;
int vdisp;
int size;
void* copyFunction;
unsigned long copyFunction;
};
struct _MSVC_CatchableTypeArray
{
int count;
_MSVC_CatchableType* types[0];
unsigned long types[0];
};
struct _MSVC_ThrowInfo
{
unsigned int attributes;
void* pfnUnwind;
void* pfnForwardCompat;
_MSVC_CatchableTypeArray* pCatchableTypeArray;
unsigned long pfnUnwind;
unsigned long pfnForwardCompat;
unsigned long pCatchableTypeArray;
};
#if defined(_WIN64)
extern "C" int __ImageBase;
#define IMAGE_RELATIVE(ptr) ((decltype(ptr))(ptr ? ((uintptr_t)ptr - (uintptr_t)&__ImageBase) : (uintptr_t)nullptr))
#define IMAGE_RELATIVE(ptr, base) (static_cast<unsigned long>((ptr ? ((uintptr_t)ptr - (uintptr_t)base) : (uintptr_t)nullptr)))
#else
#define IMAGE_RELATIVE(ptr) (ptr)
#define IMAGE_RELATIVE(ptr, base) reinterpret_cast<unsigned long>((ptr))
#endif
extern "C" void __stdcall _CxxThrowException(void*, _MSVC_ThrowInfo*);
@ -60,8 +64,11 @@ namespace
static std::string mangleObjcObject()
{
// This mangled name doesn't vary based on bitness.
#if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8
return ".PEAUobjc_object@@";
#else
return ".PAUobjc_object@@";
#endif
}
static std::string mangleStructNamed(const char* className)
@ -70,13 +77,15 @@ static std::string mangleStructNamed(const char* className)
// .PAUxxx@@ = ?? struct xxx * `RTTI Type Descriptor'
// 64-bit:
// .PEAUxxx@@ = ?? struct xxx * __ptr64 `RTTI Type Descriptor'
return
//return
auto r =
#if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8
std::string(".PEAU") +
#else
std::string(".PAU") +
#endif
className + "@@";
return r;
}
void fillCatchableType(_MSVC_CatchableType* exceptType)
@ -86,13 +95,18 @@ void fillCatchableType(_MSVC_CatchableType* exceptType)
exceptType->pdisp = -1;
exceptType->vdisp = 0;
exceptType->size = sizeof(id);
exceptType->copyFunction = nullptr;
exceptType->copyFunction = 0;
}
} // <anonymous-namespace>
struct X {};
PUBLIC extern "C" void objc_exception_rethrow(void* exc);
PUBLIC extern "C" void objc_exception_throw(id object)
{
// Base used for image-relative addresses.
char x;
// This is the base vtable for all RTTI entries
static const void* typeid_vtable = *(void**)&typeid(void *);
@ -118,7 +132,7 @@ PUBLIC extern "C" void objc_exception_throw(id object)
size_t typeCount = 1;
// Get count of all types in exception
for (Class cls = object_getClass(object); cls != nil; cls = class_getSuperclass(cls), ++typeCount)
for (Class cls = object_getClass(object); cls != Nil; cls = class_getSuperclass(cls), ++typeCount)
;
// Unfortunately we can't put this in a real function since the alloca has to be in this stack frame:
@ -134,37 +148,66 @@ PUBLIC extern "C" void objc_exception_throw(id object)
// Add exception type and all base types to throw information
size_t curTypeIndex = 0;
for (Class cls = object_getClass(object); cls != nil; cls = class_getSuperclass(cls))
for (Class cls = object_getClass(object); cls != Nil; cls = class_getSuperclass(cls))
{
auto exceptType = (_MSVC_CatchableType*)_alloca(sizeof(_MSVC_CatchableType));
fillCatchableType(exceptType);
auto mangledName = mangleStructNamed(class_getName(cls));
CREATE_TYPE_DESCRIPTOR(exceptType->type, mangledName);
exceptType->type = IMAGE_RELATIVE(exceptType->type);
exceptTypes->types[curTypeIndex++] = IMAGE_RELATIVE(exceptType);
_MSVC_TypeDescriptor *ty;
CREATE_TYPE_DESCRIPTOR(ty, mangledName);
exceptType->type = IMAGE_RELATIVE(ty, &x);
exceptTypes->types[curTypeIndex++] = IMAGE_RELATIVE(exceptType, &x);
}
// Add id (struct objc_object*)
auto exceptType = (_MSVC_CatchableType*)_alloca(sizeof(_MSVC_CatchableType));
fillCatchableType(exceptType);
auto idName = mangleObjcObject();
CREATE_TYPE_DESCRIPTOR(exceptType->type, idName);
exceptType->type = IMAGE_RELATIVE(exceptType->type);
exceptTypes->types[curTypeIndex++] = IMAGE_RELATIVE(exceptType);
_MSVC_TypeDescriptor *ty;
CREATE_TYPE_DESCRIPTOR(ty, idName);
exceptType->type = IMAGE_RELATIVE(ty, &x);
exceptTypes->types[curTypeIndex++] = IMAGE_RELATIVE(exceptType, &x);
_MSVC_ThrowInfo ti = {
0, // attributes
NULL, // pfnUnwind
NULL, // pfnForwardCompat
IMAGE_RELATIVE(exceptTypes) // pCatchableTypeArray
0, // pfnUnwind
0, // pfnForwardCompat
IMAGE_RELATIVE(exceptTypes, &x) // pCatchableTypeArray
};
_CxxThrowException(&object, &ti);
# define EH_EXCEPTION_NUMBER ('msc' | 0xE0000000)
# define EH_MAGIC_NUMBER1 0x19930520
# define EXCEPTION_NONCONTINUABLE 0x1
EXCEPTION_RECORD exception;
exception.ExceptionCode = EH_EXCEPTION_NUMBER;
exception.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
exception.ExceptionRecord = nullptr;
exception.ExceptionAddress = nullptr;
exception.NumberParameters = 4;
exception.ExceptionInformation[0] = EH_MAGIC_NUMBER1;
exception.ExceptionInformation[1] = reinterpret_cast<ULONG_PTR>(&object);
exception.ExceptionInformation[2] = reinterpret_cast<ULONG_PTR>(&ti);
exception.ExceptionInformation[3] = reinterpret_cast<ULONG_PTR>(&x);
RtlRaiseException(&exception);
__builtin_unreachable();
}
PUBLIC extern "C" void objc_exception_rethrow(void* exc)
{
_CxxThrowException(nullptr, nullptr);
__builtin_unreachable();
}
// DO NOT COMMIT THIS!
// It's just here to get things to build while I work on EH support
PUBLIC extern "C" void *objc_begin_catch(void* exc)
{
return exc;
}
PUBLIC extern "C" void *objc_end_catch(void* exc)
{
return exc;
}

@ -8,6 +8,10 @@
#include "method.h"
#include "visibility.h"
#ifdef max
# undef max
#endif
size_t objc_alignof_type (const char *type);
// It would be so nice if this works, but in fact it returns nonsense:

@ -18,7 +18,6 @@
* which has a static size.
*/
#include "lock.h"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

@ -165,7 +165,10 @@ struct objc_init
struct nsstr *strings_end;
};
// end: objc_init
#ifdef DEBUG_LOADING
#include <dlfcn.h>
#endif
static enum {
LegacyABI,
@ -175,7 +178,7 @@ static enum {
void registerProtocol(Protocol *proto);
void __objc_load(struct objc_init *init)
PUBLIC void __objc_load(struct objc_init *init)
{
init_runtime();
#ifdef DEBUG_LOADING
@ -293,7 +296,7 @@ void __objc_load(struct objc_init *init)
}
#ifdef OLDABI_COMPAT
void __objc_exec_class(struct objc_module_abi_8 *module)
PUBLIC void __objc_exec_class(struct objc_module_abi_8 *module)
{
init_runtime();

@ -2,6 +2,7 @@
#pragma clang system_header
#endif
#include "objc-visibility.h"
#ifdef STRICT_MACOS_X
# define OBJC_NONPORTABLE __attribute__((error("Function not supported by the Apple runtime")))

@ -13,9 +13,9 @@
#define BLOCKS_EXPORT extern
#endif
BLOCKS_EXPORT void *_Block_copy(const void *);
BLOCKS_EXPORT void _Block_release(const void *);
BLOCKS_EXPORT const char *block_getType_np(const void *b) OBJC_NONPORTABLE;
PUBLIC BLOCKS_EXPORT void *_Block_copy(const void *);
PUBLIC BLOCKS_EXPORT void _Block_release(const void *);
PUBLIC BLOCKS_EXPORT const char *block_getType_np(const void *b) OBJC_NONPORTABLE;
#define Block_copy(x) ((__typeof(x))_Block_copy((const void *)(x)))
#define Block_release(x) _Block_release((const void *)(x))

@ -136,6 +136,7 @@ extern "C" {
* Run time feature test. This function returns 1 if the runtime supports the
* specified feature or 0 if it does not.
*/
PUBLIC
int objc_test_capability(int x) OBJC_NONPORTABLE;
#ifdef __cplusplus
}

@ -1,6 +1,7 @@
#if defined(__clang__) && !defined(__OBJC_RUNTIME_INTERNAL__)
#pragma clang system_header
#endif
#include "objc-visibility.h"
#ifdef __cplusplus
extern "C" {
@ -13,7 +14,7 @@ extern "C" {
#ifndef OBJC_HOOK
#define OBJC_HOOK extern
#define OBJC_HOOK PUBLIC extern
#endif
struct objc_category;
/**
@ -34,17 +35,17 @@ OBJC_HOOK void (*_objc_load_callback)(Class cls, struct objc_category *category)
* The hook used for fast proxy lookups. This takes an object and a selector
* and returns the instance that the message should be forwarded to.
*/
extern id (*objc_proxy_lookup)(id receiver, SEL op);
OBJC_HOOK id (*objc_proxy_lookup)(id receiver, SEL op);
/**
* New runtime forwarding hook. This is no longer used, but is retained to
* prevent errors at link time.
*/
extern struct objc_slot *(*__objc_msg_forward3)(id, SEL) OBJC_DEPRECATED;
OBJC_HOOK struct objc_slot *(*__objc_msg_forward3)(id, SEL) OBJC_DEPRECATED;
/**
* Forwarding hook. Takes an object and a selector and returns a method that
* handles the forwarding.
*/
extern IMP (*__objc_msg_forward2)(id, SEL);
OBJC_HOOK IMP (*__objc_msg_forward2)(id, SEL);
/**
* Hook defined for handling unhandled exceptions. If the unwind library
* reaches the end of the stack without finding a handler then this hook is
@ -66,7 +67,7 @@ OBJC_HOOK Class (*_objc_class_for_boxing_foreign_exception)(int64_t exceptionCla
* receiver. This should return the slot to use instead, although it may throw
* an exception or perform some other action.
*/
extern IMP (*_objc_selector_type_mismatch2)(Class cls,
OBJC_HOOK IMP (*_objc_selector_type_mismatch2)(Class cls,
SEL selector, struct objc_slot2 *result);
/**
* Legacy hook for when selector types do not match. This is only called
@ -108,7 +109,7 @@ typedef IMP (*objc_tracing_hook)(id, SEL, IMP, int, void*);
/**
* Registers a tracing hook for a specified selector.
*/
int objc_registerTracingHook(SEL, objc_tracing_hook);
PUBLIC int objc_registerTracingHook(SEL, objc_tracing_hook);
#ifdef __cplusplus
}

@ -1,6 +1,7 @@
#if defined(__clang__)
#pragma clang system_header
#endif
#include "objc-visibility.h"
#ifndef _OBJC_MESSAGE_H_
#define _OBJC_MESSAGE_H_
@ -22,6 +23,7 @@
* systems even within the same architecture, so take great care if using this
* function for small (two integer) structures.
*/
PUBLIC
id objc_msgSend(id self, SEL _cmd, ...);
/**
* Standard message sending function. This function must be cast to the
@ -38,6 +40,7 @@ id objc_msgSend(id self, SEL _cmd, ...);
* architecture, so take great care if using this function for small (two
* integer) structures.
*/
PUBLIC
#ifdef __cplusplus
id objc_msgSend_stret(id self, SEL _cmd, ...);
#else
@ -55,6 +58,7 @@ void objc_msgSend_stret(id self, SEL _cmd, ...);
* This version of the function is used for all messages that return floating
* point values.
*/
PUBLIC
long double objc_msgSend_fpret(id self, SEL _cmd, ...);
#endif

@ -1,6 +1,7 @@
#if defined(__clang__) && !defined(__OBJC_RUNTIME_INTERNAL__)
#pragma clang system_header
#endif
#include "objc-visibility.h"
#ifndef __OBJC_ARC_INCLUDED__
#define __OBJC_ARC_INCLUDED__
@ -12,90 +13,90 @@ extern "C" {
/**
* Autoreleases the argument. Equivalent to [obj autorelease].
*/
id objc_autorelease(id obj);
PUBLIC id objc_autorelease(id obj);
/**
* Autoreleases a return value. This is equivalent to [obj autorelease], but
* may also store the object somewhere where it can be quickly removed without
* the need for any message sending.
*/
id objc_autoreleaseReturnValue(id obj);
PUBLIC id objc_autoreleaseReturnValue(id obj);
/**
* Initializes object as a weak pointer and stores value in it, or nil if value
* has already begun deallocation.
*/
id objc_initWeak(id *object, id value);
PUBLIC id objc_initWeak(id *object, id value);
/**
* Loads the object. Returns nil if the object stored at this address has
* already begun deallocation.
*/
id objc_loadWeak(id* object);
PUBLIC id objc_loadWeak(id* object);
/**
* Loads a weak value and retains it.
*/
id objc_loadWeakRetained(id* obj);
PUBLIC id objc_loadWeakRetained(id* obj);
/**
* Retains the argument. Equivalent to [obj retain].
*/
id objc_retain(id obj);
PUBLIC id objc_retain(id obj);
/**
* Retains the argument, assuming that the argument is a normal object and has
* its reference count managed by the runtime.
* This is intended to implement `-retain` in ARC-compatible root classes.
*/
id objc_retain_fast_np(id obj) OBJC_NONPORTABLE;
PUBLIC id objc_retain_fast_np(id obj) OBJC_NONPORTABLE;
/**
* Retains and autoreleases an object. Equivalent to [[obj retain] autorelease].
*/
id objc_retainAutorelease(id obj);
PUBLIC id objc_retainAutorelease(id obj);
/**
* Retains and releases a return value. Equivalent to
* objc_retain(objc_autoreleaseReturnValue(obj)).
*/
id objc_retainAutoreleaseReturnValue(id obj);
PUBLIC id objc_retainAutoreleaseReturnValue(id obj);
/**
* Retains a return value that has previously been autoreleased and returned.
* This is equivalent to objc_retainAutoreleaseReturnValue(), but may support a
* fast path, skipping the autorelease pool entirely.
*/
id objc_retainAutoreleasedReturnValue(id obj);
PUBLIC id objc_retainAutoreleasedReturnValue(id obj);
/**
* Retains a block.
*/
id objc_retainBlock(id b);
PUBLIC id objc_retainBlock(id b);
/**
* Stores value in addr. This first retains value, then releases the old value
* at addr, and stores the retained value in the address.
*/
id objc_storeStrong(id *addr, id value);
PUBLIC id objc_storeStrong(id *addr, id value);
/**
* Stores obj in zeroing weak pointer addr. If obj has begun deallocation,
* then this stores nil.
*/
id objc_storeWeak(id *addr, id obj);
PUBLIC id objc_storeWeak(id *addr, id obj);
/**
* Allocates an autorelease pool and pushes it onto the top of the autorelease
* pool stack. Note that the returned autorelease pool is not required to be
* an object.
*/
void *objc_autoreleasePoolPush(void);
PUBLIC void *objc_autoreleasePoolPush(void);
/**
* Pops the specified autorelease pool from the stack, sending release messages
* to every object that has been autreleased since the pool was created.
*/
void objc_autoreleasePoolPop(void *pool);
PUBLIC void objc_autoreleasePoolPop(void *pool);
/**
* Initializes dest as a weak pointer and stores the value stored in src into
* it.
*/
void objc_copyWeak(id *dest, id *src);
PUBLIC void objc_copyWeak(id *dest, id *src);
/**
* Destroys addr as a weak pointer.
*/
void objc_destroyWeak(id* addr);
PUBLIC void objc_destroyWeak(id* addr);
/**
* Equivalent to objc_copyWeak(), but may also set src to nil.
*/
void objc_moveWeak(id *dest, id *src);
PUBLIC void objc_moveWeak(id *dest, id *src);
/**
* Releases the argument, assuming that the argument is a normal object and has
* its reference count managed by the runtime. If the retain count reaches
@ -105,7 +106,7 @@ void objc_moveWeak(id *dest, id *src);
* This is intended to implement `-release` in ARC-compatible root
* classes.
*/
void objc_release_fast_np(id obj) OBJC_NONPORTABLE;
PUBLIC void objc_release_fast_np(id obj) OBJC_NONPORTABLE;
/**
* Releases the argument, assuming that the argument is a normal object and has
* its reference count managed by the runtime. If the retain count reaches
@ -115,15 +116,15 @@ void objc_release_fast_np(id obj) OBJC_NONPORTABLE;
* This is intended to implement `NSDecrementExtraRefCountWasZero` for use with
* ARC-compatible classes.
*/
BOOL objc_release_fast_no_destroy_np(id obj) OBJC_NONPORTABLE;
PUBLIC BOOL objc_release_fast_no_destroy_np(id obj) OBJC_NONPORTABLE;
/**
* Returns the retain count of an object.
*/
size_t object_getRetainCount_np(id obj) OBJC_NONPORTABLE;
PUBLIC size_t object_getRetainCount_np(id obj) OBJC_NONPORTABLE;
/**
* Releases an object. Equivalent to [obj release].
*/
void objc_release(id obj);
PUBLIC void objc_release(id obj);
/**
* Mark the object as about to begin deallocation. All subsequent reads of
* weak pointers will return 0. This function should be called in -release,
@ -133,16 +134,16 @@ void objc_release(id obj);
*
* Nonstandard extension.
*/
BOOL objc_delete_weak_refs(id obj);
PUBLIC BOOL objc_delete_weak_refs(id obj);
/**
* Returns the total number of objects in the ARC-managed autorelease pool.
*/
unsigned long objc_arc_autorelease_count_np(void);
PUBLIC unsigned long objc_arc_autorelease_count_np(void);
/**
* Returns the total number of times that an object has been autoreleased in
* this thread.
*/
unsigned long objc_arc_autorelease_count_for_object_np(id);
PUBLIC unsigned long objc_arc_autorelease_count_for_object_np(id);
#ifdef __cplusplus
}

@ -1,6 +1,7 @@
#if defined(__clang__) && !defined(__OBJC_RUNTIME_INTERNAL__)
#pragma clang system_header
#endif
#include "objc-visibility.h"
#ifndef __LIBOBJC_RUNTIME_H_INCLUDED__
#define __LIBOBJC_RUNTIME_H_INCLUDED__
@ -124,7 +125,7 @@ typedef struct objc_method *Method;
# ifdef STRICT_APPLE_COMPATIBILITY
typedef signed char BOOL;
# else
# ifdef __vxworks
# if defined(__vxworks) || defined(_WIN32)
typedef int BOOL;
# else
typedef unsigned char BOOL;
@ -224,6 +225,7 @@ typedef struct
* registered by the runtime. The alignment must be the base-2 logarithm of
* the alignment requirement and the types should be an Objective-C type encoding.
*/
PUBLIC
BOOL class_addIvar(Class cls,
const char *name,
size_t size,
@ -233,11 +235,13 @@ BOOL class_addIvar(Class cls,
/**
* Adds a method to the class.
*/
PUBLIC
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);
/**
* Adds a protocol to the class.
*/
PUBLIC
BOOL class_addProtocol(Class cls, Protocol *protocol);
/**
@ -245,6 +249,7 @@ BOOL class_addProtocol(Class cls, Protocol *protocol);
* name are regarded as equivalent, even if they have different methods. This
* behaviour will change in a future version.
*/
PUBLIC
BOOL class_conformsToProtocol(Class cls, Protocol *protocol);
/**
@ -252,6 +257,7 @@ BOOL class_conformsToProtocol(Class cls, Protocol *protocol);
* the outCount argument is set to the number of instance variables returned.
* The caller is responsible for freeing the returned buffer.
*/
PUBLIC
Ivar* class_copyIvarList(Class cls, unsigned int *outCount);
/**
@ -259,6 +265,7 @@ Ivar* class_copyIvarList(Class cls, unsigned int *outCount);
* outCount argument is set to the number of methods returned. The caller is
* responsible for freeing the returned buffer.
*/
PUBLIC
Method * class_copyMethodList(Class cls, unsigned int *outCount);
/**
@ -266,6 +273,7 @@ Method * class_copyMethodList(Class cls, unsigned int *outCount);
* the outCount argument is set to the number of declared properties returned.
* The caller is responsible for freeing the returned buffer.
*/
PUBLIC
objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount);
/**
@ -273,11 +281,13 @@ objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount);
* outCount argument is set to the number of protocols returned. The caller is
* responsible for freeing the returned buffer.
*/
PUBLIC
Protocol *__unsafe_unretained* class_copyProtocolList(Class cls, unsigned int *outCount);
/**
* Creates an instance of this class, allocating memory using malloc.
*/
PUBLIC
id class_createInstance(Class cls, size_t extraBytes);
/**
@ -285,6 +295,7 @@ id class_createInstance(Class cls, size_t extraBytes);
* class. This is an opaque data type and must be accessed with the method_*()
* family of functions.
*/
PUBLIC
Method class_getClassMethod(Class aClass, SEL aSelector);
/**
@ -292,6 +303,7 @@ Method class_getClassMethod(Class aClass, SEL aSelector);
* this class. This is an opaque data type and must be accessed with the
* ivar_*() family of functions.
*/
PUBLIC
Ivar class_getClassVariable(Class cls, const char* name);
/**
@ -299,6 +311,7 @@ Ivar class_getClassVariable(Class cls, const char* name);
* in this class. This is an opaque data type and must be accessed with the
* method_*() family of functions.
*/
PUBLIC
Method class_getInstanceMethod(Class aClass, SEL aSelector);
/**
@ -306,6 +319,7 @@ Method class_getInstanceMethod(Class aClass, SEL aSelector);
* class's superclasses must be loaded before this call, or the result is
* undefined with the non-fragile ABI.
*/
PUBLIC
size_t class_getInstanceSize(Class cls);
/**
@ -313,22 +327,26 @@ size_t class_getInstanceSize(Class cls);
* returning a pointer to the instance variable definition or a null
* pointer if no instance variable of that name was found.
*/
PUBLIC
Ivar class_getInstanceVariable(Class cls, const char* name);
/**
* Sets the object value of a specified instance variable.
*/
PUBLIC
void object_setIvar(id object, Ivar ivar, id value);
/**
* Sets a named instance variable to the value specified by *value. Note that
* the instance variable must be a pointer-sized quantity.
*/
PUBLIC
Ivar object_setInstanceVariable(id obj, const char *name, void *value);
/**
* Returns the value of the named instance variable. This should not be used
* with instance variables that are not pointers.
*/
PUBLIC
id object_getIvar(id object, Ivar ivar);
/**
@ -337,6 +355,7 @@ id object_getIvar(id object, Ivar ivar);
*
* Note that the instance variable must be a pointer-sized quantity.
*/
PUBLIC
Ivar object_getInstanceVariable(id obj, const char *name, void **outValue);
/**
@ -344,54 +363,62 @@ Ivar object_getInstanceVariable(id obj, const char *name, void **outValue);
* the receiver does not have a method corresponding to this message then this
* function may return a runtime function that performs forwarding.
*/
PUBLIC
IMP class_getMethodImplementation(Class cls, SEL name);
/**
* Identical to class_getMethodImplementation().
*/
PUBLIC
IMP class_getMethodImplementation_stret(Class cls, SEL name);
/**
* Returns the name of the class. This string is owned by the runtime and is
* valid for (at least) as long as the class remains loaded.
*/
PUBLIC
const char * class_getName(Class cls);
/**
* Retrieves metadata about the property with the specified name.
*/
PUBLIC
objc_property_t class_getProperty(Class cls, const char *name);
/**
* Returns the superclass of the specified class.
*/
PUBLIC
Class class_getSuperclass(Class cls);
/**
* Returns the version of the class. Currently, the class version is not used
* inside the runtime at all, however it may be used for the developer-mode ABI.
*/
PUBLIC
int class_getVersion(Class theClass);
/**
* Sets the version for this class.
*/
PUBLIC
void class_setVersion(Class theClass, int version);
OBJC_GNUSTEP_RUNTIME_UNSUPPORTED("Weak instance variables")
PUBLIC OBJC_GNUSTEP_RUNTIME_UNSUPPORTED("Weak instance variables")
const char *class_getWeakIvarLayout(Class cls);
/**
* Returns whether the class is a metaclass. This can be used in conjunction
* with object_getClass() for differentiating between objects and classes.
*/
PUBLIC
BOOL class_isMetaClass(Class cls);
/**
* Registers an alias for the class. Returns YES if the alias could be
* registered successfully.
*/
OBJC_NONPORTABLE
PUBLIC OBJC_NONPORTABLE
BOOL class_registerAlias_np(Class cls, const char *alias);
/**
@ -399,6 +426,7 @@ BOOL class_registerAlias_np(Class cls, const char *alias);
* Objective-C runtime uses typed selectors, however the types of the selector
* will be ignored and a new selector registered with the specified types.
*/
PUBLIC
IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types);
/**
@ -407,17 +435,20 @@ IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types);
* or more of the various forwarding mechanisms, then this will still return
* NO.
*/
PUBLIC
BOOL class_respondsToSelector(Class cls, SEL sel);
/**
* Returns the instance variable layout of this class as an opaque list that
* can be applied to other classes.
*/
PUBLIC
const char *class_getIvarLayout(Class cls);
/**
* Sets the class's instance variable layout. The layout argument must be a
* value returned by class_getIvarLayout().
*/
PUBLIC
void class_setIvarLayout(Class cls, const char *layout);
/**
@ -425,26 +456,29 @@ void class_setIvarLayout(Class cls, const char *layout);
* because modifying the superclass of a class at run time is a very complex
* operation and this function is almost always used incorrectly.
*/
__attribute__((deprecated))
PUBLIC __attribute__((deprecated))
Class class_setSuperclass(Class cls, Class newSuper);
OBJC_GNUSTEP_RUNTIME_UNSUPPORTED("Weak instance variables")
PUBLIC OBJC_GNUSTEP_RUNTIME_UNSUPPORTED("Weak instance variables")
void class_setWeakIvarLayout(Class cls, const char *layout);
/**
* Returns the name of an instance variable.
*/
PUBLIC
const char* ivar_getName(Ivar ivar);
/**
* Returns the offset of an instance variable. This value can be added to the
* object pointer to get the address of the instance variable.
*/
PUBLIC
ptrdiff_t ivar_getOffset(Ivar ivar);
/**
* Returns the Objective-C type encoding of the instance variable.
*/
PUBLIC
const char* ivar_getTypeEncoding(Ivar ivar);
/**
@ -453,12 +487,14 @@ const char* ivar_getTypeEncoding(Ivar ivar);
* Objective-C method will be the self and _cmd parameters, so the returned
* value will be "@" and ":" respectively.
*/
PUBLIC
char* method_copyArgumentType(Method method, unsigned int index);
/**
* Copies the type encoding of an argument of this method. The caller is
* responsible for freeing the returned C string.
*/
PUBLIC
char* method_copyReturnType(Method method);
/**
@ -466,6 +502,7 @@ char* method_copyReturnType(Method method);
* expensive on the GNUstep runtime and its use is discouraged. It is
* recommended that users call class_replaceMethod() instead.
*/
PUBLIC
void method_exchangeImplementations(Method m1, Method m2);
/**
@ -475,11 +512,13 @@ void method_exchangeImplementations(Method m1, Method m2);
* output string if there is enough space for the argument type and the NULL
* terminator. Its use is therefore discouraged.
*/
PUBLIC
void method_getArgumentType(Method method, unsigned int index, char *dst, size_t dst_len);
/**
* Returns a pointer to the function used to implement this method.
*/
PUBLIC
IMP method_getImplementation(Method method);
/**
@ -489,12 +528,14 @@ IMP method_getImplementation(Method method);
* although calling method_getTypeEncoding() is faster if you just require the
* types.
*/
PUBLIC
SEL method_getName(Method method);
/**
* Returns the number of arguments (including self and _cmd) that this method
* expects.
*/
PUBLIC
unsigned method_getNumberOfArguments(Method method);
/**
@ -504,6 +545,7 @@ unsigned method_getNumberOfArguments(Method method);
* output string if there is enough space for the argument type and the NULL
* terminator. Its use is therefore discouraged.
*/
PUBLIC
void method_getReturnType(Method method, char *dst, size_t dst_len);
/**
@ -511,6 +553,7 @@ void method_getReturnType(Method method, char *dst, size_t dst_len);
* runtime and will persist for (at least) as long as the class owning the
* method is loaded.
*/
PUBLIC
const char * method_getTypeEncoding(Method method);
/**
@ -518,6 +561,7 @@ const char * method_getTypeEncoding(Method method);
* expensive with the GNUstep runtime and its use is discouraged. It is
* recommended that you call class_replaceMethod() instead.
*/
PUBLIC
IMP method_setImplementation(Method method, IMP imp);
/**
@ -526,6 +570,7 @@ IMP method_setImplementation(Method method, IMP imp);
* used for class variables by adding instance variables to the returned
* metaclass.
*/
PUBLIC
Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);
/**
@ -533,6 +578,7 @@ Class objc_allocateClassPair(Class superclass, const char *name, size_t extraByt
* attempts to send messages to instances of this class or its subclasses
* result in undefined behaviour.
*/
PUBLIC
void objc_disposeClassPair(Class cls);
/**
@ -541,6 +587,7 @@ void objc_disposeClassPair(Class cls);
* loaded, it calls the _objc_lookup_class() callback to allow an external
* library to load the module providing this class.
*/
PUBLIC
id objc_getClass(const char *name);
/**
@ -549,18 +596,21 @@ id objc_getClass(const char *name);
* is 0, it returns the total number of classes registered with the runtime.
* Otherwise, it copies classes and returns the number copied.
*/
PUBLIC
int objc_getClassList(Class *buffer, int bufferLen);
/**
* Returns a copy of the list of all classes in the system. The caller is
* responsible for freeing this list. The number of classes is returned in the
* parameter.
*/
PUBLIC
Class *objc_copyClassList(unsigned int *outCount);
/**
* Returns the metaclass with the specified name. This is equivalent to
* calling object_getClass() on the result of objc_getClass().
*/
PUBLIC
id objc_getMetaClass(const char *name);
/**
@ -568,17 +618,20 @@ id objc_getMetaClass(const char *name);
* function should generally only be called early on in a program, to ensure
* that all required libraries are loaded.
*/
PUBLIC
id objc_getRequiredClass(const char *name);
/**
* Looks up the class with the specified name, but does not invoke any
* external lazy loading mechanisms.
*/
PUBLIC
id objc_lookUpClass(const char *name);
/**
* Returns the protocol with the specified name.
*/
PUBLIC
Protocol *objc_getProtocol(const char *name);
/**
* Allocates a new protocol. This returns NULL if a protocol with the same
@ -587,15 +640,18 @@ Protocol *objc_getProtocol(const char *name);
* Protocols are immutable after they have been registered, so may only be
* modified between calling this function and calling objc_registerProtocol().
*/
PUBLIC
Protocol *objc_allocateProtocol(const char *name);
/**
* Registers a protocol with the runtime. After this point, the protocol may
* not be modified.
*/
PUBLIC
void objc_registerProtocol(Protocol *proto);
/**
* Adds a method to the protocol.
*/
PUBLIC
void protocol_addMethodDescription(Protocol *aProtocol,
SEL name,
const char *types,
@ -604,10 +660,12 @@ void protocol_addMethodDescription(Protocol *aProtocol,
/**
* Adds a protocol to the protocol.
*/
PUBLIC
void protocol_addProtocol(Protocol *aProtocol, Protocol *addition);
/**
* Adds a property to the protocol.
*/
PUBLIC
void protocol_addProperty(Protocol *aProtocol,
const char *name,
const objc_property_attribute_t *attributes,
@ -622,6 +680,7 @@ void protocol_addProperty(Protocol *aProtocol,
* adding instance variables and methods to it. A class can not have instance
* variables added to it after objc_registerClassPair() has been called.
*/
PUBLIC
void objc_registerClassPair(Class cls);
/**
@ -629,6 +688,7 @@ void objc_registerClassPair(Class cls);
* object. This is a pointer to the storage specified with the extraBytes
* parameter given when allocating an object.
*/
PUBLIC
void *object_getIndexedIvars(id obj);
// FIXME: The GNU runtime has a version of this which omits the size parameter
@ -637,30 +697,35 @@ void *object_getIndexedIvars(id obj);
/**
* Free an object created with class_createInstance().
*/
PUBLIC
id object_dispose(id obj);
/**
* Returns the class of the object. Note: the isa pointer should not be
* accessed directly with the GNUstep runtime.
*/
PUBLIC
Class object_getClass(id obj);
/**
* Sets the class of the object. Note: the isa pointer should not be
* accessed directly with the GNUstep runtime.
*/
PUBLIC
Class object_setClass(id obj, Class cls);
/**
* Returns the name of the class of the object. This is equivalent to calling
* class_getName() on the result of object_getClass().
*/
PUBLIC
const char *object_getClassName(id obj);
/**
* Returns the name of a specified property.
*/
PUBLIC
const char *property_getName(objc_property_t property);
/**
@ -669,11 +734,13 @@ const char *property_getName(objc_property_t property);
* description of the format for this string may be found in Apple's
* Objective-C Runtime Programming Guide.
*/
PUBLIC
const char *property_getAttributes(objc_property_t property);
/**
* Returns an array of attributes for this property.
*/
PUBLIC
objc_property_attribute_t *property_copyAttributeList(objc_property_t property,
unsigned int *outCount);
/**
@ -681,6 +748,7 @@ objc_property_attribute_t *property_copyAttributeList(objc_property_t property,
* that this only sets the property metadata. The property accessor methods
* must already be created.
*/
PUBLIC
BOOL class_addProperty(Class cls,
const char *name,
const objc_property_attribute_t *attributes,
@ -690,6 +758,7 @@ BOOL class_addProperty(Class cls,
* Replaces property metadata. If the property does not exist, then this is
* equivalent to calling class_addProperty().
*/
PUBLIC
void class_replaceProperty(Class cls,
const char *name,
const objc_property_attribute_t *attributes,
@ -698,12 +767,14 @@ void class_replaceProperty(Class cls,
/**
* Returns a copy of a single attribute.
*/
PUBLIC
char *property_copyAttributeValue(objc_property_t property,
const char *attributeName);
/**
* Testswhether a protocol conforms to another protocol.
*/
PUBLIC
BOOL protocol_conformsToProtocol(Protocol *p, Protocol *other);
/**
@ -711,6 +782,7 @@ BOOL protocol_conformsToProtocol(Protocol *p, Protocol *other);
* the array in the variable pointed to by the last parameter. The caller is
* responsible for freeing this array.
*/
PUBLIC
struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p,
BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *count);
@ -719,6 +791,7 @@ struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p,
* stored in the variable pointed to by the last argument. The caller is
* responsible for freeing the returned array.
*/
PUBLIC
objc_property_t *protocol_copyPropertyList(Protocol *p, unsigned int *count);
/**
@ -726,6 +799,7 @@ objc_property_t *protocol_copyPropertyList(Protocol *p, unsigned int *count);
* being stored in the variable pointed to by the last argument. The caller is
* responsible for freeing the returned array.
*/
PUBLIC
objc_property_t *protocol_copyPropertyList2(Protocol *p, unsigned int *count,
BOOL isRequiredProperty, BOOL isInstanceProperty);
@ -734,6 +808,7 @@ objc_property_t *protocol_copyPropertyList2(Protocol *p, unsigned int *count,
* number of protocols in the array being returned via the last argument. The
* caller is responsible for freeing this array.
*/
PUBLIC
Protocol *__unsafe_unretained*protocol_copyProtocolList(Protocol *p, unsigned int *count);
/**
@ -744,11 +819,13 @@ Protocol *__unsafe_unretained*protocol_copyProtocolList(Protocol *p, unsigned in
*
* The caller is responsible for freeing the returned array.
*/
PUBLIC
Protocol *__unsafe_unretained*objc_copyProtocolList(unsigned int *outCount);
/**
* Returns the method description for the specified method within a given
* protocol.
*/
PUBLIC
struct objc_method_description protocol_getMethodDescription(Protocol *p,
SEL aSel, BOOL isRequiredMethod, BOOL isInstanceMethod);
@ -759,17 +836,20 @@ struct objc_method_description protocol_getMethodDescription(Protocol *p,
* implementation and so its semantics may change in the future and this
* runtime may diverge from Apple's.
*/
PUBLIC
const char *_protocol_getMethodTypeEncoding(Protocol *p, SEL aSel,
BOOL isRequiredMethod, BOOL isInstanceMethod);
/**
* Returns the name of the specified protocol.
*/
PUBLIC
const char* protocol_getName(Protocol *p);
/**
* Returns the property metadata for the property with the specified name.
*/
PUBLIC
objc_property_t protocol_getProperty(Protocol *p, const char *name,
BOOL isRequiredProperty, BOOL isInstanceProperty);
@ -779,6 +859,7 @@ objc_property_t protocol_getProperty(Protocol *p, const char *name,
* which made not attempt to unique protocols (or even register them with the
* runtime).
*/
PUBLIC
BOOL protocol_isEqual(Protocol *p, Protocol *other);
/**
@ -786,21 +867,25 @@ BOOL protocol_isEqual(Protocol *p, Protocol *other);
* the function (either a method or a forwarding hook) that should be called in
* response to a given message.
*/
PUBLIC
IMP objc_msg_lookup(id, SEL) OBJC_NONPORTABLE;
/**
* The message lookup function used for messages sent to super in the GCC ABI.
* This specifies both the class and the
*/
PUBLIC
IMP objc_msg_lookup_super(struct objc_super*, SEL) OBJC_NONPORTABLE;
/**
* Returns the name of the specified selector.
*/
PUBLIC
const char *sel_getName(SEL sel);
/**
* Registers a selector with the runtime. This is equivalent to sel_registerName().
*/
PUBLIC
SEL sel_getUid(const char *selName);
/**
@ -813,22 +898,26 @@ SEL sel_getUid(const char *selName);
* both b and c are typed selectors with different types, then then the first
* two will return YES, but the third case will return NO.
*/
PUBLIC
BOOL sel_isEqual(SEL sel1, SEL sel2);
/**
* Registers an untyped selector with the runtime.
*/
PUBLIC
SEL sel_registerName(const char *selName);
/**
* Register a typed selector.
*/
PUBLIC
SEL sel_registerTypedName_np(const char *selName, const char *types) OBJC_NONPORTABLE;
/**
* Returns the type encoding associated with a selector, or the empty string is
* there is no such type.
*/
PUBLIC
const char *sel_getType_np(SEL aSel) OBJC_NONPORTABLE;
/**
@ -839,6 +928,7 @@ const char *sel_getType_np(SEL aSel) OBJC_NONPORTABLE;
* once with a relatively small on-stack buffer and then only call it again
* with a heap-allocated buffer if there is not enough space.
*/
PUBLIC
unsigned sel_copyTypes_np(const char *selName, const char **types, unsigned count) OBJC_NONPORTABLE;
/**
@ -849,12 +939,14 @@ unsigned sel_copyTypes_np(const char *selName, const char **types, unsigned coun
* once with a relatively small on-stack buffer and then only call it again
* with a heap-allocated buffer if there is not enough space.
*/
PUBLIC
unsigned sel_copyTypedSelectors_np(const char *selName, SEL *const sels, unsigned count) OBJC_NONPORTABLE;
/**
* New ABI lookup function. Receiver may be modified during lookup or proxy
* forwarding and the sender may affect how lookup occurs.
*/
PUBLIC
extern struct objc_slot *objc_msg_lookup_sender(id *receiver, SEL selector, id sender)
OBJC_NONPORTABLE OBJC_DEPRECATED;
@ -862,6 +954,7 @@ extern struct objc_slot *objc_msg_lookup_sender(id *receiver, SEL selector, id s
* Deprecated function for accessing a slot without going via any forwarding
* mechanisms.
*/
PUBLIC
extern struct objc_slot *objc_get_slot(Class, SEL)
OBJC_NONPORTABLE OBJC_DEPRECATED;
@ -871,6 +964,7 @@ extern struct objc_slot *objc_get_slot(Class, SEL)
* counter. If this value is equal to `objc_method_cache_version` then the
* slot is safe to reuse without performing another lookup.
*/
PUBLIC
extern struct objc_slot2 *objc_get_slot2(Class, SEL, uint64_t*)
OBJC_NONPORTABLE;
@ -880,12 +974,14 @@ extern struct objc_slot2 *objc_get_slot2(Class, SEL, uint64_t*)
* counter. If this value is equal to `objc_method_cache_version` then the
* slot is safe to reuse without performing another lookup.
*/
PUBLIC
extern struct objc_slot2 *objc_slot_lookup_version(id *receiver, SEL selector, uint64_t*)
OBJC_NONPORTABLE;
/**
* Look up a slot, invoking any required forwarding mechanisms.
*/
PUBLIC
extern IMP objc_msg_lookup2(id *receiver, SEL selector) OBJC_NONPORTABLE;
/**
@ -893,6 +989,7 @@ extern IMP objc_msg_lookup2(id *receiver, SEL selector) OBJC_NONPORTABLE;
* pointer. If the class can be registered, then this returns YES. The second
* argument specifies the bit pattern to use to identify the small object.
*/
PUBLIC
BOOL objc_registerSmallObjectClass_np(Class cls, uintptr_t classId);
/**
@ -956,6 +1053,7 @@ typedef uintptr_t objc_AssociationPolicy;
* Returns an object previously stored by calling objc_setAssociatedObject()
* with the same arguments, or nil if none exists.
*/
PUBLIC
id objc_getAssociatedObject(id object, void *key);
/**
* Associates an object with another. This provides a mechanism for storing
@ -965,10 +1063,12 @@ id objc_getAssociatedObject(id object, void *key);
* value may be any object, but must respond to -copy or -retain, and -release,
* if an association policy of copy or retain is passed as the final argument.
*/
PUBLIC
void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy);
/**
* Removes all associations from an object.
*/
PUBLIC
void objc_removeAssociatedObjects(id object);
/**
@ -976,6 +1076,7 @@ void objc_removeAssociatedObjects(id object);
* take an object pointer (self) as its first argument, and then the same
* arguments as the method.
*/
PUBLIC
IMP imp_implementationWithBlock(void *block);
/**
* Returns the type encoding of an IMP that would be returned by passing the
@ -983,42 +1084,49 @@ IMP imp_implementationWithBlock(void *block);
* block encoding for transforming to an IMP (it must take id as its first
* argument). The caller is responsible for freeing the returned value.
*/
PUBLIC
char *block_copyIMPTypeEncoding_np(void*block);
/**
* Returns the block that was used in an IMP created by
* imp_implementationWithBlock(). The result of calling this function with any
* other IMP is undefined.
*/
PUBLIC
void *imp_getBlock(IMP anImp);
/**
* Removes a block that was converted to an IMP with
* imp_implementationWithBlock(). The result of calling this function with any
* other IMP is undefined. Returns YES on success, NO on failure.
*/
PUBLIC
BOOL imp_removeBlock(IMP anImp);
/**
* Adds a method to a specific object, This method will not be added to any
* other instances of the same class.
*/
PUBLIC
BOOL object_addMethod_np(id object, SEL name, IMP imp, const char *types);
/**
* Replaces a method on a specific object, This method will not be added to
* any other instances of the same class.
*/
PUBLIC
IMP object_replaceMethod_np(id object, SEL name, IMP imp, const char *types);
/**
* Creates a clone, in the JavaScript sense - an object which inherits both
* associated references and methods from the original object.
*/
PUBLIC
id object_clone_np(id object);
/**
* Returns the prototype of the object if it was created with
* object_clone_np(), or nil otherwise.
*/
PUBLIC
id object_getPrototype_np(id object);
/**
@ -1039,6 +1147,7 @@ id object_getPrototype_np(id object);
* This currently sets a global value. In the future, it may be configurable
* on a per-thread basis.
*/
PUBLIC
int objc_set_apple_compatible_objcxx_exceptions(int newValue) OBJC_NONPORTABLE;

@ -15,4 +15,9 @@
#endif
#ifdef __ELF__
.section .note.GNU-stack,"",%progbits
#elif defined(_WIN32)
.section .drectve,"yn"
.ascii " /EXPORT:objc_msgSend"
.ascii " /EXPORT:objc_msgSend_fpret"
.ascii " /EXPORT:objc_msgSend_stret"
#endif

@ -1,6 +1,24 @@
.macro MSGSEND receiver, sel
.cfi_startproc # Start emitting unwind data. We
#ifdef _WIN64
# define START_PROC(x) .seh_proc x
# define END_PROC(x) .seh_endproc
# define FRAME_OFFSET(x) .seh_stackalloc x
# define FIRST_ARGUMENT_STR "%rcx"
# define FIRST_ARGUMENT %rcx
# define SECOND_ARGUMENT %rdx
# define THIRD_ARGUMENT %r8
#else
# define START_PROC(x) .cfi_startproc
# define END_PROC(x) .cfi_endproc
# define FRAME_OFFSET(x) .cfi_adjust_cfa_offset x
# define FIRST_ARGUMENT_STR "%rdi"
# define FIRST_ARGUMENT %rdi
# define SECOND_ARGUMENT %rsi
# define THIRD_ARGUMENT %rdx
#endif
.macro MSGSEND fnname receiver, sel
START_PROC(\fnname) # Start emitting unwind data. We
# don't actually care about any of
# the stuff except the slow call,
# because that's the only one that
@ -202,26 +220,26 @@
#rdi rsi rdx
# We're (potentially) modifying the self argument with the lookup, so we don't want to be
.ifc "\receiver", "%rdi"
push %rdi
mov %rsp, %rdi
push %rsi # Save _cmd (not preserved across calls)
push %rdx
.ifc "\receiver", FIRST_ARGUMENT_STR
push FIRST_ARGUMENT
mov %rsp, FIRST_ARGUMENT
push SECOND_ARGUMENT # Save _cmd (not preserved across calls)
push THIRD_ARGUMENT
.else
push %rdi # Save the sret pointer
push %rsi # Save self where it can be modified
mov %rsp, %rdi
push %rdx
mov %rdx, %rsi # move _cmd to where the callee expects it to be
push FIRST_ARGUMENT # Save the sret pointer
push SECOND_ARGUMENT # Save self where it can be modified
mov %rsp, FIRST_ARGUMENT
push THIRD_ARGUMENT
mov THIRD_ARGUMENT, SECOND_ARGUMENT # move _cmd to where the callee expects it to be
.endif
.cfi_adjust_cfa_offset 0xD8
FRAME_OFFSET(0xD8)
call CDECL(slowMsgLookup) # Call the slow lookup function
mov %rax, %r10 # Load the returned IMP
pop %rdx
pop %rsi
pop %rdi
pop THIRD_ARGUMENT
pop SECOND_ARGUMENT
pop FIRST_ARGUMENT
movups 0x80(%rsp), %xmm0
movups 0x70(%rsp), %xmm1
@ -244,16 +262,43 @@
lea CDECL(SmallObjectClasses)(%rip), %r11
mov (%r11, %r10, 8), %r10
jmp 1b
.cfi_endproc
END_PROC(\fnname)
.endm
#ifdef _WIN64
.text
.def objc_msgSend;
.scl 2;
.type 32;
.endef
.def objc_msgSend_fpret;
.scl 2;
.type 32;
.endef
.def objc_msgSend_stret;
.scl 2;
.type 32;
.endef
.globl CDECL(objc_msgSend_fpret)
TYPE_DIRECTIVE(CDECL(objc_msgSend_fpret), @function)
.globl CDECL(objc_msgSend)
TYPE_DIRECTIVE(CDECL(objc_msgSend), @function)
CDECL(objc_msgSend_fpret):
CDECL(objc_msgSend):
MSGSEND objc_msgSend, %rcx, %rdx
.globl CDECL(objc_msgSend_stret)
TYPE_DIRECTIVE(CDECL(objc_msgSend_stret), @function)
CDECL(objc_msgSend_stret):
MSGSEND objc_msgSend_stret, %rdx, %r8
#else
.globl CDECL(objc_msgSend)
TYPE_DIRECTIVE(CDECL(objc_msgSend), @function)
.globl CDECL(objc_msgSend_fpret)
TYPE_DIRECTIVE(CDECL(objc_msgSend_fpret), @function)
CDECL(objc_msgSend_fpret):
CDECL(objc_msgSend):
MSGSEND %rdi, %rsi
MSGSEND objc_msgSend, %rdi, %rsi
.globl CDECL(objc_msgSend_stret)
TYPE_DIRECTIVE(CDECL(objc_msgSend_stret), @function)
CDECL(objc_msgSend_stret):
MSGSEND %rsi, %rdx
MSGSEND objc_msgSend_stret, %rsi, %rdx
#endif

@ -4,7 +4,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "unistd.h"
#include "class.h"
#include "properties.h"
#include "spinlock.h"
@ -18,6 +18,7 @@ PRIVATE int spinlocks[spinlock_count];
/**
* Public function for getting a property.
*/
PUBLIC
id objc_getProperty(id obj, SEL _cmd, ptrdiff_t offset, BOOL isAtomic)
{
if (nil == obj) { return nil; }
@ -45,6 +46,7 @@ id objc_getProperty(id obj, SEL _cmd, ptrdiff_t offset, BOOL isAtomic)
return ret;
}
PUBLIC
void objc_setProperty(id obj, SEL _cmd, ptrdiff_t offset, id arg, BOOL isAtomic, BOOL isCopy)
{
if (nil == obj) { return; }
@ -85,6 +87,7 @@ void objc_setProperty(id obj, SEL _cmd, ptrdiff_t offset, id arg, BOOL isAtomic,
objc_release(old);
}
PUBLIC
void objc_setProperty_atomic(id obj, SEL _cmd, id arg, ptrdiff_t offset)
{
char *addr = (char*)obj;
@ -98,6 +101,7 @@ void objc_setProperty_atomic(id obj, SEL _cmd, id arg, ptrdiff_t offset)
objc_release(old);
}
PUBLIC
void objc_setProperty_atomic_copy(id obj, SEL _cmd, id arg, ptrdiff_t offset)
{
char *addr = (char*)obj;
@ -112,6 +116,7 @@ void objc_setProperty_atomic_copy(id obj, SEL _cmd, id arg, ptrdiff_t offset)
objc_release(old);
}
PUBLIC
void objc_setProperty_nonatomic(id obj, SEL _cmd, id arg, ptrdiff_t offset)
{
char *addr = (char*)obj;
@ -122,6 +127,7 @@ void objc_setProperty_nonatomic(id obj, SEL _cmd, id arg, ptrdiff_t offset)
objc_release(old);
}
PUBLIC
void objc_setProperty_nonatomic_copy(id obj, SEL _cmd, id arg, ptrdiff_t offset)
{
char *addr = (char*)obj;
@ -131,6 +137,7 @@ void objc_setProperty_nonatomic_copy(id obj, SEL _cmd, id arg, ptrdiff_t offset)
objc_release(old);
}
PUBLIC
void objc_copyCppObjectAtomic(void *dest, const void *src,
void (*copyHelper) (void *dest, const void *source))
{
@ -143,6 +150,7 @@ void objc_copyCppObjectAtomic(void *dest, const void *src,
unlock_spinlock(lock2);
}
PUBLIC
void objc_getCppObjectAtomic(void *dest, const void *src,
void (*copyHelper) (void *dest, const void *source))
{
@ -152,6 +160,7 @@ void objc_getCppObjectAtomic(void *dest, const void *src,
unlock_spinlock(lock);
}
PUBLIC
void objc_setCppObjectAtomic(void *dest, const void *src,
void (*copyHelper) (void *dest, const void *source))
{
@ -168,6 +177,7 @@ void objc_setCppObjectAtomic(void *dest, const void *src,
* pointers corresponds to the object, which causes some excessive locking to
* be needed.
*/
PUBLIC
void objc_copyPropertyStruct(void *dest,
void *src,
ptrdiff_t size,
@ -194,6 +204,7 @@ void objc_copyPropertyStruct(void *dest,
* Get property structure function. Copies a structure from an ivar to another
* variable. Locks on the address of src.
*/
PUBLIC
void objc_getPropertyStruct(void *dest,
void *src,
ptrdiff_t size,
@ -217,6 +228,7 @@ void objc_getPropertyStruct(void *dest,
* Set property structure function. Copes a structure to an ivar. Locks on
* dest.
*/
PUBLIC
void objc_setPropertyStruct(void *dest,
void *src,
ptrdiff_t size,
@ -237,6 +249,7 @@ void objc_setPropertyStruct(void *dest,
}
PUBLIC
objc_property_t class_getProperty(Class cls, const char *name)
{
if (Nil == cls)
@ -259,6 +272,7 @@ objc_property_t class_getProperty(Class cls, const char *name)
return NULL;
}
PUBLIC
objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount)
{
if (Nil == cls)
@ -296,7 +310,8 @@ objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount)
}
return list;
}
static const char* property_getIVar(objc_property_t property) {
static const char* property_getIVar(objc_property_t property)
{
const char *iVar = property_getAttributes(property);
if (iVar != 0)
{
@ -312,6 +327,7 @@ static const char* property_getIVar(objc_property_t property) {
return 0;
}
PUBLIC
const char *property_getName(objc_property_t property)
{
if (NULL == property) { return NULL; }
@ -336,6 +352,7 @@ static const char *property_getTypeEncoding(objc_property_t property)
return property->type;
}
PUBLIC
const char *property_getAttributes(objc_property_t property)
{
if (NULL == property) { return NULL; }
@ -343,6 +360,7 @@ const char *property_getAttributes(objc_property_t property)
}
PUBLIC
objc_property_attribute_t *property_copyAttributeList(objc_property_t property,
unsigned int *outCount)
{
@ -533,6 +551,7 @@ PRIVATE struct objc_property propertyFromAttrs(const objc_property_attribute_t *
}
PUBLIC
BOOL class_addProperty(Class cls,
const char *name,
const objc_property_attribute_t *attributes,
@ -553,6 +572,7 @@ BOOL class_addProperty(Class cls,
return YES;
}
PUBLIC
void class_replaceProperty(Class cls,
const char *name,
const objc_property_attribute_t *attributes,
@ -569,6 +589,7 @@ void class_replaceProperty(Class cls,
LOCK_RUNTIME_FOR_SCOPE();
memcpy(old, &p, sizeof(struct objc_property));
}
PUBLIC
char *property_copyAttributeValue(objc_property_t property,
const char *attributeName)
{

@ -4,5 +4,7 @@
# include_next "unistd.h"
# define __block __attribute__((__blocks__(byref)))
#else
# include_next "unistd.h"
# if __has_include_next("unitstd.h")
# include_next "unistd.h"
# endif
#endif

@ -1,8 +1,8 @@
#include "objc/objc-visibility.h"
#if defined _WIN32 || defined __CYGWIN__
# define PUBLIC __attribute__((dllexport))
# define PRIVATE
#else
# define PUBLIC __attribute__ ((visibility("default")))
# define PRIVATE __attribute__ ((visibility("hidden")))
#endif
#ifdef NO_LEGACY

Loading…
Cancel
Save