ncgutil.pas 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894
  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. begin
  1109. stackalloclist:=taasmoutput.Create;
  1110. { the actual stack allocation code, symbol entry point and
  1111. gdb stabs information is generated AFTER the rest of this
  1112. code, since temp. allocation might occur before - carl
  1113. }
  1114. if (cs_profile in aktmoduleswitches) and
  1115. not(po_assembler in aktprocdef.procoptions) and not(inlined) then
  1116. cg.g_profilecode(list);
  1117. { for the save all registers we can simply use a pusha,popa which
  1118. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1119. if (po_saveregisters in aktprocdef.procoptions) then
  1120. cg.g_save_all_registers(list)
  1121. else
  1122. { should we save edi,esi,ebx like C ? }
  1123. if (po_savestdregs in aktprocdef.procoptions) then
  1124. cg.g_save_standard_registers(list,aktprocdef.usedregisters);
  1125. { a constructor needs a help procedure }
  1126. if (aktprocdef.proctypeoption=potype_constructor) then
  1127. cg.g_call_constructor_helper(list);
  1128. { don't load ESI, does the caller }
  1129. { we must do it for local function }
  1130. { that can be called from a foreach_static }
  1131. { of another object than self !! PM }
  1132. if assigned(procinfo._class) and { !!!!! shouldn't we load ESI always? }
  1133. (lexlevel>normal_function_level) then
  1134. cg.g_maybe_loadself(list);
  1135. { When message method contains self as a parameter,
  1136. we must load it into ESI }
  1137. If (po_containsself in aktprocdef.procoptions) then
  1138. begin
  1139. list.concat(tai_regalloc.Alloc(self_pointer_reg));
  1140. reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
  1141. cg.a_load_ref_reg(list,OS_ADDR,href,self_pointer_reg);
  1142. end;
  1143. { initialize return value }
  1144. if (not is_void(aktprocdef.rettype.def)) and
  1145. (aktprocdef.rettype.def.needs_inittable) then
  1146. begin
  1147. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  1148. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1149. cg.g_initialize(list,aktprocdef.rettype.def,href,paramanager.ret_in_param(aktprocdef.rettype.def));
  1150. end;
  1151. { initialisize local data like ansistrings }
  1152. case aktprocdef.proctypeoption of
  1153. potype_unitinit:
  1154. begin
  1155. { using current_module.globalsymtable is hopefully }
  1156. { more robust than symtablestack and symtablestack.next }
  1157. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1158. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1159. end;
  1160. { units have seperate code for initilization and finalization }
  1161. potype_unitfinalize: ;
  1162. else
  1163. aktprocdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1164. end;
  1165. { initialisizes temp. ansi/wide string data }
  1166. inittempvariables(list);
  1167. { generate copies of call by value parameters }
  1168. if not(po_assembler in aktprocdef.procoptions) and
  1169. not(aktprocdef.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_palmossyscall,pocall_system]) then
  1170. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
  1171. if assigned(aktprocdef.parast) then
  1172. begin
  1173. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
  1174. { move register parameters which aren't regable into memory }
  1175. { we do this after init_paras because it saves some code in init_paras if parameters are in register }
  1176. { instead in memory }
  1177. hp:=tparaitem(procinfo.procdef.para.first);
  1178. while assigned(hp) do
  1179. begin
  1180. if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER]) and
  1181. (([vo_regable,vo_fpuregable]*tvarsym(hp.parasym).varoptions)=[]) then
  1182. begin
  1183. case hp.paraloc.loc of
  1184. LOC_REGISTER:
  1185. begin
  1186. reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address);
  1187. cg.a_load_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
  1188. end;
  1189. LOC_FPUREGISTER:
  1190. begin
  1191. reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address);
  1192. cg.a_loadfpu_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
  1193. end;
  1194. else
  1195. internalerror(2002081302);
  1196. end;
  1197. end;
  1198. hp:=tparaitem(hp.next);
  1199. end;
  1200. end;
  1201. if (not inlined) then
  1202. begin
  1203. { call startup helpers from main program }
  1204. if (aktprocdef.proctypeoption=potype_proginit) then
  1205. begin
  1206. { initialize profiling for win32 }
  1207. if (target_info.system in [system_i386_win32,system_i386_wdosx]) and
  1208. (cs_profile in aktmoduleswitches) then
  1209. cg.a_call_name(list,'__monstartup');
  1210. { add local threadvars in units (only if needed because not all platforms
  1211. have threadvar support) }
  1212. if have_local_threadvars then
  1213. cg.a_call_name(list,'FPC_INITIALIZELOCALTHREADVARS');
  1214. { add global threadvars }
  1215. p:=symtablestack;
  1216. while assigned(p) do
  1217. begin
  1218. p.foreach_static({$ifndef TP}@{$endif}initialize_threadvar,list);
  1219. p:=p.next;
  1220. end;
  1221. { initialize units }
  1222. cg.a_call_name(list,'FPC_INITIALIZEUNITS');
  1223. end;
  1224. { do we need an exception frame because of ansi/widestrings/interfaces ? }
  1225. if ((procinfo.flags and pi_needs_implicit_finally)<>0) and
  1226. { but it's useless in init/final code of units }
  1227. not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  1228. begin
  1229. include(rg.usedinproc,accumulator);
  1230. tg.GetTemp(list,JMP_BUF_SIZE,tt_noreuse,procinfo.exception_jmp_ref);
  1231. tg.GetTemp(list,12,tt_noreuse,procinfo.exception_env_ref);
  1232. tg.GetTemp(list,sizeof(aword),tt_noreuse,procinfo.exception_result_ref);
  1233. new_exception(list,procinfo.exception_jmp_ref,
  1234. procinfo.exception_env_ref,
  1235. procinfo.exception_result_ref,1,aktexitlabel);
  1236. { probably we've to reload self here }
  1237. cg.g_maybe_loadself(list);
  1238. end;
  1239. {$ifdef GDB}
  1240. if (cs_debuginfo in aktmoduleswitches) then
  1241. list.concat(Tai_force_line.Create);
  1242. {$endif GDB}
  1243. end;
  1244. if inlined then
  1245. load_regvars(list,nil);
  1246. {************************* Stack allocation **************************}
  1247. { and symbol entry point as well as debug information }
  1248. { will be inserted in front of the rest of this list. }
  1249. { Insert alignment and assembler names }
  1250. if not inlined then
  1251. begin
  1252. { Align, gprof uses 16 byte granularity }
  1253. if (cs_profile in aktmoduleswitches) then
  1254. stackalloclist.concat(Tai_align.Create_op(16,$90))
  1255. else
  1256. stackalloclist.concat(Tai_align.Create(aktalignment.procalign));
  1257. if (cs_profile in aktmoduleswitches) or
  1258. (aktprocdef.owner.symtabletype=globalsymtable) or
  1259. (assigned(procinfo._class) and (procinfo._class.owner.symtabletype=globalsymtable)) then
  1260. make_global:=true;
  1261. if make_global or ((procinfo.flags and pi_is_global) <> 0) then
  1262. aktprocsym.is_global := True;
  1263. {$ifdef GDB}
  1264. if (cs_debuginfo in aktmoduleswitches) then
  1265. begin
  1266. aktprocdef.concatstabto(stackalloclist);
  1267. aktprocsym.isstabwritten:=true;
  1268. end;
  1269. {$endif GDB}
  1270. repeat
  1271. hs:=aktprocdef.aliasnames.getfirst;
  1272. if hs='' then
  1273. break;
  1274. {$ifdef GDB}
  1275. if (cs_debuginfo in aktmoduleswitches) and
  1276. target_info.use_function_relative_addresses then
  1277. stackalloclist.concat(Tai_stab_function_name.Create(strpnew(hs)));
  1278. {$endif GDB}
  1279. if make_global then
  1280. stackalloclist.concat(Tai_symbol.Createname_global(hs,0))
  1281. else
  1282. stackalloclist.concat(Tai_symbol.Createname(hs,0));
  1283. until false;
  1284. stackframe:=stackframe+tg.gettempsize;
  1285. {$ifndef powerpc}
  1286. { at least for the ppc this applies always, so this code isn't usable (FK) }
  1287. { omit stack frame ? }
  1288. if (procinfo.framepointer=STACK_POINTER_REG) then
  1289. begin
  1290. CGMessage(cg_d_stackframe_omited);
  1291. nostackframe:=true;
  1292. if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  1293. parasize:=0
  1294. else
  1295. parasize:=aktprocdef.parast.datasize+procinfo.para_offset-4;
  1296. if stackframe<>0 then
  1297. cg.a_op_const_reg(stackalloclist,OP_SUB,stackframe,procinfo.framepointer);
  1298. end
  1299. else
  1300. {$endif powerpc}
  1301. begin
  1302. nostackframe:=false;
  1303. if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  1304. parasize:=0
  1305. else
  1306. parasize:=aktprocdef.parast.datasize+procinfo.para_offset-target_info.first_parm_offset;
  1307. if (po_interrupt in aktprocdef.procoptions) then
  1308. cg.g_interrupt_stackframe_entry(stackalloclist);
  1309. cg.g_stackframe_entry(stackalloclist,stackframe);
  1310. if (cs_check_stack in aktlocalswitches) then
  1311. cg.g_stackcheck(stackalloclist,stackframe);
  1312. end;
  1313. list.insertlist(stackalloclist);
  1314. { stackalloclist.free;}
  1315. end;
  1316. {************************* End Stack allocation **************************}
  1317. end;
  1318. procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe,inlined:boolean);
  1319. var
  1320. {$ifdef GDB}
  1321. stabsendlabel : tasmlabel;
  1322. mangled_length : longint;
  1323. p : pchar;
  1324. st : string[2];
  1325. {$endif GDB}
  1326. okexitlabel,
  1327. noreraiselabel,nodestroycall : tasmlabel;
  1328. tmpreg : tregister;
  1329. href : treference;
  1330. usesacc,
  1331. usesacchi,
  1332. usesself,usesfpu : boolean;
  1333. pd : tprocdef;
  1334. begin
  1335. if aktexit2label.is_used and
  1336. ((procinfo.flags and (pi_needs_implicit_finally or pi_uses_exceptions)) <> 0) then
  1337. begin
  1338. cg.a_jmp_always(list,aktexitlabel);
  1339. cg.a_label(list,aktexit2label);
  1340. handle_fast_exit_return_value(list);
  1341. end;
  1342. if aktexitlabel.is_used then
  1343. list.concat(Tai_label.Create(aktexitlabel));
  1344. cleanup_regvars(list);
  1345. { call the destructor help procedure }
  1346. if (aktprocdef.proctypeoption=potype_destructor) and
  1347. assigned(procinfo._class) then
  1348. cg.g_call_destructor_helper(list);
  1349. { finalize temporary data }
  1350. finalizetempvariables(list);
  1351. { finalize local data like ansistrings}
  1352. case aktprocdef.proctypeoption of
  1353. potype_unitfinalize:
  1354. begin
  1355. { using current_module.globalsymtable is hopefully }
  1356. { more robust than symtablestack and symtablestack.next }
  1357. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1358. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1359. end;
  1360. { units have seperate code for initialization and finalization }
  1361. potype_unitinit: ;
  1362. else
  1363. aktprocdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1364. end;
  1365. { finalize paras data }
  1366. if assigned(aktprocdef.parast) then
  1367. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
  1368. { do we need to handle exceptions because of ansi/widestrings ? }
  1369. if not inlined and
  1370. ((procinfo.flags and pi_needs_implicit_finally)<>0) and
  1371. { but it's useless in init/final code of units }
  1372. not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  1373. begin
  1374. { the exception helper routines modify all registers }
  1375. aktprocdef.usedregisters:=all_registers;
  1376. objectlibrary.getlabel(noreraiselabel);
  1377. free_exception(list,
  1378. procinfo.exception_jmp_ref,
  1379. procinfo.exception_env_ref,
  1380. procinfo.exception_result_ref,0,
  1381. noreraiselabel,false);
  1382. tg.Ungettemp(list,procinfo.exception_jmp_ref);
  1383. tg.Ungettemp(list,procinfo.exception_env_ref);
  1384. tg.Ungettemp(list,procinfo.exception_result_ref);
  1385. if (aktprocdef.proctypeoption=potype_constructor) then
  1386. begin
  1387. if assigned(procinfo._class) then
  1388. begin
  1389. pd:=procinfo._class.searchdestructor;
  1390. if assigned(pd) then
  1391. begin
  1392. objectlibrary.getlabel(nodestroycall);
  1393. reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
  1394. cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,nodestroycall);
  1395. if is_class(procinfo._class) then
  1396. begin
  1397. cg.a_param_const(list,OS_INT,1,paramanager.getintparaloc(2));
  1398. cg.a_param_reg(list,OS_ADDR,self_pointer_reg,paramanager.getintparaloc(1));
  1399. end
  1400. else if is_object(procinfo._class) then
  1401. begin
  1402. cg.a_param_reg(list,OS_ADDR,self_pointer_reg,paramanager.getintparaloc(2));
  1403. reference_reset_symbol(href,objectlibrary.newasmsymbol(procinfo._class.vmt_mangledname),0);
  1404. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(1));
  1405. end
  1406. else
  1407. Internalerror(200006164);
  1408. if (po_virtualmethod in pd.procoptions) then
  1409. begin
  1410. reference_reset_base(href,self_pointer_reg,0);
  1411. tmpreg:=cg.get_scratch_reg_address(list);
  1412. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  1413. reference_reset_base(href,tmpreg,procinfo._class.vmtmethodoffset(pd.extnumber));
  1414. cg.free_scratch_reg(list,tmpreg);
  1415. cg.a_call_ref(list,href);
  1416. end
  1417. else
  1418. cg.a_call_name(list,pd.mangledname);
  1419. { not necessary because the result is never assigned in the
  1420. case of an exception (FK) }
  1421. cg.a_label(list,nodestroycall);
  1422. end;
  1423. end
  1424. end
  1425. else
  1426. begin
  1427. { no constructor }
  1428. { must be the return value finalized before reraising the exception? }
  1429. if (not is_void(aktprocdef.rettype.def)) and
  1430. (aktprocdef.rettype.def.needs_inittable) and
  1431. ((aktprocdef.rettype.def.deftype<>objectdef) or
  1432. not is_class(aktprocdef.rettype.def)) then
  1433. begin
  1434. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1435. cg.g_finalize(list,aktprocdef.rettype.def,href,paramanager.ret_in_param(aktprocdef.rettype.def));
  1436. end;
  1437. end;
  1438. cg.a_call_name(list,'FPC_RERAISE');
  1439. cg.a_label(list,noreraiselabel);
  1440. end;
  1441. { call __EXIT for main program }
  1442. if (not DLLsource) and
  1443. (not inlined) and
  1444. (aktprocdef.proctypeoption=potype_proginit) then
  1445. cg.a_call_name(list,'FPC_DO_EXIT');
  1446. { handle return value, this is not done for assembler routines when
  1447. they didn't reference the result variable }
  1448. usesacc:=false;
  1449. usesacchi:=false;
  1450. usesself:=false;
  1451. if not(po_assembler in aktprocdef.procoptions) or
  1452. (assigned(aktprocdef.funcretsym) and
  1453. (tfuncretsym(aktprocdef.funcretsym).refcount>1)) then
  1454. begin
  1455. if (aktprocdef.proctypeoption<>potype_constructor) then
  1456. handle_return_value(list,inlined,usesacc,usesacchi,usesfpu)
  1457. else
  1458. begin
  1459. { successful constructor deletes the zero flag }
  1460. { and returns self in eax }
  1461. { eax must be set to zero if the allocation failed !!! }
  1462. objectlibrary.getlabel(okexitlabel);
  1463. cg.a_jmp_always(list,okexitlabel);
  1464. cg.a_label(list,faillabel);
  1465. cg.g_call_fail_helper(list);
  1466. cg.a_label(list,okexitlabel);
  1467. { for classes this is done after the call to }
  1468. { AfterConstruction }
  1469. if is_object(procinfo._class) then
  1470. begin
  1471. cg.a_reg_alloc(list,accumulator);
  1472. cg.a_load_reg_reg(list,OS_ADDR,self_pointer_reg,accumulator);
  1473. usesacc:=true;
  1474. end;
  1475. {$ifdef i386}
  1476. list.concat(taicpu.op_reg_reg(A_TEST,S_L,R_ESI,R_ESI));
  1477. {$else}
  1478. {$warning constructor returns in flags for i386}
  1479. {$endif i386}
  1480. usesself:=true;
  1481. end;
  1482. end;
  1483. if aktexit2label.is_used and not aktexit2label.is_set then
  1484. cg.a_label(list,aktexit2label);
  1485. {$ifdef GDB}
  1486. if ((cs_debuginfo in aktmoduleswitches) and not inlined) then
  1487. begin
  1488. objectlibrary.getlabel(stabsendlabel);
  1489. cg.a_label(list,stabsendlabel);
  1490. end;
  1491. {$endif GDB}
  1492. { remove copies of call by value parameters when there are also
  1493. registers saved on the stack }
  1494. if ((po_saveregisters in aktprocdef.procoptions) or
  1495. (po_savestdregs in aktprocdef.procoptions)) and
  1496. not(po_assembler in aktprocdef.procoptions) and
  1497. not(aktprocdef.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_palmossyscall,pocall_system]) then
  1498. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}removevalueparas,list);
  1499. { for the save all registers we can simply use a pusha,popa which
  1500. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1501. if (po_saveregisters in aktprocdef.procoptions) then
  1502. cg.g_restore_all_registers(list,usesself,usesacc,usesacchi)
  1503. else
  1504. { should we restore edi ? }
  1505. if (po_savestdregs in aktprocdef.procoptions) then
  1506. cg.g_restore_standard_registers(list,aktprocdef.usedregisters);
  1507. { remove stackframe }
  1508. if not inlined then
  1509. begin
  1510. if (not nostackframe) then
  1511. cg.g_restore_frame_pointer(list)
  1512. else
  1513. if (tg.gettempsize<>0) then
  1514. cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,STACK_POINTER_REG);
  1515. end;
  1516. { at last, the return is generated }
  1517. if not inlined then
  1518. begin
  1519. if (po_interrupt in aktprocdef.procoptions) then
  1520. cg.g_interrupt_stackframe_exit(list,usesself,usesacc,usesacchi)
  1521. else
  1522. cg.g_return_from_proc(list,parasize);
  1523. end;
  1524. if not inlined then
  1525. list.concat(Tai_symbol_end.Createname(aktprocdef.mangledname));
  1526. {$ifdef GDB}
  1527. if (cs_debuginfo in aktmoduleswitches) and not inlined then
  1528. begin
  1529. if assigned(procinfo._class) then
  1530. if (not assigned(procinfo.parent) or
  1531. not assigned(procinfo.parent._class)) then
  1532. begin
  1533. if (po_classmethod in aktprocdef.procoptions) or
  1534. ((po_virtualmethod in aktprocdef.procoptions) and
  1535. (potype_constructor=aktprocdef.proctypeoption)) or
  1536. (po_staticmethod in aktprocdef.procoptions) then
  1537. begin
  1538. list.concat(Tai_stabs.Create(strpnew(
  1539. '"pvmt:p'+tstoreddef(pvmttype.def).numberstring+'",'+
  1540. tostr(N_tsym)+',0,0,'+tostr(procinfo.selfpointer_offset))));
  1541. end
  1542. else
  1543. begin
  1544. if not(is_class(procinfo._class)) then
  1545. st:='v'
  1546. else
  1547. st:='p';
  1548. list.concat(Tai_stabs.Create(strpnew(
  1549. '"$t:'+st+procinfo._class.numberstring+'",'+
  1550. tostr(N_tsym)+',0,0,'+tostr(procinfo.selfpointer_offset))));
  1551. end;
  1552. end
  1553. else
  1554. begin
  1555. if not is_class(procinfo._class) then
  1556. st:='*'
  1557. else
  1558. st:='';
  1559. list.concat(Tai_stabs.Create(strpnew(
  1560. '"$t:r'+st+procinfo._class.numberstring+'",'+
  1561. tostr(N_RSYM)+',0,0,'+tostr(stab_regindex[SELF_POINTER_REG]))));
  1562. end;
  1563. { define calling EBP as pseudo local var PM }
  1564. { this enables test if the function is a local one !! }
  1565. if assigned(procinfo.parent) and (lexlevel>normal_function_level) then
  1566. list.concat(Tai_stabs.Create(strpnew(
  1567. '"parent_ebp:'+tstoreddef(voidpointertype.def).numberstring+'",'+
  1568. tostr(N_LSYM)+',0,0,'+tostr(procinfo.framepointer_offset))));
  1569. if (not is_void(aktprocdef.rettype.def)) then
  1570. begin
  1571. if paramanager.ret_in_param(aktprocdef.rettype.def) then
  1572. list.concat(Tai_stabs.Create(strpnew(
  1573. '"'+aktprocsym.name+':X*'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1574. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))))
  1575. else
  1576. list.concat(Tai_stabs.Create(strpnew(
  1577. '"'+aktprocsym.name+':X'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1578. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))));
  1579. if (m_result in aktmodeswitches) then
  1580. if paramanager.ret_in_param(aktprocdef.rettype.def) then
  1581. list.concat(Tai_stabs.Create(strpnew(
  1582. '"RESULT:X*'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1583. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))))
  1584. else
  1585. list.concat(Tai_stabs.Create(strpnew(
  1586. '"RESULT:X'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1587. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))));
  1588. end;
  1589. mangled_length:=length(aktprocdef.mangledname);
  1590. getmem(p,2*mangled_length+50);
  1591. strpcopy(p,'192,0,0,');
  1592. strpcopy(strend(p),aktprocdef.mangledname);
  1593. if (target_info.use_function_relative_addresses) then
  1594. begin
  1595. strpcopy(strend(p),'-');
  1596. strpcopy(strend(p),aktprocdef.mangledname);
  1597. end;
  1598. list.concat(Tai_stabn.Create(strnew(p)));
  1599. {List.concat(Tai_stabn.Create(strpnew('192,0,0,'
  1600. +aktprocdef.mangledname))));
  1601. p[0]:='2';p[1]:='2';p[2]:='4';
  1602. strpcopy(strend(p),'_end');}
  1603. strpcopy(p,'224,0,0,'+stabsendlabel.name);
  1604. if (target_info.use_function_relative_addresses) then
  1605. begin
  1606. strpcopy(strend(p),'-');
  1607. strpcopy(strend(p),aktprocdef.mangledname);
  1608. end;
  1609. list.concatlist(withdebuglist);
  1610. list.concat(Tai_stabn.Create(strnew(p)));
  1611. { strpnew('224,0,0,'
  1612. +aktprocdef.mangledname+'_end'))));}
  1613. freemem(p,2*mangled_length+50);
  1614. end;
  1615. {$endif GDB}
  1616. if inlined then
  1617. cleanup_regvars(list);
  1618. end;
  1619. procedure genimplicitunitinit(list : TAAsmoutput);
  1620. begin
  1621. {$ifdef GDB}
  1622. if (cs_debuginfo in aktmoduleswitches) and
  1623. target_info.use_function_relative_addresses then
  1624. list.concat(Tai_stab_function_name.Create(strpnew('INIT$$'+current_module.modulename^)));
  1625. {$endif GDB}
  1626. list.concat(Tai_symbol.Createname_global('INIT$$'+current_module.modulename^,0));
  1627. list.concat(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_init',0));
  1628. { using current_module.globalsymtable is hopefully }
  1629. { more robust than symtablestack and symtablestack.next }
  1630. tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1631. tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1632. cg.g_return_from_proc(list,0);
  1633. end;
  1634. procedure genimplicitunitfinal(list : TAAsmoutput);
  1635. begin
  1636. {$ifdef GDB}
  1637. if (cs_debuginfo in aktmoduleswitches) and
  1638. target_info.use_function_relative_addresses then
  1639. list.concat(Tai_stab_function_name.Create(strpnew('FINALIZE$$'+current_module.modulename^)));
  1640. {$endif GDB}
  1641. list.concat(Tai_symbol.Createname_global('FINALIZE$$'+current_module.modulename^,0));
  1642. list.concat(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_finalize',0));
  1643. { using current_module.globalsymtable is hopefully }
  1644. { more robust than symtablestack and symtablestack.next }
  1645. tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1646. tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1647. cg.g_return_from_proc(list,0);
  1648. end;
  1649. end.
  1650. {
  1651. $Log$
  1652. Revision 1.48 2002-09-07 15:25:03 peter
  1653. * old logs removed and tabs fixed
  1654. Revision 1.47 2002/09/02 18:44:48 peter
  1655. * fixed (not) pushing of empty parameters
  1656. * fixed implicit initialization/finalization generation
  1657. * fixed/optimized local copy of value arguments init/final
  1658. Revision 1.46 2002/09/01 19:27:34 peter
  1659. * use index register when available for generating a reference with
  1660. only a signle register. Using the base register could possibly
  1661. destroy the framepointer
  1662. Revision 1.45 2002/09/01 18:50:20 peter
  1663. * fixed maybe_save that did not support a reference with only
  1664. a index register. It now also updates the location with the new
  1665. base register only
  1666. Revision 1.44 2002/09/01 14:42:41 peter
  1667. * removevaluepara added to fix the stackpointer so restoring of
  1668. saved registers works
  1669. Revision 1.43 2002/08/25 19:25:18 peter
  1670. * sym.insert_in_data removed
  1671. * symtable.insertvardata/insertconstdata added
  1672. * removed insert_in_data call from symtable.insert, it needs to be
  1673. called separatly. This allows to deref the address calculation
  1674. * procedures now calculate the parast addresses after the procedure
  1675. directives are parsed. This fixes the cdecl parast problem
  1676. * push_addr_param has an extra argument that specifies if cdecl is used
  1677. or not
  1678. Revision 1.42 2002/08/24 18:38:26 peter
  1679. * really use tt_noreuse for exception frame buffers
  1680. Revision 1.41 2002/08/23 16:14:49 peter
  1681. * tempgen cleanup
  1682. * tt_noreuse temp type added that will be used in genentrycode
  1683. Revision 1.40 2002/08/18 10:42:37 florian
  1684. * remaining assembler writer bugs fixed, the errors in the
  1685. system unit are inline assembler problems
  1686. Revision 1.39 2002/08/17 09:23:36 florian
  1687. * first part of procinfo rewrite
  1688. Revision 1.38 2002/08/16 14:24:57 carl
  1689. * issameref() to test if two references are the same (then emit no opcodes)
  1690. + ret_in_reg to replace ret_in_acc
  1691. (fix some register allocation bugs at the same time)
  1692. + save_std_register now has an extra parameter which is the
  1693. usedinproc registers
  1694. Revision 1.37 2002/08/15 15:15:55 carl
  1695. * jmpbuf size allocation for exceptions is now cpu specific (as it should)
  1696. * more generic nodes for maths
  1697. * several fixes for better m68k support
  1698. Revision 1.36 2002/08/14 19:25:09 carl
  1699. * fix Florian's last commit for m68k compilation
  1700. Revision 1.35 2002/08/13 21:40:56 florian
  1701. * more fixes for ppc calling conventions
  1702. Revision 1.34 2002/08/12 15:08:39 carl
  1703. + stab register indexes for powerpc (moved from gdb to cpubase)
  1704. + tprocessor enumeration moved to cpuinfo
  1705. + linker in target_info is now a class
  1706. * many many updates for m68k (will soon start to compile)
  1707. - removed some ifdef or correct them for correct cpu
  1708. Revision 1.33 2002/08/11 14:32:27 peter
  1709. * renamed current_library to objectlibrary
  1710. Revision 1.32 2002/08/11 13:24:12 peter
  1711. * saving of asmsymbols in ppu supported
  1712. * asmsymbollist global is removed and moved into a new class
  1713. tasmlibrarydata that will hold the info of a .a file which
  1714. corresponds with a single module. Added librarydata to tmodule
  1715. to keep the library info stored for the module. In the future the
  1716. objectfiles will also be stored to the tasmlibrarydata class
  1717. * all getlabel/newasmsymbol and friends are moved to the new class
  1718. Revision 1.31 2002/08/09 19:16:57 carl
  1719. * stack allocation is now done separately (at the end) of genentrycode
  1720. so temps. can be allocated before.
  1721. * fix generic exception handling
  1722. Revision 1.30 2002/08/06 20:55:21 florian
  1723. * first part of ppc calling conventions fix
  1724. Revision 1.29 2002/08/04 19:09:22 carl
  1725. + added generic exception support (still does not work!)
  1726. + more documentation
  1727. Revision 1.28 2002/07/29 21:23:42 florian
  1728. * more fixes for the ppc
  1729. + wrappers for the tcnvnode.first_* stuff introduced
  1730. }