forward.m 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. // TEST_CONFIG MEM=mrc
  2. #include "test.h"
  3. #include <objc/runtime.h>
  4. #include <objc/message.h>
  5. id ID_RESULT = (id)0x12345678;
  6. long long LL_RESULT = __LONG_LONG_MAX__ - 2LL*__INT_MAX__;
  7. double FP_RESULT = __DBL_MIN__ + __DBL_EPSILON__;
  8. long double LFP_RESULT = __LDBL_MIN__ + __LDBL_EPSILON__;
  9. // STRET_RESULT in test.h
  10. static int state = 0;
  11. static id receiver;
  12. OBJC_ROOT_CLASS
  13. @interface Super { id isa; } @end
  14. @interface Super (Forwarded)
  15. +(id)idret:
  16. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  17. +(id)idre2:
  18. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  19. +(id)idre3:
  20. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  21. +(long long)llret:
  22. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  23. +(long long)llre2:
  24. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  25. +(long long)llre3:
  26. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  27. +(struct stret)stret:
  28. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  29. +(struct stret)stre2:
  30. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  31. +(struct stret)stre3:
  32. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  33. +(double)fpret:
  34. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  35. +(double)fpre2:
  36. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  37. +(double)fpre3:
  38. (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15;
  39. @end
  40. long long forward_handler(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15)
  41. {
  42. #if __arm64__
  43. # if __LP64__
  44. # define p "x" // true arm64
  45. # else
  46. # define p "w" // arm64_32
  47. # endif
  48. void *struct_addr;
  49. __asm__ volatile("mov %"p"0, "p"8" : "=r" (struct_addr) : : p"8");
  50. #endif
  51. testassert(self == receiver);
  52. testassert(i1 == 1);
  53. testassert(i2 == 2);
  54. testassert(i3 == 3);
  55. testassert(i4 == 4);
  56. testassert(i5 == 5);
  57. testassert(i6 == 6);
  58. testassert(i7 == 7);
  59. testassert(i8 == 8);
  60. testassert(i9 == 9);
  61. testassert(i10 == 10);
  62. testassert(i11 == 11);
  63. testassert(i12 == 12);
  64. testassert(i13 == 13);
  65. testassert(f1 == 1.0);
  66. testassert(f2 == 2.0);
  67. testassert(f3 == 3.0);
  68. testassert(f4 == 4.0);
  69. testassert(f5 == 5.0);
  70. testassert(f6 == 6.0);
  71. testassert(f7 == 7.0);
  72. testassert(f8 == 8.0);
  73. testassert(f9 == 9.0);
  74. testassert(f10 == 10.0);
  75. testassert(f11 == 11.0);
  76. testassert(f12 == 12.0);
  77. testassert(f13 == 13.0);
  78. testassert(f14 == 14.0);
  79. testassert(f15 == 15.0);
  80. if (_cmd == @selector(idret::::::::::::::::::::::::::::) ||
  81. _cmd == @selector(idre2::::::::::::::::::::::::::::) ||
  82. _cmd == @selector(idre3::::::::::::::::::::::::::::))
  83. {
  84. union {
  85. id idval;
  86. long long llval;
  87. } result;
  88. testassert(state == 11);
  89. state = 12;
  90. result.idval = ID_RESULT;
  91. return result.llval;
  92. }
  93. else if (_cmd == @selector(llret::::::::::::::::::::::::::::) ||
  94. _cmd == @selector(llre2::::::::::::::::::::::::::::) ||
  95. _cmd == @selector(llre3::::::::::::::::::::::::::::))
  96. {
  97. testassert(state == 13);
  98. state = 14;
  99. return LL_RESULT;
  100. }
  101. else if (_cmd == @selector(fpret::::::::::::::::::::::::::::) ||
  102. _cmd == @selector(fpre2::::::::::::::::::::::::::::) ||
  103. _cmd == @selector(fpre3::::::::::::::::::::::::::::))
  104. {
  105. testassert(state == 15);
  106. state = 16;
  107. #if defined(__i386__)
  108. __asm__ volatile("fldl %0" : : "m" (FP_RESULT));
  109. #elif defined(__x86_64__)
  110. __asm__ volatile("movsd %0, %%xmm0" : : "m" (FP_RESULT));
  111. #elif defined(__arm64__)
  112. __asm__ volatile("ldr d0, %0" : : "m" (FP_RESULT));
  113. #elif defined(__arm__) && __ARM_ARCH_7K__
  114. __asm__ volatile("vld1.64 {d0}, %0" : : "m" (FP_RESULT));
  115. #elif defined(__arm__)
  116. union {
  117. double fpval;
  118. long long llval;
  119. } result;
  120. result.fpval = FP_RESULT;
  121. return result.llval;
  122. #else
  123. # error unknown architecture
  124. #endif
  125. return 0;
  126. }
  127. else if (_cmd == @selector(stret::::::::::::::::::::::::::::) ||
  128. _cmd == @selector(stre2::::::::::::::::::::::::::::) ||
  129. _cmd == @selector(stre3::::::::::::::::::::::::::::))
  130. {
  131. #if __i386__ || __x86_64__ || __arm__
  132. fail("stret message sent to non-stret forward_handler");
  133. #elif __arm64_32__ || __arm64__
  134. testassert(state == 17);
  135. state = 18;
  136. memcpy(struct_addr, &STRET_RESULT, sizeof(STRET_RESULT));
  137. return 0;
  138. #else
  139. # error unknown architecture
  140. #endif
  141. }
  142. else {
  143. fail("unknown selector %s in forward_handler", sel_getName(_cmd));
  144. }
  145. }
  146. struct stret forward_stret_handler(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15)
  147. {
  148. testassert(self == receiver);
  149. testassert(i1 == 1);
  150. testassert(i2 == 2);
  151. testassert(i3 == 3);
  152. testassert(i4 == 4);
  153. testassert(i5 == 5);
  154. testassert(i6 == 6);
  155. testassert(i7 == 7);
  156. testassert(i8 == 8);
  157. testassert(i9 == 9);
  158. testassert(i10 == 10);
  159. testassert(i11 == 11);
  160. testassert(i12 == 12);
  161. testassert(i13 == 13);
  162. testassert(f1 == 1.0);
  163. testassert(f2 == 2.0);
  164. testassert(f3 == 3.0);
  165. testassert(f4 == 4.0);
  166. testassert(f5 == 5.0);
  167. testassert(f6 == 6.0);
  168. testassert(f7 == 7.0);
  169. testassert(f8 == 8.0);
  170. testassert(f9 == 9.0);
  171. testassert(f10 == 10.0);
  172. testassert(f11 == 11.0);
  173. testassert(f12 == 12.0);
  174. testassert(f13 == 13.0);
  175. testassert(f14 == 14.0);
  176. testassert(f15 == 15.0);
  177. if (_cmd == @selector(idret::::::::::::::::::::::::::::) ||
  178. _cmd == @selector(idre2::::::::::::::::::::::::::::) ||
  179. _cmd == @selector(idre3::::::::::::::::::::::::::::) ||
  180. _cmd == @selector(llret::::::::::::::::::::::::::::) ||
  181. _cmd == @selector(llre2::::::::::::::::::::::::::::) ||
  182. _cmd == @selector(llre3::::::::::::::::::::::::::::) ||
  183. _cmd == @selector(fpret::::::::::::::::::::::::::::) ||
  184. _cmd == @selector(fpre2::::::::::::::::::::::::::::) ||
  185. _cmd == @selector(fpre3::::::::::::::::::::::::::::))
  186. {
  187. fail("non-stret selector %s sent to forward_stret_handler", sel_getName(_cmd));
  188. }
  189. else if (_cmd == @selector(stret::::::::::::::::::::::::::::) ||
  190. _cmd == @selector(stre2::::::::::::::::::::::::::::) ||
  191. _cmd == @selector(stre3::::::::::::::::::::::::::::))
  192. {
  193. testassert(state == 17);
  194. state = 18;
  195. return STRET_RESULT;
  196. }
  197. else {
  198. fail("unknown selector %s in forward_stret_handler", sel_getName(_cmd));
  199. }
  200. }
  201. @implementation Super
  202. +(void)initialize { }
  203. +(id)class { return self; }
  204. @end
  205. typedef id (*id_fn_t)(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15);
  206. typedef long long (*ll_fn_t)(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15);
  207. typedef double (*fp_fn_t)(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15);
  208. typedef struct stret (*st_fn_t)(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15);
  209. #if __x86_64__
  210. typedef struct stret * (*fake_st_fn_t)(struct stret *, id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15);
  211. #endif
  212. __BEGIN_DECLS
  213. extern void *getSP(void);
  214. __END_DECLS
  215. #if defined(__x86_64__)
  216. asm(".text \n _getSP: movq %rsp, %rax \n retq \n");
  217. #elif defined(__i386__)
  218. asm(".text \n _getSP: movl %esp, %eax \n ret \n");
  219. #elif defined(__arm__)
  220. asm(".text \n .thumb \n .thumb_func _getSP \n "
  221. "_getSP: mov r0, sp \n bx lr \n");
  222. #elif defined(__arm64__)
  223. asm(".text \n _getSP: mov x0, sp \n ret \n");
  224. #else
  225. # error unknown architecture
  226. #endif
  227. int main()
  228. {
  229. id idval;
  230. long long llval;
  231. struct stret stval;
  232. #if __x86_64__
  233. struct stret *stptr;
  234. #endif
  235. double fpval;
  236. void *sp1 = (void*)1;
  237. void *sp2 = (void*)2;
  238. st_fn_t stret_fwd;
  239. #if __arm64__
  240. stret_fwd = (st_fn_t)_objc_msgForward;
  241. #else
  242. stret_fwd = (st_fn_t)_objc_msgForward_stret;
  243. #endif
  244. receiver = [Super class];
  245. // Test user-defined forward handler
  246. objc_setForwardHandler((void*)&forward_handler, (void*)&forward_stret_handler);
  247. state = 11;
  248. sp1 = getSP();
  249. idval = [Super idre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  250. sp2 = getSP();
  251. testassert(sp1 == sp2);
  252. testassert(state == 12);
  253. testassert(idval == ID_RESULT);
  254. state = 13;
  255. sp1 = getSP();
  256. llval = [Super llre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  257. sp2 = getSP();
  258. testassert(sp1 == sp2);
  259. testassert(state == 14);
  260. testassert(llval == LL_RESULT);
  261. state = 15;
  262. sp1 = getSP();
  263. fpval = [Super fpre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  264. sp2 = getSP();
  265. testassert(sp1 == sp2);
  266. testassert(state == 16);
  267. testassert(fpval == FP_RESULT);
  268. state = 17;
  269. sp1 = getSP();
  270. stval = [Super stre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  271. sp2 = getSP();
  272. testassert(sp1 == sp2);
  273. testassert(state == 18);
  274. testassert(stret_equal(stval, STRET_RESULT));
  275. #if __x86_64__
  276. // check stret return register
  277. state = 17;
  278. sp1 = getSP();
  279. stptr = ((fake_st_fn_t)objc_msgSend_stret)(&stval, [Super class], @selector(stre3::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  280. sp2 = getSP();
  281. testassert(sp1 == sp2);
  282. testassert(state == 18);
  283. testassert(stret_equal(stval, STRET_RESULT));
  284. testassert(stptr == &stval);
  285. #endif
  286. // Test user-defined forward handler, cached
  287. state = 11;
  288. sp1 = getSP();
  289. idval = [Super idre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  290. sp2 = getSP();
  291. testassert(sp1 == sp2);
  292. testassert(state == 12);
  293. testassert(idval == ID_RESULT);
  294. state = 13;
  295. sp1 = getSP();
  296. llval = [Super llre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  297. sp2 = getSP();
  298. testassert(sp1 == sp2);
  299. testassert(state == 14);
  300. testassert(llval == LL_RESULT);
  301. state = 15;
  302. sp1 = getSP();
  303. fpval = [Super fpre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  304. sp2 = getSP();
  305. testassert(sp1 == sp2);
  306. testassert(state == 16);
  307. testassert(fpval == FP_RESULT);
  308. state = 17;
  309. sp1 = getSP();
  310. stval = [Super stre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  311. sp2 = getSP();
  312. testassert(sp1 == sp2);
  313. testassert(state == 18);
  314. testassert(stret_equal(stval, STRET_RESULT));
  315. #if __x86_64__
  316. // check stret return register
  317. state = 17;
  318. sp1 = getSP();
  319. stptr = ((fake_st_fn_t)objc_msgSend_stret)(&stval, [Super class], @selector(stre3::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  320. sp2 = getSP();
  321. testassert(sp1 == sp2);
  322. testassert(state == 18);
  323. testassert(stret_equal(stval, STRET_RESULT));
  324. testassert(stptr == &stval);
  325. #endif
  326. // Test user-defined forward handler, uncached but fixed-up
  327. _objc_flush_caches(nil);
  328. state = 11;
  329. sp1 = getSP();
  330. idval = [Super idre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  331. sp2 = getSP();
  332. testassert(sp1 == sp2);
  333. testassert(state == 12);
  334. testassert(idval == ID_RESULT);
  335. state = 13;
  336. sp1 = getSP();
  337. llval = [Super llre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  338. sp2 = getSP();
  339. testassert(sp1 == sp2);
  340. testassert(state == 14);
  341. testassert(llval == LL_RESULT);
  342. state = 15;
  343. sp1 = getSP();
  344. fpval = [Super fpre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  345. sp2 = getSP();
  346. testassert(sp1 == sp2);
  347. testassert(state == 16);
  348. testassert(fpval == FP_RESULT);
  349. state = 17;
  350. sp1 = getSP();
  351. stval = [Super stre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
  352. sp2 = getSP();
  353. testassert(sp1 == sp2);
  354. testassert(state == 18);
  355. testassert(stret_equal(stval, STRET_RESULT));
  356. #if __x86_64__
  357. // check stret return register
  358. state = 17;
  359. sp1 = getSP();
  360. stptr = ((fake_st_fn_t)objc_msgSend_stret)(&stval, [Super class], @selector(stre3::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  361. sp2 = getSP();
  362. testassert(sp1 == sp2);
  363. testassert(state == 18);
  364. testassert(stret_equal(stval, STRET_RESULT));
  365. testassert(stptr == &stval);
  366. #endif
  367. // Test user-defined forward handler, manual forwarding
  368. state = 11;
  369. sp1 = getSP();
  370. idval = ((id_fn_t)_objc_msgForward)(receiver, @selector(idre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  371. sp2 = getSP();
  372. testassert(sp1 == sp2);
  373. testassert(state == 12);
  374. testassert(idval == ID_RESULT);
  375. state = 13;
  376. sp1 = getSP();
  377. llval = ((ll_fn_t)_objc_msgForward)(receiver, @selector(llre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  378. sp2 = getSP();
  379. testassert(sp1 == sp2);
  380. testassert(state == 14);
  381. testassert(llval == LL_RESULT);
  382. state = 15;
  383. sp1 = getSP();
  384. fpval = ((fp_fn_t)_objc_msgForward)(receiver, @selector(fpre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  385. sp2 = getSP();
  386. testassert(sp1 == sp2);
  387. testassert(state == 16);
  388. testassert(fpval == FP_RESULT);
  389. state = 17;
  390. sp1 = getSP();
  391. stval = stret_fwd(receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  392. sp2 = getSP();
  393. testassert(sp1 == sp2);
  394. testassert(state == 18);
  395. testassert(stret_equal(stval, STRET_RESULT));
  396. // Test user-defined forward handler, manual forwarding, cached
  397. state = 11;
  398. sp1 = getSP();
  399. idval = ((id_fn_t)_objc_msgForward)(receiver, @selector(idre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  400. sp2 = getSP();
  401. testassert(sp1 == sp2);
  402. testassert(state == 12);
  403. testassert(idval == ID_RESULT);
  404. state = 13;
  405. sp1 = getSP();
  406. llval = ((ll_fn_t)_objc_msgForward)(receiver, @selector(llre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  407. sp2 = getSP();
  408. testassert(sp1 == sp2);
  409. testassert(state == 14);
  410. testassert(llval == LL_RESULT);
  411. state = 15;
  412. sp1 = getSP();
  413. fpval = ((fp_fn_t)_objc_msgForward)(receiver, @selector(fpre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  414. sp2 = getSP();
  415. testassert(sp1 == sp2);
  416. testassert(state == 16);
  417. testassert(fpval == FP_RESULT);
  418. state = 17;
  419. sp1 = getSP();
  420. stval = stret_fwd(receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  421. sp2 = getSP();
  422. testassert(sp1 == sp2);
  423. testassert(state == 18);
  424. testassert(stret_equal(stval, STRET_RESULT));
  425. // Test user-defined forward handler, manual forwarding, uncached but fixed-up
  426. _objc_flush_caches(nil);
  427. state = 11;
  428. sp1 = getSP();
  429. idval = ((id_fn_t)_objc_msgForward)(receiver, @selector(idre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  430. sp2 = getSP();
  431. testassert(sp1 == sp2);
  432. testassert(state == 12);
  433. testassert(idval == ID_RESULT);
  434. state = 13;
  435. sp1 = getSP();
  436. llval = ((ll_fn_t)_objc_msgForward)(receiver, @selector(llre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  437. sp2 = getSP();
  438. testassert(sp1 == sp2);
  439. testassert(state == 14);
  440. testassert(llval == LL_RESULT);
  441. state = 15;
  442. sp1 = getSP();
  443. fpval = ((fp_fn_t)_objc_msgForward)(receiver, @selector(fpre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  444. sp2 = getSP();
  445. testassert(sp1 == sp2);
  446. testassert(state == 16);
  447. testassert(fpval == FP_RESULT);
  448. state = 17;
  449. sp1 = getSP();
  450. stval = stret_fwd(receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
  451. sp2 = getSP();
  452. testassert(sp1 == sp2);
  453. testassert(state == 18);
  454. testassert(stret_equal(stval, STRET_RESULT));
  455. succeed(__FILE__);
  456. }