cpupara.pas 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. {
  2. Copyright (c) 1998-2010 by Florian Klaempfl, Jonas Maebe
  3. Calling conventions for the JVM
  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. unit cpupara;
  17. {$i fpcdefs.inc}
  18. interface
  19. uses
  20. globtype,
  21. cclasses,
  22. aasmtai,aasmdata,
  23. cpubase,cpuinfo,
  24. symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase,cgutils;
  25. type
  26. { TJVMParaManager }
  27. TJVMParaManager=class(TParaManager)
  28. function push_high_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  29. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  30. function push_size(varspez: tvarspez; def: tdef; calloption: tproccalloption): longint;override;
  31. {Returns a structure giving the information on the storage of the parameter
  32. (which must be an integer parameter)
  33. @param(nr Parameter number of routine, starting from 1)}
  34. procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
  35. function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
  36. function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
  37. function param_use_paraloc(const cgpara: tcgpara): boolean; override;
  38. function ret_in_param(def: tdef; calloption: tproccalloption): boolean; override;
  39. function is_stack_paraloc(paraloc: pcgparalocation): boolean;override;
  40. private
  41. procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  42. procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
  43. var parasize:longint);
  44. end;
  45. implementation
  46. uses
  47. cutils,verbose,systems,
  48. defutil,jvmdef,
  49. cgobj;
  50. procedure TJVMParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint;var cgpara : tcgpara);
  51. begin
  52. { don't know whether it's an actual integer or a pointer (necessary for cgpara.def) }
  53. internalerror(2010121001);
  54. end;
  55. function TJVMParaManager.push_high_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean;
  56. begin
  57. { we don't need a separate high parameter, since all arrays in Java
  58. have an implicit associated length }
  59. if not is_open_array(def) then
  60. result:=inherited
  61. else
  62. result:=false;
  63. end;
  64. { true if a parameter is too large to copy and only the address is pushed }
  65. function TJVMParaManager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  66. begin
  67. result:=jvmimplicitpointertype(def);
  68. end;
  69. function TJVMParaManager.push_size(varspez: tvarspez; def: tdef; calloption: tproccalloption): longint;
  70. begin
  71. { all aggregate types are emulated using indirect pointer types }
  72. if def.typ in [arraydef,recorddef,setdef,stringdef] then
  73. result:=4
  74. else
  75. result:=inherited;
  76. end;
  77. procedure TJVMParaManager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  78. begin
  79. p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
  80. end;
  81. function TJVMParaManager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
  82. var
  83. paraloc : pcgparalocation;
  84. retcgsize : tcgsize;
  85. begin
  86. result.init;
  87. result.alignment:=get_para_align(p.proccalloption);
  88. result.def:=def;
  89. { void has no location }
  90. if is_void(def) then
  91. begin
  92. paraloc:=result.add_location;
  93. result.size:=OS_NO;
  94. result.intsize:=0;
  95. paraloc^.size:=OS_NO;
  96. paraloc^.loc:=LOC_VOID;
  97. exit;
  98. end;
  99. { Constructors return self instead of a boolean }
  100. if (p.proctypeoption=potype_constructor) then
  101. begin
  102. retcgsize:=OS_INT;
  103. result.intsize:=sizeof(pint);
  104. end
  105. else
  106. begin
  107. retcgsize:=def_cgsize(def);
  108. result.intsize:=def.size;
  109. end;
  110. result.size:=retcgsize;
  111. paraloc:=result.add_location;
  112. { all values are returned on the evaluation stack }
  113. paraloc^.loc:=LOC_REFERENCE;
  114. paraloc^.reference.index:=NR_EVAL_STACK_BASE;
  115. paraloc^.reference.offset:=0;
  116. end;
  117. function TJVMParaManager.param_use_paraloc(const cgpara: tcgpara): boolean;
  118. begin
  119. { all parameters are copied by the VM to local variable locations }
  120. result:=true;
  121. end;
  122. function TJVMParaManager.ret_in_param(def: tdef; calloption: tproccalloption): boolean;
  123. begin
  124. Result:=false;
  125. end;
  126. function TJVMParaManager.is_stack_paraloc(paraloc: pcgparalocation): boolean;
  127. begin
  128. { all parameters are passed on the evaluation stack }
  129. result:=true;
  130. end;
  131. procedure TJVMParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
  132. var parasize:longint);
  133. var
  134. paraloc : pcgparalocation;
  135. i : integer;
  136. hp : tparavarsym;
  137. paracgsize : tcgsize;
  138. paraofs : longint;
  139. begin
  140. paraofs:=0;
  141. for i:=0 to paras.count-1 do
  142. begin
  143. hp:=tparavarsym(paras[i]);
  144. paracgsize:=def_cgsize(hp.vardef);
  145. if paracgsize=OS_NO then
  146. paracgsize:=OS_ADDR;
  147. hp.paraloc[side].reset;
  148. hp.paraloc[side].size:=paracgsize;
  149. hp.paraloc[side].def:=hp.vardef;
  150. hp.paraloc[side].alignment:=std_param_align;
  151. hp.paraloc[side].intsize:=tcgsize2size[paracgsize];
  152. paraloc:=hp.paraloc[side].add_location;
  153. { All parameters are passed on the evaluation stack, pushed from
  154. left to right (including self, if applicable). At the callee side,
  155. they're available as local variables 0..n-1 (with 64 bit values
  156. taking up two slots) }
  157. paraloc^.loc:=LOC_REFERENCE;;
  158. paraloc^.reference.offset:=paraofs;
  159. case side of
  160. callerside:
  161. begin
  162. paraloc^.loc:=LOC_REFERENCE;
  163. { we use a fake loc_reference to indicate the stack location;
  164. the offset (set above) will be used by ncal to order the
  165. parameters so they will be pushed in the right order }
  166. paraloc^.reference.index:=NR_EVAL_STACK_BASE;
  167. end;
  168. calleeside:
  169. begin
  170. paraloc^.loc:=LOC_REFERENCE;
  171. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  172. end;
  173. end;
  174. { 2 slots for 64 bit integers and floats, 1 slot for the rest }
  175. if not(is_64bit(hp.vardef) or
  176. ((hp.vardef.typ=floatdef) and
  177. (tfloatdef(hp.vardef).floattype=s64real))) then
  178. inc(paraofs)
  179. else
  180. inc(paraofs,2);
  181. end;
  182. parasize:=paraofs;
  183. end;
  184. function TJVMParaManager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  185. var
  186. parasize : longint;
  187. begin
  188. parasize:=0;
  189. create_paraloc_info_intern(p,side,p.paras,parasize);
  190. { Create Function result paraloc }
  191. create_funcretloc_info(p,side);
  192. { We need to return the size allocated on the stack }
  193. result:=parasize;
  194. end;
  195. begin
  196. ParaManager:=TJVMParaManager.create;
  197. end.