cpupara.pas 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230
  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;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;var cgpara:TCGPara);
  669. var
  670. paraloc : pcgparalocation;
  671. begin
  672. cgpara.reset;
  673. cgpara.size:=OS_ADDR;
  674. cgpara.intsize:=sizeof(pint);
  675. cgpara.alignment:=get_para_align(calloption);
  676. paraloc:=cgpara.add_location;
  677. with paraloc^ do
  678. begin
  679. size:=OS_INT;
  680. if target_info.system=system_x86_64_win64 then
  681. begin
  682. if nr<1 then
  683. internalerror(200304303)
  684. else if nr<=high(paraintsupregs_winx64)+1 then
  685. begin
  686. loc:=LOC_REGISTER;
  687. register:=newreg(R_INTREGISTER,paraintsupregs_winx64[nr-1],R_SUBWHOLE);
  688. end
  689. else
  690. begin
  691. loc:=LOC_REFERENCE;
  692. reference.index:=NR_STACK_POINTER_REG;
  693. reference.offset:=(nr-6)*sizeof(aint);
  694. end;
  695. end
  696. else
  697. begin
  698. if nr<1 then
  699. internalerror(200304303)
  700. else if nr<=high(paraintsupregs)+1 then
  701. begin
  702. loc:=LOC_REGISTER;
  703. register:=newreg(R_INTREGISTER,paraintsupregs[nr-1],R_SUBWHOLE);
  704. end
  705. else
  706. begin
  707. loc:=LOC_REFERENCE;
  708. reference.index:=NR_STACK_POINTER_REG;
  709. reference.offset:=(nr-6)*sizeof(aint);
  710. end;
  711. end;
  712. end;
  713. end;
  714. procedure tx86_64paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  715. begin
  716. p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
  717. end;
  718. function tx86_64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
  719. const
  720. intretregs: array[0..1] of tregister = (NR_FUNCTION_RETURN_REG,NR_FUNCTION_RETURN_REG_HIGH);
  721. mmretregs: array[0..1] of tregister = (NR_MM_RESULT_REG,NR_MM_RESULT_REG_HIGH);
  722. var
  723. classes: tx64paraclasses;
  724. i,
  725. numclasses: longint;
  726. intretregidx,
  727. mmretregidx: longint;
  728. retcgsize : tcgsize;
  729. paraloc : pcgparalocation;
  730. begin
  731. if set_common_funcretloc_info(p,def,retcgsize,result) then
  732. exit;
  733. { integer sizes < 32 bit have to be sign/zero extended to 32 bit on
  734. the callee side (caller can expect those bits are valid) }
  735. if (side=calleeside) and
  736. (retcgsize in [OS_8,OS_S8,OS_16,OS_S16]) then
  737. begin
  738. retcgsize:=OS_S32;
  739. result.def:=s32inttype;
  740. result.intsize:=4;
  741. result.size:=retcgsize;
  742. end;
  743. { Return in FPU register? -> don't use classify_argument(), because
  744. currency and comp need special treatment here (they are integer class
  745. when passing as parameter, but LOC_FPUREGISTER as function result) }
  746. if def.typ=floatdef then
  747. begin
  748. paraloc:=result.add_location;
  749. case tfloatdef(def).floattype of
  750. s32real:
  751. begin
  752. paraloc^.loc:=LOC_MMREGISTER;
  753. paraloc^.register:=newreg(R_MMREGISTER,RS_MM_RESULT_REG,R_SUBMMS);
  754. paraloc^.size:=OS_F32;
  755. end;
  756. s64real:
  757. begin
  758. paraloc^.loc:=LOC_MMREGISTER;
  759. paraloc^.register:=newreg(R_MMREGISTER,RS_MM_RESULT_REG,R_SUBMMD);
  760. paraloc^.size:=OS_F64;
  761. end;
  762. { the first two only exist on targets with an x87, on others
  763. they are replace by int64 }
  764. s64currency,
  765. s64comp,
  766. s80real,
  767. sc80real:
  768. begin
  769. paraloc^.loc:=LOC_FPUREGISTER;
  770. paraloc^.register:=NR_FPU_RESULT_REG;
  771. paraloc^.size:=retcgsize;
  772. end;
  773. else
  774. internalerror(200405034);
  775. end;
  776. end
  777. else
  778. { Return in register }
  779. begin
  780. numclasses:=classify_argument(def,vs_value,def.size,classes,0);
  781. { this would mean a memory return }
  782. if (numclasses=0) then
  783. internalerror(2010021502);
  784. { this would mean an _m256 vector (valid, but not yet supported) }
  785. if (numclasses>2) then
  786. internalerror(2010021503);
  787. intretregidx:=0;
  788. mmretregidx:=0;
  789. for i:=0 to numclasses-1 do
  790. begin
  791. paraloc:=result.add_location;
  792. case classes[i] of
  793. X86_64_INTEGERSI_CLASS,
  794. X86_64_INTEGER_CLASS:
  795. begin
  796. paraloc^.loc:=LOC_REGISTER;
  797. paraloc^.register:=intretregs[intretregidx];
  798. if classes[i]=X86_64_INTEGER_CLASS then
  799. paraloc^.size:=OS_64
  800. else if result.intsize in [1,2,4] then
  801. paraloc^.size:=retcgsize
  802. else
  803. paraloc^.size:=OS_32;
  804. setsubreg(paraloc^.register,cgsize2subreg(R_INTREGISTER,paraloc^.size));
  805. inc(intretregidx);
  806. end;
  807. X86_64_SSE_CLASS,
  808. X86_64_SSEUP_CLASS,
  809. X86_64_SSESF_CLASS,
  810. X86_64_SSEDF_CLASS:
  811. begin
  812. paraloc^.loc:=LOC_MMREGISTER;
  813. paraloc^.register:=mmretregs[mmretregidx];
  814. case classes[i] of
  815. X86_64_SSESF_CLASS:
  816. begin
  817. setsubreg(paraloc^.register,R_SUBMMS);
  818. paraloc^.size:=OS_F32;
  819. end;
  820. X86_64_SSEDF_CLASS:
  821. begin
  822. setsubreg(paraloc^.register,R_SUBMMD);
  823. paraloc^.size:=OS_F64;
  824. end;
  825. else
  826. begin
  827. setsubreg(paraloc^.register,R_SUBMMWHOLE);
  828. paraloc^.size:=OS_M64;
  829. end;
  830. end;
  831. inc(mmretregidx);
  832. end;
  833. X86_64_NO_CLASS:
  834. begin
  835. { empty record/array }
  836. if (i<>0) or
  837. (numclasses<>1) then
  838. internalerror(2010060302);
  839. paraloc^.loc:=LOC_VOID;
  840. end;
  841. else
  842. internalerror(2010021504);
  843. end;
  844. end;
  845. end;
  846. end;
  847. procedure tx86_64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
  848. var intparareg,mmparareg,parasize:longint;varargsparas: boolean);
  849. var
  850. hp : tparavarsym;
  851. paradef : tdef;
  852. paraloc : pcgparalocation;
  853. subreg : tsubregister;
  854. pushaddr : boolean;
  855. paracgsize : tcgsize;
  856. loc : array[1..2] of tx64paraclass;
  857. needintloc,
  858. needmmloc,
  859. paralen,
  860. locidx,
  861. i,
  862. varalign,
  863. paraalign : longint;
  864. begin
  865. paraalign:=get_para_align(p.proccalloption);
  866. { Register parameters are assigned from left to right }
  867. for i:=0 to paras.count-1 do
  868. begin
  869. hp:=tparavarsym(paras[i]);
  870. paradef:=hp.vardef;
  871. pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
  872. if pushaddr then
  873. begin
  874. loc[1]:=X86_64_INTEGER_CLASS;
  875. loc[2]:=X86_64_NO_CLASS;
  876. paracgsize:=OS_ADDR;
  877. paralen:=sizeof(pint);
  878. paradef:=getpointerdef(paradef);
  879. end
  880. else
  881. begin
  882. getvalueparaloc(hp.varspez,paradef,loc[1],loc[2]);
  883. paralen:=push_size(hp.varspez,paradef,p.proccalloption);
  884. paracgsize:=def_cgsize(paradef);
  885. { integer sizes < 32 bit have to be sign/zero extended to 32 bit
  886. on the caller side }
  887. if (side=callerside) and
  888. (paracgsize in [OS_8,OS_S8,OS_16,OS_S16]) then
  889. begin
  890. paracgsize:=OS_S32;
  891. paralen:=4;
  892. paradef:=s32inttype;
  893. end;
  894. end;
  895. { cheat for now, we should copy the value to an mm reg as well (FK) }
  896. if varargsparas and
  897. (target_info.system = system_x86_64_win64) and
  898. (paradef.typ = floatdef) then
  899. begin
  900. loc[2]:=X86_64_NO_CLASS;
  901. if paracgsize=OS_F64 then
  902. begin
  903. loc[1]:=X86_64_INTEGER_CLASS;
  904. paracgsize:=OS_64;
  905. paradef:=u64inttype;
  906. end
  907. else
  908. begin
  909. loc[1]:=X86_64_INTEGERSI_CLASS;
  910. paracgsize:=OS_32;
  911. paradef:=u32inttype;
  912. end;
  913. end;
  914. hp.paraloc[side].reset;
  915. hp.paraloc[side].size:=paracgsize;
  916. hp.paraloc[side].intsize:=paralen;
  917. hp.paraloc[side].Alignment:=paraalign;
  918. hp.paraloc[side].def:=paradef;
  919. if paralen>0 then
  920. begin
  921. { Enough registers free? }
  922. needintloc:=0;
  923. needmmloc:=0;
  924. for locidx:=low(loc) to high(loc) do
  925. case loc[locidx] of
  926. X86_64_INTEGER_CLASS,
  927. X86_64_INTEGERSI_CLASS:
  928. inc(needintloc);
  929. X86_64_SSE_CLASS,
  930. X86_64_SSESF_CLASS,
  931. X86_64_SSEDF_CLASS,
  932. X86_64_SSEUP_CLASS:
  933. inc(needmmloc);
  934. end;
  935. { the "-1" is because we can also use the current register }
  936. if ((target_info.system=system_x86_64_win64) and
  937. ((intparareg+needintloc-1 > high(paraintsupregs_winx64)) or
  938. (mmparareg+needmmloc-1 > high(parammsupregs_winx64)))) or
  939. ((target_info.system<>system_x86_64_win64) and
  940. ((intparareg+needintloc-1 > high(paraintsupregs)) or
  941. (mmparareg+needmmloc-1 > high(parammsupregs)))) then
  942. begin
  943. { If there are no registers available for any
  944. eightbyte of an argument, the whole argument is
  945. passed on the stack. }
  946. loc[low(loc)]:=X86_64_MEMORY_CLASS;
  947. for locidx:=succ(low(loc)) to high(loc) do
  948. loc[locidx]:=X86_64_NO_CLASS;
  949. end;
  950. locidx:=1;
  951. while (paralen>0) do
  952. begin
  953. if locidx>2 then
  954. internalerror(200501283);
  955. { Allocate }
  956. case loc[locidx] of
  957. X86_64_INTEGER_CLASS,
  958. X86_64_INTEGERSI_CLASS:
  959. begin
  960. paraloc:=hp.paraloc[side].add_location;
  961. paraloc^.loc:=LOC_REGISTER;
  962. if (paracgsize=OS_NO) or (loc[2]<>X86_64_NO_CLASS) then
  963. begin
  964. if loc[locidx]=X86_64_INTEGER_CLASS then
  965. begin
  966. paraloc^.size:=OS_INT;
  967. subreg:=R_SUBWHOLE;
  968. end
  969. else
  970. begin
  971. paraloc^.size:=OS_32;
  972. subreg:=R_SUBD;
  973. end;
  974. end
  975. else
  976. begin
  977. paraloc^.size:=paracgsize;
  978. { s64comp is pushed in an int register }
  979. if paraloc^.size=OS_C64 then
  980. paraloc^.size:=OS_64;
  981. subreg:=cgsize2subreg(R_INTREGISTER,paraloc^.size);
  982. end;
  983. { winx64 uses different registers }
  984. if target_info.system=system_x86_64_win64 then
  985. paraloc^.register:=newreg(R_INTREGISTER,paraintsupregs_winx64[intparareg],subreg)
  986. else
  987. paraloc^.register:=newreg(R_INTREGISTER,paraintsupregs[intparareg],subreg);
  988. { matching mm register must be skipped }
  989. if target_info.system=system_x86_64_win64 then
  990. inc(mmparareg);
  991. inc(intparareg);
  992. dec(paralen,tcgsize2size[paraloc^.size]);
  993. end;
  994. X86_64_SSE_CLASS,
  995. X86_64_SSESF_CLASS,
  996. X86_64_SSEDF_CLASS,
  997. X86_64_SSEUP_CLASS:
  998. begin
  999. paraloc:=hp.paraloc[side].add_location;
  1000. paraloc^.loc:=LOC_MMREGISTER;
  1001. case loc[locidx] of
  1002. X86_64_SSESF_CLASS:
  1003. begin
  1004. subreg:=R_SUBMMS;
  1005. paraloc^.size:=OS_F32;
  1006. end;
  1007. X86_64_SSEDF_CLASS:
  1008. begin
  1009. subreg:=R_SUBMMD;
  1010. paraloc^.size:=OS_F64;
  1011. end;
  1012. else
  1013. begin
  1014. subreg:=R_SUBMMWHOLE;
  1015. paraloc^.size:=OS_M64;
  1016. end;
  1017. end;
  1018. { winx64 uses different registers }
  1019. if target_info.system=system_x86_64_win64 then
  1020. paraloc^.register:=newreg(R_MMREGISTER,parammsupregs_winx64[mmparareg],subreg)
  1021. else
  1022. paraloc^.register:=newreg(R_MMREGISTER,parammsupregs[mmparareg],subreg);
  1023. { matching int register must be skipped }
  1024. if target_info.system=system_x86_64_win64 then
  1025. inc(intparareg);
  1026. inc(mmparareg);
  1027. dec(paralen,tcgsize2size[paraloc^.size]);
  1028. end;
  1029. X86_64_MEMORY_CLASS :
  1030. begin
  1031. paraloc:=hp.paraloc[side].add_location;
  1032. paraloc^.loc:=LOC_REFERENCE;
  1033. {Hack alert!!! We should modify int_cgsize to handle OS_128,
  1034. however, since int_cgsize is called in many places in the
  1035. compiler where only a few can already handle OS_128, fixing it
  1036. properly is out of the question to release 2.2.0 in time. (DM)}
  1037. if paracgsize=OS_128 then
  1038. if paralen=8 then
  1039. paraloc^.size:=OS_64
  1040. else if paralen=16 then
  1041. paraloc^.size:=OS_128
  1042. else
  1043. internalerror(200707143)
  1044. else if paracgsize in [OS_F32,OS_F64,OS_F80,OS_F128] then
  1045. paraloc^.size:=int_float_cgsize(paralen)
  1046. else
  1047. paraloc^.size:=int_cgsize(paralen);
  1048. if side=callerside then
  1049. paraloc^.reference.index:=NR_STACK_POINTER_REG
  1050. else
  1051. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  1052. varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
  1053. paraloc^.reference.offset:=parasize;
  1054. parasize:=align(parasize+paralen,varalign);
  1055. paralen:=0;
  1056. end;
  1057. else
  1058. internalerror(2010053113);
  1059. end;
  1060. if (locidx<2) and
  1061. (loc[locidx+1]<>X86_64_NO_CLASS) then
  1062. inc(locidx);
  1063. end;
  1064. end
  1065. else
  1066. begin
  1067. paraloc:=hp.paraloc[side].add_location;
  1068. paraloc^.loc:=LOC_VOID;
  1069. end;
  1070. end;
  1071. { Register parameters are assigned from left-to-right, but the
  1072. offsets on the stack are right-to-left. There is no need
  1073. to reverse the offset, only adapt the calleeside with the
  1074. start offset of the first param on the stack }
  1075. if side=calleeside then
  1076. begin
  1077. for i:=0 to paras.count-1 do
  1078. begin
  1079. hp:=tparavarsym(paras[i]);
  1080. paraloc:=hp.paraloc[side].location;
  1081. while paraloc<>nil do
  1082. begin
  1083. with paraloc^ do
  1084. if (loc=LOC_REFERENCE) then
  1085. inc(reference.offset,target_info.first_parm_offset);
  1086. paraloc:=paraloc^.next;
  1087. end;
  1088. end;
  1089. end;
  1090. end;
  1091. function tx86_64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  1092. var
  1093. intparareg,mmparareg,
  1094. parasize : longint;
  1095. begin
  1096. intparareg:=0;
  1097. mmparareg:=0;
  1098. if target_info.system=system_x86_64_win64 then
  1099. parasize:=4*8
  1100. else
  1101. parasize:=0;
  1102. { calculate the registers for the normal parameters }
  1103. create_paraloc_info_intern(p,callerside,p.paras,intparareg,mmparareg,parasize,false);
  1104. { append the varargs }
  1105. create_paraloc_info_intern(p,callerside,varargspara,intparareg,mmparareg,parasize,true);
  1106. { store used no. of SSE registers, that needs to be passed in %AL }
  1107. varargspara.mmregsused:=mmparareg;
  1108. result:=parasize;
  1109. end;
  1110. function tx86_64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  1111. var
  1112. intparareg,mmparareg,
  1113. parasize : longint;
  1114. begin
  1115. intparareg:=0;
  1116. mmparareg:=0;
  1117. if target_info.system=system_x86_64_win64 then
  1118. parasize:=4*8
  1119. else
  1120. parasize:=0;
  1121. create_paraloc_info_intern(p,side,p.paras,intparareg,mmparareg,parasize,false);
  1122. { Create Function result paraloc }
  1123. create_funcretloc_info(p,side);
  1124. { We need to return the size allocated on the stack }
  1125. result:=parasize;
  1126. end;
  1127. begin
  1128. paramanager:=tx86_64paramanager.create;
  1129. end.