checkin thirdparty; improvements
This commit is contained in:
parent
6247cc7f84
commit
280688b615
78 changed files with 5401 additions and 51 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,5 +1,4 @@
|
|||
.zed/
|
||||
out/p2601*
|
||||
thirdparty/blocksruntime
|
||||
thirdparty/zig*
|
||||
.DS_Store
|
||||
|
|
|
|||
6
do.ps1
6
do.ps1
|
|
@ -37,7 +37,6 @@ $ZIG_SLUG = "zig-${HOST_ARCH}-${HOST_OS}-${ZIG_VERSION}";
|
|||
$ZIG_DIR = Join-Path $DEPS_DIR $ZIG_SLUG
|
||||
$ZIG = Join-Path $ZIG_DIR "zig$(Get-Ext $HOST_OS)"
|
||||
|
||||
$BLOCKS_RT_REPO = "https://github.com/mackyle/blocksruntime.git";
|
||||
$BLOCKS_RT_DIR = Join-Path $DEPS_DIR "blocksruntime";
|
||||
$BLOCKS_RT_FLAGS = "-I$BLOCKS_RT_DIR -I$(Join-Path $BLOCKS_RT_DIR "BlocksRuntime")";
|
||||
$BLOCKS_RT_SOURCE = (Join-Path $BLOCKS_RT_DIR "BlocksRuntime" "runtime.c") + " " + (Join-Path $BLOCKS_RT_DIR "BlocksRuntime" "data.c");
|
||||
|
|
@ -74,11 +73,6 @@ if (-not (Test-Path $ZIG)) {
|
|||
curl -sSfL $zig_url | tar -xJ -C $DEPS_DIR
|
||||
}
|
||||
}
|
||||
# try vendoring blocks runtime
|
||||
if (-not (Test-Path $BLOCKS_RT_DIR)) {
|
||||
Write-Host ":: Cloning libBlocksRuntime";
|
||||
git clone --depth 1 $BLOCKS_RT_REPO $BLOCKS_RT_DIR
|
||||
}
|
||||
|
||||
# ensure the out directory exists
|
||||
New-Item -ItemType Directory -Force -Path $OUT_DIR | Out-Null;
|
||||
|
|
|
|||
2
justfile
Normal file
2
justfile
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
default:
|
||||
@pwsh do.ps1 b
|
||||
22
src/arena.c
22
src/arena.c
|
|
@ -1,10 +1,6 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef enum { arena__alloc, arena__reset, arena__save, arena__restore, arena__release } arena__action;
|
||||
|
||||
typedef closure(void*, arena__action, uregister, uregister, void*, const char*, sregister) Arena;
|
||||
typedef closure(void*, arena__action, uword, uword, void*, const char*, sword) Arena;
|
||||
|
||||
#define arena_new(A, T) cast(T*, A(arena__alloc, sizeof(T), alignof(T), 0, __FILE__, __LINE__))
|
||||
#define arena_make(A, C, T) cast(T*, A(arena__alloc, sizeof(T) * (C), alignof(T), 0, __FILE__, __LINE__))
|
||||
|
|
@ -14,13 +10,13 @@ typedef closure(void*, arena__action, uregister, uregister, void*, const char*,
|
|||
#define arena_restore(A, SP) A(arena__restore, 0, 0, (SP), __FILE__, __LINE__)
|
||||
|
||||
// tiny macro to make arenas easier to declare
|
||||
#define $(a1, a2, a3, a4, a5, a6) ^void* (arena__action a1, uregister a2, uregister a3, void* a4, const char* a5, sregister a6)
|
||||
#define $(a1, a2, a3, a4, a5, a6) ^void* (arena__action a1, uword a2, uword a3, void* a4, const char* a5, sword a6)
|
||||
|
||||
static Arena
|
||||
Static(uint8* data, uregister count) {
|
||||
Static(uint8* data, uword count) {
|
||||
memset(data, 0, count);
|
||||
|
||||
capture uregister offset = 0;
|
||||
capture uword offset = 0;
|
||||
return persist($(action, size, align, savepoint, _2, _3) {
|
||||
switch (action) {
|
||||
default: {
|
||||
|
|
@ -43,12 +39,12 @@ Static(uint8* data, uregister count) {
|
|||
|
||||
case arena__save: {
|
||||
assert(savepoint != NULL && "Static: savepoint was null");
|
||||
*cast(uregister*, savepoint) = offset;
|
||||
*cast(uword*, savepoint) = offset;
|
||||
} break;
|
||||
|
||||
case arena__restore: {
|
||||
assert(savepoint != NULL && "Static: savepoint was null");
|
||||
offset = *cast(uregister*, savepoint);
|
||||
offset = *cast(uword*, savepoint);
|
||||
} break;
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +53,7 @@ Static(uint8* data, uregister count) {
|
|||
}
|
||||
|
||||
static Arena
|
||||
Linear(uregister max_memory) {
|
||||
Linear(uword max_memory) {
|
||||
void* ptr = malloc(max_memory);
|
||||
Arena backing = Static(ptr, max_memory);
|
||||
return persist($(action, size, align, savepoint, file, line) {
|
||||
|
|
@ -82,14 +78,14 @@ Logger(Arena arena) {
|
|||
case arena__restore: action_str = "restore"; break;
|
||||
}
|
||||
|
||||
printf("[ARENA] %s:%zd: %s (%zu, %zu)\n", file, line, action_str, size, align);
|
||||
printf("[ARENA] %s:%d: %s (%d, %d)\n", file, cast(int, line), action_str, cast(int, size), cast(int, align));
|
||||
return arena(action, size, align, savepoint, file, line);
|
||||
});
|
||||
}
|
||||
|
||||
static Arena
|
||||
Region(Arena arena) {
|
||||
capture uregister savepoint = 0;
|
||||
capture uword savepoint = 0;
|
||||
arena_save(arena, &savepoint);
|
||||
|
||||
return persist($(action, size, align, _, file, line) {
|
||||
|
|
|
|||
63
src/base.c
63
src/base.c
|
|
@ -1,26 +1,58 @@
|
|||
#include <stdint.h>
|
||||
typedef unsigned _BitInt(1) bool1;
|
||||
typedef unsigned _BitInt(2) bool2;
|
||||
typedef unsigned _BitInt(4) bool4;
|
||||
typedef unsigned _BitInt(8) bool8;
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
typedef unsigned _BitInt(1) u1;
|
||||
typedef unsigned _BitInt(2) u2;
|
||||
typedef unsigned _BitInt(4) u4;
|
||||
typedef unsigned _BitInt(8) u8;
|
||||
typedef unsigned _BitInt(16) u16;
|
||||
typedef unsigned _BitInt(32) u32;
|
||||
typedef unsigned _BitInt(64) u64;
|
||||
typedef unsigned _BitInt(128) u128;
|
||||
|
||||
typedef int8_t sint8;
|
||||
typedef int16_t sint16;
|
||||
typedef int32_t sint32;
|
||||
typedef int64_t sint64;
|
||||
typedef signed _BitInt(2) s2;
|
||||
typedef signed _BitInt(4) s4;
|
||||
typedef signed _BitInt(8) s8;
|
||||
typedef signed _BitInt(16) s16;
|
||||
typedef signed _BitInt(32) s32;
|
||||
typedef signed _BitInt(64) s64;
|
||||
typedef signed _BitInt(128) s128;
|
||||
|
||||
typedef float float32;
|
||||
typedef double float64;
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
typedef uintptr_t upointer;
|
||||
typedef intptr_t spointer;
|
||||
#if POINTER_32
|
||||
typedef u32 uaddr;
|
||||
typedef s32 saddr;
|
||||
|
||||
typedef upointer uregister;
|
||||
typedef spointer sregister;
|
||||
typedef u32 uword;
|
||||
typedef s32 sword;
|
||||
#else
|
||||
typedef u64 uaddr;
|
||||
typedef s64 saddr;
|
||||
|
||||
typedef u64 uword;
|
||||
typedef s64 sword;
|
||||
#endif
|
||||
|
||||
static_assert(sizeof(uaddr) == sizeof(void*), "uaddr was not equal to a pointer");
|
||||
|
||||
#define auto __auto_type
|
||||
|
||||
typedef struct { u8* data; uword count; } string;
|
||||
|
||||
#define string_const(S) (string){ .data = (S), .count = count_of((S)) }
|
||||
#define string_from(P) (string){ .data = (P), .count = cast(uword, strlen((P))) }
|
||||
#define string_from_count(P, C) (string){ .data = (P), .count = (C) }
|
||||
|
||||
#define size_of(T) cast(uword, sizeof(T))
|
||||
#define ssize_of(T) cast(sword, sizeof(T))
|
||||
#define align_of(T) cast(uword, alignof(T))
|
||||
#define salign_of(T) cast(sword, alignof(T))
|
||||
#define count_of(P) (size_of(P) / size_of((P)[0]))
|
||||
|
||||
// Thanks azmr
|
||||
#define cast(to_type, expr) ((to_type)(expr))
|
||||
#define chkcast(to_type, from_type, expr) _Generic(expr, from_type: (to_type)(expr))
|
||||
|
|
@ -45,3 +77,4 @@ static inline void __scope_exit_run(__scope_exit *blk) { (*blk)(); }
|
|||
#define scope_exit \
|
||||
__attribute__((cleanup(__scope_exit_run), unused)) \
|
||||
__scope_exit __concat(_defer_, __LINE__) = ^void(void)
|
||||
|
||||
|
|
|
|||
37
src/main.c
37
src/main.c
|
|
@ -1,4 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
#define SOKOL_D3D11
|
||||
|
|
@ -6,6 +9,8 @@
|
|||
#define SOKOL_METAL
|
||||
#elifdef PLATFORM_LINUX
|
||||
#define SOKOL_GLES3
|
||||
#elifdef PLATFORM_WASM
|
||||
#define SOKOL_GLCORE
|
||||
#else
|
||||
#error "unsupported platform"
|
||||
#endif
|
||||
|
|
@ -26,7 +31,7 @@ sg_pass_action pass_action;
|
|||
static void
|
||||
init(void) {
|
||||
scope_exit {
|
||||
printf("leaving init...");
|
||||
printf("leaving init...\n");
|
||||
};
|
||||
|
||||
sg_setup(&(sg_desc){
|
||||
|
|
@ -59,7 +64,7 @@ init(void) {
|
|||
});
|
||||
|
||||
printf("x = %d (before)\n", x);
|
||||
for (uregister i = 0; i < 10; i += 1) {
|
||||
for (uword i = 0; i < 10; i += 1) {
|
||||
inc();
|
||||
}
|
||||
printf("x = %d (after)\n", x);
|
||||
|
|
@ -67,37 +72,37 @@ init(void) {
|
|||
auto arena = Logger(Linear(1024 * 1024));
|
||||
scope_exit { arena_release(arena); };
|
||||
|
||||
sregister* a = arena_new(arena, sregister);
|
||||
sregister* b = arena_new(arena, sregister);
|
||||
sword* a = arena_new(arena, sword);
|
||||
sword* b = arena_new(arena, sword);
|
||||
|
||||
{
|
||||
auto region = Region(arena);
|
||||
scope_exit { arena_reset(region); };
|
||||
|
||||
arena_make(region, 10, sregister);
|
||||
arena_make(region, 10, float32);
|
||||
arena_make(region, 10, sword);
|
||||
arena_make(region, 10, f32);
|
||||
arena_make(region, 10, bool);
|
||||
}
|
||||
|
||||
sregister* c = arena_new(arena, sregister);
|
||||
sword* c = arena_new(arena, sword);
|
||||
|
||||
*a = 1024;
|
||||
*b = 2048;
|
||||
*c = 4096;
|
||||
|
||||
printf("%zu (%p)\n", *a, a);
|
||||
printf("%zu (%p)\n", *b, b);
|
||||
printf("%zu (%p)\n", *c, c);
|
||||
printf("%d (%p)\n", cast(int, *a), a);
|
||||
printf("%d (%p)\n", cast(int, *b), b);
|
||||
printf("%d (%p)\n", cast(int, *c), c);
|
||||
|
||||
arena_reset(arena);
|
||||
|
||||
c = arena_new(arena, sregister);
|
||||
b = arena_new(arena, sregister);
|
||||
a = arena_new(arena, sregister);
|
||||
c = arena_new(arena, sword);
|
||||
b = arena_new(arena, sword);
|
||||
a = arena_new(arena, sword);
|
||||
|
||||
printf("%zu (%p)\n", *a, a);
|
||||
printf("%zu (%p)\n", *b, b);
|
||||
printf("%zu (%p)\n", *c, c);
|
||||
printf("%d (%p)\n", cast(int, *a), a);
|
||||
printf("%d (%p)\n", cast(int, *b), b);
|
||||
printf("%d (%p)\n", cast(int, *c), c);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
7
thirdparty/blocksruntime/.gitattributes
vendored
Normal file
7
thirdparty/blocksruntime/.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/README.md export-ignore
|
||||
.gitignore export-ignore
|
||||
.gitattributes export-ignore
|
||||
/buildlib text eol=lf
|
||||
/buildlib-osx text eol=lf
|
||||
/checktests text eol=lf
|
||||
/installlib text eol=lf
|
||||
10
thirdparty/blocksruntime/.gitignore
vendored
Normal file
10
thirdparty/blocksruntime/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
*.o
|
||||
*.s
|
||||
*.dSYM
|
||||
*.exe
|
||||
*.html
|
||||
/libBlocksRuntime.a
|
||||
/libBlocksRuntime.so
|
||||
/libBlocksRuntime.dylib
|
||||
/testbin
|
||||
/sample
|
||||
59
thirdparty/blocksruntime/BlocksRuntime/Block.h
vendored
Normal file
59
thirdparty/blocksruntime/BlocksRuntime/Block.h
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Block.h
|
||||
*
|
||||
* Copyright 2008-2010 Apple, Inc. Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BLOCK_H_
|
||||
#define _BLOCK_H_
|
||||
|
||||
#if !defined(BLOCK_EXPORT)
|
||||
# if defined(__cplusplus)
|
||||
# define BLOCK_EXPORT extern "C"
|
||||
# else
|
||||
# define BLOCK_EXPORT extern
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Create a heap based copy of a Block or simply add a reference to an existing one.
|
||||
* This must be paired with Block_release to recover memory, even when running
|
||||
* under Objective-C Garbage Collection.
|
||||
*/
|
||||
BLOCK_EXPORT void *_Block_copy(const void *aBlock);
|
||||
|
||||
/* Lose the reference, and if heap based and last reference, recover the memory. */
|
||||
BLOCK_EXPORT void _Block_release(const void *aBlock);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Type correct macros. */
|
||||
|
||||
#define Block_copy(...) ((__typeof(__VA_ARGS__))_Block_copy((const void *)(__VA_ARGS__)))
|
||||
#define Block_release(...) _Block_release((const void *)(__VA_ARGS__))
|
||||
|
||||
|
||||
#endif
|
||||
179
thirdparty/blocksruntime/BlocksRuntime/Block_private.h
vendored
Normal file
179
thirdparty/blocksruntime/BlocksRuntime/Block_private.h
vendored
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Block_private.h
|
||||
*
|
||||
* Copyright 2008-2010 Apple, Inc. Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BLOCK_PRIVATE_H_
|
||||
#define _BLOCK_PRIVATE_H_
|
||||
|
||||
#if !defined(BLOCK_EXPORT)
|
||||
# if defined(__cplusplus)
|
||||
# define BLOCK_EXPORT extern "C"
|
||||
# else
|
||||
# define BLOCK_EXPORT extern
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
/* MSVC doesn't have <stdbool.h>. Compensate. */
|
||||
typedef char bool;
|
||||
#define true (bool)1
|
||||
#define false (bool)0
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
enum {
|
||||
BLOCK_REFCOUNT_MASK = (0xffff),
|
||||
BLOCK_NEEDS_FREE = (1 << 24),
|
||||
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
|
||||
BLOCK_HAS_CTOR = (1 << 26), /* Helpers have C++ code. */
|
||||
BLOCK_IS_GC = (1 << 27),
|
||||
BLOCK_IS_GLOBAL = (1 << 28),
|
||||
BLOCK_HAS_DESCRIPTOR = (1 << 29)
|
||||
};
|
||||
|
||||
|
||||
/* Revised new layout. */
|
||||
struct Block_descriptor {
|
||||
unsigned long int reserved;
|
||||
unsigned long int size;
|
||||
void (*copy)(void *dst, void *src);
|
||||
void (*dispose)(void *);
|
||||
};
|
||||
|
||||
|
||||
struct Block_layout {
|
||||
void *isa;
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(void *, ...);
|
||||
struct Block_descriptor *descriptor;
|
||||
/* Imported variables. */
|
||||
};
|
||||
|
||||
|
||||
struct Block_byref {
|
||||
void *isa;
|
||||
struct Block_byref *forwarding;
|
||||
int flags; /* refcount; */
|
||||
int size;
|
||||
void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src);
|
||||
void (*byref_destroy)(struct Block_byref *);
|
||||
/* long shared[0]; */
|
||||
};
|
||||
|
||||
|
||||
struct Block_byref_header {
|
||||
void *isa;
|
||||
struct Block_byref *forwarding;
|
||||
int flags;
|
||||
int size;
|
||||
};
|
||||
|
||||
|
||||
/* Runtime support functions used by compiler when generating copy/dispose helpers. */
|
||||
|
||||
enum {
|
||||
/* See function implementation for a more complete description of these fields and combinations */
|
||||
BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), block, ... */
|
||||
BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
|
||||
BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the __block variable */
|
||||
BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy helpers */
|
||||
BLOCK_BYREF_CALLER = 128 /* called from __block (byref) copy/dispose support routines. */
|
||||
};
|
||||
|
||||
/* Runtime entry point called by compiler when assigning objects inside copy helper routines */
|
||||
BLOCK_EXPORT void _Block_object_assign(void *destAddr, const void *object, const int flags);
|
||||
/* BLOCK_FIELD_IS_BYREF is only used from within block copy helpers */
|
||||
|
||||
|
||||
/* runtime entry point called by the compiler when disposing of objects inside dispose helper routine */
|
||||
BLOCK_EXPORT void _Block_object_dispose(const void *object, const int flags);
|
||||
|
||||
|
||||
|
||||
/* Other support functions */
|
||||
|
||||
/* Runtime entry to get total size of a closure */
|
||||
BLOCK_EXPORT unsigned long int Block_size(void *block_basic);
|
||||
|
||||
|
||||
|
||||
/* the raw data space for runtime classes for blocks */
|
||||
/* class+meta used for stack, malloc, and collectable based blocks */
|
||||
BLOCK_EXPORT void * _NSConcreteStackBlock[32];
|
||||
BLOCK_EXPORT void * _NSConcreteMallocBlock[32];
|
||||
BLOCK_EXPORT void * _NSConcreteAutoBlock[32];
|
||||
BLOCK_EXPORT void * _NSConcreteFinalizingBlock[32];
|
||||
BLOCK_EXPORT void * _NSConcreteGlobalBlock[32];
|
||||
BLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32];
|
||||
|
||||
|
||||
/* the intercept routines that must be used under GC */
|
||||
BLOCK_EXPORT void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
|
||||
void (*setHasRefcount)(const void *, const bool),
|
||||
void (*gc_assign_strong)(void *, void **),
|
||||
void (*gc_assign_weak)(const void *, void *),
|
||||
void (*gc_memmove)(void *, void *, unsigned long));
|
||||
|
||||
/* earlier version, now simply transitional */
|
||||
BLOCK_EXPORT void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
|
||||
void (*setHasRefcount)(const void *, const bool),
|
||||
void (*gc_assign_strong)(void *, void **),
|
||||
void (*gc_assign_weak)(const void *, void *));
|
||||
|
||||
BLOCK_EXPORT void _Block_use_RR( void (*retain)(const void *),
|
||||
void (*release)(const void *));
|
||||
|
||||
/* make a collectable GC heap based Block. Not useful under non-GC. */
|
||||
BLOCK_EXPORT void *_Block_copy_collectable(const void *aBlock);
|
||||
|
||||
/* thread-unsafe diagnostic */
|
||||
BLOCK_EXPORT const char *_Block_dump(const void *block);
|
||||
|
||||
|
||||
/* Obsolete */
|
||||
|
||||
/* first layout */
|
||||
struct Block_basic {
|
||||
void *isa;
|
||||
int Block_flags; /* int32_t */
|
||||
int Block_size; /* XXX should be packed into Block_flags */
|
||||
void (*Block_invoke)(void *);
|
||||
void (*Block_copy)(void *dst, void *src); /* iff BLOCK_HAS_COPY_DISPOSE */
|
||||
void (*Block_dispose)(void *); /* iff BLOCK_HAS_COPY_DISPOSE */
|
||||
/* long params[0]; // where const imports, __block storage references, etc. get laid down */
|
||||
};
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _BLOCK_PRIVATE_H_ */
|
||||
36
thirdparty/blocksruntime/BlocksRuntime/CREDITS.TXT
vendored
Normal file
36
thirdparty/blocksruntime/BlocksRuntime/CREDITS.TXT
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
This file is a partial list of people who have contributed to the LLVM/CompilerRT
|
||||
project. If you have contributed a patch or made some other contribution to
|
||||
LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
|
||||
done!
|
||||
|
||||
The list is sorted by surname and formatted to allow easy grepping and
|
||||
beautification by scripts. The fields are: name (N), email (E), web-address
|
||||
(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
|
||||
(S).
|
||||
|
||||
N: Craig van Vliet
|
||||
E: cvanvliet@auroraux.org
|
||||
W: http://www.auroraux.org
|
||||
D: Code style and Readability fixes.
|
||||
|
||||
N: Edward O'Callaghan
|
||||
E: eocallaghan@auroraux.org
|
||||
W: http://www.auroraux.org
|
||||
D: CMake'ify Compiler-RT build system
|
||||
D: Maintain Solaris & AuroraUX ports of Compiler-RT
|
||||
|
||||
N: Howard Hinnant
|
||||
E: hhinnant@apple.com
|
||||
D: Architect and primary author of compiler-rt
|
||||
|
||||
N: Guan-Hong Liu
|
||||
E: koviankevin@hotmail.com
|
||||
D: IEEE Quad-precision functions
|
||||
|
||||
N: Joerg Sonnenberger
|
||||
E: joerg@NetBSD.org
|
||||
D: Maintains NetBSD port.
|
||||
|
||||
N: Matt Thomas
|
||||
E: matt@NetBSD.org
|
||||
D: ARM improvements.
|
||||
76
thirdparty/blocksruntime/BlocksRuntime/LICENSE.TXT
vendored
Normal file
76
thirdparty/blocksruntime/BlocksRuntime/LICENSE.TXT
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
==============================================================================
|
||||
compiler_rt License
|
||||
==============================================================================
|
||||
|
||||
The compiler_rt library is dual licensed under both the University of Illinois
|
||||
"BSD-Like" license and the MIT license. As a user of this code you may choose
|
||||
to use it under either license. As a contributor, you agree to allow your code
|
||||
to be used under both.
|
||||
|
||||
Full text of the relevant licenses is included below.
|
||||
|
||||
==============================================================================
|
||||
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
|
||||
LLVM Team
|
||||
|
||||
University of Illinois at Urbana-Champaign
|
||||
|
||||
http://llvm.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal with
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimers.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimers in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the names of the LLVM Team, University of Illinois at
|
||||
Urbana-Champaign, nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this Software without specific
|
||||
prior written permission.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
||||
SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
|
||||
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
11
thirdparty/blocksruntime/BlocksRuntime/README.txt
vendored
Normal file
11
thirdparty/blocksruntime/BlocksRuntime/README.txt
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
Compiler-RT
|
||||
================================
|
||||
|
||||
This directory and its subdirectories contain source code for the compiler
|
||||
support routines.
|
||||
|
||||
Compiler-RT is open source software. You may freely distribute it under the
|
||||
terms of the license agreement found in LICENSE.txt.
|
||||
|
||||
================================
|
||||
|
||||
41
thirdparty/blocksruntime/BlocksRuntime/data.c
vendored
Normal file
41
thirdparty/blocksruntime/BlocksRuntime/data.c
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* data.c
|
||||
*
|
||||
* Copyright 2008-2010 Apple, Inc. Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/********************
|
||||
NSBlock support
|
||||
|
||||
We allocate space and export a symbol to be used as the Class for the on-stack and malloc'ed copies until ObjC arrives on the scene. These data areas are set up by Foundation to link in as real classes post facto.
|
||||
|
||||
We keep these in a separate file so that we can include the runtime code in test subprojects but not include the data so that compiled code that sees the data in libSystem doesn't get confused by a second copy. Somehow these don't get unified in a common block.
|
||||
**********************/
|
||||
|
||||
void * _NSConcreteStackBlock[32] = { 0 };
|
||||
void * _NSConcreteMallocBlock[32] = { 0 };
|
||||
void * _NSConcreteAutoBlock[32] = { 0 };
|
||||
void * _NSConcreteFinalizingBlock[32] = { 0 };
|
||||
void * _NSConcreteGlobalBlock[32] = { 0 };
|
||||
void * _NSConcreteWeakBlockVariable[32] = { 0 };
|
||||
|
||||
void _Block_copy_error(void) {
|
||||
}
|
||||
700
thirdparty/blocksruntime/BlocksRuntime/runtime.c
vendored
Normal file
700
thirdparty/blocksruntime/BlocksRuntime/runtime.c
vendored
Normal file
|
|
@ -0,0 +1,700 @@
|
|||
/*
|
||||
* runtime.c
|
||||
*
|
||||
* Copyright 2008-2010 Apple, Inc. Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Block_private.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_AVAILABILITY_MACROS_H
|
||||
#include <AvailabilityMacros.h>
|
||||
#endif /* HAVE_AVAILABILITY_MACROS_H */
|
||||
|
||||
#ifdef HAVE_TARGET_CONDITIONALS_H
|
||||
#include <TargetConditionals.h>
|
||||
#endif /* HAVE_TARGET_CONDITIONALS_H */
|
||||
|
||||
#if defined(HAVE_OSATOMIC_COMPARE_AND_SWAP_INT) && defined(HAVE_OSATOMIC_COMPARE_AND_SWAP_LONG)
|
||||
|
||||
#ifdef HAVE_LIBKERN_OSATOMIC_H
|
||||
#include <libkern/OSAtomic.h>
|
||||
#endif /* HAVE_LIBKERN_OSATOMIC_H */
|
||||
|
||||
#elif defined(__WIN32__) || defined(_WIN32)
|
||||
#define _CRT_SECURE_NO_WARNINGS 1
|
||||
#include <windows.h>
|
||||
|
||||
static __inline bool OSAtomicCompareAndSwapLong(long oldl, long newl, long volatile *dst) {
|
||||
/* fixme barrier is overkill -- see objc-os.h */
|
||||
long original = InterlockedCompareExchange(dst, newl, oldl);
|
||||
return (original == oldl);
|
||||
}
|
||||
|
||||
static __inline bool OSAtomicCompareAndSwapInt(int oldi, int newi, int volatile *dst) {
|
||||
/* fixme barrier is overkill -- see objc-os.h */
|
||||
int original = InterlockedCompareExchange(dst, newi, oldi);
|
||||
return (original == oldi);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the GCC atomic built-ins are available. If we're on
|
||||
* a 64-bit system, make sure we have an 8-byte atomic function
|
||||
* available.
|
||||
*
|
||||
*/
|
||||
|
||||
#elif defined(HAVE_SYNC_BOOL_COMPARE_AND_SWAP_INT) && defined(HAVE_SYNC_BOOL_COMPARE_AND_SWAP_LONG)
|
||||
|
||||
static __inline bool OSAtomicCompareAndSwapLong(long oldl, long newl, long volatile *dst) {
|
||||
return __sync_bool_compare_and_swap(dst, oldl, newl);
|
||||
}
|
||||
|
||||
static __inline bool OSAtomicCompareAndSwapInt(int oldi, int newi, int volatile *dst) {
|
||||
return __sync_bool_compare_and_swap(dst, oldi, newi);
|
||||
}
|
||||
|
||||
#else
|
||||
#error unknown atomic compare-and-swap primitive
|
||||
#endif /* HAVE_OSATOMIC_COMPARE_AND_SWAP_INT && HAVE_OSATOMIC_COMPARE_AND_SWAP_LONG */
|
||||
|
||||
|
||||
/*
|
||||
* Globals:
|
||||
*/
|
||||
|
||||
static void *_Block_copy_class = _NSConcreteMallocBlock;
|
||||
static void *_Block_copy_finalizing_class = _NSConcreteMallocBlock;
|
||||
static int _Block_copy_flag = BLOCK_NEEDS_FREE;
|
||||
static int _Byref_flag_initial_value = BLOCK_NEEDS_FREE | 2;
|
||||
|
||||
static const int WANTS_ONE = (1 << 16);
|
||||
|
||||
static bool isGC = false;
|
||||
|
||||
/*
|
||||
* Internal Utilities:
|
||||
*/
|
||||
|
||||
#if 0
|
||||
static unsigned long int latching_incr_long(unsigned long int *where) {
|
||||
while (1) {
|
||||
unsigned long int old_value = *(volatile unsigned long int *)where;
|
||||
if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
|
||||
return BLOCK_REFCOUNT_MASK;
|
||||
}
|
||||
if (OSAtomicCompareAndSwapLong(old_value, old_value+1, (volatile long int *)where)) {
|
||||
return old_value+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* if 0 */
|
||||
|
||||
static int latching_incr_int(int *where) {
|
||||
while (1) {
|
||||
int old_value = *(volatile int *)where;
|
||||
if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
|
||||
return BLOCK_REFCOUNT_MASK;
|
||||
}
|
||||
if (OSAtomicCompareAndSwapInt(old_value, old_value+1, (volatile int *)where)) {
|
||||
return old_value+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int latching_decr_long(unsigned long int *where) {
|
||||
while (1) {
|
||||
unsigned long int old_value = *(volatile int *)where;
|
||||
if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
|
||||
return BLOCK_REFCOUNT_MASK;
|
||||
}
|
||||
if ((old_value & BLOCK_REFCOUNT_MASK) == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (OSAtomicCompareAndSwapLong(old_value, old_value-1, (volatile long int *)where)) {
|
||||
return old_value-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* if 0 */
|
||||
|
||||
static int latching_decr_int(int *where) {
|
||||
while (1) {
|
||||
int old_value = *(volatile int *)where;
|
||||
if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
|
||||
return BLOCK_REFCOUNT_MASK;
|
||||
}
|
||||
if ((old_value & BLOCK_REFCOUNT_MASK) == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (OSAtomicCompareAndSwapInt(old_value, old_value-1, (volatile int *)where)) {
|
||||
return old_value-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GC support stub routines:
|
||||
*/
|
||||
#if 0
|
||||
#pragma mark GC Support Routines
|
||||
#endif /* if 0 */
|
||||
|
||||
|
||||
static void *_Block_alloc_default(const unsigned long size, const bool initialCountIsOne, const bool isObject) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void _Block_assign_default(void *value, void **destptr) {
|
||||
*destptr = value;
|
||||
}
|
||||
|
||||
static void _Block_setHasRefcount_default(const void *ptr, const bool hasRefcount) {
|
||||
}
|
||||
|
||||
static void _Block_do_nothing(const void *aBlock) { }
|
||||
|
||||
static void _Block_retain_object_default(const void *ptr) {
|
||||
if (!ptr) return;
|
||||
}
|
||||
|
||||
static void _Block_release_object_default(const void *ptr) {
|
||||
if (!ptr) return;
|
||||
}
|
||||
|
||||
static void _Block_assign_weak_default(const void *ptr, void *dest) {
|
||||
*(void **)dest = (void *)ptr;
|
||||
}
|
||||
|
||||
static void _Block_memmove_default(void *dst, void *src, unsigned long size) {
|
||||
memmove(dst, src, (size_t)size);
|
||||
}
|
||||
|
||||
static void _Block_memmove_gc_broken(void *dest, void *src, unsigned long size) {
|
||||
void **destp = (void **)dest;
|
||||
void **srcp = (void **)src;
|
||||
while (size) {
|
||||
_Block_assign_default(*srcp, destp);
|
||||
destp++;
|
||||
srcp++;
|
||||
size -= sizeof(void *);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* GC support callout functions - initially set to stub routines:
|
||||
*/
|
||||
|
||||
static void *(*_Block_allocator)(const unsigned long, const bool isOne, const bool isObject) = _Block_alloc_default;
|
||||
static void (*_Block_deallocator)(const void *) = (void (*)(const void *))free;
|
||||
static void (*_Block_assign)(void *value, void **destptr) = _Block_assign_default;
|
||||
static void (*_Block_setHasRefcount)(const void *ptr, const bool hasRefcount) = _Block_setHasRefcount_default;
|
||||
static void (*_Block_retain_object)(const void *ptr) = _Block_retain_object_default;
|
||||
static void (*_Block_release_object)(const void *ptr) = _Block_release_object_default;
|
||||
static void (*_Block_assign_weak)(const void *dest, void *ptr) = _Block_assign_weak_default;
|
||||
static void (*_Block_memmove)(void *dest, void *src, unsigned long size) = _Block_memmove_default;
|
||||
|
||||
|
||||
/*
|
||||
* GC support SPI functions - called from ObjC runtime and CoreFoundation:
|
||||
*/
|
||||
|
||||
/* Public SPI
|
||||
* Called from objc-auto to turn on GC.
|
||||
* version 3, 4 arg, but changed 1st arg
|
||||
*/
|
||||
void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
|
||||
void (*setHasRefcount)(const void *, const bool),
|
||||
void (*gc_assign)(void *, void **),
|
||||
void (*gc_assign_weak)(const void *, void *),
|
||||
void (*gc_memmove)(void *, void *, unsigned long)) {
|
||||
|
||||
isGC = true;
|
||||
_Block_allocator = alloc;
|
||||
_Block_deallocator = _Block_do_nothing;
|
||||
_Block_assign = gc_assign;
|
||||
_Block_copy_flag = BLOCK_IS_GC;
|
||||
_Block_copy_class = _NSConcreteAutoBlock;
|
||||
/* blocks with ctors & dtors need to have the dtor run from a class with a finalizer */
|
||||
_Block_copy_finalizing_class = _NSConcreteFinalizingBlock;
|
||||
_Block_setHasRefcount = setHasRefcount;
|
||||
_Byref_flag_initial_value = BLOCK_IS_GC; // no refcount
|
||||
_Block_retain_object = _Block_do_nothing;
|
||||
_Block_release_object = _Block_do_nothing;
|
||||
_Block_assign_weak = gc_assign_weak;
|
||||
_Block_memmove = gc_memmove;
|
||||
}
|
||||
|
||||
/* transitional */
|
||||
void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
|
||||
void (*setHasRefcount)(const void *, const bool),
|
||||
void (*gc_assign)(void *, void **),
|
||||
void (*gc_assign_weak)(const void *, void *)) {
|
||||
/* until objc calls _Block_use_GC it will call us; supply a broken internal memmove implementation until then */
|
||||
_Block_use_GC(alloc, setHasRefcount, gc_assign, gc_assign_weak, _Block_memmove_gc_broken);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called from objc-auto to alternatively turn on retain/release.
|
||||
* Prior to this the only "object" support we can provide is for those
|
||||
* super special objects that live in libSystem, namely dispatch queues.
|
||||
* Blocks and Block_byrefs have their own special entry points.
|
||||
*
|
||||
*/
|
||||
void _Block_use_RR( void (*retain)(const void *),
|
||||
void (*release)(const void *)) {
|
||||
_Block_retain_object = retain;
|
||||
_Block_release_object = release;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal Support routines for copying:
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#pragma mark Copy/Release support
|
||||
#endif /* if 0 */
|
||||
|
||||
/* Copy, or bump refcount, of a block. If really copying, call the copy helper if present. */
|
||||
static void *_Block_copy_internal(const void *arg, const int flags) {
|
||||
struct Block_layout *aBlock;
|
||||
const bool wantsOne = (WANTS_ONE & flags) == WANTS_ONE;
|
||||
|
||||
//printf("_Block_copy_internal(%p, %x)\n", arg, flags);
|
||||
if (!arg) return NULL;
|
||||
|
||||
|
||||
// The following would be better done as a switch statement
|
||||
aBlock = (struct Block_layout *)arg;
|
||||
if (aBlock->flags & BLOCK_NEEDS_FREE) {
|
||||
// latches on high
|
||||
latching_incr_int(&aBlock->flags);
|
||||
return aBlock;
|
||||
}
|
||||
else if (aBlock->flags & BLOCK_IS_GC) {
|
||||
// GC refcounting is expensive so do most refcounting here.
|
||||
if (wantsOne && ((latching_incr_int(&aBlock->flags) & BLOCK_REFCOUNT_MASK) == 1)) {
|
||||
// Tell collector to hang on this - it will bump the GC refcount version
|
||||
_Block_setHasRefcount(aBlock, true);
|
||||
}
|
||||
return aBlock;
|
||||
}
|
||||
else if (aBlock->flags & BLOCK_IS_GLOBAL) {
|
||||
return aBlock;
|
||||
}
|
||||
|
||||
// Its a stack block. Make a copy.
|
||||
if (!isGC) {
|
||||
struct Block_layout *result = malloc(aBlock->descriptor->size);
|
||||
if (!result) return (void *)0;
|
||||
memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first
|
||||
// reset refcount
|
||||
result->flags &= ~(BLOCK_REFCOUNT_MASK); // XXX not needed
|
||||
result->flags |= BLOCK_NEEDS_FREE | 1;
|
||||
result->isa = _NSConcreteMallocBlock;
|
||||
if (result->flags & BLOCK_HAS_COPY_DISPOSE) {
|
||||
//printf("calling block copy helper %p(%p, %p)...\n", aBlock->descriptor->copy, result, aBlock);
|
||||
(*aBlock->descriptor->copy)(result, aBlock); // do fixup
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
// Under GC want allocation with refcount 1 so we ask for "true" if wantsOne
|
||||
// This allows the copy helper routines to make non-refcounted block copies under GC
|
||||
unsigned long int flags = aBlock->flags;
|
||||
bool hasCTOR = (flags & BLOCK_HAS_CTOR) != 0;
|
||||
struct Block_layout *result = _Block_allocator(aBlock->descriptor->size, wantsOne, hasCTOR);
|
||||
if (!result) return (void *)0;
|
||||
memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first
|
||||
// reset refcount
|
||||
// if we copy a malloc block to a GC block then we need to clear NEEDS_FREE.
|
||||
flags &= ~(BLOCK_NEEDS_FREE|BLOCK_REFCOUNT_MASK); // XXX not needed
|
||||
if (wantsOne)
|
||||
flags |= BLOCK_IS_GC | 1;
|
||||
else
|
||||
flags |= BLOCK_IS_GC;
|
||||
result->flags = flags;
|
||||
if (flags & BLOCK_HAS_COPY_DISPOSE) {
|
||||
//printf("calling block copy helper...\n");
|
||||
(*aBlock->descriptor->copy)(result, aBlock); // do fixup
|
||||
}
|
||||
if (hasCTOR) {
|
||||
result->isa = _NSConcreteFinalizingBlock;
|
||||
}
|
||||
else {
|
||||
result->isa = _NSConcreteAutoBlock;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Runtime entry points for maintaining the sharing knowledge of byref data blocks.
|
||||
*
|
||||
* A closure has been copied and its fixup routine is asking us to fix up the reference to the shared byref data
|
||||
* Closures that aren't copied must still work, so everyone always accesses variables after dereferencing the forwarding ptr.
|
||||
* We ask if the byref pointer that we know about has already been copied to the heap, and if so, increment it.
|
||||
* Otherwise we need to copy it and update the stack forwarding pointer
|
||||
* XXX We need to account for weak/nonretained read-write barriers.
|
||||
*/
|
||||
|
||||
static void _Block_byref_assign_copy(void *dest, const void *arg, const int flags) {
|
||||
struct Block_byref **destp = (struct Block_byref **)dest;
|
||||
struct Block_byref *src = (struct Block_byref *)arg;
|
||||
|
||||
//printf("_Block_byref_assign_copy called, byref destp %p, src %p, flags %x\n", destp, src, flags);
|
||||
//printf("src dump: %s\n", _Block_byref_dump(src));
|
||||
if (src->forwarding->flags & BLOCK_IS_GC) {
|
||||
; // don't need to do any more work
|
||||
}
|
||||
else if ((src->forwarding->flags & BLOCK_REFCOUNT_MASK) == 0) {
|
||||
//printf("making copy\n");
|
||||
// src points to stack
|
||||
bool isWeak = ((flags & (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK)) == (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK));
|
||||
// if its weak ask for an object (only matters under GC)
|
||||
struct Block_byref *copy = (struct Block_byref *)_Block_allocator(src->size, false, isWeak);
|
||||
copy->flags = src->flags | _Byref_flag_initial_value; // non-GC one for caller, one for stack
|
||||
copy->forwarding = copy; // patch heap copy to point to itself (skip write-barrier)
|
||||
src->forwarding = copy; // patch stack to point to heap copy
|
||||
copy->size = src->size;
|
||||
if (isWeak) {
|
||||
copy->isa = &_NSConcreteWeakBlockVariable; // mark isa field so it gets weak scanning
|
||||
}
|
||||
if (src->flags & BLOCK_HAS_COPY_DISPOSE) {
|
||||
// Trust copy helper to copy everything of interest
|
||||
// If more than one field shows up in a byref block this is wrong XXX
|
||||
copy->byref_keep = src->byref_keep;
|
||||
copy->byref_destroy = src->byref_destroy;
|
||||
(*src->byref_keep)(copy, src);
|
||||
}
|
||||
else {
|
||||
// just bits. Blast 'em using _Block_memmove in case they're __strong
|
||||
_Block_memmove(
|
||||
(void *)©->byref_keep,
|
||||
(void *)&src->byref_keep,
|
||||
src->size - sizeof(struct Block_byref_header));
|
||||
}
|
||||
}
|
||||
// already copied to heap
|
||||
else if ((src->forwarding->flags & BLOCK_NEEDS_FREE) == BLOCK_NEEDS_FREE) {
|
||||
latching_incr_int(&src->forwarding->flags);
|
||||
}
|
||||
// assign byref data block pointer into new Block
|
||||
_Block_assign(src->forwarding, (void **)destp);
|
||||
}
|
||||
|
||||
// Old compiler SPI
|
||||
static void _Block_byref_release(const void *arg) {
|
||||
struct Block_byref *shared_struct = (struct Block_byref *)arg;
|
||||
int refcount;
|
||||
|
||||
// dereference the forwarding pointer since the compiler isn't doing this anymore (ever?)
|
||||
shared_struct = shared_struct->forwarding;
|
||||
|
||||
//printf("_Block_byref_release %p called, flags are %x\n", shared_struct, shared_struct->flags);
|
||||
// To support C++ destructors under GC we arrange for there to be a finalizer for this
|
||||
// by using an isa that directs the code to a finalizer that calls the byref_destroy method.
|
||||
if ((shared_struct->flags & BLOCK_NEEDS_FREE) == 0) {
|
||||
return; // stack or GC or global
|
||||
}
|
||||
refcount = shared_struct->flags & BLOCK_REFCOUNT_MASK;
|
||||
if (refcount <= 0) {
|
||||
printf("_Block_byref_release: Block byref data structure at %p underflowed\n", arg);
|
||||
}
|
||||
else if ((latching_decr_int(&shared_struct->flags) & BLOCK_REFCOUNT_MASK) == 0) {
|
||||
//printf("disposing of heap based byref block\n");
|
||||
if (shared_struct->flags & BLOCK_HAS_COPY_DISPOSE) {
|
||||
//printf("calling out to helper\n");
|
||||
(*shared_struct->byref_destroy)(shared_struct);
|
||||
}
|
||||
_Block_deallocator((struct Block_layout *)shared_struct);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* API supporting SPI
|
||||
* _Block_copy, _Block_release, and (old) _Block_destroy
|
||||
*
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#pragma mark SPI/API
|
||||
#endif /* if 0 */
|
||||
|
||||
void *_Block_copy(const void *arg) {
|
||||
return _Block_copy_internal(arg, WANTS_ONE);
|
||||
}
|
||||
|
||||
|
||||
// API entry point to release a copied Block
|
||||
void _Block_release(void *arg) {
|
||||
struct Block_layout *aBlock = (struct Block_layout *)arg;
|
||||
int32_t newCount;
|
||||
if (!aBlock) return;
|
||||
newCount = latching_decr_int(&aBlock->flags) & BLOCK_REFCOUNT_MASK;
|
||||
if (newCount > 0) return;
|
||||
// Hit zero
|
||||
if (aBlock->flags & BLOCK_IS_GC) {
|
||||
// Tell GC we no longer have our own refcounts. GC will decr its refcount
|
||||
// and unless someone has done a CFRetain or marked it uncollectable it will
|
||||
// now be subject to GC reclamation.
|
||||
_Block_setHasRefcount(aBlock, false);
|
||||
}
|
||||
else if (aBlock->flags & BLOCK_NEEDS_FREE) {
|
||||
if (aBlock->flags & BLOCK_HAS_COPY_DISPOSE)(*aBlock->descriptor->dispose)(aBlock);
|
||||
_Block_deallocator(aBlock);
|
||||
}
|
||||
else if (aBlock->flags & BLOCK_IS_GLOBAL) {
|
||||
;
|
||||
}
|
||||
else {
|
||||
printf("Block_release called upon a stack Block: %p, ignored\n", (void *)aBlock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Old Compiler SPI point to release a copied Block used by the compiler in dispose helpers
|
||||
static void _Block_destroy(const void *arg) {
|
||||
struct Block_layout *aBlock;
|
||||
if (!arg) return;
|
||||
aBlock = (struct Block_layout *)arg;
|
||||
if (aBlock->flags & BLOCK_IS_GC) {
|
||||
// assert(aBlock->Block_flags & BLOCK_HAS_CTOR);
|
||||
return; // ignore, we are being called because of a DTOR
|
||||
}
|
||||
_Block_release(aBlock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* SPI used by other layers
|
||||
*
|
||||
*/
|
||||
|
||||
// SPI, also internal. Called from NSAutoBlock only under GC
|
||||
void *_Block_copy_collectable(const void *aBlock) {
|
||||
return _Block_copy_internal(aBlock, 0);
|
||||
}
|
||||
|
||||
|
||||
// SPI
|
||||
unsigned long int Block_size(void *arg) {
|
||||
return ((struct Block_layout *)arg)->descriptor->size;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
#pragma mark Compiler SPI entry points
|
||||
#endif /* if 0 */
|
||||
|
||||
|
||||
/*******************************************************
|
||||
|
||||
Entry points used by the compiler - the real API!
|
||||
|
||||
|
||||
A Block can reference four different kinds of things that require help when the Block is copied to the heap.
|
||||
1) C++ stack based objects
|
||||
2) References to Objective-C objects
|
||||
3) Other Blocks
|
||||
4) __block variables
|
||||
|
||||
In these cases helper functions are synthesized by the compiler for use in Block_copy and Block_release, called the copy and dispose helpers. The copy helper emits a call to the C++ const copy constructor for C++ stack based objects and for the rest calls into the runtime support function _Block_object_assign. The dispose helper has a call to the C++ destructor for case 1 and a call into _Block_object_dispose for the rest.
|
||||
|
||||
The flags parameter of _Block_object_assign and _Block_object_dispose is set to
|
||||
* BLOCK_FIELD_IS_OBJECT (3), for the case of an Objective-C Object,
|
||||
* BLOCK_FIELD_IS_BLOCK (7), for the case of another Block, and
|
||||
* BLOCK_FIELD_IS_BYREF (8), for the case of a __block variable.
|
||||
If the __block variable is marked weak the compiler also or's in BLOCK_FIELD_IS_WEAK (16).
|
||||
|
||||
So the Block copy/dispose helpers should only ever generate the four flag values of 3, 7, 8, and 24.
|
||||
|
||||
When a __block variable is either a C++ object, an Objective-C object, or another Block then the compiler also generates copy/dispose helper functions. Similarly to the Block copy helper, the "__block" copy helper (formerly and still a.k.a. "byref" copy helper) will do a C++ copy constructor (not a const one though!) and the dispose helper will do the destructor. And similarly the helpers will call into the same two support functions with the same values for objects and Blocks with the additional BLOCK_BYREF_CALLER (128) bit of information supplied.
|
||||
|
||||
So the __block copy/dispose helpers will generate flag values of 3 or 7 for objects and Blocks respectively, with BLOCK_FIELD_IS_WEAK (16) or'ed as appropriate and always 128 or'd in, for the following set of possibilities:
|
||||
__block id 128+3
|
||||
__weak block id 128+3+16
|
||||
__block (^Block) 128+7
|
||||
__weak __block (^Block) 128+7+16
|
||||
|
||||
The implementation of the two routines would be improved by switch statements enumerating the eight cases.
|
||||
|
||||
********************************************************/
|
||||
|
||||
/*
|
||||
* When Blocks or Block_byrefs hold objects then their copy routine helpers use this entry point
|
||||
* to do the assignment.
|
||||
*/
|
||||
void _Block_object_assign(void *destAddr, const void *object, const int flags) {
|
||||
//printf("_Block_object_assign(*%p, %p, %x)\n", destAddr, object, flags);
|
||||
if ((flags & BLOCK_BYREF_CALLER) == BLOCK_BYREF_CALLER) {
|
||||
if ((flags & BLOCK_FIELD_IS_WEAK) == BLOCK_FIELD_IS_WEAK) {
|
||||
_Block_assign_weak(object, destAddr);
|
||||
}
|
||||
else {
|
||||
// do *not* retain or *copy* __block variables whatever they are
|
||||
_Block_assign((void *)object, destAddr);
|
||||
}
|
||||
}
|
||||
else if ((flags & BLOCK_FIELD_IS_BYREF) == BLOCK_FIELD_IS_BYREF) {
|
||||
// copying a __block reference from the stack Block to the heap
|
||||
// flags will indicate if it holds a __weak reference and needs a special isa
|
||||
_Block_byref_assign_copy(destAddr, object, flags);
|
||||
}
|
||||
// (this test must be before next one)
|
||||
else if ((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) {
|
||||
// copying a Block declared variable from the stack Block to the heap
|
||||
_Block_assign(_Block_copy_internal(object, flags), destAddr);
|
||||
}
|
||||
// (this test must be after previous one)
|
||||
else if ((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) {
|
||||
//printf("retaining object at %p\n", object);
|
||||
_Block_retain_object(object);
|
||||
//printf("done retaining object at %p\n", object);
|
||||
_Block_assign((void *)object, destAddr);
|
||||
}
|
||||
}
|
||||
|
||||
// When Blocks or Block_byrefs hold objects their destroy helper routines call this entry point
|
||||
// to help dispose of the contents
|
||||
// Used initially only for __attribute__((NSObject)) marked pointers.
|
||||
void _Block_object_dispose(const void *object, const int flags) {
|
||||
//printf("_Block_object_dispose(%p, %x)\n", object, flags);
|
||||
if (flags & BLOCK_FIELD_IS_BYREF) {
|
||||
// get rid of the __block data structure held in a Block
|
||||
_Block_byref_release(object);
|
||||
}
|
||||
else if ((flags & (BLOCK_FIELD_IS_BLOCK|BLOCK_BYREF_CALLER)) == BLOCK_FIELD_IS_BLOCK) {
|
||||
// get rid of a referenced Block held by this Block
|
||||
// (ignore __block Block variables, compiler doesn't need to call us)
|
||||
_Block_destroy(object);
|
||||
}
|
||||
else if ((flags & (BLOCK_FIELD_IS_WEAK|BLOCK_FIELD_IS_BLOCK|BLOCK_BYREF_CALLER)) == BLOCK_FIELD_IS_OBJECT) {
|
||||
// get rid of a referenced object held by this Block
|
||||
// (ignore __block object variables, compiler doesn't need to call us)
|
||||
_Block_release_object(object);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Debugging support:
|
||||
*/
|
||||
#if 0
|
||||
#pragma mark Debugging
|
||||
#endif /* if 0 */
|
||||
|
||||
|
||||
const char *_Block_dump(const void *block) {
|
||||
struct Block_layout *closure = (struct Block_layout *)block;
|
||||
static char buffer[512];
|
||||
char *cp = buffer;
|
||||
if (closure == NULL) {
|
||||
sprintf(cp, "NULL passed to _Block_dump\n");
|
||||
return buffer;
|
||||
}
|
||||
if (! (closure->flags & BLOCK_HAS_DESCRIPTOR)) {
|
||||
printf("Block compiled by obsolete compiler, please recompile source for this Block\n");
|
||||
exit(1);
|
||||
}
|
||||
cp += sprintf(cp, "^%p (new layout) =\n", (void *)closure);
|
||||
if (closure->isa == NULL) {
|
||||
cp += sprintf(cp, "isa: NULL\n");
|
||||
}
|
||||
else if (closure->isa == _NSConcreteStackBlock) {
|
||||
cp += sprintf(cp, "isa: stack Block\n");
|
||||
}
|
||||
else if (closure->isa == _NSConcreteMallocBlock) {
|
||||
cp += sprintf(cp, "isa: malloc heap Block\n");
|
||||
}
|
||||
else if (closure->isa == _NSConcreteAutoBlock) {
|
||||
cp += sprintf(cp, "isa: GC heap Block\n");
|
||||
}
|
||||
else if (closure->isa == _NSConcreteGlobalBlock) {
|
||||
cp += sprintf(cp, "isa: global Block\n");
|
||||
}
|
||||
else if (closure->isa == _NSConcreteFinalizingBlock) {
|
||||
cp += sprintf(cp, "isa: finalizing Block\n");
|
||||
}
|
||||
else {
|
||||
cp += sprintf(cp, "isa?: %p\n", (void *)closure->isa);
|
||||
}
|
||||
cp += sprintf(cp, "flags:");
|
||||
if (closure->flags & BLOCK_HAS_DESCRIPTOR) {
|
||||
cp += sprintf(cp, " HASDESCRIPTOR");
|
||||
}
|
||||
if (closure->flags & BLOCK_NEEDS_FREE) {
|
||||
cp += sprintf(cp, " FREEME");
|
||||
}
|
||||
if (closure->flags & BLOCK_IS_GC) {
|
||||
cp += sprintf(cp, " ISGC");
|
||||
}
|
||||
if (closure->flags & BLOCK_HAS_COPY_DISPOSE) {
|
||||
cp += sprintf(cp, " HASHELP");
|
||||
}
|
||||
if (closure->flags & BLOCK_HAS_CTOR) {
|
||||
cp += sprintf(cp, " HASCTOR");
|
||||
}
|
||||
cp += sprintf(cp, "\nrefcount: %u\n", closure->flags & BLOCK_REFCOUNT_MASK);
|
||||
cp += sprintf(cp, "invoke: %p\n", (void *)(uintptr_t)closure->invoke);
|
||||
{
|
||||
struct Block_descriptor *dp = closure->descriptor;
|
||||
cp += sprintf(cp, "descriptor: %p\n", (void *)dp);
|
||||
cp += sprintf(cp, "descriptor->reserved: %lu\n", dp->reserved);
|
||||
cp += sprintf(cp, "descriptor->size: %lu\n", dp->size);
|
||||
|
||||
if (closure->flags & BLOCK_HAS_COPY_DISPOSE) {
|
||||
cp += sprintf(cp, "descriptor->copy helper: %p\n", (void *)(uintptr_t)dp->copy);
|
||||
cp += sprintf(cp, "descriptor->dispose helper: %p\n", (void *)(uintptr_t)dp->dispose);
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
const char *_Block_byref_dump(struct Block_byref *src) {
|
||||
static char buffer[256];
|
||||
char *cp = buffer;
|
||||
cp += sprintf(cp, "byref data block %p contents:\n", (void *)src);
|
||||
cp += sprintf(cp, " forwarding: %p\n", (void *)src->forwarding);
|
||||
cp += sprintf(cp, " flags: 0x%x\n", src->flags);
|
||||
cp += sprintf(cp, " size: %d\n", src->size);
|
||||
if (src->flags & BLOCK_HAS_COPY_DISPOSE) {
|
||||
cp += sprintf(cp, " copy helper: %p\n", (void *)(uintptr_t)src->byref_keep);
|
||||
cp += sprintf(cp, " dispose helper: %p\n", (void *)(uintptr_t)src->byref_destroy);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
25
thirdparty/blocksruntime/BlocksRuntime/tests/block-static.c
vendored
Normal file
25
thirdparty/blocksruntime/BlocksRuntime/tests/block-static.c
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// testfilerunner CONFIG
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
static int numberOfSquesals = 5;
|
||||
|
||||
^{ numberOfSquesals = 6; }();
|
||||
|
||||
if (numberOfSquesals == 6) {
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
printf("**** did not update static local, rdar://6177162\n");
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
51
thirdparty/blocksruntime/BlocksRuntime/tests/blockimport.c
vendored
Normal file
51
thirdparty/blocksruntime/BlocksRuntime/tests/blockimport.c
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* blockimport.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 10/13/08.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// pure C nothing more needed
|
||||
// CONFIG rdar://6289344
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block.h>
|
||||
#include <Block_private.h>
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i = 1;
|
||||
int (^intblock)(void) = ^{ return i*10; };
|
||||
|
||||
void (^vv)(void) = ^{
|
||||
if (argc > 0) {
|
||||
printf("intblock returns %d\n", intblock());
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
//printf("Block dump %s\n", _Block_dump(vv));
|
||||
{
|
||||
struct Block_layout *layout = (struct Block_layout *)(void *)vv;
|
||||
printf("isa %p\n", layout->isa);
|
||||
printf("flags %x\n", layout->flags);
|
||||
printf("descriptor %p\n", layout->descriptor);
|
||||
printf("descriptor->size %d\n", layout->descriptor->size);
|
||||
}
|
||||
#endif
|
||||
void (^vvcopy)(void) = Block_copy(vv);
|
||||
Block_release(vvcopy);
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
34
thirdparty/blocksruntime/BlocksRuntime/tests/byrefaccess.c
vendored
Normal file
34
thirdparty/blocksruntime/BlocksRuntime/tests/byrefaccess.c
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
//
|
||||
// byrefaccess.m
|
||||
// test that byref access to locals is accurate
|
||||
// testObjects
|
||||
//
|
||||
// Created by Blaine Garst on 5/13/08.
|
||||
//
|
||||
// CONFIG
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void callVoidVoid(void (^closure)(void)) {
|
||||
closure();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
__block int i = 10;
|
||||
|
||||
callVoidVoid(^{ ++i; });
|
||||
|
||||
if (i != 11) {
|
||||
printf("*** %s didn't update i\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
41
thirdparty/blocksruntime/BlocksRuntime/tests/byrefcopy.c
vendored
Normal file
41
thirdparty/blocksruntime/BlocksRuntime/tests/byrefcopy.c
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
//
|
||||
// byrefcopy.m
|
||||
// testObjects
|
||||
//
|
||||
// Created by Blaine Garst on 5/13/08.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block.h>
|
||||
#include <Block_private.h>
|
||||
|
||||
// CONFIG
|
||||
|
||||
void callVoidVoid(void (^closure)(void)) {
|
||||
closure();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int __block i = 10;
|
||||
|
||||
void (^block)(void) = ^{ ++i; };
|
||||
//printf("original (old style) is %s\n", _Block_dump_old(block));
|
||||
//printf("original (new style) is %s\n", _Block_dump(block));
|
||||
void (^blockcopy)(void) = Block_copy(block);
|
||||
//printf("copy is %s\n", _Block_dump(blockcopy));
|
||||
// use a copy & see that it updates i
|
||||
callVoidVoid(block);
|
||||
|
||||
if (i != 11) {
|
||||
printf("*** %s didn't update i\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
46
thirdparty/blocksruntime/BlocksRuntime/tests/byrefcopycopy.c
vendored
Normal file
46
thirdparty/blocksruntime/BlocksRuntime/tests/byrefcopycopy.c
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// CONFIG rdar://6255170
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <Block.h>
|
||||
#include <Block_private.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
__block int var = 0;
|
||||
int shouldbe = 0;
|
||||
void (^b)(void) = ^{ var++; /*printf("var is at %p with value %d\n", &var, var);*/ };
|
||||
__typeof(b) _b;
|
||||
//printf("before copy...\n");
|
||||
b(); ++shouldbe;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
_b = Block_copy(b); // make a new copy each time
|
||||
assert(_b);
|
||||
++shouldbe;
|
||||
_b(); // should still update the stack
|
||||
Block_release(_b);
|
||||
}
|
||||
|
||||
//printf("after...\n");
|
||||
b(); ++shouldbe;
|
||||
|
||||
if (var != shouldbe) {
|
||||
printf("Hmm, var is %d but should be %d\n", var, shouldbe);
|
||||
return 1;
|
||||
}
|
||||
printf("%s: Success!!\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
32
thirdparty/blocksruntime/BlocksRuntime/tests/byrefcopyinner.c
vendored
Normal file
32
thirdparty/blocksruntime/BlocksRuntime/tests/byrefcopyinner.c
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
#include <Block.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// CONFIG rdar://6225809
|
||||
// fixed in 5623
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
__block int a = 42;
|
||||
int* ap = &a; // just to keep the address on the stack.
|
||||
|
||||
void (^b)(void) = ^{
|
||||
//a; // workaround, a should be implicitly imported
|
||||
Block_copy(^{
|
||||
a = 2;
|
||||
});
|
||||
};
|
||||
|
||||
Block_copy(b);
|
||||
|
||||
if(&a == ap) {
|
||||
printf("**** __block heap storage should have been created at this point\n");
|
||||
return 1;
|
||||
}
|
||||
printf("%s: Success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
69
thirdparty/blocksruntime/BlocksRuntime/tests/byrefcopyint.c
vendored
Normal file
69
thirdparty/blocksruntime/BlocksRuntime/tests/byrefcopyint.c
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* byrefcopyint.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 12/1/08.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// byrefcopyid.m
|
||||
// testObjects
|
||||
//
|
||||
// Created by Blaine Garst on 5/13/08.
|
||||
//
|
||||
|
||||
// Tests copying of blocks with byref ints
|
||||
// CONFIG rdar://6414583 -C99
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Block.h>
|
||||
#include <Block_private.h>
|
||||
|
||||
|
||||
|
||||
|
||||
typedef void (^voidVoid)(void);
|
||||
|
||||
voidVoid dummy;
|
||||
|
||||
void callVoidVoid(voidVoid closure) {
|
||||
closure();
|
||||
}
|
||||
|
||||
|
||||
voidVoid testRoutine(const char *whoami) {
|
||||
__block int dumbo = strlen(whoami);
|
||||
dummy = ^{
|
||||
//printf("incring dumbo from %d\n", dumbo);
|
||||
++dumbo;
|
||||
};
|
||||
|
||||
|
||||
voidVoid copy = Block_copy(dummy);
|
||||
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
voidVoid array[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
array[i] = testRoutine(argv[0]);
|
||||
array[i]();
|
||||
}
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
Block_release(array[i]);
|
||||
}
|
||||
|
||||
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
41
thirdparty/blocksruntime/BlocksRuntime/tests/byrefcopystack.c
vendored
Normal file
41
thirdparty/blocksruntime/BlocksRuntime/tests/byrefcopystack.c
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
//
|
||||
// byrefcopystack.m
|
||||
// testObjects
|
||||
//
|
||||
// Created by Blaine Garst on 5/13/08.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block.h>
|
||||
|
||||
// CONFIG rdar://6255170
|
||||
|
||||
void (^bumpi)(void);
|
||||
int (^geti)(void);
|
||||
|
||||
void setClosures() {
|
||||
int __block i = 10;
|
||||
bumpi = Block_copy(^{ ++i; });
|
||||
geti = Block_copy(^{ return i; });
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
setClosures();
|
||||
bumpi();
|
||||
int i = geti();
|
||||
|
||||
if (i != 11) {
|
||||
printf("*** %s didn't update i\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
73
thirdparty/blocksruntime/BlocksRuntime/tests/byrefsanity.c
vendored
Normal file
73
thirdparty/blocksruntime/BlocksRuntime/tests/byrefsanity.c
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// CONFIG
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <Block.h>
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
__block int var = 0;
|
||||
void (^b)(void) = ^{ var++; };
|
||||
|
||||
//sanity(b);
|
||||
b();
|
||||
printf("%s: success!\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 1
|
||||
/* replicated internal data structures: BEWARE, MAY CHANGE!!! */
|
||||
|
||||
enum {
|
||||
BLOCK_REFCOUNT_MASK = (0xffff),
|
||||
BLOCK_NEEDS_FREE = (1 << 24),
|
||||
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
|
||||
BLOCK_NO_COPY = (1 << 26), // interim byref: no copies allowed
|
||||
BLOCK_IS_GC = (1 << 27),
|
||||
BLOCK_IS_GLOBAL = (1 << 28),
|
||||
};
|
||||
|
||||
struct byref_id {
|
||||
struct byref_id *forwarding;
|
||||
int flags;//refcount;
|
||||
int size;
|
||||
void (*byref_keep)(struct byref_id *dst, struct byref_id *src);
|
||||
void (*byref_destroy)(struct byref_id *);
|
||||
int var;
|
||||
};
|
||||
struct Block_basic2 {
|
||||
void *isa;
|
||||
int Block_flags; // int32_t
|
||||
int Block_size; // XXX should be packed into Block_flags
|
||||
void (*Block_invoke)(void *);
|
||||
void (*Block_copy)(void *dst, void *src);
|
||||
void (*Block_dispose)(void *);
|
||||
struct byref_id *ref;
|
||||
};
|
||||
|
||||
void sanity(void *arg) {
|
||||
struct Block_basic2 *bb = (struct Block_basic2 *)arg;
|
||||
if ( ! (bb->Block_flags & BLOCK_HAS_COPY_DISPOSE)) {
|
||||
printf("missing copy/dispose helpers for byref data\n");
|
||||
exit(1);
|
||||
}
|
||||
struct byref_id *ref = bb->ref;
|
||||
if (ref->forwarding != ref) {
|
||||
printf("forwarding pointer should be %p but is %p\n", ref, ref->forwarding);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
57
thirdparty/blocksruntime/BlocksRuntime/tests/byrefstruct.c
vendored
Normal file
57
thirdparty/blocksruntime/BlocksRuntime/tests/byrefstruct.c
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
|
||||
// CONFIG
|
||||
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
#import <string.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned long ps[30];
|
||||
int qs[30];
|
||||
} BobTheStruct;
|
||||
|
||||
int main (int argc, const char * argv[]) {
|
||||
__block BobTheStruct fiddly;
|
||||
BobTheStruct copy;
|
||||
|
||||
void (^incrementFiddly)() = ^{
|
||||
int i;
|
||||
for(i=0; i<30; i++) {
|
||||
fiddly.ps[i]++;
|
||||
fiddly.qs[i]++;
|
||||
}
|
||||
};
|
||||
|
||||
memset(&fiddly, 0xA5, sizeof(fiddly));
|
||||
memset(©, 0x2A, sizeof(copy));
|
||||
|
||||
int i;
|
||||
for(i=0; i<30; i++) {
|
||||
fiddly.ps[i] = i * i * i;
|
||||
fiddly.qs[i] = -i * i * i;
|
||||
}
|
||||
|
||||
copy = fiddly;
|
||||
incrementFiddly();
|
||||
|
||||
if ( © == &fiddly ) {
|
||||
printf("%s: struct wasn't copied.", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
for(i=0; i<30; i++) {
|
||||
//printf("[%d]: fiddly.ps: %lu, copy.ps: %lu, fiddly.qs: %d, copy.qs: %d\n", i, fiddly.ps[i], copy.ps[i], fiddly.qs[i], copy.qs[i]);
|
||||
if ( (fiddly.ps[i] != copy.ps[i] + 1) || (fiddly.qs[i] != copy.qs[i] + 1) ) {
|
||||
printf("%s: struct contents were not incremented.", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
20
thirdparty/blocksruntime/BlocksRuntime/tests/c99.c
vendored
Normal file
20
thirdparty/blocksruntime/BlocksRuntime/tests/c99.c
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
//
|
||||
// c99.m
|
||||
//
|
||||
// CONFIG C99 rdar://problem/6399225
|
||||
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void (^blockA)(void) = ^ { ; };
|
||||
blockA();
|
||||
printf("%s: success\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
37
thirdparty/blocksruntime/BlocksRuntime/tests/cast.c
vendored
Normal file
37
thirdparty/blocksruntime/BlocksRuntime/tests/cast.c
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* cast.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 2/17/09.
|
||||
*
|
||||
*/
|
||||
|
||||
// PURPOSE should allow casting of a Block reference to an arbitrary pointer and back
|
||||
// CONFIG open
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
void (^aBlock)(void);
|
||||
int *ip;
|
||||
char *cp;
|
||||
double *dp;
|
||||
|
||||
ip = (int *)aBlock;
|
||||
cp = (char *)aBlock;
|
||||
dp = (double *)aBlock;
|
||||
aBlock = (void (^)(void))ip;
|
||||
aBlock = (void (^)(void))cp;
|
||||
aBlock = (void (^)(void))dp;
|
||||
printf("%s: success", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
28
thirdparty/blocksruntime/BlocksRuntime/tests/constassign.c
vendored
Normal file
28
thirdparty/blocksruntime/BlocksRuntime/tests/constassign.c
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
//
|
||||
// constassign.c
|
||||
// bocktest
|
||||
//
|
||||
// Created by Blaine Garst on 3/21/08.
|
||||
//
|
||||
// shouldn't be able to assign to a const pointer
|
||||
// CONFIG error: assignment of read-only
|
||||
|
||||
#import <stdio.h>
|
||||
|
||||
void foo(void) { printf("I'm in foo\n"); }
|
||||
void bar(void) { printf("I'm in bar\n"); }
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void (*const fptr)(void) = foo;
|
||||
void (^const blockA)(void) = ^ { printf("hello\n"); };
|
||||
blockA = ^ { printf("world\n"); } ;
|
||||
fptr = bar;
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
29
thirdparty/blocksruntime/BlocksRuntime/tests/copy-block-literal-rdar6439600.c
vendored
Normal file
29
thirdparty/blocksruntime/BlocksRuntime/tests/copy-block-literal-rdar6439600.c
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// CONFIG open rdar://6439600
|
||||
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
|
||||
#define NUMBER_OF_BLOCKS 100
|
||||
int main (int argc, const char * argv[]) {
|
||||
int (^x[NUMBER_OF_BLOCKS])();
|
||||
int i;
|
||||
|
||||
for(i=0; i<NUMBER_OF_BLOCKS; i++) x[i] = ^{ return i; };
|
||||
|
||||
for(i=0; i<NUMBER_OF_BLOCKS; i++) {
|
||||
if (x[i]() != i) {
|
||||
printf("%s: failure, %d != %d\n", argv[0], x[i](), i);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s: success\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
85
thirdparty/blocksruntime/BlocksRuntime/tests/copyconstructor.C
vendored
Normal file
85
thirdparty/blocksruntime/BlocksRuntime/tests/copyconstructor.C
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block.h>
|
||||
|
||||
// CONFIG C++ rdar://6243400,rdar://6289367
|
||||
|
||||
|
||||
int constructors = 0;
|
||||
int destructors = 0;
|
||||
|
||||
|
||||
#define CONST const
|
||||
|
||||
class TestObject
|
||||
{
|
||||
public:
|
||||
TestObject(CONST TestObject& inObj);
|
||||
TestObject();
|
||||
~TestObject();
|
||||
|
||||
TestObject& operator=(CONST TestObject& inObj);
|
||||
|
||||
int version() CONST { return _version; }
|
||||
private:
|
||||
mutable int _version;
|
||||
};
|
||||
|
||||
TestObject::TestObject(CONST TestObject& inObj)
|
||||
|
||||
{
|
||||
++constructors;
|
||||
_version = inObj._version;
|
||||
//printf("%p (%d) -- TestObject(const TestObject&) called\n", this, _version);
|
||||
}
|
||||
|
||||
|
||||
TestObject::TestObject()
|
||||
{
|
||||
_version = ++constructors;
|
||||
//printf("%p (%d) -- TestObject() called\n", this, _version);
|
||||
}
|
||||
|
||||
|
||||
TestObject::~TestObject()
|
||||
{
|
||||
//printf("%p -- ~TestObject() called\n", this);
|
||||
++destructors;
|
||||
}
|
||||
|
||||
|
||||
TestObject& TestObject::operator=(CONST TestObject& inObj)
|
||||
{
|
||||
//printf("%p -- operator= called\n", this);
|
||||
_version = inObj._version;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void testRoutine() {
|
||||
TestObject one;
|
||||
|
||||
void (^b)(void) = ^{ printf("my const copy of one is %d\n", one.version()); };
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
testRoutine();
|
||||
if (constructors == 0) {
|
||||
printf("No copy constructors!!!\n");
|
||||
return 1;
|
||||
}
|
||||
if (constructors != destructors) {
|
||||
printf("%d constructors but only %d destructors\n", constructors, destructors);
|
||||
return 1;
|
||||
}
|
||||
printf("%s:success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
37
thirdparty/blocksruntime/BlocksRuntime/tests/copynull.c
vendored
Normal file
37
thirdparty/blocksruntime/BlocksRuntime/tests/copynull.c
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* copynull.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 10/15/08.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <stdio.h>
|
||||
#import <Block.h>
|
||||
#import <Block_private.h>
|
||||
|
||||
// CONFIG rdar://6295848
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
void (^block)(void) = (void (^)(void))0;
|
||||
void (^blockcopy)(void) = Block_copy(block);
|
||||
|
||||
if (blockcopy != (void (^)(void))0) {
|
||||
printf("whoops, somehow we copied NULL!\n");
|
||||
return 1;
|
||||
}
|
||||
// make sure we can also
|
||||
Block_release(blockcopy);
|
||||
// and more secretly
|
||||
//_Block_destroy(blockcopy);
|
||||
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
57
thirdparty/blocksruntime/BlocksRuntime/tests/dispatch_async.c
vendored
Normal file
57
thirdparty/blocksruntime/BlocksRuntime/tests/dispatch_async.c
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <unistd.h>
|
||||
//#import <Foundation/Foundation.h>
|
||||
#include <Block.h>
|
||||
|
||||
// CONFIG rdar://problem/6371811
|
||||
|
||||
const char *whoami = "nobody";
|
||||
|
||||
void EnqueueStuff(dispatch_queue_t q)
|
||||
{
|
||||
__block CFIndex counter;
|
||||
|
||||
// above call has a side effect: it works around:
|
||||
// <rdar://problem/6225809> __block variables not implicitly imported into intermediate scopes
|
||||
dispatch_async(q, ^{
|
||||
counter = 0;
|
||||
});
|
||||
|
||||
|
||||
dispatch_async(q, ^{
|
||||
//printf("outer block.\n");
|
||||
counter++;
|
||||
dispatch_async(q, ^{
|
||||
//printf("inner block.\n");
|
||||
counter--;
|
||||
if(counter == 0) {
|
||||
printf("%s: success\n", whoami);
|
||||
exit(0);
|
||||
}
|
||||
});
|
||||
if(counter == 0) {
|
||||
printf("already done? inconceivable!\n");
|
||||
exit(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
int main (int argc, const char * argv[]) {
|
||||
dispatch_queue_t q = dispatch_queue_create("queue", NULL);
|
||||
|
||||
whoami = argv[0];
|
||||
|
||||
EnqueueStuff(q);
|
||||
|
||||
dispatch_main();
|
||||
printf("shouldn't get here\n");
|
||||
return 1;
|
||||
}
|
||||
31
thirdparty/blocksruntime/BlocksRuntime/tests/dispatch_call_Block_with_release.c
vendored
Normal file
31
thirdparty/blocksruntime/BlocksRuntime/tests/dispatch_call_Block_with_release.c
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block.h>
|
||||
|
||||
// CONFIG
|
||||
|
||||
void callsomething(const char *format, int argument) {
|
||||
}
|
||||
|
||||
void
|
||||
dispatch_call_Block_with_release2(void *block)
|
||||
{
|
||||
void (^b)(void) = (void (^)(void))block;
|
||||
b();
|
||||
Block_release(b);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void (^b1)(void) = ^{ callsomething("argc is %d\n", argc); };
|
||||
void (^b2)(void) = ^{ callsomething("hellow world\n", 0); }; // global block now
|
||||
|
||||
dispatch_call_Block_with_release2(Block_copy(b1));
|
||||
dispatch_call_Block_with_release2(Block_copy(b2));
|
||||
printf("%s: Success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
107
thirdparty/blocksruntime/BlocksRuntime/tests/fail.c
vendored
Normal file
107
thirdparty/blocksruntime/BlocksRuntime/tests/fail.c
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* fail.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 9/16/08.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
bool readfile(char *buffer, const char *from) {
|
||||
int fd = open(from, 0);
|
||||
if (fd < 0) return false;
|
||||
int count = read(fd, buffer, 512);
|
||||
if (count < 0) return false;
|
||||
buffer[count] = 0; // zap newline
|
||||
return true;
|
||||
}
|
||||
|
||||
// basic idea, take compiler args, run compiler, and verify that expected failure matches any existing one
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc == 1) return 0;
|
||||
char *copy[argc+1]; // make a copy
|
||||
// find and strip off -e "errorfile"
|
||||
char *errorfile = NULL;
|
||||
int counter = 0, i = 0;
|
||||
for (i = 1; i < argc; ++i) { // skip 0 arg which is "fail"
|
||||
if (!strncmp(argv[i], "-e", 2)) {
|
||||
errorfile = argv[++i];
|
||||
}
|
||||
else {
|
||||
copy[counter++] = argv[i];
|
||||
}
|
||||
}
|
||||
copy[counter] = NULL;
|
||||
pid_t child = fork();
|
||||
char buffer[512];
|
||||
if (child == 0) {
|
||||
// in child
|
||||
sprintf(buffer, "/tmp/errorfile_%d", getpid());
|
||||
close(1);
|
||||
int fd = creat(buffer, 0777);
|
||||
if (fd != 1) {
|
||||
fprintf(stderr, "didn't open custom error file %s as 1, got %d\n", buffer, fd);
|
||||
exit(1);
|
||||
}
|
||||
close(2);
|
||||
dup(1);
|
||||
int result = execv(copy[0], copy);
|
||||
exit(10);
|
||||
}
|
||||
if (child < 0) {
|
||||
printf("fork failed\n");
|
||||
exit(1);
|
||||
}
|
||||
int status = 0;
|
||||
pid_t deadchild = wait(&status);
|
||||
if (deadchild != child) {
|
||||
printf("wait got %d instead of %d\n", deadchild, child);
|
||||
exit(1);
|
||||
}
|
||||
if (WEXITSTATUS(status) == 0) {
|
||||
printf("compiler exited normally, not good under these circumstances\n");
|
||||
exit(1);
|
||||
}
|
||||
//printf("exit status of child %d was %d\n", child, WEXITSTATUS(status));
|
||||
sprintf(buffer, "/tmp/errorfile_%d", child);
|
||||
if (errorfile) {
|
||||
//printf("ignoring error file: %s\n", errorfile);
|
||||
char desired[512];
|
||||
char got[512];
|
||||
bool gotErrorFile = readfile(desired, errorfile);
|
||||
bool gotOutput = readfile(got, buffer);
|
||||
if (!gotErrorFile && gotOutput) {
|
||||
printf("didn't read errorfile %s, it should have something from\n*****\n%s\n*****\nin it.\n",
|
||||
errorfile, got);
|
||||
exit(1);
|
||||
}
|
||||
else if (gotErrorFile && gotOutput) {
|
||||
char *where = strstr(got, desired);
|
||||
if (!where) {
|
||||
printf("didn't find contents of %s in %s\n", errorfile, buffer);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("errorfile %s and output %s inconsistent\n", errorfile, buffer);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
unlink(buffer);
|
||||
printf("success\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
21
thirdparty/blocksruntime/BlocksRuntime/tests/flagsisa.c
vendored
Normal file
21
thirdparty/blocksruntime/BlocksRuntime/tests/flagsisa.c
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* CONFIG rdar://6310599
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
__block int flags;
|
||||
__block void *isa;
|
||||
|
||||
^{ flags=1; isa = (void *)isa; };
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
42
thirdparty/blocksruntime/BlocksRuntime/tests/globalexpression.c
vendored
Normal file
42
thirdparty/blocksruntime/BlocksRuntime/tests/globalexpression.c
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// testfilerunner CONFIG
|
||||
|
||||
#import <stdio.h>
|
||||
#import <Block.h>
|
||||
|
||||
int global;
|
||||
|
||||
void (^gblock)(int) = ^(int x){ global = x; };
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
gblock(1);
|
||||
if (global != 1) {
|
||||
printf("%s: *** did not set global to 1\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
void (^gblockcopy)(int) = Block_copy(gblock);
|
||||
if (gblockcopy != gblock) {
|
||||
printf("global copy %p not a no-op %p\n", (void *)gblockcopy, (void *)gblock);
|
||||
return 1;
|
||||
}
|
||||
Block_release(gblockcopy);
|
||||
gblock(3);
|
||||
if (global != 3) {
|
||||
printf("%s: *** did not set global to 3\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
gblockcopy = Block_copy(gblock);
|
||||
gblockcopy(5);
|
||||
if (global != 5) {
|
||||
printf("%s: *** did not set global to 5\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
printf("%s: Success!\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
34
thirdparty/blocksruntime/BlocksRuntime/tests/goto.c
vendored
Normal file
34
thirdparty/blocksruntime/BlocksRuntime/tests/goto.c
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* goto.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 10/17/08.
|
||||
*
|
||||
*/
|
||||
|
||||
// CONFIG rdar://6289031
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
__block int val = 0;
|
||||
|
||||
^{ val = 1; }();
|
||||
|
||||
if (val == 0) {
|
||||
goto out_bad; // error: local byref variable val is in the scope of this goto
|
||||
}
|
||||
|
||||
printf("%s: Success!\n", argv[0]);
|
||||
return 0;
|
||||
out_bad:
|
||||
printf("%s: val not updated!\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
29
thirdparty/blocksruntime/BlocksRuntime/tests/hasdescriptor.c
vendored
Normal file
29
thirdparty/blocksruntime/BlocksRuntime/tests/hasdescriptor.c
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
|
||||
|
||||
// CONFIG C
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block_private.h>
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void (^inner)(void) = ^ { printf("argc was %d\n", argc); };
|
||||
void (^outer)(void) = ^{
|
||||
inner();
|
||||
inner();
|
||||
};
|
||||
//printf("size of inner is %ld\n", Block_size(inner));
|
||||
//printf("size of outer is %ld\n", Block_size(outer));
|
||||
if (Block_size(inner) != Block_size(outer)) {
|
||||
printf("not the same size, using old compiler??\n");
|
||||
return 1;
|
||||
}
|
||||
printf("%s: Success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
32
thirdparty/blocksruntime/BlocksRuntime/tests/josh.C
vendored
Normal file
32
thirdparty/blocksruntime/BlocksRuntime/tests/josh.C
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// CONFIG C++ GC RR open rdar://6347910
|
||||
|
||||
|
||||
|
||||
struct MyStruct {
|
||||
int something;
|
||||
};
|
||||
|
||||
struct TestObject {
|
||||
|
||||
void test(void){
|
||||
{
|
||||
MyStruct first; // works
|
||||
}
|
||||
void (^b)(void) = ^{
|
||||
MyStruct inner; // fails to compile!
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("%s: Success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
33
thirdparty/blocksruntime/BlocksRuntime/tests/k-and-r.c
vendored
Normal file
33
thirdparty/blocksruntime/BlocksRuntime/tests/k-and-r.c
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
|
||||
// CONFIG error: incompatible block pointer types assigning
|
||||
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
#ifndef __cplusplus
|
||||
char (^rot13)();
|
||||
rot13 = ^(char c) { return (char)(((c - 'a' + 13) % 26) + 'a'); };
|
||||
char n = rot13('a');
|
||||
char c = rot13('p');
|
||||
if ( n != 'n' || c != 'c' ) {
|
||||
printf("%s: rot13('a') returned %c, rot13('p') returns %c\n", argv[0], n, c);
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
// yield characteristic error message for C++
|
||||
#error incompatible block pointer types assigning
|
||||
#endif
|
||||
#ifndef __clang__
|
||||
// yield characteristic error message for C++
|
||||
#error incompatible block pointer types assigning
|
||||
#endif
|
||||
printf("%s: success\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
51
thirdparty/blocksruntime/BlocksRuntime/tests/large-struct.c
vendored
Normal file
51
thirdparty/blocksruntime/BlocksRuntime/tests/large-struct.c
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
|
||||
// CONFIG
|
||||
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
#import <string.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned long ps[30];
|
||||
int qs[30];
|
||||
} BobTheStruct;
|
||||
|
||||
int main (int argc, const char * argv[]) {
|
||||
BobTheStruct inny;
|
||||
BobTheStruct outty;
|
||||
BobTheStruct (^copyStruct)(BobTheStruct);
|
||||
int i;
|
||||
|
||||
memset(&inny, 0xA5, sizeof(inny));
|
||||
memset(&outty, 0x2A, sizeof(outty));
|
||||
|
||||
for(i=0; i<30; i++) {
|
||||
inny.ps[i] = i * i * i;
|
||||
inny.qs[i] = -i * i * i;
|
||||
}
|
||||
|
||||
copyStruct = ^(BobTheStruct aBigStruct){ return aBigStruct; }; // pass-by-value intrinsically copies the argument
|
||||
|
||||
outty = copyStruct(inny);
|
||||
|
||||
if ( &inny == &outty ) {
|
||||
printf("%s: struct wasn't copied.", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
for(i=0; i<30; i++) {
|
||||
if ( (inny.ps[i] != outty.ps[i]) || (inny.qs[i] != outty.qs[i]) ) {
|
||||
printf("%s: struct contents did not match.", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s: success\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
42
thirdparty/blocksruntime/BlocksRuntime/tests/localisglobal.c
vendored
Normal file
42
thirdparty/blocksruntime/BlocksRuntime/tests/localisglobal.c
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* localisglobal.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 9/29/08.
|
||||
*
|
||||
* works in all configurations
|
||||
* CONFIG rdar://6230297
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void (^global)(void) = ^{ printf("hello world\n"); };
|
||||
|
||||
int aresame(void *first, void *second) {
|
||||
long *f = (long *)first;
|
||||
long *s = (long *)second;
|
||||
return *f == *s;
|
||||
}
|
||||
int main(int argc, char *argv[]) {
|
||||
int i = 10;
|
||||
void (^local)(void) = ^ { printf("hi %d\n", i); };
|
||||
void (^localisglobal)(void) = ^ { printf("hi\n"); };
|
||||
|
||||
if (aresame(local, localisglobal)) {
|
||||
printf("local block could be global, but isn't\n");
|
||||
return 1;
|
||||
}
|
||||
if (!aresame(global, localisglobal)) {
|
||||
printf("local block is not global, not stack, what is it??\n");
|
||||
return 1;
|
||||
}
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
|
||||
}
|
||||
14
thirdparty/blocksruntime/BlocksRuntime/tests/macro.c
vendored
Normal file
14
thirdparty/blocksruntime/BlocksRuntime/tests/macro.c
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// CONFIG open rdar://6718399
|
||||
#include <Block.h>
|
||||
|
||||
void foo() {
|
||||
void (^bbb)(void) = Block_copy(^ {
|
||||
int j, cnt;
|
||||
});
|
||||
}
|
||||
70
thirdparty/blocksruntime/BlocksRuntime/tests/makefile
vendored
Normal file
70
thirdparty/blocksruntime/BlocksRuntime/tests/makefile
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
CCDIR=/usr/bin
|
||||
#CCDIR=/Volumes/Keep/gcc/usr/bin
|
||||
|
||||
all: std
|
||||
|
||||
clean:
|
||||
rm -fr *.dSYM *.o *-bin testfilerunner
|
||||
|
||||
TFR = ~public/bin/testfilerunner
|
||||
|
||||
testfilerunner: testfilerunner.h testfilerunner.m
|
||||
gcc -fobjc-gc-only -g -arch x86_64 -arch i386 -std=gnu99 testfilerunner.m -o testfilerunner -framework Foundation
|
||||
|
||||
tests:
|
||||
grep CONFIG *.[cmCM] | $(TFR) $(CCDIR) --
|
||||
|
||||
open:
|
||||
grep CONFIG *.[cmCM] | $(TFR) $(CCDIR) -open --
|
||||
|
||||
fast:
|
||||
grep CONFIG *.[cmCM] | $(TFR) -fast $(CCDIR) --
|
||||
|
||||
std:
|
||||
grep CONFIG *.[cmCM] | $(TFR) --
|
||||
|
||||
clang:
|
||||
grep CONFIG *.[cmCM] | $(TFR) -clang -fast --
|
||||
|
||||
fastd:
|
||||
grep CONFIG *.[cmCM] | $(TFR) -fast --
|
||||
|
||||
|
||||
# Hack Alert: arguably most of the following belongs in libclosure's Makefile; sticking it here until I get around to grokking what goes on in that file.
|
||||
sudid:
|
||||
@echo Enabling sudo: # Hack Alert: enable sudo first thing so we don't hang at the password prompt later
|
||||
@sudo echo Thanks
|
||||
|
||||
|
||||
RootsDirectory ?= /tmp/
|
||||
# Note: the libsystem project (built by the libsystemroot target below) uses the ALTUSRLOCALLIBSYSTEM variable, so we use it here to maintain parity
|
||||
ALTUSRLOCALLIBSYSTEM ?= $(RootsDirectory)/alt-usr-local-lib-system/
|
||||
altusrlocallibsystem:
|
||||
ditto /usr/local/lib/system $(ALTUSRLOCALLIBSYSTEM) # FIXME: conditionalize this copy
|
||||
|
||||
|
||||
# <rdar://problem/6456031> ER: option to not require extra privileges (-nosudo or somesuch)
|
||||
Buildit ?= ~rc/bin/buildit -rootsDirectory $(RootsDirectory) -arch i386 -arch ppc -arch x86_64
|
||||
blocksroot: sudid clean altusrlocallibsystem
|
||||
sudo $(Buildit) ..
|
||||
ditto $(RootsDirectory)/libclosure.roots/libclosure~dst/usr/local/lib/system $(ALTUSRLOCALLIBSYSTEM)
|
||||
|
||||
|
||||
LibsystemVersion ?= 121
|
||||
LibsystemPath ?= ~rc/Software/SnowLeopard/Projects/Libsystem/Libsystem-$(LibsystemVersion)
|
||||
LibsystemTmpPath ?= $(RootsDirectory)/Libsystem-$(LibsystemVersion)
|
||||
libsystemroot: blocksroot
|
||||
ditto $(LibsystemPath) $(LibsystemTmpPath) # FIXME: conditionalize this copy
|
||||
sudo ALTUSRLOCALLIBSYSTEM=$(ALTUSRLOCALLIBSYSTEM) $(Buildit) $(LibsystemTmpPath)
|
||||
|
||||
|
||||
# Defaults to product of the libsystemroot target but does not automatically rebuild that, make both targets if you want a fresh root
|
||||
LibsystemRootPath ?= $(RootsDirectory)/Libsystem-$(LibsystemVersion).roots/Libsystem-$(LibsystemVersion)~dst/usr/lib/
|
||||
roottests:
|
||||
grep CONFIG *.[cmCM] | $(TFR) -dyld $(LibsystemRootPath) -- # FIXME: figure out if I can "call" the std target instead of duplicating it
|
||||
|
||||
18
thirdparty/blocksruntime/BlocksRuntime/tests/modglobal.c
vendored
Normal file
18
thirdparty/blocksruntime/BlocksRuntime/tests/modglobal.c
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
#include <stdio.h>
|
||||
|
||||
// CONFIG
|
||||
|
||||
int AGlobal;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void (^f)(void) = ^ { AGlobal++; };
|
||||
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
|
||||
}
|
||||
44
thirdparty/blocksruntime/BlocksRuntime/tests/nestedimport.c
vendored
Normal file
44
thirdparty/blocksruntime/BlocksRuntime/tests/nestedimport.c
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
//
|
||||
// nestedimport.m
|
||||
// testObjects
|
||||
//
|
||||
// Created by Blaine Garst on 6/24/08.
|
||||
//
|
||||
// pure C nothing more needed
|
||||
// CONFIG
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
int Global = 0;
|
||||
|
||||
void callVoidVoid(void (^closure)(void)) {
|
||||
closure();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i = 1;
|
||||
|
||||
void (^vv)(void) = ^{
|
||||
if (argc > 0) {
|
||||
callVoidVoid(^{ Global = i; });
|
||||
}
|
||||
};
|
||||
|
||||
i = 2;
|
||||
vv();
|
||||
if (Global != 1) {
|
||||
printf("%s: error, Global not set to captured value\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
43
thirdparty/blocksruntime/BlocksRuntime/tests/nullblockisa.c
vendored
Normal file
43
thirdparty/blocksruntime/BlocksRuntime/tests/nullblockisa.c
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
//
|
||||
// nullblockisa.m
|
||||
// testObjects
|
||||
//
|
||||
// Created by Blaine Garst on 9/24/08.
|
||||
//
|
||||
// CONFIG rdar://6244520
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <Block_private.h>
|
||||
|
||||
|
||||
void check(void (^b)(void)) {
|
||||
struct _custom {
|
||||
struct Block_layout layout;
|
||||
struct Block_byref *innerp;
|
||||
} *custom = (struct _custom *)(void *)(b);
|
||||
//printf("block is at %p, size is %lx, inner is %p\n", (void *)b, Block_size(b), innerp);
|
||||
if (custom->innerp->isa != (void *)NULL) {
|
||||
printf("not a NULL __block isa\n");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
__block int i;
|
||||
|
||||
check(^{ printf("%d\n", ++i); });
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
77
thirdparty/blocksruntime/BlocksRuntime/tests/objectRRGC.c
vendored
Normal file
77
thirdparty/blocksruntime/BlocksRuntime/tests/objectRRGC.c
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* objectRRGC.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 10/31/08.
|
||||
*
|
||||
* Test that the runtime honors the new callouts properly for retain/release and GC
|
||||
* CON FIG C rdar://6175959
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block_private.h>
|
||||
|
||||
|
||||
int AssignCalled = 0;
|
||||
int DisposeCalled = 0;
|
||||
|
||||
// local copy instead of libSystem.B.dylib copy
|
||||
void _Block_object_assign(void *destAddr, const void *object, const int isWeak) {
|
||||
//printf("_Block_object_assign(%p, %p, %d) called\n", destAddr, object, isWeak);
|
||||
AssignCalled = 1;
|
||||
}
|
||||
|
||||
void _Block_object_dispose(const void *object, const int isWeak) {
|
||||
//printf("_Block_object_dispose(%p, %d) called\n", object, isWeak);
|
||||
DisposeCalled = 1;
|
||||
}
|
||||
|
||||
struct MyStruct {
|
||||
long isa;
|
||||
long field;
|
||||
};
|
||||
|
||||
typedef struct MyStruct *__attribute__((NSObject)) MyStruct_t;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// create a block
|
||||
struct MyStruct X;
|
||||
MyStruct_t xp = (MyStruct_t)&X;
|
||||
xp->field = 10;
|
||||
void (^myBlock)(void) = ^{ printf("field is %ld\n", xp->field); };
|
||||
// should be a copy helper generated with a calls to above routines
|
||||
// Lets find out!
|
||||
struct Block_layout *bl = (struct Block_layout *)(void *)myBlock;
|
||||
if ((bl->flags & BLOCK_HAS_DESCRIPTOR) != BLOCK_HAS_DESCRIPTOR) {
|
||||
printf("using old runtime layout!\n");
|
||||
return 1;
|
||||
}
|
||||
if ((bl->flags & BLOCK_HAS_COPY_DISPOSE) != BLOCK_HAS_COPY_DISPOSE) {
|
||||
printf("no copy dispose!!!!\n");
|
||||
return 1;
|
||||
}
|
||||
// call helper routines directly. These will, in turn, we hope, call the stubs above
|
||||
long destBuffer[256];
|
||||
//printf("destbuffer is at %p, block at %p\n", destBuffer, (void *)bl);
|
||||
//printf("dump is %s\n", _Block_dump(myBlock));
|
||||
bl->descriptor->copy(destBuffer, bl);
|
||||
bl->descriptor->dispose(bl);
|
||||
if (AssignCalled == 0) {
|
||||
printf("did not call assign helper!\n");
|
||||
return 1;
|
||||
}
|
||||
if (DisposeCalled == 0) {
|
||||
printf("did not call dispose helper\n");
|
||||
return 1;
|
||||
}
|
||||
printf("%s: Success!\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
76
thirdparty/blocksruntime/BlocksRuntime/tests/objectassign.c
vendored
Normal file
76
thirdparty/blocksruntime/BlocksRuntime/tests/objectassign.c
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* objectassign.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 10/28/08.
|
||||
*
|
||||
* This just tests that the compiler is issuing the proper helper routines
|
||||
* CONFIG C rdar://6175959
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block_private.h>
|
||||
|
||||
|
||||
int AssignCalled = 0;
|
||||
int DisposeCalled = 0;
|
||||
|
||||
// local copy instead of libSystem.B.dylib copy
|
||||
void _Block_object_assign(void *destAddr, const void *object, const int isWeak) {
|
||||
//printf("_Block_object_assign(%p, %p, %d) called\n", destAddr, object, isWeak);
|
||||
AssignCalled = 1;
|
||||
}
|
||||
|
||||
void _Block_object_dispose(const void *object, const int isWeak) {
|
||||
//printf("_Block_object_dispose(%p, %d) called\n", object, isWeak);
|
||||
DisposeCalled = 1;
|
||||
}
|
||||
|
||||
struct MyStruct {
|
||||
long isa;
|
||||
long field;
|
||||
};
|
||||
|
||||
typedef struct MyStruct *__attribute__((NSObject)) MyStruct_t;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (__APPLE_CC__ < 5627) {
|
||||
printf("need compiler version %d, have %d\n", 5627, __APPLE_CC__);
|
||||
return 0;
|
||||
}
|
||||
// create a block
|
||||
struct MyStruct X;
|
||||
MyStruct_t xp = (MyStruct_t)&X;
|
||||
xp->field = 10;
|
||||
void (^myBlock)(void) = ^{ printf("field is %ld\n", xp->field); };
|
||||
// should be a copy helper generated with a calls to above routines
|
||||
// Lets find out!
|
||||
struct Block_layout *bl = (struct Block_layout *)(void *)myBlock;
|
||||
if ((bl->flags & BLOCK_HAS_COPY_DISPOSE) != BLOCK_HAS_COPY_DISPOSE) {
|
||||
printf("no copy dispose!!!!\n");
|
||||
return 1;
|
||||
}
|
||||
// call helper routines directly. These will, in turn, we hope, call the stubs above
|
||||
long destBuffer[256];
|
||||
//printf("destbuffer is at %p, block at %p\n", destBuffer, (void *)bl);
|
||||
//printf("dump is %s\n", _Block_dump(myBlock));
|
||||
bl->descriptor->copy(destBuffer, bl);
|
||||
bl->descriptor->dispose(bl);
|
||||
if (AssignCalled == 0) {
|
||||
printf("did not call assign helper!\n");
|
||||
return 1;
|
||||
}
|
||||
if (DisposeCalled == 0) {
|
||||
printf("did not call dispose helper\n");
|
||||
return 1;
|
||||
}
|
||||
printf("%s: Success!\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
23
thirdparty/blocksruntime/BlocksRuntime/tests/orbars.c
vendored
Normal file
23
thirdparty/blocksruntime/BlocksRuntime/tests/orbars.c
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* orbars.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 9/17/08.
|
||||
*
|
||||
* CONFIG rdar://6276695 error: before ‘|’ token
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i = 10;
|
||||
void (^b)(void) = ^(void){ | i | printf("hello world, %d\n", ++i); };
|
||||
printf("%s: success :-(\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
32
thirdparty/blocksruntime/BlocksRuntime/tests/rdar6396238.c
vendored
Normal file
32
thirdparty/blocksruntime/BlocksRuntime/tests/rdar6396238.c
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// CONFIG rdar://6396238
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int count = 0;
|
||||
|
||||
void (^mkblock(void))(void)
|
||||
{
|
||||
count++;
|
||||
return ^{
|
||||
count++;
|
||||
};
|
||||
}
|
||||
|
||||
int main (int argc, const char * argv[]) {
|
||||
mkblock()();
|
||||
if (count != 2) {
|
||||
printf("%s: failure, 2 != %d\n", argv[0], count);
|
||||
exit(1);
|
||||
} else {
|
||||
printf("%s: success\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
29
thirdparty/blocksruntime/BlocksRuntime/tests/rdar6405500.c
vendored
Normal file
29
thirdparty/blocksruntime/BlocksRuntime/tests/rdar6405500.c
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// CONFIG rdar://6405500
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#import <dispatch/dispatch.h>
|
||||
#import <objc/objc-auto.h>
|
||||
|
||||
int main (int argc, const char * argv[]) {
|
||||
__block void (^blockFu)(size_t t);
|
||||
blockFu = ^(size_t t){
|
||||
if (t == 20) {
|
||||
printf("%s: success\n", argv[0]);
|
||||
exit(0);
|
||||
} else
|
||||
dispatch_async(dispatch_get_main_queue(), ^{ blockFu(20); });
|
||||
};
|
||||
|
||||
dispatch_apply(10, dispatch_get_concurrent_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT), blockFu);
|
||||
|
||||
dispatch_main();
|
||||
printf("shouldn't get here\n");
|
||||
return 1;
|
||||
}
|
||||
31
thirdparty/blocksruntime/BlocksRuntime/tests/rdar6414583.c
vendored
Normal file
31
thirdparty/blocksruntime/BlocksRuntime/tests/rdar6414583.c
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// CONFIG rdar://6414583
|
||||
|
||||
// a smaller case of byrefcopyint
|
||||
|
||||
#include <Block.h>
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
__block int c = 1;
|
||||
|
||||
//printf("&c = %p - c = %i\n", &c, c);
|
||||
|
||||
int i;
|
||||
for(i =0; i < 2; i++) {
|
||||
dispatch_block_t block = Block_copy(^{ c = i; });
|
||||
|
||||
block();
|
||||
// printf("%i: &c = %p - c = %i\n", i, &c, c);
|
||||
|
||||
Block_release(block);
|
||||
}
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
55
thirdparty/blocksruntime/BlocksRuntime/tests/recursive-block.c
vendored
Normal file
55
thirdparty/blocksruntime/BlocksRuntime/tests/recursive-block.c
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block.h>
|
||||
#include <Block_private.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// CONFIG
|
||||
|
||||
|
||||
int cumulation = 0;
|
||||
|
||||
int doSomething(int i) {
|
||||
cumulation += i;
|
||||
return cumulation;
|
||||
}
|
||||
|
||||
void dirtyStack() {
|
||||
int i = random();
|
||||
int j = doSomething(i);
|
||||
int k = doSomething(j);
|
||||
doSomething(i + j + k);
|
||||
}
|
||||
|
||||
typedef void (^voidVoid)(void);
|
||||
|
||||
voidVoid testFunction() {
|
||||
int i = random();
|
||||
__block voidVoid inner = ^{ doSomething(i); };
|
||||
//printf("inner, on stack, is %p\n", (void*)inner);
|
||||
/*__block*/ voidVoid outer = ^{
|
||||
//printf("will call inner block %p\n", (void *)inner);
|
||||
inner();
|
||||
};
|
||||
//printf("outer looks like: %s\n", _Block_dump(outer));
|
||||
voidVoid result = Block_copy(outer);
|
||||
//Block_release(inner);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
voidVoid block = testFunction();
|
||||
dirtyStack();
|
||||
block();
|
||||
Block_release(block);
|
||||
|
||||
printf("%s: success\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
74
thirdparty/blocksruntime/BlocksRuntime/tests/recursive-test.c
vendored
Normal file
74
thirdparty/blocksruntime/BlocksRuntime/tests/recursive-test.c
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// CONFIG open rdar://6416474
|
||||
// was rdar://5847976
|
||||
// was rdar://6348320
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block.h>
|
||||
|
||||
int verbose = 0;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
if (argc > 1) verbose = 1;
|
||||
|
||||
__block void (^recursive_local_block)(int);
|
||||
|
||||
if (verbose) printf("recursive_local_block is a local recursive block\n");
|
||||
recursive_local_block = ^(int i) {
|
||||
if (verbose) printf("%d\n", i);
|
||||
if (i > 0) {
|
||||
recursive_local_block(i - 1);
|
||||
}
|
||||
};
|
||||
|
||||
if (verbose) printf("recursive_local_block's address is %p, running it:\n", (void*)recursive_local_block);
|
||||
recursive_local_block(5);
|
||||
|
||||
if (verbose) printf("Creating other_local_block: a local block that calls recursive_local_block\n");
|
||||
|
||||
void (^other_local_block)(int) = ^(int i) {
|
||||
if (verbose) printf("other_local_block running\n");
|
||||
recursive_local_block(i);
|
||||
};
|
||||
|
||||
if (verbose) printf("other_local_block's address is %p, running it:\n", (void*)other_local_block);
|
||||
|
||||
other_local_block(5);
|
||||
|
||||
#if __APPLE_CC__ >= 5627
|
||||
if (verbose) printf("Creating other_copied_block: a Block_copy of a block that will call recursive_local_block\n");
|
||||
|
||||
void (^other_copied_block)(int) = Block_copy(^(int i) {
|
||||
if (verbose) printf("other_copied_block running\n");
|
||||
recursive_local_block(i);
|
||||
});
|
||||
|
||||
if (verbose) printf("other_copied_block's address is %p, running it:\n", (void*)other_copied_block);
|
||||
|
||||
other_copied_block(5);
|
||||
#endif
|
||||
|
||||
__block void (^recursive_copy_block)(int);
|
||||
|
||||
if (verbose) printf("Creating recursive_copy_block: a Block_copy of a block that will call recursive_copy_block recursively\n");
|
||||
|
||||
recursive_copy_block = Block_copy(^(int i) {
|
||||
if (verbose) printf("%d\n", i);
|
||||
if (i > 0) {
|
||||
recursive_copy_block(i - 1);
|
||||
}
|
||||
});
|
||||
|
||||
if (verbose) printf("recursive_copy_block's address is %p, running it:\n", (void*)recursive_copy_block);
|
||||
|
||||
recursive_copy_block(5);
|
||||
|
||||
printf("%s: Success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
44
thirdparty/blocksruntime/BlocksRuntime/tests/recursiveassign.c
vendored
Normal file
44
thirdparty/blocksruntime/BlocksRuntime/tests/recursiveassign.c
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* recursiveassign.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 12/3/08.
|
||||
*
|
||||
*/
|
||||
|
||||
// CONFIG rdar://6639533
|
||||
|
||||
// The compiler is prefetching x->forwarding before evaluting code that recomputes forwarding and so the value goes to a place that is never seen again.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <Block.h>
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
__block void (^recursive_copy_block)(int) = ^(int arg) { printf("got wrong Block\n"); exit(1); };
|
||||
|
||||
|
||||
recursive_copy_block = Block_copy(^(int i) {
|
||||
if (i > 0) {
|
||||
recursive_copy_block(i - 1);
|
||||
}
|
||||
else {
|
||||
printf("done!\n");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
recursive_copy_block(5);
|
||||
|
||||
printf("%s: Success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
95
thirdparty/blocksruntime/BlocksRuntime/tests/reference.C
vendored
Normal file
95
thirdparty/blocksruntime/BlocksRuntime/tests/reference.C
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
#import <Block.h>
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
|
||||
// CONFIG C++
|
||||
|
||||
int recovered = 0;
|
||||
|
||||
|
||||
|
||||
int constructors = 0;
|
||||
int destructors = 0;
|
||||
|
||||
#define CONST const
|
||||
|
||||
class TestObject
|
||||
{
|
||||
public:
|
||||
TestObject(CONST TestObject& inObj);
|
||||
TestObject();
|
||||
~TestObject();
|
||||
|
||||
TestObject& operator=(CONST TestObject& inObj);
|
||||
|
||||
void test(void);
|
||||
|
||||
int version() CONST { return _version; }
|
||||
private:
|
||||
mutable int _version;
|
||||
};
|
||||
|
||||
TestObject::TestObject(CONST TestObject& inObj)
|
||||
|
||||
{
|
||||
++constructors;
|
||||
_version = inObj._version;
|
||||
//printf("%p (%d) -- TestObject(const TestObject&) called", this, _version);
|
||||
}
|
||||
|
||||
|
||||
TestObject::TestObject()
|
||||
{
|
||||
_version = ++constructors;
|
||||
//printf("%p (%d) -- TestObject() called\n", this, _version);
|
||||
}
|
||||
|
||||
|
||||
TestObject::~TestObject()
|
||||
{
|
||||
//printf("%p -- ~TestObject() called\n", this);
|
||||
++destructors;
|
||||
}
|
||||
|
||||
#if 1
|
||||
TestObject& TestObject::operator=(CONST TestObject& inObj)
|
||||
{
|
||||
//printf("%p -- operator= called", this);
|
||||
_version = inObj._version;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
void TestObject::test(void) {
|
||||
void (^b)(void) = ^{ recovered = _version; };
|
||||
void (^b2)(void) = Block_copy(b);
|
||||
b2();
|
||||
Block_release(b2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void testRoutine() {
|
||||
TestObject one;
|
||||
|
||||
|
||||
one.test();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
testRoutine();
|
||||
if (recovered == 1) {
|
||||
printf("%s: success\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
printf("%s: *** didn't recover byref block variable\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
36
thirdparty/blocksruntime/BlocksRuntime/tests/rettypepromotion.c
vendored
Normal file
36
thirdparty/blocksruntime/BlocksRuntime/tests/rettypepromotion.c
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* rettypepromotion.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 11/3/08.
|
||||
*
|
||||
*/
|
||||
|
||||
// CONFIG error:
|
||||
// C++ and C give different errors so we don't check for an exact match.
|
||||
// The error is that enum's are defined to be ints, always, even if defined with explicit long values
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
enum { LESS = -1, EQUAL, GREATER };
|
||||
|
||||
void sortWithBlock(long (^comp)(void *arg1, void *arg2)) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
sortWithBlock(^(void *arg1, void *arg2) {
|
||||
if (random()) return LESS;
|
||||
if (random()) return EQUAL;
|
||||
if (random()) return GREATER;
|
||||
});
|
||||
printf("%s: Success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
23
thirdparty/blocksruntime/BlocksRuntime/tests/returnfunctionptr.c
vendored
Normal file
23
thirdparty/blocksruntime/BlocksRuntime/tests/returnfunctionptr.c
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
|
||||
// CONFIG rdar://6339747 but wasn't
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int (*funcptr)(long);
|
||||
|
||||
int (*(^b)(char))(long);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// implicit is fine
|
||||
b = ^(char x) { return funcptr; };
|
||||
// explicit never parses
|
||||
b = ^int (*(char x))(long) { return funcptr; };
|
||||
printf("%s: Success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
24
thirdparty/blocksruntime/BlocksRuntime/tests/shorthandexpression.c
vendored
Normal file
24
thirdparty/blocksruntime/BlocksRuntime/tests/shorthandexpression.c
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* shorthandexpression.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 9/16/08.
|
||||
*
|
||||
* CONFIG error:
|
||||
*/
|
||||
|
||||
|
||||
void foo() {
|
||||
void (^b)(void) = ^(void)printf("hello world\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("%s: this shouldn't compile\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
26
thirdparty/blocksruntime/BlocksRuntime/tests/sizeof.c
vendored
Normal file
26
thirdparty/blocksruntime/BlocksRuntime/tests/sizeof.c
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* sizeof.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 2/17/09.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// CONFIG error:
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
void (^aBlock)(void) = ^{ printf("hellow world\n"); };
|
||||
|
||||
printf("the size of a block is %ld\n", sizeof(*aBlock));
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
45
thirdparty/blocksruntime/BlocksRuntime/tests/small-struct.c
vendored
Normal file
45
thirdparty/blocksruntime/BlocksRuntime/tests/small-struct.c
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
|
||||
// CONFIG
|
||||
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
#import <string.h>
|
||||
|
||||
typedef struct {
|
||||
int a;
|
||||
int b;
|
||||
} MiniStruct;
|
||||
|
||||
int main (int argc, const char * argv[]) {
|
||||
MiniStruct inny;
|
||||
MiniStruct outty;
|
||||
MiniStruct (^copyStruct)(MiniStruct);
|
||||
|
||||
memset(&inny, 0xA5, sizeof(inny));
|
||||
memset(&outty, 0x2A, sizeof(outty));
|
||||
|
||||
inny.a = 12;
|
||||
inny.b = 42;
|
||||
|
||||
copyStruct = ^(MiniStruct aTinyStruct){ return aTinyStruct; }; // pass-by-value intrinsically copies the argument
|
||||
|
||||
outty = copyStruct(inny);
|
||||
|
||||
if ( &inny == &outty ) {
|
||||
printf("%s: struct wasn't copied.", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if ( (inny.a != outty.a) || (inny.b != outty.b) ) {
|
||||
printf("%s: struct contents did not match.", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
45
thirdparty/blocksruntime/BlocksRuntime/tests/structmember.c
vendored
Normal file
45
thirdparty/blocksruntime/BlocksRuntime/tests/structmember.c
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* structmember.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 9/30/08.
|
||||
* CONFIG
|
||||
*/
|
||||
#include <Block.h>
|
||||
#include <Block_private.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// CONFIG
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct stuff {
|
||||
long int a;
|
||||
long int b;
|
||||
long int c;
|
||||
} localStuff = { 10, 20, 30 };
|
||||
int d;
|
||||
|
||||
void (^a)(void) = ^ { printf("d is %d", d); };
|
||||
void (^b)(void) = ^ { printf("d is %d, localStuff.a is %lu", d, localStuff.a); };
|
||||
|
||||
unsigned nominalsize = Block_size(b) - Block_size(a);
|
||||
#if __cplusplus__
|
||||
// need copy+dispose helper for C++ structures
|
||||
nominalsize += 2*sizeof(void*);
|
||||
#endif
|
||||
if ((Block_size(b) - Block_size(a)) != nominalsize) {
|
||||
printf("sizeof a is %ld, sizeof b is %ld, expected %d\n", Block_size(a), Block_size(b), nominalsize);
|
||||
printf("dump of b is %s\n", _Block_dump(b));
|
||||
return 1;
|
||||
}
|
||||
printf("%s: Success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
110
thirdparty/blocksruntime/BlocksRuntime/tests/testfilerunner.h
vendored
Normal file
110
thirdparty/blocksruntime/BlocksRuntime/tests/testfilerunner.h
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
//
|
||||
// testfilerunner.h
|
||||
// testObjects
|
||||
//
|
||||
// Created by Blaine Garst on 9/24/08.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
/*
|
||||
variations:
|
||||
four source types: C, ObjC, C++, ObjC++,
|
||||
and for ObjC or ObjC++ we have
|
||||
RR and GC capabilities
|
||||
we assume C++ friendly includes for C/ObjC even if C++ isn't used
|
||||
|
||||
|
||||
four compilers: C, ObjC, C++, ObjC++
|
||||
and for ObjC or ObjC++ we can compile
|
||||
RR, RR+GC, GC+RR, GC
|
||||
although to test RR+GC we need to build a shell "main" in both modes
|
||||
and/or run with GC disabled if possible.
|
||||
|
||||
To maximize coverage we mark files with capabilities and then ask them to be
|
||||
compiled with each variation of compiler and option.
|
||||
If the file doesn't have the capability it politely refuses.
|
||||
*/
|
||||
|
||||
enum options {
|
||||
Do64 = (1 << 0),
|
||||
DoCPP = (1 << 1),
|
||||
DoOBJC = (1 << 3),
|
||||
DoGC = (1 << 4),
|
||||
DoRR = (1 << 5),
|
||||
DoRRGC = (1 << 6), // -fobjc-gc but main w/o so it runs in RR mode
|
||||
DoGCRR = (1 << 7), // -fobjc-gc & run GC mode
|
||||
|
||||
//DoDashG = (1 << 8),
|
||||
DoDashO = (1 << 9),
|
||||
DoDashOs = (1 << 10),
|
||||
DoDashO2 = (1 << 11),
|
||||
|
||||
DoC99 = (1 << 12), // -std=c99
|
||||
};
|
||||
|
||||
|
||||
@class TestFileExeGenerator;
|
||||
|
||||
// this class will actually compile and/or run a target binary
|
||||
// XXX we don't track which dynamic libraries requested/used nor set them up
|
||||
@interface TestFileExe : NSObject {
|
||||
NSPointerArray *compileLine;
|
||||
int options;
|
||||
bool shouldFail;
|
||||
TestFileExeGenerator *generator;
|
||||
__strong char *binaryName;
|
||||
__strong char *sourceName;
|
||||
__strong char *libraryPath;
|
||||
__strong char *frameworkPath;
|
||||
}
|
||||
@property int options;
|
||||
@property(assign) NSPointerArray *compileLine;
|
||||
@property(assign) TestFileExeGenerator *generator;
|
||||
@property bool shouldFail;
|
||||
@property __strong char *binaryName;
|
||||
@property __strong char *sourceName;
|
||||
@property __strong char *libraryPath;
|
||||
@property __strong char *frameworkPath;
|
||||
- (bool) compileUnlessExists:(bool)skip;
|
||||
- (bool) run;
|
||||
@property(readonly) __strong char *radar;
|
||||
@end
|
||||
|
||||
// this class generates an appropriate set of configurations to compile
|
||||
// we don't track which gcc we use but we should XXX
|
||||
@interface TestFileExeGenerator : NSObject {
|
||||
bool hasObjC;
|
||||
bool hasRR;
|
||||
bool hasGC;
|
||||
bool hasCPlusPlus;
|
||||
bool wantsC99;
|
||||
bool wants64;
|
||||
bool wants32;
|
||||
bool supposedToNotCompile;
|
||||
bool open; // this problem is still open - e.g. unresolved
|
||||
__strong char *radar; // for things already known to go wrong
|
||||
__strong char *filename;
|
||||
__strong char *compilerPath;
|
||||
__strong char *errorString;
|
||||
__strong char *warningString;
|
||||
NSPointerArray *extraLibraries;
|
||||
}
|
||||
@property bool hasObjC, hasRR, hasGC, hasCPlusPlus, wantsC99, supposedToNotCompile, open, wants32, wants64;
|
||||
@property(assign) __strong char *radar;
|
||||
@property __strong char *filename;
|
||||
@property __strong char *compilerPath;
|
||||
@property __strong char *errorString;
|
||||
@property __strong char *warningString;
|
||||
- (TestFileExe *)lineForOptions:(int)options; // nil if no can do
|
||||
+ (NSArray *)generatorsFromFILE:(FILE *)fd;
|
||||
+ (NSArray *)generatorsFromPath:(NSString *)path;
|
||||
@end
|
||||
|
||||
|
||||
805
thirdparty/blocksruntime/BlocksRuntime/tests/testfilerunner.m
vendored
Normal file
805
thirdparty/blocksruntime/BlocksRuntime/tests/testfilerunner.m
vendored
Normal file
|
|
@ -0,0 +1,805 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
//
|
||||
// testfilerunner.m
|
||||
// testObjects
|
||||
//
|
||||
// Created by Blaine Garst on 9/24/08.
|
||||
//
|
||||
|
||||
#import "testfilerunner.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool Everything = false; // do it also with 3 levels of optimization
|
||||
bool DoClang = false;
|
||||
|
||||
static bool isDirectory(char *path);
|
||||
static bool isExecutable(char *path);
|
||||
static bool isYounger(char *source, char *binary);
|
||||
static bool readErrorFile(char *buffer, const char *from);
|
||||
|
||||
__strong char *gcstrcpy2(__strong const char *arg, char *endp) {
|
||||
unsigned size = endp - arg + 1;
|
||||
__strong char *result = NSAllocateCollectable(size, 0);
|
||||
strncpy(result, arg, size);
|
||||
result[size-1] = 0;
|
||||
return result;
|
||||
}
|
||||
__strong char *gcstrcpy1(__strong char *arg) {
|
||||
unsigned size = strlen(arg) + 1;
|
||||
__strong char *result = NSAllocateCollectable(size, 0);
|
||||
strncpy(result, arg, size);
|
||||
result[size-1] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
@implementation TestFileExe
|
||||
|
||||
@synthesize options, compileLine, shouldFail, binaryName, sourceName;
|
||||
@synthesize generator;
|
||||
@synthesize libraryPath, frameworkPath;
|
||||
|
||||
- (NSString *)description {
|
||||
NSMutableString *result = [NSMutableString new];
|
||||
if (shouldFail) [result appendString:@"fail"];
|
||||
for (id x in compileLine) {
|
||||
[result appendString:[NSString stringWithFormat:@" %s", (char *)x]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (__strong char *)radar {
|
||||
return generator.radar;
|
||||
}
|
||||
|
||||
- (bool) compileUnlessExists:(bool)skip {
|
||||
if (shouldFail) {
|
||||
printf("don't use this to compile anymore!\n");
|
||||
return false;
|
||||
}
|
||||
if (skip && isExecutable(binaryName) && !isYounger(sourceName, binaryName)) return true;
|
||||
int argc = [compileLine count];
|
||||
char *argv[argc+1];
|
||||
for (int i = 0; i < argc; ++i)
|
||||
argv[i] = (char *)[compileLine pointerAtIndex:i];
|
||||
argv[argc] = NULL;
|
||||
pid_t child = fork();
|
||||
if (child == 0) {
|
||||
execv(argv[0], argv);
|
||||
exit(10); // shouldn't happen
|
||||
}
|
||||
if (child < 0) {
|
||||
printf("fork failed\n");
|
||||
return false;
|
||||
}
|
||||
int status = 0;
|
||||
pid_t deadchild = wait(&status);
|
||||
if (deadchild != child) {
|
||||
printf("wait got %d instead of %d\n", deadchild, child);
|
||||
exit(1);
|
||||
}
|
||||
if (WEXITSTATUS(status) == 0) {
|
||||
return true;
|
||||
}
|
||||
printf("run failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lookforIn(char *lookfor, const char *format, pid_t child) {
|
||||
char buffer[512];
|
||||
char got[512];
|
||||
sprintf(buffer, format, child);
|
||||
bool gotOutput = readErrorFile(got, buffer);
|
||||
if (!gotOutput) {
|
||||
printf("**** didn't get an output file %s to analyze!!??\n", buffer);
|
||||
return false;
|
||||
}
|
||||
char *where = strstr(got, lookfor);
|
||||
if (!where) {
|
||||
printf("didn't find '%s' in output file %s\n", lookfor, buffer);
|
||||
return false;
|
||||
}
|
||||
unlink(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
- (bool) compileWithExpectedFailure {
|
||||
if (!shouldFail) {
|
||||
printf("Why am I being called?\n");
|
||||
return false;
|
||||
}
|
||||
int argc = [compileLine count];
|
||||
char *argv[argc+1];
|
||||
for (int i = 0; i < argc; ++i)
|
||||
argv[i] = (char *)[compileLine pointerAtIndex:i];
|
||||
argv[argc] = NULL;
|
||||
pid_t child = fork();
|
||||
char buffer[512];
|
||||
if (child == 0) {
|
||||
// in child
|
||||
sprintf(buffer, "/tmp/errorfile_%d", getpid());
|
||||
close(1);
|
||||
int fd = creat(buffer, 0777);
|
||||
if (fd != 1) {
|
||||
fprintf(stderr, "didn't open custom error file %s as 1, got %d\n", buffer, fd);
|
||||
exit(1);
|
||||
}
|
||||
close(2);
|
||||
dup(1);
|
||||
int result = execv(argv[0], argv);
|
||||
exit(10);
|
||||
}
|
||||
if (child < 0) {
|
||||
printf("fork failed\n");
|
||||
return false;
|
||||
}
|
||||
int status = 0;
|
||||
pid_t deadchild = wait(&status);
|
||||
if (deadchild != child) {
|
||||
printf("wait got %d instead of %d\n", deadchild, child);
|
||||
exit(11);
|
||||
}
|
||||
if (WIFEXITED(status)) {
|
||||
if (WEXITSTATUS(status) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("***** compiler borked/ICEd/died unexpectedly (status %x)\n", status);
|
||||
return false;
|
||||
}
|
||||
char *error = generator.errorString;
|
||||
|
||||
if (!error) return true;
|
||||
#if 0
|
||||
char got[512];
|
||||
sprintf(buffer, "/tmp/errorfile_%d", child);
|
||||
bool gotOutput = readErrorFile(got, buffer);
|
||||
if (!gotOutput) {
|
||||
printf("**** didn't get an error file %s to analyze!!??\n", buffer);
|
||||
return false;
|
||||
}
|
||||
char *where = strstr(got, error);
|
||||
if (!where) {
|
||||
printf("didn't find '%s' in error file %s\n", error, buffer);
|
||||
return false;
|
||||
}
|
||||
unlink(buffer);
|
||||
#else
|
||||
if (!lookforIn(error, "/tmp/errorfile_%d", child)) return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
- (bool) run {
|
||||
if (shouldFail) return true;
|
||||
if (sizeof(long) == 4 && options & Do64) {
|
||||
return true; // skip 64-bit tests
|
||||
}
|
||||
int argc = 1;
|
||||
char *argv[argc+1];
|
||||
argv[0] = binaryName;
|
||||
argv[argc] = NULL;
|
||||
pid_t child = fork();
|
||||
if (child == 0) {
|
||||
// set up environment
|
||||
char lpath[1024];
|
||||
char fpath[1024];
|
||||
char *myenv[3];
|
||||
int counter = 0;
|
||||
if (libraryPath) {
|
||||
sprintf(lpath, "DYLD_LIBRARY_PATH=%s", libraryPath);
|
||||
myenv[counter++] = lpath;
|
||||
}
|
||||
if (frameworkPath) {
|
||||
sprintf(fpath, "DYLD_FRAMEWORK_PATH=%s", frameworkPath);
|
||||
myenv[counter++] = fpath;
|
||||
}
|
||||
myenv[counter] = NULL;
|
||||
if (generator.warningString) {
|
||||
// set up stdout/stderr
|
||||
char outfile[1024];
|
||||
sprintf(outfile, "/tmp/stdout_%d", getpid());
|
||||
close(2);
|
||||
close(1);
|
||||
creat(outfile, 0700);
|
||||
dup(1);
|
||||
}
|
||||
execve(argv[0], argv, myenv);
|
||||
exit(10); // shouldn't happen
|
||||
}
|
||||
if (child < 0) {
|
||||
printf("fork failed\n");
|
||||
return false;
|
||||
}
|
||||
int status = 0;
|
||||
pid_t deadchild = wait(&status);
|
||||
if (deadchild != child) {
|
||||
printf("wait got %d instead of %d\n", deadchild, child);
|
||||
exit(1);
|
||||
}
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
||||
if (generator.warningString) {
|
||||
if (!lookforIn(generator.warningString, "/tmp/stdout_%d", child)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
printf("**** run failed for %s\n", binaryName);
|
||||
return false;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation TestFileExeGenerator
|
||||
@synthesize filename, compilerPath, errorString;
|
||||
@synthesize hasObjC, hasRR, hasGC, hasCPlusPlus, wantsC99, supposedToNotCompile, open, wants32, wants64;
|
||||
@synthesize radar;
|
||||
@synthesize warningString;
|
||||
|
||||
- (void)setFilename:(__strong char *)name {
|
||||
filename = gcstrcpy1(name);
|
||||
}
|
||||
- (void)setCompilerPath:(__strong char *)name {
|
||||
compilerPath = gcstrcpy1(name);
|
||||
}
|
||||
|
||||
- (void)forMostThings:(NSMutableArray *)lines options:(int)options {
|
||||
TestFileExe *item = nil;
|
||||
item = [self lineForOptions:options];
|
||||
if (item) [lines addObject:item];
|
||||
item = [self lineForOptions:options|Do64];
|
||||
if (item) [lines addObject:item];
|
||||
item = [self lineForOptions:options|DoCPP];
|
||||
if (item) [lines addObject:item];
|
||||
item = [self lineForOptions:options|Do64|DoCPP];
|
||||
if (item) [lines addObject:item];
|
||||
}
|
||||
|
||||
/*
|
||||
DoDashG = (1 << 8),
|
||||
DoDashO = (1 << 9),
|
||||
DoDashOs = (1 << 10),
|
||||
DoDashO2 = (1 << 11),
|
||||
*/
|
||||
|
||||
- (void)forAllThings:(NSMutableArray *)lines options:(int)options {
|
||||
[self forMostThings:lines options:options];
|
||||
if (!Everything) {
|
||||
return;
|
||||
}
|
||||
// now do it with three explicit optimization flags
|
||||
[self forMostThings:lines options:options | DoDashO];
|
||||
[self forMostThings:lines options:options | DoDashOs];
|
||||
[self forMostThings:lines options:options | DoDashO2];
|
||||
}
|
||||
|
||||
- (NSArray *)allLines {
|
||||
NSMutableArray *result = [NSMutableArray new];
|
||||
TestFileExe *item = nil;
|
||||
|
||||
int options = 0;
|
||||
[self forAllThings:result options:0];
|
||||
[self forAllThings:result options:DoOBJC | DoRR];
|
||||
[self forAllThings:result options:DoOBJC | DoGC];
|
||||
[self forAllThings:result options:DoOBJC | DoGCRR];
|
||||
//[self forAllThings:result options:DoOBJC | DoRRGC];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)addLibrary:(const char *)dashLSomething {
|
||||
if (!extraLibraries) {
|
||||
extraLibraries = [NSPointerArray pointerArrayWithOptions:
|
||||
NSPointerFunctionsStrongMemory |
|
||||
NSPointerFunctionsCStringPersonality];
|
||||
}
|
||||
[extraLibraries addPointer:(void *)dashLSomething];
|
||||
}
|
||||
|
||||
- (TestFileExe *)lineForOptions:(int)options { // nil if no can do
|
||||
if (hasObjC && !(options & DoOBJC)) return nil;
|
||||
if (hasCPlusPlus && !(options & DoCPP)) return nil;
|
||||
if (hasObjC) {
|
||||
if (!hasGC && (options & (DoGC|DoGCRR))) return nil; // not smart enough
|
||||
if (!hasRR && (options & (DoRR|DoRRGC))) return nil;
|
||||
}
|
||||
NSPointerArray *pa = [NSPointerArray pointerArrayWithOptions:
|
||||
NSPointerFunctionsStrongMemory |
|
||||
NSPointerFunctionsCStringPersonality];
|
||||
// construct path
|
||||
char path[512];
|
||||
path[0] = 0;
|
||||
if (!compilerPath) compilerPath = "/usr/bin";
|
||||
if (compilerPath) {
|
||||
strcat(path, compilerPath);
|
||||
strcat(path, "/");
|
||||
}
|
||||
if (options & DoCPP) {
|
||||
strcat(path, DoClang ? "clang++" : "g++-4.2");
|
||||
}
|
||||
else {
|
||||
strcat(path, DoClang ? "clang" : "gcc-4.2");
|
||||
}
|
||||
[pa addPointer:gcstrcpy1(path)];
|
||||
if (options & DoOBJC) {
|
||||
if (options & DoCPP) {
|
||||
[pa addPointer:"-ObjC++"];
|
||||
}
|
||||
else {
|
||||
[pa addPointer:"-ObjC"];
|
||||
}
|
||||
}
|
||||
[pa addPointer:"-g"];
|
||||
if (options & DoDashO) [pa addPointer:"-O"];
|
||||
else if (options & DoDashO2) [pa addPointer:"-O2"];
|
||||
else if (options & DoDashOs) [pa addPointer:"-Os"];
|
||||
if (wantsC99 && (! (options & DoCPP))) {
|
||||
[pa addPointer:"-std=c99"];
|
||||
[pa addPointer:"-fblocks"];
|
||||
}
|
||||
[pa addPointer:"-arch"];
|
||||
[pa addPointer: (options & Do64) ? "x86_64" : "i386"];
|
||||
|
||||
if (options & DoOBJC) {
|
||||
switch (options & (DoRR|DoGC|DoGCRR|DoRRGC)) {
|
||||
case DoRR:
|
||||
break;
|
||||
case DoGC:
|
||||
[pa addPointer:"-fobjc-gc-only"];
|
||||
break;
|
||||
case DoGCRR:
|
||||
[pa addPointer:"-fobjc-gc"];
|
||||
break;
|
||||
case DoRRGC:
|
||||
printf("DoRRGC unsupported right now\n");
|
||||
[pa addPointer:"-c"];
|
||||
return nil;
|
||||
}
|
||||
[pa addPointer:"-framework"];
|
||||
[pa addPointer:"Foundation"];
|
||||
}
|
||||
[pa addPointer:gcstrcpy1(filename)];
|
||||
[pa addPointer:"-o"];
|
||||
|
||||
path[0] = 0;
|
||||
strcat(path, filename);
|
||||
strcat(path, ".");
|
||||
strcat(path, (options & Do64) ? "64" : "32");
|
||||
if (options & DoOBJC) {
|
||||
switch (options & (DoRR|DoGC|DoGCRR|DoRRGC)) {
|
||||
case DoRR: strcat(path, "-rr"); break;
|
||||
case DoGC: strcat(path, "-gconly"); break;
|
||||
case DoGCRR: strcat(path, "-gcrr"); break;
|
||||
case DoRRGC: strcat(path, "-rrgc"); break;
|
||||
}
|
||||
}
|
||||
if (options & DoCPP) strcat(path, "++");
|
||||
if (options & DoDashO) strcat(path, "-O");
|
||||
else if (options & DoDashO2) strcat(path, "-O2");
|
||||
else if (options & DoDashOs) strcat(path, "-Os");
|
||||
if (wantsC99) strcat(path, "-C99");
|
||||
strcat(path, DoClang ? "-clang" : "-gcc");
|
||||
strcat(path, "-bin");
|
||||
TestFileExe *result = [TestFileExe new];
|
||||
result.binaryName = gcstrcpy1(path); // could snarf copy in pa
|
||||
[pa addPointer:result.binaryName];
|
||||
for (id cString in extraLibraries) {
|
||||
[pa addPointer:cString];
|
||||
}
|
||||
|
||||
result.sourceName = gcstrcpy1(filename); // could snarf copy in pa
|
||||
result.compileLine = pa;
|
||||
result.options = options;
|
||||
result.shouldFail = supposedToNotCompile;
|
||||
result.generator = self;
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (NSArray *)generatorsFromPath:(NSString *)path {
|
||||
FILE *fp = fopen([path fileSystemRepresentation], "r");
|
||||
if (fp == NULL) return nil;
|
||||
NSArray *result = [self generatorsFromFILE:fp];
|
||||
fclose(fp);
|
||||
return result;
|
||||
}
|
||||
|
||||
#define LOOKFOR "CON" "FIG"
|
||||
|
||||
char *__strong parseRadar(char *line) {
|
||||
line = strstr(line, "rdar:"); // returns beginning
|
||||
char *endp = line + strlen("rdar:");
|
||||
while (*endp && *endp != ' ' && *endp != '\n')
|
||||
++endp;
|
||||
return gcstrcpy2(line, endp);
|
||||
}
|
||||
|
||||
- (void)parseLibraries:(const char *)line {
|
||||
start:
|
||||
line = strstr(line, "-l");
|
||||
char *endp = (char *)line + 2;
|
||||
while (*endp && *endp != ' ' && *endp != '\n')
|
||||
++endp;
|
||||
[self addLibrary:gcstrcpy2(line, endp)];
|
||||
if (strstr(endp, "-l")) {
|
||||
line = endp;
|
||||
goto start;
|
||||
}
|
||||
}
|
||||
|
||||
+ (TestFileExeGenerator *)generatorFromLine:(char *)line filename:(char *)filename {
|
||||
TestFileExeGenerator *item = [TestFileExeGenerator new];
|
||||
item.filename = gcstrcpy1(filename);
|
||||
if (strstr(line, "GC")) item.hasGC = true;
|
||||
if (strstr(line, "RR")) item.hasRR = true;
|
||||
if (strstr(line, "C++")) item.hasCPlusPlus = true;
|
||||
if (strstr(line, "-C99")) {
|
||||
item.wantsC99 = true;
|
||||
}
|
||||
if (strstr(line, "64")) item.wants64 = true;
|
||||
if (strstr(line, "32")) item.wants32 = true;
|
||||
if (strstr(line, "-l")) [item parseLibraries:line];
|
||||
if (strstr(line, "open")) item.open = true;
|
||||
if (strstr(line, "FAIL")) item.supposedToNotCompile = true; // old
|
||||
// compile time error
|
||||
if (strstr(line, "error:")) {
|
||||
item.supposedToNotCompile = true;
|
||||
// zap newline
|
||||
char *error = strstr(line, "error:") + strlen("error:");
|
||||
// make sure we have something before the newline
|
||||
char *newline = strstr(error, "\n");
|
||||
if (newline && ((newline-error) > 1)) {
|
||||
*newline = 0;
|
||||
item.errorString = gcstrcpy1(strstr(line, "error:") + strlen("error: "));
|
||||
}
|
||||
}
|
||||
// run time warning
|
||||
if (strstr(line, "runtime:")) {
|
||||
// zap newline
|
||||
char *error = strstr(line, "runtime:") + strlen("runtime:");
|
||||
// make sure we have something before the newline
|
||||
char *newline = strstr(error, "\n");
|
||||
if (newline && ((newline-error) > 1)) {
|
||||
*newline = 0;
|
||||
item.warningString = gcstrcpy1(strstr(line, "runtime:") + strlen("runtime:"));
|
||||
}
|
||||
}
|
||||
if (strstr(line, "rdar:")) item.radar = parseRadar(line);
|
||||
if (item.hasGC || item.hasRR) item.hasObjC = true;
|
||||
if (!item.wants32 && !item.wants64) { // give them both if they ask for neither
|
||||
item.wants32 = item.wants64 = true;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
+ (NSArray *)generatorsFromFILE:(FILE *)fp {
|
||||
NSMutableArray *result = [NSMutableArray new];
|
||||
// pretend this is a grep LOOKFOR *.[cmCM][cmCM] input
|
||||
// look for
|
||||
// filename: ... LOOKFOR [GC] [RR] [C++] [FAIL ...]
|
||||
char buf[512];
|
||||
while (fgets(buf, 512, fp)) {
|
||||
char *config = strstr(buf, LOOKFOR);
|
||||
if (!config) continue;
|
||||
char *filename = buf;
|
||||
char *end = strchr(buf, ':');
|
||||
*end = 0;
|
||||
[result addObject:[self generatorFromLine:config filename:filename]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (TestFileExeGenerator *)generatorFromFilename:(char *)filename {
|
||||
FILE *fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
printf("didn't open %s!!\n", filename);
|
||||
return nil;
|
||||
}
|
||||
char buf[512];
|
||||
while (fgets(buf, 512, fp)) {
|
||||
char *config = strstr(buf, LOOKFOR);
|
||||
if (!config) continue;
|
||||
fclose(fp);
|
||||
return [self generatorFromLine:config filename:filename];
|
||||
}
|
||||
fclose(fp);
|
||||
// guess from filename
|
||||
char *ext = strrchr(filename, '.');
|
||||
if (!ext) return nil;
|
||||
TestFileExeGenerator *result = [TestFileExeGenerator new];
|
||||
result.filename = gcstrcpy1(filename);
|
||||
if (!strncmp(ext, ".m", 2)) {
|
||||
result.hasObjC = true;
|
||||
result.hasRR = true;
|
||||
result.hasGC = true;
|
||||
}
|
||||
else if (!strcmp(ext, ".c")) {
|
||||
;
|
||||
}
|
||||
else if (!strcmp(ext, ".M") || !strcmp(ext, ".mm")) {
|
||||
result.hasObjC = true;
|
||||
result.hasRR = true;
|
||||
result.hasGC = true;
|
||||
result.hasCPlusPlus = true;
|
||||
}
|
||||
else if (!strcmp(ext, ".cc")
|
||||
|| !strcmp(ext, ".cp")
|
||||
|| !strcmp(ext, ".cxx")
|
||||
|| !strcmp(ext, ".cpp")
|
||||
|| !strcmp(ext, ".CPP")
|
||||
|| !strcmp(ext, ".c++")
|
||||
|| !strcmp(ext, ".C")) {
|
||||
result.hasCPlusPlus = true;
|
||||
}
|
||||
else {
|
||||
printf("unknown extension, file %s ignored\n", filename);
|
||||
result = nil;
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"%s: %s%s%s%s%s%s",
|
||||
filename,
|
||||
LOOKFOR,
|
||||
hasGC ? " GC" : "",
|
||||
hasRR ? " RR" : "",
|
||||
hasCPlusPlus ? " C++" : "",
|
||||
wantsC99 ? "C99" : "",
|
||||
supposedToNotCompile ? " FAIL" : ""];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void printDetails(NSArray *failures, const char *whatAreThey) {
|
||||
if ([failures count]) {
|
||||
NSMutableString *output = [NSMutableString new];
|
||||
printf("%s:\n", whatAreThey);
|
||||
for (TestFileExe *line in failures) {
|
||||
printf("%s", line.binaryName);
|
||||
char *radar = line.generator.radar;
|
||||
if (radar)
|
||||
printf(" (due to %s?),", radar);
|
||||
printf(" recompile via:\n%s\n\n", line.description.UTF8String);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void help(const char *whoami) {
|
||||
printf("Usage: %s [-fast] [-e] [-dyld librarypath] [gcc4.2dir] [-- | source1 ...]\n", whoami);
|
||||
printf(" -fast don't recompile if binary younger than source\n");
|
||||
printf(" -open only run tests that are thought to still be unresolved\n");
|
||||
printf(" -clang use the clang and clang++ compilers\n");
|
||||
printf(" -e compile all variations also with -Os, -O2, -O3\n");
|
||||
printf(" -dyld p override DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH to p when running tests\n");
|
||||
printf(" <compilerpath> directory containing gcc-4.2 (or clang) that you wish to use to compile the tests\n");
|
||||
printf(" -- assume stdin is a grep CON" "FIG across the test sources\n");
|
||||
printf(" otherwise treat each remaining argument as a single test file source\n");
|
||||
printf("%s will compile and run individual test files under a variety of compilers, c, obj-c, c++, and objc++\n", whoami);
|
||||
printf(" .c files are compiled with all four compilers\n");
|
||||
printf(" .m files are compiled with objc and objc++ compilers\n");
|
||||
printf(" .C files are compiled with c++ and objc++ compilers\n");
|
||||
printf(" .M files are compiled only with the objc++ compiler\n");
|
||||
printf("(actually all forms of extensions recognized by the compilers are honored, .cc, .c++ etc.)\n");
|
||||
printf("\nTest files should run to completion with no output and exit (return) 0 on success.\n");
|
||||
printf("Further they should be able to be compiled and run with GC on or off and by the C++ compilers\n");
|
||||
printf("A line containing the string CON" "FIG within the source enables restrictions to the above assumptions\n");
|
||||
printf("and other options.\n");
|
||||
printf("Following CON" "FIG the string\n");
|
||||
printf(" C++ restricts the test to only be run by c++ and objc++ compilers\n");
|
||||
printf(" GC restricts the test to only be compiled and run with GC on\n");
|
||||
printf(" RR (retain/release) restricts the test to only be compiled and run with GC off\n");
|
||||
printf("Additionally,\n");
|
||||
printf(" -C99 restricts the C versions of the test to -fstd=c99 -fblocks\n");
|
||||
printf(" -O adds the -O optimization level\n");
|
||||
printf(" -O2 adds the -O2 optimization level\n");
|
||||
printf(" -Os adds the -Os optimization level\n");
|
||||
printf("Files that are known to exhibit unresolved problems can provide the term \"open\" and this can");
|
||||
printf("in turn allow highlighting of fixes that have regressed as well as identify that fixes are now available.\n");
|
||||
printf("Files that exhibit known bugs may provide\n");
|
||||
printf(" rdar://whatever such that if they fail the rdar will get cited\n");
|
||||
printf("Files that are expected to fail to compile should provide, as their last token sequence,\n");
|
||||
printf(" error:\n");
|
||||
printf(" or error: substring to match.\n");
|
||||
printf("Files that are expected to produce a runtime error message should provide, as their last token sequence,\n");
|
||||
printf(" warning: string to match\n");
|
||||
printf("\n%s will compile and run all configurations of the test files and report a summary at the end. Good luck.\n", whoami);
|
||||
printf(" Blaine Garst blaine@apple.com\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("running on %s-bit architecture\n", sizeof(long) == 4 ? "32" : "64");
|
||||
char *compilerDir = "/usr/bin";
|
||||
NSMutableArray *generators = [NSMutableArray new];
|
||||
bool doFast = false;
|
||||
bool doStdin = false;
|
||||
bool onlyOpen = false;
|
||||
char *libraryPath = getenv("DYLD_LIBRARY_PATH");
|
||||
char *frameworkPath = getenv("DYLD_FRAMEWORK_PATH");
|
||||
// process options
|
||||
while (argc > 1) {
|
||||
if (!strcmp(argv[1], "-fast")) {
|
||||
doFast = true;
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
else if (!strcmp(argv[1], "-dyld")) {
|
||||
doFast = true;
|
||||
--argc;
|
||||
++argv;
|
||||
frameworkPath = argv[1];
|
||||
libraryPath = argv[1];
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
else if (!strcmp(argv[1], "-open")) {
|
||||
onlyOpen = true;
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
else if (!strcmp(argv[1], "-clang")) {
|
||||
DoClang = true;
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
else if (!strcmp(argv[1], "-e")) {
|
||||
Everything = true;
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
else if (!strcmp(argv[1], "--")) {
|
||||
doStdin = true;
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
else if (!strcmp(argv[1], "-")) {
|
||||
help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
else if (argc > 1 && isDirectory(argv[1])) {
|
||||
compilerDir = argv[1];
|
||||
++argv;
|
||||
--argc;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
// process remaining arguments, or stdin
|
||||
if (argc == 1) {
|
||||
if (doStdin)
|
||||
generators = (NSMutableArray *)[TestFileExeGenerator generatorsFromFILE:stdin];
|
||||
else {
|
||||
help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else while (argc > 1) {
|
||||
TestFileExeGenerator *generator = [TestFileExeGenerator generatorFromFilename:argv[1]];
|
||||
if (generator) [generators addObject:generator];
|
||||
++argv;
|
||||
--argc;
|
||||
}
|
||||
// see if we can generate all possibilities
|
||||
NSMutableArray *failureToCompile = [NSMutableArray new];
|
||||
NSMutableArray *failureToFailToCompile = [NSMutableArray new];
|
||||
NSMutableArray *failureToRun = [NSMutableArray new];
|
||||
NSMutableArray *successes = [NSMutableArray new];
|
||||
for (TestFileExeGenerator *generator in generators) {
|
||||
//NSLog(@"got %@", generator);
|
||||
if (onlyOpen && !generator.open) {
|
||||
//printf("skipping resolved test %s\n", generator.filename);
|
||||
continue; // skip closed if onlyOpen
|
||||
}
|
||||
if (!onlyOpen && generator.open) {
|
||||
//printf("skipping open test %s\n", generator.filename);
|
||||
continue; // skip open if not asked for onlyOpen
|
||||
}
|
||||
generator.compilerPath = compilerDir;
|
||||
NSArray *tests = [generator allLines];
|
||||
for (TestFileExe *line in tests) {
|
||||
line.frameworkPath = frameworkPath; // tell generators about it instead XXX
|
||||
line.libraryPath = libraryPath; // tell generators about it instead XXX
|
||||
if ([line shouldFail]) {
|
||||
if (doFast) continue; // don't recompile & don't count as success
|
||||
if ([line compileWithExpectedFailure]) {
|
||||
[successes addObject:line];
|
||||
}
|
||||
else
|
||||
[failureToFailToCompile addObject:line];
|
||||
}
|
||||
else if ([line compileUnlessExists:doFast]) {
|
||||
if ([line run]) {
|
||||
printf("%s ran successfully\n", line.binaryName);
|
||||
[successes addObject:line];
|
||||
}
|
||||
else {
|
||||
[failureToRun addObject:line];
|
||||
}
|
||||
}
|
||||
else {
|
||||
[failureToCompile addObject:line];
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n--- results ---\n\n%lu successes\n%lu unexpected compile failures\n%lu failure to fail to compile errors\n%lu run failures\n",
|
||||
[successes count], [failureToCompile count], [failureToFailToCompile count], [failureToRun count]);
|
||||
printDetails(failureToCompile, "unexpected compile failures");
|
||||
printDetails(failureToFailToCompile, "should have failed to compile but didn't failures");
|
||||
printDetails(failureToRun, "run failures");
|
||||
|
||||
if (onlyOpen && [successes count]) {
|
||||
NSMutableSet *radars = [NSMutableSet new];
|
||||
printf("The following tests ran successfully suggesting that they are now resolved:\n");
|
||||
for (TestFileExe *line in successes) {
|
||||
printf("%s\n", line.binaryName);
|
||||
if (line.radar) [radars addObject:line.generator];
|
||||
}
|
||||
if ([radars count]) {
|
||||
printf("The following radars may be resolved:\n");
|
||||
for (TestFileExeGenerator *line in radars) {
|
||||
printf("%s\n", line.radar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [failureToCompile count] + [failureToRun count];
|
||||
}
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
static bool isDirectory(char *path) {
|
||||
struct stat statb;
|
||||
int retval = stat(path, &statb);
|
||||
if (retval != 0) return false;
|
||||
if (statb.st_mode & S_IFDIR) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isExecutable(char *path) {
|
||||
struct stat statb;
|
||||
int retval = stat(path, &statb);
|
||||
if (retval != 0) return false;
|
||||
if (!(statb.st_mode & S_IFREG)) return false;
|
||||
if (statb.st_mode & S_IXUSR) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isYounger(char *source, char *binary) {
|
||||
struct stat statb;
|
||||
int retval = stat(binary, &statb);
|
||||
if (retval != 0) return true; // if doesn't exit, lie
|
||||
|
||||
struct stat stata;
|
||||
retval = stat(source, &stata);
|
||||
if (retval != 0) return true; // we're hosed
|
||||
// the greater the timeval the younger it is
|
||||
if (stata.st_mtimespec.tv_sec > statb.st_mtimespec.tv_sec) return true;
|
||||
if (stata.st_mtimespec.tv_nsec > statb.st_mtimespec.tv_nsec) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool readErrorFile(char *buffer, const char *from) {
|
||||
int fd = open(from, 0);
|
||||
if (fd < 0) {
|
||||
printf("didn't open %s, (might not have been created?)\n", buffer);
|
||||
return false;
|
||||
}
|
||||
int count = read(fd, buffer, 512);
|
||||
if (count < 1) {
|
||||
printf("read error on %s\n", buffer);
|
||||
return false;
|
||||
}
|
||||
buffer[count-1] = 0; // zap newline
|
||||
return true;
|
||||
}
|
||||
44
thirdparty/blocksruntime/BlocksRuntime/tests/varargs-bad-assign.c
vendored
Normal file
44
thirdparty/blocksruntime/BlocksRuntime/tests/varargs-bad-assign.c
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
|
||||
// HACK ALERT: gcc and g++ give different errors, referencing the line number to ensure that it checks for the right error; MUST KEEP IN SYNC WITH THE TEST
|
||||
// CONFIG 27: error:
|
||||
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
#import <string.h>
|
||||
#import <stdarg.h>
|
||||
|
||||
|
||||
int main (int argc, const char * argv[]) {
|
||||
int (^sumn)(int n, ...);
|
||||
int six = 0;
|
||||
|
||||
sumn = ^(int a, int b, int n, ...){
|
||||
int result = 0;
|
||||
va_list numbers;
|
||||
int i;
|
||||
|
||||
va_start(numbers, n);
|
||||
for (i = 0 ; i < n ; i++) {
|
||||
result += va_arg(numbers, int);
|
||||
}
|
||||
va_end(numbers);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
six = sumn(3, 1, 2, 3);
|
||||
|
||||
if ( six != 6 ) {
|
||||
printf("%s: Expected 6 but got %d\n", argv[0], six);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
39
thirdparty/blocksruntime/BlocksRuntime/tests/varargs.c
vendored
Normal file
39
thirdparty/blocksruntime/BlocksRuntime/tests/varargs.c
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
|
||||
// CONFIG
|
||||
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
#import <string.h>
|
||||
#import <stdarg.h>
|
||||
|
||||
|
||||
int main (int argc, const char * argv[]) {
|
||||
int (^sumn)(int n, ...) = ^(int n, ...){
|
||||
int result = 0;
|
||||
va_list numbers;
|
||||
int i;
|
||||
|
||||
va_start(numbers, n);
|
||||
for (i = 0 ; i < n ; i++) {
|
||||
result += va_arg(numbers, int);
|
||||
}
|
||||
va_end(numbers);
|
||||
|
||||
return result;
|
||||
};
|
||||
int six = sumn(3, 1, 2, 3);
|
||||
|
||||
if ( six != 6 ) {
|
||||
printf("%s: Expected 6 but got %d\n", argv[0], six);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("%s: success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
66
thirdparty/blocksruntime/BlocksRuntime/tests/variadic.c
vendored
Normal file
66
thirdparty/blocksruntime/BlocksRuntime/tests/variadic.c
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* variadic.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 2/17/09.
|
||||
*
|
||||
*/
|
||||
|
||||
// PURPOSE Test that variadic arguments compile and work for Blocks
|
||||
// CONFIG
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
long (^addthem)(const char *, ...) = ^long (const char *format, ...){
|
||||
va_list argp;
|
||||
const char *p;
|
||||
int i;
|
||||
char c;
|
||||
double d;
|
||||
long result = 0;
|
||||
va_start(argp, format);
|
||||
//printf("starting...\n");
|
||||
for (p = format; *p; p++) switch (*p) {
|
||||
case 'i':
|
||||
i = va_arg(argp, int);
|
||||
//printf("i: %d\n", i);
|
||||
result += i;
|
||||
break;
|
||||
case 'd':
|
||||
d = va_arg(argp, double);
|
||||
//printf("d: %g\n", d);
|
||||
result += (int)d;
|
||||
break;
|
||||
case 'c':
|
||||
c = va_arg(argp, int);
|
||||
//printf("c: '%c'\n", c);
|
||||
result += c;
|
||||
break;
|
||||
}
|
||||
//printf("...done\n\n");
|
||||
return result;
|
||||
};
|
||||
long testresult = addthem("ii", 10, 20);
|
||||
if (testresult != 30) {
|
||||
printf("got wrong result: %ld\n", testresult);
|
||||
return 1;
|
||||
}
|
||||
testresult = addthem("idc", 30, 40.0, 'a');
|
||||
if (testresult != (70+'a')) {
|
||||
printf("got different wrong result: %ld\n", testresult);
|
||||
return 1;
|
||||
}
|
||||
printf("%s: Success\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
27
thirdparty/blocksruntime/BlocksRuntime/tests/voidarg.c
vendored
Normal file
27
thirdparty/blocksruntime/BlocksRuntime/tests/voidarg.c
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
/*
|
||||
* voidarg.c
|
||||
* testObjects
|
||||
*
|
||||
* Created by Blaine Garst on 2/17/09.
|
||||
*
|
||||
*/
|
||||
|
||||
// PURPOSE should complain about missing 'void' but both GCC and clang are supporting K&R instead
|
||||
// CONFIG open error:
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int Global;
|
||||
|
||||
void (^globalBlock)() = ^{ ++Global; }; // should be void (^gb)(void) = ...
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("%s: success", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
1
thirdparty/blocksruntime/README.md
vendored
Symbolic link
1
thirdparty/blocksruntime/README.md
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
README.txt
|
||||
283
thirdparty/blocksruntime/README.txt
vendored
Normal file
283
thirdparty/blocksruntime/README.txt
vendored
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
|
||||
Blocks Runtime
|
||||
==============
|
||||
|
||||
This project provides a convenient way to install the BlocksRuntime library
|
||||
from the compiler-rt project (see <http://compiler-rt.llvm.org/>).
|
||||
|
||||
Several systems (Linux, FreeBSD, MacPorts, etc.) provide the clang compiler
|
||||
either preinstalled or as an available package which has Blocks support
|
||||
(provided the `-fblocks` compiler option is used).
|
||||
|
||||
Unfortunately, those installer packages do not provide the Blocks runtime
|
||||
library.
|
||||
|
||||
On the other hand, the compiler-rt library can be downloaded and does contain
|
||||
the Blocks runtime support if properly enabled in the cmake build file.
|
||||
|
||||
By default, however, the compiler-rt library also builds a compiler runtime
|
||||
support library which is undesirable.
|
||||
|
||||
This project contains only the BlocksRuntime files (in the `BlocksRuntime`
|
||||
subdirectory) along with tests (in the `BlocksRuntime/tests` subdirectory) and
|
||||
the original `CREDITS.TXT`, `LICENSE.TXT` and `README.txt` from the top-level
|
||||
`compiler-rt` project (which have been placed in the `BlocksRuntime`
|
||||
subdirectory). Note that in 2014-02 the compiler-rt project moved the
|
||||
BlocksRuntime sources from the `BlocksRuntime` directory to the
|
||||
`lib/BlocksRuntime` directory and moved the tests from the `BlocksRuntime/tests`
|
||||
directory to the `test/BlocksRuntime` directory. The files themselves, however,
|
||||
remain unchanged and are still the same as they were in 2010-08.
|
||||
|
||||
This runtime can also be used with the `gcc-apple-4.2` compiler built using the
|
||||
MacPorts.org apple-gcc42 package on Mac OS X.
|
||||
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
The compiler-rt project (and hence the BlocksRuntime since it's a part of that
|
||||
project) has a very liberal dual-license of either the UIUC or MIT license.
|
||||
The MIT license is fully GPL compatible (and pretty much compatible with just
|
||||
about everything), so there should be no problems linking the
|
||||
`libBlocksRuntime.a` library with your executable. (Note that on the FSF's site
|
||||
<http://www.gnu.org/licenses/license-list.html>, you find the MIT license under
|
||||
the 'X11 License' section.) See the `LICENSE.TXT` file in the `BlocksRuntime`
|
||||
subdirectory for all the details.
|
||||
|
||||
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
Since there are only two files to build, a makefile didn't seem warranted. A
|
||||
special `config.h` file has been created to make the build work. Build the
|
||||
`libBlocksRuntime.a` library by running:
|
||||
|
||||
./buildlib
|
||||
|
||||
The `gcc` compiler will be used by default, but you can do `CC=clang ./buildlib`
|
||||
for example to use the `clang` compiler instead. Note that neither `make` nor
|
||||
`cmake` are needed (but `ar` and `ranlib` will be used but they can also be
|
||||
changed with the `AR` and `RANLIB` environment variables similarly to the way
|
||||
the compiler can be changed).
|
||||
|
||||
**IMPORTANT** Mac OS X Note: If you are building this library on Mac OS X
|
||||
(presumably to use with a `clang` or `gcc-apple-4.2` built with MacPorts or
|
||||
otherwise obtained), you probably want a fat library with multiple architectures
|
||||
in it. You can do that with the `CFLAGS` variable like so:
|
||||
|
||||
CFLAGS='-O2 -arch x86_64 -arch ppc64 -arch i386 -arch ppc' ./buildlib
|
||||
|
||||
The `buildlib-osx` script will attempt to make an intelligent guess about
|
||||
building an OS X library and then run `buildlib`. If you're using Mac OS X you
|
||||
can do this to build a FAT OS X library:
|
||||
|
||||
./buildlib-osx
|
||||
|
||||
The `buildlib` (and `buildlib-osx`) script takes a single optional `-shared`
|
||||
argument. If given it will attempt to also build a shared library instead
|
||||
of just a static one in case you have a policy situation where use of a static
|
||||
library has been forbidden.
|
||||
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Skip this step at your peril! It's really quite painless. You see it's
|
||||
possible that the underlying blocks ABI between the blocks runtime files
|
||||
provided in this project and the blocks ABI used by your version of the clang
|
||||
compiler to implement the `-fblocks` option have diverged in an incompatible
|
||||
way. If this has happened, at least some of the tests should fail in
|
||||
spectacular ways (i.e. bus faults). For that reason skipping this step is not
|
||||
recommended.
|
||||
|
||||
You must have the clang compiler with `-fblocks` support installed for this step
|
||||
(if you don't have a clang compiler with `-fblocks` support available, why
|
||||
bother installing the Blocks runtime in the first place?)
|
||||
Run the tests like so:
|
||||
|
||||
./checktests
|
||||
|
||||
By default `checktests` expects the `clang` compiler to be available in the
|
||||
`PATH` and named `clang`. If you are using `gcc-apple-4.2` or your `clang` is
|
||||
named something different (such as `clang-mp-2.9` or `clang-mp-3.0`) run the
|
||||
tests like this instead (replacing `clang-mp-3.0` with your compiler's name):
|
||||
|
||||
CC=clang-mp-3.0 ./checktests
|
||||
|
||||
Problems are indicated with a line that starts `not ok`. You will see a few
|
||||
of these. The ones that are marked with `# TODO` are expected to fail for the
|
||||
reason shown. The `copy-block-literal-rdar6439600.c` expected failure is a real
|
||||
failure. No it's not a bug in the Blocks runtime library, it's actually a bug
|
||||
in the compiler. You may want to examine the `copy-block-literal-rdar6439600.c`
|
||||
source file to make sure you fully grok the failure so you can avoid getting
|
||||
burned by it in your code. There may be a fix in the clang project by now (but
|
||||
as of the clang 3.2 release it still seems to fail), however it may be a while
|
||||
until it rolls downhill to your clang package.
|
||||
|
||||
If you are using `CC=gcc-apple-4.2`, you will probably get two additional expect
|
||||
failure compiler bugs in the `cast.c` and `josh.C` tests. These extra failures
|
||||
are not failures in the blocks runtime itself, just `gcc` not accepting some
|
||||
source files that `clang` accepts. You can still use the `libBlocksRuntime.a`
|
||||
library just fine.
|
||||
|
||||
Note that if you have an earlier version of `clang` (anything before version 2.8
|
||||
see `clang -v`) then `clang++` (C++ support) is either incomplete or missing and
|
||||
the few C++ tests (`.C` extension) will be automatically skipped (if `clang++`
|
||||
is missing) or possibly fail in odd ways (if `clang++` is present but older than
|
||||
version 2.8).
|
||||
|
||||
Note that the `./checktests` output is TAP (Test Anything Protocol) compliant
|
||||
and can therefore be run with Perl's prove utility like so:
|
||||
|
||||
prove -v checktests
|
||||
|
||||
Optionally first setting `CC` like so:
|
||||
|
||||
CC=gcc-apple-4.2 prove -v checktests
|
||||
|
||||
Omit the `-v` option for more succinct output.
|
||||
|
||||
|
||||
|
||||
ARM Hard Float Bug
|
||||
------------------
|
||||
|
||||
When running on a system that uses the ARM hard float ABI (e.g. RaspberryPi),
|
||||
the clang compiler has a bug. When passing float arguments to a vararg function
|
||||
they must also be passed on the stack, not just in hardware floating point
|
||||
registers. The clang compiler does this correctly for normal vararg functions,
|
||||
but fails to do this for block vararg functions.
|
||||
|
||||
If you really need this, a workaround is to call a normal vararg function that
|
||||
takes a block and `...` arguments. It can then package up the `...` arguments
|
||||
into a `va_list` and then call the block it was passed as an argument passing
|
||||
the block the `va_list`. This works fine and avoids the `clang` bug even
|
||||
though it's fugly.
|
||||
|
||||
The `checktests` script marks this test (`variadic.c`) as expect fail when
|
||||
running the tests on an ARM hard float ABI system if it's able to detect that
|
||||
the ARM hard float ABI is in use.
|
||||
|
||||
|
||||
|
||||
clang -fblocks failure
|
||||
----------------------
|
||||
|
||||
If clang is not using the integrated assembler (option `-integrated-as`) then it
|
||||
will incorrectly pass options such as `-fblocks` down to the assembler which
|
||||
will probably not like it. One example of an error caused by this bug is:
|
||||
|
||||
gcc: error: unrecognized command line option '-fblocks'
|
||||
|
||||
In this case clang is not using the integrated assembler (which is not supported
|
||||
on all platforms) and passes the `-fblocks` option down to the gcc assembler
|
||||
which does not like that option at all.
|
||||
|
||||
The following references talk about this:
|
||||
|
||||
- <http://thread.gmane.org/gmane.comp.compilers.llvm.devel/56563>
|
||||
- <http://llvm.org/bugs/show_bug.cgi?id=12920>
|
||||
|
||||
The ugly workaround for this problem is to compile the sources using both the
|
||||
`-S` and `-fblocks` options to produce a `.s` file which can then be compiled
|
||||
into whatever is desired without needing to use the `-fblocks` option.
|
||||
|
||||
If `checktests` detects this situation it will emit a line similar to this:
|
||||
|
||||
WARNING: -S required for -fblocks with clang
|
||||
|
||||
If this is the case, then rules to compile `.c` into `.s` and then compile `.s`
|
||||
into `.o` (or whatever) will be needed instead of the usual compile `.c` into
|
||||
`.o` (or whatever).
|
||||
|
||||
Note that this workaround is required to use `-fblocks` with the version of
|
||||
clang included with cygwin.
|
||||
|
||||
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
Assuming that you have built the library (with `./buildlib`) and are satisfied
|
||||
it works (`./checktests`) then it can be installed with:
|
||||
|
||||
sudo ./installlib
|
||||
|
||||
The default installation `prefix` is `/usr/local`, but can be changed to
|
||||
`/myprefix` like so:
|
||||
|
||||
sudo env prefix=/myprefix ./installlib
|
||||
|
||||
The include file (`Block.h`) is installed into `$prefix/include` and the library
|
||||
(`libBlocksRuntime.a`) into `$prefix/lib` by default. (Those can also be
|
||||
changed by setting and exporting `includedir` and/or `libdir` in the same way
|
||||
`prefix` can be changed.)
|
||||
|
||||
If you want to see what will be installed without actually installing use:
|
||||
|
||||
./installlib --dry-run
|
||||
|
||||
Note that `DESTDIR` is supported by the `installlib` script if that's needed.
|
||||
Just set `DESTDIR` before running `installlib` the same way `prefix` can be set.
|
||||
|
||||
Note that if the shared library exists it will also be installed. Add a single
|
||||
optional `-shared` or `-static` option to install only one or the other.
|
||||
|
||||
|
||||
|
||||
Sample Code
|
||||
-----------
|
||||
|
||||
After you have installed the Blocks runtime header and library, you can check
|
||||
to make sure everything's working by building the `sample.c` file. The
|
||||
instructions are at the top of the file (use `head sample.c` to see them) or
|
||||
just do this (replace `clang` with the name of the compiler you're using):
|
||||
|
||||
clang -o sample -fblocks sample.c -lBlocksRuntime && ./sample
|
||||
|
||||
If the above line outputs `Hello world 2` then your Blocks runtime support is
|
||||
correctly installed and fully usable. Have fun!
|
||||
|
||||
Note that if you have the problem described above in the section named
|
||||
"clang -fblocks failure", then you'll need to do this instead:
|
||||
|
||||
clang -S -o sample.s -fblocks sample.c && \
|
||||
clang -o sample sample.s -lBlocksRuntime && ./sample
|
||||
|
||||
Note that it's possible to use the Blocks runtime without installing it into
|
||||
the system directories. You simply need to add an appropriate `-I` option to
|
||||
find the `Block.h` header when you compile your source(s). And a `-L` option to
|
||||
find the `libBlocksRuntime.a` library when you link your executable. Since
|
||||
`libBlocksRuntime.a` is a static library no special system support will be
|
||||
needed to run the resulting executable.
|
||||
|
||||
|
||||
|
||||
Glibc Problem
|
||||
-------------
|
||||
|
||||
The `unistd.h` header from older versions of `glibc` has an incompatibility with
|
||||
the `-fblocks` option. See <http://mackyle.github.io/blocksruntime/#glibc> for
|
||||
a workaround.
|
||||
|
||||
This problem was corrected with commit 84ae135d3282dc362bed0a5c9a575319ef336884
|
||||
(<http://repo.or.cz/w/glibc.git/commit/84ae135d>) on 2013-11-21 and first
|
||||
appears in `glibc-2.19` released on 2014-02-07. Since `ldd` is part of `glibc`
|
||||
you can check to see what version of `glibc` you have with:
|
||||
|
||||
ldd --version
|
||||
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
You can find information on the Blocks language extension at these URLs
|
||||
|
||||
- <http://clang.llvm.org/docs/LanguageExtensions.html#blocks>
|
||||
- <http://clang.llvm.org/docs/BlockLanguageSpec.html>
|
||||
- <http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Blocks>
|
||||
- <http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Blocks/Blocks.pdf>
|
||||
112
thirdparty/blocksruntime/buildlib
vendored
Executable file
112
thirdparty/blocksruntime/buildlib
vendored
Executable file
|
|
@ -0,0 +1,112 @@
|
|||
#!/bin/sh
|
||||
|
||||
case "$1" in -h|-H|-help|--help)
|
||||
cat <<EOT
|
||||
Usage: ${0##*/} [-shared]
|
||||
-shared also attempt to build a shared library
|
||||
Env: CC explicit "cc" compiler to use
|
||||
AR explicit "ar" to use
|
||||
RANLIB explicit "ranlib" to use
|
||||
CFLAGS explicit compiler options to use
|
||||
FPIC explicit -fPIC/-fpic (or none) option to use
|
||||
EOT
|
||||
exit 0
|
||||
esac
|
||||
|
||||
set -e
|
||||
|
||||
LIB=libBlocksRuntime.a
|
||||
SRC=BlocksRuntime
|
||||
|
||||
shared=
|
||||
[ z"$1" != z"-shared" -a z"$1" != z"--shared" ] || shared=1
|
||||
|
||||
if [ -n "$shared" ]; then
|
||||
UNAME_S="$(uname -s 2>/dev/null)" || :
|
||||
case "$UNAME_S" in
|
||||
Darwin)
|
||||
SHLIB="${LIB%.a}.dylib"
|
||||
SHOPT="-dynamiclib -Wl,-all_load"
|
||||
SHOPT2=
|
||||
;;
|
||||
*)
|
||||
SHLIB="${LIB%.a}.so"
|
||||
SHOPT="-shared -Wl,-whole-archive"
|
||||
SHOPT2="-Wl,-no-whole-archive"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ -z "$CC" ]; then
|
||||
if command -v gcc > /dev/null; then
|
||||
CC=gcc
|
||||
elif command -v clang > /dev/null; then
|
||||
CC=clang
|
||||
elif command -v cc > /dev/null; then
|
||||
CC=cc
|
||||
else
|
||||
echo "Could not guess name of compiler, please set CC" >&2
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "CC=$CC"
|
||||
: ${AR:=ar}
|
||||
echo "AR=$AR"
|
||||
: ${RANLIB:=ranlib}
|
||||
echo "RANLIB=$RANLIB"
|
||||
|
||||
if [ "${CFLAGS+set}" != "set" ]; then
|
||||
case "$CC" in
|
||||
*gcc*|*clang*)
|
||||
CFLAGS=-O2
|
||||
;;
|
||||
*)
|
||||
CFLAGS=-O
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
has_cc_opt()
|
||||
{
|
||||
"$CC" "$1" -o /tmp/cc.$$ -c -x c /dev/null >/dev/null 2>&1 &&
|
||||
rm -f /tmp/cc.$$
|
||||
}
|
||||
if [ "${FPIC+set}" != "set" ]; then
|
||||
if has_cc_opt "-fPIC"; then
|
||||
FPIC="-fPIC"
|
||||
elif has_cc_opt "-fpic"; then
|
||||
FPIC="-fpic"
|
||||
fi
|
||||
fi
|
||||
[ -z "$FPIC" ] || echo "FPIC=$FPIC"
|
||||
|
||||
echo "CFLAGS=$CFLAGS"
|
||||
|
||||
echo "LIB=$LIB"
|
||||
[ -z "$shared" ] || echo "SHLIB=$SHLIB"
|
||||
[ -z "$shared" ] || echo "SHOPT=$SHOPT"
|
||||
[ -z "$shared" ] || [ -z "$SHOPT2" ] || echo "SHOPT2=$SHOPT2"
|
||||
echo "SRC=$SRC"
|
||||
|
||||
(
|
||||
PS4= && set -ex
|
||||
! test -e $LIB || rm $LIB
|
||||
) || exit
|
||||
[ -z "$shared" ] ||
|
||||
(
|
||||
PS4= && set -ex
|
||||
! test -e $SHLIB || rm $SHLIB
|
||||
) || exit
|
||||
(
|
||||
PS4= && set -ex
|
||||
"$CC" -c $FPIC $CFLAGS -o $SRC/data.o $SRC/data.c &&
|
||||
"$CC" -c $FPIC $CFLAGS -o $SRC/runtime.o -I . $SRC/runtime.c &&
|
||||
"$AR" cr $LIB $SRC/data.o $SRC/runtime.o &&
|
||||
"$RANLIB" $LIB
|
||||
) || exit
|
||||
[ -z "$shared" ] ||
|
||||
(
|
||||
PS4= && set -ex
|
||||
"$CC" $FPIC $CFLAGS -o "$SHLIB" $SHOPT $LIB $SHOPT2
|
||||
) || exit
|
||||
108
thirdparty/blocksruntime/buildlib-osx
vendored
Executable file
108
thirdparty/blocksruntime/buildlib-osx
vendored
Executable file
|
|
@ -0,0 +1,108 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Attempt to build a universal library for OSX
|
||||
|
||||
set -e
|
||||
|
||||
done=
|
||||
dp="$(xcode-select -print-path 2>/dev/null)"
|
||||
: "${dp:=/Developer}"
|
||||
|
||||
gc40="$(command -v gcc-4.0 2>/dev/null)"
|
||||
gc42="$(command -v gcc-4.2 2>/dev/null)"
|
||||
mp42="$(command -v gcc-apple-4.2 2>/dev/null)"
|
||||
lv42="$(command -v llvm-gcc-4.2 2>/dev/null)"
|
||||
gca0=
|
||||
gca2=
|
||||
if [ -n "$gc42" ]; then
|
||||
gca2="$gc42"
|
||||
elif [ -n "$mp42" ]; then
|
||||
gca2="$mp42"
|
||||
elif [ -n "$lv42" ]; then
|
||||
gca2="$lv42"
|
||||
fi
|
||||
if [ -n "$gc40" ]; then
|
||||
gca0="$gc40"
|
||||
elif [ -n "$gca2" ]; then
|
||||
gca0="$gca2"
|
||||
fi
|
||||
|
||||
if [ -d "$dp/SDKs" ]; then
|
||||
# First see if 10.4u is available and gcc-4.0
|
||||
if [ -z "$done" -a -r "$dp/SDKs/MacOSX10.4u.sdk/SDKSettings.plist" -a -n "$gc40" ]; then
|
||||
done=1
|
||||
NEWCC="$gc40"
|
||||
NEWCFLAGS="-arch x86_64 -arch ppc64 -arch i386 -arch ppc"
|
||||
NEWCFLAGS="$NEWCFLAGS -isysroot$dp/SDKs/MacOSX10.4u.sdk"
|
||||
fi
|
||||
# Or see if 10.5 is available, any compiler will do
|
||||
if [ -z "$done" -a -r "$dp/SDKs/MacOSX10.5.sdk/SDKSettings.plist" -a -n "$gca0" ]; then
|
||||
done=1
|
||||
NEWCC="$gca0"
|
||||
NEWCFLAGS="-arch x86_64 -arch ppc64 -arch i386 -arch ppc"
|
||||
NEWCFLAGS="$NEWCFLAGS -isysroot$dp/SDKs/MacOSX10.5.sdk"
|
||||
fi
|
||||
# Or see if 10.6 is available, any 4.2 compiler will do
|
||||
if [ -z "$done" -a -r "$dp/SDKs/MacOSX10.6.sdk/SDKSettings.plist" -a -n "$gca2" ]; then
|
||||
done=1
|
||||
NEWCC="$gca2"
|
||||
NEWCFLAGS="-arch x86_64 -arch i386 -arch ppc"
|
||||
NEWCFLAGS="$NEWCFLAGS -isysroot$dp/SDKs/MacOSX10.6.sdk"
|
||||
fi
|
||||
# Or see if 10.7 is available, any 4.2 compiler will do
|
||||
if [ -z "$done" -a -r "$dp/SDKs/MacOSX10.7.sdk/SDKSettings.plist" -a -n "$gca2" ]; then
|
||||
done=1
|
||||
NEWCC="$gca2"
|
||||
NEWCFLAGS="-arch x86_64 -arch i386"
|
||||
NEWCFLAGS="$NEWCFLAGS -isysroot$dp/SDKs/MacOSX10.7.sdk"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$done" ]; then
|
||||
# Select by OS version as we have no SDKs
|
||||
dv="$(sysctl -n kern.osrelease 2>/dev/null | cut -d. -f1 2>/dev/null)"
|
||||
if [ -z "$done" -a "$dv" = "8" ]; then
|
||||
# Tiger 10.4.x
|
||||
done=1
|
||||
NEWCC="$gca0"
|
||||
# Tiger's system libraries are not guaranteed to be universal
|
||||
fi
|
||||
if [ -z "$done" -a "$dv" = "9" ]; then
|
||||
# Leopard 10.5.x
|
||||
done=1
|
||||
NEWCC="$gca0"
|
||||
NEWCFLAGS="-arch x86_64 -arch ppc64 -arch i386 -arch ppc"
|
||||
fi
|
||||
if [ -z "$done" -a "$dv" = "10" ]; then
|
||||
# Snow Leopard 10.6.x
|
||||
done=1
|
||||
NEWCC="$gca2"
|
||||
NEWCFLAGS="-arch x86_64 -arch i386 -arch ppc"
|
||||
fi
|
||||
if [ -z "$done" -a "$dv" = "11" ]; then
|
||||
# Lion 10.7.x
|
||||
done=1
|
||||
NEWCC="$gca2"
|
||||
NEWCFLAGS="-arch x86_64 -arch i386"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$NEWCC" -a -z "$CC" ]; then
|
||||
CC="$NEWCC" && export CC
|
||||
fi
|
||||
if [ -n "$done" ]; then
|
||||
if [ -z "$MACOSX_DEPLOYMENT_TARGET" ]; then
|
||||
MACOSX_DEPLOYMENT_TARGET=10.4 && export MACOSX_DEPLOYMENT_TARGET
|
||||
fi
|
||||
fi
|
||||
if [ -n "$NEWCFLAGS" ]; then
|
||||
if [ -z "$CFLAGS" ]; then
|
||||
CFLAGS="-O2 $NEWCFLAGS" && export CFLAGS
|
||||
else
|
||||
CFLAGS="$CFLAGS $NEWCFLAGS" && export CFLAGS
|
||||
fi
|
||||
fi
|
||||
build="$(dirname "$0")/buildlib"
|
||||
if [ -n "$MACOSX_DEPLOYMENT_TARGET" ]; then
|
||||
echo "MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET"
|
||||
fi
|
||||
exec "$build" "$@"
|
||||
290
thirdparty/blocksruntime/checktests
vendored
Executable file
290
thirdparty/blocksruntime/checktests
vendored
Executable file
|
|
@ -0,0 +1,290 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This file produces TAP compliant output
|
||||
|
||||
# NOTE:
|
||||
# This file can be run directly or with "prove" like this:
|
||||
# prove checktests
|
||||
# Or like this:
|
||||
# prove -v checktests
|
||||
# Do not forget to set the compiler if needed like so:
|
||||
# CC=my-clang-build prove -v checktests
|
||||
|
||||
: ${CC:=clang}
|
||||
: ${CXX:=$CC}
|
||||
: ${CFLAGS:=}
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
CPPFLAGS='-O -Wno-unused -include testprefix.h -IBlocksRuntime'
|
||||
CCFLAGS='-std=c99 -Wimplicit-function-declaration'
|
||||
LIB=libBlocksRuntime.a
|
||||
TESTDIR=testbin
|
||||
rm -rf $TESTDIR
|
||||
mkdir $TESTDIR
|
||||
diag () {
|
||||
while [ $# != 0 ]; do
|
||||
echo '# '"$1"
|
||||
shift
|
||||
done
|
||||
}
|
||||
diagfilt() {
|
||||
while read -r LINE; do
|
||||
echo '# '"$LINE"
|
||||
done
|
||||
}
|
||||
usedashs=
|
||||
diag 'blocksruntime tests' ''
|
||||
if ! ccver="$("$CC" --version 2>&1)"; then
|
||||
echo 'Bail out! '"\"$CC\" not installed (did you forget to set \$CC?)"
|
||||
exit 1
|
||||
else
|
||||
out="$( ("$CC" -fblocks -c -o /dev/null -x c - < /dev/null 2>&1 || echo '-fblocks') 2>&1)"
|
||||
case "$out" in *"-fblocks"*)
|
||||
out="$( ("$CC" -fblocks -S -o /dev/null -x c - < /dev/null 2>&1 || echo '-fblocks') 2>&1)"
|
||||
case "$out" in *"-fblocks"*)
|
||||
echo 'Bail out! '"\"$CC\" does not support the -fblocks option"
|
||||
exit 1
|
||||
esac
|
||||
usedashs=1
|
||||
diag "WARNING: -S required for -fblocks with $CC"
|
||||
esac
|
||||
ccmach="$("$CC" -dumpmachine 2>/dev/null)"
|
||||
fi
|
||||
warnskipcxx=
|
||||
if cxxver="$("$CXX" --version 2>&1)"; then
|
||||
dopp=1
|
||||
out="$( ("$CXX" -fblocks -c -o /dev/null -x c - < /dev/null 2>&1 || echo '-fblocks') 2>&1)"
|
||||
case "$out" in *"-fblocks"*)
|
||||
out="$( ("$CXX" -fblocks -S -o /dev/null -x c - < /dev/null 2>&1 || echo '-fblocks') 2>&1)"
|
||||
case "$out" in
|
||||
*"-fblocks"*)
|
||||
warnskipcxx="\"$CXX\" does not support the -fblocks option; skipping C++ tests"
|
||||
dopp=
|
||||
;;
|
||||
*)
|
||||
usedashs=1
|
||||
;;
|
||||
esac
|
||||
if [ "$CC" != "$CXX" ]; then
|
||||
diag "WARNING: -S required for -fblocks with $CXX"
|
||||
fi
|
||||
esac
|
||||
if [ -n "$dopp" ]; then
|
||||
cxxmach="$("$CXX" -dumpmachine 2>/dev/null)"
|
||||
cxxdver="$("$CXX" -dumpversion 2>/dev/null)"
|
||||
fi
|
||||
else
|
||||
warnskipcxx="\"$CXX\" not installed; skipping C++ tests"
|
||||
fi
|
||||
if [ -n "$usedashs" ]; then
|
||||
diag ""
|
||||
fi
|
||||
if [ -n "$warnskipcxx" ]; then
|
||||
diag "$warnskipcxx" ""
|
||||
fi
|
||||
if [ ! -r "$LIB" ]; then
|
||||
echo 'Bail out! '"No \"$LIB\" file found, try running \"$(dirname "$0")/buildlib\" first"
|
||||
exit 1
|
||||
fi
|
||||
iscc_clang=
|
||||
iscxx_clang=
|
||||
case "$ccver" in *[Cc][Ll][Aa][Nn][Gg]*)
|
||||
iscc_clang=1
|
||||
esac
|
||||
case "$cxxver" in *[Cc][Ll][Aa][Nn][Gg]*)
|
||||
iscxx_clang=1
|
||||
esac
|
||||
if [ -n "$iscxx_clang" ]; then case "$cxxdver" in
|
||||
"1.1")
|
||||
skiprefC=1
|
||||
esac; fi
|
||||
iscc_armhf=
|
||||
iscxx_armhf=
|
||||
case "$ccmach" in arm-*)
|
||||
case "$ccmach" in *abihf)
|
||||
iscc_armhf=1
|
||||
esac
|
||||
esac
|
||||
case "$cxxmach" in arm-*)
|
||||
case "$cxxmach" in *abihf)
|
||||
iscxx_armhf=1
|
||||
esac
|
||||
esac
|
||||
diag "CC${iscc_clang:+(clang)}: $CC --version"
|
||||
echo "$ccver" | diagfilt
|
||||
diag ''
|
||||
if [ -n "$dopp" -a z"$CXX" != z"$CC" ]; then
|
||||
diag "CXX${iscxx_clang:+(clang)}: $CXX --version"
|
||||
echo "$cxxver" | diagfilt
|
||||
diag ''
|
||||
fi
|
||||
testcount=0
|
||||
failcount=0
|
||||
xfailcount=0
|
||||
bonuscount=0
|
||||
skipcount=0
|
||||
skipcpp=0
|
||||
passcount=0
|
||||
testsfailed=
|
||||
for test in BlocksRuntime/tests/*.[cC]; do
|
||||
testname="${test#BlocksRuntime/tests/}"
|
||||
skip=
|
||||
skipdoze=
|
||||
extra=
|
||||
stub=
|
||||
xfail=
|
||||
reason=
|
||||
showxfail=
|
||||
testcount=$(($testcount + 1))
|
||||
case $testname in
|
||||
rdar6405500.c | \
|
||||
rdar6414583.c | \
|
||||
objectRRGC.c | \
|
||||
dispatch_async.c) skip=1;;
|
||||
fail.c) skipdoze=1;;
|
||||
macro.c) stub='void foo(); int main(){foo(); printf("success");}';;
|
||||
varargs-bad-assign.c | \
|
||||
rettypepromotion.c | \
|
||||
shorthandexpression.c | \
|
||||
k-and-r.c | \
|
||||
sizeof.c | \
|
||||
orbars.c | \
|
||||
constassign.c) xfail=1;;
|
||||
copy-block-literal-rdar6439600.c) reason='compiler bug'; showxfail=1; xfail=1;;
|
||||
${iscc_clang}cast.c) reason='gcc compiler bug'; showxfail=1; xfail=1;;
|
||||
${iscxx_clang}josh.C) reason='g++ compiler bug'; showxfail=1; xfail=1;;
|
||||
reference.C)
|
||||
if [ -n "$skiprefC" ]; then
|
||||
reason="\"$CXX\" version too old"
|
||||
xfail=1
|
||||
fi;;
|
||||
variadic.c)
|
||||
if [ -n "$iscc_armhf" ]; then
|
||||
reason='incorrect clang armhf block float vararg implementation'
|
||||
showxfail=1
|
||||
xfail=1
|
||||
fi;;
|
||||
esac
|
||||
ext=.c
|
||||
cpp=
|
||||
USECC="$CC"
|
||||
USEFLAGS="$CCFLAGS $CPPFLAGS"
|
||||
USELIB="$LIB"
|
||||
case $test in
|
||||
*.C) cpp=1; ext=.C;;
|
||||
*.cpp) cpp=1; ext=.cpp;;
|
||||
*.cp) cpp=1; ext=.cp;;
|
||||
*.c++) cpp=1; ext=.c++;;
|
||||
esac
|
||||
if [ -n "$cpp" ]; then
|
||||
USECC="$CXX"
|
||||
USEFLAGS="$CPPFLAGS"
|
||||
USELIB="$LIB -lstdc++"
|
||||
fi
|
||||
if [ -n "$COMSPEC" -a -n "$skipdoze" ]; then
|
||||
skip=1
|
||||
fi
|
||||
if [ -z "$skip" -a -n "$cpp" -a -z "$dopp" ]; then
|
||||
echo "ok $testcount - $testname # skipped: C++ with blocks not available"
|
||||
skipcpp=$(($skipcpp + 1))
|
||||
skipcount=$(($skipcount + 1))
|
||||
else
|
||||
if [ -n "$skip" ]; then
|
||||
if [ -n "$skipdoze" ]; then
|
||||
echo "ok $testcount - $testname # skipped: not supported on this platform"
|
||||
else
|
||||
echo "ok $testcount - $testname # skipped: not supported"
|
||||
fi
|
||||
skipcount=$(($skipcount + 1))
|
||||
else
|
||||
if [ -n "$stub" ]; then
|
||||
out="$( (
|
||||
if [ -z "$usedashs" ]; then
|
||||
"$USECC" -c $CFLAGS $USEFLAGS $extra -o $TESTDIR/$(basename $test $ext).o -fblocks $test && \
|
||||
echo "$stub" | "$USECC" $CFLAGS $USEFLAGS $extra -o $TESTDIR/$(basename $test $ext) -fblocks \
|
||||
$TESTDIR/$(basename $test $ext).o $USELIB -x c - && \
|
||||
cd $TESTDIR && ./$(basename $test $ext)
|
||||
else
|
||||
"$USECC" -S $CFLAGS $USEFLAGS $extra -o $TESTDIR/$(basename $test $ext).s -fblocks $test && \
|
||||
"$USECC" -c $CFLAGS $extra -o $TESTDIR/$(basename $test $ext).o \
|
||||
$TESTDIR/$(basename $test $ext).s && \
|
||||
echo "$stub" | "$USECC" $CFLAGS $USEFLAGS $extra -o $TESTDIR/$(basename $test $ext) \
|
||||
$TESTDIR/$(basename $test $ext).o $USELIB -x c - && \
|
||||
cd $TESTDIR && ./$(basename $test $ext)
|
||||
fi
|
||||
) 2>&1)"
|
||||
else
|
||||
out="$( (
|
||||
if [ -z "$usedashs" ]; then
|
||||
"$USECC" -c $CFLAGS $USEFLAGS $extra -o $TESTDIR/$(basename $test $ext).o -fblocks $test && \
|
||||
"$USECC" $CFLAGS -o $TESTDIR/$(basename $test $ext) -fblocks $TESTDIR/$(basename $test $ext).o $USELIB && \
|
||||
cd $TESTDIR && ./$(basename $test $ext)
|
||||
else
|
||||
"$USECC" -S $CFLAGS $USEFLAGS $extra -o $TESTDIR/$(basename $test $ext).s -fblocks $test && \
|
||||
"$USECC" -c $CFLAGS $extra -o $TESTDIR/$(basename $test $ext).o \
|
||||
$TESTDIR/$(basename $test $ext).s && \
|
||||
"$USECC" $CFLAGS -o $TESTDIR/$(basename $test $ext) $TESTDIR/$(basename $test $ext).o $USELIB && \
|
||||
cd $TESTDIR && ./$(basename $test $ext)
|
||||
fi
|
||||
) 2>&1)"
|
||||
fi
|
||||
result=$?
|
||||
if [ -n "$xfail" ]; then
|
||||
xfailcount=$(($xfailcount + 1))
|
||||
: ${reason:=expected to fail}
|
||||
if [ $result = 0 ]; then
|
||||
bonuscount=$(($bonuscount + 1))
|
||||
passcount=$(($passcount + 1))
|
||||
echo "ok $testcount - $testname # TODO: $reason"
|
||||
else
|
||||
echo "not ok $testcount - $testname # TODO: $reason"
|
||||
if [ -n "$showxfail" ]; then
|
||||
echo "$out" | diagfilt
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if [ $result != 0 ]; then
|
||||
testsfailed=1
|
||||
failcount=$(($failcount + 1))
|
||||
echo "not ok $testcount - $testname"
|
||||
echo "$out" | diagfilt
|
||||
else
|
||||
echo "ok $testcount - $testname"
|
||||
passcount=$(($passcount + 1))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
diag "" "test count: $testcount"
|
||||
if [ $bonuscount != 0 ]; then
|
||||
diag " passed: $passcount (todo=$bonuscount)"
|
||||
else
|
||||
diag " passed: $passcount"
|
||||
fi
|
||||
if [ $xfailcount != 0 ]; then
|
||||
if [ $bonuscount != 0 ]; then
|
||||
diag " xfail: $xfailcount (passed=$bonuscount)"
|
||||
else
|
||||
diag " xfail: $xfailcount"
|
||||
fi
|
||||
fi
|
||||
if [ $skipcount != 0 ]; then
|
||||
if [ $skipcpp != 0 ]; then
|
||||
diag " skipped: $skipcount (C++=$skipcpp)"
|
||||
else
|
||||
diag " skipped: $skipcount"
|
||||
fi
|
||||
fi
|
||||
if [ $failcount != 0 ]; then
|
||||
diag " failed: $failcount"
|
||||
fi
|
||||
if [ -n "$testsfailed" ]; then
|
||||
diag "test failures occurred"
|
||||
else
|
||||
diag "all tests passed"
|
||||
fi
|
||||
diag ""
|
||||
echo "1..$testcount"
|
||||
[ -z "$testsfailed" ] || exit 1
|
||||
exit 0
|
||||
64
thirdparty/blocksruntime/config.h
vendored
Normal file
64
thirdparty/blocksruntime/config.h
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#define HAVE_AVAILABILITY_MACROS_H 1
|
||||
#define HAVE_TARGET_CONDITIONALS_H 1
|
||||
#define HAVE_OSATOMIC_COMPARE_AND_SWAP_INT 1
|
||||
#define HAVE_OSATOMIC_COMPARE_AND_SWAP_LONG 1
|
||||
#define HAVE_LIBKERN_OSATOMIC_H
|
||||
|
||||
/* Be sneaky and turn OSAtomicCompareAndSwapInt into OSAtomicCompareAndSwap32
|
||||
* and OSAtomicCompareAndSwapLong into either OSAtomicCompareAndSwap32
|
||||
* or OSAtomicCompareAndSwap64 (depending on __LP64__) so that the library
|
||||
* is Tiger compatible!
|
||||
*/
|
||||
#include <libkern/OSAtomic.h>
|
||||
#undef OSAtomicCompareAndSwapInt
|
||||
#undef OSAtomicCompareAndSwapLong
|
||||
#define OSAtomicCompareAndSwapInt(o,n,v) OSAtomicCompareAndSwap32Compat(o,n,v)
|
||||
#ifdef __LP64__
|
||||
#define OSAtomicCompareAndSwapLong(o,n,v) OSAtomicCompareAndSwap64Compat(o,n,v)
|
||||
#else
|
||||
#define OSAtomicCompareAndSwapLong(o,n,v) OSAtomicCompareAndSwap32Compat(o,n,v)
|
||||
#endif
|
||||
|
||||
static __inline bool OSAtomicCompareAndSwap32Compat(int32_t o, int32_t n, volatile int32_t *v)
|
||||
{return OSAtomicCompareAndSwap32(o,n,(int32_t *)v);}
|
||||
#ifdef __LP64__
|
||||
static __inline bool OSAtomicCompareAndSwap64Compat(int64_t o, int64_t n, volatile int64_t *v)
|
||||
{return OSAtomicCompareAndSwap64(o,n,(int64_t *)v);}
|
||||
#endif
|
||||
|
||||
#else /* !__APPLE__ */
|
||||
|
||||
#if defined(__WIN32__) || defined(_WIN32)
|
||||
|
||||
/* Poor runtime.c code causes warnings calling InterlockedCompareExchange */
|
||||
#define _CRT_SECURE_NO_WARNINGS 1
|
||||
#include <windows.h>
|
||||
static __inline int InterlockedCompareExchangeCompat(volatile void *v, long n, long o)
|
||||
{return (int)InterlockedCompareExchange((LONG *)v, (LONG)n, (LONG)o);}
|
||||
#undef InterlockedCompareExchange
|
||||
#define InterlockedCompareExchange(v,n,o) InterlockedCompareExchangeCompat(v,n,o)
|
||||
|
||||
#elif defined(__GNUC__) /* && !defined(__WIN32__) && !defined(_WIN32) */
|
||||
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) /* GCC >= 4.1 */
|
||||
|
||||
/* runtime.c ignores these if __WIN32__ or _WIN32 is defined */
|
||||
#define HAVE_SYNC_BOOL_COMPARE_AND_SWAP_INT 1
|
||||
#define HAVE_SYNC_BOOL_COMPARE_AND_SWAP_LONG 1
|
||||
|
||||
#else /* GCC earlier than version 4.1 */
|
||||
|
||||
#error GCC version 4.1 (or compatible) or later is required on non-apple, non-w32 targets
|
||||
|
||||
#endif /* GCC earlier than version 4.1 */
|
||||
|
||||
#endif /* !defined(__GNUC__) && !defined(__WIN32__) && !defined(_WIN32) */
|
||||
|
||||
#endif /* !__APPLE__ */
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
||||
95
thirdparty/blocksruntime/installlib
vendored
Executable file
95
thirdparty/blocksruntime/installlib
vendored
Executable file
|
|
@ -0,0 +1,95 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
: "${prefix:=/usr/local}"
|
||||
: "${includedir:=$prefix/include}"
|
||||
: "${libdir:=$prefix/lib}"
|
||||
: "${DESTDIR:=}"
|
||||
|
||||
HEADER=BlocksRuntime/Block.h
|
||||
LIB=libBlocksRuntime.a
|
||||
SHLIB=
|
||||
|
||||
docmd()
|
||||
{
|
||||
echo "$*"
|
||||
if [ -z "$dryrun" ]; then eval "$*"; fi
|
||||
}
|
||||
|
||||
if ! myid="$(id -u)"; then
|
||||
echo "Cannot run id, aborting!"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -r $HEADER ]; then
|
||||
echo "Cannot find $HEADER, aborting!"
|
||||
exit 1
|
||||
fi
|
||||
dryrun=
|
||||
if [ "$1" = '-n' ] || [ "$1" = '--dry-run' ]; then
|
||||
dryrun=1
|
||||
shift
|
||||
fi
|
||||
static=1
|
||||
shared=1
|
||||
case "$1" in
|
||||
"-static"|"--static")
|
||||
shift
|
||||
shared=
|
||||
;;
|
||||
"-shared"|"--shared")
|
||||
shift
|
||||
static=
|
||||
;;
|
||||
esac
|
||||
if [ "$#" != 0 ]; then
|
||||
echo "Usage: [prefix=prefixdir] $0 [-n | --dry-run] [-shared | -static]"
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$shared" ]; then
|
||||
UNAME_S="$(uname -s 2>/dev/null)" || :
|
||||
case "$UNAME_S" in
|
||||
Darwin)
|
||||
SHLIB="${LIB%.a}.dylib"
|
||||
SHLIBMODE=755
|
||||
;;
|
||||
*)
|
||||
SHLIB="${LIB%.a}.so"
|
||||
SHLIBMODE=644
|
||||
;;
|
||||
esac
|
||||
if [ -n "$static" ]; then
|
||||
# ignore a missing shared library
|
||||
[ -e "$SHLIB" ] || SHLIB=
|
||||
else
|
||||
LIB=
|
||||
fi
|
||||
fi
|
||||
if [ -n "$LIB" ] && [ ! -r "$LIB" ]; then
|
||||
echo "Cannot find $LIB, did you run \`buildlib\` or \`buildlib-osx\`?"
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$SHLIB" ] && [ ! -r "$SHLIB" ]; then
|
||||
echo "Cannot find $SHLIB, did you run \`buildlib -shared\` or \`buildlib-osx -shared\`?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ -z "$DESTDIR" ] ||
|
||||
echo "Destination Root(\$DESTDIR): $DESTDIR (default is \"\")"
|
||||
echo "Install Prefix(\$prefix): $prefix (default is /usr/local)"
|
||||
echo "Include Directory(\$includedir): $includedir (default is \$prefix/include)"
|
||||
echo "Library Directory(\$libdir): $libdir (default is \$prefix/lib)"
|
||||
echo "(use prefix=prefixdir $0 [or similar] to change)"
|
||||
echo ''
|
||||
|
||||
if [ -z "$DESTDIR" -a -z "$dryrun" -a "$myid" != 0 ]; then
|
||||
echo "Must be root to install, use sudo $0"
|
||||
echo "(Or try using the --dry-run option)"
|
||||
exit 1
|
||||
fi
|
||||
docmd "install -d "$DESTDIR"$includedir "$DESTDIR"$libdir"
|
||||
docmd "install -m 644 $HEADER "$DESTDIR"$includedir/"
|
||||
[ -z "$LIB" ] ||
|
||||
docmd "install -m 644 $LIB "$DESTDIR"$libdir/"
|
||||
[ -z "$SHLIB" ] ||
|
||||
docmd "install -m $SHLIBMODE $SHLIB "$DESTDIR"$libdir/"
|
||||
33
thirdparty/blocksruntime/sample.c
vendored
Normal file
33
thirdparty/blocksruntime/sample.c
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Test your installation by running:
|
||||
|
||||
clang -o sample -fblocks sample.c -lBlocksRuntime && ./sample
|
||||
|
||||
The above line should result in:
|
||||
|
||||
Hello world 2
|
||||
|
||||
If you have everything correctly installed.
|
||||
*/
|
||||
|
||||
#ifndef __BLOCKS__
|
||||
#error must be compiled with -fblocks option enabled
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Block.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
__block int i;
|
||||
i = 0;
|
||||
void (^block)() = ^{
|
||||
printf("Hello world %d\n", i);
|
||||
};
|
||||
++i;
|
||||
void (^block2)() = Block_copy(block);
|
||||
++i;
|
||||
block2();
|
||||
Block_release(block2);
|
||||
return 0;
|
||||
}
|
||||
17
thirdparty/blocksruntime/testprefix.h
vendored
Normal file
17
thirdparty/blocksruntime/testprefix.h
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#undef __APPLE_CC__
|
||||
#define __APPLE_CC__ 5627
|
||||
#define _BSD_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#define random() rand()
|
||||
#else /* !_WIN32 */
|
||||
#ifdef __linux__
|
||||
#undef __block
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#ifdef __linux__
|
||||
#define __block __attribute__((__blocks__(byref)))
|
||||
#endif
|
||||
#include <sys/wait.h>
|
||||
#endif /* !_WIN32 */
|
||||
Loading…
Reference in a new issue