cpupara.pas 52 KB

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