Adding more missing stuff etc.

This commit is contained in:
Lubos Dolezel 2017-02-28 17:50:29 +01:00
parent e5e3f95c44
commit 5d8d13ea12
24 changed files with 1197 additions and 2743 deletions

View File

@ -671,3 +671,14 @@ void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences *self, CFPr
updateDictRep(self);
__CFUnlock(&__CFApplicationPreferencesLock);
}
CFDictionaryRef _CFPrefsCopyAppDictionary(_CFApplicationPreferences *prefs) {
CFDictionaryRef retVal = NULL;
__CFLock(&__CFApplicationPreferencesLock);
CFPreferencesDomainRef applicationDomain = _CFPreferencesStandardDomain(prefs->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
if (applicationDomain) {
retVal = _CFPreferencesDomainDeepCopyDictionary(applicationDomain);
}
__CFUnlock(&__CFApplicationPreferencesLock);
return retVal;
}

View File

@ -8,7 +8,7 @@
#include <CoreFoundation/CFAttributedString.h>
#include "CFRuntime.h"
#include "CFInternal.h"
#include "debug.h"
#include "macros.h"
typedef struct
{

View File

@ -188,6 +188,9 @@ CF_EXTERN_C_BEGIN
#endif
#endif
#define CF_ASSUME_NONNULL_BEGIN
#define CF_ASSUME_NONNULL_END
// Marks functions which return a CF type that needs to be released by the caller but whose names are not consistent with CoreFoundation naming rules. The recommended fix to this is to rename the functions, but this macro can be used to let the clang static analyzer know of any exceptions that cannot be fixed.
// This macro is ONLY to be used in exceptional circumstances, not to annotate functions which conform to the CoreFoundation naming rules.
#ifndef CF_RETURNS_RETAINED

251
CFForwardingPrep.S Normal file
View File

@ -0,0 +1,251 @@
/**************************************
* The marg_list's layout is:
* d0 <-- args
* d1
* d2 | increasing address
* d3 v
* d4
* d5
* d6
* d7
* a1
* a2
* a3
* a4
* stack args...
*
* typedef struct objc_sendv_margs {
* int a[4];
* int stackArgs[...];
* };
*
**************************************/
#if __arm__
#include <arm/arch.h>
#if defined(__DYNAMIC__)
#define MI_EXTERN(var) \
.non_lazy_symbol_pointer ;\
L ## var ## __non_lazy_ptr: ;\
.indirect_symbol var ;\
.long 0
#else
#define MI_EXTERN(var) \
.globl var
#endif
MI_EXTERN(___forwarding___)
.globl __CF_forwarding_prep_0
.align 2
.fnstart
__CF_forwarding_prep_0: // top of stack is used as marg_list
stmfd sp!, {r0-r3} // push args to marg_list
stmfd sp!, {fp, lr} // setup stack frame: sp -= 8, marg_list @ sp+8
.save {fp, lr}
.setfp fp, sp, #4
add fp, sp, #4
.pad #8
sub sp, sp, #8 // pad the stack: sp -= 8, marg_list @ sp+16
add r1, sp, #16 // use marg_list as return strage pointer
add r0, sp, #16 // load marg_list
bl ____forwarding___ // call through
sub sp, fp, #4 // restore stack
ldmfd sp!, {fp, lr} // destroy stack frame
cmp r0, #0 // check for forwarding completion
bne LContinue // circle back around if we're not done or failed
ldmfd sp!, {r0-r3} // load return value registers from marg_list
bx lr // return
LContinue:
str r0, [sp] // failed or redirect; save new target in marg_list
ldmfd sp!, {r0-r3} // restore arg registers from marg_list
b objc_msgSend // restart message send
.fnend
.globl __CF_forwarding_prep_1
.align 2
.fnstart
__CF_forwarding_prep_1: // top of stack is used as marg_list
stmfd sp!, {r0-r3} // push stret pointer and args to marg_list
stmfd sp!, {fp, lr} // setup stack frame
.save {fp, lr}
.setfp fp, sp, #4
add fp, sp, #4
.pad #8
sub sp, sp, #8 // pad the stack
add r1, r0, #0 // load stret pointer as return storage pointer
add r0, sp, #20 // load marg_list, skipping the stret pointer
bl ____forwarding___ // call through
sub sp, fp, #4 // restore stack
ldmfd sp!, {fp, lr} // destroy stack frame
cmp r0, #0 // check for forwarding completion
bne LStretContinue // circle back around if we're not done or failed
ldmfd sp!, {r0-r3} // load return value registers and stret pointer from marg_list
bx lr // return
LStretContinue:
str r0, [sp, #4] // failed or redirect; save new target in marg_list
ldmfd sp!, {r0-r3} // restore arg registers and stret pointer from marg_list
b objc_msgSend_stret // restart message send
.fnend
#elif __i386__
.text
.global __CF_forwarding_prep_0
.align 2, 0x90
__CF_forwarding_prep_0:
// All arguments are stack-based on i386
// Using EAX as a scratch register
push %ebp
mov %esp, %ebp // create a stack frame
sub $0x10, %esp // reserve space for args pointer, return value pointer, and return values
and $-16, %esp // align stack
lea 8(%ebp), %eax // load marg_list, skipping frame pointer and return address
mov %eax, (%esp) // pass marg_list as first argument
lea 8(%esp), %eax // load pointer to return value space on stack
mov %eax, 4(%esp) // pass pointer as second argument
movl $0x0, 8(%esp) // clear out return value space
movl $0x0, 12(%esp)
call ____forwarding___ // call through
mov 4(%esp), %edx // temporarily save return storage pointer
mov %ebp, %esp // restore stack
pop %ebp // pop stack frame
cmp $0, %eax // check for forwarding completion
je LSuccess // return to caller if done
// Overwriting the caller's stack frame like this is not great, but there's
// no easy place to save off the old value; the next-best solution would
// be to call through a VERY slow path of __invoking__, at which point
// there's no use in having a fast path in the first place. This is not an
// issue on ARM or 64-bit Intel, and this SHOULD be safe for all cases.
// If this causes an issue, it will manifest as subsequent messages to an
// object that implements -forwardingTargetForSelector: being sent to the
// forwarding target directly instead of going to the original object. This
// would have to be caused by the compiler not reloading the object pointer
// onto the stack for subsequent message sends to the same target.
mov %eax, 4(%esp) // overwrite original "self" value
jmp _objc_msgSend // restart message send
LSuccess:
mov (%edx), %eax // load return value registers from return storage
mov 4(%edx), %edx
ret // return
.text
.global __CF_forwarding_prep_1
.align 2, 0x90
__CF_forwarding_prep_1:
push %ebp
mov %esp, %ebp // create a stack frame
sub $0x8, %esp // reserve space for args pointer and return value
and $-16, %esp // align stack
lea 12(%ebp), %eax // load marg_list, skipping frame pointer, return address, and stret pointer
mov %eax, (%esp) // pass marg_list as first argument
mov 8(%ebp), %eax // load stret pointer
mov %eax, 4(%esp) // pass as second argument
call ____forwarding___ // call through
mov %ebp, %esp // restore stack
pop %ebp // pop stack frame
cmp $0, %eax // check for forwarding completion
je LStretSuccess // return to caller if done
mov %eax, 8(%esp) // overwrite original "self" value (see long comment above)
jmp _objc_msgSend_stret // restart message send
LStretSuccess:
ret $4 // return value in stret pointer; return
#elif __x86_64__
.text
.globl __CF_forwarding_prep_0
.globl __CF_forwarding_prep_1
.align 2, 0x90
__CF_forwarding_prep_0:
__CF_forwarding_prep_1:
push %rbp
movq %rsp, %rbp
// Copy args from regs into a stack var
subq $0xd0, %rsp
movq %rax, 0xb0(%rsp)
movapd %xmm7, 0xa0(%rsp)
movapd %xmm6, 0x90(%rsp)
movapd %xmm5, 0x80(%rsp)
movapd %xmm4, 0x70(%rsp)
movapd %xmm3, 0x60(%rsp)
movapd %xmm2, 0x50(%rsp)
movapd %xmm1, 0x40(%rsp)
movapd %xmm0, 0x30(%rsp)
movq %r9, 0x28(%rsp)
movq %r8, 0x20(%rsp)
movq %rcx, 0x18(%rsp)
movq %rdx, 0x10(%rsp)
movq %rsi, 8(%rsp)
movq %rdi, (%rsp)
movq %rsp, %rdi
xorl %esi, %esi
call ____forwarding___ // call through
cmpq $0, %rax // check for forwarding completion
jne Lfail // return to caller if done
// double return
movapd 0x20(%rax), %xmm1
movapd 0x10(%rax), %xmm0
movq 8(%rax), %rdx
movq (%rax), %rax
movq %rbp, %rsp
pop %rbp
ret
Lfail:
movq %rax, %rdi
movq 0x80(%rsp), %rax
movapd 0xa0(%rsp), %xmm7
movapd 0x90(%rsp), %xmm6
movapd 0x80(%rsp), %xmm5
movapd 0x70(%rsp), %xmm4
movapd 0x60(%rsp), %xmm3
movapd 0x50(%rsp), %xmm2
movapd 0x40(%rsp), %xmm1
movapd 0x30(%rsp), %xmm0
movq 0x28(%rsp), %r9
movq 0x20(%rsp), %r8
movq 0x18(%rsp), %rcx
movq 0x10(%rsp), %rdx
movq 8(%rsp), %rsi
// movq (%rsp), %rdi // self overwritten
movq %rbp, %rsp
pop %rbp
jmp _objc_msgSend // restart message send
#else
#error Missing forwarding prep handlers for this arch https://code.google.com/p/apportable/issues/detail?id=619
#endif

View File

@ -1459,6 +1459,17 @@ CF_EXPORT CFTypeRef _CFRunLoopGet2b(CFRunLoopRef rl) {
return rl->_counterpart;
}
CF_EXPORT CFTypeRef _CFRunLoopSet2(CFRunLoopRef rl, CFTypeRef (*counterpartProvider)(CFRunLoopRef)) {
CFTypeRef ret = NULL;
__CFLock(&loopsLock);
if (rl->_counterpart == NULL) {
rl->_counterpart = counterpartProvider(rl);
}
ret = rl->_counterpart;
__CFUnlock(&loopsLock);
return ret;
}
#if DEPLOYMENT_TARGET_MACOSX
void _CFRunLoopSetCurrent(CFRunLoopRef rl) {
if (pthread_main_np()) return;

View File

@ -903,6 +903,10 @@ void __CFInitialize(void) {
if (!__CFInitialized && !__CFInitializing) {
__CFInitializing = 1;
#ifdef __i386__
__exceptionInit();
#endif
#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_IPHONESIMULATOR
if (!pthread_main_np()) HALT; // CoreFoundation must be initialized on the main thread
#endif

42
CFXPCBridge.c Normal file
View File

@ -0,0 +1,42 @@
/* CFXPCBridge.c
Copyright (C) 2016 Lubos Dolezel
This file is part of the GNUstep CoreBase Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; see the file COPYING.LIB.
If not, see <http://www.gnu.org/licenses/> or write to the
Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <CoreFoundation/CFXPCBridge.h>
CFTypeRef _CFXPCCreateCFObjectFromXPCObject(xpc_object_t xpcattrs)
{
// TODO
// This function converts XPC null, bool, string, data, int64,
// double, date, uuid, array and dictionary types to their
// CF counterparts.
return NULL;
}
xpc_object_t _CFXPCCreateXPCObjectFromCFObject(CFTypeRef attrs)
{
return NULL;
}
// TODO: _CFXPCCreateCFObjectFromXPCMessage
// This function takes the "ECF19A18-7AA6-4141-B4DC-A2E5123B2B5C" data value
// from the dictionary and parses it as a binary plist.

37
CFXPCBridge.h Normal file
View File

@ -0,0 +1,37 @@
/* CFXPCBridge.h
Copyright (C) 2016 Lubos Dolezel
This file is part of the GNUstep CoreBase Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; see the file COPYING.LIB.
If not, see <http://www.gnu.org/licenses/> or write to the
Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef __CFCOREFOUNDATION_CFXPC_H__
#define __CFCOREFOUNDATION_CFXPC_H__
#include <CoreFoundation/CFBase.h>
#include <xpc/xpc.h>
CF_EXTERN_C_BEGIN
extern CFTypeRef _CFXPCCreateCFObjectFromXPCObject(xpc_object_t xpcattrs);
extern xpc_object_t _CFXPCCreateXPCObjectFromCFObject(CFTypeRef attrs);
CF_EXTERN_C_END
#endif

View File

@ -3,6 +3,7 @@ project(corefoundation)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc -fblocks -fconstant-cfstrings -fexceptions \
-Wno-bridge-cast \
-include ${CMAKE_CURRENT_SOURCE_DIR}/CoreFoundation_Prefix.h \
-include ${CMAKE_CURRENT_SOURCE_DIR}/macros.h \
-mmacosx-version-min=10.10")
include(darling_framework)
@ -26,7 +27,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src/external/cfnetwork/include
${CMAKE_SOURCE_DIR}/src/external/foundation/include
${CMAKE_SOURCE_DIR}/src/external/foundation/src
${CMAKE_SOURCE_DIR}/src/libmalloc/include)
${CMAKE_SOURCE_DIR}/src/external/coregraphics/Headers
${CMAKE_SOURCE_DIR}/src/libmalloc/include
)
add_definitions(-DCF_BUILDING_CF
-DDEPLOYMENT_TARGET_MACOSX=1
@ -98,6 +101,7 @@ set(cf_sources
CFStringEncodingDatabase.c
CFStringEncodings.c
CFStringScanner.c
CFStringTokenizer.c
CFStringUtilities.c
CFSystemDirectories.c
CFTimeZone.c
@ -138,6 +142,7 @@ set(cf_sources
NSCharacterSet.m
NSInputStream.m
NSInvocation.m
NSInvoke-x86.S
NSLocale.m
NSMessageBuilder.m
NSMethodSignature.m
@ -157,9 +162,9 @@ set(cf_sources
NSTimeZone.m
NSURL.m
NSZombie.m
cifframe.m
GSFFIInvocation.m
GSObjCRuntime.m
CFForwardingPrep.S
FoundationExceptions.m
CFXPCBridge.c
)
add_framework(CoreFoundation
@ -172,7 +177,6 @@ add_framework(CoreFoundation
objc
system
icucore
ffi
LINK_FLAGS
"-Wl,-init,___CFInitialize \
-Wl,-compatibility_version,150 \
@ -184,3 +188,7 @@ add_framework(CoreFoundation
-Wl,-segprot,__UNICODE,r,r"
)
add_darling_executable(plconvert plconvert.c)
target_link_libraries(plconvert system CoreFoundation)
install(TARGETS plconvert DESTINATION libexec/darling/usr/bin)

View File

@ -85,6 +85,8 @@
#include <CoreFoundation/CFURLAccess.h>
#include <CoreFoundation/CFUUID.h>
#include <CoreFoundation/CFUtilities.h>
#include <CoreFoundation/CFMachPort.h>
#include <CoreFoundation/CFXPCBridge.h>
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) || TARGET_OS_WIN32
#include <CoreFoundation/CFBundle.h>

39
FoundationExceptions.h Normal file
View File

@ -0,0 +1,39 @@
/**
* Copyright (C) 2017 Lubos Dolezel
*
* Darling is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Foobar is distributed in the hope that it will be useful,
* Darling WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _FOUNDATION_EXCEPTIONS_H
#define _FOUNDATION_EXCEPTIONS_H
#if !__OBJC2__
enum {
kCFDoExceptionOperationGetUncaughtHandler = 0,
kCFDoExceptionOperationSetUncaughtHandler,
kCFDoExceptionOperationRaiseError = 40,
kCFDoExceptionOperationAddHandler = 50,
kCFDoExceptionOperationRemoveHandler,
kCFDoExceptionOperationExtractException
};
void* _CFDoExceptionOperation(int op, void* arg);
__attribute__((visibility("hidden")))
void __exceptionInit(void);
#endif
#endif

192
FoundationExceptions.m Normal file
View File

@ -0,0 +1,192 @@
/**
* Copyright (C) 2017 Lubos Dolezel
*
* Darling is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Foobar is distributed in the hope that it will be useful,
* Darling WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#if !__OBJC2__
#include <objc/runtime.h>
#include <objc/objc-exception.h>
#include "CFLogUtilities.h"
#include "CFInternal.h"
#include "ForFoundationOnly.h"
#include "FoundationExceptions.h"
#include <stdlib.h>
#include <dlfcn.h>
#import <Foundation/NSObject.h>
#import <Foundation/NSException.h>
static void (*__uncaughtExceptionHandler)(id exc) = NULL;
typedef struct {
jmp_buf buf;
void* pointers[4];
} LocalData_t;
typedef struct ThreadChainLink
{
void** localExceptionData;
size_t localExceptionDataCount, localExceptionDataSize;
} ThreadChainLink_t;
static int objectIsKindOfNSException(id exc);
// Throw handler with Foundation support
static void __raiseError(id exc)
{
ThreadChainLink_t* chainLink = (ThreadChainLink_t*) _CFGetTSD(__CFTSDKeyExceptionData);
if (chainLink != NULL)
{
LocalData_t* led = (LocalData_t*) chainLink->localExceptionData[chainLink->localExceptionDataCount - 1];
if (led != NULL)
{
chainLink->localExceptionDataCount--;
led->pointers[0] = exc;
_longjmp(led->buf, 1);
}
}
if (__uncaughtExceptionHandler != NULL && objectIsKindOfNSException(exc))
{
__uncaughtExceptionHandler(exc);
}
else
{
if (!objectIsKindOfNSException(exc))
{
CFLog(kCFLogLevelError, CFSTR("*** Terminating app due to uncaught exception of class %s"), object_getClassName(exc));
}
else
{
CFLog(kCFLogLevelError, CFSTR("*** Terminating app due to uncaught exception of class %@, reason: \"%@\",\n"
"*** Call stack:\n%@\n"),
[exc name], [exc reason], [exc description]);
}
}
abort();
}
static id __exceptionExtract(void* localExceptionData)
{
LocalData_t* led = (LocalData_t*)localExceptionData;
return (id) led->pointers[0];
}
static int objectIsKindOfNSException(id exc)
{
Class c = [NSException class];
if (class_respondsToSelector(object_getClass(exc), @selector(isKindOfClass:)))
{
return [exc isKindOfClass: c];
}
else
{
// NSException implements isKindOfClass:, so this means it's not an NSException
return 0;
}
}
static void __exceptionFinalize(void* ptr)
{
ThreadChainLink_t* tsd = (ThreadChainLink_t*) ptr;
free(tsd->localExceptionData);
free(tsd);
}
static int __exceptionMatch(Class matchClass, id exc)
{
Class excClass = object_getClass(exc);
if (class_respondsToSelector(excClass, @selector(isKindOfClass:)))
{
return [exc isKindOfClass: matchClass];
}
else
{
while (excClass != NULL)
{
if (excClass == matchClass)
return 1;
excClass = class_getSuperclass(excClass);
}
return 0;
}
}
static void __addHandler2(void* localExceptionData)
{
ThreadChainLink_t* tsd = (ThreadChainLink_t*) _CFGetTSD(__CFTSDKeyExceptionData);
if (!tsd)
{
tsd = (ThreadChainLink_t*) malloc(sizeof(ThreadChainLink_t));
memset(tsd, 0, sizeof(*tsd));
_CFSetTSD(__CFTSDKeyExceptionData, tsd, __exceptionFinalize);
}
if (tsd->localExceptionDataCount+1 > tsd->localExceptionDataSize)
{
tsd->localExceptionDataSize += 16;
tsd->localExceptionData = (void**) realloc(tsd->localExceptionData, sizeof(void*) * tsd->localExceptionDataSize);
}
// store pointer to localExceptionData in tsd
tsd->localExceptionData[tsd->localExceptionDataCount] = localExceptionData;
tsd->localExceptionDataCount++;
}
static void __removeHandler2(void* localExceptionData)
{
ThreadChainLink_t* tsd = (ThreadChainLink_t*) _CFGetTSD(__CFTSDKeyExceptionData);
tsd->localExceptionDataCount--;
}
void* _CFDoExceptionOperation(int op, void* arg)
{
switch (op)
{
case kCFDoExceptionOperationGetUncaughtHandler:
return __uncaughtExceptionHandler;
case kCFDoExceptionOperationSetUncaughtHandler:
__uncaughtExceptionHandler = arg;
break;
case kCFDoExceptionOperationRaiseError:
__raiseError((id) arg);
break;
case kCFDoExceptionOperationAddHandler:
__addHandler2(arg);
break;
case kCFDoExceptionOperationRemoveHandler:
__removeHandler2(arg);
break;
case kCFDoExceptionOperationExtractException:
return __exceptionExtract(arg);
}
return NULL;
}
static objc_exception_functions_t old_exc_funcs;
// Called from __CFInitialize
void __exceptionInit(void)
{
objc_exception_functions_t funcs = { 0, __raiseError, __addHandler2, __removeHandler2, __exceptionExtract, __exceptionMatch };
objc_exception_get_functions(&old_exc_funcs);
objc_exception_set_functions(&funcs);
}
#endif // !__OBJC2__

View File

@ -1,5 +1,4 @@
#import <Foundation/NSException.h>
#include "debug.h"
#define NUM_BUCKET_SIZES 64

View File

@ -8,7 +8,6 @@
#import "NSBlock.h"
#import <dispatch/dispatch.h>
#import <objc/runtime.h>
#include "debug.h"
extern Class objc_initializeClassPair(Class superclass_gen, const char *name, Class cls_gen, Class meta_gen);

View File

@ -9,7 +9,6 @@
#import <Foundation/NSLocale.h>
#import "NSCalendarInternal.h"
#import "NSObjectInternal.h"
#include "debug.h"
extern void CFCalendarSetGregorianStartDate(CFCalendarRef calendar, CFDateRef date);
extern CFDateRef CFCalendarCopyGregorianStartDate(CFCalendarRef calendar);

File diff suppressed because it is too large Load Diff

10
NSInvocationInternal.h Normal file
View File

@ -0,0 +1,10 @@
#import <objc/message.h>
// By grabbing at least 4 words for retSize, we can blindly copy r0-r3
// into retdata when returning from an invocation.
#define RET_SIZE_ARGS (4 * sizeof(int))
void __invoke__(void *send, void *retdata, marg_list args, size_t len, const char *rettype);
extern void _CF_forwarding_prep_0();
extern void _CF_forwarding_prep_1();

149
NSInvoke-x86.S Normal file
View File

@ -0,0 +1,149 @@
.text
.align 2, 0x90
.globl ___invoke__
___invoke__:
# void __invoke__(void (*msgSend)(...),
# void *retdata,
# marg_list args,
# size_t frame_length,
# const char *return_type)
#ifdef __i386__
# Save retdata, scratch register, and return address.
push %ebp # Prologue
mov %esp, %ebp
push %edi
push %esi
push %edx
push %ebx
mov 12+8(%ebp), %eax #$eax = frame_length
mov 8+8(%ebp), %edx #$edx = args
mov %esp, %ebx
subl %eax, %esp #push the stack down
andl $-16, %esp #and align
Lpush:
movl -4(%eax,%edx), %edi
movl %edi, -4(%esp,%eax)
sub $4, %eax
test %eax, %eax
jne Lpush
mov 0+8(%ebp), %edi #$edi = msgSend
calll *%edi
mov 4+8(%ebp), %esi #$esi = retdata
mov %eax, (%esi) # copy the result (probably) into *retdata
#next, check to see if we need to put something else (ie something from
#the x87 registers or a 64-bit value) into *retdata instead.
mov 8+16(%ebp), %eax #$eax == return_type
mov (%eax), %al
cmpb $0x71, %al # if (returnType[0] == 'q') // int64_t
je Lsixtyfourret
cmpb $0x51, %al # if (returnType[0] == 'Q') // uint64_t
je Lsixtyfourret
cmpb $0x44, %al # if (returnType[0] == 'D') // long double
je Llongdoubleret
cmpb $0x64, %al # if (returnType[0] == 'd') // double
je Ldoubleret
cmpb $0x66, %al # if (returnType[0] == 'f') // float
jne Ldone
fstps (%esi) # this is how to get things out of x87.
# fstp pops and stores a certain length (determined by the suffix -
# s for float, l for double, t for long double - just go with it)
# in the location given (in this case *$esi)
jmp Ldone #then jump to to cleanup and return
Lsixtyfourret:
# just store edx too
mov %edx, 4(%esi)
jmp Ldone
Ldoubleret:
fstpl (%esi)
jmp Ldone
Llongdoubleret:
fstpt (%esi)
Ldone:
mov %ebx, %esp # restore stack!
pop %ebx
pop %edx
pop %esi
pop %edi
mov %ebp, %esp # Epilogue
pop %ebp
ret
#else // Now the x86-64 version
push %rbp # Prologue
movq %rsp, %rbp
push %rdi
push %rsi
push %r8
movq %rdx, %rsi
subq %rcx, %rsp # Push the stack down
andq $-16, %rsp #and align
# Shift stack contents (frame_length/8) times,
# 8 bytes at a time
# TODO: More efficient than the Lpush loop
# in i386 assembly above
movq %rsp, %rdi
shrq $3, %rcx # frame_length /= 8
cld
rep movsq
# Copy args into registers
movq 0xb0(%rsp), %rax
movapd 0xa0(%rsp), %xmm7
movapd 0x90(%rsp), %xmm6
movapd 0x80(%rsp), %xmm5
movapd 0x70(%rsp), %xmm4
movapd 0x60(%rsp), %xmm3
movapd 0x50(%rsp), %xmm2
movapd 0x40(%rsp), %xmm1
movapd 0x30(%rsp), %xmm0
movq 0x28(%rsp), %r9
movq 0x20(%rsp), %r8
movq 0x18(%rsp), %rcx
movq 0x10(%rsp), %rdx
movq 8(%rsp), %rsi
movq (%rsp), %rdi
addq $224, %rsp
movq -8(%rbp), %r10 # call objc_msgSend
callq *%r10
movq -16(%rbp), %rsi # return value
movq -24(%rbp), %rcx
cmpb $0x44, %cl # if (returnType[0] == 'D') // long double
je Llongdoubleret
# double
movapd %xmm1, 32(%rsi)
movapd %xmm0, 16(%rsi)
# int128
movq %rdx, 8(%rsi)
movq %rax, (%rsi)
jmp Ldone
Llongdoubleret:
fstpt (%rsi)
Ldone:
movq %rbp, %rsp # Epilogue
pop %rbp
ret
#endif

View File

@ -19,7 +19,6 @@
#import "NSBasicHash.h"
#import "NSFastEnumerationEnumerator.h"
#import "NSObjectInternal.h"
#include "debug.h"
@interface __NSPlaceholderOrderedSet : NSMutableOrderedSet
+ (id)mutablePlaceholder;

View File

@ -1,86 +0,0 @@
/* cifframe - Wrapper/Objective-C interface for ffi function interface
Copyright (C) 1999, Free Software Foundation, Inc.
Written by: Adam Fedor <fedor@gnu.org>
Created: Feb 2000
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02111 USA.
*/
#ifndef cifframe_h_INCLUDE
#define cifframe_h_INCLUDE
#include <ffi.h>
#if defined(_WIN32)
/*
* Avoid conflicts when other headers try to define UINT32 and UINT64
*/
#if defined(UINT32)
#undef UINT32
#endif
#if defined(UINT64)
#undef UINT64
#endif
#endif
#import "Foundation/NSMethodSignature.h"
//#import "GNUstepBase/DistributedObjects.h"
//#import "GSPrivate.h"
typedef struct _cifframe_t {
ffi_cif cif;
int nargs;
ffi_type **arg_types;
void **values;
} cifframe_t;
/* Memory to use to put executable code in.
*/
@interface GSCodeBuffer : NSObject
{
unsigned size;
void *buffer;
void *executable;
id frame;
}
+ (GSCodeBuffer*) memoryWithSize: (NSUInteger)_size;
- (void*) buffer;
- (void*) executable;
- (id) initWithSize: (NSUInteger)_size;
- (void) protect;
- (void) setFrame: (id)aFrame;
@end
@class NSMutableData;
extern NSMutableData *cifframe_from_signature (NSMethodSignature *info);
extern GSCodeBuffer* cifframe_closure (NSMethodSignature *sig, void (*func)());
extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer,
int size);
extern void cifframe_get_arg(cifframe_t *cframe, int index, void *buffer,
int size);
extern void *cifframe_arg_addr(cifframe_t *cframe, int index);
extern BOOL cifframe_decode_arg (const char *type, void* buffer);
extern BOOL cifframe_encode_arg (const char *type, void* buffer);
#endif

View File

@ -1,747 +0,0 @@
/** cifframe.m - Wrapper/Objective-C interface for ffi function interface
Copyright (C) 1999-2015 Free Software Foundation, Inc.
Written by: Adam Fedor <fedor@gnu.org>
Date: Dec 1999, rewritten Apr 2002
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
//#import "common.h"
//#if !defined (__GNU_LIBOBJC__)
# include <objc/objc-class.h>
//#endif
#include <malloc.h>
#include <alloca.h>
#include <ctype.h>
#include "cifframe.h"
#import "Foundation/NSException.h"
#import "Foundation/NSData.h"
#import "Foundation/NSGeometry.h"
#import "GSInvocation.h"
#include "encoding.c"
//#import "GSPrivate.h"
#define GS_SIZEOF_SHORT 2
#define GS_SIZEOF_INT 4
#define GS_SIZEOF_LONG_LONG 8
#ifdef __x86_64__
# define GS_SIZEOF_LONG 8
#else
# define GS_SIZEOF_LONG 4
#endif
/* ffi defines types in a very odd way that doesn't map to the
normal objective-c type (see ffi.h). Here we make up for that */
#if GS_SIZEOF_SHORT == 2
#define gsffi_type_ushort ffi_type_uint16
#define gsffi_type_sshort ffi_type_sint16
#elif GS_SIZEOF_SHORT == 4
#define gsffi_type_ushort ffi_type_uint32
#define gsffi_type_sshort ffi_type_sint32
#else
#error FFI Sizeof SHORT case not handled
#endif
#if GS_SIZEOF_INT == 2
#define gsffi_type_uint ffi_type_uint16
#define gsffi_type_sint ffi_type_sint16
#elif GS_SIZEOF_INT == 4
#define gsffi_type_uint ffi_type_uint32
#define gsffi_type_sint ffi_type_sint32
#elif GS_SIZEOF_INT == 8
#define gsffi_type_uint ffi_type_uint64
#define gsffi_type_sint ffi_type_sint64
#else
#error FFI Sizeof INT case not handled
#endif
#if GS_SIZEOF_LONG == 2
#define gsffi_type_ulong ffi_type_uint16
#define gsffi_type_slong ffi_type_sint16
#elif GS_SIZEOF_LONG == 4
#define gsffi_type_ulong ffi_type_uint32
#define gsffi_type_slong ffi_type_sint32
#elif GS_SIZEOF_LONG == 8
#define gsffi_type_ulong ffi_type_uint64
#define gsffi_type_slong ffi_type_sint64
#else
#error FFI Sizeof LONG case not handled
#endif
#ifdef _C_LNG_LNG
#if GS_SIZEOF_LONG_LONG == 8
#define gsffi_type_ulong_long ffi_type_uint64
#define gsffi_type_slong_long ffi_type_sint64
#else
#error FFI Sizeof LONG LONG case not handled
#endif
#endif
ffi_type *cifframe_type(const char *typePtr, const char **advance);
static inline const char *
gs_skip_type_qualifier_and_layout_info (const char *types)
{
while (*types == '+'
|| *types == '-'
|| *types == _C_CONST
|| *types == _C_IN
|| *types == _C_INOUT
|| *types == _C_OUT
|| *types == _C_BYCOPY
|| *types == _C_BYREF
|| *types == _C_ONEWAY
|| *types == _C_GCINVISIBLE
|| isdigit ((unsigned char) *types))
{
types++;
}
return types;
}
static BOOL
GSSelectorTypesMatch(const char *types1, const char *types2)
{
if (! types1 || ! types2)
return NO;
while (*types1 && *types2)
{
types1 = gs_skip_type_qualifier_and_layout_info (types1);
types2 = gs_skip_type_qualifier_and_layout_info (types2);
/* Reached the end of the selector. */
if (! *types1 && ! *types2)
return YES;
/* Ignore structure name yet compare layout. */
if (*types1 == '{' && *types2 == '{')
{
while (*types1 != '=')
types1++;
while (*types2 != '=')
types2++;
}
if (*types1 != *types2)
return NO;
types1++;
types2++;
}
types1 = gs_skip_type_qualifier_and_layout_info (types1);
types2 = gs_skip_type_qualifier_and_layout_info (types2);
return (! *types1 && ! *types2);
}
/* Best guess at the space needed for a structure, since we don't know
for sure until it's calculated in ffi_prep_cif, which is too late */
int
cifframe_guess_struct_size(ffi_type *stype)
{
int i, size;
unsigned align = __alignof(double);
if (stype->elements == NULL)
return stype->size;
size = 0;
i = 0;
while (stype->elements[i])
{
if (stype->elements[i]->elements)
size += cifframe_guess_struct_size(stype->elements[i]);
else
size += stype->elements[i]->size;
if (size % align != 0)
{
size += (align - size % align);
}
i++;
}
return size;
}
NSMutableData *
cifframe_from_signature (NSMethodSignature *info)
{
unsigned size = sizeof(cifframe_t);
unsigned align = __alignof(double);
unsigned type_offset = 0;
unsigned offset = 0;
NSMutableData *result;
void *buf;
int i;
int numargs = [info numberOfArguments];
ffi_type *rtype;
ffi_type *arg_types[numargs];
cifframe_t *cframe;
/* FIXME: in cifframe_type, return values/arguments that are structures
have custom ffi_types with are allocated separately. We should allocate
them in our cifframe so we don't leak memory. Or maybe we could
cache structure types? */
rtype = cifframe_type([info methodReturnType], NULL);
for (i = 0; i < numargs; i++)
{
arg_types[i] = cifframe_type([info getArgumentTypeAtIndex: i], NULL);
}
if (numargs > 0)
{
if (size % align != 0)
{
size += align - (size % align);
}
type_offset = size;
/* Make room to copy the arg_types */
size += sizeof(ffi_type *) * numargs;
if (size % align != 0)
{
size += align - (size % align);
}
offset = size;
size += numargs * sizeof(void*);
if (size % align != 0)
{
size += (align - (size % align));
}
for (i = 0; i < numargs; i++)
{
if (arg_types[i]->elements)
size += cifframe_guess_struct_size(arg_types[i]);
else
size += arg_types[i]->size;
if (size % align != 0)
{
size += (align - size % align);
}
}
}
result = [NSMutableData dataWithCapacity: size];
[result setLength: size];
cframe = buf = [result mutableBytes];
if (cframe)
{
cframe->nargs = numargs;
cframe->arg_types = buf + type_offset;
memcpy(cframe->arg_types, arg_types, sizeof(ffi_type *) * numargs);
cframe->values = buf + offset;
if (ffi_prep_cif (&cframe->cif, FFI_DEFAULT_ABI, numargs,
rtype, cframe->arg_types) != FFI_OK)
{
cframe = NULL;
result = NULL;
}
else
{
/* Set values locations. This must be done after ffi_prep_cif so
that any structure sizes get calculated first. */
offset += numargs * sizeof(void*);
if (offset % align != 0)
{
offset += align - (offset % align);
}
for (i = 0; i < numargs; i++)
{
cframe->values[i] = buf + offset;
offset += arg_types[i]->size;
if (offset % align != 0)
{
offset += (align - offset % align);
}
}
}
}
return result;
}
void
cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size)
{
if (index < 0 || index >= cframe->nargs)
return;
memcpy(cframe->values[index], buffer, size);
}
void
cifframe_get_arg(cifframe_t *cframe, int index, void *buffer, int size)
{
if (index < 0 || index >= cframe->nargs)
return;
memcpy(buffer, cframe->values[index], size);
}
void *
cifframe_arg_addr(cifframe_t *cframe, int index)
{
if (index < 0 || index >= cframe->nargs)
return NULL;
return cframe->values[index];
}
/*
* Get the ffi_type for this type
*/
ffi_type *
cifframe_type(const char *typePtr, const char **advance)
{
static ffi_type stypeNSPoint = { 0 };
static ffi_type stypeNSRange = { 0 };
static ffi_type stypeNSRect = { 0 };
static ffi_type stypeNSSize = { 0 };
const char *type;
ffi_type *ftype = 0;
typePtr = objc_skip_type_qualifiers (typePtr);
type = typePtr;
/*
* Scan for size and alignment information.
*/
switch (*typePtr++)
{
case _C_ID: ftype = &ffi_type_pointer;
break;
case _C_CLASS: ftype = &ffi_type_pointer;
break;
case _C_SEL: ftype = &ffi_type_pointer;
break;
case _C_CHR: ftype = &ffi_type_schar;
break;
case _C_UCHR: ftype = &ffi_type_uchar;
break;
case _C_SHT: ftype = &gsffi_type_sshort;
break;
case _C_USHT: ftype = &gsffi_type_ushort;
break;
case _C_INT: ftype = &gsffi_type_sint;
break;
case _C_UINT: ftype = &gsffi_type_uint;
break;
case _C_LNG: ftype = &gsffi_type_slong;
break;
case _C_ULNG: ftype = &gsffi_type_ulong;
break;
#ifdef _C_LNG_LNG
case _C_LNG_LNG: ftype = &gsffi_type_slong_long;
break;
case _C_ULNG_LNG: ftype = &gsffi_type_ulong_long;
break;
#endif
case _C_FLT: ftype = &ffi_type_float;
break;
case _C_DBL: ftype = &ffi_type_double;
break;
case _C_PTR:
ftype = &ffi_type_pointer;
if (*typePtr == '?')
{
typePtr++;
}
else
{
const char *adv;
cifframe_type(typePtr, &adv);
typePtr = adv;
}
break;
case _C_ATOM:
case _C_CHARPTR:
ftype = &ffi_type_pointer;
break;
case _C_ARY_B:
{
const char *adv;
ftype = &ffi_type_pointer;
while (isdigit(*typePtr))
{
typePtr++;
}
cifframe_type(typePtr, &adv);
typePtr = adv;
typePtr++; /* Skip end-of-array */
}
break;
case _C_STRUCT_B:
{
int types, maxtypes, size;
ffi_type *local;
const char *adv;
unsigned align = __alignof(double);
/* Standard structures can be handled using cached type information.
Since the switch statement has already skipped the _C_STRUCT_B
character, we must use typePtr-1 below to successfully match the
type encoding with one of the standard type encodings. The same
holds for skipping past the whole structure type's encoding with
objc_skip_typespec.
*/
if (GSSelectorTypesMatch(typePtr - 1, @encode(NSRange)))
{
ftype = &stypeNSRange;
if (ftype->type == 0)
{
static ffi_type *elems[3];
if (*@encode(NSUInteger) == _C_ULNG)
{
elems[0] = &gsffi_type_ulong;
}
#ifdef _C_LNG_LNG
else if (*@encode(NSUInteger) == _C_ULNG_LNG)
{
elems[0] = &gsffi_type_ulong_long;
}
#endif
else
{
elems[0] = &gsffi_type_uint;
}
elems[1] = elems[0];
elems[2] = 0;
ftype->elements = elems;
ftype->type = FFI_TYPE_STRUCT;
}
typePtr = objc_skip_typespec (typePtr - 1);
break;
}
else if (GSSelectorTypesMatch(typePtr - 1, @encode(NSPoint)))
{
ftype = &stypeNSPoint;
if (ftype->type == 0)
{
static ffi_type *elems[3];
if (*@encode(CGFloat) == _C_DBL)
{
elems[0] = &ffi_type_double;
}
else
{
elems[0] = &ffi_type_float;
}
elems[1] = elems[0];
elems[2] = 0;
ftype->elements = elems;
ftype->type = FFI_TYPE_STRUCT;
}
typePtr = objc_skip_typespec (typePtr - 1);
break;
}
else if (GSSelectorTypesMatch(typePtr - 1, @encode(NSSize)))
{
ftype = &stypeNSSize;
if (ftype->type == 0)
{
static ffi_type *elems[3];
if (*@encode(CGFloat) == _C_DBL)
{
elems[0] = &ffi_type_double;
}
else
{
elems[0] = &ffi_type_float;
}
elems[1] = elems[0];
elems[2] = 0;
ftype->elements = elems;
ftype->type = FFI_TYPE_STRUCT;
}
typePtr = objc_skip_typespec (typePtr - 1);
break;
}
else if (GSSelectorTypesMatch(typePtr - 1, @encode(NSRect)))
{
ftype = &stypeNSRect;
if (ftype->type == 0)
{
static ffi_type *elems[3];
/* An NSRect is an NSPoint and an NSSize, but those
* two structures are actually identical.
*/
elems[0] = cifframe_type(@encode(NSSize), NULL);
elems[1] = cifframe_type(@encode(NSPoint), NULL);
elems[2] = 0;
ftype->elements = elems;
ftype->type = FFI_TYPE_STRUCT;
}
typePtr = objc_skip_typespec (typePtr - 1);
break;
}
/*
* Skip "<name>=" stuff.
*/
while (*typePtr != _C_STRUCT_E)
{
if (*typePtr++ == '=')
{
break;
}
}
types = 0;
maxtypes = 4;
size = sizeof(ffi_type);
if (size % align != 0)
{
size += (align - (size % align));
}
ftype = malloc(size + (maxtypes+1)*sizeof(ffi_type));
ftype->size = 0;
ftype->alignment = 0;
ftype->type = FFI_TYPE_STRUCT;
ftype->elements = (void*)ftype + size;
/*
* Continue accumulating structure size.
*/
while (*typePtr != _C_STRUCT_E)
{
local = cifframe_type(typePtr, &adv);
typePtr = adv;
// NSCAssert(typePtr, @"End of signature while parsing");
ftype->elements[types++] = local;
if (types >= maxtypes)
{
maxtypes *=2;
ftype = realloc(ftype,
size + (maxtypes+1)*sizeof(ffi_type));
ftype->elements = (void*)ftype + size;
}
}
ftype->elements[types] = NULL;
typePtr++; /* Skip end-of-struct */
}
break;
case _C_UNION_B:
{
const char *adv;
int max_align = 0;
/*
* Skip "<name>=" stuff.
*/
while (*typePtr != _C_UNION_E)
{
if (*typePtr++ == '=')
{
break;
}
}
ftype = NULL;
while (*typePtr != _C_UNION_E)
{
ffi_type *local;
int align = objc_alignof_type(typePtr);
local = cifframe_type(typePtr, &adv);
typePtr = adv;
// NSCAssert(typePtr, @"End of signature while parsing");
if (align > max_align)
{
if (ftype && ftype->type == FFI_TYPE_STRUCT
&& ftype != &stypeNSPoint
&& ftype != &stypeNSRange
&& ftype != &stypeNSRect
&& ftype != &stypeNSSize)
{
free(ftype);
}
ftype = local;
max_align = align;
}
}
typePtr++; /* Skip end-of-union */
}
break;
case _C_VOID: ftype = &ffi_type_void;
break;
#if __GNUC__ > 2 && defined(_C_BOOL)
case _C_BOOL: ftype = &ffi_type_uchar;
break;
#endif
default:
ftype = &ffi_type_void;
// NSCAssert(0, @"Unknown type in sig");
}
/* Skip past any offset information, if there is any */
if (*type != _C_PTR || *type == '?')
{
if (*typePtr == '+')
typePtr++;
if (*typePtr == '-')
typePtr++;
while (isdigit(*typePtr))
typePtr++;
}
if (advance)
*advance = typePtr;
return ftype;
}
GSCodeBuffer*
cifframe_closure (NSMethodSignature *sig, void (*cb)())
{
NSMutableData *frame;
cifframe_t *cframe;
ffi_closure *cclosure;
void *executable;
GSCodeBuffer *memory;
/* Construct the frame (stored in an NSMutableDate object) and sety it
* in a new closure.
*/
frame = cifframe_from_signature(sig);
cframe = [frame mutableBytes];
memory = [GSCodeBuffer memoryWithSize: sizeof(ffi_closure)];
[memory setFrame: frame];
cclosure = [memory buffer];
executable = [memory executable];
if (cframe == NULL || cclosure == NULL)
{
[NSException raise: NSMallocException format: @"Allocating closure"];
}
#if HAVE_FFI_PREP_CLOSURE_LOC
if (ffi_prep_closure_loc(cclosure, &(cframe->cif),
cb, frame, executable) != FFI_OK)
{
[NSException raise: NSGenericException format: @"Preping closure"];
}
#else
executable = (void*)cclosure;
if (ffi_prep_closure(cclosure, &(cframe->cif),
cb, frame) != FFI_OK)
{
[NSException raise: NSGenericException format: @"Preping closure"];
}
#endif
[memory protect];
return memory;
}
/*-------------------------------------------------------------------------*/
/* Functions for handling sending and receiving messages accross a
connection
*/
/* Some return types actually get coded differently. We need to convert
back to the expected return type */
BOOL
cifframe_decode_arg (const char *type, void* buffer)
{
type = objc_skip_type_qualifiers (type);
switch (*type)
{
case _C_CHR:
*(signed char*)buffer = (signed char)(*((ffi_sarg *)buffer));
break;
case _C_UCHR:
*(unsigned char*)buffer = (unsigned char)(*((ffi_arg *)buffer));
break;
case _C_SHT:
*(signed short*)buffer = (signed short)(*((ffi_sarg *)buffer));
break;
case _C_USHT:
*(unsigned short*)buffer = (unsigned short)(*((ffi_arg *)buffer));
break;
case _C_INT:
*(signed int*)buffer = (signed int)(*((ffi_sarg *)buffer));
break;
case _C_UINT:
*(unsigned int*)buffer = (unsigned int)(*((ffi_arg *)buffer));
break;
case _C_LNG:
if (sizeof(signed long) < sizeof(ffi_sarg))
*(signed long*)buffer = (signed long)(*((ffi_sarg *)buffer));
break;
case _C_ULNG:
if (sizeof(unsigned long) < sizeof(ffi_arg))
*(unsigned long*)buffer = (unsigned long)(*((ffi_arg *)buffer));
break;
default:
return NO;
}
return YES;
}
BOOL
cifframe_encode_arg (const char *type, void* buffer)
{
type = objc_skip_type_qualifiers (type);
switch (*type)
{
case _C_CHR:
*(ffi_sarg *)buffer = (ffi_sarg)(*((signed char *)buffer));
break;
case _C_UCHR:
*(ffi_arg *)buffer = (ffi_arg)(*((unsigned char *)buffer));
break;
case _C_SHT:
*(ffi_sarg *)buffer = (ffi_sarg)(*((signed short *)buffer));
break;
case _C_USHT:
*(ffi_arg *)buffer = (ffi_arg)(*((unsigned short *)buffer));
break;
case _C_INT:
*(ffi_sarg *)buffer = (ffi_sarg)(*((signed int *)buffer));
break;
case _C_UINT:
*(ffi_arg *)buffer = (ffi_arg)(*((unsigned int *)buffer));
break;
case _C_LNG:
if (sizeof(signed long) < sizeof(ffi_sarg))
*(ffi_sarg *)buffer = (ffi_sarg)(*((signed long *)buffer));
break;
case _C_ULNG:
if (sizeof(unsigned long) < sizeof(ffi_arg))
*(ffi_arg *)buffer = (ffi_arg)(*((unsigned int *)buffer));
break;
default:
return NO;
}
return YES;
}

View File

@ -1,8 +0,0 @@
#ifndef CF_DEBUG_H_
#define CF_DEBUG_H_
#define DEBUG_BREAK() __asm__("int3")
#define DEBUG_LOG(fmt, ...)
#endif

1020
encoding.c

File diff suppressed because it is too large Load Diff

5
macros.h Normal file
View File

@ -0,0 +1,5 @@
#define RELEASE_LOG(fmt, ...)
#define DEBUG_LOG(fmt, ...)
#define DEBUG_BREAK() __builtin_trap()
#define UNLIKELY(x) __builtin_expect((x),0)