ncgutil.pas 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Helper routines for all code generators
  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 ncgutil;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,cpuinfo,
  23. cpubase,cpupara,
  24. aasmbase,aasmtai,aasmcpu,
  25. cginfo,symbase,symdef,symtype,
  26. rgobj;
  27. type
  28. tloadregvars = (lr_dont_load_regvars, lr_load_regvars);
  29. tmaybesave = record
  30. saved : boolean;
  31. ref : treference;
  32. end;
  33. procedure firstcomplex(p : tbinarynode);
  34. procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
  35. procedure remove_non_regvars_from_loc(const t: tlocation; var regs: tregisterset);
  36. procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  37. procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
  38. procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
  39. procedure maybe_restore(list:taasmoutput;var l:tlocation;const s:tmaybesave);
  40. function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
  41. procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
  42. para_offset:longint;alignment : longint;
  43. const locpara : tparalocation);
  44. procedure genentrycode(list : TAAsmoutput;
  45. make_global:boolean;
  46. stackframe:longint;
  47. var parasize:longint;var nostackframe:boolean;
  48. inlined : boolean);
  49. procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe,inlined:boolean);
  50. procedure genimplicitunitinit(list : TAAsmoutput);
  51. procedure genimplicitunitfinal(list : TAAsmoutput);
  52. {#
  53. Allocate the buffers for exception management and setjmp environment.
  54. Return a pointer to these buffers, send them to the utility routine
  55. so they are registered, and then call setjmp.
  56. Then compare the result of setjmp with 0, and if not equal
  57. to zero, then jump to exceptlabel.
  58. Also store the result of setjmp to a temporary space by calling g_save_exception_reason
  59. It is to note that this routine may be called *after* the stackframe of a
  60. routine has been called, therefore on machines where the stack cannot
  61. be modified, all temps should be allocated on the heap instead of the
  62. stack.
  63. }
  64. procedure new_exception(list : taasmoutput;const jmpbuf,envbuf, href : treference;
  65. a : aword; exceptlabel : tasmlabel);
  66. procedure free_exception(list : taasmoutput;const jmpbuf, envbuf, href : treference;
  67. a : aword ; endexceptlabel : tasmlabel; onlyfree : boolean);
  68. implementation
  69. uses
  70. {$ifdef Delphi}
  71. Sysutils,
  72. {$else}
  73. strings,
  74. {$endif}
  75. cutils,cclasses,globtype,globals,systems,verbose,
  76. symconst,symsym,symtable,defbase,paramgr,
  77. fmodule,
  78. cgbase,regvars,
  79. {$ifdef GDB}
  80. gdb,
  81. {$endif GDB}
  82. ncon,
  83. tgobj,cgobj,cgcpu,cg64f32;
  84. {*****************************************************************************
  85. Misc Helpers
  86. *****************************************************************************}
  87. { DO NOT RELY on the fact that the tnode is not yet swaped
  88. because of inlining code PM }
  89. procedure firstcomplex(p : tbinarynode);
  90. var
  91. hp : tnode;
  92. begin
  93. { always calculate boolean AND and OR from left to right }
  94. if (p.nodetype in [orn,andn]) and
  95. (p.left.resulttype.def.deftype=orddef) and
  96. (torddef(p.left.resulttype.def).typ in [bool8bit,bool16bit,bool32bit]) then
  97. begin
  98. { p.swaped:=false}
  99. if nf_swaped in p.flags then
  100. internalerror(234234);
  101. end
  102. else
  103. if (((p.location.loc=LOC_FPUREGISTER) and
  104. (p.right.registersfpu > p.left.registersfpu)) or
  105. ((((p.left.registersfpu = 0) and
  106. (p.right.registersfpu = 0)) or
  107. (p.location.loc<>LOC_FPUREGISTER)) and
  108. (p.left.registers32<p.right.registers32))) and
  109. { the following check is appropriate, because all }
  110. { 4 registers are rarely used and it is thereby }
  111. { achieved that the extra code is being dropped }
  112. { by exchanging not commutative operators }
  113. (p.right.registers32<=c_countusableregsint) then
  114. begin
  115. hp:=p.left;
  116. p.left:=p.right;
  117. p.right:=hp;
  118. if nf_swaped in p.flags then
  119. exclude(p.flags,nf_swaped)
  120. else
  121. include(p.flags,nf_swaped);
  122. end;
  123. end;
  124. procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
  125. {
  126. produces jumps to true respectively false labels using boolean expressions
  127. depending on whether the loading of regvars is currently being
  128. synchronized manually (such as in an if-node) or automatically (most of
  129. the other cases where this procedure is called), loadregvars can be
  130. "lr_load_regvars" or "lr_dont_load_regvars"
  131. }
  132. var
  133. opsize : tcgsize;
  134. storepos : tfileposinfo;
  135. begin
  136. if nf_error in p.flags then
  137. exit;
  138. storepos:=aktfilepos;
  139. aktfilepos:=p.fileinfo;
  140. if is_boolean(p.resulttype.def) then
  141. begin
  142. if loadregvars = lr_load_regvars then
  143. load_all_regvars(list);
  144. if is_constboolnode(p) then
  145. begin
  146. if tordconstnode(p).value<>0 then
  147. cg.a_jmp_always(list,truelabel)
  148. else
  149. cg.a_jmp_always(list,falselabel)
  150. end
  151. else
  152. begin
  153. opsize:=def_cgsize(p.resulttype.def);
  154. case p.location.loc of
  155. LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
  156. begin
  157. if (p.location.loc = LOC_CREGISTER) then
  158. load_regvar_reg(list,p.location.register);
  159. cg.a_cmp_const_loc_label(list,opsize,OC_NE,
  160. 0,p.location,truelabel);
  161. { !!! should happen right after cmp (JM) }
  162. location_release(list,p.location);
  163. cg.a_jmp_always(list,falselabel);
  164. end;
  165. LOC_FLAGS :
  166. begin
  167. cg.a_jmp_flags(list,p.location.resflags,
  168. truelabel);
  169. cg.a_jmp_always(list,falselabel);
  170. end;
  171. end;
  172. end;
  173. end
  174. else
  175. internalerror(200112305);
  176. aktfilepos:=storepos;
  177. end;
  178. procedure remove_non_regvars_from_loc(const t: tlocation; var regs: tregisterset);
  179. begin
  180. case t.loc of
  181. LOC_REGISTER:
  182. begin
  183. { can't be a regvar, since it would be LOC_CREGISTER then }
  184. exclude(regs,t.register);
  185. if t.registerhigh <> R_NO then
  186. exclude(regs,t.registerhigh);
  187. end;
  188. LOC_CREFERENCE,LOC_REFERENCE:
  189. begin
  190. if not(cs_regalloc in aktglobalswitches) or
  191. (t.reference.base in rg.usableregsint) then
  192. exclude(regs,t.reference.base);
  193. if not(cs_regalloc in aktglobalswitches) or
  194. (t.reference.index in rg.usableregsint) then
  195. exclude(regs,t.reference.index);
  196. end;
  197. end;
  198. end;
  199. {*****************************************************************************
  200. EXCEPTION MANAGEMENT
  201. *****************************************************************************}
  202. procedure new_exception(list : taasmoutput;const jmpbuf,envbuf, href : treference;
  203. a : aword; exceptlabel : tasmlabel);
  204. begin
  205. cg.a_paramaddr_ref(list,envbuf,paramanager.getintparaloc(3));
  206. cg.a_paramaddr_ref(list,jmpbuf,paramanager.getintparaloc(2));
  207. { push type of exceptionframe }
  208. cg.a_param_const(list,OS_S32,1,paramanager.getintparaloc(1));
  209. cg.a_call_name(list,'FPC_PUSHEXCEPTADDR');
  210. cg.a_param_reg(list,OS_ADDR,accumulator,paramanager.getintparaloc(1));
  211. cg.a_call_name(list,'FPC_SETJMP');
  212. cg.g_exception_reason_save(list, href);
  213. cg.a_cmp_const_reg_label(list,OS_S32,OC_NE,0,accumulator,exceptlabel);
  214. end;
  215. procedure free_exception(list : taasmoutput;const jmpbuf, envbuf, href : treference;
  216. a : aword ; endexceptlabel : tasmlabel; onlyfree : boolean);
  217. begin
  218. cg.a_call_name(list,'FPC_POPADDRSTACK');
  219. if not onlyfree then
  220. begin
  221. cg.g_exception_reason_load(list, href);
  222. cg.a_cmp_const_reg_label(list,OS_S32,OC_EQ,a,accumulator,endexceptlabel);
  223. end;
  224. end;
  225. {*****************************************************************************
  226. TLocation
  227. *****************************************************************************}
  228. { 32-bit version }
  229. procedure location_force_reg32(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  230. var
  231. hregister,
  232. hregisterhi : tregister;
  233. hreg64 : tregister64;
  234. hl : tasmlabel;
  235. begin
  236. { handle transformations to 64bit separate }
  237. if dst_size in [OS_64,OS_S64] then
  238. begin
  239. if not (l.size in [OS_64,OS_S64]) then
  240. begin
  241. { load a smaller size to OS_64 }
  242. if l.loc=LOC_REGISTER then
  243. begin
  244. hregister:=rg.makeregsize(l.registerlow,OS_INT);
  245. cg.a_load_reg_reg(list,l.size,l.registerlow,hregister);
  246. end
  247. else
  248. hregister:=rg.getregisterint(list);
  249. { load value in low register }
  250. case l.loc of
  251. LOC_FLAGS :
  252. cg.g_flags2reg(list,OS_INT,l.resflags,hregister);
  253. LOC_JUMP :
  254. begin
  255. cg.a_label(list,truelabel);
  256. cg.a_load_const_reg(list,OS_INT,1,hregister);
  257. objectlibrary.getlabel(hl);
  258. cg.a_jmp_always(list,hl);
  259. cg.a_label(list,falselabel);
  260. cg.a_load_const_reg(list,OS_INT,0,hregister);
  261. cg.a_label(list,hl);
  262. end;
  263. else
  264. cg.a_load_loc_reg(list,l,hregister);
  265. end;
  266. { reset hi part, take care of the signed bit of the current value }
  267. hregisterhi:=rg.getregisterint(list);
  268. if (dst_size=OS_S64) and
  269. (l.size in [OS_S8,OS_S16,OS_S32]) then
  270. begin
  271. if l.loc=LOC_CONSTANT then
  272. begin
  273. if (longint(l.value)<0) then
  274. cg.a_load_const_reg(list,OS_32,$ffffffff,hregisterhi)
  275. else
  276. cg.a_load_const_reg(list,OS_32,0,hregisterhi);
  277. end
  278. else
  279. begin
  280. cg.a_op_const_reg_reg(list,OP_SAR,OS_32,31,hregister,
  281. hregisterhi);
  282. end;
  283. end
  284. else
  285. cg.a_load_const_reg(list,OS_32,0,hregisterhi);
  286. location_reset(l,LOC_REGISTER,dst_size);
  287. l.registerlow:=hregister;
  288. l.registerhigh:=hregisterhi;
  289. end
  290. else
  291. begin
  292. { 64bit to 64bit }
  293. if (l.loc=LOC_REGISTER) or
  294. ((l.loc=LOC_CREGISTER) and maybeconst) then
  295. begin
  296. hregister:=l.registerlow;
  297. hregisterhi:=l.registerhigh;
  298. end
  299. else
  300. begin
  301. hregister:=rg.getregisterint(list);
  302. hregisterhi:=rg.getregisterint(list);
  303. end;
  304. hreg64.reglo:=hregister;
  305. hreg64.reghi:=hregisterhi;
  306. { load value in new register }
  307. cg64.a_load64_loc_reg(list,l,hreg64);
  308. location_reset(l,LOC_REGISTER,dst_size);
  309. l.registerlow:=hregister;
  310. l.registerhigh:=hregisterhi;
  311. end;
  312. end
  313. else
  314. begin
  315. { transformations to 32bit or smaller }
  316. if l.loc=LOC_REGISTER then
  317. begin
  318. { if the previous was 64bit release the high register }
  319. if l.size in [OS_64,OS_S64] then
  320. begin
  321. rg.ungetregisterint(list,l.registerhigh);
  322. l.registerhigh:=R_NO;
  323. end;
  324. hregister:=l.register;
  325. end
  326. else
  327. begin
  328. { get new register }
  329. if (l.loc=LOC_CREGISTER) and
  330. maybeconst and
  331. (TCGSize2Size[dst_size]=TCGSize2Size[l.size]) then
  332. hregister:=l.register
  333. else
  334. hregister:=rg.getregisterint(list);
  335. end;
  336. hregister:=rg.makeregsize(hregister,dst_size);
  337. { load value in new register }
  338. case l.loc of
  339. LOC_FLAGS :
  340. cg.g_flags2reg(list,dst_size,l.resflags,hregister);
  341. LOC_JUMP :
  342. begin
  343. cg.a_label(list,truelabel);
  344. cg.a_load_const_reg(list,dst_size,1,hregister);
  345. objectlibrary.getlabel(hl);
  346. cg.a_jmp_always(list,hl);
  347. cg.a_label(list,falselabel);
  348. cg.a_load_const_reg(list,dst_size,0,hregister);
  349. cg.a_label(list,hl);
  350. end;
  351. else
  352. begin
  353. { load_loc_reg can only handle size >= l.size, when the
  354. new size is smaller then we need to adjust the size
  355. of the orignal and maybe recalculate l.register for i386 }
  356. if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
  357. begin
  358. if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  359. l.register:=rg.makeregsize(l.register,dst_size);
  360. { for big endian systems, the reference's offset must }
  361. { be increased in this case, since they have the }
  362. { MSB first in memory and e.g. byte(word_var) should }
  363. { return the second byte in this case (JM) }
  364. if (target_info.endian = ENDIAN_BIG) and
  365. (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  366. inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
  367. l.size:=dst_size;
  368. end;
  369. cg.a_load_loc_reg(list,l,hregister);
  370. end;
  371. end;
  372. location_reset(l,LOC_REGISTER,dst_size);
  373. l.register:=hregister;
  374. end;
  375. end;
  376. { 64-bit version }
  377. procedure location_force_reg64(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  378. var
  379. hregister : tregister;
  380. hl : tasmlabel;
  381. begin
  382. { handle transformations to 64bit separate }
  383. if dst_size in [OS_64,OS_S64] then
  384. begin
  385. { load a smaller size to OS_64 }
  386. if l.loc=LOC_REGISTER then
  387. hregister:=rg.makeregsize(l.register,OS_INT)
  388. else
  389. hregister:=rg.getregisterint(list);
  390. { load value in low register }
  391. case l.loc of
  392. LOC_FLAGS :
  393. cg.g_flags2reg(list,OS_INT,l.resflags,hregister);
  394. LOC_JUMP :
  395. begin
  396. cg.a_label(list,truelabel);
  397. cg.a_load_const_reg(list,OS_INT,1,hregister);
  398. objectlibrary.getlabel(hl);
  399. cg.a_jmp_always(list,hl);
  400. cg.a_label(list,falselabel);
  401. cg.a_load_const_reg(list,OS_INT,0,hregister);
  402. cg.a_label(list,hl);
  403. end;
  404. else
  405. cg.a_load_loc_reg(list,l,hregister);
  406. end;
  407. location_reset(l,LOC_REGISTER,dst_size);
  408. l.register:=hregister;
  409. end
  410. else
  411. begin
  412. { transformations to 32bit or smaller }
  413. if l.loc=LOC_REGISTER then
  414. begin
  415. hregister:=l.register;
  416. end
  417. else
  418. begin
  419. { get new register }
  420. if (l.loc=LOC_CREGISTER) and
  421. maybeconst and
  422. (TCGSize2Size[dst_size]=TCGSize2Size[l.size]) then
  423. hregister:=l.register
  424. else
  425. hregister:=rg.getregisterint(list);
  426. end;
  427. hregister:=rg.makeregsize(hregister,dst_size);
  428. { load value in new register }
  429. case l.loc of
  430. LOC_FLAGS :
  431. cg.g_flags2reg(list,dst_size,l.resflags,hregister);
  432. LOC_JUMP :
  433. begin
  434. cg.a_label(list,truelabel);
  435. cg.a_load_const_reg(list,dst_size,1,hregister);
  436. objectlibrary.getlabel(hl);
  437. cg.a_jmp_always(list,hl);
  438. cg.a_label(list,falselabel);
  439. cg.a_load_const_reg(list,dst_size,0,hregister);
  440. cg.a_label(list,hl);
  441. end;
  442. else
  443. begin
  444. { load_loc_reg can only handle size >= l.size, when the
  445. new size is smaller then we need to adjust the size
  446. of the orignal and maybe recalculate l.register for i386 }
  447. if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
  448. begin
  449. if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  450. l.register:=rg.makeregsize(l.register,dst_size);
  451. { for big endian systems, the reference's offset must }
  452. { be increased in this case, since they have the }
  453. { MSB first in memory and e.g. byte(word_var) should }
  454. { return the second byte in this case (JM) }
  455. if (target_info.endian = ENDIAN_BIG) and
  456. (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  457. inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
  458. l.size:=dst_size;
  459. end;
  460. cg.a_load_loc_reg(list,l,hregister);
  461. end;
  462. end;
  463. location_reset(l,LOC_REGISTER,dst_size);
  464. l.register:=hregister;
  465. end;
  466. end;
  467. procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  468. begin
  469. { release previous location before demanding a new register }
  470. if (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  471. begin
  472. location_freetemp(list,l);
  473. location_release(list,l);
  474. end;
  475. if sizeof(aword) < 8 then
  476. location_force_reg32(list, l, dst_size, maybeconst)
  477. else
  478. location_force_reg64(list, l, dst_size, maybeconst);
  479. end;
  480. procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
  481. var
  482. r : treference;
  483. begin
  484. case l.loc of
  485. LOC_FPUREGISTER,
  486. LOC_CFPUREGISTER :
  487. begin
  488. tg.gettempofsizereference(list,TCGSize2Size[l.size],r);
  489. cg.a_loadfpu_reg_ref(list,l.size,l.register,r);
  490. location_reset(l,LOC_REFERENCE,l.size);
  491. l.reference:=r;
  492. end;
  493. LOC_CONSTANT,
  494. LOC_REGISTER,
  495. LOC_CREGISTER :
  496. begin
  497. tg.gettempofsizereference(list,TCGSize2Size[l.size],r);
  498. if l.size in [OS_64,OS_S64] then
  499. cg64.a_load64_loc_ref(list,l,r)
  500. else
  501. cg.a_load_loc_ref(list,l,r);
  502. location_reset(l,LOC_REFERENCE,l.size);
  503. l.reference:=r;
  504. end;
  505. LOC_CREFERENCE,
  506. LOC_REFERENCE : ;
  507. else
  508. internalerror(200203219);
  509. end;
  510. end;
  511. {*****************************************************************************
  512. Maybe_Save
  513. *****************************************************************************}
  514. procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
  515. begin
  516. s.saved:=false;
  517. if l.loc=LOC_CREGISTER then
  518. begin
  519. s.saved:=true;
  520. exit;
  521. end;
  522. if needed>rg.countunusedregsint then
  523. begin
  524. case l.loc of
  525. LOC_REGISTER :
  526. begin
  527. if l.size in [OS_64,OS_S64] then
  528. begin
  529. tg.gettempofsizereference(exprasmlist,8,s.ref);
  530. cg64.a_load64_reg_ref(exprasmlist,joinreg64(l.registerlow,l.registerhigh),s.ref);
  531. end
  532. else
  533. begin
  534. tg.gettempofsizereference(exprasmlist,TCGSize2Size[l.size],s.ref);
  535. cg.a_load_reg_ref(exprasmlist,l.size,l.register,s.ref);
  536. end;
  537. location_release(exprasmlist,l);
  538. s.saved:=true;
  539. end;
  540. LOC_REFERENCE,
  541. LOC_CREFERENCE :
  542. begin
  543. if ((l.reference.base<>R_NO) or
  544. (l.reference.index<>R_NO)) then
  545. begin
  546. { load address into a single base register }
  547. cg.a_loadaddr_ref_reg(list,l.reference,l.reference.base);
  548. { save base register }
  549. tg.gettempofsizereference(exprasmlist,TCGSize2Size[OS_ADDR],s.ref);
  550. cg.a_load_reg_ref(exprasmlist,OS_ADDR,l.reference.base,s.ref);
  551. { release }
  552. location_release(exprasmlist,l);
  553. s.saved:=true;
  554. end;
  555. end;
  556. end;
  557. end;
  558. end;
  559. procedure maybe_restore(list:taasmoutput;var l:tlocation;const s:tmaybesave);
  560. begin
  561. if not s.saved then
  562. exit;
  563. if l.loc=LOC_CREGISTER then
  564. begin
  565. load_regvar_reg(list,l.register);
  566. exit;
  567. end;
  568. case l.loc of
  569. LOC_REGISTER :
  570. begin
  571. if l.size in [OS_64,OS_S64] then
  572. begin
  573. l.registerlow:=rg.getregisterint(exprasmlist);
  574. l.registerhigh:=rg.getregisterint(exprasmlist);
  575. cg64.a_load64_ref_reg(exprasmlist,s.ref,joinreg64(l.registerlow,l.registerhigh));
  576. end
  577. else
  578. begin
  579. l.register:=rg.getregisterint(exprasmlist);
  580. cg.a_load_ref_reg(exprasmlist,OS_INT,s.ref,l.register);
  581. end;
  582. end;
  583. LOC_CREFERENCE,
  584. LOC_REFERENCE :
  585. begin
  586. reference_reset(l.reference);
  587. l.reference.base:=rg.getaddressregister(exprasmlist);
  588. cg.a_load_ref_reg(exprasmlist,OS_ADDR,s.ref,l.reference.base);
  589. end;
  590. end;
  591. tg.ungetiftemp(exprasmlist,s.ref);
  592. end;
  593. function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
  594. begin
  595. if (needed>=maxfpuregs) and
  596. (l.loc = LOC_FPUREGISTER) then
  597. begin
  598. location_force_mem(list,l);
  599. maybe_pushfpu:=true;
  600. end
  601. else
  602. maybe_pushfpu:=false;
  603. end;
  604. {*****************************************************************************
  605. Push Value Para
  606. *****************************************************************************}
  607. procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
  608. para_offset:longint;alignment : longint;
  609. const locpara : tparalocation);
  610. var
  611. tempreference : treference;
  612. href : treference;
  613. hreg : tregister;
  614. sizetopush,
  615. size : longint;
  616. cgsize : tcgsize;
  617. begin
  618. { Move flags and jump in register to make it less complex }
  619. if p.location.loc in [LOC_FLAGS,LOC_JUMP] then
  620. location_force_reg(exprasmlist,p.location,def_cgsize(p.resulttype.def),false);
  621. { Handle Floating point types differently }
  622. if p.resulttype.def.deftype=floatdef then
  623. begin
  624. case p.location.loc of
  625. LOC_FPUREGISTER,
  626. LOC_CFPUREGISTER:
  627. begin
  628. size:=align(tfloatdef(p.resulttype.def).size,alignment);
  629. inc(pushedparasize,size);
  630. if not inlined then
  631. cg.a_op_const_reg(exprasmlist,OP_SUB,size,STACK_POINTER_REG);
  632. {$ifdef GDB}
  633. if (cs_debuginfo in aktmoduleswitches) and
  634. (exprasmList.first=exprasmList.last) then
  635. exprasmList.concat(Tai_force_line.Create);
  636. {$endif GDB}
  637. { this is the easiest case for inlined !! }
  638. if inlined then
  639. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize)
  640. else
  641. reference_reset_base(href,stack_pointer_reg,0);
  642. cg.a_loadfpu_reg_ref(exprasmlist,
  643. def_cgsize(p.resulttype.def),p.location.register,href);
  644. end;
  645. LOC_REFERENCE,
  646. LOC_CREFERENCE :
  647. begin
  648. sizetopush:=align(p.resulttype.def.size,alignment);
  649. tempreference:=p.location.reference;
  650. inc(tempreference.offset,sizetopush);
  651. while (sizetopush>0) do
  652. begin
  653. if sizetopush>=4 then
  654. begin
  655. cgsize:=OS_32;
  656. inc(pushedparasize,4);
  657. dec(tempreference.offset,4);
  658. dec(sizetopush,4);
  659. end
  660. else
  661. begin
  662. cgsize:=OS_16;
  663. inc(pushedparasize,2);
  664. dec(tempreference.offset,2);
  665. dec(sizetopush,2);
  666. end;
  667. if inlined then
  668. begin
  669. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  670. cg.a_load_ref_ref(exprasmlist,cgsize,tempreference,href);
  671. end
  672. else
  673. cg.a_param_ref(exprasmlist,cgsize,tempreference,locpara);
  674. end;
  675. end;
  676. else
  677. internalerror(200204243);
  678. end;
  679. end
  680. else
  681. begin
  682. { call by value open array ? }
  683. if is_cdecl and
  684. paramanager.push_addr_param(p.resulttype.def) then
  685. begin
  686. if not (p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  687. internalerror(200204241);
  688. { push on stack }
  689. size:=align(p.resulttype.def.size,alignment);
  690. inc(pushedparasize,size);
  691. cg.a_op_const_reg(exprasmlist,OP_SUB,size,STACK_POINTER_REG);
  692. reference_reset_base(href,STACK_POINTER_REG,0);
  693. cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false);
  694. end
  695. else
  696. begin
  697. case p.location.loc of
  698. LOC_CONSTANT,
  699. LOC_REGISTER,
  700. LOC_CREGISTER,
  701. LOC_REFERENCE,
  702. LOC_CREFERENCE :
  703. begin
  704. cgsize:=def_cgsize(p.resulttype.def);
  705. if cgsize in [OS_64,OS_S64] then
  706. begin
  707. inc(pushedparasize,8);
  708. if inlined then
  709. begin
  710. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  711. cg64.a_load64_loc_ref(exprasmlist,p.location,href);
  712. end
  713. else
  714. cg64.a_param64_loc(exprasmlist,p.location,locpara);
  715. end
  716. else
  717. begin
  718. case cgsize of
  719. OS_8,OS_S8 :
  720. begin
  721. if alignment=4 then
  722. cgsize:=OS_32
  723. else
  724. cgsize:=OS_16;
  725. end;
  726. OS_16,OS_S16 :
  727. begin
  728. if alignment=4 then
  729. cgsize:=OS_32;
  730. end;
  731. end;
  732. { update register to use to match alignment }
  733. if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  734. begin
  735. hreg:=p.location.register;
  736. p.location.register:=rg.makeregsize(p.location.register,cgsize);
  737. end;
  738. inc(pushedparasize,alignment);
  739. if inlined then
  740. begin
  741. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  742. cg.a_load_loc_ref(exprasmlist,p.location,href);
  743. end
  744. else
  745. cg.a_param_loc(exprasmlist,p.location,locpara);
  746. { restore old register }
  747. if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  748. p.location.register:=hreg;
  749. end;
  750. location_release(exprasmlist,p.location);
  751. end;
  752. {$ifdef SUPPORT_MMX}
  753. LOC_MMXREGISTER,
  754. LOC_CMMXREGISTER:
  755. begin
  756. inc(pushedparasize,8);
  757. if inlined then
  758. begin
  759. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  760. cg.a_loadmm_reg_ref(exprasmlist,p.location.register,href);
  761. end
  762. else
  763. cg.a_parammm_reg(exprasmlist,p.location.register);
  764. end;
  765. {$endif SUPPORT_MMX}
  766. else
  767. internalerror(200204241);
  768. end;
  769. end;
  770. end;
  771. end;
  772. {****************************************************************************
  773. Entry/Exit Code
  774. ****************************************************************************}
  775. procedure copyvalueparas(p : tnamedindexitem;arg:pointer);
  776. var
  777. href1,href2 : treference;
  778. list : taasmoutput;
  779. begin
  780. list:=taasmoutput(arg);
  781. if (tsym(p).typ=varsym) and
  782. (tvarsym(p).varspez=vs_value) and
  783. (paramanager.push_addr_param(tvarsym(p).vartype.def)) then
  784. begin
  785. reference_reset_base(href1,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  786. if is_open_array(tvarsym(p).vartype.def) or
  787. is_array_of_const(tvarsym(p).vartype.def) then
  788. cg.g_copyvaluepara_openarray(list,href1,tarraydef(tvarsym(p).vartype.def).elesize)
  789. else
  790. begin
  791. reference_reset_base(href2,procinfo.framepointer,-tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup);
  792. if is_shortstring(tvarsym(p).vartype.def) then
  793. cg.g_copyshortstring(list,href1,href2,tstringdef(tvarsym(p).vartype.def).len,false,true)
  794. else
  795. cg.g_concatcopy(list,href1,href2,tvarsym(p).vartype.def.size,true,true);
  796. end;
  797. end;
  798. end;
  799. procedure initialize_threadvar(p : tnamedindexitem;arg:pointer);
  800. var
  801. href : treference;
  802. list : taasmoutput;
  803. begin
  804. list:=taasmoutput(arg);
  805. if (tsym(p).typ=varsym) and
  806. (vo_is_thread_var in tvarsym(p).varoptions) then
  807. begin
  808. cg.a_param_const(list,OS_INT,tvarsym(p).getsize,paramanager.getintparaloc(2));
  809. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(p).mangledname),0);
  810. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(1));
  811. rg.saveregvars(list,all_registers);
  812. cg.a_call_name(list,'FPC_INIT_THREADVAR');
  813. end;
  814. end;
  815. { generates the code for initialisation of local data }
  816. procedure initialize_data(p : tnamedindexitem;arg:pointer);
  817. var
  818. href : treference;
  819. list : taasmoutput;
  820. begin
  821. list:=taasmoutput(arg);
  822. if (tsym(p).typ=varsym) and
  823. assigned(tvarsym(p).vartype.def) and
  824. not(is_class(tvarsym(p).vartype.def)) and
  825. tvarsym(p).vartype.def.needs_inittable then
  826. begin
  827. if assigned(procinfo) then
  828. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  829. if tsym(p).owner.symtabletype in [localsymtable,inlinelocalsymtable] then
  830. reference_reset_base(href,procinfo.framepointer,-tvarsym(p).address+tvarsym(p).owner.address_fixup)
  831. else
  832. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(p).mangledname),0);
  833. cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
  834. end;
  835. end;
  836. { generates the code for finalisation of local data }
  837. procedure finalize_data(p : tnamedindexitem;arg:pointer);
  838. var
  839. href : treference;
  840. list : taasmoutput;
  841. begin
  842. list:=taasmoutput(arg);
  843. if (tsym(p).typ=varsym) and
  844. assigned(tvarsym(p).vartype.def) and
  845. not(is_class(tvarsym(p).vartype.def)) and
  846. tvarsym(p).vartype.def.needs_inittable then
  847. begin
  848. if tsym(p).owner.symtabletype in [localsymtable,inlinelocalsymtable] then
  849. reference_reset_base(href,procinfo.framepointer,-tvarsym(p).address+tvarsym(p).owner.address_fixup)
  850. else
  851. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(p).mangledname),0);
  852. cg.g_finalize(list,tvarsym(p).vartype.def,href,false);
  853. end;
  854. end;
  855. { generates the code for incrementing the reference count of parameters and
  856. initialize out parameters }
  857. procedure init_paras(p : tnamedindexitem;arg:pointer);
  858. var
  859. href : treference;
  860. tmpreg : tregister;
  861. list : taasmoutput;
  862. begin
  863. list:=taasmoutput(arg);
  864. if (tsym(p).typ=varsym) and
  865. not is_class(tvarsym(p).vartype.def) and
  866. tvarsym(p).vartype.def.needs_inittable then
  867. begin
  868. case tvarsym(p).varspez of
  869. vs_value :
  870. begin
  871. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  872. if assigned(tvarsym(p).localvarsym) then
  873. reference_reset_base(href,procinfo.framepointer,
  874. -tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup)
  875. else
  876. reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  877. cg.g_incrrefcount(list,tvarsym(p).vartype.def,href);
  878. end;
  879. vs_out :
  880. begin
  881. reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  882. tmpreg:=cg.get_scratch_reg_address(list);
  883. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  884. reference_reset_base(href,tmpreg,0);
  885. cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
  886. cg.free_scratch_reg(list,tmpreg);
  887. end;
  888. end;
  889. end;
  890. end;
  891. { generates the code for decrementing the reference count of parameters }
  892. procedure final_paras(p : tnamedindexitem;arg:pointer);
  893. var
  894. href : treference;
  895. list : taasmoutput;
  896. begin
  897. list:=taasmoutput(arg);
  898. if (tsym(p).typ=varsym) and
  899. not is_class(tvarsym(p).vartype.def) and
  900. tvarsym(p).vartype.def.needs_inittable then
  901. begin
  902. if (tvarsym(p).varspez=vs_value) then
  903. begin
  904. if assigned(tvarsym(p).localvarsym) then
  905. reference_reset_base(href,procinfo.framepointer,
  906. -tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup)
  907. else
  908. reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  909. cg.g_decrrefcount(list,tvarsym(p).vartype.def,href);
  910. end;
  911. end;
  912. end;
  913. { Initialize temp ansi/widestrings,interfaces }
  914. procedure inittempvariables(list:taasmoutput);
  915. var
  916. hp : ptemprecord;
  917. href : treference;
  918. begin
  919. hp:=tg.templist;
  920. while assigned(hp) do
  921. begin
  922. if hp^.temptype in [tt_ansistring,tt_freeansistring,
  923. tt_widestring,tt_freewidestring,
  924. tt_interfacecom] then
  925. begin
  926. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  927. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  928. cg.a_load_const_ref(list,OS_ADDR,0,href);
  929. end;
  930. hp:=hp^.next;
  931. end;
  932. end;
  933. procedure finalizetempvariables(list:taasmoutput);
  934. var
  935. hp : ptemprecord;
  936. href : treference;
  937. begin
  938. hp:=tg.templist;
  939. while assigned(hp) do
  940. begin
  941. case hp^.temptype of
  942. tt_ansistring,
  943. tt_freeansistring :
  944. begin
  945. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  946. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(1));
  947. cg.a_call_name(list,'FPC_ANSISTR_DECR_REF');
  948. end;
  949. tt_widestring,
  950. tt_freewidestring :
  951. begin
  952. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  953. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
  954. cg.a_call_name(list,'FPC_WIDESTR_DECR_REF');
  955. end;
  956. tt_interfacecom :
  957. begin
  958. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  959. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
  960. cg.a_call_name(list,'FPC_INTF_DECR_REF');
  961. end;
  962. end;
  963. hp:=hp^.next;
  964. end;
  965. end;
  966. procedure handle_return_value(list:TAAsmoutput; inlined : boolean;var uses_acc,uses_acchi,uses_fpu : boolean);
  967. var
  968. href : treference;
  969. hreg : tregister;
  970. cgsize : TCGSize;
  971. begin
  972. if not is_void(aktprocdef.rettype.def) then
  973. begin
  974. if (tfuncretsym(aktprocdef.funcretsym).funcretstate<>vs_assigned) and
  975. (not inlined) then
  976. CGMessage(sym_w_function_result_not_set);
  977. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  978. cgsize:=def_cgsize(aktprocdef.rettype.def);
  979. case aktprocdef.rettype.def.deftype of
  980. orddef,
  981. enumdef :
  982. begin
  983. uses_acc:=true;
  984. cg.a_reg_alloc(list,accumulator);
  985. if cgsize in [OS_64,OS_S64] then
  986. begin
  987. uses_acchi:=true;
  988. cg.a_reg_alloc(list,accumulatorhigh);
  989. cg64.a_load64_ref_reg(list,href,joinreg64(accumulator,accumulatorhigh));
  990. end
  991. else
  992. begin
  993. hreg:=rg.makeregsize(accumulator,cgsize);
  994. cg.a_load_ref_reg(list,cgsize,href,hreg);
  995. end;
  996. end;
  997. floatdef :
  998. begin
  999. uses_fpu := true;
  1000. cg.a_loadfpu_ref_reg(list,cgsize,href,FPU_RESULT_REG);
  1001. end;
  1002. else
  1003. begin
  1004. if paramanager.ret_in_acc(aktprocdef.rettype.def) then
  1005. begin
  1006. uses_acc:=true;
  1007. cg.a_reg_alloc(list,accumulator);
  1008. cg.a_load_ref_reg(list,cgsize,href,accumulator);
  1009. end
  1010. end;
  1011. end;
  1012. end;
  1013. end;
  1014. procedure handle_fast_exit_return_value(list:TAAsmoutput);
  1015. var
  1016. href : treference;
  1017. hreg : tregister;
  1018. cgsize : TCGSize;
  1019. begin
  1020. if not is_void(aktprocdef.rettype.def) then
  1021. begin
  1022. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1023. cgsize:=def_cgsize(aktprocdef.rettype.def);
  1024. case aktprocdef.rettype.def.deftype of
  1025. orddef,
  1026. enumdef :
  1027. begin
  1028. if cgsize in [OS_64,OS_S64] then
  1029. cg64.a_load64_reg_ref(list,joinreg64(accumulator,accumulatorhigh),href)
  1030. else
  1031. begin
  1032. hreg:=rg.makeregsize(accumulator,cgsize);
  1033. cg.a_load_reg_ref(list,cgsize,hreg,href);
  1034. end;
  1035. end;
  1036. floatdef :
  1037. begin
  1038. cg.a_loadfpu_reg_ref(list,cgsize,FPU_RESULT_REG,href);
  1039. end;
  1040. else
  1041. begin
  1042. if paramanager.ret_in_acc(aktprocdef.rettype.def) then
  1043. cg.a_load_reg_ref(list,cgsize,accumulator,href);
  1044. end;
  1045. end;
  1046. end;
  1047. end;
  1048. procedure genentrycode(list : TAAsmoutput;
  1049. make_global:boolean;
  1050. stackframe:longint;
  1051. var parasize:longint;var nostackframe:boolean;
  1052. inlined : boolean);
  1053. var
  1054. hs : string;
  1055. href : treference;
  1056. p : tsymtable;
  1057. tmpreg : tregister;
  1058. stackalloclist : taasmoutput;
  1059. hp : tparaitem;
  1060. begin
  1061. stackalloclist:=taasmoutput.Create;
  1062. { the actual stack allocation code, symbol entry point and
  1063. gdb stabs information is generated AFTER the rest of this
  1064. code, since temp. allocation might occur before - carl
  1065. }
  1066. if (cs_profile in aktmoduleswitches) and
  1067. not(po_assembler in aktprocdef.procoptions) and not(inlined) then
  1068. cg.g_profilecode(list);
  1069. { for the save all registers we can simply use a pusha,popa which
  1070. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1071. if (po_saveregisters in aktprocdef.procoptions) then
  1072. cg.g_save_all_registers(list)
  1073. else
  1074. { should we save edi,esi,ebx like C ? }
  1075. if (po_savestdregs in aktprocdef.procoptions) then
  1076. cg.g_save_standard_registers(list,aktprocdef.usedregisters);
  1077. { a constructor needs a help procedure }
  1078. if (aktprocdef.proctypeoption=potype_constructor) then
  1079. cg.g_call_constructor_helper(list);
  1080. { don't load ESI, does the caller }
  1081. { we must do it for local function }
  1082. { that can be called from a foreach_static }
  1083. { of another object than self !! PM }
  1084. if assigned(procinfo._class) and { !!!!! shouldn't we load ESI always? }
  1085. (lexlevel>normal_function_level) then
  1086. cg.g_maybe_loadself(list);
  1087. { When message method contains self as a parameter,
  1088. we must load it into ESI }
  1089. If (po_containsself in aktprocdef.procoptions) then
  1090. begin
  1091. list.concat(tai_regalloc.Alloc(self_pointer_reg));
  1092. reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
  1093. cg.a_load_ref_reg(list,OS_ADDR,href,self_pointer_reg);
  1094. end;
  1095. { initialize return value }
  1096. if (not is_void(aktprocdef.rettype.def)) and
  1097. (aktprocdef.rettype.def.needs_inittable) then
  1098. begin
  1099. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  1100. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1101. cg.g_initialize(list,aktprocdef.rettype.def,href,paramanager.ret_in_param(aktprocdef.rettype.def));
  1102. end;
  1103. { initialisize local data like ansistrings }
  1104. case aktprocdef.proctypeoption of
  1105. potype_unitinit:
  1106. begin
  1107. { using current_module.globalsymtable is hopefully }
  1108. { more robust than symtablestack and symtablestack.next }
  1109. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1110. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1111. end;
  1112. { units have seperate code for initilization and finalization }
  1113. potype_unitfinalize: ;
  1114. else
  1115. aktprocdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1116. end;
  1117. { initialisizes temp. ansi/wide string data }
  1118. inittempvariables(list);
  1119. { generate copies of call by value parameters }
  1120. if not(po_assembler in aktprocdef.procoptions) and
  1121. not(aktprocdef.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_palmossyscall,pocall_system]) then
  1122. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
  1123. if assigned(aktprocdef.parast) then
  1124. begin
  1125. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
  1126. { move register parameters which aren't regable into memory }
  1127. { we do this after init_paras because it saves some code in init_paras if parameters are in register }
  1128. { instead in memory }
  1129. hp:=tparaitem(procinfo.procdef.para.first);
  1130. while assigned(hp) do
  1131. begin
  1132. if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER]) and
  1133. (([vo_regable,vo_fpuregable]*tvarsym(hp.parasym).varoptions)=[]) then
  1134. begin
  1135. case hp.paraloc.loc of
  1136. LOC_REGISTER:
  1137. begin
  1138. reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address);
  1139. cg.a_load_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
  1140. end;
  1141. LOC_FPUREGISTER:
  1142. begin
  1143. reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address);
  1144. cg.a_loadfpu_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
  1145. end;
  1146. else
  1147. internalerror(2002081302);
  1148. end;
  1149. end;
  1150. hp:=tparaitem(hp.next);
  1151. end;
  1152. end;
  1153. if (not inlined) then
  1154. begin
  1155. { call startup helpers from main program }
  1156. if (aktprocdef.proctypeoption=potype_proginit) then
  1157. begin
  1158. { initialize profiling for win32 }
  1159. if (target_info.system in [system_i386_win32,system_i386_wdosx]) and
  1160. (cs_profile in aktmoduleswitches) then
  1161. cg.a_call_name(list,'__monstartup');
  1162. { add local threadvars in units (only if needed because not all platforms
  1163. have threadvar support) }
  1164. if have_local_threadvars then
  1165. cg.a_call_name(list,'FPC_INITIALIZELOCALTHREADVARS');
  1166. { add global threadvars }
  1167. p:=symtablestack;
  1168. while assigned(p) do
  1169. begin
  1170. p.foreach_static({$ifndef TP}@{$endif}initialize_threadvar,list);
  1171. p:=p.next;
  1172. end;
  1173. { initialize units }
  1174. cg.a_call_name(list,'FPC_INITIALIZEUNITS');
  1175. end;
  1176. { do we need an exception frame because of ansi/widestrings/interfaces ? }
  1177. if ((procinfo.flags and pi_needs_implicit_finally)<>0) and
  1178. { but it's useless in init/final code of units }
  1179. not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  1180. begin
  1181. include(rg.usedinproc,accumulator);
  1182. tg.gettempofsizereferencepersistant(list,JMP_BUF_SIZE,procinfo.exception_jmp_ref);
  1183. tg.gettempofsizereferencepersistant(list,12,procinfo.exception_env_ref);
  1184. tg.gettempofsizereferencepersistant(list,sizeof(aword),procinfo.exception_result_ref);
  1185. new_exception(list,procinfo.exception_jmp_ref,
  1186. procinfo.exception_env_ref,
  1187. procinfo.exception_result_ref,1,aktexitlabel);
  1188. { probably we've to reload self here }
  1189. cg.g_maybe_loadself(list);
  1190. end;
  1191. {$ifdef GDB}
  1192. if (cs_debuginfo in aktmoduleswitches) then
  1193. list.concat(Tai_force_line.Create);
  1194. {$endif GDB}
  1195. end;
  1196. if inlined then
  1197. load_regvars(list,nil);
  1198. {************************* Stack allocation **************************}
  1199. { and symbol entry point as well as debug information }
  1200. { will be inserted in front of the rest of this list. }
  1201. { Insert alignment and assembler names }
  1202. if not inlined then
  1203. begin
  1204. { Align, gprof uses 16 byte granularity }
  1205. if (cs_profile in aktmoduleswitches) then
  1206. stackalloclist.concat(Tai_align.Create_op(16,$90))
  1207. else
  1208. stackalloclist.concat(Tai_align.Create(aktalignment.procalign));
  1209. if (cs_profile in aktmoduleswitches) or
  1210. (aktprocdef.owner.symtabletype=globalsymtable) or
  1211. (assigned(procinfo._class) and (procinfo._class.owner.symtabletype=globalsymtable)) then
  1212. make_global:=true;
  1213. if make_global or ((procinfo.flags and pi_is_global) <> 0) then
  1214. aktprocsym.is_global := True;
  1215. {$ifdef GDB}
  1216. if (cs_debuginfo in aktmoduleswitches) then
  1217. begin
  1218. aktprocdef.concatstabto(stackalloclist);
  1219. aktprocsym.isstabwritten:=true;
  1220. end;
  1221. {$endif GDB}
  1222. repeat
  1223. hs:=aktprocdef.aliasnames.getfirst;
  1224. if hs='' then
  1225. break;
  1226. {$ifdef GDB}
  1227. if (cs_debuginfo in aktmoduleswitches) and
  1228. target_info.use_function_relative_addresses then
  1229. stackalloclist.concat(Tai_stab_function_name.Create(strpnew(hs)));
  1230. {$endif GDB}
  1231. if make_global then
  1232. stackalloclist.concat(Tai_symbol.Createname_global(hs,0))
  1233. else
  1234. stackalloclist.concat(Tai_symbol.Createname(hs,0));
  1235. until false;
  1236. stackframe:=stackframe+tg.gettempsize;
  1237. {$ifndef powerpc}
  1238. { at least for the ppc this applies always, so this code isn't usable (FK) }
  1239. { omit stack frame ? }
  1240. if (procinfo.framepointer=STACK_POINTER_REG) then
  1241. begin
  1242. CGMessage(cg_d_stackframe_omited);
  1243. nostackframe:=true;
  1244. if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  1245. parasize:=0
  1246. else
  1247. parasize:=aktprocdef.parast.datasize+procinfo.para_offset-4;
  1248. if stackframe<>0 then
  1249. cg.a_op_const_reg(stackalloclist,OP_SUB,stackframe,procinfo.framepointer);
  1250. end
  1251. else
  1252. {$endif powerpc}
  1253. begin
  1254. nostackframe:=false;
  1255. if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  1256. parasize:=0
  1257. else
  1258. parasize:=aktprocdef.parast.datasize+procinfo.para_offset-target_info.first_parm_offset;
  1259. if (po_interrupt in aktprocdef.procoptions) then
  1260. cg.g_interrupt_stackframe_entry(stackalloclist);
  1261. cg.g_stackframe_entry(stackalloclist,stackframe);
  1262. if (cs_check_stack in aktlocalswitches) then
  1263. cg.g_stackcheck(stackalloclist,stackframe);
  1264. end;
  1265. list.insertlist(stackalloclist);
  1266. { stackalloclist.free;}
  1267. end;
  1268. {************************* End Stack allocation **************************}
  1269. end;
  1270. procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe,inlined:boolean);
  1271. var
  1272. {$ifdef GDB}
  1273. stabsendlabel : tasmlabel;
  1274. mangled_length : longint;
  1275. p : pchar;
  1276. st : string[2];
  1277. {$endif GDB}
  1278. okexitlabel,
  1279. noreraiselabel,nodestroycall : tasmlabel;
  1280. tmpreg : tregister;
  1281. href : treference;
  1282. usesacc,
  1283. usesacchi,
  1284. usesself,usesfpu : boolean;
  1285. pd : tprocdef;
  1286. begin
  1287. if aktexit2label.is_used and
  1288. ((procinfo.flags and (pi_needs_implicit_finally or pi_uses_exceptions)) <> 0) then
  1289. begin
  1290. cg.a_jmp_always(list,aktexitlabel);
  1291. cg.a_label(list,aktexit2label);
  1292. handle_fast_exit_return_value(list);
  1293. end;
  1294. if aktexitlabel.is_used then
  1295. list.concat(Tai_label.Create(aktexitlabel));
  1296. cleanup_regvars(list);
  1297. { call the destructor help procedure }
  1298. if (aktprocdef.proctypeoption=potype_destructor) and
  1299. assigned(procinfo._class) then
  1300. cg.g_call_destructor_helper(list);
  1301. { finalize temporary data }
  1302. finalizetempvariables(list);
  1303. { finalize local data like ansistrings}
  1304. case aktprocdef.proctypeoption of
  1305. potype_unitfinalize:
  1306. begin
  1307. { using current_module.globalsymtable is hopefully }
  1308. { more robust than symtablestack and symtablestack.next }
  1309. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1310. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1311. end;
  1312. { units have seperate code for initialization and finalization }
  1313. potype_unitinit: ;
  1314. else
  1315. aktprocdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1316. end;
  1317. { finalize paras data }
  1318. if assigned(aktprocdef.parast) then
  1319. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
  1320. { do we need to handle exceptions because of ansi/widestrings ? }
  1321. if not inlined and
  1322. ((procinfo.flags and pi_needs_implicit_finally)<>0) and
  1323. { but it's useless in init/final code of units }
  1324. not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  1325. begin
  1326. { the exception helper routines modify all registers }
  1327. aktprocdef.usedregisters:=all_registers;
  1328. objectlibrary.getlabel(noreraiselabel);
  1329. free_exception(list,
  1330. procinfo.exception_jmp_ref,
  1331. procinfo.exception_env_ref,
  1332. procinfo.exception_result_ref,0
  1333. ,noreraiselabel,false);
  1334. if (aktprocdef.proctypeoption=potype_constructor) then
  1335. begin
  1336. if assigned(procinfo._class) then
  1337. begin
  1338. pd:=procinfo._class.searchdestructor;
  1339. if assigned(pd) then
  1340. begin
  1341. objectlibrary.getlabel(nodestroycall);
  1342. reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
  1343. cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,nodestroycall);
  1344. if is_class(procinfo._class) then
  1345. begin
  1346. cg.a_param_const(list,OS_INT,1,paramanager.getintparaloc(2));
  1347. cg.a_param_reg(list,OS_ADDR,self_pointer_reg,paramanager.getintparaloc(1));
  1348. end
  1349. else if is_object(procinfo._class) then
  1350. begin
  1351. cg.a_param_reg(list,OS_ADDR,self_pointer_reg,paramanager.getintparaloc(2));
  1352. reference_reset_symbol(href,objectlibrary.newasmsymbol(procinfo._class.vmt_mangledname),0);
  1353. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(1));
  1354. end
  1355. else
  1356. Internalerror(200006164);
  1357. if (po_virtualmethod in pd.procoptions) then
  1358. begin
  1359. reference_reset_base(href,self_pointer_reg,0);
  1360. tmpreg:=cg.get_scratch_reg_address(list);
  1361. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  1362. reference_reset_base(href,tmpreg,procinfo._class.vmtmethodoffset(pd.extnumber));
  1363. cg.free_scratch_reg(list,tmpreg);
  1364. cg.a_call_ref(list,href);
  1365. end
  1366. else
  1367. cg.a_call_name(list,pd.mangledname);
  1368. { not necessary because the result is never assigned in the
  1369. case of an exception (FK) }
  1370. cg.a_label(list,nodestroycall);
  1371. end;
  1372. end
  1373. end
  1374. else
  1375. begin
  1376. { no constructor }
  1377. { must be the return value finalized before reraising the exception? }
  1378. if (not is_void(aktprocdef.rettype.def)) and
  1379. (aktprocdef.rettype.def.needs_inittable) and
  1380. ((aktprocdef.rettype.def.deftype<>objectdef) or
  1381. not is_class(aktprocdef.rettype.def)) then
  1382. begin
  1383. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1384. cg.g_finalize(list,aktprocdef.rettype.def,href,paramanager.ret_in_param(aktprocdef.rettype.def));
  1385. end;
  1386. end;
  1387. cg.a_call_name(list,'FPC_RERAISE');
  1388. cg.a_label(list,noreraiselabel);
  1389. end;
  1390. { call __EXIT for main program }
  1391. if (not DLLsource) and
  1392. (not inlined) and
  1393. (aktprocdef.proctypeoption=potype_proginit) then
  1394. cg.a_call_name(list,'FPC_DO_EXIT');
  1395. { handle return value, this is not done for assembler routines when
  1396. they didn't reference the result variable }
  1397. usesacc:=false;
  1398. usesacchi:=false;
  1399. usesself:=false;
  1400. if not(po_assembler in aktprocdef.procoptions) or
  1401. (assigned(aktprocdef.funcretsym) and
  1402. (tfuncretsym(aktprocdef.funcretsym).refcount>1)) then
  1403. begin
  1404. if (aktprocdef.proctypeoption<>potype_constructor) then
  1405. handle_return_value(list,inlined,usesacc,usesacchi,usesfpu)
  1406. else
  1407. begin
  1408. { successful constructor deletes the zero flag }
  1409. { and returns self in eax }
  1410. { eax must be set to zero if the allocation failed !!! }
  1411. objectlibrary.getlabel(okexitlabel);
  1412. cg.a_jmp_always(list,okexitlabel);
  1413. cg.a_label(list,faillabel);
  1414. cg.g_call_fail_helper(list);
  1415. cg.a_label(list,okexitlabel);
  1416. { for classes this is done after the call to }
  1417. { AfterConstruction }
  1418. if is_object(procinfo._class) then
  1419. begin
  1420. cg.a_reg_alloc(list,accumulator);
  1421. cg.a_load_reg_reg(list,OS_ADDR,self_pointer_reg,accumulator);
  1422. usesacc:=true;
  1423. end;
  1424. {$ifdef i386}
  1425. list.concat(taicpu.op_reg_reg(A_TEST,S_L,R_ESI,R_ESI));
  1426. {$else}
  1427. {$warning constructor returns in flags for i386}
  1428. {$endif i386}
  1429. usesself:=true;
  1430. end;
  1431. end;
  1432. if aktexit2label.is_used and not aktexit2label.is_set then
  1433. cg.a_label(list,aktexit2label);
  1434. {$ifdef GDB}
  1435. if ((cs_debuginfo in aktmoduleswitches) and not inlined) then
  1436. begin
  1437. objectlibrary.getlabel(stabsendlabel);
  1438. cg.a_label(list,stabsendlabel);
  1439. end;
  1440. {$endif GDB}
  1441. { for the save all registers we can simply use a pusha,popa which
  1442. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1443. if (po_saveregisters in aktprocdef.procoptions) then
  1444. cg.g_restore_all_registers(list,usesself,usesacc,usesacchi)
  1445. else
  1446. { should we restore edi ? }
  1447. if (po_savestdregs in aktprocdef.procoptions) then
  1448. cg.g_restore_standard_registers(list,aktprocdef.usedregisters);
  1449. { remove stackframe }
  1450. if not inlined then
  1451. begin
  1452. if (not nostackframe) then
  1453. cg.g_restore_frame_pointer(list)
  1454. else
  1455. if (tg.gettempsize<>0) then
  1456. cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,STACK_POINTER_REG);
  1457. end;
  1458. { at last, the return is generated }
  1459. if not inlined then
  1460. begin
  1461. if (po_interrupt in aktprocdef.procoptions) then
  1462. cg.g_interrupt_stackframe_exit(list,usesself,usesacc,usesacchi)
  1463. else
  1464. cg.g_return_from_proc(list,parasize);
  1465. end;
  1466. if not inlined then
  1467. list.concat(Tai_symbol_end.Createname(aktprocdef.mangledname));
  1468. {$ifdef GDB}
  1469. if (cs_debuginfo in aktmoduleswitches) and not inlined then
  1470. begin
  1471. if assigned(procinfo._class) then
  1472. if (not assigned(procinfo.parent) or
  1473. not assigned(procinfo.parent._class)) then
  1474. begin
  1475. if (po_classmethod in aktprocdef.procoptions) or
  1476. ((po_virtualmethod in aktprocdef.procoptions) and
  1477. (potype_constructor=aktprocdef.proctypeoption)) or
  1478. (po_staticmethod in aktprocdef.procoptions) then
  1479. begin
  1480. list.concat(Tai_stabs.Create(strpnew(
  1481. '"pvmt:p'+tstoreddef(pvmttype.def).numberstring+'",'+
  1482. tostr(N_tsym)+',0,0,'+tostr(procinfo.selfpointer_offset))));
  1483. end
  1484. else
  1485. begin
  1486. if not(is_class(procinfo._class)) then
  1487. st:='v'
  1488. else
  1489. st:='p';
  1490. list.concat(Tai_stabs.Create(strpnew(
  1491. '"$t:'+st+procinfo._class.numberstring+'",'+
  1492. tostr(N_tsym)+',0,0,'+tostr(procinfo.selfpointer_offset))));
  1493. end;
  1494. end
  1495. else
  1496. begin
  1497. if not is_class(procinfo._class) then
  1498. st:='*'
  1499. else
  1500. st:='';
  1501. list.concat(Tai_stabs.Create(strpnew(
  1502. '"$t:r'+st+procinfo._class.numberstring+'",'+
  1503. tostr(N_RSYM)+',0,0,'+tostr(stab_regindex[SELF_POINTER_REG]))));
  1504. end;
  1505. { define calling EBP as pseudo local var PM }
  1506. { this enables test if the function is a local one !! }
  1507. if assigned(procinfo.parent) and (lexlevel>normal_function_level) then
  1508. list.concat(Tai_stabs.Create(strpnew(
  1509. '"parent_ebp:'+tstoreddef(voidpointertype.def).numberstring+'",'+
  1510. tostr(N_LSYM)+',0,0,'+tostr(procinfo.framepointer_offset))));
  1511. if (not is_void(aktprocdef.rettype.def)) then
  1512. begin
  1513. if paramanager.ret_in_param(aktprocdef.rettype.def) then
  1514. list.concat(Tai_stabs.Create(strpnew(
  1515. '"'+aktprocsym.name+':X*'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1516. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))))
  1517. else
  1518. list.concat(Tai_stabs.Create(strpnew(
  1519. '"'+aktprocsym.name+':X'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1520. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))));
  1521. if (m_result in aktmodeswitches) then
  1522. if paramanager.ret_in_param(aktprocdef.rettype.def) then
  1523. list.concat(Tai_stabs.Create(strpnew(
  1524. '"RESULT:X*'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1525. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))))
  1526. else
  1527. list.concat(Tai_stabs.Create(strpnew(
  1528. '"RESULT:X'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1529. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))));
  1530. end;
  1531. mangled_length:=length(aktprocdef.mangledname);
  1532. getmem(p,2*mangled_length+50);
  1533. strpcopy(p,'192,0,0,');
  1534. strpcopy(strend(p),aktprocdef.mangledname);
  1535. if (target_info.use_function_relative_addresses) then
  1536. begin
  1537. strpcopy(strend(p),'-');
  1538. strpcopy(strend(p),aktprocdef.mangledname);
  1539. end;
  1540. list.concat(Tai_stabn.Create(strnew(p)));
  1541. {List.concat(Tai_stabn.Create(strpnew('192,0,0,'
  1542. +aktprocdef.mangledname))));
  1543. p[0]:='2';p[1]:='2';p[2]:='4';
  1544. strpcopy(strend(p),'_end');}
  1545. strpcopy(p,'224,0,0,'+stabsendlabel.name);
  1546. if (target_info.use_function_relative_addresses) then
  1547. begin
  1548. strpcopy(strend(p),'-');
  1549. strpcopy(strend(p),aktprocdef.mangledname);
  1550. end;
  1551. list.concatlist(withdebuglist);
  1552. list.concat(Tai_stabn.Create(strnew(p)));
  1553. { strpnew('224,0,0,'
  1554. +aktprocdef.mangledname+'_end'))));}
  1555. freemem(p,2*mangled_length+50);
  1556. end;
  1557. {$endif GDB}
  1558. if inlined then
  1559. cleanup_regvars(list);
  1560. end;
  1561. procedure genimplicitunitinit(list : TAAsmoutput);
  1562. begin
  1563. { using current_module.globalsymtable is hopefully }
  1564. { more robust than symtablestack and symtablestack.next }
  1565. tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1566. tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1567. list.insert(Tai_symbol.Createname_global('INIT$$'+current_module.modulename^,0));
  1568. list.insert(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_init',0));
  1569. {$ifdef GDB}
  1570. if (cs_debuginfo in aktmoduleswitches) and
  1571. target_info.use_function_relative_addresses then
  1572. list.insert(Tai_stab_function_name.Create(strpnew('INIT$$'+current_module.modulename^)));
  1573. {$endif GDB}
  1574. cg.g_return_from_proc(list,0);
  1575. end;
  1576. procedure genimplicitunitfinal(list : TAAsmoutput);
  1577. begin
  1578. { using current_module.globalsymtable is hopefully }
  1579. { more robust than symtablestack and symtablestack.next }
  1580. tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1581. tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1582. list.insert(Tai_symbol.Createname_global('FINALIZE$$'+current_module.modulename^,0));
  1583. list.insert(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_finalize',0));
  1584. {$ifdef GDB}
  1585. if (cs_debuginfo in aktmoduleswitches) and
  1586. target_info.use_function_relative_addresses then
  1587. list.insert(Tai_stab_function_name.Create(strpnew('FINALIZE$$'+current_module.modulename^)));
  1588. {$endif GDB}
  1589. cg.g_return_from_proc(list,0);
  1590. end;
  1591. end.
  1592. {
  1593. $Log$
  1594. Revision 1.40 2002-08-18 10:42:37 florian
  1595. * remaining assembler writer bugs fixed, the errors in the
  1596. system unit are inline assembler problems
  1597. Revision 1.39 2002/08/17 09:23:36 florian
  1598. * first part of procinfo rewrite
  1599. Revision 1.38 2002/08/16 14:24:57 carl
  1600. * issameref() to test if two references are the same (then emit no opcodes)
  1601. + ret_in_reg to replace ret_in_acc
  1602. (fix some register allocation bugs at the same time)
  1603. + save_std_register now has an extra parameter which is the
  1604. usedinproc registers
  1605. Revision 1.37 2002/08/15 15:15:55 carl
  1606. * jmpbuf size allocation for exceptions is now cpu specific (as it should)
  1607. * more generic nodes for maths
  1608. * several fixes for better m68k support
  1609. Revision 1.36 2002/08/14 19:25:09 carl
  1610. * fix Florian's last commit for m68k compilation
  1611. Revision 1.35 2002/08/13 21:40:56 florian
  1612. * more fixes for ppc calling conventions
  1613. Revision 1.34 2002/08/12 15:08:39 carl
  1614. + stab register indexes for powerpc (moved from gdb to cpubase)
  1615. + tprocessor enumeration moved to cpuinfo
  1616. + linker in target_info is now a class
  1617. * many many updates for m68k (will soon start to compile)
  1618. - removed some ifdef or correct them for correct cpu
  1619. Revision 1.33 2002/08/11 14:32:27 peter
  1620. * renamed current_library to objectlibrary
  1621. Revision 1.32 2002/08/11 13:24:12 peter
  1622. * saving of asmsymbols in ppu supported
  1623. * asmsymbollist global is removed and moved into a new class
  1624. tasmlibrarydata that will hold the info of a .a file which
  1625. corresponds with a single module. Added librarydata to tmodule
  1626. to keep the library info stored for the module. In the future the
  1627. objectfiles will also be stored to the tasmlibrarydata class
  1628. * all getlabel/newasmsymbol and friends are moved to the new class
  1629. Revision 1.31 2002/08/09 19:16:57 carl
  1630. * stack allocation is now done separately (at the end) of genentrycode
  1631. so temps. can be allocated before.
  1632. * fix generic exception handling
  1633. Revision 1.30 2002/08/06 20:55:21 florian
  1634. * first part of ppc calling conventions fix
  1635. Revision 1.29 2002/08/04 19:09:22 carl
  1636. + added generic exception support (still does not work!)
  1637. + more documentation
  1638. Revision 1.28 2002/07/29 21:23:42 florian
  1639. * more fixes for the ppc
  1640. + wrappers for the tcnvnode.first_* stuff introduced
  1641. Revision 1.27 2002/07/28 15:59:57 jonas
  1642. * fixed bug in location_force_reg32() when converting smaller values to
  1643. 64 bit locations
  1644. * use cg.op_const_reg_reg() instead of a move and then cg.op_const_reg()
  1645. in location_force_reg32()
  1646. Revision 1.26 2002/07/27 19:53:51 jonas
  1647. + generic implementation of tcg.g_flags2ref()
  1648. * tcg.flags2xxx() now also needs a size parameter
  1649. Revision 1.25 2002/07/26 21:15:38 florian
  1650. * rewrote the system handling
  1651. Revision 1.24 2002/07/25 17:58:24 carl
  1652. + FPURESULTREG -> FPU_RESULT_REG
  1653. Revision 1.23 2002/07/20 11:57:54 florian
  1654. * types.pas renamed to defbase.pas because D6 contains a types
  1655. unit so this would conflicts if D6 programms are compiled
  1656. + Willamette/SSE2 instructions to assembler added
  1657. Revision 1.22 2002/07/11 14:41:28 florian
  1658. * start of the new generic parameter handling
  1659. Revision 1.21 2002/07/11 07:33:25 jonas
  1660. * big-endian fixes for location_force_reg*()
  1661. Revision 1.20 2002/07/07 09:52:32 florian
  1662. * powerpc target fixed, very simple units can be compiled
  1663. * some basic stuff for better callparanode handling, far from being finished
  1664. Revision 1.19 2002/07/01 18:46:23 peter
  1665. * internal linker
  1666. * reorganized aasm layer
  1667. Revision 1.18 2002/07/01 16:23:53 peter
  1668. * cg64 patch
  1669. * basics for currency
  1670. * asnode updates for class and interface (not finished)
  1671. Revision 1.17 2002/05/20 13:30:40 carl
  1672. * bugfix of hdisponen (base must be set, not index)
  1673. * more portability fixes
  1674. Revision 1.16 2002/05/18 13:34:09 peter
  1675. * readded missing revisions
  1676. Revision 1.15 2002/05/16 19:46:37 carl
  1677. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1678. + try to fix temp allocation (still in ifdef)
  1679. + generic constructor calls
  1680. + start of tassembler / tmodulebase class cleanup
  1681. Revision 1.13 2002/05/13 19:54:37 peter
  1682. * removed n386ld and n386util units
  1683. * maybe_save/maybe_restore added instead of the old maybe_push
  1684. Revision 1.12 2002/05/12 19:58:36 carl
  1685. * some small portability fixes
  1686. Revision 1.11 2002/05/12 16:53:07 peter
  1687. * moved entry and exitcode to ncgutil and cgobj
  1688. * foreach gets extra argument for passing local data to the
  1689. iterator function
  1690. * -CR checks also class typecasts at runtime by changing them
  1691. into as
  1692. * fixed compiler to cycle with the -CR option
  1693. * fixed stabs with elf writer, finally the global variables can
  1694. be watched
  1695. * removed a lot of routines from cga unit and replaced them by
  1696. calls to cgobj
  1697. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1698. u32bit then the other is typecasted also to u32bit without giving
  1699. a rangecheck warning/error.
  1700. * fixed pascal calling method with reversing also the high tree in
  1701. the parast, detected by tcalcst3 test
  1702. Revision 1.10 2002/04/21 19:02:03 peter
  1703. * removed newn and disposen nodes, the code is now directly
  1704. inlined from pexpr
  1705. * -an option that will write the secondpass nodes to the .s file, this
  1706. requires EXTDEBUG define to actually write the info
  1707. * fixed various internal errors and crashes due recent code changes
  1708. Revision 1.9 2002/04/21 15:24:38 carl
  1709. + a_jmp_cond -> a_jmp_always (a_jmp_cond is NOT portable)
  1710. + changeregsize -> rg.makeregsize
  1711. Revision 1.8 2002/04/19 15:39:34 peter
  1712. * removed some more routines from cga
  1713. * moved location_force_reg/mem to ncgutil
  1714. * moved arrayconstructnode secondpass to ncgld
  1715. Revision 1.7 2002/04/15 18:58:47 carl
  1716. + target_info.size_of_pointer -> pointer_Size
  1717. Revision 1.6 2002/04/06 18:10:42 jonas
  1718. * several powerpc-related additions and fixes
  1719. Revision 1.5 2002/04/04 19:05:57 peter
  1720. * removed unused units
  1721. * use tlocation.size in cg.a_*loc*() routines
  1722. Revision 1.4 2002/04/02 17:11:28 peter
  1723. * tlocation,treference update
  1724. * LOC_CONSTANT added for better constant handling
  1725. * secondadd splitted in multiple routines
  1726. * location_force_reg added for loading a location to a register
  1727. of a specified size
  1728. * secondassignment parses now first the right and then the left node
  1729. (this is compatible with Kylix). This saves a lot of push/pop especially
  1730. with string operations
  1731. * adapted some routines to use the new cg methods
  1732. Revision 1.3 2002/03/31 20:26:34 jonas
  1733. + a_loadfpu_* and a_loadmm_* methods in tcg
  1734. * register allocation is now handled by a class and is mostly processor
  1735. independent (+rgobj.pas and i386/rgcpu.pas)
  1736. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1737. * some small improvements and fixes to the optimizer
  1738. * some register allocation fixes
  1739. * some fpuvaroffset fixes in the unary minus node
  1740. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1741. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1742. also better optimizable)
  1743. * fixed and optimized register saving/restoring for new/dispose nodes
  1744. * LOC_FPU locations now also require their "register" field to be set to
  1745. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1746. - list field removed of the tnode class because it's not used currently
  1747. and can cause hard-to-find bugs
  1748. Revision 1.2 2002/03/04 19:10:11 peter
  1749. * removed compiler warnings
  1750. }