cpupara.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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. end;
  46. implementation
  47. uses
  48. systems,verbose,
  49. symsym,
  50. cpuinfo,
  51. cgbase;
  52. {****************************************************************************
  53. TI386PARAMANAGER
  54. ****************************************************************************}
  55. function ti386paramanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
  56. begin
  57. case target_info.system of
  58. system_i386_win32 :
  59. begin
  60. { Win32 returns small records in the FUNCTION_RETURN_REG }
  61. case def.deftype of
  62. recorddef :
  63. begin
  64. if (calloption in [pocall_stdcall,pocall_cdecl,pocall_cppdecl]) and (def.size<=8) then
  65. begin
  66. result:=false;
  67. exit;
  68. end;
  69. end;
  70. end;
  71. end;
  72. end;
  73. result:=inherited ret_in_param(def,calloption);
  74. end;
  75. function ti386paramanager.push_addr_param(def : tdef;calloption : tproccalloption) : boolean;
  76. begin
  77. case target_info.system of
  78. system_i386_win32 :
  79. begin
  80. case def.deftype of
  81. recorddef :
  82. begin
  83. { This is not true for the WinAPI expects (PFV)
  84. if (calloption=pocall_stdcall) and (def.size<=8) then
  85. begin
  86. result:=false;
  87. exit;
  88. end; }
  89. end;
  90. arraydef :
  91. begin
  92. if (tarraydef(def).highrange>=tarraydef(def).lowrange) and
  93. (calloption in [pocall_cdecl,pocall_cppdecl]) then
  94. begin
  95. result:=true;
  96. exit;
  97. end;
  98. end;
  99. end;
  100. end;
  101. end;
  102. result:=inherited push_addr_param(def,calloption);
  103. end;
  104. function ti386paramanager.get_volatile_registers_int(calloption : tproccalloption):tsuperregisterset;
  105. begin
  106. case calloption of
  107. pocall_internproc :
  108. result:=[];
  109. pocall_compilerproc :
  110. begin
  111. if pocall_default=pocall_oldfpccall then
  112. result:=[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI,RS_EBX]
  113. else
  114. result:=[RS_EAX,RS_EDX,RS_ECX];
  115. end;
  116. pocall_inline,
  117. pocall_register,
  118. pocall_safecall,
  119. pocall_stdcall,
  120. pocall_cdecl,
  121. pocall_cppdecl :
  122. result:=[RS_EAX,RS_EDX,RS_ECX];
  123. pocall_far16,
  124. pocall_pascal,
  125. pocall_oldfpccall :
  126. result:=[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI,RS_EBX];
  127. else
  128. internalerror(200309071);
  129. end;
  130. end;
  131. function ti386paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tsuperregisterset;
  132. begin
  133. result:=[first_fpu_supreg..last_fpu_supreg];;
  134. end;
  135. function ti386paramanager.getintparaloc(list: taasmoutput; nr : longint) : tparalocation;
  136. begin
  137. getintparaloc.loc:=LOC_REFERENCE;
  138. getintparaloc.reference.index:=NR_EBP;
  139. getintparaloc.reference.offset:=4*nr;
  140. end;
  141. procedure ti386paramanager.freeintparaloc(list: taasmoutput; nr : longint);
  142. begin
  143. { nothing to release }
  144. end;
  145. function ti386paramanager.getparaloc(p : tdef) : tcgloc;
  146. begin
  147. result:=LOC_REFERENCE;
  148. end;
  149. procedure ti386paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee);
  150. var
  151. hp : tparaitem;
  152. paraloc : tparalocation;
  153. begin
  154. hp:=tparaitem(p.para.first);
  155. while assigned(hp) do
  156. begin
  157. if hp.paratyp in [vs_var,vs_out] then
  158. paraloc.size:=OS_ADDR
  159. else
  160. paraloc.size:=def_cgsize(hp.paratype.def);
  161. paraloc.loc:=LOC_REFERENCE;
  162. if assigned(current_procinfo) then
  163. paraloc.reference.index:=current_procinfo.framepointer
  164. else
  165. paraloc.reference.index:=NR_FRAME_POINTER_REG;
  166. paraloc.reference.offset:=tvarsym(hp.parasym).adjusted_address;
  167. hp.paraloc[side]:=paraloc;
  168. {$warning callerparaloc shall not be the same as calleeparaloc}
  169. hp:=tparaitem(hp.next);
  170. end;
  171. { Function return }
  172. fillchar(paraloc,sizeof(tparalocation),0);
  173. paraloc.size:=def_cgsize(p.rettype.def);
  174. { Return in FPU register? }
  175. if p.rettype.def.deftype=floatdef then
  176. begin
  177. paraloc.loc:=LOC_FPUREGISTER;
  178. paraloc.register:=NR_FPU_RESULT_REG;
  179. end
  180. else
  181. { Return in register? }
  182. if not ret_in_param(p.rettype.def,p.proccalloption) then
  183. begin
  184. paraloc.loc:=LOC_REGISTER;
  185. {$ifndef cpu64bit}
  186. if paraloc.size in [OS_64,OS_S64] then
  187. begin
  188. paraloc.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  189. paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  190. end
  191. else
  192. {$endif cpu64bit}
  193. begin
  194. paraloc.register:=NR_FUNCTION_RETURN_REG;
  195. end;
  196. end
  197. else
  198. begin
  199. paraloc.loc:=LOC_REFERENCE;
  200. end;
  201. p.funcret_paraloc[side]:=paraloc;
  202. end;
  203. function ti386paramanager.getselflocation(p : tabstractprocdef) : tparalocation;
  204. var
  205. hsym : tvarsym;
  206. begin
  207. hsym:=tvarsym(trecorddef(methodpointertype.def).symtable.search('self'));
  208. if not assigned(hsym) then
  209. internalerror(200305251);
  210. getselflocation.loc:=LOC_REFERENCE;
  211. getselflocation.sp_fixup:=POINTER_SIZE;
  212. getselflocation.reference.index:=NR_STACK_POINTER_REG;
  213. getselflocation.reference.offset:=hsym.adjusted_address;
  214. end;
  215. begin
  216. paramanager:=ti386paramanager.create;
  217. end.
  218. {
  219. $Log$
  220. Revision 1.26 2003-09-09 15:55:05 peter
  221. * winapi doesn't like pushing 8 byte record
  222. Revision 1.25 2003/09/08 18:28:51 peter
  223. * fix compilerproc for default=oldfpccall
  224. Revision 1.24 2003/09/07 22:09:35 peter
  225. * preparations for different default calling conventions
  226. * various RA fixes
  227. Revision 1.23 2003/09/03 15:55:01 peter
  228. * NEWRA branch merged
  229. Revision 1.22.2.2 2003/08/28 18:35:08 peter
  230. * tregister changed to cardinal
  231. Revision 1.22.2.1 2003/08/27 19:55:54 peter
  232. * first tregister patch
  233. Revision 1.22 2003/08/11 21:18:20 peter
  234. * start of sparc support for newra
  235. Revision 1.21 2003/07/05 20:11:41 jonas
  236. * create_paraloc_info() is now called separately for the caller and
  237. callee info
  238. * fixed ppc cycle
  239. Revision 1.20 2003/07/02 22:18:04 peter
  240. * paraloc splitted in callerparaloc,calleeparaloc
  241. * sparc calling convention updates
  242. Revision 1.19 2003/06/17 16:34:19 peter
  243. * freeintparaloc added
  244. Revision 1.18 2003/06/07 18:57:04 jonas
  245. + added freeintparaloc
  246. * ppc get/freeintparaloc now check whether the parameter regs are
  247. properly allocated/deallocated (and get an extra list para)
  248. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  249. * fixed lot of missing pi_do_call's
  250. Revision 1.17 2003/06/06 14:41:22 peter
  251. * needs cpuinfo
  252. Revision 1.16 2003/06/06 07:36:06 michael
  253. + Forgot a line in patch from peter
  254. Revision 1.15 2003/06/06 07:35:14 michael
  255. + Patch to Patch from peter
  256. Revision 1.14 2003/06/06 07:34:11 michael
  257. + Patch from peter
  258. Revision 1.13 2003/06/05 20:58:05 peter
  259. * updated
  260. Revision 1.12 2003/05/30 23:57:08 peter
  261. * more sparc cleanup
  262. * accumulator removed, splitted in function_return_reg (called) and
  263. function_result_reg (caller)
  264. Revision 1.11 2003/05/13 15:16:13 peter
  265. * removed ret_in_acc, it's the reverse of ret_in_param
  266. * fixed ret_in_param for win32 cdecl array
  267. Revision 1.10 2003/04/22 23:50:23 peter
  268. * firstpass uses expectloc
  269. * checks if there are differences between the expectloc and
  270. location.loc from secondpass in EXTDEBUG
  271. Revision 1.9 2003/04/22 14:33:38 peter
  272. * removed some notes/hints
  273. Revision 1.8 2003/01/08 18:43:57 daniel
  274. * Tregister changed into a record
  275. Revision 1.7 2002/12/24 15:56:50 peter
  276. * stackpointer_alloc added for adjusting ESP. Win32 needs
  277. this for the pageprotection
  278. Revision 1.6 2002/12/17 22:19:33 peter
  279. * fixed pushing of records>8 bytes with stdcall
  280. * simplified hightree loading
  281. Revision 1.5 2002/11/18 17:32:00 peter
  282. * pass proccalloption to ret_in_xxx and push_xxx functions
  283. Revision 1.4 2002/11/15 01:58:56 peter
  284. * merged changes from 1.0.7 up to 04-11
  285. - -V option for generating bug report tracing
  286. - more tracing for option parsing
  287. - errors for cdecl and high()
  288. - win32 import stabs
  289. - win32 records<=8 are returned in eax:edx (turned off by default)
  290. - heaptrc update
  291. - more info for temp management in .s file with EXTDEBUG
  292. Revision 1.3 2002/08/09 07:33:04 florian
  293. * a couple of interface related fixes
  294. Revision 1.2 2002/07/11 14:41:32 florian
  295. * start of the new generic parameter handling
  296. Revision 1.1 2002/07/07 09:52:33 florian
  297. * powerpc target fixed, very simple units can be compiled
  298. * some basic stuff for better callparanode handling, far from being finished
  299. }