ncgcal.pas 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate assembler for call nodes
  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 ncgcal;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cpubase,
  23. globtype,
  24. symdef,node,ncal;
  25. type
  26. tcgcallparanode = class(tcallparanode)
  27. private
  28. tempparaloc : tparalocation;
  29. procedure allocate_tempparaloc;
  30. procedure push_addr_para;
  31. procedure push_value_para;
  32. public
  33. procedure secondcallparan;override;
  34. end;
  35. tcgcallnode = class(tcallnode)
  36. private
  37. procedure release_para_temps;
  38. procedure normal_pass_2;
  39. procedure inlined_pass_2;
  40. protected
  41. { save the size of pushed parameter, needed po_clearstack
  42. and alignment }
  43. pushedparasize : longint;
  44. framepointer_paraloc : tparalocation;
  45. refcountedtemp : treference;
  46. procedure handle_return_value;
  47. {# This routine is used to push the current frame pointer
  48. on the stack. This is used in nested routines where the
  49. value of the frame pointer is always pushed as an extra
  50. parameter.
  51. The default handling is the standard handling used on
  52. most stack based machines, where the frame pointer is
  53. the first invisible parameter.
  54. }
  55. function align_parasize:longint;virtual;
  56. procedure pop_parasize(pop_size:longint);virtual;
  57. procedure extra_interrupt_code;virtual;
  58. procedure extra_call_code;virtual;
  59. public
  60. procedure pass_2;override;
  61. end;
  62. implementation
  63. uses
  64. systems,
  65. cutils,verbose,globals,
  66. symconst,symsym,symtable,defutil,paramgr,
  67. {$ifdef GDB}
  68. {$ifdef delphi}
  69. sysutils,
  70. {$else}
  71. strings,
  72. {$endif}
  73. gdb,
  74. {$endif GDB}
  75. cgbase,pass_2,
  76. cpuinfo,aasmbase,aasmtai,
  77. nbas,nmem,nld,ncnv,nutils,
  78. {$ifdef x86}
  79. cga,cgx86,
  80. {$endif x86}
  81. ncgutil,
  82. cgutils,cgobj,tgobj,
  83. procinfo;
  84. {*****************************************************************************
  85. TCGCALLPARANODE
  86. *****************************************************************************}
  87. procedure tcgcallparanode.allocate_tempparaloc;
  88. begin
  89. { Allocate (temporary) paralocation }
  90. tempparaloc:=paraitem.paraloc[callerside];
  91. case tempparaloc.loc of
  92. LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER:
  93. paramanager.alloctempregs(exprasmlist,tempparaloc);
  94. {$ifdef cputargethasfixedstack}
  95. LOC_REFERENCE:
  96. begin
  97. { currently, we copy the value always to a secure location }
  98. if true then
  99. paramanager.alloctempparaloc(exprasmlist,aktcallnode.procdefinition.proccalloption,paraitem,tempparaloc);
  100. end;
  101. {$endif cputargethasfixedstack}
  102. end;
  103. end;
  104. procedure tcgcallparanode.push_addr_para;
  105. begin
  106. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  107. internalerror(200304235);
  108. location_release(exprasmlist,left.location);
  109. cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
  110. inc(tcgcallnode(aktcallnode).pushedparasize,POINTER_SIZE);
  111. end;
  112. procedure tcgcallparanode.push_value_para;
  113. var
  114. href : treference;
  115. size : longint;
  116. cgsize : tcgsize;
  117. begin
  118. { we've nothing to push when the size of the parameter is 0 }
  119. if left.resulttype.def.size=0 then
  120. exit;
  121. { Move flags and jump in register to make it less complex }
  122. if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  123. location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
  124. { Handle Floating point types differently }
  125. if left.resulttype.def.deftype=floatdef then
  126. begin
  127. location_release(exprasmlist,left.location);
  128. {$ifdef i386}
  129. if tempparaloc.loc<>LOC_REFERENCE then
  130. internalerror(200309291);
  131. case left.location.loc of
  132. LOC_FPUREGISTER,
  133. LOC_CFPUREGISTER:
  134. begin
  135. size:=align(TCGSize2Size[left.location.size],tempparaloc.alignment);
  136. inc(tcgcallnode(aktcallnode).pushedparasize,size);
  137. if tempparaloc.reference.index=NR_STACK_POINTER_REG then
  138. begin
  139. cg.g_stackpointer_alloc(exprasmlist,size);
  140. reference_reset_base(href,NR_STACK_POINTER_REG,0);
  141. end
  142. else
  143. reference_reset_base(href,tempparaloc.reference.index,tempparaloc.reference.offset);
  144. cg.a_loadfpu_reg_ref(exprasmlist,def_cgsize(left.resulttype.def),left.location.register,href);
  145. end;
  146. LOC_MMREGISTER,
  147. LOC_CMMREGISTER:
  148. begin
  149. size:=align(tfloatdef(left.resulttype.def).size,tempparaloc.alignment);
  150. inc(tcgcallnode(aktcallnode).pushedparasize,size);
  151. if tempparaloc.reference.index=NR_STACK_POINTER_REG then
  152. begin
  153. cg.g_stackpointer_alloc(exprasmlist,size);
  154. reference_reset_base(href,NR_STACK_POINTER_REG,0);
  155. end
  156. else
  157. reference_reset_base(href,tempparaloc.reference.index,tempparaloc.reference.offset);
  158. cg.a_loadmm_reg_ref(exprasmlist,def_cgsize(left.resulttype.def),def_cgsize(left.resulttype.def),left.location.register,href,mms_movescalar);
  159. end;
  160. LOC_REFERENCE,
  161. LOC_CREFERENCE :
  162. begin
  163. size:=align(left.resulttype.def.size,tempparaloc.alignment);
  164. if tempparaloc.reference.index=NR_STACK_POINTER_REG then
  165. begin
  166. href:=left.location.reference;
  167. inc(href.offset,size);
  168. while (size>0) do
  169. begin
  170. if (size>=4) or (tempparaloc.alignment>=4) then
  171. begin
  172. cgsize:=OS_32;
  173. inc(tcgcallnode(aktcallnode).pushedparasize,4);
  174. dec(href.offset,4);
  175. dec(size,4);
  176. end
  177. else
  178. begin
  179. cgsize:=OS_16;
  180. inc(tcgcallnode(aktcallnode).pushedparasize,2);
  181. dec(href.offset,2);
  182. dec(size,2);
  183. end;
  184. cg.a_param_ref(exprasmlist,cgsize,href,tempparaloc);
  185. end;
  186. end
  187. else
  188. begin
  189. reference_reset_base(href,tempparaloc.reference.index,tempparaloc.reference.offset);
  190. cg.g_concatcopy(exprasmlist,left.location.reference,href,size,false,false);
  191. inc(tcgcallnode(aktcallnode).pushedparasize,size);
  192. end;
  193. end;
  194. else
  195. internalerror(200204243);
  196. end;
  197. {$else i386}
  198. case left.location.loc of
  199. LOC_MMREGISTER,
  200. LOC_CMMREGISTER:
  201. begin
  202. if tempparaloc.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
  203. begin
  204. location_force_fpureg(exprasmlist,left.location,false);
  205. cg.a_paramfpu_reg(exprasmlist,def_cgsize(left.resulttype.def),left.location.register,tempparaloc);
  206. end
  207. else
  208. cg.a_parammm_reg(exprasmlist,def_cgsize(left.resulttype.def),left.location.register,tempparaloc,mms_movescalar);
  209. end;
  210. LOC_FPUREGISTER,
  211. LOC_CFPUREGISTER:
  212. begin
  213. if tempparaloc.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  214. begin
  215. location_force_mmregscalar(exprasmlist,left.location,false);
  216. cg.a_parammm_reg(exprasmlist,def_cgsize(left.resulttype.def),left.location.register,tempparaloc,mms_movescalar);
  217. end
  218. else
  219. cg.a_paramfpu_reg(exprasmlist,def_cgsize(left.resulttype.def),left.location.register,tempparaloc);
  220. end;
  221. LOC_REFERENCE,
  222. LOC_CREFERENCE:
  223. case tempparaloc.loc of
  224. LOC_MMREGISTER,
  225. LOC_CMMREGISTER:
  226. cg.a_parammm_ref(exprasmlist,def_cgsize(left.resulttype.def),left.location.reference,tempparaloc,mms_movescalar);
  227. LOC_REFERENCE,
  228. LOC_CREFERENCE,
  229. LOC_FPUREGISTER,
  230. LOC_CFPUREGISTER:
  231. cg.a_paramfpu_ref(exprasmlist,def_cgsize(left.resulttype.def),left.location.reference,tempparaloc);
  232. else
  233. internalerror(200204243);
  234. end;
  235. else
  236. internalerror(200204243);
  237. end;
  238. {$endif i386}
  239. end
  240. else
  241. begin
  242. { copy the value on the stack or use normal parameter push?
  243. Check for varargs first because that has no paraitem }
  244. if not(nf_varargs_para in flags) and
  245. paramanager.copy_value_on_stack(paraitem.paratyp,left.resulttype.def,
  246. aktcallnode.procdefinition.proccalloption) then
  247. begin
  248. location_release(exprasmlist,left.location);
  249. {$ifdef i386}
  250. if tempparaloc.loc<>LOC_REFERENCE then
  251. internalerror(200309292);
  252. if not (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  253. internalerror(200204241);
  254. { push on stack }
  255. size:=align(left.resulttype.def.size,tempparaloc.alignment);
  256. inc(tcgcallnode(aktcallnode).pushedparasize,size);
  257. if tempparaloc.reference.index=NR_STACK_POINTER_REG then
  258. begin
  259. cg.g_stackpointer_alloc(exprasmlist,size);
  260. reference_reset_base(href,NR_STACK_POINTER_REG,0);
  261. end
  262. else
  263. reference_reset_base(href,tempparaloc.reference.index,tempparaloc.reference.offset);
  264. cg.g_concatcopy(exprasmlist,left.location.reference,href,size,false,false);
  265. {$else i386}
  266. cg.a_param_copy_ref(exprasmlist,left.resulttype.def.size,left.location.reference,tempparaloc);
  267. {$endif i386}
  268. end
  269. else
  270. begin
  271. case left.location.loc of
  272. LOC_CONSTANT,
  273. LOC_REGISTER,
  274. LOC_CREGISTER,
  275. LOC_REFERENCE,
  276. LOC_CREFERENCE :
  277. begin
  278. cgsize:=def_cgsize(left.resulttype.def);
  279. if cgsize in [OS_64,OS_S64] then
  280. begin
  281. inc(tcgcallnode(aktcallnode).pushedparasize,8);
  282. cg64.a_param64_loc(exprasmlist,left.location,tempparaloc);
  283. location_release(exprasmlist,left.location);
  284. end
  285. else
  286. begin
  287. location_release(exprasmlist,left.location);
  288. inc(tcgcallnode(aktcallnode).pushedparasize,align(tcgsize2size[tempparaloc.size],tempparaloc.alignment));
  289. cg.a_param_loc(exprasmlist,left.location,tempparaloc);
  290. end;
  291. end;
  292. {$ifdef SUPPORT_MMX}
  293. LOC_MMXREGISTER,
  294. LOC_CMMXREGISTER:
  295. begin
  296. location_release(exprasmlist,left.location);
  297. inc(tcgcallnode(aktcallnode).pushedparasize,8);
  298. cg.a_parammm_reg(exprasmlist,left.location.register);
  299. end;
  300. {$endif SUPPORT_MMX}
  301. else
  302. internalerror(200204241);
  303. end;
  304. end;
  305. end;
  306. end;
  307. procedure tcgcallparanode.secondcallparan;
  308. var
  309. otlabel,
  310. oflabel : tasmlabel;
  311. hp : tnode;
  312. begin
  313. if not(assigned(paraitem)) or
  314. not(assigned(paraitem.paratype.def)) or
  315. not(assigned(paraitem.parasym) or
  316. (nf_varargs_para in flags)) then
  317. internalerror(200304242);
  318. { Skip nothingn nodes which are used after disabling
  319. a parameter }
  320. if (left.nodetype<>nothingn) then
  321. begin
  322. otlabel:=truelabel;
  323. oflabel:=falselabel;
  324. objectlibrary.getlabel(truelabel);
  325. objectlibrary.getlabel(falselabel);
  326. secondpass(left);
  327. allocate_tempparaloc;
  328. { handle varargs first, because paraitem.parasym is not valid }
  329. if (nf_varargs_para in flags) then
  330. begin
  331. if paramanager.push_addr_param(vs_value,left.resulttype.def,
  332. aktcallnode.procdefinition.proccalloption) then
  333. push_addr_para
  334. else
  335. push_value_para;
  336. end
  337. { hidden parameters }
  338. else if paraitem.is_hidden then
  339. begin
  340. { don't push a node that already generated a pointer type
  341. by address for implicit hidden parameters }
  342. if (vo_is_funcret in tvarsym(paraitem.parasym).varoptions) or
  343. (not(left.resulttype.def.deftype in [pointerdef,classrefdef]) and
  344. paramanager.push_addr_param(paraitem.paratyp,paraitem.paratype.def,
  345. aktcallnode.procdefinition.proccalloption)) then
  346. push_addr_para
  347. else
  348. push_value_para;
  349. end
  350. { formal def }
  351. else if (paraitem.paratype.def.deftype=formaldef) then
  352. begin
  353. { allow passing of a constant to a const formaldef }
  354. if (tvarsym(paraitem.parasym).varspez=vs_const) and
  355. (left.location.loc=LOC_CONSTANT) then
  356. location_force_mem(exprasmlist,left.location);
  357. { allow (typecasted) @var }
  358. hp:=left;
  359. while (hp.nodetype=typeconvn) do
  360. hp:=ttypeconvnode(hp).left;
  361. if (hp.nodetype=addrn) and
  362. (not(nf_procvarload in hp.flags)) then
  363. begin
  364. inc(tcgcallnode(aktcallnode).pushedparasize,POINTER_SIZE);
  365. location_release(exprasmlist,left.location);
  366. cg.a_param_loc(exprasmlist,left.location,tempparaloc);
  367. end
  368. else
  369. push_addr_para;
  370. end
  371. { Normal parameter }
  372. else
  373. begin
  374. { don't push a node that already generated a pointer type
  375. by address for implicit hidden parameters }
  376. if (not(
  377. paraitem.is_hidden and
  378. (left.resulttype.def.deftype in [pointerdef,classrefdef])
  379. ) and
  380. paramanager.push_addr_param(paraitem.paratyp,paraitem.paratype.def,
  381. aktcallnode.procdefinition.proccalloption)) then
  382. begin
  383. { Check for passing a constant to var,out parameter }
  384. if (paraitem.paratyp in [vs_var,vs_out]) and
  385. (left.location.loc<>LOC_REFERENCE) then
  386. begin
  387. { passing self to a var parameter is allowed in
  388. TP and delphi }
  389. if not((left.location.loc=LOC_CREFERENCE) and
  390. is_self_node(left)) then
  391. internalerror(200106041);
  392. end;
  393. { Force to be in memory }
  394. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  395. location_force_mem(exprasmlist,left.location);
  396. push_addr_para;
  397. end
  398. else
  399. push_value_para;
  400. end;
  401. truelabel:=otlabel;
  402. falselabel:=oflabel;
  403. { update return location in callnode when this is the function
  404. result }
  405. if assigned(paraitem.parasym) and
  406. (vo_is_funcret in tvarsym(paraitem.parasym).varoptions) then
  407. location_copy(aktcallnode.location,left.location);
  408. end;
  409. { next parameter }
  410. if assigned(right) then
  411. tcallparanode(right).secondcallparan;
  412. end;
  413. {*****************************************************************************
  414. TCGCALLNODE
  415. *****************************************************************************}
  416. procedure tcgcallnode.extra_interrupt_code;
  417. begin
  418. end;
  419. procedure tcgcallnode.extra_call_code;
  420. begin
  421. end;
  422. function tcgcallnode.align_parasize:longint;
  423. begin
  424. result:=0;
  425. end;
  426. procedure tcgcallnode.pop_parasize(pop_size:longint);
  427. begin
  428. end;
  429. procedure tcgcallnode.handle_return_value;
  430. var
  431. cgsize : tcgsize;
  432. hregister : tregister;
  433. tempnode: tnode;
  434. begin
  435. { structured results are easy to handle.... }
  436. { needed also when result_no_used !! }
  437. if paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
  438. begin
  439. { Location should be setup by the funcret para }
  440. if location.loc<>LOC_REFERENCE then
  441. internalerror(200304241);
  442. end
  443. else
  444. { ansi/widestrings must be registered, so we can dispose them }
  445. if resulttype.def.needs_inittable then
  446. begin
  447. { the FUNCTION_RESULT_REG is already allocated }
  448. if not assigned(funcretnode) then
  449. begin
  450. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  451. location.reference:=refcountedtemp;
  452. { a_load_reg_ref may allocate registers! }
  453. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,location.reference);
  454. cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT_REG);
  455. end
  456. else
  457. begin
  458. cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT_REG);
  459. hregister := cg.getaddressregister(exprasmlist);
  460. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
  461. { in case of a regular funcretnode with ret_in_param, the }
  462. { original funcretnode isn't touched -> make sure it's }
  463. { the same here (not sure if it's necessary) }
  464. tempnode := funcretnode.getcopy;
  465. tempnode.pass_2;
  466. location := tempnode.location;
  467. tempnode.free;
  468. cg.g_decrrefcount(exprasmlist,resulttype.def,location.reference, false);
  469. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  470. cg.ungetregister(exprasmlist,hregister);
  471. end;
  472. end
  473. else
  474. { we have only to handle the result if it is used }
  475. if (nf_return_value_used in flags) then
  476. begin
  477. if (resulttype.def.deftype=floatdef) then
  478. begin
  479. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  480. {$ifdef cpufpemu}
  481. if cs_fp_emulation in aktmoduleswitches then
  482. location.register:=NR_FUNCTION_RESULT_REG
  483. else
  484. {$endif cpufpemu}
  485. begin
  486. location.register:=NR_FPU_RESULT_REG;
  487. {$ifdef sparc}
  488. { Double are returned in F0:F1 }
  489. if location.size=OS_F64 then
  490. setsubreg(location.register,R_SUBFD);
  491. {$endif sparc}
  492. end;
  493. {$ifdef x86}
  494. tcgx86(cg).inc_fpu_stack;
  495. {$else x86}
  496. cg.ungetregister(exprasmlist,location.register);
  497. hregister := cg.getfpuregister(exprasmlist,location.size);
  498. cg.a_loadfpu_reg_reg(exprasmlist,location.size,location.register,hregister);
  499. location.register := hregister;
  500. {$endif x86}
  501. end
  502. else
  503. begin
  504. cgsize:=def_cgsize(resulttype.def);
  505. if cgsize<>OS_NO then
  506. begin
  507. location_reset(location,LOC_REGISTER,cgsize);
  508. {$ifndef cpu64bit}
  509. if cgsize in [OS_64,OS_S64] then
  510. begin
  511. { Move the function result to free registers, preferably the
  512. FUNCTION_RESULT_REG/FUNCTION_RESULTHIGH_REG, so no move is necessary.}
  513. { the FUNCTION_RESULT_LOW_REG/FUNCTION_RESULT_HIGH_REG
  514. are already allocated }
  515. cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_LOW_REG);
  516. location.registerlow:=cg.getintregister(exprasmlist,OS_INT);
  517. cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,NR_FUNCTION_RESULT64_LOW_REG,location.registerlow);
  518. cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_HIGH_REG);
  519. location.registerhigh:=cg.getintregister(exprasmlist,OS_INT);
  520. cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,NR_FUNCTION_RESULT64_HIGH_REG,location.registerhigh);
  521. end
  522. else
  523. {$endif cpu64bit}
  524. begin
  525. {Move the function result to a free register, preferably the
  526. FUNCTION_RESULT_REG, so no move is necessary.}
  527. { the FUNCTION_RESULT_REG is already allocated }
  528. cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT_REG);
  529. { change register size after the unget because the
  530. getregister was done for the full register }
  531. location.register:=cg.getintregister(exprasmlist,cgsize);
  532. cg.a_load_reg_reg(exprasmlist,cgsize,cgsize,cg.makeregsize(NR_FUNCTION_RESULT_REG,cgsize),location.register);
  533. end;
  534. end
  535. else
  536. begin
  537. if resulttype.def.size>0 then
  538. internalerror(200305131);
  539. end;
  540. end;
  541. end
  542. else
  543. begin
  544. cgsize:=def_cgsize(resulttype.def);
  545. { an object constructor is a function with pointer result }
  546. if (procdefinition.proctypeoption=potype_constructor) then
  547. cgsize:=OS_ADDR;
  548. if cgsize<>OS_NO then
  549. {$ifndef cpu64bit}
  550. if cgsize in [OS_64,OS_S64] then
  551. begin
  552. cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_LOW_REG);
  553. cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_HIGH_REG);
  554. end
  555. else
  556. {$endif cpu64bit}
  557. cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT_REG);
  558. location_reset(location,LOC_VOID,OS_NO);
  559. end;
  560. end;
  561. procedure tcgcallnode.release_para_temps;
  562. var
  563. hp : tnode;
  564. ppn : tcallparanode;
  565. begin
  566. { Release temps from parameters }
  567. ppn:=tcallparanode(left);
  568. while assigned(ppn) do
  569. begin
  570. if assigned(ppn.left) then
  571. begin
  572. { don't release the funcret temp }
  573. if not(assigned(ppn.paraitem.parasym)) or
  574. not(vo_is_funcret in tvarsym(ppn.paraitem.parasym).varoptions) then
  575. location_freetemp(exprasmlist,ppn.left.location);
  576. { process also all nodes of an array of const }
  577. if ppn.left.nodetype=arrayconstructorn then
  578. begin
  579. if assigned(tarrayconstructornode(ppn.left).left) then
  580. begin
  581. hp:=ppn.left;
  582. while assigned(hp) do
  583. begin
  584. location_freetemp(exprasmlist,tarrayconstructornode(hp).left.location);
  585. hp:=tarrayconstructornode(hp).right;
  586. end;
  587. end;
  588. end;
  589. end;
  590. ppn:=tcallparanode(ppn.right);
  591. end;
  592. end;
  593. procedure tcgcallnode.normal_pass_2;
  594. var
  595. regs_to_push_fpu,
  596. regs_to_alloc,
  597. regs_to_free : Tcpuregisterset;
  598. oldpushedparasize : longint;
  599. {$ifdef cputargethasfixedstack}
  600. href2,
  601. {$endif cputargethasfixedstack}
  602. href : treference;
  603. pop_size : longint;
  604. pvreg,
  605. vmtreg : tregister;
  606. oldaktcallnode : tcallnode;
  607. procedure pushparas;
  608. var
  609. ppn : tcgcallparanode;
  610. begin
  611. { copy all resources to the allocated registers }
  612. ppn:=tcgcallparanode(left);
  613. while assigned(ppn) do
  614. begin
  615. if (ppn.left.nodetype<>nothingn) then
  616. begin
  617. { better check for the real location of the parameter here, when stack passed parameters
  618. are saved temporary in registers, checking for the tempparaloc.loc is wrong
  619. }
  620. case ppn.paraitem.paraloc[callerside].loc of
  621. LOC_REGISTER:
  622. begin
  623. paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
  624. paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
  625. {$ifdef sparc}
  626. case ppn.tempparaloc.size of
  627. OS_F32 :
  628. ppn.tempparaloc.size:=OS_32;
  629. OS_F64 :
  630. ppn.tempparaloc.size:=OS_64;
  631. end;
  632. {$endif sparc}
  633. {$ifndef cpu64bit}
  634. if ppn.tempparaloc.size in [OS_64,OS_S64] then
  635. begin
  636. cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,ppn.tempparaloc.registerlow,
  637. ppn.paraitem.paraloc[callerside].registerlow);
  638. cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,ppn.tempparaloc.registerhigh,
  639. ppn.paraitem.paraloc[callerside].registerhigh);
  640. end
  641. else
  642. {$endif cpu64bit}
  643. cg.a_load_reg_reg(exprasmlist,ppn.tempparaloc.size,ppn.tempparaloc.size,
  644. ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register);
  645. end;
  646. LOC_FPUREGISTER:
  647. begin
  648. paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
  649. paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
  650. cg.a_loadfpu_reg_reg(exprasmlist,ppn.tempparaloc.size,
  651. ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register);
  652. end;
  653. LOC_MMREGISTER:
  654. begin
  655. paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
  656. paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
  657. cg.a_loadmm_reg_reg(exprasmlist,ppn.tempparaloc.size,
  658. ppn.tempparaloc.size,ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register,mms_movescalar);
  659. end;
  660. LOC_REFERENCE:
  661. begin
  662. {$ifdef cputargethasfixedstack}
  663. { copy parameters in case they were moved to a temp. location because we've a fixed stack }
  664. paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
  665. paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
  666. case ppn.tempparaloc.loc of
  667. LOC_REFERENCE:
  668. begin
  669. reference_reset_base(href,ppn.tempparaloc.reference.index,ppn.tempparaloc.reference.offset);
  670. reference_reset_base(href2,ppn.paraitem.paraloc[callerside].reference.index,ppn.paraitem.paraloc[callerside].reference.offset);
  671. cg.g_concatcopy(exprasmlist,href,href2,ppn.paraitem.paratype.def.size,false,false);
  672. end;
  673. LOC_REGISTER:
  674. if ppn.tempparaloc.size in [OS_64,OS_S64] then
  675. begin
  676. reference_reset_base(href,ppn.paraitem.paraloc[callerside].reference.index,ppn.paraitem.paraloc[callerside].reference.offset);
  677. cg.a_load_reg_ref(exprasmlist,OS_32,OS_32,ppn.tempparaloc.registerlow,
  678. href);
  679. { we don't use a c64.load here because later (when fixed ;)) one dword could be on the stack and the
  680. other in a cpu register }
  681. reference_reset_base(href,ppn.paraitem.paraloc[callerside].reference.index,ppn.paraitem.paraloc[callerside].reference.offset+4);
  682. cg.a_load_reg_ref(exprasmlist,OS_32,OS_32,ppn.tempparaloc.registerhigh,
  683. href);
  684. end
  685. else
  686. cg.a_param_reg(exprasmlist,ppn.paraitem.paraloc[callerside].size,ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside]);
  687. LOC_FPUREGISTER:
  688. cg.a_paramfpu_reg(exprasmlist,ppn.paraitem.paraloc[callerside].size,ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside]);
  689. else
  690. internalerror(200402081);
  691. end;
  692. {$endif cputargethasfixedstack}
  693. end;
  694. else
  695. internalerror(200402091);
  696. end;
  697. end;
  698. ppn:=tcgcallparanode(ppn.right);
  699. end;
  700. end;
  701. procedure freeparas;
  702. var
  703. ppn : tcgcallparanode;
  704. begin
  705. { free the resources allocated for the parameters }
  706. ppn:=tcgcallparanode(left);
  707. while assigned(ppn) do
  708. begin
  709. paramanager.freeparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
  710. ppn:=tcgcallparanode(ppn.right);
  711. end;
  712. end;
  713. begin
  714. if not assigned(procdefinition) or
  715. not procdefinition.has_paraloc_info then
  716. internalerror(200305264);
  717. if resulttype.def.needs_inittable and
  718. not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) and
  719. not assigned(funcretnode) then
  720. begin
  721. tg.gettemptyped(exprasmlist,resulttype.def,tt_normal,refcountedtemp);
  722. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
  723. end;
  724. regs_to_alloc:=paramanager.get_volatile_registers_int(procdefinition.proccalloption);
  725. regs_to_push_fpu:=paramanager.get_volatile_registers_fpu(procdefinition.proccalloption);
  726. { Include Function result registers }
  727. if (not is_void(resulttype.def)) then
  728. begin
  729. case procdefinition.funcret_paraloc[callerside].loc of
  730. LOC_REGISTER,LOC_CREGISTER:
  731. begin
  732. {$ifndef cpu64bit}
  733. if procdefinition.funcret_paraloc[callerside].size in [OS_S64,OS_64] then
  734. begin
  735. include(regs_to_alloc,getsupreg(procdefinition.funcret_paraloc[callerside].registerlow));
  736. include(regs_to_alloc,getsupreg(procdefinition.funcret_paraloc[callerside].registerhigh));
  737. end
  738. else
  739. {$endif cpu64bit}
  740. include(regs_to_alloc,getsupreg(procdefinition.funcret_paraloc[callerside].register));
  741. end;
  742. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  743. begin
  744. include(regs_to_push_fpu,getsupreg(procdefinition.funcret_paraloc[callerside].register));
  745. end;
  746. LOC_MMREGISTER,LOC_CMMREGISTER:
  747. begin
  748. internalerror(2003102911);
  749. end;
  750. end;
  751. end;
  752. { Initialize for pushing the parameters }
  753. oldpushedparasize:=pushedparasize;
  754. pushedparasize:=0;
  755. { Process parameters, register parameters will be loaded
  756. in imaginary registers. The actual load to the correct
  757. register is done just before the call }
  758. oldaktcallnode:=aktcallnode;
  759. aktcallnode:=self;
  760. if assigned(left) then
  761. tcallparanode(left).secondcallparan;
  762. aktcallnode:=oldaktcallnode;
  763. { Align stack if required }
  764. pop_size:=align_parasize;
  765. { procedure variable or normal function call ? }
  766. if (right=nil) then
  767. begin
  768. if (po_virtualmethod in procdefinition.procoptions) and
  769. assigned(methodpointer) then
  770. begin
  771. secondpass(methodpointer);
  772. location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
  773. { virtual methods require an index }
  774. if tprocdef(procdefinition).extnumber=-1 then
  775. internalerror(200304021);
  776. { VMT should already be loaded in a register }
  777. if methodpointer.location.register=NR_NO then
  778. internalerror(200304022);
  779. { test validity of VMT }
  780. if not(is_interface(tprocdef(procdefinition)._class)) and
  781. not(is_cppclass(tprocdef(procdefinition)._class)) then
  782. cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
  783. end;
  784. {$warning fixme regvars}
  785. { rg.saveotherregvars(exprasmlist,regs_to_push_other);}
  786. if (po_virtualmethod in procdefinition.procoptions) and
  787. assigned(methodpointer) then
  788. begin
  789. vmtreg:=methodpointer.location.register;
  790. { release self }
  791. cg.ungetregister(exprasmlist,vmtreg);
  792. pvreg:=cg.getintregister(exprasmlist,OS_ADDR);
  793. reference_reset_base(href,vmtreg,
  794. tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
  795. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,pvreg);
  796. { Load parameters that are in temporary registers in the
  797. correct parameter register }
  798. if assigned(left) then
  799. pushparas;
  800. { free the resources allocated for the parameters }
  801. freeparas;
  802. { Release register containing procvar }
  803. cg.ungetregister(exprasmlist,pvreg);
  804. cg.allocexplicitregisters(exprasmlist,R_INTREGISTER,regs_to_alloc);
  805. if cg.uses_registers(R_FPUREGISTER) then
  806. cg.allocexplicitregisters(exprasmlist,R_FPUREGISTER,regs_to_push_fpu);
  807. if cg.uses_registers(R_MMREGISTER) then
  808. cg.allocexplicitregisters(exprasmlist,R_MMREGISTER,paramanager.get_volatile_registers_mm(procdefinition.proccalloption));
  809. { call method }
  810. extra_call_code;
  811. cg.a_call_reg(exprasmlist,pvreg);
  812. end
  813. else
  814. begin
  815. { Load parameters that are in temporary registers in the
  816. correct parameter register }
  817. if assigned(left) then
  818. pushparas;
  819. { free the resources allocated for the parameters }
  820. freeparas;
  821. cg.allocexplicitregisters(exprasmlist,R_INTREGISTER,regs_to_alloc);
  822. if cg.uses_registers(R_FPUREGISTER) then
  823. cg.allocexplicitregisters(exprasmlist,R_FPUREGISTER,regs_to_push_fpu);
  824. if cg.uses_registers(R_MMREGISTER) then
  825. cg.allocexplicitregisters(exprasmlist,R_MMREGISTER,paramanager.get_volatile_registers_mm(procdefinition.proccalloption));
  826. { Calling interrupt from the same code requires some
  827. extra code }
  828. if (po_interrupt in procdefinition.procoptions) then
  829. extra_interrupt_code;
  830. extra_call_code;
  831. cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
  832. end;
  833. end
  834. else
  835. { now procedure variable case }
  836. begin
  837. secondpass(right);
  838. location_release(exprasmlist,right.location);
  839. pvreg:=cg.getintregister(exprasmlist,OS_ADDR);
  840. { Only load OS_ADDR from the reference }
  841. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  842. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,right.location.reference,pvreg)
  843. else
  844. cg.a_load_loc_reg(exprasmlist,OS_ADDR,right.location,pvreg);
  845. location_freetemp(exprasmlist,right.location);
  846. { Load parameters that are in temporary registers in the
  847. correct parameter register }
  848. if assigned(left) then
  849. pushparas;
  850. { free the resources allocated for the parameters }
  851. freeparas;
  852. { Release register containing procvar }
  853. cg.ungetregister(exprasmlist,pvreg);
  854. cg.allocexplicitregisters(exprasmlist,R_INTREGISTER,regs_to_alloc);
  855. if cg.uses_registers(R_FPUREGISTER) then
  856. cg.allocexplicitregisters(exprasmlist,R_FPUREGISTER,regs_to_push_fpu);
  857. if cg.uses_registers(R_MMREGISTER) then
  858. cg.allocexplicitregisters(exprasmlist,R_MMREGISTER,paramanager.get_volatile_registers_mm(procdefinition.proccalloption));
  859. { Calling interrupt from the same code requires some
  860. extra code }
  861. if (po_interrupt in procdefinition.procoptions) then
  862. extra_interrupt_code;
  863. {$warning fixme regvars.}
  864. { rg.saveotherregvars(exprasmlist,ALL_OTHERREGISTERS);}
  865. extra_call_code;
  866. cg.a_call_reg(exprasmlist,pvreg);
  867. end;
  868. { Need to remove the parameters from the stack? }
  869. if (procdefinition.proccalloption in clearstack_pocalls) then
  870. begin
  871. { the old pop_size was already included in pushedparasize }
  872. pop_size:=pushedparasize;
  873. { for Cdecl functions we don't need to pop the funcret when it
  874. was pushed by para }
  875. if paramanager.ret_in_param(procdefinition.rettype.def,procdefinition.proccalloption) then
  876. dec(pop_size,POINTER_SIZE);
  877. end;
  878. { Remove parameters/alignment from the stack }
  879. if pop_size>0 then
  880. pop_parasize(pop_size);
  881. { Reserve space for storing parameters that will be pushed }
  882. current_procinfo.allocate_push_parasize(pushedparasize);
  883. { Restore }
  884. pushedparasize:=oldpushedparasize;
  885. { Release registers, but not the registers that contain the
  886. function result }
  887. regs_to_free:=regs_to_alloc;
  888. if (not is_void(resulttype.def)) then
  889. begin
  890. case procdefinition.funcret_paraloc[callerside].loc of
  891. LOC_REGISTER,LOC_CREGISTER:
  892. begin
  893. {$ifndef cpu64bit}
  894. if procdefinition.funcret_paraloc[callerside].size in [OS_S64,OS_64] then
  895. begin
  896. exclude(regs_to_free,getsupreg(procdefinition.funcret_paraloc[callerside].registerlow));
  897. exclude(regs_to_free,getsupreg(procdefinition.funcret_paraloc[callerside].registerhigh));
  898. end
  899. else
  900. {$endif cpu64bit}
  901. exclude(regs_to_free,getsupreg(procdefinition.funcret_paraloc[callerside].register));
  902. end;
  903. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  904. begin
  905. exclude(regs_to_push_fpu,getsupreg(procdefinition.funcret_paraloc[callerside].register));
  906. end;
  907. end;
  908. end;
  909. if cg.uses_registers(R_MMREGISTER) then
  910. cg.deallocexplicitregisters(exprasmlist,R_MMREGISTER,paramanager.get_volatile_registers_mm(procdefinition.proccalloption));
  911. if cg.uses_registers(R_FPUREGISTER) then
  912. cg.deallocexplicitregisters(exprasmlist,R_FPUREGISTER,regs_to_push_fpu);
  913. cg.deallocexplicitregisters(exprasmlist,R_INTREGISTER,regs_to_free);
  914. { handle function results }
  915. if (not is_void(resulttype.def)) then
  916. handle_return_value
  917. else
  918. location_reset(location,LOC_VOID,OS_NO);
  919. { perhaps i/o check ? }
  920. if (cs_check_io in aktlocalswitches) and
  921. (po_iocheck in procdefinition.procoptions) and
  922. not(po_iocheck in current_procinfo.procdef.procoptions) and
  923. { no IO check for methods and procedure variables }
  924. (right=nil) and
  925. not(po_virtualmethod in procdefinition.procoptions) then
  926. begin
  927. cg.allocexplicitregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  928. cg.a_call_name(exprasmlist,'FPC_IOCHECK');
  929. cg.deallocexplicitregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  930. end;
  931. { release temps of paras }
  932. release_para_temps;
  933. { if return value is not used }
  934. if (not(nf_return_value_used in flags)) and (not is_void(resulttype.def)) then
  935. begin
  936. if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
  937. begin
  938. { data which must be finalized ? }
  939. if (resulttype.def.needs_inittable) then
  940. cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
  941. { release unused temp }
  942. tg.ungetiftemp(exprasmlist,location.reference)
  943. end
  944. else if location.loc=LOC_FPUREGISTER then
  945. begin
  946. {$ifdef x86}
  947. { release FPU stack }
  948. emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
  949. {$endif x86}
  950. end;
  951. end;
  952. end;
  953. procedure tcgcallnode.inlined_pass_2;
  954. var
  955. oldaktcallnode : tcallnode;
  956. oldprocinfo : tprocinfo;
  957. oldinlining_procedure : boolean;
  958. inlineentrycode,inlineexitcode : TAAsmoutput;
  959. usesacc,usesacchi,usesfpu : boolean;
  960. {$ifdef GDB}
  961. startlabel,endlabel : tasmlabel;
  962. pp : pchar;
  963. mangled_length : longint;
  964. {$endif GDB}
  965. begin
  966. if not(assigned(procdefinition) and (procdefinition.deftype=procdef)) then
  967. internalerror(200305262);
  968. oldinlining_procedure:=inlining_procedure;
  969. oldprocinfo:=current_procinfo;
  970. { we're inlining a procedure }
  971. inlining_procedure:=true;
  972. { Add inling start }
  973. {$ifdef GDB}
  974. exprasmlist.concat(Tai_force_line.Create);
  975. {$endif GDB}
  976. exprasmList.concat(Tai_Marker.Create(InlineStart));
  977. {$ifdef extdebug}
  978. exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc '+tprocdef(procdefinition).procsym.name)));
  979. {$endif extdebug}
  980. { calculate registers to pass the parameters }
  981. paramanager.create_inline_paraloc_info(procdefinition);
  982. { Allocate parameters and locals }
  983. gen_alloc_inline_parast(exprasmlist,tparasymtable(procdefinition.parast));
  984. if tprocdef(procdefinition).localst.symtabletype=localsymtable then
  985. gen_alloc_localst(exprasmlist,tlocalsymtable(tprocdef(procdefinition).localst));
  986. { if we allocate the temp. location for ansi- or widestrings }
  987. { already here, we avoid later a push/pop }
  988. if resulttype.def.needs_inittable and
  989. not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
  990. begin
  991. tg.gettemptyped(exprasmlist,resulttype.def,tt_normal,refcountedtemp);
  992. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
  993. end;
  994. { Push parameters, still use the old current_procinfo. This
  995. is required that have the correct information available like
  996. _class and nested procedure }
  997. oldaktcallnode:=aktcallnode;
  998. aktcallnode:=self;
  999. if assigned(left) then
  1000. tcallparanode(left).secondcallparan;
  1001. aktcallnode:=oldaktcallnode;
  1002. { create temp procinfo that will be used for the inlinecode tree }
  1003. current_procinfo:=cprocinfo.create(nil);
  1004. current_procinfo.procdef:=tprocdef(procdefinition);
  1005. current_procinfo.flags:=oldprocinfo.flags;
  1006. current_procinfo.aktlocaldata.destroy;
  1007. current_procinfo.aktlocaldata:=oldprocinfo.aktlocaldata;
  1008. { when the oldprocinfo is also being inlined reuse the
  1009. inlining_procinfo }
  1010. if assigned(oldprocinfo.inlining_procinfo) then
  1011. current_procinfo.inlining_procinfo:=oldprocinfo.inlining_procinfo
  1012. else
  1013. current_procinfo.inlining_procinfo:=oldprocinfo;
  1014. { takes care of local data initialization }
  1015. inlineentrycode:=TAAsmoutput.Create;
  1016. inlineexitcode:=TAAsmoutput.Create;
  1017. {$ifdef GDB}
  1018. if (cs_debuginfo in aktmoduleswitches) then
  1019. begin
  1020. objectlibrary.getaddrlabel(startlabel);
  1021. objectlibrary.getaddrlabel(endlabel);
  1022. cg.a_label(exprasmlist,startlabel);
  1023. { Here we must include the para and local symtable info }
  1024. procdefinition.concatstabto(withdebuglist);
  1025. mangled_length:=length(current_procinfo.inlining_procinfo.procdef.mangledname);
  1026. getmem(pp,mangled_length+50);
  1027. strpcopy(pp,'192,0,0,'+startlabel.name);
  1028. if (target_info.use_function_relative_addresses) then
  1029. begin
  1030. strpcopy(strend(pp),'-');
  1031. strpcopy(strend(pp),current_procinfo.inlining_procinfo.procdef.mangledname);
  1032. end;
  1033. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  1034. end;
  1035. {$endif GDB}
  1036. gen_load_para_value(inlineentrycode);
  1037. gen_initialize_code(inlineentrycode,true);
  1038. if po_assembler in current_procinfo.procdef.procoptions then
  1039. inlineentrycode.insert(Tai_marker.Create(asmblockstart));
  1040. exprasmList.concatlist(inlineentrycode);
  1041. { process the inline code }
  1042. secondpass(inlinecode);
  1043. cg.a_label(exprasmlist,current_procinfo.aktexitlabel);
  1044. gen_finalize_code(inlineexitcode,true);
  1045. gen_load_return_value(inlineexitcode,usesacc,usesacchi,usesfpu);
  1046. if po_assembler in current_procinfo.procdef.procoptions then
  1047. inlineexitcode.concat(Tai_marker.Create(asmblockend));
  1048. exprasmlist.concatlist(inlineexitcode);
  1049. inlineentrycode.free;
  1050. inlineexitcode.free;
  1051. {$ifdef extdebug}
  1052. exprasmList.concat(tai_comment.Create(strpnew('End of inlined proc')));
  1053. {$endif extdebug}
  1054. exprasmList.concat(Tai_Marker.Create(InlineEnd));
  1055. { handle function results }
  1056. if (not is_void(resulttype.def)) then
  1057. handle_return_value
  1058. else
  1059. location_reset(location,LOC_VOID,OS_NO);
  1060. { perhaps i/o check ? }
  1061. if (cs_check_io in aktlocalswitches) and
  1062. (po_iocheck in procdefinition.procoptions) and
  1063. not(po_iocheck in current_procinfo.procdef.procoptions) and
  1064. { no IO check for methods and procedure variables }
  1065. (right=nil) and
  1066. not(po_virtualmethod in procdefinition.procoptions) then
  1067. begin
  1068. cg.allocexplicitregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1069. cg.a_call_name(exprasmlist,'FPC_IOCHECK');
  1070. cg.deallocexplicitregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1071. end;
  1072. { release temps of paras }
  1073. release_para_temps;
  1074. { if return value is not used }
  1075. if (not is_void(resulttype.def)) and
  1076. (not(nf_return_value_used in flags)) then
  1077. begin
  1078. if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
  1079. begin
  1080. { data which must be finalized ? }
  1081. if (resulttype.def.needs_inittable) then
  1082. cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
  1083. { release unused temp }
  1084. tg.ungetiftemp(exprasmlist,location.reference)
  1085. end
  1086. else if location.loc=LOC_FPUREGISTER then
  1087. begin
  1088. {$ifdef x86}
  1089. { release FPU stack }
  1090. emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
  1091. {$endif x86}
  1092. end;
  1093. end;
  1094. { Release parameters and locals }
  1095. gen_free_parast(exprasmlist,tparasymtable(current_procinfo.procdef.parast));
  1096. if current_procinfo.procdef.localst.symtabletype=localsymtable then
  1097. gen_free_localst(exprasmlist,tlocalsymtable(current_procinfo.procdef.localst));
  1098. {$ifdef GDB}
  1099. if (cs_debuginfo in aktmoduleswitches) then
  1100. begin
  1101. cg.a_label(exprasmlist,endlabel);
  1102. strpcopy(pp,'224,0,0,'+endlabel.name);
  1103. if (target_info.use_function_relative_addresses) then
  1104. begin
  1105. strpcopy(strend(pp),'-');
  1106. strpcopy(strend(pp),current_procinfo.inlining_procinfo.procdef.mangledname);
  1107. end;
  1108. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  1109. freemem(pp,mangled_length+50);
  1110. end;
  1111. {$endif GDB}
  1112. { restore }
  1113. current_procinfo.aktlocaldata:=nil;
  1114. current_procinfo.destroy;
  1115. current_procinfo:=oldprocinfo;
  1116. inlining_procedure:=oldinlining_procedure;
  1117. end;
  1118. procedure tcgcallnode.pass_2;
  1119. begin
  1120. if assigned(inlinecode) then
  1121. inlined_pass_2
  1122. else
  1123. normal_pass_2;
  1124. end;
  1125. begin
  1126. ccallparanode:=tcgcallparanode;
  1127. ccallnode:=tcgcallnode;
  1128. end.
  1129. {
  1130. $Log$
  1131. Revision 1.160 2004-02-27 10:21:05 florian
  1132. * top_symbol killed
  1133. + refaddr to treference added
  1134. + refsymbol to treference added
  1135. * top_local stuff moved to an extra record to save memory
  1136. + aint introduced
  1137. * tppufile.get/putint64/aint implemented
  1138. Revision 1.159 2004/02/26 16:12:04 peter
  1139. * support typecasts for passing @var to formal const
  1140. Revision 1.158 2004/02/22 13:01:15 daniel
  1141. * Fixed memory leak
  1142. Revision 1.157 2004/02/22 12:04:04 florian
  1143. + nx86set added
  1144. * some more x86-64 fixes
  1145. Revision 1.156 2004/02/20 22:16:35 florian
  1146. * handling of float parameters passed in mm registers fixed
  1147. Revision 1.155 2004/02/20 21:55:59 peter
  1148. * procvar cleanup
  1149. Revision 1.154 2004/02/11 19:59:06 peter
  1150. * fix compilation without GDB
  1151. Revision 1.153 2004/02/09 22:48:45 florian
  1152. * several fixes to parameter handling on arm
  1153. Revision 1.152 2004/01/31 17:45:17 peter
  1154. * Change several $ifdef i386 to x86
  1155. * Change several OS_32 to OS_INT/OS_ADDR
  1156. Revision 1.151 2004/01/26 17:34:14 florian
  1157. * set aktlocaldata for inlined procedures correctly
  1158. Revision 1.150 2004/01/12 16:39:40 peter
  1159. * sparc updates, mostly float related
  1160. Revision 1.149 2003/12/28 22:09:12 florian
  1161. + setting of bit 6 of cr for c var args on ppc implemented
  1162. Revision 1.148 2003/12/26 13:19:16 florian
  1163. * rtl and compiler compile with -Cfsse2
  1164. Revision 1.147 2003/12/21 19:42:42 florian
  1165. * fixed ppc inlining stuff
  1166. * fixed wrong unit writing
  1167. + added some sse stuff
  1168. Revision 1.146 2003/12/15 21:25:48 peter
  1169. * reg allocations for imaginary register are now inserted just
  1170. before reg allocation
  1171. * tregister changed to enum to allow compile time check
  1172. * fixed several tregister-tsuperregister errors
  1173. Revision 1.145 2003/12/07 12:41:32 jonas
  1174. * fixed ansistring/widestring results: deallocate result reg only after
  1175. it has been stored to memory, as the storing itself may require extra
  1176. results (e.g. on ppc)
  1177. Revision 1.144 2003/12/06 01:15:22 florian
  1178. * reverted Peter's alloctemp patch; hopefully properly
  1179. Revision 1.143 2003/12/03 23:13:20 peter
  1180. * delayed paraloc allocation, a_param_*() gets extra parameter
  1181. if it needs to allocate temp or real paralocation
  1182. * optimized/simplified int-real loading
  1183. Revision 1.142 2003/12/02 21:23:34 peter
  1184. * exitlabel for inline procs
  1185. Revision 1.141 2003/11/23 17:39:33 peter
  1186. * removed obsolete nf_cargs flag
  1187. Revision 1.140 2003/11/23 17:05:15 peter
  1188. * register calling is left-right
  1189. * parameter ordering
  1190. * left-right calling inserts result parameter last
  1191. Revision 1.139 2003/11/10 22:02:52 peter
  1192. * cross unit inlining fixed
  1193. Revision 1.138 2003/11/07 15:58:32 florian
  1194. * Florian's culmutative nr. 1; contains:
  1195. - invalid calling conventions for a certain cpu are rejected
  1196. - arm softfloat calling conventions
  1197. - -Sp for cpu dependend code generation
  1198. - several arm fixes
  1199. - remaining code for value open array paras on heap
  1200. Revision 1.137 2003/11/04 19:03:54 peter
  1201. * fixes for temp type patch
  1202. Revision 1.136 2003/11/04 15:35:13 peter
  1203. * fix for referencecounted temps
  1204. Revision 1.135 2003/10/30 17:12:49 peter
  1205. * fixed rangecheck error
  1206. Revision 1.134 2003/10/29 21:24:14 jonas
  1207. + support for fpu temp parameters
  1208. + saving/restoring of fpu register before/after a procedure call
  1209. Revision 1.133 2003/10/20 19:28:17 peter
  1210. * fixed inlining float parameters for i386
  1211. Revision 1.132 2003/10/17 14:38:32 peter
  1212. * 64k registers supported
  1213. * fixed some memory leaks
  1214. Revision 1.131 2003/10/17 01:22:08 florian
  1215. * compilation of the powerpc compiler fixed
  1216. Revision 1.130 2003/10/11 16:06:42 florian
  1217. * fixed some MMX<->SSE
  1218. * started to fix ppc, needs an overhaul
  1219. + stabs info improve for spilling, not sure if it works correctly/completly
  1220. - MMX_SUPPORT removed from Makefile.fpc
  1221. Revision 1.129 2003/10/10 17:48:13 peter
  1222. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  1223. * tregisteralloctor renamed to trgobj
  1224. * removed rgobj from a lot of units
  1225. * moved location_* and reference_* to cgobj
  1226. * first things for mmx register allocation
  1227. Revision 1.128 2003/10/10 09:21:53 marco
  1228. * typo fix from Wiktor
  1229. Revision 1.127 2003/10/09 21:31:37 daniel
  1230. * Register allocator splitted, ans abstract now
  1231. Revision 1.126 2003/10/07 15:17:07 peter
  1232. * inline supported again, LOC_REFERENCEs are used to pass the
  1233. parameters
  1234. * inlineparasymtable,inlinelocalsymtable removed
  1235. * exitlabel inserting fixed
  1236. Revision 1.125 2003/10/05 21:21:52 peter
  1237. * c style array of const generates callparanodes
  1238. * varargs paraloc fixes
  1239. Revision 1.124 2003/10/03 22:00:33 peter
  1240. * parameter alignment fixes
  1241. Revision 1.123 2003/10/01 20:34:48 peter
  1242. * procinfo unit contains tprocinfo
  1243. * cginfo renamed to cgbase
  1244. * moved cgmessage to verbose
  1245. * fixed ppc and sparc compiles
  1246. Revision 1.122 2003/09/30 21:02:37 peter
  1247. * updates for inlining
  1248. Revision 1.121 2003/09/30 19:55:19 peter
  1249. * remove abt reg for vmtreg
  1250. Revision 1.120 2003/09/29 20:58:55 peter
  1251. * optimized releasing of registers
  1252. Revision 1.119 2003/09/28 17:55:03 peter
  1253. * parent framepointer changed to hidden parameter
  1254. * tloadparentfpnode added
  1255. Revision 1.118 2003/09/28 13:54:43 peter
  1256. * removed a_call_ref
  1257. Revision 1.117 2003/09/25 21:28:00 peter
  1258. * parameter fixes
  1259. Revision 1.116 2003/09/23 17:56:05 peter
  1260. * locals and paras are allocated in the code generation
  1261. * tvarsym.localloc contains the location of para/local when
  1262. generating code for the current procedure
  1263. Revision 1.115 2003/09/16 16:17:01 peter
  1264. * varspez in calls to push_addr_param
  1265. Revision 1.114 2003/09/14 19:17:39 peter
  1266. * don't use a_call_ref because it can use a parameter register
  1267. as temp
  1268. Revision 1.113 2003/09/11 11:54:59 florian
  1269. * improved arm code generation
  1270. * move some protected and private field around
  1271. * the temp. register for register parameters/arguments are now released
  1272. before the move to the parameter register is done. This improves
  1273. the code in a lot of cases.
  1274. Revision 1.112 2003/09/10 08:31:47 marco
  1275. * Patch from Peter for paraloc
  1276. Revision 1.111 2003/09/07 22:09:35 peter
  1277. * preparations for different default calling conventions
  1278. * various RA fixes
  1279. Revision 1.110 2003/09/04 15:39:58 peter
  1280. * released useparatemp
  1281. Revision 1.109 2003/09/03 15:55:00 peter
  1282. * NEWRA branch merged
  1283. Revision 1.108.2.4 2003/09/01 21:02:55 peter
  1284. * sparc updates for new tregister
  1285. Revision 1.108.2.3 2003/08/31 21:07:44 daniel
  1286. * callparatemp ripped
  1287. Revision 1.108.2.2 2003/08/29 17:28:59 peter
  1288. * next batch of updates
  1289. Revision 1.108.2.1 2003/08/27 20:23:55 peter
  1290. * remove old ra code
  1291. Revision 1.108 2003/08/21 22:14:16 olle
  1292. - removed parameter from fpc_iocheck
  1293. Revision 1.107 2003/08/17 16:59:20 jonas
  1294. * fixed regvars so they work with newra (at least for ppc)
  1295. * fixed some volatile register bugs
  1296. + -dnotranslation option for -dnewra, which causes the registers not to
  1297. be translated from virtual to normal registers. Requires support in
  1298. the assembler writer as well, which is only implemented in aggas/
  1299. agppcgas currently
  1300. Revision 1.106 2003/08/16 18:56:40 marco
  1301. * fix from Jonas.
  1302. Revision 1.105 2003/08/11 21:18:20 peter
  1303. * start of sparc support for newra
  1304. Revision 1.104 2003/08/11 14:22:06 mazen
  1305. - dupplicated code removed
  1306. Revision 1.103 2003/07/23 11:01:14 jonas
  1307. * several rg.allocexplicitregistersint/rg.deallocexplicitregistersint
  1308. pairs round calls to helpers
  1309. Revision 1.102 2003/07/21 13:51:50 jonas
  1310. * fixed 64bit int results with -dnewra (you can't free both registers and
  1311. then allocate two new ones, because then the registers could be reversed
  1312. afterwards -> you get something like "movl %eax, %edx; movl %edx,%eax")
  1313. Revision 1.101 2003/07/08 21:24:59 peter
  1314. * sparc fixes
  1315. Revision 1.100 2003/07/06 21:50:33 jonas
  1316. * fixed ppc compilation problems and changed VOLATILE_REGISTERS for x86
  1317. so that it doesn't include ebp and esp anymore
  1318. Revision 1.99 2003/07/06 17:58:22 peter
  1319. * framepointer fixes for sparc
  1320. * parent framepointer code more generic
  1321. Revision 1.98 2003/07/06 15:31:20 daniel
  1322. * Fixed register allocator. *Lots* of fixes.
  1323. Revision 1.97 2003/07/05 20:21:26 jonas
  1324. * create_paraloc_info() is now called separately for the caller and
  1325. callee info
  1326. * fixed ppc cycle
  1327. Revision 1.96 2003/07/02 22:18:04 peter
  1328. * paraloc splitted in paraloc[callerside],calleeparaloc
  1329. * sparc calling convention updates
  1330. Revision 1.95 2003/06/17 16:34:44 jonas
  1331. * lots of newra fixes (need getfuncretparaloc implementation for i386)!
  1332. * renamed all_intregisters to paramanager.get_volatile_registers_int(pocall_default) and made it
  1333. processor dependent
  1334. Revision 1.94 2003/06/15 16:52:02 jonas
  1335. * release function result registers if the functino result isn't used
  1336. * don't allocate function result register with -dnewra if there is none
  1337. * some optimizations for non-x86 processor (don't save any registers
  1338. before a call)
  1339. Revision 1.93 2003/06/13 21:19:30 peter
  1340. * current_procdef removed, use current_procinfo.procdef instead
  1341. Revision 1.92 2003/06/12 21:10:50 peter
  1342. * newra fixes
  1343. Revision 1.91 2003/06/12 18:38:45 jonas
  1344. * deallocate parameter registers in time for newra
  1345. * for non-i386, procvars and methodpointers always have to be processed
  1346. in advance, whether or not newra is defined
  1347. Revision 1.90 2003/06/09 14:54:26 jonas
  1348. * (de)allocation of registers for parameters is now performed properly
  1349. (and checked on the ppc)
  1350. - removed obsolete allocation of all parameter registers at the start
  1351. of a procedure (and deallocation at the end)
  1352. Revision 1.89 2003/06/09 12:23:29 peter
  1353. * init/final of procedure data splitted from genentrycode
  1354. * use asmnode getposition to insert final at the correct position
  1355. als for the implicit try...finally
  1356. Revision 1.88 2003/06/08 20:01:53 jonas
  1357. * optimized assignments with on the right side a function that returns
  1358. an ansi- or widestring
  1359. Revision 1.87 2003/06/08 18:21:47 jonas
  1360. * fixed weird error in the copyleft statement :)
  1361. Revision 1.86 2003/06/07 18:57:04 jonas
  1362. + added freeintparaloc
  1363. * ppc get/freeintparaloc now check whether the parameter regs are
  1364. properly allocated/deallocated (and get an extra list para)
  1365. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  1366. * fixed lot of missing pi_do_call's
  1367. Revision 1.85 2003/06/04 06:43:36 jonas
  1368. * fixed double secondpassing of procvar loads
  1369. Revision 1.84 2003/06/03 21:11:09 peter
  1370. * cg.a_load_* get a from and to size specifier
  1371. * makeregsize only accepts newregister
  1372. * i386 uses generic tcgnotnode,tcgunaryminus
  1373. Revision 1.83 2003/06/03 20:27:02 daniel
  1374. * Restored original methodpointer code for non newra case
  1375. Revision 1.82 2003/06/03 13:01:59 daniel
  1376. * Register allocator finished
  1377. Revision 1.81 2003/06/01 21:38:06 peter
  1378. * getregisterfpu size parameter added
  1379. * op_const_reg size parameter added
  1380. * sparc updates
  1381. Revision 1.80 2003/05/31 15:05:28 peter
  1382. * FUNCTION_RESULT64_LOW/HIGH_REG added for int64 results
  1383. Revision 1.79 2003/05/31 00:59:44 peter
  1384. * typo in FUNCTION_RESULT_REG
  1385. Revision 1.78 2003/05/30 23:57:08 peter
  1386. * more sparc cleanup
  1387. * accumulator removed, splitted in function_return_reg (called) and
  1388. function_result_reg (caller)
  1389. Revision 1.77 2003/05/29 10:05:40 jonas
  1390. * free callparatemps created for call-by-reference parameters
  1391. Revision 1.76 2003/05/28 23:58:18 jonas
  1392. * added missing initialization of rg.usedintin,byproc
  1393. * ppc now also saves/restores used fpu registers
  1394. * ncgcal doesn't add used registers to usedby/inproc anymore, except for
  1395. i386
  1396. Revision 1.75 2003/05/26 21:17:17 peter
  1397. * procinlinenode removed
  1398. * aktexit2label removed, fast exit removed
  1399. + tcallnode.inlined_pass_2 added
  1400. Revision 1.74 2003/05/25 11:34:17 peter
  1401. * methodpointer self pushing fixed
  1402. Revision 1.73 2003/05/25 08:59:16 peter
  1403. * inline fixes
  1404. Revision 1.72 2003/05/24 13:36:54 jonas
  1405. * save fpu results in a normal fpu register on non-x86 processors
  1406. Revision 1.71 2003/05/23 19:35:50 jonas
  1407. - undid previous commit, it was wrong
  1408. Revision 1.70 2003/05/23 19:11:58 jonas
  1409. * fixed tests for whether a certain int register is unused
  1410. Revision 1.69 2003/05/23 18:01:56 jonas
  1411. * fixed ppc compiler
  1412. Revision 1.68 2003/05/23 14:27:35 peter
  1413. * remove some unit dependencies
  1414. * current_procinfo changes to store more info
  1415. Revision 1.67 2003/05/17 13:30:08 jonas
  1416. * changed tt_persistant to tt_persistent :)
  1417. * tempcreatenode now doesn't accept a boolean anymore for persistent
  1418. temps, but a ttemptype, so you can also create ansistring temps etc
  1419. Revision 1.66 2003/05/16 14:33:31 peter
  1420. * regvar fixes
  1421. Revision 1.65 2003/05/15 18:58:53 peter
  1422. * removed selfpointer_offset, vmtpointer_offset
  1423. * tvarsym.adjusted_address
  1424. * address in localsymtable is now in the real direction
  1425. * removed some obsolete globals
  1426. Revision 1.64 2003/05/14 19:36:54 jonas
  1427. * patch from Peter for int64 function results
  1428. Revision 1.63 2003/05/13 19:14:41 peter
  1429. * failn removed
  1430. * inherited result code check moven to pexpr
  1431. Revision 1.62 2003/05/13 15:18:18 peter
  1432. * generate code for procvar first before pushing parameters. Made
  1433. the already existing code for powerpc available for all platforms
  1434. Revision 1.61 2003/05/12 18:17:55 jonas
  1435. * moved fpc_check_object call earlier for the ppc, so it can't destroy
  1436. already-loaded parameter registers
  1437. Revision 1.60 2003/05/11 21:48:38 jonas
  1438. * fixed procvar bug on the ppc (load procvar before loading para's,
  1439. because the procvar may otherwise destroy the already loaded paras)
  1440. Revision 1.59 2003/05/09 17:47:02 peter
  1441. * self moved to hidden parameter
  1442. * removed hdisposen,hnewn,selfn
  1443. Revision 1.58 2003/05/05 14:53:16 peter
  1444. * vs_hidden replaced by is_hidden boolean
  1445. Revision 1.57 2003/04/30 20:53:32 florian
  1446. * error when address of an abstract method is taken
  1447. * fixed some x86-64 problems
  1448. * merged some more x86-64 and i386 code
  1449. Revision 1.56 2003/04/29 07:28:52 michael
  1450. + Patch from peter to fix wrong pushing of ansistring function results in open array
  1451. Revision 1.55 2003/04/27 11:21:33 peter
  1452. * aktprocdef renamed to current_procinfo.procdef
  1453. * procinfo renamed to current_procinfo
  1454. * procinfo will now be stored in current_module so it can be
  1455. cleaned up properly
  1456. * gen_main_procsym changed to create_main_proc and release_main_proc
  1457. to also generate a tprocinfo structure
  1458. * fixed unit implicit initfinal
  1459. Revision 1.54 2003/04/27 07:29:50 peter
  1460. * current_procinfo.procdef cleanup, current_procinfo.procdef is now always nil when parsing
  1461. a new procdef declaration
  1462. * aktprocsym removed
  1463. * lexlevel removed, use symtable.symtablelevel instead
  1464. * implicit init/final code uses the normal genentry/genexit
  1465. * funcret state checking updated for new funcret handling
  1466. Revision 1.53 2003/04/25 20:59:33 peter
  1467. * removed funcretn,funcretsym, function result is now in varsym
  1468. and aliases for result and function name are added using absolutesym
  1469. * vs_hidden parameter for funcret passed in parameter
  1470. * vs_hidden fixes
  1471. * writenode changed to printnode and released from extdebug
  1472. * -vp option added to generate a tree.log with the nodetree
  1473. * nicer printnode for statements, callnode
  1474. Revision 1.52 2003/04/25 08:25:26 daniel
  1475. * Ifdefs around a lot of calls to cleartempgen
  1476. * Fixed registers that are allocated but not freed in several nodes
  1477. * Tweak to register allocator to cause less spills
  1478. * 8-bit registers now interfere with esi,edi and ebp
  1479. Compiler can now compile rtl successfully when using new register
  1480. allocator
  1481. Revision 1.51 2003/04/22 23:50:22 peter
  1482. * firstpass uses expectloc
  1483. * checks if there are differences between the expectloc and
  1484. location.loc from secondpass in EXTDEBUG
  1485. Revision 1.50 2003/04/22 14:33:38 peter
  1486. * removed some notes/hints
  1487. Revision 1.49 2003/04/22 13:47:08 peter
  1488. * fixed C style array of const
  1489. * fixed C array passing
  1490. * fixed left to right with high parameters
  1491. Revision 1.48 2003/04/22 10:09:34 daniel
  1492. + Implemented the actual register allocator
  1493. + Scratch registers unavailable when new register allocator used
  1494. + maybe_save/maybe_restore unavailable when new register allocator used
  1495. Revision 1.47 2003/04/22 09:49:44 peter
  1496. * do not load self when calling a non-inherited class constructor
  1497. Revision 1.46 2003/04/21 20:03:32 peter
  1498. * forgot to copy vmtrefaddr to selfrefaddr when self=vmt
  1499. Revision 1.45 2003/04/21 13:53:16 jonas
  1500. - removed copying of all paras when secondpassing a callnode (this used
  1501. to be necessary for inlinign support, but currently the whole inlined
  1502. procedure is already copied in advance). Note that the compiler crashes
  1503. when compiling ucomplex with -dTEST_INLINE (also after fixing the
  1504. syntax errors), but that was also the case before this change.
  1505. Revision 1.44 2003/04/10 17:57:52 peter
  1506. * vs_hidden released
  1507. Revision 1.43 2003/04/06 21:11:23 olle
  1508. * changed newasmsymbol to newasmsymboldata for data symbols
  1509. Revision 1.42 2003/04/04 15:38:56 peter
  1510. * moved generic code from n386cal to ncgcal, i386 now also
  1511. uses the generic ncgcal
  1512. Revision 1.41 2003/03/28 19:16:56 peter
  1513. * generic constructor working for i386
  1514. * remove fixed self register
  1515. * esi added as address register for i386
  1516. Revision 1.40 2003/03/06 11:35:50 daniel
  1517. * Fixed internalerror 7843 issue
  1518. Revision 1.39 2003/02/19 22:00:14 daniel
  1519. * Code generator converted to new register notation
  1520. - Horribily outdated todo.txt removed
  1521. Revision 1.38 2003/02/15 22:17:38 carl
  1522. * bugfix of FPU emulation code
  1523. Revision 1.37 2003/02/12 22:10:07 carl
  1524. * load_frame_pointer is now generic
  1525. * change fpu emulation routine names
  1526. Revision 1.36 2003/01/30 21:46:57 peter
  1527. * self fixes for static methods (merged)
  1528. Revision 1.35 2003/01/22 20:45:15 mazen
  1529. * making math code in RTL compiling.
  1530. *NB : This does NOT mean necessary that it will generate correct code!
  1531. Revision 1.34 2003/01/17 12:03:45 daniel
  1532. * Optalign conditional code adapted to record Tregister
  1533. Revision 1.33 2003/01/08 18:43:56 daniel
  1534. * Tregister changed into a record
  1535. Revision 1.32 2002/12/15 22:50:00 florian
  1536. + some stuff for the new hidden parameter handling added
  1537. Revision 1.31 2002/12/15 21:30:12 florian
  1538. * tcallnode.paraitem introduced, all references to defcoll removed
  1539. Revision 1.30 2002/11/27 20:04:39 peter
  1540. * cdecl array of const fixes
  1541. Revision 1.29 2002/11/25 17:43:17 peter
  1542. * splitted defbase in defutil,symutil,defcmp
  1543. * merged isconvertable and is_equal into compare_defs(_ext)
  1544. * made operator search faster by walking the list only once
  1545. Revision 1.28 2002/11/18 17:31:54 peter
  1546. * pass proccalloption to ret_in_xxx and push_xxx functions
  1547. Revision 1.27 2002/11/16 15:34:30 florian
  1548. * generic location for float results
  1549. Revision 1.26 2002/11/15 01:58:51 peter
  1550. * merged changes from 1.0.7 up to 04-11
  1551. - -V option for generating bug report tracing
  1552. - more tracing for option parsing
  1553. - errors for cdecl and high()
  1554. - win32 import stabs
  1555. - win32 records<=8 are returned in eax:edx (turned off by default)
  1556. - heaptrc update
  1557. - more info for temp management in .s file with EXTDEBUG
  1558. Revision 1.25 2002/10/05 12:43:25 carl
  1559. * fixes for Delphi 6 compilation
  1560. (warning : Some features do not work under Delphi)
  1561. Revision 1.24 2002/09/30 07:00:45 florian
  1562. * fixes to common code to get the alpha compiler compiled applied
  1563. Revision 1.23 2002/09/17 18:54:02 jonas
  1564. * a_load_reg_reg() now has two size parameters: source and dest. This
  1565. allows some optimizations on architectures that don't encode the
  1566. register size in the register name.
  1567. Revision 1.22 2002/09/07 15:25:02 peter
  1568. * old logs removed and tabs fixed
  1569. Revision 1.21 2002/09/07 11:50:02 jonas
  1570. * fixed small regalloction info bug
  1571. Revision 1.20 2002/09/02 11:25:20 florian
  1572. * fixed generic procedure variable calling
  1573. Revision 1.19 2002/09/01 21:04:48 florian
  1574. * several powerpc related stuff fixed
  1575. Revision 1.18 2002/09/01 18:43:27 peter
  1576. * include FUNCTION_RETURN_REG in regs_to_push list
  1577. Revision 1.17 2002/09/01 12:13:00 peter
  1578. * use a_call_reg
  1579. * ungetiftemp for procvar of object temp
  1580. Revision 1.16 2002/08/25 19:25:18 peter
  1581. * sym.insert_in_data removed
  1582. * symtable.insertvardata/insertconstdata added
  1583. * removed insert_in_data call from symtable.insert, it needs to be
  1584. called separatly. This allows to deref the address calculation
  1585. * procedures now calculate the parast addresses after the procedure
  1586. directives are parsed. This fixes the cdecl parast problem
  1587. * push_addr_param has an extra argument that specifies if cdecl is used
  1588. or not
  1589. Revision 1.15 2002/08/23 16:14:48 peter
  1590. * tempgen cleanup
  1591. * tt_noreuse temp type added that will be used in genentrycode
  1592. Revision 1.14 2002/08/20 16:55:38 peter
  1593. * don't write (stabs)line info when inlining a procedure
  1594. Revision 1.13 2002/08/19 19:36:42 peter
  1595. * More fixes for cross unit inlining, all tnodes are now implemented
  1596. * Moved pocall_internconst to po_internconst because it is not a
  1597. calling type at all and it conflicted when inlining of these small
  1598. functions was requested
  1599. Revision 1.12 2002/08/18 20:06:23 peter
  1600. * inlining is now also allowed in interface
  1601. * renamed write/load to ppuwrite/ppuload
  1602. * tnode storing in ppu
  1603. * nld,ncon,nbas are already updated for storing in ppu
  1604. Revision 1.11 2002/08/17 22:09:44 florian
  1605. * result type handling in tcgcal.pass_2 overhauled
  1606. * better tnode.dowrite
  1607. * some ppc stuff fixed
  1608. Revision 1.10 2002/08/17 09:23:35 florian
  1609. * first part of procinfo rewrite
  1610. Revision 1.9 2002/08/13 21:40:55 florian
  1611. * more fixes for ppc calling conventions
  1612. Revision 1.8 2002/08/13 18:01:51 carl
  1613. * rename swatoperands to swapoperands
  1614. + m68k first compilable version (still needs a lot of testing):
  1615. assembler generator, system information , inline
  1616. assembler reader.
  1617. Revision 1.7 2002/08/12 15:08:39 carl
  1618. + stab register indexes for powerpc (moved from gdb to cpubase)
  1619. + tprocessor enumeration moved to cpuinfo
  1620. + linker in target_info is now a class
  1621. * many many updates for m68k (will soon start to compile)
  1622. - removed some ifdef or correct them for correct cpu
  1623. Revision 1.6 2002/08/11 14:32:26 peter
  1624. * renamed current_library to objectlibrary
  1625. Revision 1.5 2002/08/11 13:24:11 peter
  1626. * saving of asmsymbols in ppu supported
  1627. * asmsymbollist global is removed and moved into a new class
  1628. tasmlibrarydata that will hold the info of a .a file which
  1629. corresponds with a single module. Added librarydata to tmodule
  1630. to keep the library info stored for the module. In the future the
  1631. objectfiles will also be stored to the tasmlibrarydata class
  1632. * all getlabel/newasmsymbol and friends are moved to the new class
  1633. Revision 1.4 2002/08/06 20:55:20 florian
  1634. * first part of ppc calling conventions fix
  1635. Revision 1.3 2002/07/20 11:57:53 florian
  1636. * types.pas renamed to defbase.pas because D6 contains a types
  1637. unit so this would conflicts if D6 programms are compiled
  1638. + Willamette/SSE2 instructions to assembler added
  1639. Revision 1.2 2002/07/13 19:38:43 florian
  1640. * some more generic calling stuff fixed
  1641. }