ncgutil.pas 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329
  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. globtype,
  24. cpubase,cgbase,parabase,
  25. aasmbase,aasmtai,aasmcpu,
  26. symconst,symbase,symdef,symsym,symtype,symtable
  27. {$ifndef cpu64bit}
  28. ,cg64f32
  29. {$endif cpu64bit}
  30. ;
  31. type
  32. tloadregvars = (lr_dont_load_regvars, lr_load_regvars);
  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:Tsuperregisterset);
  36. procedure location_force_reg(list:TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  37. procedure location_force_fpureg(list:TAAsmoutput;var l: tlocation;maybeconst:boolean);
  38. procedure location_force_mem(list:TAAsmoutput;var l:tlocation);
  39. procedure location_force_mmregscalar(list:TAAsmoutput;var l: tlocation;maybeconst:boolean);
  40. function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
  41. procedure gen_proc_symbol(list:Taasmoutput);
  42. procedure gen_proc_symbol_end(list:Taasmoutput);
  43. procedure gen_proc_entry_code(list:Taasmoutput);
  44. procedure gen_proc_exit_code(list:Taasmoutput);
  45. procedure gen_save_used_regs(list:TAAsmoutput);
  46. procedure gen_restore_used_regs(list:TAAsmoutput;const funcretparaloc:tcgpara);
  47. procedure gen_initialize_code(list:TAAsmoutput);
  48. procedure gen_finalize_code(list:TAAsmoutput);
  49. procedure gen_entry_code(list:TAAsmoutput);
  50. procedure gen_exit_code(list:TAAsmoutput);
  51. procedure gen_load_para_value(list:TAAsmoutput);
  52. procedure gen_load_return_value(list:TAAsmoutput);
  53. {#
  54. Allocate the buffers for exception management and setjmp environment.
  55. Return a pointer to these buffers, send them to the utility routine
  56. so they are registered, and then call setjmp.
  57. Then compare the result of setjmp with 0, and if not equal
  58. to zero, then jump to exceptlabel.
  59. Also store the result of setjmp to a temporary space by calling g_save_exception_reason
  60. It is to note that this routine may be called *after* the stackframe of a
  61. routine has been called, therefore on machines where the stack cannot
  62. be modified, all temps should be allocated on the heap instead of the
  63. stack.
  64. }
  65. const
  66. EXCEPT_BUF_SIZE = 3*sizeof(aint);
  67. type
  68. texceptiontemps=record
  69. jmpbuf,
  70. envbuf,
  71. reasonbuf : treference;
  72. end;
  73. procedure get_exception_temps(list:taasmoutput;var t:texceptiontemps);
  74. procedure unget_exception_temps(list:taasmoutput;const t:texceptiontemps);
  75. procedure new_exception(list:TAAsmoutput;const t:texceptiontemps;a:aint;exceptlabel:tasmlabel);
  76. procedure free_exception(list:TAAsmoutput;const t:texceptiontemps;a:aint;endexceptlabel:tasmlabel;onlyfree:boolean);
  77. procedure insertconstdata(sym : ttypedconstsym);
  78. procedure insertbssdata(sym : tvarsym);
  79. procedure gen_alloc_symtable(list:TAAsmoutput;st:tsymtable);
  80. procedure gen_free_symtable(list:TAAsmoutput;st:tsymtable);
  81. procedure gen_alloc_inline_parast(list:TAAsmoutput;pd:tprocdef);
  82. procedure gen_alloc_inline_funcret(list:TAAsmoutput;pd:tprocdef);
  83. { rtti and init/final }
  84. procedure generate_rtti(p:Ttypesym);
  85. procedure generate_inittable(p:tsym);
  86. implementation
  87. uses
  88. strings,
  89. cutils,cclasses,
  90. globals,systems,verbose,
  91. ppu,defutil,
  92. procinfo,paramgr,fmodule,
  93. regvars,dwarf,
  94. {$ifdef GDB}
  95. gdb,
  96. {$endif GDB}
  97. pass_1,pass_2,
  98. ncon,nld,nutils,
  99. tgobj,cgutils,cgobj;
  100. {*****************************************************************************
  101. Misc Helpers
  102. *****************************************************************************}
  103. { DO NOT RELY on the fact that the tnode is not yet swaped
  104. because of inlining code PM }
  105. procedure firstcomplex(p : tbinarynode);
  106. var
  107. hp : tnode;
  108. begin
  109. { always calculate boolean AND and OR from left to right }
  110. if (p.nodetype in [orn,andn]) and
  111. is_boolean(p.left.resulttype.def) then
  112. begin
  113. if nf_swaped in p.flags then
  114. internalerror(234234);
  115. end
  116. else
  117. if (
  118. (p.location.loc=LOC_FPUREGISTER) and
  119. (p.right.registersfpu > p.left.registersfpu)
  120. ) or
  121. (
  122. (
  123. (
  124. ((p.left.registersfpu = 0) and (p.right.registersfpu = 0)) or
  125. (p.location.loc<>LOC_FPUREGISTER)
  126. ) and
  127. (p.left.registersint<p.right.registersint)
  128. )
  129. ) then
  130. begin
  131. hp:=p.left;
  132. p.left:=p.right;
  133. p.right:=hp;
  134. if nf_swaped in p.flags then
  135. exclude(p.flags,nf_swaped)
  136. else
  137. include(p.flags,nf_swaped);
  138. end;
  139. end;
  140. procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
  141. {
  142. produces jumps to true respectively false labels using boolean expressions
  143. depending on whether the loading of regvars is currently being
  144. synchronized manually (such as in an if-node) or automatically (most of
  145. the other cases where this procedure is called), loadregvars can be
  146. "lr_load_regvars" or "lr_dont_load_regvars"
  147. }
  148. var
  149. opsize : tcgsize;
  150. storepos : tfileposinfo;
  151. begin
  152. if nf_error in p.flags then
  153. exit;
  154. storepos:=aktfilepos;
  155. aktfilepos:=p.fileinfo;
  156. if is_boolean(p.resulttype.def) then
  157. begin
  158. {$ifdef OLDREGVARS}
  159. if loadregvars = lr_load_regvars then
  160. load_all_regvars(list);
  161. {$endif OLDREGVARS}
  162. if is_constboolnode(p) then
  163. begin
  164. if tordconstnode(p).value<>0 then
  165. cg.a_jmp_always(list,truelabel)
  166. else
  167. cg.a_jmp_always(list,falselabel)
  168. end
  169. else
  170. begin
  171. opsize:=def_cgsize(p.resulttype.def);
  172. case p.location.loc of
  173. LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
  174. begin
  175. {$ifdef OLDREGVARS}
  176. if (p.location.loc = LOC_CREGISTER) then
  177. load_regvar_reg(list,p.location.register);
  178. {$endif OLDREGVARS}
  179. cg.a_cmp_const_loc_label(list,opsize,OC_NE,0,p.location,truelabel);
  180. cg.a_jmp_always(list,falselabel);
  181. end;
  182. LOC_JUMP:
  183. ;
  184. {$ifdef cpuflags}
  185. LOC_FLAGS :
  186. begin
  187. cg.a_jmp_flags(list,p.location.resflags,truelabel);
  188. cg.a_jmp_always(list,falselabel);
  189. end;
  190. {$endif cpuflags}
  191. else
  192. begin
  193. printnode(output,p);
  194. internalerror(200308241);
  195. end;
  196. end;
  197. end;
  198. end
  199. else
  200. internalerror(200112305);
  201. aktfilepos:=storepos;
  202. end;
  203. (*
  204. This code needs fixing. It is not safe to use rgint; on the m68000 it
  205. would be rgaddr.
  206. procedure remove_non_regvars_from_loc(const t: tlocation; var regs:Tsuperregisterset);
  207. begin
  208. case t.loc of
  209. LOC_REGISTER:
  210. begin
  211. { can't be a regvar, since it would be LOC_CREGISTER then }
  212. exclude(regs,getsupreg(t.register));
  213. if t.registerhigh<>NR_NO then
  214. exclude(regs,getsupreg(t.registerhigh));
  215. end;
  216. LOC_CREFERENCE,LOC_REFERENCE:
  217. begin
  218. if not(cs_regvars in aktglobalswitches) or
  219. (getsupreg(t.reference.base) in cg.rgint.usableregs) then
  220. exclude(regs,getsupreg(t.reference.base));
  221. if not(cs_regvars in aktglobalswitches) or
  222. (getsupreg(t.reference.index) in cg.rgint.usableregs) then
  223. exclude(regs,getsupreg(t.reference.index));
  224. end;
  225. end;
  226. end;
  227. *)
  228. {*****************************************************************************
  229. EXCEPTION MANAGEMENT
  230. *****************************************************************************}
  231. procedure get_exception_temps(list:taasmoutput;var t:texceptiontemps);
  232. begin
  233. tg.GetTemp(list,EXCEPT_BUF_SIZE,tt_persistent,t.envbuf);
  234. tg.GetTemp(list,JMP_BUF_SIZE,tt_persistent,t.jmpbuf);
  235. tg.GetTemp(list,sizeof(aint),tt_persistent,t.reasonbuf);
  236. end;
  237. procedure unget_exception_temps(list:taasmoutput;const t:texceptiontemps);
  238. begin
  239. tg.Ungettemp(list,t.jmpbuf);
  240. tg.ungettemp(list,t.envbuf);
  241. tg.ungettemp(list,t.reasonbuf);
  242. end;
  243. procedure new_exception(list:TAAsmoutput;const t:texceptiontemps;a:aint;exceptlabel:tasmlabel);
  244. var
  245. paraloc1,paraloc2,paraloc3 : tcgpara;
  246. begin
  247. paraloc1.init;
  248. paraloc2.init;
  249. paraloc3.init;
  250. paramanager.getintparaloc(pocall_default,1,paraloc1);
  251. paramanager.getintparaloc(pocall_default,2,paraloc2);
  252. paramanager.getintparaloc(pocall_default,3,paraloc3);
  253. paramanager.allocparaloc(list,paraloc3);
  254. cg.a_paramaddr_ref(list,t.envbuf,paraloc3);
  255. paramanager.allocparaloc(list,paraloc2);
  256. cg.a_paramaddr_ref(list,t.jmpbuf,paraloc2);
  257. { push type of exceptionframe }
  258. paramanager.allocparaloc(list,paraloc1);
  259. cg.a_param_const(list,OS_S32,1,paraloc1);
  260. paramanager.freeparaloc(list,paraloc3);
  261. paramanager.freeparaloc(list,paraloc2);
  262. paramanager.freeparaloc(list,paraloc1);
  263. cg.alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  264. cg.a_call_name(list,'FPC_PUSHEXCEPTADDR');
  265. cg.dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  266. paramanager.getintparaloc(pocall_default,1,paraloc1);
  267. paramanager.allocparaloc(list,paraloc1);
  268. cg.a_param_reg(list,OS_ADDR,NR_FUNCTION_RESULT_REG,paraloc1);
  269. paramanager.freeparaloc(list,paraloc1);
  270. cg.alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  271. cg.a_call_name(list,'FPC_SETJMP');
  272. cg.dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  273. cg.g_exception_reason_save(list, t.reasonbuf);
  274. cg.a_cmp_const_reg_label(list,OS_S32,OC_NE,0,cg.makeregsize(list,NR_FUNCTION_RESULT_REG,OS_S32),exceptlabel);
  275. paraloc1.done;
  276. paraloc2.done;
  277. paraloc3.done;
  278. end;
  279. procedure free_exception(list:TAAsmoutput;const t:texceptiontemps;a:aint;endexceptlabel:tasmlabel;onlyfree:boolean);
  280. begin
  281. cg.alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  282. cg.a_call_name(list,'FPC_POPADDRSTACK');
  283. cg.dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  284. if not onlyfree then
  285. begin
  286. cg.g_exception_reason_load(list, t.reasonbuf);
  287. cg.a_cmp_const_reg_label(list,OS_INT,OC_EQ,a,NR_FUNCTION_RESULT_REG,endexceptlabel);
  288. end;
  289. end;
  290. {*****************************************************************************
  291. TLocation
  292. *****************************************************************************}
  293. {$ifndef cpu64bit}
  294. { 32-bit version }
  295. procedure location_force_reg(list:TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  296. var
  297. hregister,
  298. hregisterhi : tregister;
  299. hreg64 : tregister64;
  300. hl : tasmlabel;
  301. oldloc : tlocation;
  302. const_location: boolean;
  303. begin
  304. oldloc:=l;
  305. if dst_size=OS_NO then
  306. internalerror(200309144);
  307. { handle transformations to 64bit separate }
  308. if dst_size in [OS_64,OS_S64] then
  309. begin
  310. if not (l.size in [OS_64,OS_S64]) then
  311. begin
  312. { load a smaller size to OS_64 }
  313. if l.loc=LOC_REGISTER then
  314. begin
  315. hregister:=cg.makeregsize(list,l.registerlow,OS_32);
  316. cg.a_load_reg_reg(list,l.size,OS_32,l.registerlow,hregister);
  317. end
  318. else
  319. hregister:=cg.getintregister(list,OS_INT);
  320. { load value in low register }
  321. case l.loc of
  322. LOC_FLAGS :
  323. cg.g_flags2reg(list,OS_INT,l.resflags,hregister);
  324. LOC_JUMP :
  325. begin
  326. cg.a_label(list,truelabel);
  327. cg.a_load_const_reg(list,OS_INT,1,hregister);
  328. objectlibrary.getlabel(hl);
  329. cg.a_jmp_always(list,hl);
  330. cg.a_label(list,falselabel);
  331. cg.a_load_const_reg(list,OS_INT,0,hregister);
  332. cg.a_label(list,hl);
  333. end;
  334. else
  335. cg.a_load_loc_reg(list,OS_INT,l,hregister);
  336. end;
  337. { reset hi part, take care of the signed bit of the current value }
  338. hregisterhi:=cg.getintregister(list,OS_INT);
  339. if (l.size in [OS_S8,OS_S16,OS_S32]) then
  340. begin
  341. if l.loc=LOC_CONSTANT then
  342. begin
  343. if (longint(l.value)<0) then
  344. cg.a_load_const_reg(list,OS_32,aint($ffffffff),hregisterhi)
  345. else
  346. cg.a_load_const_reg(list,OS_32,0,hregisterhi);
  347. end
  348. else
  349. begin
  350. cg.a_op_const_reg_reg(list,OP_SAR,OS_32,31,hregister,
  351. hregisterhi);
  352. end;
  353. end
  354. else
  355. cg.a_load_const_reg(list,OS_32,0,hregisterhi);
  356. location_reset(l,LOC_REGISTER,dst_size);
  357. l.registerlow:=hregister;
  358. l.registerhigh:=hregisterhi;
  359. end
  360. else
  361. begin
  362. { 64bit to 64bit }
  363. if (l.loc=LOC_REGISTER) or
  364. ((l.loc=LOC_CREGISTER) and maybeconst) then
  365. begin
  366. hregister:=l.registerlow;
  367. hregisterhi:=l.registerhigh;
  368. end
  369. else
  370. begin
  371. hregister:=cg.getintregister(list,OS_INT);
  372. hregisterhi:=cg.getintregister(list,OS_INT);
  373. end;
  374. hreg64.reglo:=hregister;
  375. hreg64.reghi:=hregisterhi;
  376. { load value in new register }
  377. cg64.a_load64_loc_reg(list,l,hreg64);
  378. location_reset(l,LOC_REGISTER,dst_size);
  379. l.registerlow:=hregister;
  380. l.registerhigh:=hregisterhi;
  381. end;
  382. end
  383. else
  384. begin
  385. {Do not bother to recycle the existing register. The register
  386. allocator eliminates unnecessary moves, so it's not needed
  387. and trying to recycle registers can cause problems because
  388. the registers changes size and may need aditional constraints.
  389. Not if it's about LOC_CREGISTER's (JM)
  390. }
  391. const_location :=
  392. (maybeconst) and
  393. (l.loc = LOC_CREGISTER) and
  394. (TCGSize2Size[l.size] = TCGSize2Size[dst_size]) and
  395. ((l.size = dst_size) or
  396. (TCGSize2Size[l.size] = TCGSize2Size[OS_INT]));
  397. if not const_location then
  398. hregister:=cg.getintregister(list,dst_size)
  399. else
  400. hregister := l.register;
  401. { load value in new register }
  402. case l.loc of
  403. LOC_FLAGS :
  404. cg.g_flags2reg(list,dst_size,l.resflags,hregister);
  405. LOC_JUMP :
  406. begin
  407. cg.a_label(list,truelabel);
  408. cg.a_load_const_reg(list,dst_size,1,hregister);
  409. objectlibrary.getlabel(hl);
  410. cg.a_jmp_always(list,hl);
  411. cg.a_label(list,falselabel);
  412. cg.a_load_const_reg(list,dst_size,0,hregister);
  413. cg.a_label(list,hl);
  414. end;
  415. else
  416. begin
  417. { load_loc_reg can only handle size >= l.size, when the
  418. new size is smaller then we need to adjust the size
  419. of the orignal and maybe recalculate l.register for i386 }
  420. if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
  421. begin
  422. if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  423. l.register:=cg.makeregsize(list,l.register,dst_size);
  424. { for big endian systems, the reference's offset must }
  425. { be increased in this case, since they have the }
  426. { MSB first in memory and e.g. byte(word_var) should }
  427. { return the second byte in this case (JM) }
  428. if (target_info.endian = ENDIAN_BIG) and
  429. (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  430. inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
  431. {$ifdef x86}
  432. l.size:=dst_size;
  433. {$endif x86}
  434. end;
  435. cg.a_load_loc_reg(list,dst_size,l,hregister);
  436. {$ifndef x86}
  437. if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
  438. l.size:=dst_size;
  439. {$endif not x86}
  440. end;
  441. end;
  442. if not const_location then
  443. location_reset(l,LOC_REGISTER,dst_size)
  444. else
  445. location_reset(l,LOC_CREGISTER,dst_size);
  446. l.register:=hregister;
  447. end;
  448. { Release temp when it was a reference }
  449. if oldloc.loc=LOC_REFERENCE then
  450. location_freetemp(list,oldloc);
  451. end;
  452. {$else cpu64bit}
  453. { 64-bit version }
  454. procedure location_force_reg(list:TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  455. var
  456. hregister : tregister;
  457. hl : tasmlabel;
  458. oldloc : tlocation;
  459. begin
  460. oldloc:=l;
  461. hregister:=cg.getintregister(list,dst_size);
  462. { load value in new register }
  463. case l.loc of
  464. LOC_FLAGS :
  465. cg.g_flags2reg(list,dst_size,l.resflags,hregister);
  466. LOC_JUMP :
  467. begin
  468. cg.a_label(list,truelabel);
  469. cg.a_load_const_reg(list,dst_size,1,hregister);
  470. objectlibrary.getlabel(hl);
  471. cg.a_jmp_always(list,hl);
  472. cg.a_label(list,falselabel);
  473. cg.a_load_const_reg(list,dst_size,0,hregister);
  474. cg.a_label(list,hl);
  475. end;
  476. else
  477. begin
  478. { load_loc_reg can only handle size >= l.size, when the
  479. new size is smaller then we need to adjust the size
  480. of the orignal and maybe recalculate l.register for i386 }
  481. if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
  482. begin
  483. if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  484. l.register:=cg.makeregsize(list,l.register,dst_size);
  485. { for big endian systems, the reference's offset must }
  486. { be increased in this case, since they have the }
  487. { MSB first in memory and e.g. byte(word_var) should }
  488. { return the second byte in this case (JM) }
  489. if (target_info.endian = ENDIAN_BIG) and
  490. (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  491. inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
  492. {$ifdef x86}
  493. l.size:=dst_size;
  494. {$endif x86}
  495. end;
  496. cg.a_load_loc_reg(list,dst_size,l,hregister);
  497. {$ifndef x86}
  498. if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
  499. l.size:=dst_size;
  500. {$endif not x86}
  501. end;
  502. end;
  503. if (l.loc <> LOC_CREGISTER) or
  504. not maybeconst then
  505. location_reset(l,LOC_REGISTER,dst_size)
  506. else
  507. location_reset(l,LOC_CREGISTER,dst_size);
  508. l.register:=hregister;
  509. { Release temp when it was a reference }
  510. if oldloc.loc=LOC_REFERENCE then
  511. location_freetemp(list,oldloc);
  512. end;
  513. {$endif cpu64bit}
  514. procedure location_force_fpureg(list:TAAsmoutput;var l: tlocation;maybeconst:boolean);
  515. var
  516. reg : tregister;
  517. href : treference;
  518. begin
  519. if (l.loc<>LOC_FPUREGISTER) and
  520. ((l.loc<>LOC_CFPUREGISTER) or (not maybeconst)) then
  521. begin
  522. { if it's in an mm register, store to memory first }
  523. if (l.loc in [LOC_MMREGISTER,LOC_CMMREGISTER]) then
  524. begin
  525. tg.GetTemp(list,tcgsize2size[l.size],tt_normal,href);
  526. cg.a_loadmm_reg_ref(list,l.size,l.size,l.register,href,mms_movescalar);
  527. location_reset(l,LOC_REFERENCE,l.size);
  528. l.reference:=href;
  529. end;
  530. reg:=cg.getfpuregister(list,l.size);
  531. cg.a_loadfpu_loc_reg(list,l,reg);
  532. location_freetemp(list,l);
  533. location_reset(l,LOC_FPUREGISTER,l.size);
  534. l.register:=reg;
  535. end;
  536. end;
  537. procedure location_force_mmregscalar(list:TAAsmoutput;var l: tlocation;maybeconst:boolean);
  538. var
  539. reg : tregister;
  540. href : treference;
  541. begin
  542. if (l.loc<>LOC_MMREGISTER) and
  543. ((l.loc<>LOC_CMMREGISTER) or (not maybeconst)) then
  544. begin
  545. { if it's in an fpu register, store to memory first }
  546. if (l.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
  547. begin
  548. tg.GetTemp(list,tcgsize2size[l.size],tt_normal,href);
  549. cg.a_loadfpu_reg_ref(list,l.size,l.register,href);
  550. location_reset(l,LOC_REFERENCE,l.size);
  551. l.reference:=href;
  552. end;
  553. reg:=cg.getmmregister(list,l.size);
  554. cg.a_loadmm_loc_reg(list,l.size,l,reg,mms_movescalar);
  555. location_freetemp(list,l);
  556. location_reset(l,LOC_MMREGISTER,l.size);
  557. l.register:=reg;
  558. end;
  559. end;
  560. procedure location_force_mem(list:TAAsmoutput;var l:tlocation);
  561. var
  562. r : treference;
  563. begin
  564. case l.loc of
  565. LOC_FPUREGISTER,
  566. LOC_CFPUREGISTER :
  567. begin
  568. tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
  569. cg.a_loadfpu_reg_ref(list,l.size,l.register,r);
  570. location_reset(l,LOC_REFERENCE,l.size);
  571. l.reference:=r;
  572. end;
  573. LOC_MMREGISTER,
  574. LOC_CMMREGISTER:
  575. begin
  576. tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
  577. cg.a_loadmm_reg_ref(list,l.size,l.size,l.register,r,mms_movescalar);
  578. location_reset(l,LOC_REFERENCE,l.size);
  579. l.reference:=r;
  580. end;
  581. LOC_CONSTANT,
  582. LOC_REGISTER,
  583. LOC_CREGISTER :
  584. begin
  585. tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
  586. {$ifndef cpu64bit}
  587. if l.size in [OS_64,OS_S64] then
  588. cg64.a_load64_loc_ref(list,l,r)
  589. else
  590. {$endif cpu64bit}
  591. cg.a_load_loc_ref(list,l.size,l,r);
  592. location_reset(l,LOC_REFERENCE,l.size);
  593. l.reference:=r;
  594. end;
  595. LOC_CREFERENCE,
  596. LOC_REFERENCE : ;
  597. else
  598. internalerror(200203219);
  599. end;
  600. end;
  601. {*****************************************************************************
  602. Maybe_Save
  603. *****************************************************************************}
  604. function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
  605. begin
  606. {$ifdef i386}
  607. if (needed>=maxfpuregs) and
  608. (l.loc = LOC_FPUREGISTER) then
  609. begin
  610. location_force_mem(list,l);
  611. maybe_pushfpu:=true;
  612. end
  613. else
  614. maybe_pushfpu:=false;
  615. {$else i386}
  616. maybe_pushfpu:=false;
  617. {$endif i386}
  618. end;
  619. {****************************************************************************
  620. Init/Finalize Code
  621. ****************************************************************************}
  622. procedure copyvalueparas(p : tnamedindexitem;arg:pointer);
  623. var
  624. href1 : treference;
  625. list:TAAsmoutput;
  626. hsym : tvarsym;
  627. l : longint;
  628. loadref : boolean;
  629. localcopyloc : tlocation;
  630. begin
  631. list:=taasmoutput(arg);
  632. if (tsym(p).typ=varsym) and
  633. (tvarsym(p).varspez=vs_value) and
  634. (paramanager.push_addr_param(tvarsym(p).varspez,tvarsym(p).vartype.def,current_procinfo.procdef.proccalloption)) then
  635. begin
  636. loadref:=true;
  637. case tvarsym(p).localloc.loc of
  638. LOC_CREGISTER :
  639. begin
  640. reference_reset_base(href1,tvarsym(p).localloc.register,0);
  641. loadref:=false;
  642. end;
  643. LOC_REFERENCE :
  644. href1:=tvarsym(p).localloc.reference;
  645. else
  646. internalerror(200309181);
  647. end;
  648. if is_open_array(tvarsym(p).vartype.def) or
  649. is_array_of_const(tvarsym(p).vartype.def) then
  650. begin
  651. { cdecl functions don't have a high pointer so it is not possible to generate
  652. a local copy }
  653. if not(current_procinfo.procdef.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  654. begin
  655. hsym:=tvarsym(tsym(p).owner.search('high'+p.name));
  656. if not assigned(hsym) then
  657. internalerror(200306061);
  658. cg.g_copyvaluepara_openarray(list,href1,hsym.localloc,tarraydef(tvarsym(p).vartype.def).elesize,loadref);
  659. end;
  660. end
  661. else
  662. begin
  663. { Allocate space for the local copy }
  664. l:=tvarsym(p).getsize;
  665. localcopyloc.loc:=LOC_REFERENCE;
  666. localcopyloc.size:=int_cgsize(l);
  667. tg.GetLocal(list,l,tvarsym(p).vartype.def,localcopyloc.reference);
  668. { Copy data }
  669. if is_shortstring(tvarsym(p).vartype.def) then
  670. begin
  671. { this code is only executed before the code for the body and the entry/exit code is generated
  672. so we're allowed to include pi_do_call here; after pass1 is run, this isn't allowed anymore
  673. }
  674. include(current_procinfo.flags,pi_do_call);
  675. cg.g_copyshortstring(list,href1,localcopyloc.reference,tstringdef(tvarsym(p).vartype.def).len,loadref)
  676. end
  677. else
  678. cg.g_concatcopy(list,href1,localcopyloc.reference,tvarsym(p).vartype.def.size,loadref);
  679. { update localloc of varsym }
  680. tg.Ungetlocal(list,tvarsym(p).localloc.reference);
  681. tvarsym(p).localloc:=localcopyloc;
  682. end;
  683. end;
  684. end;
  685. { initializes the regvars from staticsymtable with 0 }
  686. procedure initialize_regvars(p : tnamedindexitem;arg:pointer);
  687. var
  688. oldexprasmlist : TAAsmoutput;
  689. hp : tnode;
  690. begin
  691. if (tsym(p).typ=varsym) then
  692. begin
  693. case tvarsym(p).localloc.loc of
  694. LOC_CREGISTER :
  695. cg.a_load_const_reg(taasmoutput(arg),reg_cgsize(tvarsym(p).localloc.register),0,tvarsym(p).localloc.register);
  696. LOC_REFERENCE : ;
  697. else
  698. internalerror(200410124);
  699. end;
  700. end;
  701. end;
  702. { generates the code for initialisation of local data }
  703. procedure initialize_data(p : tnamedindexitem;arg:pointer);
  704. var
  705. oldexprasmlist : TAAsmoutput;
  706. hp : tnode;
  707. begin
  708. if (tsym(p).typ=varsym) and
  709. (tvarsym(p).refs>0) and
  710. not(is_class(tvarsym(p).vartype.def)) and
  711. tvarsym(p).vartype.def.needs_inittable then
  712. begin
  713. oldexprasmlist:=exprasmlist;
  714. exprasmlist:=taasmoutput(arg);
  715. hp:=initialize_data_node(cloadnode.create(tsym(p),tsym(p).owner));
  716. firstpass(hp);
  717. secondpass(hp);
  718. hp.free;
  719. exprasmlist:=oldexprasmlist;
  720. end;
  721. end;
  722. procedure finalize_sym(asmlist:taasmoutput;sym:tsym);
  723. var
  724. hp : tnode;
  725. oldexprasmlist : TAAsmoutput;
  726. begin
  727. include(current_procinfo.flags,pi_needs_implicit_finally);
  728. oldexprasmlist:=exprasmlist;
  729. exprasmlist:=asmlist;
  730. hp:=finalize_data_node(cloadnode.create(sym,sym.owner));
  731. firstpass(hp);
  732. secondpass(hp);
  733. hp.free;
  734. exprasmlist:=oldexprasmlist;
  735. end;
  736. { generates the code for finalisation of local variables }
  737. procedure finalize_local_vars(p : tnamedindexitem;arg:pointer);
  738. begin
  739. case tsym(p).typ of
  740. varsym :
  741. begin
  742. if (tvarsym(p).refs>0) and
  743. not(vo_is_funcret in tvarsym(p).varoptions) and
  744. not(is_class(tvarsym(p).vartype.def)) and
  745. tvarsym(p).vartype.def.needs_inittable then
  746. finalize_sym(taasmoutput(arg),tsym(p));
  747. end;
  748. end;
  749. end;
  750. { generates the code for finalisation of local typedconsts }
  751. procedure finalize_local_typedconst(p : tnamedindexitem;arg:pointer);
  752. var
  753. i : longint;
  754. pd : tprocdef;
  755. begin
  756. case tsym(p).typ of
  757. typedconstsym :
  758. begin
  759. if ttypedconstsym(p).is_writable and
  760. ttypedconstsym(p).typedconsttype.def.needs_inittable then
  761. finalize_sym(taasmoutput(arg),tsym(p));
  762. end;
  763. procsym :
  764. begin
  765. for i:=1 to tprocsym(p).procdef_count do
  766. begin
  767. pd:=tprocsym(p).procdef[i];
  768. if assigned(pd.localst) and
  769. (pd.procsym=tprocsym(p)) and
  770. (pd.localst.symtabletype<>staticsymtable) then
  771. pd.localst.foreach_static(@finalize_local_typedconst,arg);
  772. end;
  773. end;
  774. end;
  775. end;
  776. { generates the code for finalization of static symtable and
  777. all local (static) typedconsts }
  778. procedure finalize_static_data(p : tnamedindexitem;arg:pointer);
  779. var
  780. i : longint;
  781. pd : tprocdef;
  782. begin
  783. case tsym(p).typ of
  784. varsym :
  785. begin
  786. if (tvarsym(p).refs>0) and
  787. not(vo_is_funcret in tvarsym(p).varoptions) and
  788. not(is_class(tvarsym(p).vartype.def)) and
  789. tvarsym(p).vartype.def.needs_inittable then
  790. finalize_sym(taasmoutput(arg),tsym(p));
  791. end;
  792. typedconstsym :
  793. begin
  794. if ttypedconstsym(p).is_writable and
  795. ttypedconstsym(p).typedconsttype.def.needs_inittable then
  796. finalize_sym(taasmoutput(arg),tsym(p));
  797. end;
  798. procsym :
  799. begin
  800. for i:=1 to tprocsym(p).procdef_count do
  801. begin
  802. pd:=tprocsym(p).procdef[i];
  803. if assigned(pd.localst) and
  804. (pd.procsym=tprocsym(p)) and
  805. (pd.localst.symtabletype<>staticsymtable) then
  806. pd.localst.foreach_static(@finalize_local_typedconst,arg);
  807. end;
  808. end;
  809. end;
  810. end;
  811. { generates the code for incrementing the reference count of parameters and
  812. initialize out parameters }
  813. procedure init_paras(p : tnamedindexitem;arg:pointer);
  814. var
  815. href : treference;
  816. tmpreg : tregister;
  817. list:TAAsmoutput;
  818. begin
  819. list:=taasmoutput(arg);
  820. if (tsym(p).typ=varsym) and
  821. not is_class_or_interface(tvarsym(p).vartype.def) and
  822. tvarsym(p).vartype.def.needs_inittable then
  823. begin
  824. case tvarsym(p).varspez of
  825. vs_value :
  826. begin
  827. if tvarsym(p).localloc.loc<>LOC_REFERENCE then
  828. internalerror(200309187);
  829. cg.g_incrrefcount(list,tvarsym(p).vartype.def,tvarsym(p).localloc.reference,is_open_array(tvarsym(p).vartype.def));
  830. end;
  831. vs_out :
  832. begin
  833. tmpreg:=cg.getaddressregister(list);
  834. cg.a_load_loc_reg(list,OS_ADDR,tvarsym(p).localloc,tmpreg);
  835. reference_reset_base(href,tmpreg,0);
  836. cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
  837. end;
  838. end;
  839. end;
  840. end;
  841. { generates the code for decrementing the reference count of parameters }
  842. procedure final_paras(p : tnamedindexitem;arg:pointer);
  843. var
  844. list:TAAsmoutput;
  845. begin
  846. list:=taasmoutput(arg);
  847. if (tsym(p).typ=varsym) and
  848. not is_class_or_interface(tvarsym(p).vartype.def) and
  849. tvarsym(p).vartype.def.needs_inittable then
  850. begin
  851. if (tvarsym(p).varspez=vs_value) then
  852. begin
  853. include(current_procinfo.flags,pi_needs_implicit_finally);
  854. if tvarsym(p).localloc.loc<>LOC_REFERENCE then
  855. internalerror(200309188);
  856. cg.g_decrrefcount(list,tvarsym(p).vartype.def,tvarsym(p).localloc.reference,is_open_array(tvarsym(p).vartype.def));
  857. end;
  858. end
  859. else if (tsym(p).typ=varsym) and
  860. (tvarsym(p).varspez=vs_value) and
  861. (is_open_array(tvarsym(p).vartype.def) or
  862. is_array_of_const(tvarsym(p).vartype.def)) then
  863. begin
  864. { cdecl functions don't have a high pointer so it is not possible to generate
  865. a local copy }
  866. if not(current_procinfo.procdef.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  867. cg.g_releasevaluepara_openarray(list,tvarsym(p).localloc.reference);
  868. end;
  869. end;
  870. { Initialize temp ansi/widestrings,interfaces }
  871. procedure inittempvariables(list:taasmoutput);
  872. var
  873. hp : ptemprecord;
  874. href : treference;
  875. begin
  876. hp:=tg.templist;
  877. while assigned(hp) do
  878. begin
  879. if assigned(hp^.def) and
  880. hp^.def.needs_inittable then
  881. begin
  882. reference_reset_base(href,current_procinfo.framepointer,hp^.pos);
  883. cg.g_initialize(list,hp^.def,href,false);
  884. end;
  885. hp:=hp^.next;
  886. end;
  887. end;
  888. procedure finalizetempvariables(list:taasmoutput);
  889. var
  890. hp : ptemprecord;
  891. href : treference;
  892. begin
  893. hp:=tg.templist;
  894. while assigned(hp) do
  895. begin
  896. if assigned(hp^.def) and
  897. hp^.def.needs_inittable then
  898. begin
  899. include(current_procinfo.flags,pi_needs_implicit_finally);
  900. reference_reset_base(href,current_procinfo.framepointer,hp^.pos);
  901. cg.g_finalize(list,hp^.def,href,false);
  902. end;
  903. hp:=hp^.next;
  904. end;
  905. end;
  906. procedure gen_load_return_value(list:TAAsmoutput);
  907. var
  908. {$ifndef cpu64bit}
  909. href : treference;
  910. {$endif cpu64bit}
  911. ressym : tvarsym;
  912. resloc,
  913. restmploc : tlocation;
  914. hreg : tregister;
  915. funcretloc : pcgparalocation;
  916. begin
  917. { Is the loading needed? }
  918. if is_void(current_procinfo.procdef.rettype.def) or
  919. (
  920. (po_assembler in current_procinfo.procdef.procoptions) and
  921. (not(assigned(current_procinfo.procdef.funcretsym)) or
  922. (tvarsym(current_procinfo.procdef.funcretsym).refs=0))
  923. ) then
  924. exit;
  925. funcretloc:=current_procinfo.procdef.funcret_paraloc[calleeside].location;
  926. if not assigned(funcretloc) then
  927. internalerror(200408202);
  928. { constructors return self }
  929. if (current_procinfo.procdef.proctypeoption=potype_constructor) then
  930. ressym:=tvarsym(current_procinfo.procdef.parast.search('self'))
  931. else
  932. ressym:=tvarsym(current_procinfo.procdef.funcretsym);
  933. if (ressym.refs>0) then
  934. begin
  935. {$ifdef OLDREGVARS}
  936. case ressym.localloc.loc of
  937. LOC_CFPUREGISTER,
  938. LOC_FPUREGISTER:
  939. begin
  940. location_reset(restmploc,LOC_CFPUREGISTER,funcretloc^.size);
  941. restmploc.register:=ressym.localloc.register;
  942. end;
  943. LOC_CREGISTER,
  944. LOC_REGISTER:
  945. begin
  946. location_reset(restmploc,LOC_CREGISTER,funcretloc^.size);
  947. restmploc.register:=ressym.localloc.register;
  948. end;
  949. LOC_MMREGISTER:
  950. begin
  951. location_reset(restmploc,LOC_CMMREGISTER,funcretloc^.size);
  952. restmploc.register:=ressym.localloc.register;
  953. end;
  954. LOC_REFERENCE:
  955. begin
  956. location_reset(restmploc,LOC_REFERENCE,funcretloc^.size);
  957. restmploc.reference:=ressym.localloc.reference;
  958. end;
  959. else
  960. internalerror(200309184);
  961. end;
  962. {$else}
  963. restmploc:=ressym.localloc;
  964. {$endif}
  965. { Here, we return the function result. In most architectures, the value is
  966. passed into the FUNCTION_RETURN_REG, but in a windowed architecure like sparc a
  967. function returns in a register and the caller receives it in an other one }
  968. case funcretloc^.loc of
  969. LOC_REGISTER:
  970. begin
  971. {$ifndef cpu64bit}
  972. if current_procinfo.procdef.funcret_paraloc[calleeside].size in [OS_64,OS_S64] then
  973. begin
  974. current_procinfo.procdef.funcret_paraloc[calleeside].get_location(resloc);
  975. if resloc.loc<>LOC_REGISTER then
  976. internalerror(200409141);
  977. { Load low and high register separate to generate better register
  978. allocation info }
  979. if getsupreg(resloc.registerlow)<first_int_imreg then
  980. begin
  981. cg.getcpuregister(list,resloc.registerlow);
  982. cg.ungetcpuregister(list,resloc.registerlow);
  983. { for the optimizer }
  984. cg.a_reg_alloc(list,resloc.registerlow);
  985. end;
  986. case restmploc.loc of
  987. LOC_REFERENCE :
  988. begin
  989. href:=restmploc.reference;
  990. if target_info.endian=ENDIAN_BIG then
  991. inc(href.offset,4);
  992. cg.a_load_ref_reg(list,OS_32,OS_32,href,resloc.registerlow);
  993. end;
  994. LOC_CREGISTER :
  995. cg.a_load_reg_reg(list,OS_32,OS_32,restmploc.registerlow,resloc.registerlow);
  996. else
  997. internalerror(200409203);
  998. end;
  999. if getsupreg(resloc.registerhigh)<first_int_imreg then
  1000. begin
  1001. cg.getcpuregister(list,resloc.registerhigh);
  1002. cg.ungetcpuregister(list,resloc.registerhigh);
  1003. { for the optimizer }
  1004. cg.a_reg_alloc(list,resloc.registerhigh);
  1005. end;
  1006. case restmploc.loc of
  1007. LOC_REFERENCE :
  1008. begin
  1009. href:=restmploc.reference;
  1010. if target_info.endian=ENDIAN_LITTLE then
  1011. inc(href.offset,4);
  1012. cg.a_load_ref_reg(list,OS_32,OS_32,href,resloc.registerhigh);
  1013. end;
  1014. LOC_CREGISTER :
  1015. cg.a_load_reg_reg(list,OS_32,OS_32,restmploc.registerhigh,resloc.registerhigh);
  1016. else
  1017. internalerror(200409204);
  1018. end;
  1019. end
  1020. else
  1021. {$endif cpu64bit}
  1022. begin
  1023. hreg:=cg.makeregsize(list,funcretloc^.register,restmploc.size);
  1024. if getsupreg(funcretloc^.register)<first_int_imreg then
  1025. begin
  1026. cg.getcpuregister(list,funcretloc^.register);
  1027. cg.ungetcpuregister(list,hreg);
  1028. { for the optimizer }
  1029. cg.a_reg_alloc(list,funcretloc^.register);
  1030. end;
  1031. cg.a_load_loc_reg(list,restmploc.size,restmploc,hreg);
  1032. end;
  1033. end;
  1034. LOC_FPUREGISTER:
  1035. begin
  1036. if getsupreg(funcretloc^.register)<first_fpu_imreg then
  1037. begin
  1038. cg.getcpuregister(list,funcretloc^.register);
  1039. cg.ungetcpuregister(list,funcretloc^.register);
  1040. end;
  1041. cg.a_loadfpu_loc_reg(list,restmploc,funcretloc^.register);
  1042. end;
  1043. LOC_MMREGISTER:
  1044. begin
  1045. if getsupreg(funcretloc^.register)<first_mm_imreg then
  1046. begin
  1047. cg.getcpuregister(list,funcretloc^.register);
  1048. cg.ungetcpuregister(list,funcretloc^.register);
  1049. end;
  1050. cg.a_loadmm_loc_reg(list,restmploc.size,restmploc,funcretloc^.register,mms_movescalar);
  1051. end;
  1052. LOC_INVALID,
  1053. LOC_REFERENCE:
  1054. ;
  1055. else
  1056. internalerror(200405025);
  1057. end;
  1058. end;
  1059. end;
  1060. procedure gen_load_para_value(list:TAAsmoutput);
  1061. procedure get_para(const paraloc:TCGParaLocation);
  1062. begin
  1063. case paraloc.loc of
  1064. LOC_REGISTER :
  1065. begin
  1066. if getsupreg(paraloc.register)<first_int_imreg then
  1067. cg.getcpuregister(list,paraloc.register);
  1068. end;
  1069. LOC_MMREGISTER :
  1070. begin
  1071. if getsupreg(paraloc.register)<first_mm_imreg then
  1072. cg.getcpuregister(list,paraloc.register);
  1073. end;
  1074. LOC_FPUREGISTER :
  1075. begin
  1076. if getsupreg(paraloc.register)<first_fpu_imreg then
  1077. cg.getcpuregister(list,paraloc.register);
  1078. end;
  1079. end;
  1080. end;
  1081. procedure unget_para(const paraloc:TCGParaLocation);
  1082. begin
  1083. case paraloc.loc of
  1084. LOC_REGISTER :
  1085. begin
  1086. if getsupreg(paraloc.register)<first_int_imreg then
  1087. cg.ungetcpuregister(list,paraloc.register);
  1088. end;
  1089. LOC_MMREGISTER :
  1090. begin
  1091. if getsupreg(paraloc.register)<first_mm_imreg then
  1092. cg.ungetcpuregister(list,paraloc.register);
  1093. end;
  1094. LOC_FPUREGISTER :
  1095. begin
  1096. if getsupreg(paraloc.register)<first_fpu_imreg then
  1097. cg.ungetcpuregister(list,paraloc.register);
  1098. end;
  1099. end;
  1100. end;
  1101. procedure gen_load_ref(const paraloc:TCGParaLocation;const ref:treference);
  1102. var
  1103. href : treference;
  1104. begin
  1105. case paraloc.loc of
  1106. LOC_REGISTER :
  1107. cg.a_load_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
  1108. LOC_MMREGISTER :
  1109. cg.a_loadmm_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref,mms_movescalar);
  1110. LOC_FPUREGISTER :
  1111. cg.a_loadfpu_reg_ref(list,paraloc.size,paraloc.register,ref);
  1112. LOC_REFERENCE :
  1113. begin
  1114. reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset);
  1115. { use concatcopy, because it can also be a float which fails when
  1116. load_ref_ref is used. Don't copy data when the references are equal }
  1117. if not((href.base=ref.base) and (href.offset=ref.offset)) then
  1118. cg.g_concatcopy(list,href,ref,tcgsize2size[paraloc.size],false);
  1119. end;
  1120. else
  1121. internalerror(2002081302);
  1122. end;
  1123. end;
  1124. procedure gen_load_reg(const paraloc:TCGParaLocation;reg:tregister);
  1125. var
  1126. href : treference;
  1127. begin
  1128. case paraloc.loc of
  1129. LOC_REGISTER :
  1130. cg.a_load_reg_reg(list,paraloc.size,paraloc.size,paraloc.register,reg);
  1131. LOC_MMREGISTER :
  1132. cg.a_loadmm_reg_reg(list,paraloc.size,paraloc.size,paraloc.register,reg,mms_movescalar);
  1133. LOC_FPUREGISTER :
  1134. cg.a_loadfpu_reg_reg(list,paraloc.size,paraloc.register,reg);
  1135. LOC_REFERENCE :
  1136. begin
  1137. reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset);
  1138. case getregtype(reg) of
  1139. R_INTREGISTER :
  1140. cg.a_load_ref_reg(list,paraloc.size,paraloc.size,href,reg);
  1141. R_FPUREGISTER :
  1142. cg.a_loadfpu_ref_reg(list,paraloc.size,href,reg);
  1143. R_MMREGISTER :
  1144. cg.a_loadmm_ref_reg(list,paraloc.size,paraloc.size,href,reg,mms_movescalar);
  1145. else
  1146. internalerror(2004101012);
  1147. end;
  1148. end;
  1149. else
  1150. internalerror(2002081302);
  1151. end;
  1152. end;
  1153. var
  1154. hp : tparaitem;
  1155. paraloc : pcgparalocation;
  1156. {$ifdef sparc}
  1157. tempref,
  1158. {$endif sparc}
  1159. href : treference;
  1160. begin
  1161. if (po_assembler in current_procinfo.procdef.procoptions) then
  1162. exit;
  1163. { Allocate registers used by parameters }
  1164. hp:=tparaitem(current_procinfo.procdef.para.first);
  1165. while assigned(hp) do
  1166. begin
  1167. paraloc:=hp.paraloc[calleeside].location;
  1168. while assigned(paraloc) do
  1169. begin
  1170. if paraloc^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER] then
  1171. get_para(paraloc^);
  1172. paraloc:=paraloc^.next;
  1173. end;
  1174. hp:=tparaitem(hp.next);
  1175. end;
  1176. { Copy parameters to local references/registers }
  1177. hp:=tparaitem(current_procinfo.procdef.para.first);
  1178. while assigned(hp) do
  1179. begin
  1180. paraloc:=hp.paraloc[calleeside].location;
  1181. if not assigned(paraloc) then
  1182. internalerror(200408203);
  1183. case tvarsym(hp.parasym).localloc.loc of
  1184. LOC_REFERENCE :
  1185. begin
  1186. href:=tvarsym(hp.parasym).localloc.reference;
  1187. while assigned(paraloc) do
  1188. begin
  1189. unget_para(paraloc^);
  1190. gen_load_ref(paraloc^,href);
  1191. inc(href.offset,TCGSize2Size[paraloc^.size]);
  1192. paraloc:=paraloc^.next;
  1193. end;
  1194. end;
  1195. LOC_CREGISTER :
  1196. begin
  1197. {$ifndef cpu64bit}
  1198. if tvarsym(hp.parasym).localloc.size in [OS_64,OS_S64] then
  1199. begin
  1200. { First 32bits }
  1201. unget_para(paraloc^);
  1202. if (target_info.endian=ENDIAN_BIG) then
  1203. gen_load_reg(paraloc^,tvarsym(hp.parasym).localloc.registerhigh)
  1204. else
  1205. gen_load_reg(paraloc^,tvarsym(hp.parasym).localloc.registerlow);
  1206. { Second 32bits }
  1207. if not assigned(paraloc^.next) then
  1208. internalerror(200410104);
  1209. unget_para(paraloc^);
  1210. if (target_info.endian=ENDIAN_BIG) then
  1211. gen_load_reg(paraloc^,tvarsym(hp.parasym).localloc.registerlow)
  1212. else
  1213. gen_load_reg(paraloc^,tvarsym(hp.parasym).localloc.registerhigh);
  1214. end
  1215. else
  1216. {$endif cpu64bit}
  1217. begin
  1218. unget_para(paraloc^);
  1219. gen_load_reg(paraloc^,tvarsym(hp.parasym).localloc.register);
  1220. if assigned(paraloc^.next) then
  1221. internalerror(200410105);
  1222. end;
  1223. end;
  1224. LOC_CFPUREGISTER :
  1225. begin
  1226. {$ifdef sparc}
  1227. { Sparc passes floats in int registers, when loading to fpu register
  1228. we need a temp }
  1229. tg.GetTemp(list,TCGSize2Size[tvarsym(hp.parasym).localloc.size],tt_normal,tempref);
  1230. href:=tempref;
  1231. while assigned(paraloc) do
  1232. begin
  1233. unget_para(paraloc^);
  1234. gen_load_ref(paraloc^,href);
  1235. inc(href.offset,TCGSize2Size[paraloc^.size]);
  1236. paraloc:=paraloc^.next;
  1237. end;
  1238. cg.a_loadfpu_ref_reg(list,tvarsym(hp.parasym).localloc.size,tempref,tvarsym(hp.parasym).localloc.register);
  1239. tg.UnGetTemp(list,tempref);
  1240. {$else sparc}
  1241. unget_para(paraloc^);
  1242. gen_load_reg(paraloc^,tvarsym(hp.parasym).localloc.register);
  1243. if assigned(paraloc^.next) then
  1244. internalerror(200410109);
  1245. {$endif sparc}
  1246. end;
  1247. LOC_CMMREGISTER :
  1248. begin
  1249. unget_para(paraloc^);
  1250. gen_load_reg(paraloc^,tvarsym(hp.parasym).localloc.register);
  1251. if assigned(paraloc^.next) then
  1252. internalerror(200410108);
  1253. end;
  1254. end;
  1255. hp:=tparaitem(hp.next);
  1256. end;
  1257. { generate copies of call by value parameters, must be done before
  1258. the initialization and body is parsed because the refcounts are
  1259. incremented using the local copies }
  1260. current_procinfo.procdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
  1261. end;
  1262. procedure gen_initialize_code(list:TAAsmoutput);
  1263. begin
  1264. { initialize local data like ansistrings }
  1265. case current_procinfo.procdef.proctypeoption of
  1266. potype_unitinit:
  1267. begin
  1268. { this is also used for initialization of variables in a
  1269. program which does not have a globalsymtable }
  1270. if assigned(current_module.globalsymtable) then
  1271. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1272. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1273. end;
  1274. { units have seperate code for initilization and finalization }
  1275. potype_unitfinalize: ;
  1276. { program init/final is generated in separate procedure }
  1277. potype_proginit: ;
  1278. else
  1279. current_procinfo.procdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1280. end;
  1281. { initialisizes temp. ansi/wide string data }
  1282. inittempvariables(list);
  1283. { initialize ansi/widesstring para's }
  1284. current_procinfo.procdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
  1285. { initialize regvars in staticsymtable with 0, like .bss }
  1286. if current_procinfo.procdef.localst.symtabletype=staticsymtable then
  1287. current_procinfo.procdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_regvars,list);
  1288. {$ifdef OLDREGVARS}
  1289. load_regvars(list,nil);
  1290. {$endif OLDREGVARS}
  1291. end;
  1292. procedure gen_finalize_code(list:TAAsmoutput);
  1293. begin
  1294. {$ifdef OLDREGVARS}
  1295. cleanup_regvars(list);
  1296. {$endif OLDREGVARS}
  1297. { finalize temporary data }
  1298. finalizetempvariables(list);
  1299. { finalize local data like ansistrings}
  1300. case current_procinfo.procdef.proctypeoption of
  1301. potype_unitfinalize:
  1302. begin
  1303. { this is also used for initialization of variables in a
  1304. program which does not have a globalsymtable }
  1305. if assigned(current_module.globalsymtable) then
  1306. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_static_data,list);
  1307. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_static_data,list);
  1308. end;
  1309. { units/progs have separate code for initialization and finalization }
  1310. potype_unitinit: ;
  1311. { program init/final is generated in separate procedure }
  1312. potype_proginit: ;
  1313. else
  1314. current_procinfo.procdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_local_vars,list);
  1315. end;
  1316. { finalize paras data }
  1317. if assigned(current_procinfo.procdef.parast) then
  1318. current_procinfo.procdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
  1319. end;
  1320. procedure gen_entry_code(list:TAAsmoutput);
  1321. var
  1322. href : treference;
  1323. paraloc1,
  1324. paraloc2 : tcgpara;
  1325. hp : tused_unit;
  1326. begin
  1327. paraloc1.init;
  1328. paraloc2.init;
  1329. { the actual profile code can clobber some registers,
  1330. therefore if the context must be saved, do it before
  1331. the actual call to the profile code
  1332. }
  1333. if (cs_profile in aktmoduleswitches) and
  1334. not(po_assembler in current_procinfo.procdef.procoptions) then
  1335. begin
  1336. { non-win32 can call mcout even in main }
  1337. if not (target_info.system in [system_i386_win32,system_i386_wdosx]) or
  1338. not (current_procinfo.procdef.proctypeoption=potype_proginit) then
  1339. begin
  1340. cg.alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_cdecl));
  1341. cg.g_profilecode(list);
  1342. cg.dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_cdecl));
  1343. end;
  1344. end;
  1345. { call startup helpers from main program }
  1346. if (current_procinfo.procdef.proctypeoption=potype_proginit) then
  1347. begin
  1348. { initialize profiling for win32 }
  1349. if (target_info.system in [system_i386_win32,system_i386_wdosx]) and
  1350. (cs_profile in aktmoduleswitches) then
  1351. begin
  1352. reference_reset_symbol(href,objectlibrary.newasmsymbol('etext',AB_EXTERNAL,AT_DATA),0);
  1353. paramanager.getintparaloc(pocall_default,1,paraloc1);
  1354. paramanager.getintparaloc(pocall_default,2,paraloc2);
  1355. paramanager.allocparaloc(list,paraloc2);
  1356. cg.a_paramaddr_ref(list,href,paraloc2);
  1357. reference_reset_symbol(href,objectlibrary.newasmsymbol('__image_base__',AB_EXTERNAL,AT_DATA),0);
  1358. paramanager.allocparaloc(list,paraloc1);
  1359. cg.a_paramaddr_ref(list,href,paraloc1);
  1360. paramanager.freeparaloc(list,paraloc2);
  1361. paramanager.freeparaloc(list,paraloc1);
  1362. cg.alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_cdecl));
  1363. cg.a_call_name(list,'_monstartup');
  1364. cg.dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_cdecl));
  1365. end;
  1366. { initialize units }
  1367. cg.alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1368. cg.a_call_name(list,'FPC_INITIALIZEUNITS');
  1369. cg.dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1370. {$ifdef GDB}
  1371. if (cs_debuginfo in aktmoduleswitches) then
  1372. if target_info.system <> system_powerpc_macos then
  1373. begin
  1374. { include reference to all debuginfo sections of used units }
  1375. hp:=tused_unit(usedunits.first);
  1376. while assigned(hp) do
  1377. begin
  1378. If (hp.u.flags and uf_has_debuginfo)=uf_has_debuginfo then
  1379. current_procinfo.aktlocaldata.concat(Tai_const.Createname(make_mangledname('DEBUGINFO',hp.u.globalsymtable,''),AT_DATA,0));
  1380. hp:=tused_unit(hp.next);
  1381. end;
  1382. { include reference to debuginfo for this program }
  1383. current_procinfo.aktlocaldata.concat(Tai_const.Createname(make_mangledname('DEBUGINFO',current_module.localsymtable,''),AT_DATA,0));
  1384. end;
  1385. {$endif GDB}
  1386. end;
  1387. {$ifdef GDB}
  1388. if (cs_debuginfo in aktmoduleswitches) then
  1389. list.concat(Tai_force_line.Create);
  1390. {$endif GDB}
  1391. {$ifdef OLDREGVARS}
  1392. load_regvars(list,nil);
  1393. {$endif OLDREGVARS}
  1394. paraloc1.done;
  1395. paraloc2.done;
  1396. end;
  1397. procedure gen_exit_code(list:TAAsmoutput);
  1398. begin
  1399. { call __EXIT for main program }
  1400. if (not DLLsource) and
  1401. (current_procinfo.procdef.proctypeoption=potype_proginit) then
  1402. cg.a_call_name(list,'FPC_DO_EXIT');
  1403. end;
  1404. {****************************************************************************
  1405. Entry/Exit
  1406. ****************************************************************************}
  1407. procedure gen_proc_symbol(list:Taasmoutput);
  1408. var
  1409. hs : string;
  1410. begin
  1411. { add symbol entry point as well as debug information }
  1412. { will be inserted in front of the rest of this list. }
  1413. { Insert alignment and assembler names }
  1414. { Align, gprof uses 16 byte granularity }
  1415. if (cs_profile in aktmoduleswitches) then
  1416. list.concat(Tai_align.create(16))
  1417. else
  1418. list.concat(Tai_align.create(aktalignment.procalign));
  1419. {$ifdef GDB}
  1420. if (cs_debuginfo in aktmoduleswitches) then
  1421. begin
  1422. if (po_public in current_procinfo.procdef.procoptions) then
  1423. Tprocsym(current_procinfo.procdef.procsym).is_global:=true;
  1424. current_procinfo.procdef.concatstabto(list);
  1425. Tprocsym(current_procinfo.procdef.procsym).isstabwritten:=true;
  1426. end;
  1427. {$endif GDB}
  1428. repeat
  1429. hs:=current_procinfo.procdef.aliasnames.getfirst;
  1430. if hs='' then
  1431. break;
  1432. {$ifdef GDB}
  1433. if (cs_debuginfo in aktmoduleswitches) and
  1434. target_info.use_function_relative_addresses then
  1435. list.concat(Tai_stab_function_name.create(strpnew(hs)));
  1436. {$endif GDB}
  1437. if (cs_profile in aktmoduleswitches) or
  1438. (po_public in current_procinfo.procdef.procoptions) then
  1439. list.concat(Tai_symbol.createname_global(hs,AT_FUNCTION,0))
  1440. else
  1441. list.concat(Tai_symbol.createname(hs,AT_FUNCTION,0));
  1442. until false;
  1443. end;
  1444. procedure gen_proc_symbol_end(list:Taasmoutput);
  1445. {$ifdef GDB}
  1446. var
  1447. stabsendlabel : tasmlabel;
  1448. mangled_length : longint;
  1449. p : pchar;
  1450. {$endif GDB}
  1451. begin
  1452. list.concat(Tai_symbol_end.Createname(current_procinfo.procdef.mangledname));
  1453. {$ifdef GDB}
  1454. if (cs_debuginfo in aktmoduleswitches) then
  1455. begin
  1456. objectlibrary.getlabel(stabsendlabel);
  1457. cg.a_label(list,stabsendlabel);
  1458. { define calling EBP as pseudo local var PM }
  1459. { this enables test if the function is a local one !! }
  1460. {if assigned(current_procinfo.parent) and
  1461. (current_procinfo.procdef.parast.symtablelevel>normal_function_level) then
  1462. list.concat(Tai_stabs.Create(strpnew(
  1463. '"parent_ebp:'+tstoreddef(voidpointertype.def).numberstring+'",'+
  1464. tostr(N_LSYM)+',0,0,'+tostr(current_procinfo.parent_framepointer_offset)))); }
  1465. if assigned(current_procinfo.procdef.funcretsym) and
  1466. (tvarsym(current_procinfo.procdef.funcretsym).refs>0) then
  1467. begin
  1468. if tvarsym(current_procinfo.procdef.funcretsym).localloc.loc=LOC_REFERENCE then
  1469. begin
  1470. {$warning Need to add gdb support for ret in param register calling}
  1471. if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption) then
  1472. begin
  1473. list.concat(Tai_stabs.Create(strpnew(
  1474. '"'+current_procinfo.procdef.procsym.name+':X*'+tstoreddef(current_procinfo.procdef.rettype.def).numberstring+'",'+
  1475. tostr(N_tsym)+',0,0,'+tostr(tvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset))));
  1476. if (m_result in aktmodeswitches) then
  1477. list.concat(Tai_stabs.Create(strpnew(
  1478. '"RESULT:X*'+tstoreddef(current_procinfo.procdef.rettype.def).numberstring+'",'+
  1479. tostr(N_tsym)+',0,0,'+tostr(tvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset))))
  1480. end
  1481. else
  1482. begin
  1483. list.concat(Tai_stabs.Create(strpnew(
  1484. '"'+current_procinfo.procdef.procsym.name+':X'+tstoreddef(current_procinfo.procdef.rettype.def).numberstring+'",'+
  1485. tostr(N_tsym)+',0,0,'+tostr(tvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset))));
  1486. if (m_result in aktmodeswitches) then
  1487. list.concat(Tai_stabs.Create(strpnew(
  1488. '"RESULT:X'+tstoreddef(current_procinfo.procdef.rettype.def).numberstring+'",'+
  1489. tostr(N_tsym)+',0,0,'+tostr(tvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset))));
  1490. end;
  1491. end;
  1492. end;
  1493. mangled_length:=length(current_procinfo.procdef.mangledname);
  1494. getmem(p,2*mangled_length+50);
  1495. strpcopy(p,'192,0,0,');
  1496. strpcopy(strend(p),current_procinfo.procdef.mangledname);
  1497. if (target_info.use_function_relative_addresses) then
  1498. begin
  1499. strpcopy(strend(p),'-');
  1500. strpcopy(strend(p),current_procinfo.procdef.mangledname);
  1501. end;
  1502. list.concat(Tai_stabn.Create(strnew(p)));
  1503. {List.concat(Tai_stabn.Create(strpnew('192,0,0,'
  1504. +current_procinfo.procdef.mangledname))));
  1505. p[0]:='2';p[1]:='2';p[2]:='4';
  1506. strpcopy(strend(p),'_end');}
  1507. strpcopy(p,'224,0,0,'+stabsendlabel.name);
  1508. if (target_info.use_function_relative_addresses) then
  1509. begin
  1510. strpcopy(strend(p),'-');
  1511. strpcopy(strend(p),current_procinfo.procdef.mangledname);
  1512. end;
  1513. list.concatlist(withdebuglist);
  1514. list.concat(Tai_stabn.Create(strnew(p)));
  1515. { strpnew('224,0,0,'
  1516. +current_procinfo.procdef.mangledname+'_end'))));}
  1517. freemem(p,2*mangled_length+50);
  1518. end;
  1519. {$endif GDB}
  1520. end;
  1521. procedure gen_proc_entry_code(list:Taasmoutput);
  1522. var
  1523. hitemp,
  1524. lotemp,
  1525. stackframe : longint;
  1526. check : boolean;
  1527. paraloc1 : tcgpara;
  1528. href : treference;
  1529. begin
  1530. paraloc1.init;
  1531. { generate call frame marker for dwarf call frame info }
  1532. dwarfcfi.start_frame(list);
  1533. { allocate temp for saving the argument used when
  1534. stack checking uses a register for pushing the stackframe size }
  1535. check:=(cs_check_stack in aktlocalswitches) and (current_procinfo.procdef.proctypeoption<>potype_proginit);
  1536. if check then
  1537. begin
  1538. { Allocate tempspace to store register parameter than
  1539. is destroyed when calling stackchecking code }
  1540. paramanager.getintparaloc(pocall_default,1,paraloc1);
  1541. if paraloc1.location^.loc=LOC_REGISTER then
  1542. tg.GetTemp(list,sizeof(aint),tt_normal,href);
  1543. end;
  1544. { Calculate size of stackframe }
  1545. stackframe:=current_procinfo.calc_stackframe_size;
  1546. { All temps are know, write offsets used for information }
  1547. if (cs_asm_source in aktglobalswitches) then
  1548. begin
  1549. if tg.direction>0 then
  1550. begin
  1551. lotemp:=current_procinfo.tempstart;
  1552. hitemp:=tg.lasttemp;
  1553. end
  1554. else
  1555. begin
  1556. lotemp:=tg.lasttemp;
  1557. hitemp:=current_procinfo.tempstart;
  1558. end;
  1559. list.concat(Tai_comment.Create(strpnew('Temps allocated between '+std_regname(current_procinfo.framepointer)+
  1560. tostr_with_plus(lotemp)+' and '+std_regname(current_procinfo.framepointer)+tostr_with_plus(hitemp))));
  1561. end;
  1562. { generate target specific proc entry code }
  1563. cg.g_proc_entry(list,stackframe,(po_nostackframe in current_procinfo.procdef.procoptions));
  1564. { Add stack checking code? }
  1565. if check then
  1566. begin
  1567. { The tempspace to store original register is already
  1568. allocated above before the stackframe size is calculated. }
  1569. if paraloc1.location^.loc=LOC_REGISTER then
  1570. cg.a_load_reg_ref(list,OS_INT,OS_INT,paraloc1.location^.register,href);
  1571. paramanager.allocparaloc(list,paraloc1);
  1572. cg.a_param_const(list,OS_INT,stackframe,paraloc1);
  1573. paramanager.freeparaloc(list,paraloc1);
  1574. cg.alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1575. cg.a_call_name(list,'FPC_STACKCHECK');
  1576. cg.dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1577. if paraloc1.location^.loc=LOC_REGISTER then
  1578. begin
  1579. cg.a_load_ref_reg(list,OS_INT,OS_INT,href,paraloc1.location^.register);
  1580. tg.UnGetTemp(list,href);
  1581. end;
  1582. end;
  1583. paraloc1.done;
  1584. end;
  1585. procedure gen_proc_exit_code(list:Taasmoutput);
  1586. var
  1587. parasize : longint;
  1588. begin
  1589. { c style clearstack does not need to remove parameters from the stack, only the
  1590. return value when it was pushed by arguments }
  1591. if current_procinfo.procdef.proccalloption in clearstack_pocalls then
  1592. begin
  1593. parasize:=0;
  1594. if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption) then
  1595. inc(parasize,sizeof(aint));
  1596. end
  1597. else
  1598. parasize:=current_procinfo.para_stack_size;
  1599. { generate target specific proc exit code }
  1600. cg.g_proc_exit(list,parasize,(po_nostackframe in current_procinfo.procdef.procoptions));
  1601. { release return registers, needed for optimizer }
  1602. paramanager.freeparaloc(list,current_procinfo.procdef.funcret_paraloc[calleeside]);
  1603. { end of frame marker for call frame info }
  1604. dwarfcfi.end_frame(list);
  1605. end;
  1606. procedure gen_save_used_regs(list:TAAsmoutput);
  1607. begin
  1608. { Pure assembler routines need to save the registers themselves }
  1609. if (po_assembler in current_procinfo.procdef.procoptions) then
  1610. exit;
  1611. { for the save all registers we can simply use a pusha,popa which
  1612. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1613. if (po_saveregisters in current_procinfo.procdef.procoptions) then
  1614. cg.g_save_all_registers(list)
  1615. else
  1616. if current_procinfo.procdef.proccalloption in savestdregs_pocalls then
  1617. cg.g_save_standard_registers(list);
  1618. end;
  1619. procedure gen_restore_used_regs(list:TAAsmoutput;const funcretparaloc:tcgpara);
  1620. begin
  1621. { Pure assembler routines need to save the registers themselves }
  1622. if (po_assembler in current_procinfo.procdef.procoptions) then
  1623. exit;
  1624. { for the save all registers we can simply use a pusha,popa which
  1625. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1626. if (po_saveregisters in current_procinfo.procdef.procoptions) then
  1627. cg.g_restore_all_registers(list,funcretparaloc)
  1628. else
  1629. if current_procinfo.procdef.proccalloption in savestdregs_pocalls then
  1630. cg.g_restore_standard_registers(list);
  1631. end;
  1632. {****************************************************************************
  1633. Const Data
  1634. ****************************************************************************}
  1635. procedure insertconstdata(sym : ttypedconstsym);
  1636. { this does not affect the local stack space, since all
  1637. typed constansts and initialized variables are always
  1638. put in the .data / .rodata section
  1639. }
  1640. var
  1641. storefilepos : tfileposinfo;
  1642. curconstsegment : taasmoutput;
  1643. l : longint;
  1644. begin
  1645. storefilepos:=aktfilepos;
  1646. aktfilepos:=sym.fileinfo;
  1647. if sym.is_writable then
  1648. curconstsegment:=datasegment
  1649. else
  1650. curconstsegment:=consts;
  1651. l:=sym.getsize;
  1652. { insert cut for smartlinking or alignment }
  1653. maybe_new_object_file(curconstSegment);
  1654. new_section(curconstSegment,sec_rodata,lower(sym.mangledname),const_align(l));
  1655. if (sym.owner.symtabletype=globalsymtable) or
  1656. maybe_smartlink_symbol or
  1657. (assigned(current_procinfo) and
  1658. (current_procinfo.procdef.proccalloption=pocall_inline)) or
  1659. DLLSource then
  1660. curconstSegment.concat(Tai_symbol.Createname_global(sym.mangledname,AT_DATA,l))
  1661. else
  1662. curconstSegment.concat(Tai_symbol.Createname(sym.mangledname,AT_DATA,l));
  1663. aktfilepos:=storefilepos;
  1664. end;
  1665. procedure insertbssdata(sym : tvarsym);
  1666. var
  1667. l,varalign : longint;
  1668. storefilepos : tfileposinfo;
  1669. begin
  1670. storefilepos:=aktfilepos;
  1671. aktfilepos:=sym.fileinfo;
  1672. l:=sym.getsize;
  1673. if (vo_is_thread_var in sym.varoptions) then
  1674. inc(l,sizeof(aint));
  1675. varalign:=var_align(l);
  1676. maybe_new_object_file(bssSegment);
  1677. new_section(bssSegment,sec_bss,lower(sym.mangledname),varalign);
  1678. if (sym.owner.symtabletype=globalsymtable) or
  1679. maybe_smartlink_symbol or
  1680. DLLSource or
  1681. (assigned(current_procinfo) and
  1682. (current_procinfo.procdef.proccalloption=pocall_inline)) or
  1683. (vo_is_exported in sym.varoptions) or
  1684. (vo_is_C_var in sym.varoptions) then
  1685. bssSegment.concat(Tai_datablock.Create_global(sym.mangledname,l))
  1686. else
  1687. bssSegment.concat(Tai_datablock.Create(sym.mangledname,l));
  1688. aktfilepos:=storefilepos;
  1689. end;
  1690. procedure gen_alloc_symtable(list:TAAsmoutput;st:tsymtable);
  1691. var
  1692. sym : tsym;
  1693. isaddr : boolean;
  1694. cgsize : tcgsize;
  1695. begin
  1696. sym:=tsym(st.symindex.first);
  1697. while assigned(sym) do
  1698. begin
  1699. if (sym.typ=varsym) then
  1700. begin
  1701. with tvarsym(sym) do
  1702. begin
  1703. { Parameters passed to assembler procedures need to be kept
  1704. in the original location }
  1705. if (st.symtabletype=parasymtable) and
  1706. (po_assembler in current_procinfo.procdef.procoptions) then
  1707. begin
  1708. paraitem.paraloc[calleeside].get_location(localloc);
  1709. end
  1710. else
  1711. begin
  1712. isaddr:=(st.symtabletype=parasymtable) and
  1713. paramanager.push_addr_param(varspez,vartype.def,current_procinfo.procdef.proccalloption);
  1714. if isaddr then
  1715. cgsize:=OS_ADDR
  1716. else
  1717. cgsize:=def_cgsize(vartype.def);
  1718. {$ifndef OLDREGVARS}
  1719. { When there is assembler code we can't use regvars }
  1720. if is_regvar then
  1721. begin
  1722. localloc.size:=cgsize;
  1723. case varregable of
  1724. vr_intreg :
  1725. begin
  1726. localloc.loc:=LOC_CREGISTER;
  1727. {$ifndef cpu64bit}
  1728. if cgsize in [OS_64,OS_S64] then
  1729. begin
  1730. localloc.registerlow:=cg.getintregister(list,OS_32);
  1731. localloc.registerhigh:=cg.getintregister(list,OS_32);
  1732. end
  1733. else
  1734. {$endif cpu64bit}
  1735. localloc.register:=cg.getintregister(list,cgsize);
  1736. end;
  1737. vr_fpureg :
  1738. begin
  1739. localloc.loc:=LOC_CFPUREGISTER;
  1740. localloc.register:=cg.getfpuregister(list,cgsize);
  1741. end;
  1742. vr_mmreg :
  1743. begin
  1744. localloc.loc:=LOC_CMMREGISTER;
  1745. localloc.register:=cg.getmmregister(list,cgsize);
  1746. end;
  1747. else
  1748. internalerror(2004101010);
  1749. end;
  1750. { Allocate register already, to prevent first allocation to be
  1751. inside a loop }
  1752. cg.a_reg_sync(list,localloc.register);
  1753. end
  1754. else
  1755. {$endif NOT OLDREGVARS}
  1756. begin
  1757. localloc.loc:=LOC_REFERENCE;
  1758. localloc.size:=cgsize;
  1759. case st.symtabletype of
  1760. parasymtable :
  1761. begin
  1762. { Reuse the parameter location for values to are at a single location on the stack }
  1763. if (paraitem.paraloc[calleeside].is_simple_reference) then
  1764. begin
  1765. reference_reset_base(localloc.reference,paraitem.paraloc[calleeside].location^.reference.index,
  1766. paraitem.paraloc[calleeside].location^.reference.offset);
  1767. end
  1768. else
  1769. begin
  1770. if isaddr then
  1771. tg.GetLocal(list,sizeof(aint),voidpointertype.def,localloc.reference)
  1772. else
  1773. tg.GetLocal(list,getsize,vartype.def,localloc.reference);
  1774. end;
  1775. end;
  1776. localsymtable,
  1777. stt_exceptsymtable :
  1778. begin
  1779. tg.GetLocal(list,getsize,vartype.def,localloc.reference);
  1780. end;
  1781. staticsymtable :
  1782. begin
  1783. { PIC, DLL and Threadvar need extra code and are handled in ncgld }
  1784. if not(cs_create_pic in aktmoduleswitches) and
  1785. not(vo_is_dll_var in varoptions) and
  1786. not(vo_is_thread_var in varoptions) then
  1787. reference_reset_symbol(localloc.reference,objectlibrary.newasmsymbol(mangledname,AB_EXTERNAL,AT_DATA),0);
  1788. end;
  1789. else
  1790. internalerror(200410103);
  1791. end;
  1792. end;
  1793. end;
  1794. if cs_asm_source in aktglobalswitches then
  1795. begin
  1796. case localloc.loc of
  1797. LOC_REGISTER,
  1798. LOC_CREGISTER :
  1799. begin
  1800. if (cs_no_regalloc in aktglobalswitches) then
  1801. list.concat(Tai_comment.Create(strpnew('Var '+realname+' located in register '+
  1802. std_regname(localloc.register))))
  1803. else
  1804. list.concat(Tai_comment.Create(strpnew('Var '+realname+' located in register')));
  1805. end;
  1806. LOC_REFERENCE :
  1807. begin
  1808. if not assigned(localloc.reference.symbol) then
  1809. list.concat(Tai_comment.Create(strpnew('Var '+realname+' located at '+
  1810. std_regname(localloc.reference.base)+tostr_with_plus(localloc.reference.offset))));
  1811. end;
  1812. end;
  1813. end;
  1814. end;
  1815. end;
  1816. sym:=tsym(sym.indexnext);
  1817. end;
  1818. end;
  1819. procedure gen_free_symtable(list:TAAsmoutput;st:tsymtable);
  1820. var
  1821. sym : tsym;
  1822. begin
  1823. sym:=tsym(st.symindex.first);
  1824. while assigned(sym) do
  1825. begin
  1826. if (sym.typ=varsym) then
  1827. begin
  1828. with tvarsym(sym) do
  1829. begin
  1830. { Note: We need to keep the data available in memory
  1831. for the sub procedures that can access local data
  1832. in the parent procedures }
  1833. case localloc.loc of
  1834. LOC_CREGISTER :
  1835. cg.a_reg_sync(list,localloc.register);
  1836. LOC_REFERENCE :
  1837. begin
  1838. case st.symtabletype of
  1839. localsymtable,
  1840. parasymtable,
  1841. stt_exceptsymtable :
  1842. tg.Ungetlocal(list,localloc.reference);
  1843. end;
  1844. end;
  1845. end;
  1846. end;
  1847. end;
  1848. sym:=tsym(sym.indexnext);
  1849. end;
  1850. end;
  1851. procedure gen_alloc_inline_parast(list:TAAsmoutput;pd:tprocdef);
  1852. var
  1853. sym : tsym;
  1854. calleeparaloc,
  1855. callerparaloc : pcgparalocation;
  1856. begin
  1857. if (po_assembler in pd.procoptions) then
  1858. exit;
  1859. sym:=tsym(pd.parast.symindex.first);
  1860. while assigned(sym) do
  1861. begin
  1862. if sym.typ=varsym then
  1863. begin
  1864. with tvarsym(sym) do
  1865. begin
  1866. { for localloc <> LOC_REFERENCE, we need regvar support inside inlined procedures }
  1867. localloc.loc:=LOC_REFERENCE;
  1868. localloc.size:=int_cgsize(paramanager.push_size(varspez,vartype.def,pocall_inline));
  1869. tg.GetLocal(list,tcgsize2size[localloc.size],vartype.def,localloc.reference);
  1870. calleeparaloc:=paraitem.paraloc[calleeside].location;
  1871. callerparaloc:=paraitem.paraloc[callerside].location;
  1872. while assigned(calleeparaloc) do
  1873. begin
  1874. if not assigned(callerparaloc) then
  1875. internalerror(200408281);
  1876. if calleeparaloc^.loc<>callerparaloc^.loc then
  1877. internalerror(200408282);
  1878. case calleeparaloc^.loc of
  1879. LOC_FPUREGISTER:
  1880. begin
  1881. calleeparaloc^.register:=cg.getfpuregister(list,calleeparaloc^.size);
  1882. callerparaloc^.register:=calleeparaloc^.register;
  1883. end;
  1884. LOC_REGISTER:
  1885. begin
  1886. calleeparaloc^.register:=cg.getintregister(list,calleeparaloc^.size);
  1887. callerparaloc^.register:=calleeparaloc^.register;
  1888. end;
  1889. LOC_MMREGISTER:
  1890. begin
  1891. calleeparaloc^.register:=cg.getmmregister(list,calleeparaloc^.size);
  1892. callerparaloc^.register:=calleeparaloc^.register;
  1893. end;
  1894. LOC_REFERENCE:
  1895. begin
  1896. calleeparaloc^.reference.offset := localloc.reference.offset;
  1897. calleeparaloc^.reference.index := localloc.reference.base;
  1898. callerparaloc^.reference.offset := localloc.reference.offset;
  1899. callerparaloc^.reference.index := localloc.reference.base;
  1900. end;
  1901. end;
  1902. calleeparaloc:=calleeparaloc^.next;
  1903. callerparaloc:=callerparaloc^.next;
  1904. end;
  1905. if cs_asm_source in aktglobalswitches then
  1906. begin
  1907. case localloc.loc of
  1908. LOC_REFERENCE :
  1909. list.concat(Tai_comment.Create(strpnew('Para '+realname+' allocated at '+
  1910. std_regname(localloc.reference.base)+tostr_with_plus(localloc.reference.offset))));
  1911. end;
  1912. end;
  1913. end;
  1914. end;
  1915. sym:=tsym(sym.indexnext);
  1916. end;
  1917. end;
  1918. procedure gen_alloc_inline_funcret(list:TAAsmoutput;pd:tprocdef);
  1919. var
  1920. calleeparaloc,
  1921. callerparaloc : pcgparalocation;
  1922. begin
  1923. if not assigned(pd.funcretsym) or
  1924. (po_assembler in pd.procoptions) then
  1925. exit;
  1926. { for localloc <> LOC_REFERENCE, we need regvar support inside inlined procedures }
  1927. with tvarsym(pd.funcretsym) do
  1928. begin
  1929. localloc.loc:=LOC_REFERENCE;
  1930. localloc.size:=int_cgsize(paramanager.push_size(varspez,vartype.def,pocall_inline));
  1931. tg.GetLocal(list,tcgsize2size[localloc.size],vartype.def,localloc.reference);
  1932. calleeparaloc:=pd.funcret_paraloc[calleeside].location;
  1933. callerparaloc:=pd.funcret_paraloc[callerside].location;
  1934. while assigned(calleeparaloc) do
  1935. begin
  1936. if not assigned(callerparaloc) then
  1937. internalerror(200408281);
  1938. if calleeparaloc^.loc<>callerparaloc^.loc then
  1939. internalerror(200408282);
  1940. case calleeparaloc^.loc of
  1941. LOC_FPUREGISTER:
  1942. begin
  1943. calleeparaloc^.register:=cg.getfpuregister(list,calleeparaloc^.size);
  1944. callerparaloc^.register:=calleeparaloc^.register;
  1945. end;
  1946. LOC_REGISTER:
  1947. begin
  1948. calleeparaloc^.register:=cg.getintregister(list,calleeparaloc^.size);
  1949. callerparaloc^.register:=calleeparaloc^.register;
  1950. end;
  1951. LOC_MMREGISTER:
  1952. begin
  1953. calleeparaloc^.register:=cg.getmmregister(list,calleeparaloc^.size);
  1954. callerparaloc^.register:=calleeparaloc^.register;
  1955. end;
  1956. LOC_REFERENCE:
  1957. begin
  1958. calleeparaloc^.reference.offset := localloc.reference.offset;
  1959. calleeparaloc^.reference.index := localloc.reference.base;
  1960. callerparaloc^.reference.offset := localloc.reference.offset;
  1961. callerparaloc^.reference.index := localloc.reference.base;
  1962. end;
  1963. end;
  1964. calleeparaloc:=calleeparaloc^.next;
  1965. callerparaloc:=callerparaloc^.next;
  1966. end;
  1967. if cs_asm_source in aktglobalswitches then
  1968. begin
  1969. case localloc.loc of
  1970. LOC_REFERENCE :
  1971. list.concat(Tai_comment.Create(strpnew('Funcret '+realname+' allocated at '+
  1972. std_regname(localloc.reference.base)+tostr_with_plus(localloc.reference.offset))));
  1973. end;
  1974. end;
  1975. end;
  1976. end;
  1977. { persistent rtti generation }
  1978. procedure generate_rtti(p:Ttypesym);
  1979. var
  1980. rsym : trttisym;
  1981. def : tstoreddef;
  1982. begin
  1983. { rtti can only be generated for classes that are always typesyms }
  1984. def:=tstoreddef(ttypesym(p).restype.def);
  1985. { there is an error, skip rtti info }
  1986. if (def.deftype=errordef) or (Errorcount>0) then
  1987. exit;
  1988. { only create rtti once for each definition }
  1989. if not(df_has_rttitable in def.defoptions) then
  1990. begin
  1991. { definition should be in the same symtable as the symbol }
  1992. if p.owner<>def.owner then
  1993. internalerror(200108262);
  1994. { create rttisym }
  1995. rsym:=trttisym.create(p.name,fullrtti);
  1996. p.owner.insert(rsym);
  1997. { register rttisym in definition }
  1998. include(def.defoptions,df_has_rttitable);
  1999. def.rttitablesym:=rsym;
  2000. { write rtti data }
  2001. def.write_child_rtti_data(fullrtti);
  2002. maybe_new_object_file(rttilist);
  2003. new_section(rttilist,sec_rodata,rsym.get_label.name,const_align(sizeof(aint)));
  2004. rttiList.concat(Tai_symbol.Create_global(rsym.get_label,0));
  2005. def.write_rtti_data(fullrtti);
  2006. rttiList.concat(Tai_symbol_end.Create(rsym.get_label));
  2007. end;
  2008. end;
  2009. { persistent init table generation }
  2010. procedure generate_inittable(p:tsym);
  2011. var
  2012. rsym : trttisym;
  2013. def : tstoreddef;
  2014. begin
  2015. { anonymous types are also allowed for records that can be varsym }
  2016. case p.typ of
  2017. typesym :
  2018. def:=tstoreddef(ttypesym(p).restype.def);
  2019. varsym :
  2020. def:=tstoreddef(tvarsym(p).vartype.def);
  2021. else
  2022. internalerror(200108263);
  2023. end;
  2024. { only create inittable once for each definition }
  2025. if not(df_has_inittable in def.defoptions) then
  2026. begin
  2027. { definition should be in the same symtable as the symbol }
  2028. if p.owner<>def.owner then
  2029. internalerror(200108264);
  2030. { create rttisym }
  2031. rsym:=trttisym.create(p.name,initrtti);
  2032. p.owner.insert(rsym);
  2033. { register rttisym in definition }
  2034. include(def.defoptions,df_has_inittable);
  2035. def.inittablesym:=rsym;
  2036. { write inittable data }
  2037. def.write_child_rtti_data(initrtti);
  2038. maybe_new_object_file(rttilist);
  2039. new_section(rttilist,sec_rodata,rsym.get_label.name,const_align(sizeof(aint)));
  2040. rttiList.concat(Tai_symbol.Create_global(rsym.get_label,0));
  2041. def.write_rtti_data(initrtti);
  2042. rttiList.concat(Tai_symbol_end.Create(rsym.get_label));
  2043. end;
  2044. end;
  2045. end.
  2046. {
  2047. $Log$
  2048. Revision 1.229 2004-10-15 09:14:17 mazen
  2049. - remove $IFDEF DELPHI and related code
  2050. - remove $IFDEF FPCPROCVAR and related code
  2051. Revision 1.228 2004/10/14 17:54:06 peter
  2052. * add reg_sync when regvars are allocated to fix first use in
  2053. loop
  2054. Revision 1.227 2004/10/13 21:12:51 peter
  2055. * -Or fixes for open array
  2056. Revision 1.226 2004/10/11 15:48:15 peter
  2057. * small regvar for para fixes
  2058. * function tvarsym.is_regvar added
  2059. * tvarsym.getvaluesize removed, use getsize instead
  2060. Revision 1.225 2004/10/10 21:08:55 peter
  2061. * parameter regvar fixes
  2062. Revision 1.224 2004/10/10 20:51:46 peter
  2063. * fixed sparc compile
  2064. * fixed float regvar loading
  2065. Revision 1.223 2004/10/10 20:22:53 peter
  2066. * symtable allocation rewritten
  2067. * loading of parameters to local temps/regs cleanup
  2068. * regvar support for parameters
  2069. * regvar support for staticsymtable (main body)
  2070. Revision 1.222 2004/10/09 10:51:13 olle
  2071. * Refs to DEBUGINFO_<x> is now not inserted for target MacOS
  2072. Revision 1.221 2004/10/08 20:52:07 florian
  2073. * fixed storage of parameters passed by ref.
  2074. Revision 1.220 2004/10/08 17:09:43 peter
  2075. * tvarsym.varregable added, split vo_regable from varoptions
  2076. Revision 1.219 2004/09/27 15:14:08 peter
  2077. * fix compile for oldregvars
  2078. Revision 1.218 2004/09/26 17:45:30 peter
  2079. * simple regvar support, not yet finished
  2080. Revision 1.217 2004/09/25 14:23:54 peter
  2081. * ungetregister is now only used for cpuregisters, renamed to
  2082. ungetcpuregister
  2083. * renamed (get|unget)explicitregister(s) to ..cpuregister
  2084. * removed location-release/reference_release
  2085. Revision 1.216 2004/09/21 17:25:12 peter
  2086. * paraloc branch merged
  2087. Revision 1.215 2004/09/14 16:33:46 peter
  2088. * release localsymtables when module is compiled
  2089. Revision 1.214 2004/09/13 20:30:05 peter
  2090. * finalize all (also procedure local) typedconst at unit finalization
  2091. Revision 1.213.4.3 2004/09/20 20:46:34 peter
  2092. * register allocation optimized for 64bit loading of parameters
  2093. and return values
  2094. Revision 1.213.4.2 2004/09/17 17:19:26 peter
  2095. * fixed 64 bit unaryminus for sparc
  2096. * fixed 64 bit inlining
  2097. * signness of not operation
  2098. Revision 1.213.4.1 2004/08/31 20:43:06 peter
  2099. * paraloc patch
  2100. Revision 1.213 2004/08/23 11:00:06 michael
  2101. + Patch from Peter to fix debuginfo in constructor.
  2102. Revision 1.212 2004/07/17 13:14:17 jonas
  2103. * don't finalize typed consts (fixes bug3212, but causes memory leak;
  2104. they should be finalized at the end of the module)
  2105. Revision 1.211 2004/07/09 23:41:04 jonas
  2106. * support register parameters for inlined procedures + some inline
  2107. cleanups
  2108. Revision 1.210 2004/07/04 12:24:59 jonas
  2109. * fixed one regvar problem, but regvars are still broken since the dwarf
  2110. merge...
  2111. Revision 1.209 2004/06/29 20:57:21 peter
  2112. * fixed size of exceptbuf
  2113. Revision 1.208 2004/06/20 08:55:29 florian
  2114. * logs truncated
  2115. Revision 1.207 2004/06/16 20:07:08 florian
  2116. * dwarf branch merged
  2117. Revision 1.206 2004/06/01 20:39:33 jonas
  2118. * fixed bug regarding parameters on the ppc (they were allocated twice
  2119. under some circumstances and not at all in others)
  2120. Revision 1.205 2004/05/30 21:41:15 jonas
  2121. * more regvar optimizations in location_force_reg
  2122. Revision 1.204 2004/05/30 21:18:22 jonas
  2123. * some optimizations and associated fixes for better regvar code
  2124. Revision 1.203 2004/05/28 21:14:13 peter
  2125. * first load para's to temps before calling entry code (profile
  2126. }