cpupara.pas 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. Generates the argument location information for x86-64 target
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit cpupara;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. cpubase,cgbase,cgutils,
  23. symconst,symtype,symsym,symdef,
  24. aasmtai,aasmdata,
  25. parabase,paramgr;
  26. type
  27. tx86_64paramanager = class(tparamanager)
  28. private
  29. procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  30. procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
  31. var intparareg,mmparareg,parasize:longint;varargsparas: boolean);
  32. public
  33. function param_use_paraloc(const cgpara:tcgpara):boolean;override;
  34. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  35. function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
  36. procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);override;
  37. function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
  38. function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
  39. function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
  40. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  41. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
  42. function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
  43. end;
  44. implementation
  45. uses
  46. cutils,verbose,
  47. systems,
  48. defutil,
  49. symtable;
  50. const
  51. paraintsupregs : array[0..5] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
  52. parammsupregs : array[0..7] of tsuperregister = (RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7);
  53. paraintsupregs_winx64 : array[0..3] of tsuperregister = (RS_RCX,RS_RDX,RS_R8,RS_R9);
  54. parammsupregs_winx64 : array[0..3] of tsuperregister = (RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3);
  55. {
  56. The argument classification code largely comes from libffi:
  57. ffi64.c - Copyright (c) 2002, 2007 Bo Thorsen <[email protected]>
  58. Copyright (c) 2008 Red Hat, Inc.
  59. x86-64 Foreign Function Interface
  60. Permission is hereby granted, free of charge, to any person obtaining
  61. a copy of this software and associated documentation files (the
  62. ``Software''), to deal in the Software without restriction, including
  63. without limitation the rights to use, copy, modify, merge, publish,
  64. distribute, sublicense, and/or sell copies of the Software, and to
  65. permit persons to whom the Software is furnished to do so, subject to
  66. the following conditions:
  67. The above copyright notice and this permission notice shall be included
  68. in all copies or substantial portions of the Software.
  69. THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
  70. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  71. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  72. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  73. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  74. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  75. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  76. DEALINGS IN THE SOFTWARE.
  77. ----------------------------------------------------------------------- *)
  78. }
  79. const
  80. MAX_PARA_CLASSES = 4;
  81. type
  82. tx64paraclass = (
  83. X86_64_NO_CLASS,
  84. X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS,
  85. X86_64_SSE_CLASS,X86_64_SSESF_CLASS,X86_64_SSEDF_CLASS,X86_64_SSEUP_CLASS,
  86. X86_64_X87_CLASS,X86_64_X87UP_CLASS,
  87. X86_64_COMPLEX_X87_CLASS,
  88. X86_64_MEMORY_CLASS
  89. );
  90. tx64paraclasses = array[0..MAX_PARA_CLASSES-1] of tx64paraclass;
  91. { Win64-specific helper }
  92. function aggregate_in_registers_win64(varspez:tvarspez;size:longint):boolean;
  93. begin
  94. { TODO: Temporary hack: vs_const parameters are always passed by reference for win64}
  95. result:=(varspez=vs_value) and (size in [1,2,4,8])
  96. end;
  97. (* x86-64 register passing implementation. See x86-64 ABI for details. Goal
  98. of this code is to classify each 8bytes of incoming argument by the register
  99. class and assign registers accordingly. *)
  100. (* Return the union class of CLASS1 and CLASS2.
  101. See the x86-64 PS ABI for details. *)
  102. function merge_classes(class1, class2: tx64paraclass): tx64paraclass;
  103. begin
  104. (* Rule #1: If both classes are equal, this is the resulting class. *)
  105. if (class1=class2) then
  106. exit(class1);
  107. (* Rule #2: If one of the classes is NO_CLASS, the resulting class is
  108. the other class. *)
  109. if (class1=X86_64_NO_CLASS) then
  110. exit(class2);
  111. if (class2=X86_64_NO_CLASS) then
  112. exit(class1);
  113. (* Rule #3: If one of the classes is MEMORY, the result is MEMORY. *)
  114. if (class1=X86_64_MEMORY_CLASS) or
  115. (class2=X86_64_MEMORY_CLASS) then
  116. exit(X86_64_MEMORY_CLASS);
  117. (* Rule #4: If one of the classes is INTEGER, the result is INTEGER. *)
  118. { 32 bit }
  119. if ((class1=X86_64_INTEGERSI_CLASS) and
  120. (class2=X86_64_SSESF_CLASS)) or
  121. ((class2=X86_64_INTEGERSI_CLASS) and
  122. (class1=X86_64_SSESF_CLASS)) then
  123. exit(X86_64_INTEGERSI_CLASS);
  124. { 64 bit }
  125. if (class1 in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) or
  126. (class2 in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) then
  127. exit(X86_64_INTEGER_CLASS);
  128. (* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
  129. MEMORY is used. *)
  130. if (class1 in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) or
  131. (class2 in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) then
  132. exit(X86_64_MEMORY_CLASS);
  133. (* Rule #6: Otherwise class SSE is used. *)
  134. result:=X86_64_SSE_CLASS;
  135. end;
  136. (* Classify the argument of type TYPE and mode MODE.
  137. CLASSES will be filled by the register class used to pass each word
  138. of the operand. The number of words is returned. In case the parameter
  139. should be passed in memory, 0 is returned. As a special case for zero
  140. sized containers, classes[0] will be NO_CLASS and 1 is returned.
  141. real_size contains either def.size, or a value derived from
  142. def.bitpackedsize and the field offset denoting the number of bytes
  143. spanned by a bitpacked field
  144. See the x86-64 PS ABI for details.
  145. *)
  146. function classify_as_integer_argument(real_size: aint; var classes: tx64paraclasses; byte_offset: aint): longint;
  147. var
  148. size: aint;
  149. begin
  150. size:=byte_offset+real_size;
  151. if size<=4 then
  152. classes[0]:=X86_64_INTEGERSI_CLASS
  153. else
  154. classes[0]:=X86_64_INTEGER_CLASS;
  155. if size<=8 then
  156. result:=1
  157. else
  158. begin
  159. if size<=12 then
  160. classes[1]:=X86_64_INTEGERSI_CLASS
  161. else if (size<=16) then
  162. classes[1]:=X86_64_INTEGER_CLASS
  163. else
  164. internalerror(2010021401);
  165. result:=2;
  166. end
  167. end;
  168. function classify_argument(def: tdef; varspez: tvarspez; real_size: aint; var classes: tx64paraclasses; byte_offset: aint): longint; forward;
  169. function init_aggregate_classification(def: tdef; varspez: tvarspez; out words: longint; out classes: tx64paraclasses): longint;
  170. var
  171. i: longint;
  172. begin
  173. words:=0;
  174. { win64 follows a different convention here }
  175. if (target_info.system=system_x86_64_win64) then
  176. begin
  177. if aggregate_in_registers_win64(varspez,def.size) then
  178. begin
  179. classes[0]:=X86_64_INTEGER_CLASS;
  180. result:=1;
  181. end
  182. else
  183. result:=0;
  184. exit;
  185. end;
  186. (* If the struct is larger than 32 bytes, pass it on the stack. *)
  187. if def.size > 32 then
  188. exit(0);
  189. words:=(def.size+7) div 8;
  190. (* Zero sized arrays or structures are NO_CLASS. We return 0 to
  191. signal memory class, so handle it as special case. *)
  192. if (words=0) then
  193. begin
  194. classes[0]:=X86_64_NO_CLASS;
  195. exit(1);
  196. end;
  197. { we'll be merging the classes elements with the subclasses
  198. elements, so initialise them first }
  199. for i:=low(classes) to high(classes) do
  200. classes[i]:=X86_64_NO_CLASS;
  201. result:=words;
  202. end;
  203. function classify_aggregate_element(def: tdef; varspez: tvarspez; real_size: aint; var classes: tx64paraclasses; new_byte_offset: aint): longint;
  204. var
  205. subclasses: tx64paraclasses;
  206. i,
  207. pos: longint;
  208. begin
  209. result:=classify_argument(def,varspez,real_size,subclasses,new_byte_offset mod 8);
  210. if (result=0) then
  211. exit;
  212. pos:=new_byte_offset div 8;
  213. if result-1+pos>high(classes) then
  214. internalerror(2010053108);
  215. for i:=0 to result-1 do
  216. begin
  217. classes[i+pos] :=
  218. merge_classes(subclasses[i],classes[i+pos]);
  219. end;
  220. end;
  221. function finalize_aggregate_classification(def: tdef; words: longint; var classes: tx64paraclasses): longint;
  222. var
  223. i: longint;
  224. begin
  225. if (words>2) then
  226. begin
  227. (* When size > 16 bytes, if the first one isn't
  228. X86_64_SSE_CLASS or any other ones aren't
  229. X86_64_SSEUP_CLASS, everything should be passed in
  230. memory. *)
  231. if (classes[0]<>X86_64_SSE_CLASS) then
  232. exit(0);
  233. for i:=1 to words-1 do
  234. if (classes[i]<>X86_64_SSEUP_CLASS) then
  235. exit(0);
  236. end;
  237. (* Final merger cleanup. *)
  238. (* The first one must never be X86_64_SSEUP_CLASS or
  239. X86_64_X87UP_CLASS. *)
  240. if (classes[0]=X86_64_SSEUP_CLASS) or
  241. (classes[0]=X86_64_X87UP_CLASS) then
  242. internalerror(2010021402);
  243. for i:=0 to words-1 do
  244. begin
  245. (* If one class is MEMORY, everything should be passed in
  246. memory. *)
  247. if (classes[i]=X86_64_MEMORY_CLASS) then
  248. exit(0);
  249. (* The X86_64_SSEUP_CLASS should be always preceded by
  250. X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. *)
  251. if (classes[i]=X86_64_SSEUP_CLASS) and
  252. (classes[i-1]<>X86_64_SSE_CLASS) and
  253. (classes[i-1]<>X86_64_SSEUP_CLASS) then
  254. classes[i]:=X86_64_SSE_CLASS;
  255. (* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
  256. everything should be passed in memory. *)
  257. if (classes[i]=X86_64_X87UP_CLASS) and
  258. (classes[i-1]<>X86_64_X87_CLASS) then
  259. exit(0);
  260. end;
  261. { FIXME: in case a record contains empty padding space, e.g. a
  262. "single" field followed by a "double", then we have a problem
  263. because the cgpara helpers cannot figure out that they should
  264. skip 4 bytes after storing the single (LOC_MMREGISTER with size
  265. OS_F32) to memory before storing the double -> for now scale
  266. such locations always up to 64 bits, although this loads/stores
  267. some superfluous data }
  268. { 1) the first part is 32 bit while there is still a second part }
  269. if (classes[1]<>X86_64_NO_CLASS) then
  270. case classes[0] of
  271. X86_64_INTEGERSI_CLASS:
  272. classes[0]:=X86_64_INTEGER_CLASS;
  273. X86_64_SSESF_CLASS:
  274. classes[0]:=X86_64_SSE_CLASS;
  275. end;
  276. { 2) the second part is 32 bit, but the total size is > 12 bytes }
  277. if (def.size>12) then
  278. case classes[1] of
  279. X86_64_INTEGERSI_CLASS:
  280. classes[1]:=X86_64_INTEGER_CLASS;
  281. X86_64_SSESF_CLASS:
  282. classes[1]:=X86_64_SSE_CLASS;
  283. end;
  284. result:=words;
  285. end;
  286. function classify_record(def: tdef; varspez: tvarspez; var classes: tx64paraclasses; byte_offset: aint): longint;
  287. var
  288. vs: tfieldvarsym;
  289. size,
  290. new_byte_offset: aint;
  291. i,
  292. words,
  293. num: longint;
  294. begin
  295. result:=init_aggregate_classification(def,varspez,words,classes);
  296. if (words=0) then
  297. exit;
  298. (* Merge the fields of the structure. *)
  299. for i:=0 to tabstractrecorddef(def).symtable.symlist.count-1 do
  300. begin
  301. if tsym(tabstractrecorddef(def).symtable.symlist[i]).typ<>fieldvarsym then
  302. continue;
  303. vs:=tfieldvarsym(tabstractrecorddef(def).symtable.symlist[i]);
  304. num:=-1;
  305. if not tabstractrecordsymtable(tabstractrecorddef(def).symtable).is_packed then
  306. begin
  307. new_byte_offset:=byte_offset+vs.fieldoffset;
  308. size:=vs.vardef.size;
  309. end
  310. else
  311. begin
  312. new_byte_offset:=byte_offset+vs.fieldoffset div 8;
  313. if (vs.vardef.typ in [orddef,enumdef]) then
  314. { calculate the number of bytes spanned by
  315. this bitpacked field }
  316. size:=((vs.fieldoffset+vs.vardef.packedbitsize+7) div 8)-(vs.fieldoffset div 8)
  317. else
  318. size:=vs.vardef.size
  319. end;
  320. num:=classify_aggregate_element(vs.vardef,varspez,size,classes,new_byte_offset);
  321. if (num=0) then
  322. exit(0);
  323. end;
  324. result:=finalize_aggregate_classification(def,words,classes);
  325. end;
  326. function classify_normal_array(def: tarraydef; varspez: tvarspez; var classes: tx64paraclasses; byte_offset: aint): longint;
  327. var
  328. i, elecount: aword;
  329. size,
  330. elesize,
  331. new_byte_offset,
  332. bitoffset: aint;
  333. words,
  334. num: longint;
  335. isbitpacked: boolean;
  336. begin
  337. result:=init_aggregate_classification(def,varspez,words,classes);
  338. if (words=0) then
  339. exit;
  340. isbitpacked:=is_packed_array(def);
  341. if not isbitpacked then
  342. begin
  343. elesize:=def.elesize;
  344. size:=elesize;
  345. end
  346. else
  347. begin
  348. elesize:=def.elepackedbitsize;
  349. bitoffset:=0;
  350. end;
  351. (* Merge the elements of the array. *)
  352. i:=0;
  353. elecount:=def.elecount;
  354. repeat
  355. if not isbitpacked then
  356. begin
  357. { size does not change }
  358. new_byte_offset:=byte_offset+i*elesize;
  359. end
  360. else
  361. begin
  362. { calculate the number of bytes spanned by this bitpacked
  363. element }
  364. size:=((bitoffset+elesize+7) div 8)-(bitoffset div 8);
  365. new_byte_offset:=byte_offset+(elesize*i) div 8;
  366. { bit offset of next element }
  367. inc(bitoffset,elesize);
  368. end;
  369. num:=classify_aggregate_element(def.elementdef,varspez,size,classes,new_byte_offset);
  370. if (num=0) then
  371. exit(0);
  372. inc(i);
  373. until (i=elecount);
  374. result:=finalize_aggregate_classification(def,words,classes);
  375. end;
  376. function classify_argument(def: tdef; varspez: tvarspez; real_size: aint; var classes: tx64paraclasses; byte_offset: aint): longint;
  377. begin
  378. case def.typ of
  379. orddef,
  380. enumdef,
  381. pointerdef,
  382. classrefdef:
  383. result:=classify_as_integer_argument(real_size,classes,byte_offset);
  384. formaldef:
  385. result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset);
  386. floatdef:
  387. begin
  388. case tfloatdef(def).floattype of
  389. s32real:
  390. begin
  391. if byte_offset=0 then
  392. classes[0]:=X86_64_SSESF_CLASS
  393. else
  394. { if we have e.g. a record with two successive "single"
  395. fields, we need a 64 bit rather than a 32 bit load }
  396. classes[0]:=X86_64_SSE_CLASS;
  397. result:=1;
  398. end;
  399. s64real:
  400. begin
  401. classes[0]:=X86_64_SSEDF_CLASS;
  402. result:=1;
  403. end;
  404. s80real,
  405. sc80real:
  406. begin
  407. classes[0]:=X86_64_X87_CLASS;
  408. classes[1]:=X86_64_X87UP_CLASS;
  409. result:=2;
  410. end;
  411. s64comp,
  412. s64currency:
  413. begin
  414. classes[0]:=X86_64_INTEGER_CLASS;
  415. result:=1;
  416. end;
  417. s128real:
  418. begin
  419. classes[0]:=X86_64_SSE_CLASS;
  420. classes[1]:=X86_64_SSEUP_CLASS;
  421. result:=2;
  422. end;
  423. else
  424. internalerror(2010060301);
  425. end;
  426. end;
  427. recorddef:
  428. result:=classify_record(def,varspez,classes,byte_offset);
  429. objectdef:
  430. begin
  431. if is_object(def) then
  432. { pass by reference, like ppc and i386 }
  433. result:=0
  434. else
  435. { all kinds of pointer types: class, objcclass, interface, ... }
  436. result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset);
  437. end;
  438. setdef:
  439. begin
  440. if is_smallset(def) then
  441. result:=classify_as_integer_argument(def.size,classes,byte_offset)
  442. else
  443. result:=0;
  444. end;
  445. stringdef:
  446. begin
  447. if (tstringdef(def).stringtype in [st_shortstring,st_longstring]) then
  448. result:=0
  449. else
  450. result:=classify_as_integer_argument(def.size,classes,byte_offset);
  451. end;
  452. arraydef:
  453. begin
  454. { a dynamic array is treated like a pointer }
  455. if is_dynamic_array(def) then
  456. result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset)
  457. { other special arrays are passed on the stack }
  458. else if is_open_array(def) or
  459. is_array_of_const(def) then
  460. result:=0
  461. else
  462. { normal array }
  463. result:=classify_normal_array(tarraydef(def),varspez,classes,byte_offset);
  464. end;
  465. { the file record is definitely too big }
  466. filedef:
  467. result:=0;
  468. procvardef:
  469. begin
  470. if (po_methodpointer in tprocvardef(def).procoptions) then
  471. begin
  472. { treat as TMethod record }
  473. def:=search_system_type('TMETHOD').typedef;
  474. result:=classify_argument(def,varspez,def.size,classes,byte_offset);
  475. end
  476. else
  477. { pointer }
  478. result:=classify_as_integer_argument(def.size,classes,byte_offset);
  479. end;
  480. variantdef:
  481. begin
  482. { same as tvardata record }
  483. def:=search_system_type('TVARDATA').typedef;
  484. result:=classify_argument(def,varspez,def.size,classes,byte_offset);
  485. end;
  486. else
  487. internalerror(2010021405);
  488. end;
  489. end;
  490. procedure getvalueparaloc(varspez:tvarspez;def:tdef;var loc1,loc2:tx64paraclass);
  491. var
  492. size: aint;
  493. i: longint;
  494. classes: tx64paraclasses;
  495. numclasses: longint;
  496. begin
  497. { init the classes array, because even if classify_argument inits only
  498. one element we copy both to loc1/loc2 in case "1" is returned }
  499. for i:=low(classes) to high(classes) do
  500. classes[i]:=X86_64_NO_CLASS;
  501. { def.size internalerrors for open arrays and dynamic arrays, since
  502. their size cannot be determined at compile-time.
  503. classify_argument does not look at the realsize argument for arrays
  504. cases, but we obviously do have to pass something... }
  505. if is_special_array(def) then
  506. size:=-1
  507. else
  508. size:=def.size;
  509. numclasses:=classify_argument(def,varspez,size,classes,0);
  510. case numclasses of
  511. 0:
  512. begin
  513. loc1:=X86_64_MEMORY_CLASS;
  514. loc2:=X86_64_NO_CLASS;
  515. end;
  516. 1,2:
  517. begin
  518. { If the class is X87, X87UP or COMPLEX_X87, it is passed in memory }
  519. if classes[0] in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
  520. classes[0]:=X86_64_MEMORY_CLASS;
  521. if classes[1] in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
  522. classes[1]:=X86_64_MEMORY_CLASS;
  523. loc1:=classes[0];
  524. loc2:=classes[1];
  525. end
  526. else
  527. { 4 can only happen for _m256 vectors, not yet supported }
  528. internalerror(2010021501);
  529. end;
  530. end;
  531. function tx86_64paramanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
  532. var
  533. classes: tx64paraclasses;
  534. numclasses: longint;
  535. begin
  536. if (tf_safecall_exceptions in target_info.flags) and
  537. (calloption=pocall_safecall) then
  538. begin
  539. result := true;
  540. exit;
  541. end;
  542. case def.typ of
  543. { for records it depends on their contents and size }
  544. recorddef,
  545. { make sure we handle 'procedure of object' correctly }
  546. procvardef:
  547. begin
  548. numclasses:=classify_argument(def,vs_value,def.size,classes,0);
  549. result:=(numclasses=0);
  550. end;
  551. else
  552. result:=inherited ret_in_param(def,calloption);
  553. end;
  554. end;
  555. function tx86_64paramanager.param_use_paraloc(const cgpara:tcgpara):boolean;
  556. var
  557. paraloc : pcgparalocation;
  558. begin
  559. if not assigned(cgpara.location) then
  560. internalerror(200410102);
  561. result:=true;
  562. { All locations are LOC_REFERENCE }
  563. paraloc:=cgpara.location;
  564. while assigned(paraloc) do
  565. begin
  566. if (paraloc^.loc<>LOC_REFERENCE) then
  567. begin
  568. result:=false;
  569. exit;
  570. end;
  571. paraloc:=paraloc^.next;
  572. end;
  573. end;
  574. { true if a parameter is too large to copy and only the address is pushed }
  575. function tx86_64paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  576. var
  577. classes: tx64paraclasses;
  578. numclasses: longint;
  579. begin
  580. result:=false;
  581. { var,out,constref always require address }
  582. if varspez in [vs_var,vs_out,vs_constref] then
  583. begin
  584. result:=true;
  585. exit;
  586. end;
  587. { Only vs_const, vs_value here }
  588. case def.typ of
  589. formaldef :
  590. result:=true;
  591. recorddef :
  592. begin
  593. { MetroWerks Pascal: const records always passed by reference
  594. (for Mac OS X interfaces) }
  595. if (calloption=pocall_mwpascal) and
  596. (varspez=vs_const) then
  597. result:=true
  598. { Win ABI depends on size to pass it in a register or not }
  599. else if (target_info.system=system_x86_64_win64) then
  600. result:=not aggregate_in_registers_win64(varspez,def.size)
  601. { pass constant parameters that would be passed via memory by
  602. reference for non-cdecl/cppdecl, and make sure that the tmethod
  603. record (size=16) is passed the same way as a complex procvar }
  604. else if ((varspez=vs_const) and
  605. not(calloption in [pocall_cdecl,pocall_cppdecl])) or
  606. (def.size=16) then
  607. begin
  608. numclasses:=classify_argument(def,vs_value,def.size,classes,0);
  609. result:=numclasses=0;
  610. end
  611. else
  612. { SysV ABI always passes it as value parameter }
  613. result:=false;
  614. end;
  615. arraydef :
  616. begin
  617. { cdecl array of const need to be ignored and therefor be puhsed
  618. as value parameter with length 0 }
  619. if ((calloption in [pocall_cdecl,pocall_cppdecl]) and
  620. is_array_of_const(def)) or
  621. is_dynamic_array(def) then
  622. result:=false
  623. else
  624. { pass all arrays by reference to be compatible with C (passing
  625. an array by value (= copying it on the stack) does not exist,
  626. because an array is the same as a pointer there }
  627. result:=true
  628. end;
  629. objectdef :
  630. begin
  631. { don't treat objects like records, because we only know wheter
  632. or not they'll have a VMT after the entire object is parsed
  633. -> if they are used as function result from one of their own
  634. methods, their size can still change after we've determined
  635. whether this function result should be returned by reference or
  636. by value }
  637. if is_object(def) then
  638. result:=true;
  639. end;
  640. variantdef,
  641. stringdef,
  642. procvardef,
  643. setdef :
  644. begin
  645. numclasses:=classify_argument(def,vs_value,def.size,classes,0);
  646. result:=numclasses=0;
  647. end;
  648. end;
  649. end;
  650. function tx86_64paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  651. begin
  652. if target_info.system=system_x86_64_win64 then
  653. result:=[RS_RAX,RS_RCX,RS_RDX,RS_R8,RS_R9,RS_R10,RS_R11]
  654. else
  655. result:=[RS_RAX,RS_RCX,RS_RDX,RS_RSI,RS_RDI,RS_R8,RS_R9,RS_R10,RS_R11];
  656. end;
  657. function tx86_64paramanager.get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;
  658. begin
  659. if target_info.system=system_x86_64_win64 then
  660. result:=[RS_XMM0..RS_XMM5]
  661. else
  662. result:=[RS_XMM0..RS_XMM15];
  663. end;
  664. function tx86_64paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
  665. begin
  666. result:=[RS_ST0..RS_ST7];
  667. end;
  668. procedure tx86_64paramanager.getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);
  669. var
  670. paraloc : pcgparalocation;
  671. begin
  672. cgpara.reset;
  673. cgpara.size:=def_cgsize(def);
  674. cgpara.intsize:=tcgsize2size[cgpara.size];
  675. cgpara.alignment:=get_para_align(calloption);
  676. cgpara.def:=def;
  677. paraloc:=cgpara.add_location;
  678. with paraloc^ do
  679. begin
  680. size:=OS_INT;
  681. if target_info.system=system_x86_64_win64 then
  682. begin
  683. if nr<1 then
  684. internalerror(200304303)
  685. else if nr<=high(paraintsupregs_winx64)+1 then
  686. begin
  687. loc:=LOC_REGISTER;
  688. register:=newreg(R_INTREGISTER,paraintsupregs_winx64[nr-1],R_SUBWHOLE);
  689. end
  690. else
  691. begin
  692. loc:=LOC_REFERENCE;
  693. reference.index:=NR_STACK_POINTER_REG;
  694. reference.offset:=(nr-6)*sizeof(aint);
  695. end;
  696. end
  697. else
  698. begin
  699. if nr<1 then
  700. internalerror(200304303)
  701. else if nr<=high(paraintsupregs)+1 then
  702. begin
  703. loc:=LOC_REGISTER;
  704. register:=newreg(R_INTREGISTER,paraintsupregs[nr-1],R_SUBWHOLE);
  705. end
  706. else
  707. begin
  708. loc:=LOC_REFERENCE;
  709. reference.index:=NR_STACK_POINTER_REG;
  710. reference.offset:=(nr-6)*sizeof(aint);
  711. end;
  712. end;
  713. end;
  714. end;
  715. procedure tx86_64paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  716. begin
  717. p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
  718. end;
  719. function tx86_64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
  720. const
  721. intretregs: array[0..1] of tregister = (NR_FUNCTION_RETURN_REG,NR_FUNCTION_RETURN_REG_HIGH);
  722. mmretregs: array[0..1] of tregister = (NR_MM_RESULT_REG,NR_MM_RESULT_REG_HIGH);
  723. var
  724. classes: tx64paraclasses;
  725. i,
  726. numclasses: longint;
  727. intretregidx,
  728. mmretregidx: longint;
  729. retcgsize : tcgsize;
  730. paraloc : pcgparalocation;
  731. begin
  732. if set_common_funcretloc_info(p,def,retcgsize,result) then
  733. exit;
  734. { integer sizes < 32 bit have to be sign/zero extended to 32 bit on
  735. the callee side (caller can expect those bits are valid) }
  736. if (side=calleeside) and
  737. (retcgsize in [OS_8,OS_S8,OS_16,OS_S16]) then
  738. begin
  739. retcgsize:=OS_S32;
  740. result.def:=s32inttype;
  741. result.intsize:=4;
  742. result.size:=retcgsize;
  743. end;
  744. { Return in FPU register? -> don't use classify_argument(), because
  745. currency and comp need special treatment here (they are integer class
  746. when passing as parameter, but LOC_FPUREGISTER as function result) }
  747. if def.typ=floatdef then
  748. begin
  749. paraloc:=result.add_location;
  750. case tfloatdef(def).floattype of
  751. s32real:
  752. begin
  753. paraloc^.loc:=LOC_MMREGISTER;
  754. paraloc^.register:=newreg(R_MMREGISTER,RS_MM_RESULT_REG,R_SUBMMS);
  755. paraloc^.size:=OS_F32;
  756. end;
  757. s64real:
  758. begin
  759. paraloc^.loc:=LOC_MMREGISTER;
  760. paraloc^.register:=newreg(R_MMREGISTER,RS_MM_RESULT_REG,R_SUBMMD);
  761. paraloc^.size:=OS_F64;
  762. end;
  763. { the first two only exist on targets with an x87, on others
  764. they are replace by int64 }
  765. s64currency,
  766. s64comp,
  767. s80real,
  768. sc80real:
  769. begin
  770. paraloc^.loc:=LOC_FPUREGISTER;
  771. paraloc^.register:=NR_FPU_RESULT_REG;
  772. paraloc^.size:=retcgsize;
  773. end;
  774. else
  775. internalerror(200405034);
  776. end;
  777. end
  778. else
  779. { Return in register }
  780. begin
  781. numclasses:=classify_argument(def,vs_value,def.size,classes,0);
  782. { this would mean a memory return }
  783. if (numclasses=0) then
  784. internalerror(2010021502);
  785. { this would mean an _m256 vector (valid, but not yet supported) }
  786. if (numclasses>2) then
  787. internalerror(2010021503);
  788. intretregidx:=0;
  789. mmretregidx:=0;
  790. for i:=0 to numclasses-1 do
  791. begin
  792. paraloc:=result.add_location;
  793. case classes[i] of
  794. X86_64_INTEGERSI_CLASS,
  795. X86_64_INTEGER_CLASS:
  796. begin
  797. paraloc^.loc:=LOC_REGISTER;
  798. paraloc^.register:=intretregs[intretregidx];
  799. if classes[i]=X86_64_INTEGER_CLASS then
  800. paraloc^.size:=OS_64
  801. else if result.intsize in [1,2,4] then
  802. paraloc^.size:=retcgsize
  803. else
  804. paraloc^.size:=OS_32;
  805. setsubreg(paraloc^.register,cgsize2subreg(R_INTREGISTER,paraloc^.size));
  806. inc(intretregidx);
  807. end;
  808. X86_64_SSE_CLASS,
  809. X86_64_SSEUP_CLASS,
  810. X86_64_SSESF_CLASS,
  811. X86_64_SSEDF_CLASS:
  812. begin
  813. paraloc^.loc:=LOC_MMREGISTER;
  814. paraloc^.register:=mmretregs[mmretregidx];
  815. case classes[i] of
  816. X86_64_SSESF_CLASS:
  817. begin
  818. setsubreg(paraloc^.register,R_SUBMMS);
  819. paraloc^.size:=OS_F32;
  820. end;
  821. X86_64_SSEDF_CLASS:
  822. begin
  823. setsubreg(paraloc^.register,R_SUBMMD);
  824. paraloc^.size:=OS_F64;
  825. end;
  826. else
  827. begin
  828. setsubreg(paraloc^.register,R_SUBMMWHOLE);
  829. paraloc^.size:=OS_M64;
  830. end;
  831. end;
  832. inc(mmretregidx);
  833. end;
  834. X86_64_NO_CLASS:
  835. begin
  836. { empty record/array }
  837. if (i<>0) or
  838. (numclasses<>1) then
  839. internalerror(2010060302);
  840. paraloc^.loc:=LOC_VOID;
  841. end;
  842. else
  843. internalerror(2010021504);
  844. end;
  845. end;
  846. end;
  847. end;
  848. procedure tx86_64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
  849. var intparareg,mmparareg,parasize:longint;varargsparas: boolean);
  850. var
  851. hp : tparavarsym;
  852. paradef : tdef;
  853. paraloc : pcgparalocation;
  854. subreg : tsubregister;
  855. pushaddr : boolean;
  856. paracgsize : tcgsize;
  857. loc : array[1..2] of tx64paraclass;
  858. needintloc,
  859. needmmloc,
  860. paralen,
  861. locidx,
  862. i,
  863. varalign,
  864. paraalign : longint;
  865. begin
  866. paraalign:=get_para_align(p.proccalloption);
  867. { Register parameters are assigned from left to right }
  868. for i:=0 to paras.count-1 do
  869. begin
  870. hp:=tparavarsym(paras[i]);
  871. paradef:=hp.vardef;
  872. pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
  873. if pushaddr then
  874. begin
  875. loc[1]:=X86_64_INTEGER_CLASS;
  876. loc[2]:=X86_64_NO_CLASS;
  877. paracgsize:=OS_ADDR;
  878. paralen:=sizeof(pint);
  879. paradef:=getpointerdef(paradef);
  880. end
  881. else
  882. begin
  883. getvalueparaloc(hp.varspez,paradef,loc[1],loc[2]);
  884. paralen:=push_size(hp.varspez,paradef,p.proccalloption);
  885. paracgsize:=def_cgsize(paradef);
  886. { integer sizes < 32 bit have to be sign/zero extended to 32 bit
  887. on the caller side }
  888. if (side=callerside) and
  889. (paracgsize in [OS_8,OS_S8,OS_16,OS_S16]) then
  890. begin
  891. paracgsize:=OS_S32;
  892. paralen:=4;
  893. paradef:=s32inttype;
  894. end;
  895. end;
  896. { cheat for now, we should copy the value to an mm reg as well (FK) }
  897. if varargsparas and
  898. (target_info.system = system_x86_64_win64) and
  899. (paradef.typ = floatdef) then
  900. begin
  901. loc[2]:=X86_64_NO_CLASS;
  902. if paracgsize=OS_F64 then
  903. begin
  904. loc[1]:=X86_64_INTEGER_CLASS;
  905. paracgsize:=OS_64;
  906. paradef:=u64inttype;
  907. end
  908. else
  909. begin
  910. loc[1]:=X86_64_INTEGERSI_CLASS;
  911. paracgsize:=OS_32;
  912. paradef:=u32inttype;
  913. end;
  914. end;
  915. hp.paraloc[side].reset;
  916. hp.paraloc[side].size:=paracgsize;
  917. hp.paraloc[side].intsize:=paralen;
  918. hp.paraloc[side].Alignment:=paraalign;
  919. hp.paraloc[side].def:=paradef;
  920. if paralen>0 then
  921. begin
  922. { Enough registers free? }
  923. needintloc:=0;
  924. needmmloc:=0;
  925. for locidx:=low(loc) to high(loc) do
  926. case loc[locidx] of
  927. X86_64_INTEGER_CLASS,
  928. X86_64_INTEGERSI_CLASS:
  929. inc(needintloc);
  930. X86_64_SSE_CLASS,
  931. X86_64_SSESF_CLASS,
  932. X86_64_SSEDF_CLASS,
  933. X86_64_SSEUP_CLASS:
  934. inc(needmmloc);
  935. end;
  936. { the "-1" is because we can also use the current register }
  937. if ((target_info.system=system_x86_64_win64) and
  938. ((intparareg+needintloc-1 > high(paraintsupregs_winx64)) or
  939. (mmparareg+needmmloc-1 > high(parammsupregs_winx64)))) or
  940. ((target_info.system<>system_x86_64_win64) and
  941. ((intparareg+needintloc-1 > high(paraintsupregs)) or
  942. (mmparareg+needmmloc-1 > high(parammsupregs)))) then
  943. begin
  944. { If there are no registers available for any
  945. eightbyte of an argument, the whole argument is
  946. passed on the stack. }
  947. loc[low(loc)]:=X86_64_MEMORY_CLASS;
  948. for locidx:=succ(low(loc)) to high(loc) do
  949. loc[locidx]:=X86_64_NO_CLASS;
  950. end;
  951. locidx:=1;
  952. while (paralen>0) do
  953. begin
  954. if locidx>2 then
  955. internalerror(200501283);
  956. { Allocate }
  957. case loc[locidx] of
  958. X86_64_INTEGER_CLASS,
  959. X86_64_INTEGERSI_CLASS:
  960. begin
  961. paraloc:=hp.paraloc[side].add_location;
  962. paraloc^.loc:=LOC_REGISTER;
  963. if (paracgsize=OS_NO) or (loc[2]<>X86_64_NO_CLASS) then
  964. begin
  965. if loc[locidx]=X86_64_INTEGER_CLASS then
  966. begin
  967. paraloc^.size:=OS_INT;
  968. subreg:=R_SUBWHOLE;
  969. end
  970. else
  971. begin
  972. paraloc^.size:=OS_32;
  973. subreg:=R_SUBD;
  974. end;
  975. end
  976. else
  977. begin
  978. paraloc^.size:=paracgsize;
  979. { s64comp is pushed in an int register }
  980. if paraloc^.size=OS_C64 then
  981. paraloc^.size:=OS_64;
  982. subreg:=cgsize2subreg(R_INTREGISTER,paraloc^.size);
  983. end;
  984. { winx64 uses different registers }
  985. if target_info.system=system_x86_64_win64 then
  986. paraloc^.register:=newreg(R_INTREGISTER,paraintsupregs_winx64[intparareg],subreg)
  987. else
  988. paraloc^.register:=newreg(R_INTREGISTER,paraintsupregs[intparareg],subreg);
  989. { matching mm register must be skipped }
  990. if target_info.system=system_x86_64_win64 then
  991. inc(mmparareg);
  992. inc(intparareg);
  993. dec(paralen,tcgsize2size[paraloc^.size]);
  994. end;
  995. X86_64_SSE_CLASS,
  996. X86_64_SSESF_CLASS,
  997. X86_64_SSEDF_CLASS,
  998. X86_64_SSEUP_CLASS:
  999. begin
  1000. paraloc:=hp.paraloc[side].add_location;
  1001. paraloc^.loc:=LOC_MMREGISTER;
  1002. case loc[locidx] of
  1003. X86_64_SSESF_CLASS:
  1004. begin
  1005. subreg:=R_SUBMMS;
  1006. paraloc^.size:=OS_F32;
  1007. end;
  1008. X86_64_SSEDF_CLASS:
  1009. begin
  1010. subreg:=R_SUBMMD;
  1011. paraloc^.size:=OS_F64;
  1012. end;
  1013. else
  1014. begin
  1015. subreg:=R_SUBMMWHOLE;
  1016. paraloc^.size:=OS_M64;
  1017. end;
  1018. end;
  1019. { winx64 uses different registers }
  1020. if target_info.system=system_x86_64_win64 then
  1021. paraloc^.register:=newreg(R_MMREGISTER,parammsupregs_winx64[mmparareg],subreg)
  1022. else
  1023. paraloc^.register:=newreg(R_MMREGISTER,parammsupregs[mmparareg],subreg);
  1024. { matching int register must be skipped }
  1025. if target_info.system=system_x86_64_win64 then
  1026. inc(intparareg);
  1027. inc(mmparareg);
  1028. dec(paralen,tcgsize2size[paraloc^.size]);
  1029. end;
  1030. X86_64_MEMORY_CLASS :
  1031. begin
  1032. paraloc:=hp.paraloc[side].add_location;
  1033. paraloc^.loc:=LOC_REFERENCE;
  1034. {Hack alert!!! We should modify int_cgsize to handle OS_128,
  1035. however, since int_cgsize is called in many places in the
  1036. compiler where only a few can already handle OS_128, fixing it
  1037. properly is out of the question to release 2.2.0 in time. (DM)}
  1038. if paracgsize=OS_128 then
  1039. if paralen=8 then
  1040. paraloc^.size:=OS_64
  1041. else if paralen=16 then
  1042. paraloc^.size:=OS_128
  1043. else
  1044. internalerror(200707143)
  1045. else if paracgsize in [OS_F32,OS_F64,OS_F80,OS_F128] then
  1046. paraloc^.size:=int_float_cgsize(paralen)
  1047. else
  1048. paraloc^.size:=int_cgsize(paralen);
  1049. if side=callerside then
  1050. paraloc^.reference.index:=NR_STACK_POINTER_REG
  1051. else
  1052. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  1053. varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
  1054. paraloc^.reference.offset:=parasize;
  1055. parasize:=align(parasize+paralen,varalign);
  1056. paralen:=0;
  1057. end;
  1058. else
  1059. internalerror(2010053113);
  1060. end;
  1061. if (locidx<2) and
  1062. (loc[locidx+1]<>X86_64_NO_CLASS) then
  1063. inc(locidx);
  1064. end;
  1065. end
  1066. else
  1067. begin
  1068. paraloc:=hp.paraloc[side].add_location;
  1069. paraloc^.loc:=LOC_VOID;
  1070. end;
  1071. end;
  1072. { Register parameters are assigned from left-to-right, but the
  1073. offsets on the stack are right-to-left. There is no need
  1074. to reverse the offset, only adapt the calleeside with the
  1075. start offset of the first param on the stack }
  1076. if side=calleeside then
  1077. begin
  1078. for i:=0 to paras.count-1 do
  1079. begin
  1080. hp:=tparavarsym(paras[i]);
  1081. paraloc:=hp.paraloc[side].location;
  1082. while paraloc<>nil do
  1083. begin
  1084. with paraloc^ do
  1085. if (loc=LOC_REFERENCE) then
  1086. inc(reference.offset,target_info.first_parm_offset);
  1087. paraloc:=paraloc^.next;
  1088. end;
  1089. end;
  1090. end;
  1091. end;
  1092. function tx86_64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  1093. var
  1094. intparareg,mmparareg,
  1095. parasize : longint;
  1096. begin
  1097. intparareg:=0;
  1098. mmparareg:=0;
  1099. if target_info.system=system_x86_64_win64 then
  1100. parasize:=4*8
  1101. else
  1102. parasize:=0;
  1103. { calculate the registers for the normal parameters }
  1104. create_paraloc_info_intern(p,callerside,p.paras,intparareg,mmparareg,parasize,false);
  1105. { append the varargs }
  1106. create_paraloc_info_intern(p,callerside,varargspara,intparareg,mmparareg,parasize,true);
  1107. { store used no. of SSE registers, that needs to be passed in %AL }
  1108. varargspara.mmregsused:=mmparareg;
  1109. result:=parasize;
  1110. end;
  1111. function tx86_64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  1112. var
  1113. intparareg,mmparareg,
  1114. parasize : longint;
  1115. begin
  1116. intparareg:=0;
  1117. mmparareg:=0;
  1118. if target_info.system=system_x86_64_win64 then
  1119. parasize:=4*8
  1120. else
  1121. parasize:=0;
  1122. create_paraloc_info_intern(p,side,p.paras,intparareg,mmparareg,parasize,false);
  1123. { Create Function result paraloc }
  1124. create_funcretloc_info(p,side);
  1125. { We need to return the size allocated on the stack }
  1126. result:=parasize;
  1127. end;
  1128. begin
  1129. paramanager:=tx86_64paramanager.create;
  1130. end.