cpupara.pas 7.2 KB

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