#include"stdio.h" int main() { void (^blk)(void) = ^{printf("Block.\n");}; blk(); return 0; }
#ifndef __OBJC2__ #define __OBJC2__ #endif struct objc_selector; struct objc_class; struct __rw_objc_super { struct objc_object *object; struct objc_object *superClass; __rw_objc_super(struct objc_object *o, struct objc_object *s) : object(o), superClass(s) {} }; #ifndef _REWRITER_typedef_Protocol typedef struct objc_object Protocol; #define _REWRITER_typedef_Protocol #endif #define __OBJC_RW_DLLIMPORT extern __OBJC_RW_DLLIMPORT void objc_msgSend(void); __OBJC_RW_DLLIMPORT void objc_msgSendSuper(void); __OBJC_RW_DLLIMPORT void objc_msgSend_stret(void); __OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void); __OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void); __OBJC_RW_DLLIMPORT struct objc_class *objc_getClass(const char *); __OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass(struct objc_class *); __OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass(const char *); __OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *); __OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *); __OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *); __OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *); #ifdef _WIN64 typedef unsigned long long _WIN_NSUInteger; #else typedef unsigned int _WIN_NSUInteger; #endif #ifndef __FASTENUMERATIONSTATE struct __objcFastEnumerationState { unsigned long state; void **itemsPtr; unsigned long *mutationsPtr; unsigned long extra[5]; }; __OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *); #define __FASTENUMERATIONSTATE #endif #ifndef __NSCONSTANTSTRINGIMPL struct __NSConstantStringImpl { int *isa; int flags; char *str; long length; }; #ifdef CF_EXPORT_CONSTANT_STRING extern "C" __declspec(dllexport) int __CFConstantStringClassReference[]; #else __OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[]; #endif #define __NSCONSTANTSTRINGIMPL #endif #ifndef BLOCK_IMPL #define BLOCK_IMPL struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; // Runtime copy/destroy helper functions (from Block_private.h) #ifdef __OBJC_EXPORT_BLOCKS extern "C" __declspec(dllexport) void _Block_object_assign(void *, const void *, const int); extern "C" __declspec(dllexport) void _Block_object_dispose(const void *, const int); extern "C" __declspec(dllexport) void *_NSConcreteGlobalBlock[32]; extern "C" __declspec(dllexport) void *_NSConcreteStackBlock[32]; #else __OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int); __OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int); __OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32]; __OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32]; #endif #endif #define __block #define __weak #include <stdarg.h> struct __NSContainer_literal { void * *arr; __NSContainer_literal (unsigned int count, ...) { va_list marker; va_start(marker, count); arr = new void *[count]; for (unsigned i = 0; i < count; i++) arr[i] = va_arg(marker, void *); va_end( marker ); }; ~__NSContainer_literal() { delete[] arr; } }; extern "C" __declspec(dllimport) void * objc_autoreleasePoolPush(void); extern "C" __declspec(dllimport) void objc_autoreleasePoolPop(void *); struct __AtAutoreleasePool { __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();} ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);} void * atautoreleasepoolobj; }; #define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER) typedef signed char __int8_t; typedef unsigned char __uint8_t; typedef short __int16_t; typedef unsigned short __uint16_t; typedef int __int32_t; typedef unsigned int __uint32_t; typedef long long __int64_t; typedef unsigned long long __uint64_t; typedef long __darwin_intptr_t; typedef unsigned int __darwin_natural_t; typedef int __darwin_ct_rune_t; typedef union { char __mbstate8[128]; long long _mbstateL; } __mbstate_t; typedef __mbstate_t __darwin_mbstate_t; typedef long int __darwin_ptrdiff_t; typedef long unsigned int __darwin_size_t; typedef __builtin_va_list __darwin_va_list; typedef int __darwin_wchar_t; typedef __darwin_wchar_t __darwin_rune_t; typedef int __darwin_wint_t; typedef unsigned long __darwin_clock_t; typedef __uint32_t __darwin_socklen_t; typedef long __darwin_ssize_t; typedef long __darwin_time_t; typedef __int64_t __darwin_blkcnt_t; typedef __int32_t __darwin_blksize_t; typedef __int32_t __darwin_dev_t; typedef unsigned int __darwin_fsblkcnt_t; typedef unsigned int __darwin_fsfilcnt_t; typedef __uint32_t __darwin_gid_t; typedef __uint32_t __darwin_id_t; typedef __uint64_t __darwin_ino64_t; typedef __darwin_ino64_t __darwin_ino_t; typedef __darwin_natural_t __darwin_mach_port_name_t; typedef __darwin_mach_port_name_t __darwin_mach_port_t; typedef __uint16_t __darwin_mode_t; typedef __int64_t __darwin_off_t; typedef __int32_t __darwin_pid_t; typedef __uint32_t __darwin_sigset_t; typedef __int32_t __darwin_suseconds_t; typedef __uint32_t __darwin_uid_t; typedef __uint32_t __darwin_useconds_t; typedef unsigned char __darwin_uuid_t[16]; typedef char __darwin_uuid_string_t[37]; struct __darwin_pthread_handler_rec { void (*__routine)(void *); void *__arg; struct __darwin_pthread_handler_rec *__next; }; struct _opaque_pthread_attr_t { long __sig; char __opaque[56]; }; struct _opaque_pthread_cond_t { long __sig; char __opaque[40]; }; struct _opaque_pthread_condattr_t { long __sig; char __opaque[8]; }; struct _opaque_pthread_mutex_t { long __sig; char __opaque[56]; }; struct _opaque_pthread_mutexattr_t { long __sig; char __opaque[8]; }; struct _opaque_pthread_once_t { long __sig; char __opaque[8]; }; struct _opaque_pthread_rwlock_t { long __sig; char __opaque[192]; }; struct _opaque_pthread_rwlockattr_t { long __sig; char __opaque[16]; }; struct _opaque_pthread_t { long __sig; struct __darwin_pthread_handler_rec *__cleanup_stack; char __opaque[8176]; }; typedef struct _opaque_pthread_attr_t __darwin_pthread_attr_t; typedef struct _opaque_pthread_cond_t __darwin_pthread_cond_t; typedef struct _opaque_pthread_condattr_t __darwin_pthread_condattr_t; typedef unsigned long __darwin_pthread_key_t; typedef struct _opaque_pthread_mutex_t __darwin_pthread_mutex_t; typedef struct _opaque_pthread_mutexattr_t __darwin_pthread_mutexattr_t; typedef struct _opaque_pthread_once_t __darwin_pthread_once_t; typedef struct _opaque_pthread_rwlock_t __darwin_pthread_rwlock_t; typedef struct _opaque_pthread_rwlockattr_t __darwin_pthread_rwlockattr_t; typedef struct _opaque_pthread_t *__darwin_pthread_t; typedef int __darwin_nl_item; typedef int __darwin_wctrans_t; typedef __uint32_t __darwin_wctype_t; typedef __darwin_va_list va_list; typedef __darwin_size_t size_t; extern "C" { int renameat(int, const char *, int, const char *) __attribute__((availability(macosx,introduced=10.10))); } typedef __darwin_off_t fpos_t; struct __sbuf { unsigned char *_base; int _size; }; struct __sFILEX; typedef struct __sFILE { unsigned char *_p; int _r; int _w; short _flags; short _file; struct __sbuf _bf; int _lbfsize; void *_cookie; int (*_close)(void *); int (*_read) (void *, char *, int); fpos_t (*_seek) (void *, fpos_t, int); int (*_write)(void *, const char *, int); struct __sbuf _ub; struct __sFILEX *_extra; int _ur; unsigned char _ubuf[3]; unsigned char _nbuf[1]; struct __sbuf _lb; int _blksize; fpos_t _offset; } FILE; extern "C" { extern FILE *__stdinp; extern FILE *__stdoutp; extern FILE *__stderrp; } extern "C" { void clearerr(FILE *); int fclose(FILE *); int feof(FILE *); int ferror(FILE *); int fflush(FILE *); int fgetc(FILE *); int fgetpos(FILE * , fpos_t *); char *fgets(char * , int, FILE *); FILE *fopen(const char * , const char * ) __asm("_" "fopen"); int fprintf(FILE * , const char * , ...) __attribute__((__format__ (__printf__, 2, 3))); int fputc(int, FILE *); int fputs(const char * , FILE * ) __asm("_" "fputs") ; size_t fread(void * , size_t, size_t, FILE * ); FILE *freopen(const char * , const char * , FILE * ) __asm("_" "freopen") ; int fscanf(FILE * , const char * , ...) __attribute__((__format__ (__scanf__, 2, 3))); int fseek(FILE *, long, int); int fsetpos(FILE *, const fpos_t *); long ftell(FILE *); size_t fwrite(const void * , size_t, size_t, FILE * ) __asm("_" "fwrite") ; int getc(FILE *); int getchar(void); char *gets(char *); void perror(const char *); int printf(const char * , ...) __attribute__((__format__ (__printf__, 1, 2))); int putc(int, FILE *); int putchar(int); int puts(const char *); int remove(const char *); int rename (const char *, const char *); void rewind(FILE *); int scanf(const char * , ...) __attribute__((__format__ (__scanf__, 1, 2))); void setbuf(FILE * , char * ); int setvbuf(FILE * , char * , int, size_t); int sprintf(char * , const char * , ...) __attribute__((__format__ (__printf__, 2, 3))); int sscanf(const char * , const char * , ...) __attribute__((__format__ (__scanf__, 2, 3))); FILE *tmpfile(void); __attribute__((deprecated("This function is provided for compatibility reasons only. Due to security concerns inherent in the design of tmpnam(3), it is highly recommended that you use mkstemp(3) instead."))) char *tmpnam(char *); int ungetc(int, FILE *); int vfprintf(FILE * , const char * , va_list) __attribute__((__format__ (__printf__, 2, 0))); int vprintf(const char * , va_list) __attribute__((__format__ (__printf__, 1, 0))); int vsprintf(char * , const char * , va_list) __attribute__((__format__ (__printf__, 2, 0))); } extern "C" { char *ctermid(char *); FILE *fdopen(int, const char *) __asm("_" "fdopen"); int fileno(FILE *); } extern "C" { int pclose(FILE *); FILE *popen(const char *, const char *) __asm("_" "popen"); } extern "C" { int __srget(FILE *); int __svfscanf(FILE *, const char *, va_list) __attribute__((__format__ (__scanf__, 2, 0))); int __swbuf(int, FILE *); } inline __attribute__ ((__always_inline__)) int __sputc(int _c, FILE *_p) { if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) return (*_p->_p++ = _c); else return (__swbuf(_c, _p)); } extern "C" { void flockfile(FILE *); int ftrylockfile(FILE *); void funlockfile(FILE *); int getc_unlocked(FILE *); int getchar_unlocked(void); int putc_unlocked(int, FILE *); int putchar_unlocked(int); int getw(FILE *); int putw(int, FILE *); __attribute__((deprecated("This function is provided for compatibility reasons only. Due to security concerns inherent in the design of tempnam(3), it is highly recommended that you use mkstemp(3) instead."))) char *tempnam(const char *, const char *) __asm("_" "tempnam") ; } typedef __darwin_off_t off_t; extern "C" { int fseeko(FILE *, off_t, int); off_t ftello(FILE *); } extern "C" { int snprintf(char * , size_t, const char * , ...) __attribute__((__format__ (__printf__, 3, 4))); int vfscanf(FILE * , const char * , va_list) __attribute__((__format__ (__scanf__, 2, 0))); int vscanf(const char * , va_list) __attribute__((__format__ (__scanf__, 1, 0))); int vsnprintf(char * , size_t, const char * , va_list) __attribute__((__format__ (__printf__, 3, 0))); int vsscanf(const char * , const char * , va_list) __attribute__((__format__ (__scanf__, 2, 0))); } typedef __darwin_ssize_t ssize_t; extern "C" { int dprintf(int, const char * , ...) __attribute__((__format__ (__printf__, 2, 3))) __attribute__((availability(macosx,introduced=10.7))); int vdprintf(int, const char * , va_list) __attribute__((__format__ (__printf__, 2, 0))) __attribute__((availability(macosx,introduced=10.7))); ssize_t getdelim(char ** , size_t * , int, FILE * ) __attribute__((availability(macosx,introduced=10.7))); ssize_t getline(char ** , size_t * , FILE * ) __attribute__((availability(macosx,introduced=10.7))); } extern "C" { extern const int sys_nerr; extern const char *const sys_errlist[]; int asprintf(char ** , const char * , ...) __attribute__((__format__ (__printf__, 2, 3))); char *ctermid_r(char *); char *fgetln(FILE *, size_t *); const char *fmtcheck(const char *, const char *); int fpurge(FILE *); void setbuffer(FILE *, char *, int); int setlinebuf(FILE *); int vasprintf(char ** , const char * , va_list) __attribute__((__format__ (__printf__, 2, 0))); FILE *zopen(const char *, const char *, int); FILE *funopen(const void *, int (*)(void *, char *, int), int (*)(void *, const char *, int), fpos_t (*)(void *, fpos_t, int), int (*)(void *)); } struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __main_block_func_0(struct __main_block_impl_0 *__cself) { printf("Block.\n");} static struct __main_block_desc_0 { size_t reserved; size_t Block_size; } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)}; int main() { void (*blk)(void) = (void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA); ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); return 0; } static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };一经clang变换,原本只有8行的代码变成了500多行。
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __main_block_func_0(struct __main_block_impl_0 *__cself) { printf("Block.\n");} static struct __main_block_desc_0 { size_t reserved; size_t Block_size; } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)}; int main() { void (*blk)(void) = (void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA); ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); return 0; }
int main() { void (*blk)(void) = (void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA); ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); return 0; }
struct
__block_impl {
void
*isa;
int
Flags;
int
Reserved;
void
*FuncPtr;
};
__main_block_impl_0的意思是main函数中的第0个block的implementation(命名:所属函数名main+block+implementation的缩写imply+block在所属函数中出现的顺序0),这个就是这个block的主体了。
int global_val = 1; static int static_global_val = 2; int main() { static int static_val = 3; void (^blk)(void) = ^{ global_val *=2; static_global_val *=3; static_val *=4; }; return 0; }clang 变换后:
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; int global_val = 1; static int static_global_val = 2; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; int *static_val; __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *_static_val, int flags=0) : static_val(_static_val) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __main_block_func_0(struct __main_block_impl_0 *__cself) { int *static_val = __cself->static_val; // bound by copy global_val *=2; static_global_val *=3; (*static_val) *=4; } static struct __main_block_desc_0 { size_t reserved; size_t Block_size; } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)}; int main() { static int static_val = 3; void (*blk)(void) = (void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, &static_val); return 0; }
int main() { __block int val_block = 3; void (^blk)(void) = ^{ val_block *=4; }; blk(); return 0; }
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; struct __Block_byref_val_block_0 { void *__isa; __Block_byref_val_block_0 *__forwarding; int __flags; int __size; int val_block; }; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; __Block_byref_val_block_0 *val_block; // by ref __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_val_block_0 *_val_block, int flags=0) : val_block(_val_block->__forwarding) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __main_block_func_0(struct __main_block_impl_0 *__cself) { __Block_byref_val_block_0 *val_block = __cself->val_block; // bound by ref (val_block->__forwarding->val_block) *=4; } static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->val_block, (void*)src->val_block, 8/*BLOCK_FIELD_IS_BYREF*/);} static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->val_block, 8/*BLOCK_FIELD_IS_BYREF*/);} static struct __main_block_desc_0 { size_t reserved; size_t Block_size; void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*); void (*dispose)(struct __main_block_impl_0*); } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0}; int main() { __attribute__((__blocks__(byref))) __Block_byref_val_block_0 val_block = {(void*)0,(__Block_byref_val_block_0 *)&val_block, 0, sizeof(__Block_byref_val_block_0), 3}; void (*blk)(void) = (void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_val_block_0 *)&val_block, 570425344); ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); return 0; }