paramgr.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. {
  2. $Id$
  3. Copyright (c) 2002 by Florian Klaempfl
  4. PowerPC specific calling conventions
  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 by
  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. {# Parameter passing manager. Used to manage how
  19. parameters are passed to routines.
  20. }
  21. unit paramgr;
  22. {$i fpcdefs.inc}
  23. interface
  24. uses
  25. cpubase,
  26. symtype,symdef;
  27. type
  28. {# This class defines some methods to take care of routine
  29. parameters. It should be overriden for each new processor
  30. }
  31. tparamanager = class
  32. {# Returns true if the return value can be put in accumulator }
  33. function ret_in_acc(def : tdef) : boolean;virtual;
  34. {# Returns true if the return value is put in a register
  35. Either a floating point register, or a general purpose
  36. register.
  37. }
  38. function ret_in_reg(def : tdef) : boolean;virtual;
  39. {# Returns true if the return value is actually a parameter
  40. pointer.
  41. }
  42. function ret_in_param(def : tdef) : boolean;virtual;
  43. function push_high_param(def : tdef) : boolean;virtual;
  44. {# Returns true if a parameter is too large to copy and only
  45. the address is pushed
  46. }
  47. function push_addr_param(def : tdef) : boolean;virtual;
  48. {# Returns a structure giving the information on
  49. the storage of the parameter (which must be
  50. an integer parameter)
  51. @param(nr Parameter number of routine, starting from 1)
  52. }
  53. function getintparaloc(nr : longint) : tparalocation;virtual;abstract;
  54. procedure create_param_loc_info(p : tabstractprocdef);virtual;abstract;
  55. {#
  56. Returns the location where the invisible parameter for structured
  57. function results will be passed.
  58. }
  59. function getfuncretloc(p : tabstractprocdef) : tparalocation;virtual;abstract;
  60. { Returns the self pointer location for the given tabstractprocdef,
  61. when the stack frame is already created. This is used by the code
  62. generating the wrappers for implemented interfaces.
  63. }
  64. function getselflocation(p : tabstractprocdef) : tparalocation;virtual;abstract;
  65. {#
  66. Returns the location of the result if the result is in
  67. a register, the register(s) return depend on the type of
  68. the result.
  69. @param(def The definition of the result type of the function)
  70. }
  71. function getfuncresultlocreg(def : tdef): tparalocation; virtual;
  72. end;
  73. procedure setparalocs(p : tprocdef);
  74. var
  75. paralocdummy : tparalocation;
  76. paramanager : tparamanager;
  77. implementation
  78. uses
  79. cpuinfo,globals,globtype,
  80. symconst,symbase,symsym,
  81. rgobj,
  82. defbase,cgbase,cginfo,verbose;
  83. { true if the return value is in accumulator (EAX for i386), D0 for 68k }
  84. function tparamanager.ret_in_acc(def : tdef) : boolean;
  85. begin
  86. ret_in_acc:=(def.deftype in [orddef,pointerdef,enumdef,classrefdef]) or
  87. ((def.deftype=stringdef) and (tstringdef(def).string_typ in [st_ansistring,st_widestring])) or
  88. ((def.deftype=procvardef) and not(po_methodpointer in tprocvardef(def).procoptions)) or
  89. ((def.deftype=objectdef) and not is_object(def)) or
  90. ((def.deftype=setdef) and (tsetdef(def).settype=smallset));
  91. end;
  92. function tparamanager.ret_in_reg(def : tdef) : boolean;
  93. begin
  94. ret_in_reg:=ret_in_acc(def) or (def.deftype=floatdef);
  95. end;
  96. { true if uses a parameter as return value }
  97. function tparamanager.ret_in_param(def : tdef) : boolean;
  98. begin
  99. ret_in_param:=(def.deftype in [arraydef,recorddef]) or
  100. ((def.deftype=stringdef) and (tstringdef(def).string_typ in [st_shortstring,st_longstring])) or
  101. ((def.deftype=procvardef) and (po_methodpointer in tprocvardef(def).procoptions)) or
  102. ((def.deftype=objectdef) and is_object(def)) or
  103. (def.deftype=variantdef) or
  104. ((def.deftype=setdef) and (tsetdef(def).settype<>smallset));
  105. end;
  106. function tparamanager.push_high_param(def : tdef) : boolean;
  107. begin
  108. push_high_param:=is_open_array(def) or
  109. is_open_string(def) or
  110. is_array_of_const(def);
  111. end;
  112. { true if a parameter is too large to copy and only the address is pushed }
  113. function tparamanager.push_addr_param(def : tdef) : boolean;
  114. begin
  115. push_addr_param:=false;
  116. if never_copy_const_param then
  117. push_addr_param:=true
  118. else
  119. begin
  120. case def.deftype of
  121. variantdef,
  122. formaldef :
  123. push_addr_param:=true;
  124. recorddef :
  125. push_addr_param:=(def.size>pointer_size);
  126. arraydef :
  127. push_addr_param:=((tarraydef(def).highrange>=tarraydef(def).lowrange) and (def.size>pointer_size)) or
  128. is_open_array(def) or
  129. is_array_of_const(def) or
  130. is_array_constructor(def);
  131. objectdef :
  132. push_addr_param:=is_object(def);
  133. stringdef :
  134. push_addr_param:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
  135. procvardef :
  136. push_addr_param:=(po_methodpointer in tprocvardef(def).procoptions);
  137. setdef :
  138. push_addr_param:=(tsetdef(def).settype<>smallset);
  139. end;
  140. end;
  141. end;
  142. function tparamanager.getfuncresultlocreg(def : tdef): tparalocation;
  143. begin
  144. fillchar(result,sizeof(tparalocation),0);
  145. if is_void(def) then exit;
  146. result.size := def_cgsize(def);
  147. case aktprocdef.rettype.def.deftype of
  148. orddef,
  149. enumdef :
  150. begin
  151. result.loc := LOC_REGISTER;
  152. if result.size in [OS_64,OS_S64] then
  153. begin
  154. result.registerhigh:=accumulatorhigh;
  155. result.register:=accumulator;
  156. end
  157. else
  158. result.register:=accumulator;
  159. end;
  160. floatdef :
  161. begin
  162. result.loc := LOC_FPUREGISTER;
  163. if cs_fp_emulation in aktmoduleswitches then
  164. result.register := accumulator
  165. else
  166. result.register := FPU_RESULT_REG;
  167. end;
  168. else
  169. begin
  170. if ret_in_acc(def) then
  171. begin
  172. result.loc := LOC_REGISTER;
  173. result.register := accumulator;
  174. end
  175. else
  176. begin
  177. result.loc := LOC_REFERENCE;
  178. internalerror(2002081602);
  179. (*
  180. {$ifdef EXTDEBUG}
  181. { it is impossible to have the
  182. return value with an index register
  183. and a symbol!
  184. }
  185. if (ref.index <> R_NO) or (assigned(ref.symbol)) then
  186. internalerror(2002081602);
  187. {$endif}
  188. result.reference.index := ref.base;
  189. result.reference.offset := ref.offset;
  190. *)
  191. end;
  192. end;
  193. end;
  194. end;
  195. procedure setparalocs(p : tprocdef);
  196. var
  197. hp : tparaitem;
  198. begin
  199. hp:=tparaitem(p.para.first);
  200. while assigned(hp) do
  201. begin
  202. {$ifdef SUPPORT_MMX}
  203. if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,
  204. LOC_MMREGISTER]) and
  205. {$else}
  206. if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER]) and
  207. {$endif}
  208. { if the parameter isn't regable, we've to work with the local copy }
  209. ((vo_regable in tvarsym(hp.parasym).varoptions) or
  210. (vo_fpuregable in tvarsym(hp.parasym).varoptions)) then
  211. begin
  212. case hp.paraloc.loc of
  213. LOC_REGISTER:
  214. hp.paraloc.loc := LOC_CREGISTER;
  215. LOC_FPUREGISTER:
  216. hp.paraloc.loc := LOC_CFPUREGISTER;
  217. {$ifdef SUPPORT_MMX}
  218. LOC_MMREGISTER:
  219. hp.paraloc.loc := LOC_CMMREGISTER;
  220. {$endif}
  221. end;
  222. tvarsym(hp.parasym).reg:=hp.paraloc.register;
  223. rg.regvar_loaded[hp.paraloc.register]:=true;
  224. end;
  225. hp:=tparaitem(hp.next);
  226. end;
  227. end;
  228. finalization
  229. paramanager.free;
  230. end.
  231. {
  232. $Log$
  233. Revision 1.12 2002-08-16 14:24:58 carl
  234. * issameref() to test if two references are the same (then emit no opcodes)
  235. + ret_in_reg to replace ret_in_acc
  236. (fix some register allocation bugs at the same time)
  237. + save_std_register now has an extra parameter which is the
  238. usedinproc registers
  239. Revision 1.11 2002/08/12 15:08:40 carl
  240. + stab register indexes for powerpc (moved from gdb to cpubase)
  241. + tprocessor enumeration moved to cpuinfo
  242. + linker in target_info is now a class
  243. * many many updates for m68k (will soon start to compile)
  244. - removed some ifdef or correct them for correct cpu
  245. Revision 1.10 2002/08/10 17:15:20 jonas
  246. * register parameters are now LOC_CREGISTER instead of LOC_REGISTER
  247. Revision 1.9 2002/08/09 07:33:02 florian
  248. * a couple of interface related fixes
  249. Revision 1.8 2002/08/06 20:55:21 florian
  250. * first part of ppc calling conventions fix
  251. Revision 1.7 2002/08/05 18:27:48 carl
  252. + more more more documentation
  253. + first version include/exclude (can't test though, not enough scratch for i386 :()...
  254. Revision 1.6 2002/07/30 20:50:43 florian
  255. * the code generator knows now if parameters are in registers
  256. Revision 1.5 2002/07/26 21:15:39 florian
  257. * rewrote the system handling
  258. Revision 1.4 2002/07/20 11:57:55 florian
  259. * types.pas renamed to defbase.pas because D6 contains a types
  260. unit so this would conflicts if D6 programms are compiled
  261. + Willamette/SSE2 instructions to assembler added
  262. Revision 1.3 2002/07/13 19:38:43 florian
  263. * some more generic calling stuff fixed
  264. Revision 1.2 2002/07/13 07:17:15 jonas
  265. * fixed memory leak reported by Sergey Korshunoff
  266. Revision 1.1 2002/07/11 14:41:28 florian
  267. * start of the new generic parameter handling
  268. }