ncgutil.pas 75 KB

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