n386obj.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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,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 saveregisters
  39. default(0): OK OK OK(1) OK OK OK
  40. virtual(2): OK OK OK(3) OK OK OK(4)
  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 eax to reach the method address so the following code be generated:
  60. set self to correct value
  61. push %ebx ; allocate space for function address
  62. push %eax
  63. mov self,%eax
  64. mov 0(%eax),%eax ; load vmt
  65. mov vmtoffs(%eax),eax ; method offs
  66. mov %eax,4(%esp)
  67. pop %eax
  68. ret 0; jmp the address
  69. }
  70. function getselfoffsetfromsp(procdef: tprocdef): longint;
  71. begin
  72. { framepointer is pushed for nested procs }
  73. if procdef.parast.symtablelevel>normal_function_level then
  74. getselfoffsetfromsp:=2*POINTER_SIZE
  75. else
  76. getselfoffsetfromsp:=POINTER_SIZE;
  77. end;
  78. procedure ti386classheader.cgintfwrapper(asmlist: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);
  79. procedure getselftoeax(offs: longint);
  80. var
  81. href : treference;
  82. begin
  83. { mov offset(%esp),%eax }
  84. reference_reset_base(href,NR_ESP,getselfoffsetfromsp(procdef)+offs);
  85. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,NR_EAX);
  86. end;
  87. procedure loadvmttoeax;
  88. var
  89. href : treference;
  90. begin
  91. { mov 0(%eax),%eax ; load vmt}
  92. reference_reset_base(href,NR_EAX,0);
  93. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,NR_EAX);
  94. end;
  95. procedure op_oneaxmethodaddr(op: TAsmOp);
  96. var
  97. href : treference;
  98. begin
  99. if (procdef.extnumber=-1) then
  100. Internalerror(200006139);
  101. { call/jmp vmtoffs(%eax) ; method offs }
  102. reference_reset_base(href,NR_EAX,procdef._class.vmtmethodoffset(procdef.extnumber));
  103. emit_ref(op,S_L,href);
  104. end;
  105. procedure loadmethodoffstoeax;
  106. var
  107. href : treference;
  108. begin
  109. if (procdef.extnumber=-1) then
  110. Internalerror(200006139);
  111. { mov vmtoffs(%eax),%eax ; method offs }
  112. reference_reset_base(href,NR_EAX,procdef._class.vmtmethodoffset(procdef.extnumber));
  113. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,NR_EAX);
  114. end;
  115. var
  116. oldexprasmlist: TAAsmoutput;
  117. lab : tasmsymbol;
  118. make_global : boolean;
  119. href : treference;
  120. begin
  121. if procdef.proctypeoption<>potype_none then
  122. Internalerror(200006137);
  123. if not assigned(procdef._class) or
  124. (procdef.procoptions*[po_classmethod, po_staticmethod,
  125. po_methodpointer, po_interrupt, po_iocheck]<>[]) then
  126. Internalerror(200006138);
  127. if procdef.owner.symtabletype<>objectsymtable then
  128. Internalerror(200109191);
  129. oldexprasmlist:=exprasmlist;
  130. exprasmlist:=asmlist;
  131. make_global:=false;
  132. if (not current_module.is_unit) or
  133. (cs_create_smart in aktmoduleswitches) or
  134. (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
  135. make_global:=true;
  136. if make_global then
  137. exprasmList.concat(Tai_symbol.Createname_global(labelname,0))
  138. else
  139. exprasmList.concat(Tai_symbol.Createname(labelname,0));
  140. { set param1 interface to self }
  141. adjustselfvalue(procdef,ioffset);
  142. { case 1 or 2 }
  143. if (procdef.proccalloption in clearstack_pocalls) then
  144. begin
  145. if po_virtualmethod in procdef.procoptions then
  146. begin { case 2 }
  147. getselftoeax(0);
  148. loadvmttoeax;
  149. op_oneaxmethodaddr(A_CALL);
  150. end
  151. else { case 1 }
  152. cg.a_call_name(exprasmlist,procdef.mangledname);
  153. { restore param1 value self to interface }
  154. adjustselfvalue(procdef,-ioffset);
  155. end
  156. { case 3 }
  157. else if [po_virtualmethod,po_saveregisters]*procdef.procoptions=[po_virtualmethod,po_saveregisters] then
  158. begin
  159. emit_reg(A_PUSH,S_L,NR_EBX); { allocate space for address}
  160. emit_reg(A_PUSH,S_L,NR_EAX);
  161. getselftoeax(8);
  162. loadvmttoeax;
  163. loadmethodoffstoeax;
  164. { mov %eax,4(%esp) }
  165. reference_reset_base(href,NR_ESP,4);
  166. emit_reg_ref(A_MOV,S_L,NR_EAX,href);
  167. { pop %eax }
  168. emit_reg(A_POP,S_L,NR_EAX);
  169. { ret ; jump to the address }
  170. emit_none(A_RET,S_L);
  171. end
  172. { case 4 }
  173. else if po_virtualmethod in procdef.procoptions then
  174. begin
  175. getselftoeax(0);
  176. loadvmttoeax;
  177. op_oneaxmethodaddr(A_JMP);
  178. end
  179. { case 0 }
  180. else
  181. begin
  182. lab:=objectlibrary.newasmsymbol(procdef.mangledname);
  183. emit_sym(A_JMP,S_NO,lab);
  184. end;
  185. exprasmlist:=oldexprasmlist;
  186. end;
  187. initialization
  188. cclassheader:=ti386classheader;
  189. end.
  190. {
  191. $Log$
  192. Revision 1.27 2003-10-10 17:48:14 peter
  193. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  194. * tregisteralloctor renamed to trgobj
  195. * removed rgobj from a lot of units
  196. * moved location_* and reference_* to cgobj
  197. * first things for mmx register allocation
  198. Revision 1.26 2003/10/01 20:34:49 peter
  199. * procinfo unit contains tprocinfo
  200. * cginfo renamed to cgbase
  201. * moved cgmessage to verbose
  202. * fixed ppc and sparc compiles
  203. Revision 1.25 2003/09/25 21:30:11 peter
  204. * parameter fixes
  205. Revision 1.24 2003/09/25 14:59:06 peter
  206. * fix intf wrapper code
  207. Revision 1.23 2003/09/23 17:56:06 peter
  208. * locals and paras are allocated in the code generation
  209. * tvarsym.localloc contains the location of para/local when
  210. generating code for the current procedure
  211. Revision 1.22 2003/09/07 22:09:35 peter
  212. * preparations for different default calling conventions
  213. * various RA fixes
  214. Revision 1.21 2003/09/03 15:55:01 peter
  215. * NEWRA branch merged
  216. Revision 1.20.2.1 2003/08/29 17:29:00 peter
  217. * next batch of updates
  218. Revision 1.20 2003/06/03 21:11:09 peter
  219. * cg.a_load_* get a from and to size specifier
  220. * makeregsize only accepts newregister
  221. * i386 uses generic tcgnotnode,tcgunaryminus
  222. Revision 1.19 2003/05/15 18:58:54 peter
  223. * removed selfpointer_offset, vmtpointer_offset
  224. * tvarsym.adjusted_address
  225. * address in localsymtable is now in the real direction
  226. * removed some obsolete globals
  227. Revision 1.18 2003/04/22 14:33:38 peter
  228. * removed some notes/hints
  229. Revision 1.17 2003/01/13 14:54:34 daniel
  230. * Further work to convert codegenerator register convention;
  231. internalerror bug fixed.
  232. Revision 1.16 2003/01/08 18:43:57 daniel
  233. * Tregister changed into a record
  234. Revision 1.15 2002/08/11 14:32:30 peter
  235. * renamed current_library to objectlibrary
  236. Revision 1.14 2002/08/11 13:24:17 peter
  237. * saving of asmsymbols in ppu supported
  238. * asmsymbollist global is removed and moved into a new class
  239. tasmlibrarydata that will hold the info of a .a file which
  240. corresponds with a single module. Added librarydata to tmodule
  241. to keep the library info stored for the module. In the future the
  242. objectfiles will also be stored to the tasmlibrarydata class
  243. * all getlabel/newasmsymbol and friends are moved to the new class
  244. Revision 1.13 2002/08/09 07:33:04 florian
  245. * a couple of interface related fixes
  246. Revision 1.12 2002/07/16 15:34:21 florian
  247. * exit is now a syssym instead of a keyword
  248. Revision 1.11 2002/07/01 18:46:33 peter
  249. * internal linker
  250. * reorganized aasm layer
  251. Revision 1.10 2002/05/18 13:34:25 peter
  252. * readded missing revisions
  253. Revision 1.9 2002/05/16 19:46:52 carl
  254. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  255. + try to fix temp allocation (still in ifdef)
  256. + generic constructor calls
  257. + start of tassembler / tmodulebase class cleanup
  258. Revision 1.7 2002/05/12 16:53:17 peter
  259. * moved entry and exitcode to ncgutil and cgobj
  260. * foreach gets extra argument for passing local data to the
  261. iterator function
  262. * -CR checks also class typecasts at runtime by changing them
  263. into as
  264. * fixed compiler to cycle with the -CR option
  265. * fixed stabs with elf writer, finally the global variables can
  266. be watched
  267. * removed a lot of routines from cga unit and replaced them by
  268. calls to cgobj
  269. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  270. u32bit then the other is typecasted also to u32bit without giving
  271. a rangecheck warning/error.
  272. * fixed pascal calling method with reversing also the high tree in
  273. the parast, detected by tcalcst3 test
  274. Revision 1.6 2002/04/02 17:11:36 peter
  275. * tlocation,treference update
  276. * LOC_CONSTANT added for better constant handling
  277. * secondadd splitted in multiple routines
  278. * location_force_reg added for loading a location to a register
  279. of a specified size
  280. * secondassignment parses now first the right and then the left node
  281. (this is compatible with Kylix). This saves a lot of push/pop especially
  282. with string operations
  283. * adapted some routines to use the new cg methods
  284. Revision 1.5 2002/03/31 20:26:39 jonas
  285. + a_loadfpu_* and a_loadmm_* methods in tcg
  286. * register allocation is now handled by a class and is mostly processor
  287. independent (+rgobj.pas and i386/rgcpu.pas)
  288. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  289. * some small improvements and fixes to the optimizer
  290. * some register allocation fixes
  291. * some fpuvaroffset fixes in the unary minus node
  292. * push/popusedregisters is now called rg.save/restoreusedregisters and
  293. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  294. also better optimizable)
  295. * fixed and optimized register saving/restoring for new/dispose nodes
  296. * LOC_FPU locations now also require their "register" field to be set to
  297. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  298. - list field removed of the tnode class because it's not used currently
  299. and can cause hard-to-find bugs
  300. }