paramgr.pas 23 KB

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