msgSend.m 95 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680
  1. /*
  2. asm-placeholder.exe is used below to disassemble objc_msgSend
  3. TEST_BUILD
  4. $C{COMPILE} -x assembler $DIR/asm-placeholder.s -o asm-placeholder.exe
  5. $C{COMPILE} $DIR/msgSend.m -o msgSend.exe -Wno-unused-parameter -Wundeclared-selector -D__DARWIN_OPAQUE_ARM_THREAD_STATE64=1
  6. END
  7. */
  8. #include "test.h"
  9. #include "testroot.i"
  10. #include <libkern/OSCacheControl.h>
  11. #include <sys/stat.h>
  12. #include <objc/objc.h>
  13. #include <objc/runtime.h>
  14. #include <objc/objc-internal.h>
  15. #include <objc/objc-abi.h>
  16. #include <simd/simd.h>
  17. #include <mach-o/loader.h>
  18. // rdar://21694990 simd.h should have a vector_equal(a, b) function
  19. static bool vector_equal(vector_ulong2 lhs, vector_ulong2 rhs) {
  20. return vector_all(lhs == rhs);
  21. }
  22. #if __arm64__
  23. // no stret dispatchers
  24. # define SUPPORT_STRET 0
  25. # define objc_msgSend_stret objc_msgSend
  26. # define objc_msgSendSuper2_stret objc_msgSendSuper2
  27. # define objc_msgSend_stret_debug objc_msgSend_debug
  28. # define objc_msgSendSuper2_stret_debug objc_msgSendSuper2_debug
  29. # define objc_msgLookup_stret objc_msgLookup
  30. # define objc_msgLookupSuper2_stret objc_msgLookupSuper2
  31. # define method_invoke_stret method_invoke
  32. #else
  33. # define SUPPORT_STRET 1
  34. #endif
  35. #if defined(__arm__)
  36. // rdar://8331406
  37. # define ALIGN_()
  38. #else
  39. # define ALIGN_() asm(".align 4");
  40. #endif
  41. @interface Super : TestRoot @end
  42. @interface Sub : Super @end
  43. static int state = 0;
  44. static id SELF;
  45. // for typeof() shorthand only
  46. id (*idmsg0)(id, SEL) __attribute__((unused));
  47. long long (*llmsg0)(id, SEL) __attribute__((unused));
  48. // struct stret (*stretmsg0)(id, SEL) __attribute__((unused));
  49. double (*fpmsg0)(id, SEL) __attribute__((unused));
  50. long double (*lfpmsg0)(id, SEL) __attribute__((unused));
  51. vector_ulong2 (*vecmsg0)(id, SEL) __attribute__((unused));
  52. #define VEC1 ((vector_ulong2){1, 1})
  53. #define VEC2 ((vector_ulong2){2, 2})
  54. #define VEC3 ((vector_ulong2){3, 3})
  55. #define VEC4 ((vector_ulong2){4, 4})
  56. #define VEC5 ((vector_ulong2){5, 5})
  57. #define VEC6 ((vector_ulong2){6, 6})
  58. #define VEC7 ((vector_ulong2){7, 7})
  59. #define VEC8 ((vector_ulong2){8, 8})
  60. #define CHECK_ARGS(sel) \
  61. do { \
  62. testassert(self == SELF); \
  63. testassert(_cmd == sel_registerName(#sel "::::::::::::::::::::::::::::::::::::"));\
  64. testassert(i1 == 1); \
  65. testassert(i2 == 2); \
  66. testassert(i3 == 3); \
  67. testassert(i4 == 4); \
  68. testassert(i5 == 5); \
  69. testassert(i6 == 6); \
  70. testassert(i7 == 7); \
  71. testassert(i8 == 8); \
  72. testassert(i9 == 9); \
  73. testassert(i10 == 10); \
  74. testassert(i11 == 11); \
  75. testassert(i12 == 12); \
  76. testassert(i13 == 13); \
  77. testassert(f1 == 1.0); \
  78. testassert(f2 == 2.0); \
  79. testassert(f3 == 3.0); \
  80. testassert(f4 == 4.0); \
  81. testassert(f5 == 5.0); \
  82. testassert(f6 == 6.0); \
  83. testassert(f7 == 7.0); \
  84. testassert(f8 == 8.0); \
  85. testassert(f9 == 9.0); \
  86. testassert(f10 == 10.0); \
  87. testassert(f11 == 11.0); \
  88. testassert(f12 == 12.0); \
  89. testassert(f13 == 13.0); \
  90. testassert(f14 == 14.0); \
  91. testassert(f15 == 15.0); \
  92. testassert(vector_all(v1 == 1)); \
  93. testassert(vector_all(v2 == 2)); \
  94. testassert(vector_all(v3 == 3)); \
  95. testassert(vector_all(v4 == 4)); \
  96. testassert(vector_all(v5 == 5)); \
  97. testassert(vector_all(v6 == 6)); \
  98. testassert(vector_all(v7 == 7)); \
  99. testassert(vector_all(v8 == 8)); \
  100. } while (0)
  101. #define CHECK_ARGS_NOARG(sel) \
  102. do { \
  103. testassert(self == SELF); \
  104. testassert(_cmd == sel_registerName(#sel "_noarg"));\
  105. } while (0)
  106. id NIL_RECEIVER;
  107. id ID_RESULT;
  108. long long LL_RESULT = __LONG_LONG_MAX__ - 2LL*__INT_MAX__;
  109. double FP_RESULT = __DBL_MIN__ + __DBL_EPSILON__;
  110. long double LFP_RESULT = __LDBL_MIN__ + __LDBL_EPSILON__;
  111. vector_ulong2 VEC_RESULT = { 0x1234567890abcdefULL, 0xfedcba0987654321ULL };
  112. // STRET_RESULT in test.h
  113. static struct stret zero;
  114. struct stret_i1 {
  115. uintptr_t i1;
  116. };
  117. struct stret_i2 {
  118. uintptr_t i1;
  119. uintptr_t i2;
  120. };
  121. struct stret_i3 {
  122. uintptr_t i1;
  123. uintptr_t i2;
  124. uintptr_t i3;
  125. };
  126. struct stret_i4 {
  127. uintptr_t i1;
  128. uintptr_t i2;
  129. uintptr_t i3;
  130. };
  131. struct stret_i5 {
  132. uintptr_t i1;
  133. uintptr_t i2;
  134. uintptr_t i3;
  135. uintptr_t i4;
  136. uintptr_t i5;
  137. };
  138. struct stret_i6 {
  139. uintptr_t i1;
  140. uintptr_t i2;
  141. uintptr_t i3;
  142. uintptr_t i4;
  143. uintptr_t i5;
  144. uintptr_t i6;
  145. };
  146. struct stret_i7 {
  147. uintptr_t i1;
  148. uintptr_t i2;
  149. uintptr_t i3;
  150. uintptr_t i4;
  151. uintptr_t i5;
  152. uintptr_t i6;
  153. uintptr_t i7;
  154. };
  155. struct stret_i8 {
  156. uintptr_t i1;
  157. uintptr_t i2;
  158. uintptr_t i3;
  159. uintptr_t i4;
  160. uintptr_t i5;
  161. uintptr_t i8;
  162. uintptr_t i9;
  163. };
  164. struct stret_i9 {
  165. uintptr_t i1;
  166. uintptr_t i2;
  167. uintptr_t i3;
  168. uintptr_t i4;
  169. uintptr_t i5;
  170. uintptr_t i6;
  171. uintptr_t i7;
  172. uintptr_t i8;
  173. uintptr_t i9;
  174. };
  175. struct stret_d1 {
  176. double d1;
  177. };
  178. struct stret_d2 {
  179. double d1;
  180. double d2;
  181. };
  182. struct stret_d3 {
  183. double d1;
  184. double d2;
  185. double d3;
  186. };
  187. struct stret_d4 {
  188. double d1;
  189. double d2;
  190. double d3;
  191. };
  192. struct stret_d5 {
  193. double d1;
  194. double d2;
  195. double d3;
  196. double d4;
  197. double d5;
  198. };
  199. struct stret_d6 {
  200. double d1;
  201. double d2;
  202. double d3;
  203. double d4;
  204. double d5;
  205. double d6;
  206. };
  207. struct stret_d7 {
  208. double d1;
  209. double d2;
  210. double d3;
  211. double d4;
  212. double d5;
  213. double d6;
  214. double d7;
  215. };
  216. struct stret_d8 {
  217. double d1;
  218. double d2;
  219. double d3;
  220. double d4;
  221. double d5;
  222. double d8;
  223. double d9;
  224. };
  225. struct stret_d9 {
  226. double d1;
  227. double d2;
  228. double d3;
  229. double d4;
  230. double d5;
  231. double d6;
  232. double d7;
  233. double d8;
  234. double d9;
  235. };
  236. @interface Super (Prototypes)
  237. // Method prototypes to pacify -Wundeclared-selector.
  238. -(id)idret:
  239. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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;
  240. -(long long)llret:
  241. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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;
  242. -(struct stret)stret:
  243. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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;
  244. -(double)fpret:
  245. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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;
  246. -(long double)lfpret:
  247. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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;
  248. -(vector_ulong2)vecret:
  249. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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;
  250. @end
  251. // Zero all volatile registers.
  252. #if __cplusplus
  253. extern "C"
  254. #endif
  255. void stomp(void);
  256. #if __x86_64__
  257. asm("\n .text"
  258. "\n .globl _stomp"
  259. "\n _stomp:"
  260. "\n mov $0, %rax"
  261. "\n mov $0, %rcx"
  262. "\n mov $0, %rdx"
  263. "\n mov $0, %rsi"
  264. "\n mov $0, %rdi"
  265. "\n mov $0, %r8"
  266. "\n mov $0, %r9"
  267. "\n mov $0, %r10"
  268. "\n mov $0, %r11"
  269. "\n xorps %xmm0, %xmm0"
  270. "\n xorps %xmm1, %xmm1"
  271. "\n xorps %xmm2, %xmm2"
  272. "\n xorps %xmm3, %xmm3"
  273. "\n xorps %xmm4, %xmm4"
  274. "\n xorps %xmm5, %xmm5"
  275. "\n xorps %xmm6, %xmm6"
  276. "\n xorps %xmm7, %xmm7"
  277. "\n xorps %xmm8, %xmm8"
  278. "\n xorps %xmm9, %xmm9"
  279. "\n xorps %xmm10, %xmm10"
  280. "\n xorps %xmm11, %xmm11"
  281. "\n xorps %xmm12, %xmm12"
  282. "\n xorps %xmm13, %xmm13"
  283. "\n xorps %xmm14, %xmm14"
  284. "\n xorps %xmm15, %xmm15"
  285. "\n ret");
  286. #elif __i386__
  287. asm("\n .text"
  288. "\n .globl _stomp"
  289. "\n _stomp:"
  290. "\n mov $0, %eax"
  291. "\n mov $0, %ecx"
  292. "\n mov $0, %edx"
  293. "\n xorps %xmm0, %xmm0"
  294. "\n xorps %xmm1, %xmm1"
  295. "\n xorps %xmm2, %xmm2"
  296. "\n xorps %xmm3, %xmm3"
  297. "\n xorps %xmm4, %xmm4"
  298. "\n xorps %xmm5, %xmm5"
  299. "\n xorps %xmm6, %xmm6"
  300. "\n xorps %xmm7, %xmm7"
  301. "\n ret");
  302. #elif __arm64__
  303. asm("\n .text"
  304. "\n .globl _stomp"
  305. "\n _stomp:"
  306. "\n mov x0, #0"
  307. "\n mov x1, #0"
  308. "\n mov x2, #0"
  309. "\n mov x3, #0"
  310. "\n mov x4, #0"
  311. "\n mov x5, #0"
  312. "\n mov x6, #0"
  313. "\n mov x7, #0"
  314. "\n mov x8, #0"
  315. "\n mov x9, #0"
  316. "\n mov x10, #0"
  317. "\n mov x11, #0"
  318. "\n mov x12, #0"
  319. "\n mov x13, #0"
  320. "\n mov x14, #0"
  321. "\n mov x15, #0"
  322. "\n mov x16, #0"
  323. "\n mov x17, #0"
  324. "\n movi d0, #0"
  325. "\n movi d1, #0"
  326. "\n movi d2, #0"
  327. "\n movi d3, #0"
  328. "\n movi d4, #0"
  329. "\n movi d5, #0"
  330. "\n movi d6, #0"
  331. "\n movi d7, #0"
  332. "\n ret"
  333. );
  334. #elif __arm__
  335. asm("\n .text"
  336. "\n .globl _stomp"
  337. "\n .thumb_func _stomp"
  338. "\n _stomp:"
  339. "\n mov r0, #0"
  340. "\n mov r1, #0"
  341. "\n mov r2, #0"
  342. "\n mov r3, #0"
  343. "\n mov r9, #0"
  344. "\n mov r12, #0"
  345. "\n vmov.i32 q0, #0"
  346. "\n vmov.i32 q1, #0"
  347. "\n vmov.i32 q2, #0"
  348. "\n vmov.i32 q3, #0"
  349. "\n vmov.i32 q8, #0"
  350. "\n vmov.i32 q9, #0"
  351. "\n vmov.i32 q10, #0"
  352. "\n vmov.i32 q11, #0"
  353. "\n vmov.i32 q12, #0"
  354. "\n vmov.i32 q13, #0"
  355. "\n vmov.i32 q14, #0"
  356. "\n vmov.i32 q15, #0"
  357. "\n bx lr"
  358. );
  359. #else
  360. # error unknown architecture
  361. #endif
  362. @implementation Super
  363. -(struct stret)stret { return STRET_RESULT; }
  364. // The IMPL_ methods are not called directly. Instead the non IMPL_ name is
  365. // called. The resolver function installs the real method. This allows
  366. // the resolver function to stomp on registers to help test register
  367. // preservation in the uncached path.
  368. +(BOOL) resolveInstanceMethod:(SEL)sel
  369. {
  370. const char *name = sel_getName(sel);
  371. if (! strstr(name, "::::::::")) return false;
  372. testprintf("resolving %s\n", name);
  373. stomp();
  374. char *realName;
  375. asprintf(&realName, "IMPL_%s", name);
  376. SEL realSel = sel_registerName(realName);
  377. free(realName);
  378. IMP imp = class_getMethodImplementation(self, realSel);
  379. if (imp == &_objc_msgForward) return false;
  380. return class_addMethod(self, sel, imp, "");
  381. }
  382. -(id)IMPL_idret:
  383. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  384. {
  385. CHECK_ARGS(idret);
  386. state = 1;
  387. return ID_RESULT;
  388. }
  389. -(long long)IMPL_llret:
  390. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  391. {
  392. CHECK_ARGS(llret);
  393. state = 2;
  394. return LL_RESULT;
  395. }
  396. -(struct stret)IMPL_stret:
  397. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  398. {
  399. CHECK_ARGS(stret);
  400. state = 3;
  401. return STRET_RESULT;
  402. }
  403. -(double)IMPL_fpret:
  404. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  405. {
  406. CHECK_ARGS(fpret);
  407. state = 4;
  408. return FP_RESULT;
  409. }
  410. -(long double)IMPL_lfpret:
  411. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  412. {
  413. CHECK_ARGS(lfpret);
  414. state = 5;
  415. return LFP_RESULT;
  416. }
  417. -(vector_ulong2)IMPL_vecret:
  418. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  419. {
  420. CHECK_ARGS(vecret);
  421. state = 6;
  422. return VEC_RESULT;
  423. }
  424. -(id)idret_noarg
  425. {
  426. CHECK_ARGS_NOARG(idret);
  427. state = 11;
  428. return ID_RESULT;
  429. }
  430. -(long long)llret_noarg
  431. {
  432. CHECK_ARGS_NOARG(llret);
  433. state = 12;
  434. return LL_RESULT;
  435. }
  436. -(struct stret)stret_noarg
  437. {
  438. CHECK_ARGS_NOARG(stret);
  439. state = 13;
  440. return STRET_RESULT;
  441. }
  442. -(double)fpret_noarg
  443. {
  444. CHECK_ARGS_NOARG(fpret);
  445. state = 14;
  446. return FP_RESULT;
  447. }
  448. -(long double)lfpret_noarg
  449. {
  450. CHECK_ARGS_NOARG(lfpret);
  451. state = 15;
  452. return LFP_RESULT;
  453. }
  454. -(vector_ulong2)vecret_noarg
  455. {
  456. CHECK_ARGS_NOARG(vecret);
  457. state = 16;
  458. return VEC_RESULT;
  459. }
  460. -(struct stret)stret_nop
  461. {
  462. return STRET_RESULT;
  463. }
  464. #define STRET_IMP(n) \
  465. +(struct stret_##n)stret_##n##_zero \
  466. { \
  467. struct stret_##n ret; \
  468. bzero(&ret, sizeof(ret)); \
  469. return ret; \
  470. } \
  471. +(struct stret_##n)stret_##n##_nonzero \
  472. { \
  473. struct stret_##n ret; \
  474. memset(&ret, 0xff, sizeof(ret)); \
  475. return ret; \
  476. }
  477. STRET_IMP(i1)
  478. STRET_IMP(i2)
  479. STRET_IMP(i3)
  480. STRET_IMP(i4)
  481. STRET_IMP(i5)
  482. STRET_IMP(i6)
  483. STRET_IMP(i7)
  484. STRET_IMP(i8)
  485. STRET_IMP(i9)
  486. STRET_IMP(d1)
  487. STRET_IMP(d2)
  488. STRET_IMP(d3)
  489. STRET_IMP(d4)
  490. STRET_IMP(d5)
  491. STRET_IMP(d6)
  492. STRET_IMP(d7)
  493. STRET_IMP(d8)
  494. STRET_IMP(d9)
  495. +(id)idret:
  496. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  497. {
  498. fail("+idret called instead of -idret");
  499. CHECK_ARGS(idret);
  500. }
  501. +(long long)llret:
  502. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  503. {
  504. fail("+llret called instead of -llret");
  505. CHECK_ARGS(llret);
  506. }
  507. +(struct stret)stret:
  508. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  509. {
  510. fail("+stret called instead of -stret");
  511. CHECK_ARGS(stret);
  512. }
  513. +(double)fpret:
  514. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  515. {
  516. fail("+fpret called instead of -fpret");
  517. CHECK_ARGS(fpret);
  518. }
  519. +(long double)lfpret:
  520. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  521. {
  522. fail("+lfpret called instead of -lfpret");
  523. CHECK_ARGS(lfpret);
  524. }
  525. +(id)idret_noarg
  526. {
  527. fail("+idret_noarg called instead of -idret_noarg");
  528. CHECK_ARGS_NOARG(idret);
  529. }
  530. +(long long)llret_noarg
  531. {
  532. fail("+llret_noarg called instead of -llret_noarg");
  533. CHECK_ARGS_NOARG(llret);
  534. }
  535. +(struct stret)stret_noarg
  536. {
  537. fail("+stret_noarg called instead of -stret_noarg");
  538. CHECK_ARGS_NOARG(stret);
  539. }
  540. +(double)fpret_noarg
  541. {
  542. fail("+fpret_noarg called instead of -fpret_noarg");
  543. CHECK_ARGS_NOARG(fpret);
  544. }
  545. +(long double)lfpret_noarg
  546. {
  547. fail("+lfpret_noarg called instead of -lfpret_noarg");
  548. CHECK_ARGS_NOARG(lfpret);
  549. }
  550. +(vector_ulong2)vecret_noarg
  551. {
  552. fail("+vecret_noarg called instead of -vecret_noarg");
  553. CHECK_ARGS_NOARG(vecret);
  554. }
  555. @end
  556. @implementation Sub
  557. -(id)IMPL_idret:
  558. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  559. {
  560. id result;
  561. CHECK_ARGS(idret);
  562. state = 100;
  563. result = [super idret:v1:v2:v3:v4:v5:v6:v7:v8:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
  564. testassert(state == 1);
  565. testassert(result == ID_RESULT);
  566. state = 101;
  567. return result;
  568. }
  569. -(long long)IMPL_llret:
  570. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  571. {
  572. long long result;
  573. CHECK_ARGS(llret);
  574. state = 100;
  575. result = [super llret:v1:v2:v3:v4:v5:v6:v7:v8:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
  576. testassert(state == 2);
  577. testassert(result == LL_RESULT);
  578. state = 102;
  579. return result;
  580. }
  581. -(struct stret)IMPL_stret:
  582. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  583. {
  584. struct stret result;
  585. CHECK_ARGS(stret);
  586. state = 100;
  587. result = [super stret:v1:v2:v3:v4:v5:v6:v7:v8:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
  588. testassert(state == 3);
  589. testassert(stret_equal(result, STRET_RESULT));
  590. state = 103;
  591. return result;
  592. }
  593. -(double)IMPL_fpret:
  594. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  595. {
  596. double result;
  597. CHECK_ARGS(fpret);
  598. state = 100;
  599. result = [super fpret:v1:v2:v3:v4:v5:v6:v7:v8:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
  600. testassert(state == 4);
  601. testassert(result == FP_RESULT);
  602. state = 104;
  603. return result;
  604. }
  605. -(long double)IMPL_lfpret:
  606. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  607. {
  608. long double result;
  609. CHECK_ARGS(lfpret);
  610. state = 100;
  611. result = [super lfpret:v1:v2:v3:v4:v5:v6:v7:v8:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
  612. testassert(state == 5);
  613. testassert(result == LFP_RESULT);
  614. state = 105;
  615. return result;
  616. }
  617. -(vector_ulong2)IMPL_vecret:
  618. (vector_ulong2)v1 :(vector_ulong2)v2 :(vector_ulong2)v3 :(vector_ulong2)v4 :(vector_ulong2)v5 :(vector_ulong2)v6 :(vector_ulong2)v7 :(vector_ulong2)v8 :(int)i1 :(int)i2 :(int)i3 :(int)i4 :(int)i5 :(int)i6 :(int)i7 :(int)i8 :(int)i9 :(int)i10 :(int)i11 :(int)i12 :(int)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
  619. {
  620. vector_ulong2 result;
  621. CHECK_ARGS(vecret);
  622. state = 100;
  623. result = [super vecret:v1:v2:v3:v4:v5:v6:v7:v8:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
  624. testassert(state == 6);
  625. testassert(vector_equal(result, VEC_RESULT));
  626. state = 106;
  627. return result;
  628. }
  629. -(id)idret_noarg
  630. {
  631. id result;
  632. CHECK_ARGS_NOARG(idret);
  633. state = 100;
  634. result = [super idret_noarg];
  635. testassert(state == 11);
  636. testassert(result == ID_RESULT);
  637. state = 111;
  638. return result;
  639. }
  640. -(long long)llret_noarg
  641. {
  642. long long result;
  643. CHECK_ARGS_NOARG(llret);
  644. state = 100;
  645. result = [super llret_noarg];
  646. testassert(state == 12);
  647. testassert(result == LL_RESULT);
  648. state = 112;
  649. return result;
  650. }
  651. -(struct stret)stret_noarg
  652. {
  653. struct stret result;
  654. CHECK_ARGS_NOARG(stret);
  655. state = 100;
  656. result = [super stret_noarg];
  657. testassert(state == 13);
  658. testassert(stret_equal(result, STRET_RESULT));
  659. state = 113;
  660. return result;
  661. }
  662. -(double)fpret_noarg
  663. {
  664. double result;
  665. CHECK_ARGS_NOARG(fpret);
  666. state = 100;
  667. result = [super fpret_noarg];
  668. testassert(state == 14);
  669. testassert(result == FP_RESULT);
  670. state = 114;
  671. return result;
  672. }
  673. -(long double)lfpret_noarg
  674. {
  675. long double result;
  676. CHECK_ARGS_NOARG(lfpret);
  677. state = 100;
  678. result = [super lfpret_noarg];
  679. testassert(state == 15);
  680. testassert(result == LFP_RESULT);
  681. state = 115;
  682. return result;
  683. }
  684. -(vector_ulong2)vecret_noarg
  685. {
  686. vector_ulong2 result;
  687. CHECK_ARGS_NOARG(vecret);
  688. state = 100;
  689. result = [super vecret_noarg];
  690. testassert(state == 16);
  691. testassert(vector_equal(result, VEC_RESULT));
  692. state = 116;
  693. return result;
  694. }
  695. @end
  696. #if OBJC_HAVE_TAGGED_POINTERS
  697. @interface TaggedSub : Sub @end
  698. @implementation TaggedSub : Sub
  699. +(void)initialize
  700. {
  701. _objc_registerTaggedPointerClass(OBJC_TAG_1, self);
  702. }
  703. @end
  704. @interface ExtTaggedSub : Sub @end
  705. @implementation ExtTaggedSub : Sub
  706. +(void)initialize
  707. {
  708. _objc_registerTaggedPointerClass(OBJC_TAG_First52BitPayload, self);
  709. }
  710. @end
  711. #endif
  712. // DWARF checking machinery
  713. #if TARGET_OS_WIN32
  714. // unimplemented on this platform
  715. #define NO_DWARF_REASON "(windows)"
  716. #elif TARGET_OS_WATCH
  717. // fixme unimplemented - ucontext not passed to signal handlers
  718. #define NO_DWARF_REASON "(watchOS)"
  719. #elif __has_feature(objc_arc)
  720. // ARC's extra RR calls hit the traps at the wrong times
  721. #define NO_DWARF_REASON "(ARC)"
  722. #else
  723. #define TEST_DWARF 1
  724. // Classes with no implementations and no cache contents from elsewhere.
  725. @interface SuperDW : TestRoot @end
  726. @implementation SuperDW @end
  727. @interface Sub0DW : SuperDW @end
  728. @implementation Sub0DW @end
  729. @interface SubDW : Sub0DW @end
  730. @implementation SubDW @end
  731. #include <dlfcn.h>
  732. #include <signal.h>
  733. #include <sys/mman.h>
  734. #include <libunwind.h>
  735. bool caught = false;
  736. uintptr_t clobbered;
  737. __BEGIN_DECLS
  738. extern void callit(void *obj, void *sel, void *fn);
  739. extern struct stret callit_stret(void *obj, void *sel, void *fn);
  740. __END_DECLS
  741. #if __x86_64__
  742. typedef uint8_t insn_t;
  743. typedef insn_t clobbered_insn_t;
  744. #define BREAK_INSN ((insn_t)0x06) // undefined
  745. #define BREAK_SIGNAL SIGILL
  746. uintptr_t r12 = 0;
  747. uintptr_t r13 = 0;
  748. uintptr_t r14 = 0;
  749. uintptr_t r15 = 0;
  750. uintptr_t rbx = 0;
  751. uintptr_t rbp = 0;
  752. uintptr_t rsp = 0;
  753. uintptr_t rip = 0;
  754. void handle_exception(x86_thread_state64_t *state)
  755. {
  756. unw_cursor_t curs;
  757. unw_word_t reg;
  758. int err;
  759. int step;
  760. err = unw_init_local(&curs, (unw_context_t *)state);
  761. testassert(!err);
  762. step = unw_step(&curs);
  763. testassert(step > 0);
  764. err = unw_get_reg(&curs, UNW_X86_64_R12, &reg);
  765. testassert(!err);
  766. testassert(reg == r12);
  767. err = unw_get_reg(&curs, UNW_X86_64_R13, &reg);
  768. testassert(!err);
  769. testassert(reg == r13);
  770. err = unw_get_reg(&curs, UNW_X86_64_R14, &reg);
  771. testassert(!err);
  772. testassert(reg == r14);
  773. err = unw_get_reg(&curs, UNW_X86_64_R15, &reg);
  774. testassert(!err);
  775. testassert(reg == r15);
  776. err = unw_get_reg(&curs, UNW_X86_64_RBX, &reg);
  777. testassert(!err);
  778. testassert(reg == rbx);
  779. err = unw_get_reg(&curs, UNW_X86_64_RBP, &reg);
  780. testassert(!err);
  781. testassert(reg == rbp);
  782. err = unw_get_reg(&curs, UNW_X86_64_RSP, &reg);
  783. testassert(!err);
  784. testassert(reg == rsp);
  785. err = unw_get_reg(&curs, UNW_REG_IP, &reg);
  786. testassert(!err);
  787. testassert(reg == rip);
  788. // set thread state to unwound state
  789. state->__r12 = r12;
  790. state->__r13 = r13;
  791. state->__r14 = r14;
  792. state->__r15 = r15;
  793. state->__rbx = rbx;
  794. state->__rbp = rbp;
  795. state->__rsp = rsp;
  796. state->__rip = rip;
  797. caught = true;
  798. }
  799. void break_handler(int sig, siginfo_t *info, void *cc)
  800. {
  801. ucontext_t *uc = (ucontext_t *)cc;
  802. mcontext_t mc = (mcontext_t)uc->uc_mcontext;
  803. testprintf(" handled\n");
  804. testassert(sig == BREAK_SIGNAL);
  805. testassert((uintptr_t)info->si_addr == clobbered);
  806. handle_exception(&mc->__ss);
  807. // handle_exception changed register state for continuation
  808. }
  809. __asm__(
  810. "\n .text"
  811. "\n .globl _callit"
  812. "\n _callit:"
  813. // save sp and return address to variables
  814. "\n movq (%rsp), %r10"
  815. "\n movq %r10, _rip(%rip)"
  816. "\n movq %rsp, _rsp(%rip)"
  817. "\n addq $8, _rsp(%rip)" // rewind to pre-call value
  818. // save other non-volatile registers to variables
  819. "\n movq %rbx, _rbx(%rip)"
  820. "\n movq %rbp, _rbp(%rip)"
  821. "\n movq %r12, _r12(%rip)"
  822. "\n movq %r13, _r13(%rip)"
  823. "\n movq %r14, _r14(%rip)"
  824. "\n movq %r15, _r15(%rip)"
  825. "\n jmpq *%rdx"
  826. );
  827. __asm__(
  828. "\n .text"
  829. "\n .globl _callit_stret"
  830. "\n _callit_stret:"
  831. // save sp and return address to variables
  832. "\n movq (%rsp), %r10"
  833. "\n movq %r10, _rip(%rip)"
  834. "\n movq %rsp, _rsp(%rip)"
  835. "\n addq $8, _rsp(%rip)" // rewind to pre-call value
  836. // save other non-volatile registers to variables
  837. "\n movq %rbx, _rbx(%rip)"
  838. "\n movq %rbp, _rbp(%rip)"
  839. "\n movq %r12, _r12(%rip)"
  840. "\n movq %r13, _r13(%rip)"
  841. "\n movq %r14, _r14(%rip)"
  842. "\n movq %r15, _r15(%rip)"
  843. "\n jmpq *%rcx"
  844. );
  845. // x86_64
  846. #elif __i386__
  847. typedef uint8_t insn_t;
  848. typedef insn_t clobbered_insn_t;
  849. #define BREAK_INSN ((insn_t)0xcc) // int3
  850. #define BREAK_SIGNAL SIGTRAP
  851. uintptr_t eip = 0;
  852. uintptr_t esp = 0;
  853. uintptr_t ebx = 0;
  854. uintptr_t ebp = 0;
  855. uintptr_t edi = 0;
  856. uintptr_t esi = 0;
  857. uintptr_t espfix = 0;
  858. void handle_exception(i386_thread_state_t *state)
  859. {
  860. unw_cursor_t curs;
  861. unw_word_t reg;
  862. int err;
  863. int step;
  864. err = unw_init_local(&curs, (unw_context_t *)state);
  865. testassert(!err);
  866. step = unw_step(&curs);
  867. testassert(step > 0);
  868. err = unw_get_reg(&curs, UNW_REG_IP, &reg);
  869. testassert(!err);
  870. testassert(reg == eip);
  871. err = unw_get_reg(&curs, UNW_X86_ESP, &reg);
  872. testassert(!err);
  873. testassert(reg == esp);
  874. err = unw_get_reg(&curs, UNW_X86_EBX, &reg);
  875. testassert(!err);
  876. testassert(reg == ebx);
  877. err = unw_get_reg(&curs, UNW_X86_EBP, &reg);
  878. testassert(!err);
  879. testassert(reg == ebp);
  880. err = unw_get_reg(&curs, UNW_X86_EDI, &reg);
  881. testassert(!err);
  882. testassert(reg == edi);
  883. err = unw_get_reg(&curs, UNW_X86_ESI, &reg);
  884. testassert(!err);
  885. testassert(reg == esi);
  886. // set thread state to unwound state
  887. state->__eip = eip;
  888. state->__esp = esp + espfix;
  889. state->__ebx = ebx;
  890. state->__ebp = ebp;
  891. state->__edi = edi;
  892. state->__esi = esi;
  893. caught = true;
  894. }
  895. void break_handler(int sig, siginfo_t *info, void *cc)
  896. {
  897. ucontext_t *uc = (ucontext_t *)cc;
  898. mcontext_t mc = (mcontext_t)uc->uc_mcontext;
  899. testprintf(" handled\n");
  900. testassert(sig == BREAK_SIGNAL);
  901. testassert((uintptr_t)info->si_addr-1 == clobbered);
  902. handle_exception(&mc->__ss);
  903. // handle_exception changed register state for continuation
  904. }
  905. __asm__(
  906. "\n .text"
  907. "\n .globl _callit"
  908. "\n _callit:"
  909. // save sp and return address to variables
  910. "\n call 1f"
  911. "\n 1: popl %edx"
  912. "\n movl (%esp), %eax"
  913. "\n movl %eax, _eip-1b(%edx)"
  914. "\n movl %esp, _esp-1b(%edx)"
  915. "\n addl $4, _esp-1b(%edx)" // rewind to pre-call value
  916. "\n movl $0, _espfix-1b(%edx)"
  917. // save other non-volatile registers to variables
  918. "\n movl %ebx, _ebx-1b(%edx)"
  919. "\n movl %ebp, _ebp-1b(%edx)"
  920. "\n movl %edi, _edi-1b(%edx)"
  921. "\n movl %esi, _esi-1b(%edx)"
  922. "\n jmpl *12(%esp)"
  923. );
  924. __asm__(
  925. "\n .text"
  926. "\n .globl _callit_stret"
  927. "\n _callit_stret:"
  928. // save sp and return address to variables
  929. "\n call 1f"
  930. "\n 1: popl %edx"
  931. "\n movl (%esp), %eax"
  932. "\n movl %eax, _eip-1b(%edx)"
  933. "\n movl %esp, _esp-1b(%edx)"
  934. "\n addl $4, _esp-1b(%edx)" // rewind to pre-call value
  935. "\n movl $4, _espfix-1b(%edx)"
  936. // save other non-volatile registers to variables
  937. "\n movl %ebx, _ebx-1b(%edx)"
  938. "\n movl %ebp, _ebp-1b(%edx)"
  939. "\n movl %edi, _edi-1b(%edx)"
  940. "\n movl %esi, _esi-1b(%edx)"
  941. "\n jmpl *16(%esp)"
  942. );
  943. // i386
  944. #elif __arm64__
  945. #include <sys/ucontext.h>
  946. typedef uint32_t insn_t;
  947. typedef insn_t clobbered_insn_t;
  948. #define BREAK_INSN ((insn_t)0xd4200020) // brk #1
  949. #define BREAK_SIGNAL SIGTRAP
  950. uintptr_t x19 = 0;
  951. uintptr_t x20 = 0;
  952. uintptr_t x21 = 0;
  953. uintptr_t x22 = 0;
  954. uintptr_t x23 = 0;
  955. uintptr_t x24 = 0;
  956. uintptr_t x25 = 0;
  957. uintptr_t x26 = 0;
  958. uintptr_t x27 = 0;
  959. uintptr_t x28 = 0;
  960. uintptr_t fp = 0;
  961. uintptr_t sp = 0;
  962. uintptr_t pc = 0;
  963. void handle_exception(arm_thread_state64_t *state)
  964. {
  965. unw_cursor_t curs;
  966. unw_word_t reg;
  967. int err;
  968. int step;
  969. // libunwind layout differs from mcontext layout
  970. // GPRs are the same but vector registers are not
  971. unw_context_t unwstate;
  972. unw_getcontext(&unwstate);
  973. memcpy(&unwstate, state, sizeof(*state));
  974. // libunwind and xnu sign some pointers differently
  975. // xnu: not signed (fixme this may change?)
  976. // libunwind: PC and LR both signed with return address key and SP
  977. void **pcp = &((arm_thread_state64_t *)&unwstate)->__opaque_pc;
  978. *pcp = ptrauth_sign_unauthenticated((void*)__darwin_arm_thread_state64_get_pc(*state),
  979. ptrauth_key_return_address,
  980. (ptrauth_extra_data_t)__darwin_arm_thread_state64_get_sp(*state));
  981. void **lrp = &((arm_thread_state64_t *)&unwstate)->__opaque_lr;
  982. *lrp = ptrauth_sign_unauthenticated((void*)__darwin_arm_thread_state64_get_lr(*state),
  983. ptrauth_key_return_address,
  984. (ptrauth_extra_data_t)__darwin_arm_thread_state64_get_sp(*state));
  985. err = unw_init_local(&curs, &unwstate);
  986. testassert(!err);
  987. step = unw_step(&curs);
  988. testassert(step > 0);
  989. err = unw_get_reg(&curs, UNW_ARM64_X19, &reg);
  990. testassert(!err);
  991. testassert(reg == x19);
  992. err = unw_get_reg(&curs, UNW_ARM64_X20, &reg);
  993. testassert(!err);
  994. testassert(reg == x20);
  995. err = unw_get_reg(&curs, UNW_ARM64_X21, &reg);
  996. testassert(!err);
  997. testassert(reg == x21);
  998. err = unw_get_reg(&curs, UNW_ARM64_X22, &reg);
  999. testassert(!err);
  1000. testassert(reg == x22);
  1001. err = unw_get_reg(&curs, UNW_ARM64_X23, &reg);
  1002. testassert(!err);
  1003. testassert(reg == x23);
  1004. err = unw_get_reg(&curs, UNW_ARM64_X24, &reg);
  1005. testassert(!err);
  1006. testassert(reg == x24);
  1007. err = unw_get_reg(&curs, UNW_ARM64_X25, &reg);
  1008. testassert(!err);
  1009. testassert(reg == x25);
  1010. err = unw_get_reg(&curs, UNW_ARM64_X26, &reg);
  1011. testassert(!err);
  1012. testassert(reg == x26);
  1013. err = unw_get_reg(&curs, UNW_ARM64_X27, &reg);
  1014. testassert(!err);
  1015. testassert(reg == x27);
  1016. err = unw_get_reg(&curs, UNW_ARM64_X28, &reg);
  1017. testassert(!err);
  1018. testassert(reg == x28);
  1019. err = unw_get_reg(&curs, UNW_ARM64_FP, &reg);
  1020. testassert(!err);
  1021. testassert(reg == fp);
  1022. err = unw_get_reg(&curs, UNW_ARM64_SP, &reg);
  1023. testassert(!err);
  1024. testassert(reg == sp);
  1025. err = unw_get_reg(&curs, UNW_REG_IP, &reg);
  1026. testassert(!err);
  1027. // libunwind's return is signed but our value is not
  1028. reg = (uintptr_t)ptrauth_strip((void *)reg, ptrauth_key_return_address);
  1029. testassert(reg == pc);
  1030. // libunwind restores PC into LR and doesn't track LR
  1031. // err = unw_get_reg(&curs, UNW_ARM64_LR, &reg);
  1032. // testassert(!err);
  1033. // testassert(reg == lr);
  1034. // set signal handler's thread state to unwound state
  1035. state->__x[19] = x19;
  1036. state->__x[20] = x20;
  1037. state->__x[21] = x21;
  1038. state->__x[22] = x22;
  1039. state->__x[23] = x23;
  1040. state->__x[24] = x24;
  1041. state->__x[25] = x25;
  1042. state->__x[26] = x26;
  1043. state->__x[27] = x27;
  1044. state->__x[28] = x28;
  1045. state->__opaque_fp = (void *)fp;
  1046. state->__opaque_lr = (void *)pc; // libunwind restores PC into LR
  1047. state->__opaque_sp = (void *)sp;
  1048. state->__opaque_pc = (void *)pc;
  1049. caught = true;
  1050. }
  1051. void break_handler(int sig, siginfo_t *info, void *cc)
  1052. {
  1053. ucontext_t *uc = (ucontext_t *)cc;
  1054. struct __darwin_mcontext64 *mc = (struct __darwin_mcontext64 *)uc->uc_mcontext;
  1055. testprintf(" handled\n");
  1056. testassert(sig == BREAK_SIGNAL);
  1057. testassert((uintptr_t)info->si_addr == clobbered);
  1058. handle_exception(&mc->__ss);
  1059. // handle_exception changed register state for continuation
  1060. }
  1061. __asm__(
  1062. "\n .text"
  1063. "\n .globl _callit"
  1064. "\n _callit:"
  1065. // save sp and return address to variables
  1066. "\n mov x16, sp"
  1067. "\n adrp x17, _sp@PAGE"
  1068. "\n str x16, [x17, _sp@PAGEOFF]"
  1069. "\n adrp x17, _pc@PAGE"
  1070. "\n str lr, [x17, _pc@PAGEOFF]"
  1071. // save other non-volatile registers to variables
  1072. "\n adrp x17, _x19@PAGE"
  1073. "\n str x19, [x17, _x19@PAGEOFF]"
  1074. "\n adrp x17, _x19@PAGE"
  1075. "\n str x20, [x17, _x20@PAGEOFF]"
  1076. "\n adrp x17, _x19@PAGE"
  1077. "\n str x21, [x17, _x21@PAGEOFF]"
  1078. "\n adrp x17, _x19@PAGE"
  1079. "\n str x22, [x17, _x22@PAGEOFF]"
  1080. "\n adrp x17, _x19@PAGE"
  1081. "\n str x23, [x17, _x23@PAGEOFF]"
  1082. "\n adrp x17, _x19@PAGE"
  1083. "\n str x24, [x17, _x24@PAGEOFF]"
  1084. "\n adrp x17, _x19@PAGE"
  1085. "\n str x25, [x17, _x25@PAGEOFF]"
  1086. "\n adrp x17, _x19@PAGE"
  1087. "\n str x26, [x17, _x26@PAGEOFF]"
  1088. "\n adrp x17, _x19@PAGE"
  1089. "\n str x27, [x17, _x27@PAGEOFF]"
  1090. "\n adrp x17, _x19@PAGE"
  1091. "\n str x28, [x17, _x28@PAGEOFF]"
  1092. "\n adrp x17, _x19@PAGE"
  1093. "\n str fp, [x17, _fp@PAGEOFF]"
  1094. "\n br x2"
  1095. );
  1096. // arm64
  1097. #elif __arm__
  1098. #include <sys/ucontext.h>
  1099. typedef uint16_t insn_t;
  1100. typedef struct {
  1101. insn_t first;
  1102. insn_t second;
  1103. bool thirty_two;
  1104. } clobbered_insn_t;
  1105. #define BREAK_INSN ((insn_t)0xdefe) // trap
  1106. #define BREAK_SIGNAL SIGILL
  1107. #define BREAK_SIGNAL2 SIGTRAP
  1108. uintptr_t r4 = 0;
  1109. uintptr_t r5 = 0;
  1110. uintptr_t r6 = 0;
  1111. uintptr_t r7 = 0;
  1112. uintptr_t r8 = 0;
  1113. uintptr_t r10 = 0;
  1114. uintptr_t r11 = 0;
  1115. uintptr_t sp = 0;
  1116. uintptr_t pc = 0;
  1117. void handle_exception(arm_thread_state_t *state)
  1118. {
  1119. // No unwind tables on this architecture so no libunwind checks.
  1120. // We run the test anyway to verify instruction-level coverage.
  1121. // set thread state to unwound state
  1122. state->__r[4] = r4;
  1123. state->__r[5] = r5;
  1124. state->__r[6] = r6;
  1125. state->__r[7] = r7;
  1126. state->__r[8] = r8;
  1127. state->__r[10] = r10;
  1128. state->__r[11] = r11;
  1129. state->__sp = sp;
  1130. state->__pc = pc;
  1131. // clear IT... bits so caller doesn't act on them
  1132. state->__cpsr &= ~0x0600fc00;
  1133. caught = true;
  1134. }
  1135. void break_handler(int sig, siginfo_t *info, void *cc)
  1136. {
  1137. ucontext_t *uc = (ucontext_t *)cc;
  1138. struct __darwin_mcontext32 *mc = (struct __darwin_mcontext32 *)uc->uc_mcontext;
  1139. testprintf(" handled\n");
  1140. testassert(sig == BREAK_SIGNAL || sig == BREAK_SIGNAL2);
  1141. testassert((uintptr_t)info->si_addr == clobbered);
  1142. handle_exception(&mc->__ss);
  1143. // handle_exception changed register state for continuation
  1144. }
  1145. __asm__(
  1146. "\n .text"
  1147. "\n .syntax unified"
  1148. "\n .code 16"
  1149. "\n .align 5"
  1150. "\n .globl _callit"
  1151. "\n .thumb_func"
  1152. "\n _callit:"
  1153. // save sp and return address to variables
  1154. "\n movw r12, :lower16:(_sp-1f-4)"
  1155. "\n movt r12, :upper16:(_sp-1f-4)"
  1156. "\n 1: add r12, pc"
  1157. "\n str sp, [r12]"
  1158. "\n movw r12, :lower16:(_pc-1f-4)"
  1159. "\n movt r12, :upper16:(_pc-1f-4)"
  1160. "\n 1: add r12, pc"
  1161. "\n str lr, [r12]"
  1162. // save other non-volatile registers to variables
  1163. "\n movw r12, :lower16:(_r4-1f-4)"
  1164. "\n movt r12, :upper16:(_r4-1f-4)"
  1165. "\n 1: add r12, pc"
  1166. "\n str r4, [r12]"
  1167. "\n movw r12, :lower16:(_r5-1f-4)"
  1168. "\n movt r12, :upper16:(_r5-1f-4)"
  1169. "\n 1: add r12, pc"
  1170. "\n str r5, [r12]"
  1171. "\n movw r12, :lower16:(_r6-1f-4)"
  1172. "\n movt r12, :upper16:(_r6-1f-4)"
  1173. "\n 1: add r12, pc"
  1174. "\n str r6, [r12]"
  1175. "\n movw r12, :lower16:(_r7-1f-4)"
  1176. "\n movt r12, :upper16:(_r7-1f-4)"
  1177. "\n 1: add r12, pc"
  1178. "\n str r7, [r12]"
  1179. "\n movw r12, :lower16:(_r8-1f-4)"
  1180. "\n movt r12, :upper16:(_r8-1f-4)"
  1181. "\n 1: add r12, pc"
  1182. "\n str r8, [r12]"
  1183. "\n movw r12, :lower16:(_r10-1f-4)"
  1184. "\n movt r12, :upper16:(_r10-1f-4)"
  1185. "\n 1: add r12, pc"
  1186. "\n str r10, [r12]"
  1187. "\n movw r12, :lower16:(_r11-1f-4)"
  1188. "\n movt r12, :upper16:(_r11-1f-4)"
  1189. "\n 1: add r12, pc"
  1190. "\n str r11, [r12]"
  1191. "\n bx r2"
  1192. );
  1193. __asm__(
  1194. "\n .text"
  1195. "\n .syntax unified"
  1196. "\n .code 16"
  1197. "\n .align 5"
  1198. "\n .globl _callit_stret"
  1199. "\n .thumb_func"
  1200. "\n _callit_stret:"
  1201. // save sp and return address to variables
  1202. "\n movw r12, :lower16:(_sp-1f-4)"
  1203. "\n movt r12, :upper16:(_sp-1f-4)"
  1204. "\n 1: add r12, pc"
  1205. "\n str sp, [r12]"
  1206. "\n movw r12, :lower16:(_pc-1f-4)"
  1207. "\n movt r12, :upper16:(_pc-1f-4)"
  1208. "\n 1: add r12, pc"
  1209. "\n str lr, [r12]"
  1210. // save other non-volatile registers to variables
  1211. "\n movw r12, :lower16:(_r4-1f-4)"
  1212. "\n movt r12, :upper16:(_r4-1f-4)"
  1213. "\n 1: add r12, pc"
  1214. "\n str r4, [r12]"
  1215. "\n movw r12, :lower16:(_r5-1f-4)"
  1216. "\n movt r12, :upper16:(_r5-1f-4)"
  1217. "\n 1: add r12, pc"
  1218. "\n str r5, [r12]"
  1219. "\n movw r12, :lower16:(_r6-1f-4)"
  1220. "\n movt r12, :upper16:(_r6-1f-4)"
  1221. "\n 1: add r12, pc"
  1222. "\n str r6, [r12]"
  1223. "\n movw r12, :lower16:(_r7-1f-4)"
  1224. "\n movt r12, :upper16:(_r7-1f-4)"
  1225. "\n 1: add r12, pc"
  1226. "\n str r7, [r12]"
  1227. "\n movw r12, :lower16:(_r8-1f-4)"
  1228. "\n movt r12, :upper16:(_r8-1f-4)"
  1229. "\n 1: add r12, pc"
  1230. "\n str r8, [r12]"
  1231. "\n movw r12, :lower16:(_r10-1f-4)"
  1232. "\n movt r12, :upper16:(_r10-1f-4)"
  1233. "\n 1: add r12, pc"
  1234. "\n str r10, [r12]"
  1235. "\n movw r12, :lower16:(_r11-1f-4)"
  1236. "\n movt r12, :upper16:(_r11-1f-4)"
  1237. "\n 1: add r12, pc"
  1238. "\n str r11, [r12]"
  1239. "\n bx r3"
  1240. );
  1241. // arm
  1242. #else
  1243. #error unknown architecture
  1244. #endif
  1245. #if __arm__
  1246. uintptr_t fnaddr(void *fn) { return (uintptr_t)fn & ~(uintptr_t)1; }
  1247. #else
  1248. uintptr_t fnaddr(void *fn) { return (uintptr_t)fn; }
  1249. #endif
  1250. void flushICache(uintptr_t addr) {
  1251. sys_icache_invalidate((void *)addr, sizeof(insn_t));
  1252. }
  1253. insn_t set(uintptr_t dst, insn_t newvalue)
  1254. {
  1255. uintptr_t start = dst & ~(PAGE_MAX_SIZE-1);
  1256. int err = mprotect((void*)start, PAGE_MAX_SIZE, PROT_READ|PROT_WRITE);
  1257. if (err) fail("mprotect(%p, RW-) failed (%d)", start, errno);
  1258. insn_t oldvalue = *(insn_t *)dst;
  1259. *(insn_t *)dst = newvalue;
  1260. err = mprotect((void*)start, PAGE_MAX_SIZE, PROT_READ|PROT_EXEC);
  1261. if (err) fail("mprotect(%p, R-X) failed (%d)", start, errno);
  1262. flushICache(dst);
  1263. return oldvalue;
  1264. }
  1265. clobbered_insn_t clobber(void *fn, uintptr_t offset)
  1266. {
  1267. clobbered = fnaddr(fn) + offset;
  1268. insn_t oldInsn = set(fnaddr(fn) + offset, BREAK_INSN);
  1269. #if __arm__
  1270. // Need to clobber 32-bit Thumb instructions with another 32-bit instruction
  1271. // to preserve the behavior of IT... blocks.
  1272. clobbered_insn_t result = {oldInsn, 0, false};
  1273. if (((oldInsn & 0xf000) == 0xf000) ||
  1274. ((oldInsn & 0xf800) == 0xe800))
  1275. {
  1276. testprintf("clobbering thumb-32 at offset %zu\n", offset);
  1277. // Old insn was 32-bit. Clobber all of it.
  1278. // First unclobber.
  1279. set(fnaddr(fn) + offset, oldInsn);
  1280. // f7f0 a0f0 is a "permanently undefined" Thumb-2 instruction.
  1281. // Clobber the first half last so `clobbered` gets the right value.
  1282. result.second = set(fnaddr(fn) + offset + 2, 0xa0f0);
  1283. result.first = set(fnaddr(fn) + offset, 0xf7f0);
  1284. result.thirty_two = true;
  1285. }
  1286. return result;
  1287. #else
  1288. return oldInsn;
  1289. #endif
  1290. }
  1291. void unclobber(void *fn, uintptr_t offset, clobbered_insn_t oldvalue)
  1292. {
  1293. #if __arm__
  1294. if (oldvalue.thirty_two) {
  1295. set(fnaddr(fn) + offset + 2, oldvalue.second);
  1296. }
  1297. set(fnaddr(fn) + offset, oldvalue.first);
  1298. #else
  1299. set(fnaddr(fn) + offset, oldvalue);
  1300. #endif
  1301. }
  1302. // terminator for the list of instruction offsets
  1303. #define END_OFFSETS ~0UL
  1304. // Disassemble instructions symbol..<symbolEnd.
  1305. // Write the offset of each non-NOP instruction start to *offsets..<end.
  1306. // Return the incremented offsets pointer.
  1307. uintptr_t *disassemble(uintptr_t symbol, uintptr_t symbolEnd,
  1308. uintptr_t *offsets, uintptr_t *end)
  1309. {
  1310. // To disassemble:
  1311. // 1. Copy asm-placeholder.exe into a temporary file.
  1312. // 2. Write the instructions into the temp file.
  1313. // 3. Run llvm-objdump on the temp file.
  1314. // 4. Parse the llvm-objdump output.
  1315. // copy asm-placeholder.exe into a new temporary file and open it.
  1316. int placeholder = open("asm-placeholder.exe", O_RDONLY);
  1317. if (placeholder < 0) {
  1318. fail("couldn't open asm-placeholder.exe (%d)", errno);
  1319. }
  1320. size_t tempdirlen = confstr(_CS_DARWIN_USER_TEMP_DIR, nil, 0);
  1321. char tempsuffix[] = "objc-test-msgSend-asm-XXXXXX";
  1322. char *tempname = (char *)malloc(tempdirlen + strlen(tempsuffix));
  1323. confstr(_CS_DARWIN_USER_TEMP_DIR, tempname, tempdirlen);
  1324. strcat(tempname, tempsuffix);
  1325. int fd = mkstemp(tempname);
  1326. if (fd < 0) {
  1327. fail("couldn't create asm temp file %s (%d)", tempname, errno);
  1328. }
  1329. struct stat st;
  1330. if (fstat(placeholder, &st) < 0) {
  1331. fail("couldn't stat asm-placeholder.exe (%d)", errno);
  1332. }
  1333. ssize_t sz = (ssize_t)st.st_size;
  1334. char *buf = (char *)malloc(sz);
  1335. if (pread(placeholder, buf, sz, 0) != sz) {
  1336. fail("couldn't read asm-placeholder.exe (%d)", errno);
  1337. }
  1338. if (pwrite(fd, buf, sz, 0) != sz) {
  1339. fail("couldn't write asm temp file %s (%d)", tempname, errno);
  1340. }
  1341. free(buf);
  1342. close(placeholder);
  1343. // write code into asm-placeholder.exe
  1344. // asm-placeholder.exe may have as little as 1024 bytes of space reserved
  1345. testassert(symbolEnd - symbol < 1024);
  1346. // text section should be 16KB into asm-placeholder.exe
  1347. if (pwrite(fd, (void*)symbol, symbolEnd - symbol, 16384) < 0) {
  1348. fail("couldn't write code into asm temp file %s (%d)", tempname, errno);
  1349. }
  1350. close(fd);
  1351. // run `llvm-objdump -disassemble`
  1352. const char *objdump;
  1353. if (0 == access("/usr/local/bin/llvm-objdump", F_OK)) {
  1354. objdump = "/usr/local/bin/llvm-objdump";
  1355. } else if (0 == access("/usr/bin/llvm-objdump", F_OK)) {
  1356. objdump = "/usr/bin/llvm-objdump";
  1357. } else {
  1358. fail("couldn't find llvm-objdump");
  1359. }
  1360. char *cmd;
  1361. asprintf(&cmd, "%s -disassemble %s", objdump, tempname);
  1362. FILE *disa = popen(cmd, "r");
  1363. if (!disa) {
  1364. fail("couldn't popen %s", cmd);
  1365. }
  1366. free(cmd);
  1367. free(tempname);
  1368. // read past "_main:" line
  1369. char *line;
  1370. size_t len;
  1371. while ((line = fgetln(disa, &len))) {
  1372. testprintf("ASM: %.*s", (int)len, line);
  1373. if (0 == strncmp(line, "_main:", strlen("_main:"))) break;
  1374. }
  1375. // read instructions and save offsets
  1376. char op[128];
  1377. long base = 0;
  1378. long addr;
  1379. uintptr_t *p = offsets;
  1380. // disassembly format:
  1381. // ADDR:\t ...instruction bytes... \tOPCODE ...etc...\n
  1382. while (2 == fscanf(disa, "%lx:\t%*[a-fA-F0-9 ]\t%s%*[^\n]\n", &addr, op)) {
  1383. if (base == 0) base = addr;
  1384. testprintf("ASM: %lx (+%d) ... %s ...\n", addr, addr - base, op);
  1385. // allow longer nops like Intel nopw and nopl
  1386. if (0 != strncmp(op, "nop", 3)) {
  1387. testassert(offsets < end);
  1388. *p++ = addr - base;
  1389. } else {
  1390. // assume nops are unreached (e.g. alignment padding)
  1391. }
  1392. }
  1393. pclose(disa);
  1394. #if __x86_64__
  1395. // hack: skip last instruction because libunwind blows up if it's
  1396. // one byte long and followed by the next function with no NOPs first
  1397. if (p > offsets) *p-- = END_OFFSETS;
  1398. #endif
  1399. return p;
  1400. }
  1401. uintptr_t *getOffsets(const char *symname, uintptr_t *outBase)
  1402. {
  1403. // Find the start of our function.
  1404. uintptr_t symbol = (uintptr_t)dlsym(RTLD_NEXT, symname);
  1405. if (!symbol) return nil;
  1406. #if __has_feature(ptrauth_calls)
  1407. symbol = (uintptr_t)
  1408. ptrauth_strip((void*)symbol, ptrauth_key_function_pointer);
  1409. #endif
  1410. if (outBase) *outBase = symbol;
  1411. // Find the end of our function by finding the start
  1412. // of the next symbol after our target symbol.
  1413. const int insnIncrement =
  1414. #if __arm64__
  1415. 4;
  1416. #elif __arm__
  1417. 2; // in case of thumb or thumb-2
  1418. #elif __i386__ || __x86_64__
  1419. 1;
  1420. #else
  1421. #error unknown architecture
  1422. #endif
  1423. uintptr_t symbolEnd;
  1424. Dl_info dli;
  1425. int ok;
  1426. for (symbolEnd = symbol + insnIncrement;
  1427. ((ok = dladdr((void*)symbolEnd, &dli))) && dli.dli_saddr == (void*)symbol;
  1428. symbolEnd += insnIncrement)
  1429. ;
  1430. testprintf("found %s at %p..<%p %d %p %s\n",
  1431. symname, (void*)symbol, (void*)symbolEnd, ok, dli.dli_saddr, dli.dli_sname);
  1432. // Record the offset to each non-NOP instruction.
  1433. uintptr_t *result = (uintptr_t *)malloc(1000 * sizeof(uintptr_t));
  1434. uintptr_t *end = result + 1000;
  1435. uintptr_t *p = result;
  1436. p = disassemble(symbol, symbolEnd, p, end);
  1437. // Also record the offsets in _objc_msgSend_uncached when present
  1438. // (which is the slow path and has a frame to unwind)
  1439. if (!strstr(symname, "_uncached")) {
  1440. const char *uncached_symname = strstr(symname, "stret")
  1441. ? "_objc_msgSend_stret_uncached" : "_objc_msgSend_uncached";
  1442. uintptr_t uncached_symbol;
  1443. uintptr_t *uncached_offsets =
  1444. getOffsets(uncached_symname, &uncached_symbol);
  1445. if (uncached_offsets) {
  1446. uintptr_t *q = uncached_offsets;
  1447. // Skip prologue and epilogue of objc_msgSend_uncached
  1448. // because it's imprecisely modeled in compact unwind
  1449. int prologueInstructions, epilogueInstructions;
  1450. #if __arm64e__
  1451. prologueInstructions = 3;
  1452. epilogueInstructions = 2;
  1453. #elif __arm64__ || __x86_64__ || __i386__ || __arm__
  1454. prologueInstructions = 2;
  1455. epilogueInstructions = 1;
  1456. #else
  1457. #error unknown architecture
  1458. #endif
  1459. // skip past prologue
  1460. for (int i = 0; i < prologueInstructions; i++) {
  1461. testassert(*q != END_OFFSETS);
  1462. q++;
  1463. }
  1464. // copy instructions
  1465. while (*q != END_OFFSETS) *p++ = *q++ + uncached_symbol - symbol;
  1466. // rewind past epilogue
  1467. for (int i = 0; i < epilogueInstructions; i++) {
  1468. testassert(p > result);
  1469. p--;
  1470. }
  1471. free(uncached_offsets);
  1472. }
  1473. }
  1474. // Terminate the list of offsets and return.
  1475. testassert(p > result);
  1476. testassert(p < end);
  1477. *p = END_OFFSETS;
  1478. return result;
  1479. }
  1480. void CALLIT(void *o, void *sel_arg, SEL s, void *f, bool stret) __attribute__((noinline));
  1481. void CALLIT(void *o, void *sel_arg, SEL s, void *f, bool stret)
  1482. {
  1483. uintptr_t message_ref[2];
  1484. if (sel_arg != s) {
  1485. // fixup dispatch
  1486. // copy to a local buffer to keep sel_arg un-fixed-up
  1487. memcpy(message_ref, sel_arg, sizeof(message_ref));
  1488. sel_arg = message_ref;
  1489. }
  1490. if (!stret) callit(o, sel_arg, f);
  1491. #if SUPPORT_STRET
  1492. else callit_stret(o, sel_arg, f);
  1493. #else
  1494. else fail("stret?");
  1495. #endif
  1496. }
  1497. void test_dw_forward(void)
  1498. {
  1499. return;
  1500. }
  1501. struct stret test_dw_forward_stret(void)
  1502. {
  1503. return zero;
  1504. }
  1505. // sub = ordinary receiver object
  1506. // tagged = tagged receiver object
  1507. // SEL = selector to send
  1508. // sub_arg = arg to pass in receiver register (may be objc_super struct)
  1509. // tagged_arg = arg to pass in receiver register (may be objc_super struct)
  1510. // sel_arg = arg to pass in sel register (may be message_ref)
  1511. // uncaughtAllowed is the number of acceptable unreachable instructions
  1512. // (for example, the ones that handle the corrupt-cache-error case)
  1513. void test_dw(const char *name, id sub, id tagged, id exttagged, bool stret,
  1514. int uncaughtAllowed)
  1515. {
  1516. testprintf("DWARF FOR %s%s\n", name, stret ? " (stret)" : "");
  1517. // We need 2 SELs of each alignment so we can generate hash collisions.
  1518. // sel_registerName() never returns those alignments because they
  1519. // differ from malloc's alignment. So we create lots of compiled-in
  1520. // SELs here and hope something fits.
  1521. #pragma clang diagnostic push
  1522. #pragma clang diagnostic ignored "-Wundeclared-selector"
  1523. SEL sel = @selector(a);
  1524. SEL lotsOfSels[] = {
  1525. @selector(a1), @selector(a2), @selector(a3), @selector(a4),
  1526. @selector(a5), @selector(a6), @selector(a7), @selector(a8),
  1527. @selector(aa), @selector(ab), @selector(ac), @selector(ad),
  1528. @selector(ae), @selector(af), @selector(ag), @selector(ah),
  1529. @selector(A1), @selector(A2), @selector(A3), @selector(A4),
  1530. @selector(A5), @selector(A6), @selector(A7), @selector(A8),
  1531. @selector(AA), @selector(Ab), @selector(Ac), @selector(Ad),
  1532. @selector(Ae), @selector(Af), @selector(Ag), @selector(Ah),
  1533. @selector(bb1), @selector(bb2), @selector(bb3), @selector(bb4),
  1534. @selector(bb5), @selector(bb6), @selector(bb7), @selector(bb8),
  1535. @selector(bba), @selector(bbb), @selector(bbc), @selector(bbd),
  1536. @selector(bbe), @selector(bbf), @selector(bbg), @selector(bbh),
  1537. @selector(BB1), @selector(BB2), @selector(BB3), @selector(BB4),
  1538. @selector(BB5), @selector(BB6), @selector(BB7), @selector(BB8),
  1539. @selector(BBa), @selector(BBb), @selector(BBc), @selector(BBd),
  1540. @selector(BBe), @selector(BBf), @selector(BBg), @selector(BBh),
  1541. @selector(ccc1), @selector(ccc2), @selector(ccc3), @selector(ccc4),
  1542. @selector(ccc5), @selector(ccc6), @selector(ccc7), @selector(ccc8),
  1543. @selector(ccca), @selector(cccb), @selector(cccc), @selector(cccd),
  1544. @selector(ccce), @selector(cccf), @selector(cccg), @selector(ccch),
  1545. @selector(CCC1), @selector(CCC2), @selector(CCC3), @selector(CCC4),
  1546. @selector(CCC5), @selector(CCC6), @selector(CCC7), @selector(CCC8),
  1547. @selector(CCCa), @selector(CCCb), @selector(CCCc), @selector(CCCd),
  1548. @selector(CCCe), @selector(CCCf), @selector(CCCg), @selector(CCCh),
  1549. };
  1550. #pragma clang diagnostic pop
  1551. {
  1552. IMP imp = stret ? (IMP)test_dw_forward_stret : (IMP)test_dw_forward;
  1553. Class cls = object_getClass(sub);
  1554. Class tagcls = object_getClass(tagged);
  1555. Class exttagcls = object_getClass(exttagged);
  1556. class_replaceMethod(cls, sel, imp, "");
  1557. class_replaceMethod(tagcls, sel, imp, "");
  1558. class_replaceMethod(exttagcls, sel, imp, "");
  1559. for (size_t i = 0; i < sizeof(lotsOfSels)/sizeof(lotsOfSels[0]); i++) {
  1560. class_replaceMethod(cls, lotsOfSels[i], imp, "");
  1561. class_replaceMethod(tagcls, lotsOfSels[i], imp, "");
  1562. class_replaceMethod(exttagcls, lotsOfSels[i], imp, "");
  1563. }
  1564. }
  1565. #define ALIGNCOUNT 16
  1566. SEL sels[ALIGNCOUNT][2] = {{0}};
  1567. for (int align = 0; align < ALIGNCOUNT; align++) {
  1568. for (size_t i = 0; i < sizeof(lotsOfSels)/sizeof(lotsOfSels[0]); i++) {
  1569. if ((uintptr_t)(void*)lotsOfSels[i] % ALIGNCOUNT == align) {
  1570. if (sels[align][0]) {
  1571. sels[align][1] = lotsOfSels[i];
  1572. } else {
  1573. sels[align][0] = lotsOfSels[i];
  1574. }
  1575. }
  1576. }
  1577. if (!sels[align][0]) fail("no SEL with alignment %d", align);
  1578. if (!sels[align][1]) fail("only one SEL with alignment %d", align);
  1579. }
  1580. void *fn = dlsym(RTLD_DEFAULT, name);
  1581. #if __has_feature(ptrauth_calls)
  1582. fn = ptrauth_strip(fn, ptrauth_key_function_pointer);
  1583. #endif
  1584. testassert(fn);
  1585. // argument substitutions
  1586. void *sub_arg = (__bridge void*)sub;
  1587. void *tagged_arg = (__bridge void*)tagged;
  1588. void *exttagged_arg = (__bridge void*)exttagged;
  1589. void *sel_arg = (void*)sel;
  1590. struct objc_super sup_st = { sub, object_getClass(sub) };
  1591. struct objc_super tagged_sup_st = { tagged, object_getClass(tagged) };
  1592. struct objc_super exttagged_sup_st = { exttagged, object_getClass(exttagged) };
  1593. struct { void *imp; SEL sel; } message_ref = { fn, sel };
  1594. Class cache_cls = object_getClass(sub);
  1595. Class tagged_cache_cls = object_getClass(tagged);
  1596. Class exttagged_cache_cls = object_getClass(exttagged);
  1597. if (strstr(name, "Super")) {
  1598. // super version - replace receiver with objc_super
  1599. // clear caches of superclass
  1600. cache_cls = class_getSuperclass(cache_cls);
  1601. tagged_cache_cls = class_getSuperclass(tagged_cache_cls);
  1602. exttagged_cache_cls = class_getSuperclass(exttagged_cache_cls);
  1603. sub_arg = &sup_st;
  1604. tagged_arg = &tagged_sup_st;
  1605. exttagged_arg = &exttagged_sup_st;
  1606. }
  1607. if (strstr(name, "_fixup")) {
  1608. // fixup version - replace sel with message_ref
  1609. sel_arg = &message_ref;
  1610. }
  1611. uintptr_t *insnOffsets = getOffsets(name, nil);
  1612. testassert(insnOffsets);
  1613. uintptr_t offset;
  1614. int uncaughtCount = 0;
  1615. for (int oo = 0; insnOffsets[oo] != ~0UL; oo++) {
  1616. offset = insnOffsets[oo];
  1617. testprintf("OFFSET %lu\n", offset);
  1618. clobbered_insn_t saved_insn = clobber(fn, offset);
  1619. caught = false;
  1620. // nil
  1621. if ((__bridge void*)sub == sub_arg) {
  1622. SELF = nil;
  1623. testprintf(" nil\n");
  1624. CALLIT(nil, sel_arg, sel, fn, stret);
  1625. CALLIT(nil, sel_arg, sel, fn, stret);
  1626. }
  1627. // uncached
  1628. SELF = sub;
  1629. testprintf(" uncached\n");
  1630. _objc_flush_caches(cache_cls);
  1631. CALLIT(sub_arg, sel_arg, sel, fn, stret);
  1632. _objc_flush_caches(cache_cls);
  1633. CALLIT(sub_arg, sel_arg, sel, fn, stret);
  1634. // cached
  1635. SELF = sub;
  1636. testprintf(" cached\n");
  1637. CALLIT(sub_arg, sel_arg, sel, fn, stret);
  1638. CALLIT(sub_arg, sel_arg, sel, fn, stret);
  1639. // uncached,tagged
  1640. SELF = tagged;
  1641. testprintf(" uncached,tagged\n");
  1642. _objc_flush_caches(tagged_cache_cls);
  1643. CALLIT(tagged_arg, sel_arg, sel, fn, stret);
  1644. _objc_flush_caches(tagged_cache_cls);
  1645. CALLIT(tagged_arg, sel_arg, sel, fn, stret);
  1646. _objc_flush_caches(exttagged_cache_cls);
  1647. CALLIT(exttagged_arg, sel_arg, sel, fn, stret);
  1648. _objc_flush_caches(exttagged_cache_cls);
  1649. CALLIT(exttagged_arg, sel_arg, sel, fn, stret);
  1650. // cached,tagged
  1651. SELF = tagged;
  1652. testprintf(" cached,tagged\n");
  1653. CALLIT(tagged_arg, sel_arg, sel, fn, stret);
  1654. CALLIT(tagged_arg, sel_arg, sel, fn, stret);
  1655. CALLIT(exttagged_arg, sel_arg, sel, fn, stret);
  1656. CALLIT(exttagged_arg, sel_arg, sel, fn, stret);
  1657. // multiple SEL alignments, collisions, wraps
  1658. SELF = sub;
  1659. for (int a = 0; a < ALIGNCOUNT; a++) {
  1660. testprintf(" cached and uncached, SEL alignment %d\n", a);
  1661. // Count both up and down to be independent of
  1662. // implementation's cache scan direction
  1663. _objc_flush_caches(cache_cls);
  1664. for (int x2 = 0; x2 < 8; x2++) {
  1665. for (int s = 0; s < 4; s++) {
  1666. int align = (a+s) % ALIGNCOUNT;
  1667. CALLIT(sub_arg, sels[align][0], sels[align][0], fn, stret);
  1668. CALLIT(sub_arg, sels[align][1], sels[align][1], fn, stret);
  1669. }
  1670. }
  1671. _objc_flush_caches(cache_cls);
  1672. for (int x2 = 0; x2 < 8; x2++) {
  1673. for (int s = 0; s < 4; s++) {
  1674. int align = abs(a-s) % ALIGNCOUNT;
  1675. CALLIT(sub_arg, sels[align][0], sels[align][0], fn, stret);
  1676. CALLIT(sub_arg, sels[align][1], sels[align][1], fn, stret);
  1677. }
  1678. }
  1679. }
  1680. unclobber(fn, offset, saved_insn);
  1681. // remember offsets that were caught by none of the above
  1682. if (caught) {
  1683. insnOffsets[oo] = 0;
  1684. } else {
  1685. uncaughtCount++;
  1686. testprintf("offset %s+%lu not caught (%d/%d)\n",
  1687. name, offset, uncaughtCount, uncaughtAllowed);
  1688. }
  1689. }
  1690. // Complain if too many offsets went uncaught.
  1691. // Acceptably-uncaught offsets include the corrupt-cache-error handler.
  1692. if (uncaughtCount != uncaughtAllowed) {
  1693. for (int oo = 0; insnOffsets[oo] != ~0UL; oo++) {
  1694. if (insnOffsets[oo]) {
  1695. fprintf(stderr, "BAD: offset %s+%lu not caught\n",
  1696. name, insnOffsets[oo]);
  1697. }
  1698. }
  1699. fail("wrong instructions not reached for %s (missed %d, expected %d)",
  1700. name, uncaughtCount, uncaughtAllowed);
  1701. }
  1702. free(insnOffsets);
  1703. }
  1704. // TEST_DWARF
  1705. #endif
  1706. void test_basic(id receiver)
  1707. {
  1708. id idval;
  1709. long long llval;
  1710. struct stret stretval;
  1711. double fpval;
  1712. long double lfpval;
  1713. vector_ulong2 vecval;
  1714. // message uncached
  1715. // message uncached long long
  1716. // message uncached stret
  1717. // message uncached fpret
  1718. // message uncached fpret long double
  1719. // message uncached noarg (as above)
  1720. // message cached
  1721. // message cached long long
  1722. // message cached stret
  1723. // message cached fpret
  1724. // message cached fpret long double
  1725. // message cached noarg (as above)
  1726. // fixme verify that uncached lookup didn't happen the 2nd time?
  1727. SELF = receiver;
  1728. _objc_flush_caches(object_getClass(receiver));
  1729. for (int i = 0; i < 5; i++) {
  1730. testprintf("idret\n");
  1731. state = 0;
  1732. idval = nil;
  1733. idval = [receiver idret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1734. testassert(state == 101);
  1735. testassert(idval == ID_RESULT);
  1736. testprintf("llret\n");
  1737. llval = 0;
  1738. llval = [receiver llret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1739. testassert(state == 102);
  1740. testassert(llval == LL_RESULT);
  1741. testprintf("stret\n");
  1742. stretval = zero;
  1743. stretval = [receiver stret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1744. testassert(state == 103);
  1745. testassert(stret_equal(stretval, STRET_RESULT));
  1746. testprintf("fpret\n");
  1747. fpval = 0;
  1748. fpval = [receiver fpret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1749. testassert(state == 104);
  1750. testassert(fpval == FP_RESULT);
  1751. testprintf("lfpret\n");
  1752. lfpval = 0;
  1753. lfpval = [receiver lfpret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1754. testassert(state == 105);
  1755. testassert(lfpval == LFP_RESULT);
  1756. testprintf("vecret\n");
  1757. vecval = 0;
  1758. vecval = [receiver vecret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1759. testassert(state == 106);
  1760. testassert(vector_equal(vecval, VEC_RESULT));
  1761. // explicitly call noarg messenger, even if compiler doesn't emit it
  1762. state = 0;
  1763. testprintf("idret noarg\n");
  1764. idval = nil;
  1765. idval = ((typeof(idmsg0))objc_msgSend_noarg)(receiver, @selector(idret_noarg));
  1766. testassert(state == 111);
  1767. testassert(idval == ID_RESULT);
  1768. testprintf("llret noarg\n");
  1769. llval = 0;
  1770. llval = ((typeof(llmsg0))objc_msgSend_noarg)(receiver, @selector(llret_noarg));
  1771. testassert(state == 112);
  1772. testassert(llval == LL_RESULT);
  1773. /*
  1774. no objc_msgSend_stret_noarg
  1775. stretval = zero;
  1776. stretval = ((typeof(stretmsg0))objc_msgSend_stret_noarg)(receiver, @selector(stret_noarg));
  1777. stretval = [receiver stret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1778. testassert(state == 113);
  1779. testassert(stret_equal(stretval, STRET_RESULT));
  1780. */
  1781. #if !__i386__
  1782. testprintf("fpret noarg\n");
  1783. fpval = 0;
  1784. fpval = ((typeof(fpmsg0))objc_msgSend_noarg)(receiver, @selector(fpret_noarg));
  1785. testassert(state == 114);
  1786. testassert(fpval == FP_RESULT);
  1787. testprintf("vecret noarg\n");
  1788. vecval = 0;
  1789. vecval = ((typeof(vecmsg0))objc_msgSend_noarg)(receiver, @selector(vecret_noarg));
  1790. testassert(state == 116);
  1791. testassert(vector_equal(vecval, VEC_RESULT));
  1792. #endif
  1793. #if !__i386__ && !__x86_64__
  1794. testprintf("lfpret noarg\n");
  1795. lfpval = 0;
  1796. lfpval = ((typeof(lfpmsg0))objc_msgSend_noarg)(receiver, @selector(lfpret_noarg));
  1797. testassert(state == 115);
  1798. testassert(lfpval == LFP_RESULT);
  1799. #endif
  1800. }
  1801. testprintf("basic done\n");
  1802. }
  1803. int main()
  1804. {
  1805. PUSH_POOL {
  1806. id idval;
  1807. long long llval;
  1808. struct stret stretval;
  1809. double fpval;
  1810. long double lfpval;
  1811. vector_ulong2 vecval;
  1812. #if __x86_64__
  1813. struct stret *stretptr;
  1814. #endif
  1815. Method idmethod;
  1816. Method llmethod;
  1817. Method stretmethod;
  1818. Method fpmethod;
  1819. Method lfpmethod;
  1820. Method vecmethod;
  1821. id (*idfn)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
  1822. long long (*llfn)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
  1823. struct stret (*stretfn)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
  1824. double (*fpfn)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
  1825. long double (*lfpfn)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
  1826. vector_ulong2 (*vecfn)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
  1827. id (*idmsg)(id, SEL, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
  1828. id (*idmsgsuper)(struct objc_super *, SEL, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
  1829. long long (*llmsg)(id, SEL, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
  1830. struct stret (*stretmsg)(id, SEL, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
  1831. struct stret (*stretmsgsuper)(struct objc_super *, SEL, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
  1832. double (*fpmsg)(id, SEL, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
  1833. long double (*lfpmsg)(id, SEL, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
  1834. vector_ulong2 (*vecmsg)(id, SEL, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
  1835. // get +initialize out of the way
  1836. [Sub class];
  1837. #if OBJC_HAVE_TAGGED_POINTERS
  1838. [TaggedSub class];
  1839. [ExtTaggedSub class];
  1840. #endif
  1841. ID_RESULT = [Super new];
  1842. Sub *sub = [Sub new];
  1843. Super *sup = [Super new];
  1844. #if OBJC_HAVE_TAGGED_POINTERS
  1845. TaggedSub *tagged = (__bridge id)_objc_makeTaggedPointer(OBJC_TAG_1, 999);
  1846. ExtTaggedSub *exttagged = (__bridge id)_objc_makeTaggedPointer(OBJC_TAG_First52BitPayload, 999);
  1847. #endif
  1848. // Basic cached and uncached dispatch.
  1849. // Do this first before anything below caches stuff.
  1850. testprintf("basic\n");
  1851. test_basic(sub);
  1852. #if OBJC_HAVE_TAGGED_POINTERS
  1853. testprintf("basic tagged\n");
  1854. test_basic(tagged);
  1855. testprintf("basic ext tagged\n");
  1856. test_basic(exttagged);
  1857. #endif
  1858. idmethod = class_getInstanceMethod([Super class], @selector(idret::::::::::::::::::::::::::::::::::::));
  1859. testassert(idmethod);
  1860. llmethod = class_getInstanceMethod([Super class], @selector(llret::::::::::::::::::::::::::::::::::::));
  1861. testassert(llmethod);
  1862. stretmethod = class_getInstanceMethod([Super class], @selector(stret::::::::::::::::::::::::::::::::::::));
  1863. testassert(stretmethod);
  1864. fpmethod = class_getInstanceMethod([Super class], @selector(fpret::::::::::::::::::::::::::::::::::::));
  1865. testassert(fpmethod);
  1866. lfpmethod = class_getInstanceMethod([Super class], @selector(lfpret::::::::::::::::::::::::::::::::::::));
  1867. testassert(lfpmethod);
  1868. vecmethod = class_getInstanceMethod([Super class], @selector(vecret::::::::::::::::::::::::::::::::::::));
  1869. testassert(vecmethod);
  1870. idfn = (id (*)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke;
  1871. llfn = (long long (*)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke;
  1872. stretfn = (struct stret (*)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke_stret;
  1873. fpfn = (double (*)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke;
  1874. lfpfn = (long double (*)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke;
  1875. vecfn = (vector_ulong2 (*)(id, Method, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, vector_ulong2, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke;
  1876. // method_invoke
  1877. // method_invoke long long
  1878. // method_invoke_stret stret
  1879. // method_invoke_stret fpret
  1880. // method_invoke fpret long double
  1881. testprintf("method_invoke\n");
  1882. SELF = sup;
  1883. state = 0;
  1884. idval = nil;
  1885. idval = (*idfn)(sup, idmethod, VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  1886. testassert(state == 1);
  1887. testassert(idval == ID_RESULT);
  1888. llval = 0;
  1889. llval = (*llfn)(sup, llmethod, VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  1890. testassert(state == 2);
  1891. testassert(llval == LL_RESULT);
  1892. stretval = zero;
  1893. stretval = (*stretfn)(sup, stretmethod, VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  1894. testassert(state == 3);
  1895. testassert(stret_equal(stretval, STRET_RESULT));
  1896. fpval = 0;
  1897. fpval = (*fpfn)(sup, fpmethod, VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  1898. testassert(state == 4);
  1899. testassert(fpval == FP_RESULT);
  1900. lfpval = 0;
  1901. lfpval = (*lfpfn)(sup, lfpmethod, VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  1902. testassert(state == 5);
  1903. testassert(lfpval == LFP_RESULT);
  1904. vecval = 0;
  1905. vecval = (*vecfn)(sup, vecmethod, VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  1906. testassert(state == 6);
  1907. testassert(vector_equal(vecval, VEC_RESULT));
  1908. // message to nil
  1909. // message to nil long long
  1910. // message to nil stret
  1911. // message to nil fpret
  1912. // message to nil fpret long double
  1913. // Use NIL_RECEIVER to avoid compiler optimizations.
  1914. testprintf("message to nil\n");
  1915. state = 0;
  1916. idval = ID_RESULT;
  1917. idval = [(id)NIL_RECEIVER idret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1918. testassert(state == 0);
  1919. testassert(idval == nil);
  1920. state = 0;
  1921. llval = LL_RESULT;
  1922. llval = [(id)NIL_RECEIVER llret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1923. testassert(state == 0);
  1924. testassert(llval == 0LL);
  1925. state = 0;
  1926. stretval = zero;
  1927. stretval = [(id)NIL_RECEIVER stret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1928. testassert(state == 0);
  1929. testassert(0 == memcmp(&stretval, &zero, sizeof(stretval)));
  1930. #if __x86_64__
  1931. // check stret return register
  1932. state = 0;
  1933. stretval = zero;
  1934. stretptr = ((struct stret *(*)(struct stret *, id, SEL))objc_msgSend_stret)
  1935. (&stretval, nil, @selector(stret_nop));
  1936. testassert(stretptr == &stretval);
  1937. testassert(state == 0);
  1938. // no stret result guarantee for hand-written calls
  1939. #endif
  1940. #if __i386__
  1941. // check struct-return address stack pop
  1942. for (int i = 0; i < 10000000; i++) {
  1943. state = 0;
  1944. ((struct stret (*)(id, SEL))objc_msgSend_stret)
  1945. (nil, @selector(stret_nop));
  1946. }
  1947. #endif
  1948. state = 0;
  1949. fpval = FP_RESULT;
  1950. fpval = [(id)NIL_RECEIVER fpret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1951. testassert(state == 0);
  1952. testassert(fpval == 0.0);
  1953. state = 0;
  1954. lfpval = LFP_RESULT;
  1955. lfpval = [(id)NIL_RECEIVER lfpret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1956. testassert(state == 0);
  1957. testassert(lfpval == 0.0);
  1958. state = 0;
  1959. vecval = VEC_RESULT;
  1960. vecval = [(id)NIL_RECEIVER vecret :VEC1:VEC2:VEC3:VEC4:VEC5:VEC6:VEC7:VEC8: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];
  1961. testassert(state == 0);
  1962. testassert(vector_all(vecval == 0));
  1963. // message to nil, different struct types
  1964. // This verifies that ordinary objc_msgSend() erases enough registers
  1965. // for structs that return in registers.
  1966. #define TEST_NIL_STRUCT(i,n) \
  1967. do { \
  1968. struct stret_##i##n z; \
  1969. bzero(&z, sizeof(z)); \
  1970. [Super stret_i##n##_nonzero]; \
  1971. [Super stret_d##n##_nonzero]; \
  1972. struct stret_##i##n val = [(id)NIL_RECEIVER stret_##i##n##_zero]; \
  1973. testassert(0 == memcmp(&z, &val, sizeof(val))); \
  1974. } while (0)
  1975. TEST_NIL_STRUCT(i,1);
  1976. TEST_NIL_STRUCT(i,2);
  1977. TEST_NIL_STRUCT(i,3);
  1978. TEST_NIL_STRUCT(i,4);
  1979. TEST_NIL_STRUCT(i,5);
  1980. TEST_NIL_STRUCT(i,6);
  1981. TEST_NIL_STRUCT(i,7);
  1982. TEST_NIL_STRUCT(i,8);
  1983. TEST_NIL_STRUCT(i,9);
  1984. #if __i386__
  1985. testwarn("rdar://16267205 i386 struct{float} and struct{double}");
  1986. #else
  1987. TEST_NIL_STRUCT(d,1);
  1988. #endif
  1989. TEST_NIL_STRUCT(d,2);
  1990. TEST_NIL_STRUCT(d,3);
  1991. TEST_NIL_STRUCT(d,4);
  1992. TEST_NIL_STRUCT(d,5);
  1993. TEST_NIL_STRUCT(d,6);
  1994. TEST_NIL_STRUCT(d,7);
  1995. TEST_NIL_STRUCT(d,8);
  1996. TEST_NIL_STRUCT(d,9);
  1997. // message to nil noarg
  1998. // explicitly call noarg messenger, even if compiler doesn't emit it
  1999. state = 0;
  2000. idval = ID_RESULT;
  2001. idval = ((typeof(idmsg0))objc_msgSend_noarg)(nil, @selector(idret_noarg));
  2002. testassert(state == 0);
  2003. testassert(idval == nil);
  2004. state = 0;
  2005. llval = LL_RESULT;
  2006. llval = ((typeof(llmsg0))objc_msgSend_noarg)(nil, @selector(llret_noarg));
  2007. testassert(state == 0);
  2008. testassert(llval == 0LL);
  2009. // no stret_noarg messenger
  2010. #if !__i386__
  2011. state = 0;
  2012. fpval = FP_RESULT;
  2013. fpval = ((typeof(fpmsg0))objc_msgSend_noarg)(nil, @selector(fpret_noarg));
  2014. testassert(state == 0);
  2015. testassert(fpval == 0.0);
  2016. state = 0;
  2017. vecval = VEC_RESULT;
  2018. vecval = ((typeof(vecmsg0))objc_msgSend_noarg)(nil, @selector(vecret_noarg));
  2019. testassert(state == 0);
  2020. testassert(vector_all(vecval == 0));
  2021. #endif
  2022. #if !__i386__ && !__x86_64__
  2023. state = 0;
  2024. lfpval = LFP_RESULT;
  2025. lfpval = ((typeof(lfpmsg0))objc_msgSend_noarg)(nil, @selector(lfpret_noarg));
  2026. testassert(state == 0);
  2027. testassert(lfpval == 0.0);
  2028. #endif
  2029. // rdar://8271364 objc_msgSendSuper2 must not change objc_super
  2030. testprintf("super struct\n");
  2031. struct objc_super sup_st = {
  2032. sub,
  2033. object_getClass(sub),
  2034. };
  2035. SELF = sub;
  2036. state = 100;
  2037. idval = nil;
  2038. idval = ((id(*)(struct objc_super *, SEL, vector_ulong2,vector_ulong2,vector_ulong2,vector_ulong2,vector_ulong2,vector_ulong2,vector_ulong2,vector_ulong2, int,int,int,int,int,int,int,int,int,int,int,int,int, double,double,double,double,double,double,double,double,double,double,double,double,double,double,double))objc_msgSendSuper2) (&sup_st, @selector(idret::::::::::::::::::::::::::::::::::::), VEC1,VEC2,VEC3,VEC4,VEC5,VEC6,VEC7,VEC8, 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);
  2039. testassert(state == 1);
  2040. testassert(idval == ID_RESULT);
  2041. testassert(sup_st.receiver == sub);
  2042. testassert(sup_st.super_class == object_getClass(sub));
  2043. state = 100;
  2044. stretval = zero;
  2045. stretval = ((struct stret(*)(struct objc_super *, SEL, vector_ulong2,vector_ulong2,vector_ulong2,vector_ulong2,vector_ulong2,vector_ulong2,vector_ulong2,vector_ulong2, int,int,int,int,int,int,int,int,int,int,int,int,int, double,double,double,double,double,double,double,double,double,double,double,double,double,double,double))objc_msgSendSuper2_stret) (&sup_st, @selector(stret::::::::::::::::::::::::::::::::::::), VEC1,VEC2,VEC3,VEC4,VEC5,VEC6,VEC7,VEC8, 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);
  2046. testassert(state == 3);
  2047. testassert(stret_equal(stretval, STRET_RESULT));
  2048. testassert(sup_st.receiver == sub);
  2049. testassert(sup_st.super_class == object_getClass(sub));
  2050. #if !__arm64__
  2051. // Debug messengers.
  2052. testprintf("debug messengers\n");
  2053. state = 0;
  2054. idmsg = (typeof(idmsg))objc_msgSend_debug;
  2055. idval = nil;
  2056. idval = (*idmsg)(sub, @selector(idret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2057. testassert(state == 101);
  2058. testassert(idval == ID_RESULT);
  2059. state = 0;
  2060. llmsg = (typeof(llmsg))objc_msgSend_debug;
  2061. llval = 0;
  2062. llval = (*llmsg)(sub, @selector(llret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2063. testassert(state == 102);
  2064. testassert(llval == LL_RESULT);
  2065. state = 0;
  2066. stretmsg = (typeof(stretmsg))objc_msgSend_stret_debug;
  2067. stretval = zero;
  2068. stretval = (*stretmsg)(sub, @selector(stret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2069. testassert(state == 103);
  2070. testassert(stret_equal(stretval, STRET_RESULT));
  2071. state = 100;
  2072. sup_st.receiver = sub;
  2073. sup_st.super_class = object_getClass(sub);
  2074. idmsgsuper = (typeof(idmsgsuper))objc_msgSendSuper2_debug;
  2075. idval = nil;
  2076. idval = (*idmsgsuper)(&sup_st, @selector(idret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2077. testassert(state == 1);
  2078. testassert(idval == ID_RESULT);
  2079. state = 100;
  2080. sup_st.receiver = sub;
  2081. sup_st.super_class = object_getClass(sub);
  2082. stretmsgsuper = (typeof(stretmsgsuper))objc_msgSendSuper2_stret_debug;
  2083. stretval = zero;
  2084. stretval = (*stretmsgsuper)(&sup_st, @selector(stret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2085. testassert(state == 3);
  2086. testassert(stret_equal(stretval, STRET_RESULT));
  2087. #if __i386__
  2088. state = 0;
  2089. fpmsg = (typeof(fpmsg))objc_msgSend_fpret_debug;
  2090. fpval = 0;
  2091. fpval = (*fpmsg)(sub, @selector(fpret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2092. testassert(state == 104);
  2093. testassert(fpval == FP_RESULT);
  2094. #endif
  2095. #if __x86_64__
  2096. state = 0;
  2097. lfpmsg = (typeof(lfpmsg))objc_msgSend_fpret_debug;
  2098. lfpval = 0;
  2099. lfpval = (*lfpmsg)(sub, @selector(lfpret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2100. testassert(state == 105);
  2101. testassert(lfpval == LFP_RESULT);
  2102. // fixme fp2ret
  2103. #endif
  2104. // debug messengers
  2105. #endif
  2106. // objc_msgLookup
  2107. #if 1
  2108. // fixme objc_msgLookup test hack stopped working after a compiler update
  2109. #elif __has_feature(objc_arc)
  2110. // ARC interferes with objc_msgLookup test hacks
  2111. #elif __i386__ && TARGET_OS_SIMULATOR
  2112. testwarn("fixme msgLookup hack doesn't work");
  2113. #else
  2114. // fixme hack: call the looked-up method
  2115. # if __arm64__
  2116. # define CALL_LOOKUP(ret) \
  2117. asm volatile ("blr x17 \n mov %x0, x0" : "=r" (ret))
  2118. # define CALL_LOOKUP_STRET(ret) \
  2119. asm volatile ("mov x8, %x1 \n blr x17 \n" : "=m" (ret) : "r" (&ret))
  2120. # elif __arm__
  2121. # define CALL_LOOKUP(ret) \
  2122. asm volatile ("blx r12 \n mov %0, r0" : "=r" (ret))
  2123. # define CALL_LOOKUP_STRET(ret) \
  2124. asm volatile ("mov r0, %1 \n blx r12 \n" : "=m" (ret) : "r" (&ret))
  2125. # elif __x86_64__
  2126. # define CALL_LOOKUP(ret) \
  2127. asm volatile ("call *%%r11 \n mov %%rax, %0" : "=r" (ret))
  2128. # define CALL_LOOKUP_STRET(ret) \
  2129. asm volatile ("mov %1, %%rdi \n call *%%r11 \n" : "=m" (ret) : "r" (&ret))
  2130. # elif __i386__
  2131. # define CALL_LOOKUP(ret) \
  2132. asm volatile ("call *%%eax \n mov %%eax, %0" : "=r" (ret))
  2133. # define CALL_LOOKUP_STRET(ret) \
  2134. asm volatile ("add $4, %%esp \n mov %1, (%%esp) \n call *%%eax \n sub $4, %%esp \n" : "=m" (ret) : "d" (&ret))
  2135. # else
  2136. # error unknown architecture
  2137. # endif
  2138. // msgLookup uncached
  2139. // msgLookup uncached super
  2140. // msgLookup uncached stret
  2141. // msgLookup uncached super stret
  2142. // msgLookup uncached fpret
  2143. // msgLookup uncached fpret long double
  2144. // msgLookup cached
  2145. // msgLookup cached stret
  2146. // msgLookup cached super
  2147. // msgLookup cached super stret
  2148. // msgLookup cached fpret
  2149. // msgLookup cached fpret long double
  2150. // fixme verify that uncached lookup didn't happen the 2nd time?
  2151. SELF = sub;
  2152. _objc_flush_caches(object_getClass(sub));
  2153. for (int i = 0; i < 5; i++) {
  2154. testprintf("objc_msgLookup\n");
  2155. state = 0;
  2156. idmsg = (typeof(idmsg))objc_msgLookup;
  2157. idval = nil;
  2158. (*idmsg)(sub, @selector(idret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2159. CALL_LOOKUP(idval);
  2160. testassert(state == 101);
  2161. testassert(idval == ID_RESULT);
  2162. testprintf("objc_msgLookup_stret\n");
  2163. state = 0;
  2164. stretmsg = (typeof(stretmsg))objc_msgLookup_stret;
  2165. stretval = zero;
  2166. (*stretmsg)(sub, @selector(stret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2167. CALL_LOOKUP_STRET(stretval);
  2168. testassert(state == 103);
  2169. testassert(stret_equal(stretval, STRET_RESULT));
  2170. testprintf("objc_msgLookupSuper2\n");
  2171. state = 100;
  2172. sup_st.receiver = sub;
  2173. sup_st.super_class = object_getClass(sub);
  2174. idmsgsuper = (typeof(idmsgsuper))objc_msgLookupSuper2;
  2175. idval = nil;
  2176. idval = (*idmsgsuper)(&sup_st, @selector(idret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2177. CALL_LOOKUP(idval);
  2178. testassert(state == 1);
  2179. testassert(idval == ID_RESULT);
  2180. testprintf("objc_msgLookupSuper2_stret\n");
  2181. state = 100;
  2182. sup_st.receiver = sub;
  2183. sup_st.super_class = object_getClass(sub);
  2184. stretmsgsuper = (typeof(stretmsgsuper))objc_msgLookupSuper2_stret;
  2185. stretval = zero;
  2186. (*stretmsgsuper)(&sup_st, @selector(stret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2187. CALL_LOOKUP_STRET(stretval);
  2188. testassert(state == 3);
  2189. testassert(stret_equal(stretval, STRET_RESULT));
  2190. #if __i386__
  2191. // fixme fpret, can't test FP stack properly
  2192. #endif
  2193. #if __x86_64__
  2194. // fixme fpret, can't test FP stack properly
  2195. // fixme fp2ret, can't test FP stack properly
  2196. #endif
  2197. }
  2198. // msgLookup to nil
  2199. // msgLookup to nil stret
  2200. // fixme msgLookup to nil long long
  2201. // fixme msgLookup to nil fpret
  2202. // fixme msgLookup to nil fp2ret
  2203. testprintf("objc_msgLookup to nil\n");
  2204. state = 0;
  2205. idmsg = (typeof(idmsg))objc_msgLookup;
  2206. idval = nil;
  2207. (*idmsg)(NIL_RECEIVER, @selector(idret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2208. CALL_LOOKUP(idval);
  2209. testassert(state == 0);
  2210. testassert(idval == nil);
  2211. testprintf("objc_msgLookup_stret to nil\n");
  2212. state = 0;
  2213. stretmsg = (typeof(stretmsg))objc_msgLookup_stret;
  2214. stretval = zero;
  2215. (*stretmsg)(NIL_RECEIVER, @selector(stret::::::::::::::::::::::::::::::::::::), VEC1, VEC2, VEC3, VEC4, VEC5, VEC6, VEC7, VEC8, 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);
  2216. CALL_LOOKUP_STRET(stretval);
  2217. testassert(state == 0);
  2218. // no stret result guarantee
  2219. #if __i386__
  2220. // fixme fpret, can't test FP stack properly
  2221. #endif
  2222. #if __x86_64__
  2223. // fixme fpret, can't test FP stack properly
  2224. // fixme fp2ret, can't test FP stack properly
  2225. #endif
  2226. // objc_msgLookup
  2227. #endif
  2228. #if !TEST_DWARF
  2229. testwarn("no unwind tables in this configuration " NO_DWARF_REASON);
  2230. #else
  2231. // DWARF unwind tables
  2232. testprintf("unwind tables\n");
  2233. // Clear simulator-related environment variables.
  2234. // Disassembly will run llvm-objdump which is not a simulator executable.
  2235. unsetenv("DYLD_ROOT_PATH");
  2236. unsetenv("DYLD_FALLBACK_LIBRARY_PATH");
  2237. unsetenv("DYLD_FALLBACK_FRAMEWORK_PATH");
  2238. // Check mprotect() of objc_msgSend.
  2239. // It doesn't work when running on a device with no libobjc root.
  2240. // In that case we skip this part of the test without failing.
  2241. // fixme make this work
  2242. // fixme now it doesn't work even with a libobjc root in place?
  2243. int err1 = mprotect((void *)((uintptr_t)&objc_msgSend & ~(PAGE_MAX_SIZE-1)),
  2244. PAGE_MAX_SIZE, PROT_READ | PROT_WRITE);
  2245. int errno1 = errno;
  2246. int err2 = mprotect((void *)((uintptr_t)&objc_msgSend & ~(PAGE_MAX_SIZE-1)),
  2247. PAGE_MAX_SIZE, PROT_READ | PROT_EXEC);
  2248. int errno2 = errno;
  2249. if (err1 || err2) {
  2250. testwarn("can't mprotect() objc_msgSend (%d, %d). "
  2251. "Skipping unwind table test.",
  2252. err1, errno1, err2, errno2);
  2253. }
  2254. else {
  2255. // install exception handler
  2256. struct sigaction act;
  2257. act.sa_sigaction = break_handler;
  2258. act.sa_mask = 0;
  2259. act.sa_flags = SA_SIGINFO;
  2260. sigaction(BREAK_SIGNAL, &act, nil);
  2261. #if defined(BREAK_SIGNAL2)
  2262. sigaction(BREAK_SIGNAL2, &act, nil);
  2263. #endif
  2264. SubDW *dw = [[SubDW alloc] init];
  2265. objc_setForwardHandler((void*)test_dw_forward, (void*)test_dw_forward_stret);
  2266. # if __x86_64__
  2267. test_dw("objc_msgSend", dw, tagged, exttagged, false, 0);
  2268. test_dw("objc_msgSend_stret", dw, tagged, exttagged, true, 0);
  2269. test_dw("objc_msgSend_fpret", dw, tagged, exttagged, false, 0);
  2270. test_dw("objc_msgSend_fp2ret", dw, tagged, exttagged, false, 0);
  2271. test_dw("objc_msgSendSuper", dw, tagged, exttagged, false, 0);
  2272. test_dw("objc_msgSendSuper2", dw, tagged, exttagged, false, 0);
  2273. test_dw("objc_msgSendSuper_stret", dw, tagged, exttagged, true, 0);
  2274. test_dw("objc_msgSendSuper2_stret", dw, tagged, exttagged, true, 0);
  2275. # elif __i386__
  2276. test_dw("objc_msgSend", dw, dw, dw, false, 0);
  2277. test_dw("objc_msgSend_stret", dw, dw, dw, true, 0);
  2278. test_dw("objc_msgSend_fpret", dw, dw, dw, false, 0);
  2279. test_dw("objc_msgSendSuper", dw, dw, dw, false, 0);
  2280. test_dw("objc_msgSendSuper2", dw, dw, dw, false, 0);
  2281. test_dw("objc_msgSendSuper_stret", dw, dw, dw, true, 0);
  2282. test_dw("objc_msgSendSuper2_stret", dw, dw, dw, true, 0);
  2283. # elif __arm64__
  2284. test_dw("objc_msgSend", dw, tagged, exttagged, false, 1);
  2285. test_dw("objc_msgSendSuper", dw, tagged, exttagged, false, 1);
  2286. test_dw("objc_msgSendSuper2", dw, tagged, exttagged, false, 1);
  2287. # elif __arm__
  2288. test_dw("objc_msgSend", dw, dw, dw, false, 0);
  2289. test_dw("objc_msgSend_stret", dw, dw, dw, true, 0);
  2290. test_dw("objc_msgSendSuper", dw, dw, dw, false, 0);
  2291. test_dw("objc_msgSendSuper2", dw, dw, dw, false, 0);
  2292. test_dw("objc_msgSendSuper_stret", dw, dw, dw, true, 0);
  2293. test_dw("objc_msgSendSuper2_stret", dw, dw, dw, true, 0);
  2294. # else
  2295. # error unknown architecture
  2296. # endif
  2297. }
  2298. // end DWARF unwind test
  2299. #endif
  2300. } POP_POOL;
  2301. succeed(__FILE__);
  2302. }