cpupara.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. {
  2. $Id$
  3. Copyright (c) 2002 by Florian Klaempfl
  4. Generates the argument location information for i386
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published bymethodpointer
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. { Generates the argument location information for i386.
  19. }
  20. unit cpupara;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. aasmtai,
  25. cpubase,
  26. globtype,
  27. cginfo,
  28. symconst,symtype,symdef,paramgr;
  29. type
  30. { Returns the location for the nr-st 32 Bit int parameter
  31. if every parameter before is an 32 Bit int parameter as well
  32. and if the calling conventions for the helper routines of the
  33. rtl are used.
  34. }
  35. ti386paramanager = class(tparamanager)
  36. function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
  37. function push_addr_param(def : tdef;calloption : tproccalloption) : boolean;override;
  38. function get_volatile_registers_int(calloption : tproccalloption):tsuperregisterset;override;
  39. function get_volatile_registers_fpu(calloption : tproccalloption):tsuperregisterset;override;
  40. function getintparaloc(list: taasmoutput; nr : longint) : tparalocation;override;
  41. procedure freeintparaloc(list: taasmoutput; nr : longint); override;
  42. function getparaloc(p : tdef) : tcgloc;
  43. procedure create_paraloc_info(p : tabstractprocdef; side: tcallercallee);override;
  44. function getselflocation(p : tabstractprocdef) : tparalocation;override;
  45. private
  46. procedure create_funcret_paraloc_info(p : tabstractprocdef; side: tcallercallee);
  47. procedure create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee);
  48. procedure create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee);
  49. end;
  50. implementation
  51. uses
  52. systems,verbose,
  53. symsym,
  54. cpuinfo,
  55. cgbase;
  56. {****************************************************************************
  57. TI386PARAMANAGER
  58. ****************************************************************************}
  59. function ti386paramanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
  60. begin
  61. case target_info.system of
  62. system_i386_win32 :
  63. begin
  64. { Win32 returns small records in the FUNCTION_RETURN_REG }
  65. case def.deftype of
  66. recorddef :
  67. begin
  68. if (calloption in [pocall_stdcall,pocall_cdecl,pocall_cppdecl]) and (def.size<=8) then
  69. begin
  70. result:=false;
  71. exit;
  72. end;
  73. end;
  74. end;
  75. end;
  76. end;
  77. result:=inherited ret_in_param(def,calloption);
  78. end;
  79. function ti386paramanager.push_addr_param(def : tdef;calloption : tproccalloption) : boolean;
  80. begin
  81. case target_info.system of
  82. system_i386_win32 :
  83. begin
  84. case def.deftype of
  85. recorddef :
  86. begin
  87. { This is not true for the WinAPI expects (PFV)
  88. if (calloption=pocall_stdcall) and (def.size<=8) then
  89. begin
  90. result:=false;
  91. exit;
  92. end; }
  93. end;
  94. arraydef :
  95. begin
  96. if (tarraydef(def).highrange>=tarraydef(def).lowrange) and
  97. (calloption in [pocall_cdecl,pocall_cppdecl]) then
  98. begin
  99. result:=true;
  100. exit;
  101. end;
  102. end;
  103. end;
  104. end;
  105. end;
  106. result:=inherited push_addr_param(def,calloption);
  107. end;
  108. function ti386paramanager.get_volatile_registers_int(calloption : tproccalloption):tsuperregisterset;
  109. begin
  110. case calloption of
  111. pocall_internproc :
  112. result:=[];
  113. pocall_compilerproc :
  114. begin
  115. if pocall_default=pocall_oldfpccall then
  116. result:=[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI,RS_EBX]
  117. else
  118. result:=[RS_EAX,RS_EDX,RS_ECX];
  119. end;
  120. pocall_inline,
  121. pocall_register,
  122. pocall_safecall,
  123. pocall_stdcall,
  124. pocall_cdecl,
  125. pocall_cppdecl :
  126. result:=[RS_EAX,RS_EDX,RS_ECX];
  127. pocall_far16,
  128. pocall_pascal,
  129. pocall_oldfpccall :
  130. result:=[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI,RS_EBX];
  131. else
  132. internalerror(200309071);
  133. end;
  134. end;
  135. function ti386paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tsuperregisterset;
  136. begin
  137. result:=[first_fpu_supreg..last_fpu_supreg];;
  138. end;
  139. function ti386paramanager.getintparaloc(list: taasmoutput; nr : longint) : tparalocation;
  140. begin
  141. getintparaloc.loc:=LOC_REFERENCE;
  142. getintparaloc.reference.index:=NR_EBP;
  143. getintparaloc.reference.offset:=4*nr;
  144. end;
  145. procedure ti386paramanager.freeintparaloc(list: taasmoutput; nr : longint);
  146. begin
  147. { nothing to release }
  148. end;
  149. function ti386paramanager.getparaloc(p : tdef) : tcgloc;
  150. begin
  151. result:=LOC_REFERENCE;
  152. end;
  153. procedure ti386paramanager.create_funcret_paraloc_info(p : tabstractprocdef; side: tcallercallee);
  154. var
  155. paraloc : tparalocation;
  156. begin
  157. { Function return }
  158. fillchar(paraloc,sizeof(tparalocation),0);
  159. paraloc.size:=def_cgsize(p.rettype.def);
  160. { Return in FPU register? }
  161. if p.rettype.def.deftype=floatdef then
  162. begin
  163. paraloc.loc:=LOC_FPUREGISTER;
  164. paraloc.register:=NR_FPU_RESULT_REG;
  165. end
  166. else
  167. { Return in register? }
  168. if not ret_in_param(p.rettype.def,p.proccalloption) then
  169. begin
  170. paraloc.loc:=LOC_REGISTER;
  171. {$ifndef cpu64bit}
  172. if paraloc.size in [OS_64,OS_S64] then
  173. begin
  174. paraloc.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  175. paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  176. end
  177. else
  178. {$endif cpu64bit}
  179. begin
  180. paraloc.register:=NR_FUNCTION_RETURN_REG;
  181. end;
  182. end
  183. else
  184. begin
  185. paraloc.loc:=LOC_REFERENCE;
  186. end;
  187. p.funcret_paraloc[side]:=paraloc;
  188. end;
  189. procedure ti386paramanager.create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee);
  190. var
  191. hp : tparaitem;
  192. paraloc : tparalocation;
  193. begin
  194. hp:=tparaitem(p.para.first);
  195. while assigned(hp) do
  196. begin
  197. if hp.paratyp in [vs_var,vs_out] then
  198. paraloc.size:=OS_ADDR
  199. else
  200. paraloc.size:=def_cgsize(hp.paratype.def);
  201. paraloc.loc:=LOC_REFERENCE;
  202. if assigned(current_procinfo) then
  203. paraloc.reference.index:=current_procinfo.framepointer
  204. else
  205. paraloc.reference.index:=NR_FRAME_POINTER_REG;
  206. paraloc.reference.offset:=tvarsym(hp.parasym).adjusted_address;
  207. hp.paraloc[side]:=paraloc;
  208. {$warning callerparaloc shall not be the same as calleeparaloc}
  209. hp:=tparaitem(hp.next);
  210. end;
  211. end;
  212. procedure ti386paramanager.create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee);
  213. var
  214. hp : tparaitem;
  215. paraloc : tparalocation;
  216. sr : tsuperregister;
  217. subreg : tsubregister;
  218. begin
  219. sr:=RS_EAX;
  220. hp:=tparaitem(p.para.first);
  221. while assigned(hp) do
  222. begin
  223. if hp.paratyp in [vs_var,vs_out] then
  224. paraloc.size:=OS_ADDR
  225. else
  226. paraloc.size:=def_cgsize(hp.paratype.def);
  227. {
  228. EAX
  229. EDX
  230. ECX
  231. Stack
  232. Stack
  233. }
  234. if sr<=NR_ECX then
  235. begin
  236. paraloc.loc:=LOC_REGISTER;
  237. if paraloc.size=OS_NO then
  238. subreg:=R_SUBWHOLE
  239. else
  240. subreg:=cgsize2subreg(paraloc.size);
  241. paraloc.register:=newreg(R_INTREGISTER,sr,subreg);
  242. inc(sr);
  243. end
  244. else
  245. begin
  246. paraloc.loc:=LOC_REFERENCE;
  247. if assigned(current_procinfo) then
  248. paraloc.reference.index:=current_procinfo.framepointer
  249. else
  250. paraloc.reference.index:=NR_FRAME_POINTER_REG;
  251. paraloc.reference.offset:=tvarsym(hp.parasym).adjusted_address;
  252. end;
  253. hp.paraloc[side]:=paraloc;
  254. {$warning callerparaloc shall not be the same as calleeparaloc}
  255. hp:=tparaitem(hp.next);
  256. end;
  257. end;
  258. procedure ti386paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee);
  259. begin
  260. if p.proccalloption=pocall_register then
  261. create_register_paraloc_info(p,side)
  262. else
  263. create_stdcall_paraloc_info(p,side);
  264. create_funcret_paraloc_info(p,side);
  265. end;
  266. function ti386paramanager.getselflocation(p : tabstractprocdef) : tparalocation;
  267. var
  268. hsym : tvarsym;
  269. begin
  270. hsym:=tvarsym(trecorddef(methodpointertype.def).symtable.search('self'));
  271. if not assigned(hsym) then
  272. internalerror(200305251);
  273. getselflocation.loc:=LOC_REFERENCE;
  274. getselflocation.sp_fixup:=POINTER_SIZE;
  275. getselflocation.reference.index:=NR_STACK_POINTER_REG;
  276. getselflocation.reference.offset:=hsym.adjusted_address;
  277. end;
  278. begin
  279. paramanager:=ti386paramanager.create;
  280. end.
  281. {
  282. $Log$
  283. Revision 1.27 2003-09-09 21:03:17 peter
  284. * basics for x86 register calling
  285. Revision 1.26 2003/09/09 15:55:05 peter
  286. * winapi doesn't like pushing 8 byte record
  287. Revision 1.25 2003/09/08 18:28:51 peter
  288. * fix compilerproc for default=oldfpccall
  289. Revision 1.24 2003/09/07 22:09:35 peter
  290. * preparations for different default calling conventions
  291. * various RA fixes
  292. Revision 1.23 2003/09/03 15:55:01 peter
  293. * NEWRA branch merged
  294. Revision 1.22.2.2 2003/08/28 18:35:08 peter
  295. * tregister changed to cardinal
  296. Revision 1.22.2.1 2003/08/27 19:55:54 peter
  297. * first tregister patch
  298. Revision 1.22 2003/08/11 21:18:20 peter
  299. * start of sparc support for newra
  300. Revision 1.21 2003/07/05 20:11:41 jonas
  301. * create_paraloc_info() is now called separately for the caller and
  302. callee info
  303. * fixed ppc cycle
  304. Revision 1.20 2003/07/02 22:18:04 peter
  305. * paraloc splitted in callerparaloc,calleeparaloc
  306. * sparc calling convention updates
  307. Revision 1.19 2003/06/17 16:34:19 peter
  308. * freeintparaloc added
  309. Revision 1.18 2003/06/07 18:57:04 jonas
  310. + added freeintparaloc
  311. * ppc get/freeintparaloc now check whether the parameter regs are
  312. properly allocated/deallocated (and get an extra list para)
  313. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  314. * fixed lot of missing pi_do_call's
  315. Revision 1.17 2003/06/06 14:41:22 peter
  316. * needs cpuinfo
  317. Revision 1.16 2003/06/06 07:36:06 michael
  318. + Forgot a line in patch from peter
  319. Revision 1.15 2003/06/06 07:35:14 michael
  320. + Patch to Patch from peter
  321. Revision 1.14 2003/06/06 07:34:11 michael
  322. + Patch from peter
  323. Revision 1.13 2003/06/05 20:58:05 peter
  324. * updated
  325. Revision 1.12 2003/05/30 23:57:08 peter
  326. * more sparc cleanup
  327. * accumulator removed, splitted in function_return_reg (called) and
  328. function_result_reg (caller)
  329. Revision 1.11 2003/05/13 15:16:13 peter
  330. * removed ret_in_acc, it's the reverse of ret_in_param
  331. * fixed ret_in_param for win32 cdecl array
  332. Revision 1.10 2003/04/22 23:50:23 peter
  333. * firstpass uses expectloc
  334. * checks if there are differences between the expectloc and
  335. location.loc from secondpass in EXTDEBUG
  336. Revision 1.9 2003/04/22 14:33:38 peter
  337. * removed some notes/hints
  338. Revision 1.8 2003/01/08 18:43:57 daniel
  339. * Tregister changed into a record
  340. Revision 1.7 2002/12/24 15:56:50 peter
  341. * stackpointer_alloc added for adjusting ESP. Win32 needs
  342. this for the pageprotection
  343. Revision 1.6 2002/12/17 22:19:33 peter
  344. * fixed pushing of records>8 bytes with stdcall
  345. * simplified hightree loading
  346. Revision 1.5 2002/11/18 17:32:00 peter
  347. * pass proccalloption to ret_in_xxx and push_xxx functions
  348. Revision 1.4 2002/11/15 01:58:56 peter
  349. * merged changes from 1.0.7 up to 04-11
  350. - -V option for generating bug report tracing
  351. - more tracing for option parsing
  352. - errors for cdecl and high()
  353. - win32 import stabs
  354. - win32 records<=8 are returned in eax:edx (turned off by default)
  355. - heaptrc update
  356. - more info for temp management in .s file with EXTDEBUG
  357. Revision 1.3 2002/08/09 07:33:04 florian
  358. * a couple of interface related fixes
  359. Revision 1.2 2002/07/11 14:41:32 florian
  360. * start of the new generic parameter handling
  361. Revision 1.1 2002/07/07 09:52:33 florian
  362. * powerpc target fixed, very simple units can be compiled
  363. * some basic stuff for better callparanode handling, far from being finished
  364. }