cpupara.pas 47 KB

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