paramgr.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. {
  2. $Id$
  3. Copyright (c) 2002 by Florian Klaempfl
  4. Generic calling convention handling
  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. {# Parameter passing manager. Used to manage how
  19. parameters are passed to routines.
  20. }
  21. unit paramgr;
  22. {$i fpcdefs.inc}
  23. interface
  24. uses
  25. cpubase,
  26. aasmtai,
  27. globtype,
  28. symconst,symtype,symdef;
  29. type
  30. {# This class defines some methods to take care of routine
  31. parameters. It should be overriden for each new processor
  32. }
  33. tparamanager = class
  34. {# Returns true if the return value is actually a parameter
  35. pointer.
  36. }
  37. function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;virtual;
  38. function push_high_param(def : tdef;calloption : tproccalloption) : boolean;virtual;
  39. { Returns true if a parameter is too large to copy and only
  40. the address is pushed
  41. }
  42. function push_addr_param(def : tdef;calloption : tproccalloption) : boolean;virtual;
  43. { return the size of a push }
  44. function push_size(varspez:tvarspez;def : tdef;calloption : tproccalloption) : longint;
  45. { Returns true if a parameter needs to be copied on the stack, this
  46. is required for cdecl procedures
  47. }
  48. function copy_value_on_stack(def : tdef;calloption : tproccalloption) : boolean;
  49. {# Returns a structure giving the information on
  50. the storage of the parameter (which must be
  51. an integer parameter). This is only used when calling
  52. internal routines directly, where all parameters must
  53. be 4-byte values.
  54. In case the location is a register, this register is allocated.
  55. Call freeintparaloc() after the call to free the locations again.
  56. Default implementation: don't do anything at all (in case you don't
  57. use register parameter passing)
  58. @param(list Current assembler list)
  59. @param(nr Parameter number of routine, starting from 1)
  60. }
  61. function getintparaloc(list: taasmoutput; nr : longint) : tparalocation;virtual;abstract;
  62. {# frees a parameter location allocated with getintparaloc
  63. @param(list Current assembler list)
  64. @param(nr Parameter number of routine, starting from 1)
  65. }
  66. procedure freeintparaloc(list: taasmoutput; nr : longint); virtual; abstract;
  67. {# allocate a parameter location created with create_paraloc_info
  68. @param(list Current assembler list)
  69. @param(loc Parameter location)
  70. }
  71. procedure allocparaloc(list: taasmoutput; const loc: tparalocation); virtual;
  72. {# free a parameter location allocated with allocparaloc
  73. @param(list Current assembler list)
  74. @param(loc Parameter location)
  75. }
  76. procedure freeparaloc(list: taasmoutput; const loc: tparalocation); virtual;
  77. {# This is used to populate the location information on all parameters
  78. for the routine. This is used for normal call resolution.
  79. }
  80. procedure create_paraloc_info(p : tabstractprocdef);virtual;abstract;
  81. {
  82. Returns the location where the invisible parameter for structured
  83. function results will be passed.
  84. }
  85. function getfuncretparaloc(p : tabstractprocdef) : tparalocation;virtual;
  86. {
  87. Returns the location where the invisible parameter for nested
  88. subroutines is passed.
  89. }
  90. function getframepointerloc(p : tabstractprocdef) : tparalocation;virtual;
  91. { Returns the self pointer location for the given tabstractprocdef,
  92. when the stack frame is already created. This is used by the code
  93. generating the wrappers for implemented interfaces.
  94. }
  95. function getselflocation(p : tabstractprocdef) : tparalocation;virtual;abstract;
  96. {
  97. Returns the location of the result if the result is in
  98. a register, the register(s) return depend on the type of
  99. the result.
  100. @param(def The definition of the result type of the function)
  101. }
  102. function getfuncresultloc(def : tdef;calloption:tproccalloption): tparalocation;virtual;
  103. procedure splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);virtual;
  104. end;
  105. var
  106. paralocdummy : tparalocation;
  107. paramanager : tparamanager;
  108. implementation
  109. uses
  110. cpuinfo,globals,systems,
  111. symbase,symsym,
  112. rgobj,
  113. defutil,cgbase,cginfo,verbose;
  114. { true if uses a parameter as return value }
  115. function tparamanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
  116. begin
  117. ret_in_param:=(def.deftype in [arraydef,recorddef]) or
  118. ((def.deftype=stringdef) and (tstringdef(def).string_typ in [st_shortstring,st_longstring])) or
  119. ((def.deftype=procvardef) and (po_methodpointer in tprocvardef(def).procoptions)) or
  120. ((def.deftype=objectdef) and is_object(def)) or
  121. (def.deftype=variantdef) or
  122. ((def.deftype=setdef) and (tsetdef(def).settype<>smallset));
  123. end;
  124. function tparamanager.push_high_param(def : tdef;calloption : tproccalloption) : boolean;
  125. begin
  126. push_high_param:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and
  127. (
  128. is_open_array(def) or
  129. is_open_string(def) or
  130. is_array_of_const(def)
  131. );
  132. end;
  133. { true if a parameter is too large to copy and only the address is pushed }
  134. function tparamanager.push_addr_param(def : tdef;calloption : tproccalloption) : boolean;
  135. begin
  136. push_addr_param:=false;
  137. case def.deftype of
  138. variantdef,
  139. formaldef :
  140. push_addr_param:=true;
  141. recorddef :
  142. push_addr_param:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (def.size>pointer_size);
  143. arraydef :
  144. begin
  145. if (calloption in [pocall_cdecl,pocall_cppdecl]) then
  146. begin
  147. { array of const values are pushed on the stack }
  148. push_addr_param:=not is_array_of_const(def);
  149. end
  150. else
  151. begin
  152. push_addr_param:=(
  153. (tarraydef(def).highrange>=tarraydef(def).lowrange) and
  154. (def.size>pointer_size)
  155. ) or
  156. is_open_array(def) or
  157. is_array_of_const(def) or
  158. is_array_constructor(def);
  159. end;
  160. end;
  161. objectdef :
  162. push_addr_param:=is_object(def);
  163. stringdef :
  164. push_addr_param:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (tstringdef(def).string_typ in [st_shortstring,st_longstring]);
  165. procvardef :
  166. push_addr_param:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (po_methodpointer in tprocvardef(def).procoptions);
  167. setdef :
  168. push_addr_param:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (tsetdef(def).settype<>smallset);
  169. end;
  170. end;
  171. { true if a parameter is too large to push and needs a concatcopy to get the value on the stack }
  172. function tparamanager.copy_value_on_stack(def : tdef;calloption : tproccalloption) : boolean;
  173. begin
  174. copy_value_on_stack:=false;
  175. { this is only for cdecl procedures }
  176. if not(calloption in [pocall_cdecl,pocall_cppdecl]) then
  177. exit;
  178. case def.deftype of
  179. variantdef,
  180. formaldef :
  181. copy_value_on_stack:=true;
  182. recorddef :
  183. copy_value_on_stack:=(def.size>pointer_size);
  184. arraydef :
  185. copy_value_on_stack:=(tarraydef(def).highrange>=tarraydef(def).lowrange) and
  186. (def.size>pointer_size);
  187. objectdef :
  188. copy_value_on_stack:=is_object(def);
  189. stringdef :
  190. copy_value_on_stack:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
  191. procvardef :
  192. copy_value_on_stack:=(po_methodpointer in tprocvardef(def).procoptions);
  193. setdef :
  194. copy_value_on_stack:=(tsetdef(def).settype<>smallset);
  195. end;
  196. end;
  197. { return the size of a push }
  198. function tparamanager.push_size(varspez:tvarspez;def : tdef;calloption : tproccalloption) : longint;
  199. begin
  200. push_size:=-1;
  201. case varspez of
  202. vs_out,
  203. vs_var :
  204. push_size:=pointer_size;
  205. vs_value,
  206. vs_const :
  207. begin
  208. if push_addr_param(def,calloption) then
  209. push_size:=pointer_size
  210. else
  211. begin
  212. { special array are normally pushed by addr, only for
  213. cdecl array of const it comes here and the pushsize
  214. is unknown }
  215. if is_array_of_const(def) then
  216. push_size:=0
  217. else
  218. push_size:=def.size;
  219. end;
  220. end;
  221. end;
  222. end;
  223. procedure tparamanager.allocparaloc(list: taasmoutput; const loc: tparalocation);
  224. begin
  225. case loc.loc of
  226. LOC_REGISTER, LOC_CREGISTER:
  227. begin
  228. {$ifndef cpu64bit}
  229. if (loc.size in [OS_64,OS_S64,OS_F64]) then
  230. begin
  231. rg.getexplicitregisterint(list,loc.registerhigh.number);
  232. rg.getexplicitregisterint(list,loc.registerlow.number);
  233. end
  234. else
  235. {$endif cpu64bit}
  236. rg.getexplicitregisterint(list,loc.register.number);
  237. end;
  238. LOC_FPUREGISTER, LOC_CFPUREGISTER:
  239. rg.getexplicitregisterfpu(list,loc.register.enum);
  240. LOC_REFERENCE,LOC_CREFERENCE:
  241. { do nothing by default, most of the time it's the framepointer }
  242. else
  243. internalerror(200306091);
  244. end;
  245. end;
  246. procedure tparamanager.freeparaloc(list: taasmoutput; const loc: tparalocation);
  247. begin
  248. case loc.loc of
  249. LOC_REGISTER, LOC_CREGISTER:
  250. begin
  251. {$ifndef cpu64bit}
  252. if (loc.size in [OS_64,OS_S64,OS_F64]) then
  253. begin
  254. rg.ungetregisterint(list,loc.registerhigh);
  255. rg.ungetregisterint(list,loc.registerlow);
  256. end
  257. else
  258. {$endif cpu64bit}
  259. rg.ungetregisterint(list,loc.register);
  260. end;
  261. LOC_FPUREGISTER, LOC_CFPUREGISTER:
  262. rg.ungetregisterfpu(list,loc.register,loc.size);
  263. LOC_REFERENCE,LOC_CREFERENCE:
  264. { do nothing by default, most of the time it's the framepointer }
  265. else
  266. internalerror(200306091);
  267. end;
  268. end;
  269. function tparamanager.getfuncretparaloc(p : tabstractprocdef) : tparalocation;
  270. begin
  271. result.loc:=LOC_REFERENCE;
  272. result.size:=OS_ADDR;
  273. result.sp_fixup:=pointer_size;
  274. result.reference.index.enum:=R_INTREGISTER;
  275. result.reference.index.number:=NR_STACK_POINTER_REG;
  276. result.reference.offset:=0;
  277. end;
  278. function tparamanager.getframepointerloc(p : tabstractprocdef) : tparalocation;
  279. begin
  280. result.loc:=LOC_REFERENCE;
  281. result.size:=OS_ADDR;
  282. result.sp_fixup:=pointer_size;
  283. result.reference.index.enum:=R_INTREGISTER;
  284. result.reference.index.number:=NR_STACK_POINTER_REG;
  285. result.reference.offset:=0;
  286. end;
  287. function tparamanager.getfuncresultloc(def : tdef;calloption:tproccalloption): tparalocation;
  288. begin
  289. fillchar(result,sizeof(tparalocation),0);
  290. if is_void(def) then exit;
  291. result.size := def_cgsize(def);
  292. case def.deftype of
  293. orddef,
  294. enumdef :
  295. begin
  296. result.loc := LOC_REGISTER;
  297. {$ifndef cpu64bit}
  298. if result.size in [OS_64,OS_S64] then
  299. begin
  300. result.register64.reglo.enum:=R_INTREGISTER;
  301. result.register64.reglo.number:=NR_FUNCTION_RETURN64_LOW_REG;
  302. result.register64.reghi.enum:=R_INTREGISTER;
  303. result.register64.reghi.number:=NR_FUNCTION_RETURN64_HIGH_REG;
  304. end
  305. else
  306. {$endif cpu64bit}
  307. begin
  308. result.register.enum:=R_INTREGISTER;
  309. result.register.number:=NR_FUNCTION_RETURN_REG;
  310. end;
  311. end;
  312. floatdef :
  313. begin
  314. result.loc := LOC_FPUREGISTER;
  315. {$ifdef cpufpemu}
  316. if cs_fp_emulation in aktmoduleswitches then
  317. begin
  318. result.register.enum:=R_INTREGISTER;
  319. result.register.number:=FUNCTION_RETURN_REG;
  320. end
  321. else
  322. {$endif cpufpemu}
  323. result.register.enum := FPU_RESULT_REG;
  324. end;
  325. else
  326. begin
  327. if not ret_in_param(def,calloption) then
  328. begin
  329. result.loc := LOC_REGISTER;
  330. result.register.enum:=R_INTREGISTER;
  331. result.register.number:=NR_FUNCTION_RETURN_REG;
  332. end
  333. else
  334. begin
  335. result.loc := LOC_REFERENCE;
  336. internalerror(2002081602);
  337. (*
  338. {$ifdef EXTDEBUG}
  339. { it is impossible to have the
  340. return value with an index register
  341. and a symbol!
  342. }
  343. if (ref.index <> R_NO) or (assigned(ref.symbol)) then
  344. internalerror(2002081602);
  345. {$endif}
  346. result.reference.index := ref.base;
  347. result.reference.offset := ref.offset;
  348. *)
  349. end;
  350. end;
  351. end;
  352. end;
  353. procedure tparamanager.splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);
  354. begin
  355. if not(locpara.size in [OS_64,OS_S64]) then
  356. internalerror(200307023);
  357. lochipara:=locpara;
  358. loclopara:=locpara;
  359. if locpara.size=OS_S64 then
  360. lochipara.size:=OS_S32
  361. else
  362. lochipara.size:=OS_32;
  363. loclopara.size:=OS_32;
  364. case locpara.loc of
  365. LOC_REGISTER,LOC_CREGISTER:
  366. begin
  367. loclopara.register:=locpara.registerlow;
  368. lochipara.register:=locpara.registerhigh;
  369. end;
  370. LOC_REFERENCE:
  371. begin
  372. if target_info.endian=endian_big then
  373. inc(loclopara.reference.offset,4)
  374. else
  375. inc(lochipara.reference.offset,4);
  376. end;
  377. else
  378. internalerror(200307024);
  379. end;
  380. end;
  381. initialization
  382. ;
  383. finalization
  384. paramanager.free;
  385. end.
  386. {
  387. $Log$
  388. Revision 1.47 2003-07-02 22:18:04 peter
  389. * paraloc splitted in callerparaloc,calleeparaloc
  390. * sparc calling convention updates
  391. Revision 1.46 2003/06/17 16:32:03 peter
  392. * allocpara/freepara 64bit support
  393. Revision 1.45 2003/06/13 21:19:30 peter
  394. * current_procdef removed, use current_procinfo.procdef instead
  395. Revision 1.44 2003/06/12 21:11:10 peter
  396. * ungetregisterfpu gets size parameter
  397. Revision 1.43 2003/06/09 14:54:26 jonas
  398. * (de)allocation of registers for parameters is now performed properly
  399. (and checked on the ppc)
  400. - removed obsolete allocation of all parameter registers at the start
  401. of a procedure (and deallocation at the end)
  402. Revision 1.42 2003/06/08 10:54:41 jonas
  403. - disabled changing of LOC_*REGISTER to LOC_C*REGISTER in setparalocs,
  404. this is not necessary anymore (doesn't do anything anymore actually,
  405. except making sure the interface crc changes)
  406. Revision 1.41 2003/06/07 18:57:04 jonas
  407. + added freeintparaloc
  408. * ppc get/freeintparaloc now check whether the parameter regs are
  409. properly allocated/deallocated (and get an extra list para)
  410. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  411. * fixed lot of missing pi_do_call's
  412. Revision 1.40 2003/05/31 15:05:28 peter
  413. * FUNCTION_RESULT64_LOW/HIGH_REG added for int64 results
  414. Revision 1.39 2003/05/30 23:57:08 peter
  415. * more sparc cleanup
  416. * accumulator removed, splitted in function_return_reg (called) and
  417. function_result_reg (caller)
  418. Revision 1.38 2003/05/13 15:16:13 peter
  419. * removed ret_in_acc, it's the reverse of ret_in_param
  420. * fixed ret_in_param for win32 cdecl array
  421. Revision 1.37 2003/04/30 22:15:59 florian
  422. * some 64 bit adaptions in ncgadd
  423. * x86-64 now uses ncgadd
  424. * tparamanager.ret_in_acc doesn't return true anymore for a void-def
  425. Revision 1.36 2003/04/27 11:21:33 peter
  426. * aktprocdef renamed to current_procinfo.procdef
  427. * procinfo renamed to current_procinfo
  428. * procinfo will now be stored in current_module so it can be
  429. cleaned up properly
  430. * gen_main_procsym changed to create_main_proc and release_main_proc
  431. to also generate a tprocinfo structure
  432. * fixed unit implicit initfinal
  433. Revision 1.35 2003/04/27 07:29:50 peter
  434. * current_procinfo.procdef cleanup, current_procdef is now always nil when parsing
  435. a new procdef declaration
  436. * aktprocsym removed
  437. * lexlevel removed, use symtable.symtablelevel instead
  438. * implicit init/final code uses the normal genentry/genexit
  439. * funcret state checking updated for new funcret handling
  440. Revision 1.34 2003/04/23 13:15:04 peter
  441. * fix push_high_param for cdecl
  442. Revision 1.33 2003/04/23 10:14:30 peter
  443. * cdecl array of const has no addr push
  444. Revision 1.32 2003/04/22 13:47:08 peter
  445. * fixed C style array of const
  446. * fixed C array passing
  447. * fixed left to right with high parameters
  448. Revision 1.31 2003/02/02 19:25:54 carl
  449. * Several bugfixes for m68k target (register alloc., opcode emission)
  450. + VIS target
  451. + Generic add more complete (still not verified)
  452. Revision 1.30 2003/01/08 18:43:56 daniel
  453. * Tregister changed into a record
  454. Revision 1.29 2002/12/23 20:58:03 peter
  455. * remove unused global var
  456. Revision 1.28 2002/12/17 22:19:33 peter
  457. * fixed pushing of records>8 bytes with stdcall
  458. * simplified hightree loading
  459. Revision 1.27 2002/12/06 16:56:58 peter
  460. * only compile cs_fp_emulation support when cpufpuemu is defined
  461. * define cpufpuemu for m68k only
  462. Revision 1.26 2002/11/27 20:04:09 peter
  463. * tvarsym.get_push_size replaced by paramanager.push_size
  464. Revision 1.25 2002/11/27 02:33:19 peter
  465. * copy_value_on_stack method added for cdecl record passing
  466. Revision 1.24 2002/11/25 17:43:21 peter
  467. * splitted defbase in defutil,symutil,defcmp
  468. * merged isconvertable and is_equal into compare_defs(_ext)
  469. * made operator search faster by walking the list only once
  470. Revision 1.23 2002/11/18 17:31:58 peter
  471. * pass proccalloption to ret_in_xxx and push_xxx functions
  472. Revision 1.22 2002/11/16 18:00:04 peter
  473. * only push small arrays on the stack for win32
  474. Revision 1.21 2002/10/05 12:43:25 carl
  475. * fixes for Delphi 6 compilation
  476. (warning : Some features do not work under Delphi)
  477. Revision 1.20 2002/09/30 07:07:25 florian
  478. * fixes to common code to get the alpha compiler compiled applied
  479. Revision 1.19 2002/09/30 07:00:47 florian
  480. * fixes to common code to get the alpha compiler compiled applied
  481. Revision 1.18 2002/09/09 09:10:51 florian
  482. + added generic tparamanager.getframepointerloc
  483. Revision 1.17 2002/09/07 19:40:39 florian
  484. * tvarsym.paraitem is set now
  485. Revision 1.16 2002/09/01 21:04:48 florian
  486. * several powerpc related stuff fixed
  487. Revision 1.15 2002/08/25 19:25:19 peter
  488. * sym.insert_in_data removed
  489. * symtable.insertvardata/insertconstdata added
  490. * removed insert_in_data call from symtable.insert, it needs to be
  491. called separatly. This allows to deref the address calculation
  492. * procedures now calculate the parast addresses after the procedure
  493. directives are parsed. This fixes the cdecl parast problem
  494. * push_addr_param has an extra argument that specifies if cdecl is used
  495. or not
  496. Revision 1.14 2002/08/17 22:09:47 florian
  497. * result type handling in tcgcal.pass_2 overhauled
  498. * better tnode.dowrite
  499. * some ppc stuff fixed
  500. Revision 1.13 2002/08/17 09:23:38 florian
  501. * first part of procinfo rewrite
  502. Revision 1.12 2002/08/16 14:24:58 carl
  503. * issameref() to test if two references are the same (then emit no opcodes)
  504. + ret_in_reg to replace ret_in_acc
  505. (fix some register allocation bugs at the same time)
  506. + save_std_register now has an extra parameter which is the
  507. usedinproc registers
  508. Revision 1.11 2002/08/12 15:08:40 carl
  509. + stab register indexes for powerpc (moved from gdb to cpubase)
  510. + tprocessor enumeration moved to cpuinfo
  511. + linker in target_info is now a class
  512. * many many updates for m68k (will soon start to compile)
  513. - removed some ifdef or correct them for correct cpu
  514. Revision 1.10 2002/08/10 17:15:20 jonas
  515. * register parameters are now LOC_CREGISTER instead of LOC_REGISTER
  516. Revision 1.9 2002/08/09 07:33:02 florian
  517. * a couple of interface related fixes
  518. Revision 1.8 2002/08/06 20:55:21 florian
  519. * first part of ppc calling conventions fix
  520. Revision 1.7 2002/08/05 18:27:48 carl
  521. + more more more documentation
  522. + first version include/exclude (can't test though, not enough scratch for i386 :()...
  523. Revision 1.6 2002/07/30 20:50:43 florian
  524. * the code generator knows now if parameters are in registers
  525. Revision 1.5 2002/07/26 21:15:39 florian
  526. * rewrote the system handling
  527. Revision 1.4 2002/07/20 11:57:55 florian
  528. * types.pas renamed to defbase.pas because D6 contains a types
  529. unit so this would conflicts if D6 programms are compiled
  530. + Willamette/SSE2 instructions to assembler added
  531. Revision 1.3 2002/07/13 19:38:43 florian
  532. * some more generic calling stuff fixed
  533. Revision 1.2 2002/07/13 07:17:15 jonas
  534. * fixed memory leak reported by Sergey Korshunoff
  535. Revision 1.1 2002/07/11 14:41:28 florian
  536. * start of the new generic parameter handling
  537. }