ncgutil.pas 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014
  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. { Move flags and jump in register to make it less complex }
  635. if p.location.loc in [LOC_FLAGS,LOC_JUMP] then
  636. location_force_reg(exprasmlist,p.location,def_cgsize(p.resulttype.def),false);
  637. { Handle Floating point types differently }
  638. if p.resulttype.def.deftype=floatdef then
  639. begin
  640. case p.location.loc of
  641. LOC_FPUREGISTER,
  642. LOC_CFPUREGISTER:
  643. begin
  644. size:=align(tfloatdef(p.resulttype.def).size,alignment);
  645. inc(pushedparasize,size);
  646. if not inlined then
  647. cg.a_op_const_reg(exprasmlist,OP_SUB,size,STACK_POINTER_REG);
  648. {$ifdef GDB}
  649. if (cs_debuginfo in aktmoduleswitches) and
  650. (exprasmList.first=exprasmList.last) then
  651. exprasmList.concat(Tai_force_line.Create);
  652. {$endif GDB}
  653. { this is the easiest case for inlined !! }
  654. if inlined then
  655. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize)
  656. else
  657. reference_reset_base(href,stack_pointer_reg,0);
  658. cg.a_loadfpu_reg_ref(exprasmlist,
  659. def_cgsize(p.resulttype.def),p.location.register,href);
  660. end;
  661. LOC_REFERENCE,
  662. LOC_CREFERENCE :
  663. begin
  664. sizetopush:=align(p.resulttype.def.size,alignment);
  665. tempreference:=p.location.reference;
  666. inc(tempreference.offset,sizetopush);
  667. while (sizetopush>0) do
  668. begin
  669. if sizetopush>=4 then
  670. begin
  671. cgsize:=OS_32;
  672. inc(pushedparasize,4);
  673. dec(tempreference.offset,4);
  674. dec(sizetopush,4);
  675. end
  676. else
  677. begin
  678. cgsize:=OS_16;
  679. inc(pushedparasize,2);
  680. dec(tempreference.offset,2);
  681. dec(sizetopush,2);
  682. end;
  683. if inlined then
  684. begin
  685. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  686. cg.a_load_ref_ref(exprasmlist,cgsize,tempreference,href);
  687. end
  688. else
  689. cg.a_param_ref(exprasmlist,cgsize,tempreference,locpara);
  690. end;
  691. end;
  692. else
  693. internalerror(200204243);
  694. end;
  695. end
  696. else
  697. begin
  698. { call by value open array ? }
  699. if is_cdecl and
  700. paramanager.push_addr_param(p.resulttype.def,false) then
  701. begin
  702. if not (p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  703. internalerror(200204241);
  704. { push on stack }
  705. size:=align(p.resulttype.def.size,alignment);
  706. inc(pushedparasize,size);
  707. cg.a_op_const_reg(exprasmlist,OP_SUB,size,STACK_POINTER_REG);
  708. reference_reset_base(href,STACK_POINTER_REG,0);
  709. cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false);
  710. end
  711. else
  712. begin
  713. case p.location.loc of
  714. LOC_CONSTANT,
  715. LOC_REGISTER,
  716. LOC_CREGISTER,
  717. LOC_REFERENCE,
  718. LOC_CREFERENCE :
  719. begin
  720. cgsize:=def_cgsize(p.resulttype.def);
  721. if cgsize in [OS_64,OS_S64] then
  722. begin
  723. inc(pushedparasize,8);
  724. if inlined then
  725. begin
  726. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  727. if p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  728. begin
  729. size:=align(p.resulttype.def.size,alignment);
  730. cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false)
  731. end
  732. else
  733. cg64.a_load64_loc_ref(exprasmlist,p.location,href);
  734. end
  735. else
  736. cg64.a_param64_loc(exprasmlist,p.location,locpara);
  737. end
  738. else
  739. begin
  740. case cgsize of
  741. OS_8,OS_S8 :
  742. begin
  743. if alignment=4 then
  744. cgsize:=OS_32
  745. else
  746. cgsize:=OS_16;
  747. end;
  748. OS_16,OS_S16 :
  749. begin
  750. if alignment=4 then
  751. cgsize:=OS_32;
  752. end;
  753. end;
  754. { update register to use to match alignment }
  755. if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  756. begin
  757. hreg:=p.location.register;
  758. p.location.register:=rg.makeregsize(p.location.register,cgsize);
  759. end;
  760. inc(pushedparasize,alignment);
  761. if inlined then
  762. begin
  763. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  764. if p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  765. begin
  766. size:=align(p.resulttype.def.size,alignment);
  767. cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false)
  768. end
  769. else
  770. cg.a_load_loc_ref(exprasmlist,p.location,href);
  771. end
  772. else
  773. cg.a_param_loc(exprasmlist,p.location,locpara);
  774. { restore old register }
  775. if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  776. p.location.register:=hreg;
  777. end;
  778. location_release(exprasmlist,p.location);
  779. end;
  780. {$ifdef SUPPORT_MMX}
  781. LOC_MMXREGISTER,
  782. LOC_CMMXREGISTER:
  783. begin
  784. inc(pushedparasize,8);
  785. if inlined then
  786. begin
  787. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  788. cg.a_loadmm_reg_ref(exprasmlist,p.location.register,href);
  789. end
  790. else
  791. cg.a_parammm_reg(exprasmlist,p.location.register);
  792. end;
  793. {$endif SUPPORT_MMX}
  794. else
  795. internalerror(200204241);
  796. end;
  797. end;
  798. end;
  799. end;
  800. {****************************************************************************
  801. Entry/Exit Code
  802. ****************************************************************************}
  803. procedure copyvalueparas(p : tnamedindexitem;arg:pointer);
  804. var
  805. href1,href2 : treference;
  806. list : taasmoutput;
  807. begin
  808. list:=taasmoutput(arg);
  809. if (tsym(p).typ=varsym) and
  810. (tvarsym(p).varspez=vs_value) and
  811. (paramanager.push_addr_param(tvarsym(p).vartype.def,false)) then
  812. begin
  813. reference_reset_base(href1,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  814. if is_open_array(tvarsym(p).vartype.def) or
  815. is_array_of_const(tvarsym(p).vartype.def) then
  816. cg.g_copyvaluepara_openarray(list,href1,tarraydef(tvarsym(p).vartype.def).elesize)
  817. else
  818. begin
  819. reference_reset_base(href2,procinfo.framepointer,-tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup);
  820. if is_shortstring(tvarsym(p).vartype.def) then
  821. cg.g_copyshortstring(list,href1,href2,tstringdef(tvarsym(p).vartype.def).len,false,true)
  822. else
  823. cg.g_concatcopy(list,href1,href2,tvarsym(p).vartype.def.size,true,true);
  824. end;
  825. end;
  826. end;
  827. procedure removevalueparas(p : tnamedindexitem;arg:pointer);
  828. var
  829. href1 : treference;
  830. list : taasmoutput;
  831. begin
  832. list:=taasmoutput(arg);
  833. if (tsym(p).typ=varsym) and
  834. (tvarsym(p).varspez=vs_value) and
  835. (is_open_array(tvarsym(p).vartype.def) or
  836. is_array_of_const(tvarsym(p).vartype.def)) and
  837. (paramanager.push_addr_param(tvarsym(p).vartype.def,false)) then
  838. begin
  839. reference_reset_base(href1,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  840. cg.g_removevaluepara_openarray(list,href1,tarraydef(tvarsym(p).vartype.def).elesize);
  841. end;
  842. end;
  843. procedure initialize_threadvar(p : tnamedindexitem;arg:pointer);
  844. var
  845. href : treference;
  846. list : taasmoutput;
  847. begin
  848. list:=taasmoutput(arg);
  849. if (tsym(p).typ=varsym) and
  850. (vo_is_thread_var in tvarsym(p).varoptions) then
  851. begin
  852. cg.a_param_const(list,OS_INT,tvarsym(p).getsize,paramanager.getintparaloc(2));
  853. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(p).mangledname),0);
  854. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(1));
  855. rg.saveregvars(list,all_registers);
  856. cg.a_call_name(list,'FPC_INIT_THREADVAR');
  857. end;
  858. end;
  859. { generates the code for initialisation of local data }
  860. procedure initialize_data(p : tnamedindexitem;arg:pointer);
  861. var
  862. href : treference;
  863. list : taasmoutput;
  864. begin
  865. list:=taasmoutput(arg);
  866. if (tsym(p).typ=varsym) and
  867. assigned(tvarsym(p).vartype.def) and
  868. not(is_class(tvarsym(p).vartype.def)) and
  869. tvarsym(p).vartype.def.needs_inittable then
  870. begin
  871. if assigned(procinfo) then
  872. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  873. if tsym(p).owner.symtabletype in [localsymtable,inlinelocalsymtable] then
  874. reference_reset_base(href,procinfo.framepointer,-tvarsym(p).address+tvarsym(p).owner.address_fixup)
  875. else
  876. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(p).mangledname),0);
  877. cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
  878. end;
  879. end;
  880. { generates the code for finalisation of local data }
  881. procedure finalize_data(p : tnamedindexitem;arg:pointer);
  882. var
  883. href : treference;
  884. list : taasmoutput;
  885. begin
  886. list:=taasmoutput(arg);
  887. if (tsym(p).typ=varsym) and
  888. assigned(tvarsym(p).vartype.def) and
  889. not(is_class(tvarsym(p).vartype.def)) and
  890. tvarsym(p).vartype.def.needs_inittable then
  891. begin
  892. if tsym(p).owner.symtabletype in [localsymtable,inlinelocalsymtable] then
  893. reference_reset_base(href,procinfo.framepointer,-tvarsym(p).address+tvarsym(p).owner.address_fixup)
  894. else
  895. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(p).mangledname),0);
  896. cg.g_finalize(list,tvarsym(p).vartype.def,href,false);
  897. end;
  898. end;
  899. { generates the code for incrementing the reference count of parameters and
  900. initialize out parameters }
  901. procedure init_paras(p : tnamedindexitem;arg:pointer);
  902. var
  903. href : treference;
  904. tmpreg : tregister;
  905. list : taasmoutput;
  906. begin
  907. list:=taasmoutput(arg);
  908. if (tsym(p).typ=varsym) and
  909. not is_class(tvarsym(p).vartype.def) and
  910. tvarsym(p).vartype.def.needs_inittable then
  911. begin
  912. case tvarsym(p).varspez of
  913. vs_value :
  914. begin
  915. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  916. if assigned(tvarsym(p).localvarsym) then
  917. reference_reset_base(href,procinfo.framepointer,
  918. -tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup)
  919. else
  920. reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  921. cg.g_incrrefcount(list,tvarsym(p).vartype.def,href);
  922. end;
  923. vs_out :
  924. begin
  925. reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  926. tmpreg:=cg.get_scratch_reg_address(list);
  927. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  928. reference_reset_base(href,tmpreg,0);
  929. cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
  930. cg.free_scratch_reg(list,tmpreg);
  931. end;
  932. end;
  933. end;
  934. end;
  935. { generates the code for decrementing the reference count of parameters }
  936. procedure final_paras(p : tnamedindexitem;arg:pointer);
  937. var
  938. href : treference;
  939. list : taasmoutput;
  940. begin
  941. list:=taasmoutput(arg);
  942. if (tsym(p).typ=varsym) and
  943. not is_class(tvarsym(p).vartype.def) and
  944. tvarsym(p).vartype.def.needs_inittable then
  945. begin
  946. if (tvarsym(p).varspez=vs_value) then
  947. begin
  948. if assigned(tvarsym(p).localvarsym) then
  949. reference_reset_base(href,procinfo.framepointer,
  950. -tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup)
  951. else
  952. reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  953. cg.g_decrrefcount(list,tvarsym(p).vartype.def,href);
  954. end;
  955. end;
  956. end;
  957. { Initialize temp ansi/widestrings,interfaces }
  958. procedure inittempvariables(list:taasmoutput);
  959. var
  960. hp : ptemprecord;
  961. href : treference;
  962. begin
  963. hp:=tg.templist;
  964. while assigned(hp) do
  965. begin
  966. if hp^.temptype in [tt_ansistring,tt_freeansistring,
  967. tt_widestring,tt_freewidestring,
  968. tt_interfacecom,tt_freeinterfacecom] then
  969. begin
  970. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  971. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  972. cg.a_load_const_ref(list,OS_ADDR,0,href);
  973. end;
  974. hp:=hp^.next;
  975. end;
  976. end;
  977. procedure finalizetempvariables(list:taasmoutput);
  978. var
  979. hp : ptemprecord;
  980. href : treference;
  981. begin
  982. hp:=tg.templist;
  983. while assigned(hp) do
  984. begin
  985. case hp^.temptype of
  986. tt_ansistring,
  987. tt_freeansistring :
  988. begin
  989. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  990. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(1));
  991. cg.a_call_name(list,'FPC_ANSISTR_DECR_REF');
  992. end;
  993. tt_widestring,
  994. tt_freewidestring :
  995. begin
  996. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  997. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
  998. cg.a_call_name(list,'FPC_WIDESTR_DECR_REF');
  999. end;
  1000. tt_interfacecom :
  1001. begin
  1002. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  1003. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
  1004. cg.a_call_name(list,'FPC_INTF_DECR_REF');
  1005. end;
  1006. end;
  1007. hp:=hp^.next;
  1008. end;
  1009. end;
  1010. procedure handle_return_value(list:TAAsmoutput; inlined : boolean;var uses_acc,uses_acchi,uses_fpu : boolean);
  1011. var
  1012. href : treference;
  1013. hreg : tregister;
  1014. cgsize : TCGSize;
  1015. begin
  1016. if not is_void(aktprocdef.rettype.def) then
  1017. begin
  1018. if (tfuncretsym(aktprocdef.funcretsym).funcretstate<>vs_assigned) and
  1019. (not inlined) then
  1020. CGMessage(sym_w_function_result_not_set);
  1021. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1022. cgsize:=def_cgsize(aktprocdef.rettype.def);
  1023. case aktprocdef.rettype.def.deftype of
  1024. orddef,
  1025. enumdef :
  1026. begin
  1027. uses_acc:=true;
  1028. cg.a_reg_alloc(list,accumulator);
  1029. if cgsize in [OS_64,OS_S64] then
  1030. begin
  1031. uses_acchi:=true;
  1032. cg.a_reg_alloc(list,accumulatorhigh);
  1033. cg64.a_load64_ref_reg(list,href,joinreg64(accumulator,accumulatorhigh));
  1034. end
  1035. else
  1036. begin
  1037. hreg:=rg.makeregsize(accumulator,cgsize);
  1038. cg.a_load_ref_reg(list,cgsize,href,hreg);
  1039. end;
  1040. end;
  1041. floatdef :
  1042. begin
  1043. uses_fpu := true;
  1044. cg.a_loadfpu_ref_reg(list,cgsize,href,FPU_RESULT_REG);
  1045. end;
  1046. else
  1047. begin
  1048. if paramanager.ret_in_acc(aktprocdef.rettype.def) then
  1049. begin
  1050. uses_acc:=true;
  1051. cg.a_reg_alloc(list,accumulator);
  1052. cg.a_load_ref_reg(list,cgsize,href,accumulator);
  1053. end
  1054. end;
  1055. end;
  1056. end;
  1057. end;
  1058. procedure handle_fast_exit_return_value(list:TAAsmoutput);
  1059. var
  1060. href : treference;
  1061. hreg : tregister;
  1062. cgsize : TCGSize;
  1063. begin
  1064. if not is_void(aktprocdef.rettype.def) then
  1065. begin
  1066. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1067. cgsize:=def_cgsize(aktprocdef.rettype.def);
  1068. case aktprocdef.rettype.def.deftype of
  1069. orddef,
  1070. enumdef :
  1071. begin
  1072. if cgsize in [OS_64,OS_S64] then
  1073. cg64.a_load64_reg_ref(list,joinreg64(accumulator,accumulatorhigh),href)
  1074. else
  1075. begin
  1076. hreg:=rg.makeregsize(accumulator,cgsize);
  1077. cg.a_load_reg_ref(list,cgsize,hreg,href);
  1078. end;
  1079. end;
  1080. floatdef :
  1081. begin
  1082. cg.a_loadfpu_reg_ref(list,cgsize,FPU_RESULT_REG,href);
  1083. end;
  1084. else
  1085. begin
  1086. if paramanager.ret_in_acc(aktprocdef.rettype.def) then
  1087. cg.a_load_reg_ref(list,cgsize,accumulator,href);
  1088. end;
  1089. end;
  1090. end;
  1091. end;
  1092. procedure genentrycode(list : TAAsmoutput;
  1093. make_global:boolean;
  1094. stackframe:longint;
  1095. var parasize:longint;var nostackframe:boolean;
  1096. inlined : boolean);
  1097. var
  1098. hs : string;
  1099. href : treference;
  1100. p : tsymtable;
  1101. stackalloclist : taasmoutput;
  1102. hp : tparaitem;
  1103. begin
  1104. stackalloclist:=taasmoutput.Create;
  1105. { the actual stack allocation code, symbol entry point and
  1106. gdb stabs information is generated AFTER the rest of this
  1107. code, since temp. allocation might occur before - carl
  1108. }
  1109. if (cs_profile in aktmoduleswitches) and
  1110. not(po_assembler in aktprocdef.procoptions) and not(inlined) then
  1111. cg.g_profilecode(list);
  1112. { for the save all registers we can simply use a pusha,popa which
  1113. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1114. if (po_saveregisters in aktprocdef.procoptions) then
  1115. cg.g_save_all_registers(list)
  1116. else
  1117. { should we save edi,esi,ebx like C ? }
  1118. if (po_savestdregs in aktprocdef.procoptions) then
  1119. cg.g_save_standard_registers(list,aktprocdef.usedregisters);
  1120. { a constructor needs a help procedure }
  1121. if (aktprocdef.proctypeoption=potype_constructor) then
  1122. cg.g_call_constructor_helper(list);
  1123. { don't load ESI, does the caller }
  1124. { we must do it for local function }
  1125. { that can be called from a foreach_static }
  1126. { of another object than self !! PM }
  1127. if assigned(procinfo._class) and { !!!!! shouldn't we load ESI always? }
  1128. (lexlevel>normal_function_level) then
  1129. cg.g_maybe_loadself(list);
  1130. { When message method contains self as a parameter,
  1131. we must load it into ESI }
  1132. If (po_containsself in aktprocdef.procoptions) then
  1133. begin
  1134. list.concat(tai_regalloc.Alloc(self_pointer_reg));
  1135. reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
  1136. cg.a_load_ref_reg(list,OS_ADDR,href,self_pointer_reg);
  1137. end;
  1138. { initialize return value }
  1139. if (not is_void(aktprocdef.rettype.def)) and
  1140. (aktprocdef.rettype.def.needs_inittable) then
  1141. begin
  1142. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  1143. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1144. cg.g_initialize(list,aktprocdef.rettype.def,href,paramanager.ret_in_param(aktprocdef.rettype.def));
  1145. end;
  1146. { initialisize local data like ansistrings }
  1147. case aktprocdef.proctypeoption of
  1148. potype_unitinit:
  1149. begin
  1150. { using current_module.globalsymtable is hopefully }
  1151. { more robust than symtablestack and symtablestack.next }
  1152. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1153. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1154. end;
  1155. { units have seperate code for initilization and finalization }
  1156. potype_unitfinalize: ;
  1157. else
  1158. aktprocdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1159. end;
  1160. { initialisizes temp. ansi/wide string data }
  1161. inittempvariables(list);
  1162. { generate copies of call by value parameters }
  1163. if not(po_assembler in aktprocdef.procoptions) and
  1164. not(aktprocdef.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_palmossyscall,pocall_system]) then
  1165. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
  1166. if assigned(aktprocdef.parast) then
  1167. begin
  1168. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
  1169. { move register parameters which aren't regable into memory }
  1170. { we do this after init_paras because it saves some code in init_paras if parameters are in register }
  1171. { instead in memory }
  1172. hp:=tparaitem(procinfo.procdef.para.first);
  1173. while assigned(hp) do
  1174. begin
  1175. if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER]) and
  1176. (([vo_regable,vo_fpuregable]*tvarsym(hp.parasym).varoptions)=[]) then
  1177. begin
  1178. case hp.paraloc.loc of
  1179. LOC_REGISTER:
  1180. begin
  1181. reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address);
  1182. cg.a_load_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
  1183. end;
  1184. LOC_FPUREGISTER:
  1185. begin
  1186. reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address);
  1187. cg.a_loadfpu_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
  1188. end;
  1189. else
  1190. internalerror(2002081302);
  1191. end;
  1192. end;
  1193. hp:=tparaitem(hp.next);
  1194. end;
  1195. end;
  1196. if (not inlined) then
  1197. begin
  1198. { call startup helpers from main program }
  1199. if (aktprocdef.proctypeoption=potype_proginit) then
  1200. begin
  1201. { initialize profiling for win32 }
  1202. if (target_info.system in [system_i386_win32,system_i386_wdosx]) and
  1203. (cs_profile in aktmoduleswitches) then
  1204. cg.a_call_name(list,'__monstartup');
  1205. { add local threadvars in units (only if needed because not all platforms
  1206. have threadvar support) }
  1207. if have_local_threadvars then
  1208. cg.a_call_name(list,'FPC_INITIALIZELOCALTHREADVARS');
  1209. { add global threadvars }
  1210. p:=symtablestack;
  1211. while assigned(p) do
  1212. begin
  1213. p.foreach_static({$ifndef TP}@{$endif}initialize_threadvar,list);
  1214. p:=p.next;
  1215. end;
  1216. { initialize units }
  1217. cg.a_call_name(list,'FPC_INITIALIZEUNITS');
  1218. end;
  1219. { do we need an exception frame because of ansi/widestrings/interfaces ? }
  1220. if ((procinfo.flags and pi_needs_implicit_finally)<>0) and
  1221. { but it's useless in init/final code of units }
  1222. not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  1223. begin
  1224. include(rg.usedinproc,accumulator);
  1225. tg.GetTemp(list,JMP_BUF_SIZE,tt_noreuse,procinfo.exception_jmp_ref);
  1226. tg.GetTemp(list,12,tt_noreuse,procinfo.exception_env_ref);
  1227. tg.GetTemp(list,sizeof(aword),tt_noreuse,procinfo.exception_result_ref);
  1228. new_exception(list,procinfo.exception_jmp_ref,
  1229. procinfo.exception_env_ref,
  1230. procinfo.exception_result_ref,1,aktexitlabel);
  1231. { probably we've to reload self here }
  1232. cg.g_maybe_loadself(list);
  1233. end;
  1234. {$ifdef GDB}
  1235. if (cs_debuginfo in aktmoduleswitches) then
  1236. list.concat(Tai_force_line.Create);
  1237. {$endif GDB}
  1238. end;
  1239. if inlined then
  1240. load_regvars(list,nil);
  1241. {************************* Stack allocation **************************}
  1242. { and symbol entry point as well as debug information }
  1243. { will be inserted in front of the rest of this list. }
  1244. { Insert alignment and assembler names }
  1245. if not inlined then
  1246. begin
  1247. { Align, gprof uses 16 byte granularity }
  1248. if (cs_profile in aktmoduleswitches) then
  1249. stackalloclist.concat(Tai_align.Create_op(16,$90))
  1250. else
  1251. stackalloclist.concat(Tai_align.Create(aktalignment.procalign));
  1252. if (cs_profile in aktmoduleswitches) or
  1253. (aktprocdef.owner.symtabletype=globalsymtable) or
  1254. (assigned(procinfo._class) and (procinfo._class.owner.symtabletype=globalsymtable)) then
  1255. make_global:=true;
  1256. if make_global or ((procinfo.flags and pi_is_global) <> 0) then
  1257. aktprocsym.is_global := True;
  1258. {$ifdef GDB}
  1259. if (cs_debuginfo in aktmoduleswitches) then
  1260. begin
  1261. aktprocdef.concatstabto(stackalloclist);
  1262. aktprocsym.isstabwritten:=true;
  1263. end;
  1264. {$endif GDB}
  1265. repeat
  1266. hs:=aktprocdef.aliasnames.getfirst;
  1267. if hs='' then
  1268. break;
  1269. {$ifdef GDB}
  1270. if (cs_debuginfo in aktmoduleswitches) and
  1271. target_info.use_function_relative_addresses then
  1272. stackalloclist.concat(Tai_stab_function_name.Create(strpnew(hs)));
  1273. {$endif GDB}
  1274. if make_global then
  1275. stackalloclist.concat(Tai_symbol.Createname_global(hs,0))
  1276. else
  1277. stackalloclist.concat(Tai_symbol.Createname(hs,0));
  1278. until false;
  1279. stackframe:=stackframe+tg.gettempsize;
  1280. {$ifndef powerpc}
  1281. { at least for the ppc this applies always, so this code isn't usable (FK) }
  1282. { omit stack frame ? }
  1283. if (procinfo.framepointer=STACK_POINTER_REG) then
  1284. begin
  1285. CGMessage(cg_d_stackframe_omited);
  1286. nostackframe:=true;
  1287. if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  1288. parasize:=0
  1289. else
  1290. parasize:=aktprocdef.parast.datasize+procinfo.para_offset-4;
  1291. if stackframe<>0 then
  1292. cg.a_op_const_reg(stackalloclist,OP_SUB,stackframe,procinfo.framepointer);
  1293. end
  1294. else
  1295. {$endif powerpc}
  1296. begin
  1297. nostackframe:=false;
  1298. if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  1299. parasize:=0
  1300. else
  1301. parasize:=aktprocdef.parast.datasize+procinfo.para_offset-target_info.first_parm_offset;
  1302. if (po_interrupt in aktprocdef.procoptions) then
  1303. cg.g_interrupt_stackframe_entry(stackalloclist);
  1304. cg.g_stackframe_entry(stackalloclist,stackframe);
  1305. if (cs_check_stack in aktlocalswitches) then
  1306. cg.g_stackcheck(stackalloclist,stackframe);
  1307. end;
  1308. list.insertlist(stackalloclist);
  1309. { stackalloclist.free;}
  1310. end;
  1311. {************************* End Stack allocation **************************}
  1312. end;
  1313. procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe,inlined:boolean);
  1314. var
  1315. {$ifdef GDB}
  1316. stabsendlabel : tasmlabel;
  1317. mangled_length : longint;
  1318. p : pchar;
  1319. st : string[2];
  1320. {$endif GDB}
  1321. okexitlabel,
  1322. noreraiselabel,nodestroycall : tasmlabel;
  1323. tmpreg : tregister;
  1324. href : treference;
  1325. usesacc,
  1326. usesacchi,
  1327. usesself,usesfpu : boolean;
  1328. pd : tprocdef;
  1329. begin
  1330. if aktexit2label.is_used and
  1331. ((procinfo.flags and (pi_needs_implicit_finally or pi_uses_exceptions)) <> 0) then
  1332. begin
  1333. cg.a_jmp_always(list,aktexitlabel);
  1334. cg.a_label(list,aktexit2label);
  1335. handle_fast_exit_return_value(list);
  1336. end;
  1337. if aktexitlabel.is_used then
  1338. list.concat(Tai_label.Create(aktexitlabel));
  1339. cleanup_regvars(list);
  1340. { call the destructor help procedure }
  1341. if (aktprocdef.proctypeoption=potype_destructor) and
  1342. assigned(procinfo._class) then
  1343. cg.g_call_destructor_helper(list);
  1344. { finalize temporary data }
  1345. finalizetempvariables(list);
  1346. { finalize local data like ansistrings}
  1347. case aktprocdef.proctypeoption of
  1348. potype_unitfinalize:
  1349. begin
  1350. { using current_module.globalsymtable is hopefully }
  1351. { more robust than symtablestack and symtablestack.next }
  1352. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1353. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1354. end;
  1355. { units have seperate code for initialization and finalization }
  1356. potype_unitinit: ;
  1357. else
  1358. aktprocdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1359. end;
  1360. { finalize paras data }
  1361. if assigned(aktprocdef.parast) then
  1362. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
  1363. { do we need to handle exceptions because of ansi/widestrings ? }
  1364. if not inlined and
  1365. ((procinfo.flags and pi_needs_implicit_finally)<>0) and
  1366. { but it's useless in init/final code of units }
  1367. not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  1368. begin
  1369. { the exception helper routines modify all registers }
  1370. aktprocdef.usedregisters:=all_registers;
  1371. objectlibrary.getlabel(noreraiselabel);
  1372. free_exception(list,
  1373. procinfo.exception_jmp_ref,
  1374. procinfo.exception_env_ref,
  1375. procinfo.exception_result_ref,0,
  1376. noreraiselabel,false);
  1377. tg.Ungettemp(list,procinfo.exception_jmp_ref);
  1378. tg.Ungettemp(list,procinfo.exception_env_ref);
  1379. tg.Ungettemp(list,procinfo.exception_result_ref);
  1380. if (aktprocdef.proctypeoption=potype_constructor) then
  1381. begin
  1382. if assigned(procinfo._class) then
  1383. begin
  1384. pd:=procinfo._class.searchdestructor;
  1385. if assigned(pd) then
  1386. begin
  1387. objectlibrary.getlabel(nodestroycall);
  1388. reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
  1389. cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,nodestroycall);
  1390. if is_class(procinfo._class) then
  1391. begin
  1392. cg.a_param_const(list,OS_INT,1,paramanager.getintparaloc(2));
  1393. cg.a_param_reg(list,OS_ADDR,self_pointer_reg,paramanager.getintparaloc(1));
  1394. end
  1395. else if is_object(procinfo._class) then
  1396. begin
  1397. cg.a_param_reg(list,OS_ADDR,self_pointer_reg,paramanager.getintparaloc(2));
  1398. reference_reset_symbol(href,objectlibrary.newasmsymbol(procinfo._class.vmt_mangledname),0);
  1399. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(1));
  1400. end
  1401. else
  1402. Internalerror(200006164);
  1403. if (po_virtualmethod in pd.procoptions) then
  1404. begin
  1405. reference_reset_base(href,self_pointer_reg,0);
  1406. tmpreg:=cg.get_scratch_reg_address(list);
  1407. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  1408. reference_reset_base(href,tmpreg,procinfo._class.vmtmethodoffset(pd.extnumber));
  1409. cg.free_scratch_reg(list,tmpreg);
  1410. cg.a_call_ref(list,href);
  1411. end
  1412. else
  1413. cg.a_call_name(list,pd.mangledname);
  1414. { not necessary because the result is never assigned in the
  1415. case of an exception (FK) }
  1416. cg.a_label(list,nodestroycall);
  1417. end;
  1418. end
  1419. end
  1420. else
  1421. begin
  1422. { no constructor }
  1423. { must be the return value finalized before reraising the exception? }
  1424. if (not is_void(aktprocdef.rettype.def)) and
  1425. (aktprocdef.rettype.def.needs_inittable) and
  1426. ((aktprocdef.rettype.def.deftype<>objectdef) or
  1427. not is_class(aktprocdef.rettype.def)) then
  1428. begin
  1429. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1430. cg.g_finalize(list,aktprocdef.rettype.def,href,paramanager.ret_in_param(aktprocdef.rettype.def));
  1431. end;
  1432. end;
  1433. cg.a_call_name(list,'FPC_RERAISE');
  1434. cg.a_label(list,noreraiselabel);
  1435. end;
  1436. { call __EXIT for main program }
  1437. if (not DLLsource) and
  1438. (not inlined) and
  1439. (aktprocdef.proctypeoption=potype_proginit) then
  1440. cg.a_call_name(list,'FPC_DO_EXIT');
  1441. { handle return value, this is not done for assembler routines when
  1442. they didn't reference the result variable }
  1443. usesacc:=false;
  1444. usesacchi:=false;
  1445. usesself:=false;
  1446. if not(po_assembler in aktprocdef.procoptions) or
  1447. (assigned(aktprocdef.funcretsym) and
  1448. (tfuncretsym(aktprocdef.funcretsym).refcount>1)) then
  1449. begin
  1450. if (aktprocdef.proctypeoption<>potype_constructor) then
  1451. handle_return_value(list,inlined,usesacc,usesacchi,usesfpu)
  1452. else
  1453. begin
  1454. { successful constructor deletes the zero flag }
  1455. { and returns self in eax }
  1456. { eax must be set to zero if the allocation failed !!! }
  1457. objectlibrary.getlabel(okexitlabel);
  1458. cg.a_jmp_always(list,okexitlabel);
  1459. cg.a_label(list,faillabel);
  1460. cg.g_call_fail_helper(list);
  1461. cg.a_label(list,okexitlabel);
  1462. { for classes this is done after the call to }
  1463. { AfterConstruction }
  1464. if is_object(procinfo._class) then
  1465. begin
  1466. cg.a_reg_alloc(list,accumulator);
  1467. cg.a_load_reg_reg(list,OS_ADDR,self_pointer_reg,accumulator);
  1468. usesacc:=true;
  1469. end;
  1470. {$ifdef i386}
  1471. list.concat(taicpu.op_reg_reg(A_TEST,S_L,R_ESI,R_ESI));
  1472. {$else}
  1473. {$warning constructor returns in flags for i386}
  1474. {$endif i386}
  1475. usesself:=true;
  1476. end;
  1477. end;
  1478. if aktexit2label.is_used and not aktexit2label.is_set then
  1479. cg.a_label(list,aktexit2label);
  1480. {$ifdef GDB}
  1481. if ((cs_debuginfo in aktmoduleswitches) and not inlined) then
  1482. begin
  1483. objectlibrary.getlabel(stabsendlabel);
  1484. cg.a_label(list,stabsendlabel);
  1485. end;
  1486. {$endif GDB}
  1487. { remove copies of call by value parameters when there are also
  1488. registers saved on the stack }
  1489. if ((po_saveregisters in aktprocdef.procoptions) or
  1490. (po_savestdregs in aktprocdef.procoptions)) and
  1491. not(po_assembler in aktprocdef.procoptions) and
  1492. not(aktprocdef.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_palmossyscall,pocall_system]) then
  1493. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}removevalueparas,list);
  1494. { for the save all registers we can simply use a pusha,popa which
  1495. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1496. if (po_saveregisters in aktprocdef.procoptions) then
  1497. cg.g_restore_all_registers(list,usesself,usesacc,usesacchi)
  1498. else
  1499. { should we restore edi ? }
  1500. if (po_savestdregs in aktprocdef.procoptions) then
  1501. cg.g_restore_standard_registers(list,aktprocdef.usedregisters);
  1502. { remove stackframe }
  1503. if not inlined then
  1504. begin
  1505. if (not nostackframe) then
  1506. cg.g_restore_frame_pointer(list)
  1507. else
  1508. if (tg.gettempsize<>0) then
  1509. cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,STACK_POINTER_REG);
  1510. end;
  1511. { at last, the return is generated }
  1512. if not inlined then
  1513. begin
  1514. if (po_interrupt in aktprocdef.procoptions) then
  1515. cg.g_interrupt_stackframe_exit(list,usesself,usesacc,usesacchi)
  1516. else
  1517. cg.g_return_from_proc(list,parasize);
  1518. end;
  1519. if not inlined then
  1520. list.concat(Tai_symbol_end.Createname(aktprocdef.mangledname));
  1521. {$ifdef GDB}
  1522. if (cs_debuginfo in aktmoduleswitches) and not inlined then
  1523. begin
  1524. if assigned(procinfo._class) then
  1525. if (not assigned(procinfo.parent) or
  1526. not assigned(procinfo.parent._class)) then
  1527. begin
  1528. if (po_classmethod in aktprocdef.procoptions) or
  1529. ((po_virtualmethod in aktprocdef.procoptions) and
  1530. (potype_constructor=aktprocdef.proctypeoption)) or
  1531. (po_staticmethod in aktprocdef.procoptions) then
  1532. begin
  1533. list.concat(Tai_stabs.Create(strpnew(
  1534. '"pvmt:p'+tstoreddef(pvmttype.def).numberstring+'",'+
  1535. tostr(N_tsym)+',0,0,'+tostr(procinfo.selfpointer_offset))));
  1536. end
  1537. else
  1538. begin
  1539. if not(is_class(procinfo._class)) then
  1540. st:='v'
  1541. else
  1542. st:='p';
  1543. list.concat(Tai_stabs.Create(strpnew(
  1544. '"$t:'+st+procinfo._class.numberstring+'",'+
  1545. tostr(N_tsym)+',0,0,'+tostr(procinfo.selfpointer_offset))));
  1546. end;
  1547. end
  1548. else
  1549. begin
  1550. if not is_class(procinfo._class) then
  1551. st:='*'
  1552. else
  1553. st:='';
  1554. list.concat(Tai_stabs.Create(strpnew(
  1555. '"$t:r'+st+procinfo._class.numberstring+'",'+
  1556. tostr(N_RSYM)+',0,0,'+tostr(stab_regindex[SELF_POINTER_REG]))));
  1557. end;
  1558. { define calling EBP as pseudo local var PM }
  1559. { this enables test if the function is a local one !! }
  1560. if assigned(procinfo.parent) and (lexlevel>normal_function_level) then
  1561. list.concat(Tai_stabs.Create(strpnew(
  1562. '"parent_ebp:'+tstoreddef(voidpointertype.def).numberstring+'",'+
  1563. tostr(N_LSYM)+',0,0,'+tostr(procinfo.framepointer_offset))));
  1564. if (not is_void(aktprocdef.rettype.def)) then
  1565. begin
  1566. if paramanager.ret_in_param(aktprocdef.rettype.def) then
  1567. list.concat(Tai_stabs.Create(strpnew(
  1568. '"'+aktprocsym.name+':X*'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1569. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))))
  1570. else
  1571. list.concat(Tai_stabs.Create(strpnew(
  1572. '"'+aktprocsym.name+':X'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1573. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))));
  1574. if (m_result in aktmodeswitches) then
  1575. if paramanager.ret_in_param(aktprocdef.rettype.def) then
  1576. list.concat(Tai_stabs.Create(strpnew(
  1577. '"RESULT:X*'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1578. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))))
  1579. else
  1580. list.concat(Tai_stabs.Create(strpnew(
  1581. '"RESULT:X'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1582. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))));
  1583. end;
  1584. mangled_length:=length(aktprocdef.mangledname);
  1585. getmem(p,2*mangled_length+50);
  1586. strpcopy(p,'192,0,0,');
  1587. strpcopy(strend(p),aktprocdef.mangledname);
  1588. if (target_info.use_function_relative_addresses) then
  1589. begin
  1590. strpcopy(strend(p),'-');
  1591. strpcopy(strend(p),aktprocdef.mangledname);
  1592. end;
  1593. list.concat(Tai_stabn.Create(strnew(p)));
  1594. {List.concat(Tai_stabn.Create(strpnew('192,0,0,'
  1595. +aktprocdef.mangledname))));
  1596. p[0]:='2';p[1]:='2';p[2]:='4';
  1597. strpcopy(strend(p),'_end');}
  1598. strpcopy(p,'224,0,0,'+stabsendlabel.name);
  1599. if (target_info.use_function_relative_addresses) then
  1600. begin
  1601. strpcopy(strend(p),'-');
  1602. strpcopy(strend(p),aktprocdef.mangledname);
  1603. end;
  1604. list.concatlist(withdebuglist);
  1605. list.concat(Tai_stabn.Create(strnew(p)));
  1606. { strpnew('224,0,0,'
  1607. +aktprocdef.mangledname+'_end'))));}
  1608. freemem(p,2*mangled_length+50);
  1609. end;
  1610. {$endif GDB}
  1611. if inlined then
  1612. cleanup_regvars(list);
  1613. end;
  1614. procedure genimplicitunitinit(list : TAAsmoutput);
  1615. begin
  1616. { using current_module.globalsymtable is hopefully }
  1617. { more robust than symtablestack and symtablestack.next }
  1618. tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1619. tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1620. list.insert(Tai_symbol.Createname_global('INIT$$'+current_module.modulename^,0));
  1621. list.insert(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_init',0));
  1622. {$ifdef GDB}
  1623. if (cs_debuginfo in aktmoduleswitches) and
  1624. target_info.use_function_relative_addresses then
  1625. list.insert(Tai_stab_function_name.Create(strpnew('INIT$$'+current_module.modulename^)));
  1626. {$endif GDB}
  1627. cg.g_return_from_proc(list,0);
  1628. end;
  1629. procedure genimplicitunitfinal(list : TAAsmoutput);
  1630. begin
  1631. { using current_module.globalsymtable is hopefully }
  1632. { more robust than symtablestack and symtablestack.next }
  1633. tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1634. tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1635. list.insert(Tai_symbol.Createname_global('FINALIZE$$'+current_module.modulename^,0));
  1636. list.insert(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_finalize',0));
  1637. {$ifdef GDB}
  1638. if (cs_debuginfo in aktmoduleswitches) and
  1639. target_info.use_function_relative_addresses then
  1640. list.insert(Tai_stab_function_name.Create(strpnew('FINALIZE$$'+current_module.modulename^)));
  1641. {$endif GDB}
  1642. cg.g_return_from_proc(list,0);
  1643. end;
  1644. end.
  1645. {
  1646. $Log$
  1647. Revision 1.46 2002-09-01 19:27:34 peter
  1648. * use index register when available for generating a reference with
  1649. only a signle register. Using the base register could possibly
  1650. destroy the framepointer
  1651. Revision 1.45 2002/09/01 18:50:20 peter
  1652. * fixed maybe_save that did not support a reference with only
  1653. a index register. It now also updates the location with the new
  1654. base register only
  1655. Revision 1.44 2002/09/01 14:42:41 peter
  1656. * removevaluepara added to fix the stackpointer so restoring of
  1657. saved registers works
  1658. Revision 1.43 2002/08/25 19:25:18 peter
  1659. * sym.insert_in_data removed
  1660. * symtable.insertvardata/insertconstdata added
  1661. * removed insert_in_data call from symtable.insert, it needs to be
  1662. called separatly. This allows to deref the address calculation
  1663. * procedures now calculate the parast addresses after the procedure
  1664. directives are parsed. This fixes the cdecl parast problem
  1665. * push_addr_param has an extra argument that specifies if cdecl is used
  1666. or not
  1667. Revision 1.42 2002/08/24 18:38:26 peter
  1668. * really use tt_noreuse for exception frame buffers
  1669. Revision 1.41 2002/08/23 16:14:49 peter
  1670. * tempgen cleanup
  1671. * tt_noreuse temp type added that will be used in genentrycode
  1672. Revision 1.40 2002/08/18 10:42:37 florian
  1673. * remaining assembler writer bugs fixed, the errors in the
  1674. system unit are inline assembler problems
  1675. Revision 1.39 2002/08/17 09:23:36 florian
  1676. * first part of procinfo rewrite
  1677. Revision 1.38 2002/08/16 14:24:57 carl
  1678. * issameref() to test if two references are the same (then emit no opcodes)
  1679. + ret_in_reg to replace ret_in_acc
  1680. (fix some register allocation bugs at the same time)
  1681. + save_std_register now has an extra parameter which is the
  1682. usedinproc registers
  1683. Revision 1.37 2002/08/15 15:15:55 carl
  1684. * jmpbuf size allocation for exceptions is now cpu specific (as it should)
  1685. * more generic nodes for maths
  1686. * several fixes for better m68k support
  1687. Revision 1.36 2002/08/14 19:25:09 carl
  1688. * fix Florian's last commit for m68k compilation
  1689. Revision 1.35 2002/08/13 21:40:56 florian
  1690. * more fixes for ppc calling conventions
  1691. Revision 1.34 2002/08/12 15:08:39 carl
  1692. + stab register indexes for powerpc (moved from gdb to cpubase)
  1693. + tprocessor enumeration moved to cpuinfo
  1694. + linker in target_info is now a class
  1695. * many many updates for m68k (will soon start to compile)
  1696. - removed some ifdef or correct them for correct cpu
  1697. Revision 1.33 2002/08/11 14:32:27 peter
  1698. * renamed current_library to objectlibrary
  1699. Revision 1.32 2002/08/11 13:24:12 peter
  1700. * saving of asmsymbols in ppu supported
  1701. * asmsymbollist global is removed and moved into a new class
  1702. tasmlibrarydata that will hold the info of a .a file which
  1703. corresponds with a single module. Added librarydata to tmodule
  1704. to keep the library info stored for the module. In the future the
  1705. objectfiles will also be stored to the tasmlibrarydata class
  1706. * all getlabel/newasmsymbol and friends are moved to the new class
  1707. Revision 1.31 2002/08/09 19:16:57 carl
  1708. * stack allocation is now done separately (at the end) of genentrycode
  1709. so temps. can be allocated before.
  1710. * fix generic exception handling
  1711. Revision 1.30 2002/08/06 20:55:21 florian
  1712. * first part of ppc calling conventions fix
  1713. Revision 1.29 2002/08/04 19:09:22 carl
  1714. + added generic exception support (still does not work!)
  1715. + more documentation
  1716. Revision 1.28 2002/07/29 21:23:42 florian
  1717. * more fixes for the ppc
  1718. + wrappers for the tcnvnode.first_* stuff introduced
  1719. Revision 1.27 2002/07/28 15:59:57 jonas
  1720. * fixed bug in location_force_reg32() when converting smaller values to
  1721. 64 bit locations
  1722. * use cg.op_const_reg_reg() instead of a move and then cg.op_const_reg()
  1723. in location_force_reg32()
  1724. Revision 1.26 2002/07/27 19:53:51 jonas
  1725. + generic implementation of tcg.g_flags2ref()
  1726. * tcg.flags2xxx() now also needs a size parameter
  1727. Revision 1.25 2002/07/26 21:15:38 florian
  1728. * rewrote the system handling
  1729. Revision 1.24 2002/07/25 17:58:24 carl
  1730. + FPURESULTREG -> FPU_RESULT_REG
  1731. Revision 1.23 2002/07/20 11:57:54 florian
  1732. * types.pas renamed to defbase.pas because D6 contains a types
  1733. unit so this would conflicts if D6 programms are compiled
  1734. + Willamette/SSE2 instructions to assembler added
  1735. Revision 1.22 2002/07/11 14:41:28 florian
  1736. * start of the new generic parameter handling
  1737. Revision 1.21 2002/07/11 07:33:25 jonas
  1738. * big-endian fixes for location_force_reg*()
  1739. Revision 1.20 2002/07/07 09:52:32 florian
  1740. * powerpc target fixed, very simple units can be compiled
  1741. * some basic stuff for better callparanode handling, far from being finished
  1742. Revision 1.19 2002/07/01 18:46:23 peter
  1743. * internal linker
  1744. * reorganized aasm layer
  1745. Revision 1.18 2002/07/01 16:23:53 peter
  1746. * cg64 patch
  1747. * basics for currency
  1748. * asnode updates for class and interface (not finished)
  1749. Revision 1.17 2002/05/20 13:30:40 carl
  1750. * bugfix of hdisponen (base must be set, not index)
  1751. * more portability fixes
  1752. Revision 1.16 2002/05/18 13:34:09 peter
  1753. * readded missing revisions
  1754. Revision 1.15 2002/05/16 19:46:37 carl
  1755. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1756. + try to fix temp allocation (still in ifdef)
  1757. + generic constructor calls
  1758. + start of tassembler / tmodulebase class cleanup
  1759. Revision 1.13 2002/05/13 19:54:37 peter
  1760. * removed n386ld and n386util units
  1761. * maybe_save/maybe_restore added instead of the old maybe_push
  1762. Revision 1.12 2002/05/12 19:58:36 carl
  1763. * some small portability fixes
  1764. Revision 1.11 2002/05/12 16:53:07 peter
  1765. * moved entry and exitcode to ncgutil and cgobj
  1766. * foreach gets extra argument for passing local data to the
  1767. iterator function
  1768. * -CR checks also class typecasts at runtime by changing them
  1769. into as
  1770. * fixed compiler to cycle with the -CR option
  1771. * fixed stabs with elf writer, finally the global variables can
  1772. be watched
  1773. * removed a lot of routines from cga unit and replaced them by
  1774. calls to cgobj
  1775. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1776. u32bit then the other is typecasted also to u32bit without giving
  1777. a rangecheck warning/error.
  1778. * fixed pascal calling method with reversing also the high tree in
  1779. the parast, detected by tcalcst3 test
  1780. Revision 1.10 2002/04/21 19:02:03 peter
  1781. * removed newn and disposen nodes, the code is now directly
  1782. inlined from pexpr
  1783. * -an option that will write the secondpass nodes to the .s file, this
  1784. requires EXTDEBUG define to actually write the info
  1785. * fixed various internal errors and crashes due recent code changes
  1786. Revision 1.9 2002/04/21 15:24:38 carl
  1787. + a_jmp_cond -> a_jmp_always (a_jmp_cond is NOT portable)
  1788. + changeregsize -> rg.makeregsize
  1789. Revision 1.8 2002/04/19 15:39:34 peter
  1790. * removed some more routines from cga
  1791. * moved location_force_reg/mem to ncgutil
  1792. * moved arrayconstructnode secondpass to ncgld
  1793. Revision 1.7 2002/04/15 18:58:47 carl
  1794. + target_info.size_of_pointer -> pointer_Size
  1795. Revision 1.6 2002/04/06 18:10:42 jonas
  1796. * several powerpc-related additions and fixes
  1797. Revision 1.5 2002/04/04 19:05:57 peter
  1798. * removed unused units
  1799. * use tlocation.size in cg.a_*loc*() routines
  1800. Revision 1.4 2002/04/02 17:11:28 peter
  1801. * tlocation,treference update
  1802. * LOC_CONSTANT added for better constant handling
  1803. * secondadd splitted in multiple routines
  1804. * location_force_reg added for loading a location to a register
  1805. of a specified size
  1806. * secondassignment parses now first the right and then the left node
  1807. (this is compatible with Kylix). This saves a lot of push/pop especially
  1808. with string operations
  1809. * adapted some routines to use the new cg methods
  1810. Revision 1.3 2002/03/31 20:26:34 jonas
  1811. + a_loadfpu_* and a_loadmm_* methods in tcg
  1812. * register allocation is now handled by a class and is mostly processor
  1813. independent (+rgobj.pas and i386/rgcpu.pas)
  1814. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1815. * some small improvements and fixes to the optimizer
  1816. * some register allocation fixes
  1817. * some fpuvaroffset fixes in the unary minus node
  1818. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1819. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1820. also better optimizable)
  1821. * fixed and optimized register saving/restoring for new/dispose nodes
  1822. * LOC_FPU locations now also require their "register" field to be set to
  1823. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1824. - list field removed of the tnode class because it's not used currently
  1825. and can cause hard-to-find bugs
  1826. Revision 1.2 2002/03/04 19:10:11 peter
  1827. * removed compiler warnings
  1828. }