cpupara.pas 7.5 KB

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