paramgr.pas 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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 actually a parameter
  35. pointer.
  36. }
  37. function ret_in_param(def : tdef) : boolean;virtual;
  38. function push_high_param(def : tdef) : boolean;virtual;
  39. {# Returns true if a parameter is too large to copy and only
  40. the address is pushed
  41. }
  42. function push_addr_param(def : tdef) : boolean;virtual;
  43. {# Returns a structure giving the information on
  44. the storage of the parameter (which must be
  45. an integer parameter)
  46. @param(nr Parameter number of routine, starting from 1)
  47. }
  48. function getintparaloc(nr : longint) : tparalocation;virtual;abstract;
  49. procedure create_param_loc_info(p : tabstractprocdef);virtual;abstract;
  50. {#
  51. Returns the location where the invisible parameter for structured
  52. function results will be passed.
  53. }
  54. function getfuncretloc(p : tabstractprocdef) : tparalocation;virtual;abstract;
  55. { Returns the self pointer location for the given tabstractprocdef,
  56. when the stack frame is already created. This is used by the code
  57. generating the wrappers for implemented interfaces.
  58. }
  59. function getselflocation(p : tabstractprocdef) : tparalocation;virtual;abstract;
  60. end;
  61. procedure setparalocs(p : tprocdef);
  62. var
  63. paralocdummy : tparalocation;
  64. paramanager : tparamanager;
  65. implementation
  66. uses
  67. cpuinfo,
  68. symconst,symbase,symsym,
  69. rgobj,
  70. defbase;
  71. { true if the return value is in accumulator (EAX for i386), D0 for 68k }
  72. function tparamanager.ret_in_acc(def : tdef) : boolean;
  73. begin
  74. ret_in_acc:=(def.deftype in [orddef,pointerdef,enumdef,classrefdef]) or
  75. ((def.deftype=stringdef) and (tstringdef(def).string_typ in [st_ansistring,st_widestring])) or
  76. ((def.deftype=procvardef) and not(po_methodpointer in tprocvardef(def).procoptions)) or
  77. ((def.deftype=objectdef) and not is_object(def)) or
  78. ((def.deftype=setdef) and (tsetdef(def).settype=smallset));
  79. end;
  80. { true if uses a parameter as return value }
  81. function tparamanager.ret_in_param(def : tdef) : boolean;
  82. begin
  83. ret_in_param:=(def.deftype in [arraydef,recorddef]) or
  84. ((def.deftype=stringdef) and (tstringdef(def).string_typ in [st_shortstring,st_longstring])) or
  85. ((def.deftype=procvardef) and (po_methodpointer in tprocvardef(def).procoptions)) or
  86. ((def.deftype=objectdef) and is_object(def)) or
  87. (def.deftype=variantdef) or
  88. ((def.deftype=setdef) and (tsetdef(def).settype<>smallset));
  89. end;
  90. function tparamanager.push_high_param(def : tdef) : boolean;
  91. begin
  92. push_high_param:=is_open_array(def) or
  93. is_open_string(def) or
  94. is_array_of_const(def);
  95. end;
  96. { true if a parameter is too large to copy and only the address is pushed }
  97. function tparamanager.push_addr_param(def : tdef) : boolean;
  98. begin
  99. push_addr_param:=false;
  100. if never_copy_const_param then
  101. push_addr_param:=true
  102. else
  103. begin
  104. case def.deftype of
  105. variantdef,
  106. formaldef :
  107. push_addr_param:=true;
  108. recorddef :
  109. push_addr_param:=(def.size>pointer_size);
  110. arraydef :
  111. push_addr_param:=((tarraydef(def).highrange>=tarraydef(def).lowrange) and (def.size>pointer_size)) or
  112. is_open_array(def) or
  113. is_array_of_const(def) or
  114. is_array_constructor(def);
  115. objectdef :
  116. push_addr_param:=is_object(def);
  117. stringdef :
  118. push_addr_param:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
  119. procvardef :
  120. push_addr_param:=(po_methodpointer in tprocvardef(def).procoptions);
  121. setdef :
  122. push_addr_param:=(tsetdef(def).settype<>smallset);
  123. end;
  124. end;
  125. end;
  126. procedure setparalocs(p : tprocdef);
  127. var
  128. hp : tparaitem;
  129. begin
  130. hp:=tparaitem(p.para.first);
  131. while assigned(hp) do
  132. begin
  133. if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER]) and
  134. { if the parameter isn't regable, we've to work with the local copy }
  135. ((vo_regable in tvarsym(hp.parasym).varoptions) or
  136. (vo_fpuregable in tvarsym(hp.parasym).varoptions)) then
  137. begin
  138. tvarsym(hp.parasym).reg:=hp.paraloc.register;
  139. rg.regvar_loaded[hp.paraloc.register]:=true;
  140. end;
  141. hp:=tparaitem(hp.next);
  142. end;
  143. end;
  144. finalization
  145. paramanager.free;
  146. end.
  147. {
  148. $Log$
  149. Revision 1.9 2002-08-09 07:33:02 florian
  150. * a couple of interface related fixes
  151. Revision 1.8 2002/08/06 20:55:21 florian
  152. * first part of ppc calling conventions fix
  153. Revision 1.7 2002/08/05 18:27:48 carl
  154. + more more more documentation
  155. + first version include/exclude (can't test though, not enough scratch for i386 :()...
  156. Revision 1.6 2002/07/30 20:50:43 florian
  157. * the code generator knows now if parameters are in registers
  158. Revision 1.5 2002/07/26 21:15:39 florian
  159. * rewrote the system handling
  160. Revision 1.4 2002/07/20 11:57:55 florian
  161. * types.pas renamed to defbase.pas because D6 contains a types
  162. unit so this would conflicts if D6 programms are compiled
  163. + Willamette/SSE2 instructions to assembler added
  164. Revision 1.3 2002/07/13 19:38:43 florian
  165. * some more generic calling stuff fixed
  166. Revision 1.2 2002/07/13 07:17:15 jonas
  167. * fixed memory leak reported by Sergey Korshunoff
  168. Revision 1.1 2002/07/11 14:41:28 florian
  169. * start of the new generic parameter handling
  170. }