paramgr.pas 21 KB

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