ncgutil.pas 77 KB

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