n386obj.pas 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Kovacs Attila Zoltan
  4. Generate i386 assembly wrapper code interface implementor objects
  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. unit n386obj;
  19. {$i fpcdefs.inc}
  20. interface
  21. implementation
  22. uses
  23. systems,
  24. verbose,globals,globtype,
  25. aasmbase,aasmtai,
  26. symconst,symdef,
  27. fmodule,
  28. nobj,
  29. cpuinfo,cpubase,
  30. cga,cgutils,cgobj;
  31. type
  32. ti386classheader=class(tclassheader)
  33. protected
  34. procedure cgintfwrapper(asmlist: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);override;
  35. end;
  36. {
  37. possible calling conventions:
  38. default stdcall cdecl pascal register
  39. default(0): OK OK OK(1) OK OK
  40. virtual(2): OK OK OK(3) OK OK
  41. (0):
  42. set self parameter to correct value
  43. jmp mangledname
  44. (1): The code is the following
  45. set self parameter to correct value
  46. call mangledname
  47. set self parameter to interface value
  48. (2): The wrapper code use %eax to reach the virtual method address
  49. set self to correct value
  50. move self,%eax
  51. mov 0(%eax),%eax ; load vmt
  52. jmp vmtoffs(%eax) ; method offs
  53. (3): The wrapper code use %eax to reach the virtual method address
  54. set self to correct value
  55. move self,%eax
  56. mov 0(%eax),%eax ; load vmt
  57. jmp vmtoffs(%eax) ; method offs
  58. set self parameter to interface value
  59. (4): Virtual use values pushed on stack to reach the method address
  60. so the following code be generated:
  61. set self to correct value
  62. push %ebx ; allocate space for function address
  63. push %eax
  64. mov self,%eax
  65. mov 0(%eax),%eax ; load vmt
  66. mov vmtoffs(%eax),eax ; method offs
  67. mov %eax,4(%esp)
  68. pop %eax
  69. ret 0; jmp the address
  70. }
  71. function getselfoffsetfromsp(procdef: tprocdef): longint;
  72. begin
  73. { framepointer is pushed for nested procs }
  74. if procdef.parast.symtablelevel>normal_function_level then
  75. getselfoffsetfromsp:=2*sizeof(aint)
  76. else
  77. getselfoffsetfromsp:=sizeof(aint);
  78. end;
  79. procedure ti386classheader.cgintfwrapper(asmlist: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);
  80. procedure getselftoeax(offs: longint);
  81. var
  82. href : treference;
  83. begin
  84. { mov offset(%esp),%eax }
  85. if (procdef.proccalloption<>pocall_register) then
  86. begin
  87. reference_reset_base(href,NR_ESP,getselfoffsetfromsp(procdef)+offs);
  88. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,NR_EAX);
  89. end;
  90. end;
  91. procedure loadvmttoeax;
  92. var
  93. href : treference;
  94. begin
  95. { mov 0(%eax),%eax ; load vmt}
  96. reference_reset_base(href,NR_EAX,0);
  97. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,NR_EAX);
  98. end;
  99. procedure op_oneaxmethodaddr(op: TAsmOp);
  100. var
  101. href : treference;
  102. begin
  103. if (procdef.extnumber=$ffff) then
  104. Internalerror(200006139);
  105. { call/jmp vmtoffs(%eax) ; method offs }
  106. reference_reset_base(href,NR_EAX,procdef._class.vmtmethodoffset(procdef.extnumber));
  107. emit_ref(op,S_L,href);
  108. end;
  109. procedure loadmethodoffstoeax;
  110. var
  111. href : treference;
  112. begin
  113. if (procdef.extnumber=$ffff) then
  114. Internalerror(200006139);
  115. { mov vmtoffs(%eax),%eax ; method offs }
  116. reference_reset_base(href,NR_EAX,procdef._class.vmtmethodoffset(procdef.extnumber));
  117. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,NR_EAX);
  118. end;
  119. var
  120. oldexprasmlist: TAAsmoutput;
  121. lab : tasmsymbol;
  122. make_global : boolean;
  123. href : treference;
  124. begin
  125. if procdef.proctypeoption<>potype_none then
  126. Internalerror(200006137);
  127. if not assigned(procdef._class) or
  128. (procdef.procoptions*[po_classmethod, po_staticmethod,
  129. po_methodpointer, po_interrupt, po_iocheck]<>[]) then
  130. Internalerror(200006138);
  131. if procdef.owner.symtabletype<>objectsymtable then
  132. Internalerror(200109191);
  133. oldexprasmlist:=exprasmlist;
  134. exprasmlist:=asmlist;
  135. make_global:=false;
  136. if (not current_module.is_unit) or
  137. (cs_create_smart in aktmoduleswitches) or
  138. (af_smartlink_sections in target_asm.flags) or
  139. (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
  140. make_global:=true;
  141. if make_global then
  142. exprasmList.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
  143. else
  144. exprasmList.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
  145. { set param1 interface to self }
  146. adjustselfvalue(procdef,ioffset);
  147. { case 1 or 2 }
  148. if (procdef.proccalloption in clearstack_pocalls) then
  149. begin
  150. if po_virtualmethod in procdef.procoptions then
  151. begin
  152. { case 2 }
  153. getselftoeax(0);
  154. loadvmttoeax;
  155. op_oneaxmethodaddr(A_CALL);
  156. end
  157. else
  158. begin
  159. { case 1 }
  160. cg.a_call_name(exprasmlist,procdef.mangledname);
  161. end;
  162. { restore param1 value self to interface }
  163. adjustselfvalue(procdef,-ioffset);
  164. end
  165. else if po_virtualmethod in procdef.procoptions then
  166. begin
  167. if (procdef.proccalloption=pocall_register) then
  168. begin
  169. { case 4 }
  170. emit_reg(A_PUSH,S_L,NR_EBX); { allocate space for address}
  171. emit_reg(A_PUSH,S_L,NR_EAX);
  172. getselftoeax(8);
  173. loadvmttoeax;
  174. loadmethodoffstoeax;
  175. { mov %eax,4(%esp) }
  176. reference_reset_base(href,NR_ESP,4);
  177. emit_reg_ref(A_MOV,S_L,NR_EAX,href);
  178. { pop %eax }
  179. emit_reg(A_POP,S_L,NR_EAX);
  180. { ret ; jump to the address }
  181. emit_none(A_RET,S_L);
  182. end
  183. else
  184. begin
  185. { case 3 }
  186. getselftoeax(0);
  187. loadvmttoeax;
  188. op_oneaxmethodaddr(A_JMP);
  189. end;
  190. end
  191. { case 0 }
  192. else
  193. begin
  194. lab:=objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION);
  195. emit_sym(A_JMP,S_NO,lab);
  196. end;
  197. exprasmList.concat(Tai_symbol_end.Createname(labelname));
  198. exprasmlist:=oldexprasmlist;
  199. end;
  200. initialization
  201. cclassheader:=ti386classheader;
  202. end.
  203. {
  204. $Log$
  205. Revision 1.35 2004-10-24 20:01:08 peter
  206. * remove saveregister calling convention
  207. Revision 1.34 2004/06/20 08:55:31 florian
  208. * logs truncated
  209. Revision 1.33 2004/06/16 20:07:10 florian
  210. * dwarf branch merged
  211. Revision 1.32.2.2 2004/05/01 16:02:10 peter
  212. * POINTER_SIZE replaced with sizeof(aint)
  213. * aint,aword,tconst*int moved to globtype
  214. Revision 1.32.2.1 2004/04/08 18:33:22 peter
  215. * rewrite of TAsmSection
  216. Revision 1.32 2004/03/02 00:36:33 olle
  217. * big transformation of Tai_[const_]Symbol.Create[data]name*
  218. Revision 1.31 2004/02/27 13:42:52 olle
  219. + added Tai_symbol_end
  220. }