ncgutil.pas 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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 defines.inc}
  20. interface
  21. uses
  22. node,
  23. cginfo,cpubase,aasm;
  24. type
  25. tloadregvars = (lr_dont_load_regvars, lr_load_regvars);
  26. procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  27. procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
  28. procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
  29. procedure genentrycode(list : TAAsmoutput;
  30. make_global:boolean;
  31. stackframe:longint;
  32. var parasize:longint;var nostackframe:boolean;
  33. inlined : boolean);
  34. procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe,inlined:boolean);
  35. procedure genimplicitunitinit(list : TAAsmoutput);
  36. procedure genimplicitunitfinal(list : TAAsmoutput);
  37. implementation
  38. uses
  39. {$ifdef Delphi}
  40. Sysutils,
  41. {$else}
  42. strings,
  43. {$endif}
  44. cutils,cclasses,globtype,globals,systems,verbose,
  45. symbase,symconst,symtype,symsym,symdef,symtable,types,
  46. fmodule,
  47. cgbase,regvars,tainst,cpuasm,
  48. {$ifdef GDB}
  49. gdb,
  50. {$endif GDB}
  51. ncon,
  52. tgobj,cpuinfo,cgobj,cgcpu,rgobj,cg64f32;
  53. {*****************************************************************************
  54. TLocation
  55. *****************************************************************************}
  56. { 32-bit version }
  57. procedure location_force_reg32(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  58. var
  59. hregister,
  60. hregisterhi : tregister;
  61. hl : tasmlabel;
  62. begin
  63. { handle transformations to 64bit separate }
  64. if dst_size in [OS_64,OS_S64] then
  65. begin
  66. if not (l.size in [OS_64,OS_S64]) then
  67. begin
  68. { load a smaller size to OS_64 }
  69. if l.loc=LOC_REGISTER then
  70. hregister:=rg.makeregsize(l.registerlow,OS_INT)
  71. else
  72. hregister:=rg.getregisterint(list);
  73. { load value in low register }
  74. case l.loc of
  75. LOC_FLAGS :
  76. cg.g_flags2reg(list,l.resflags,hregister);
  77. LOC_JUMP :
  78. begin
  79. cg.a_label(list,truelabel);
  80. cg.a_load_const_reg(list,OS_INT,1,hregister);
  81. getlabel(hl);
  82. cg.a_jmp_always(list,hl);
  83. cg.a_label(list,falselabel);
  84. cg.a_load_const_reg(list,OS_INT,0,hregister);
  85. cg.a_label(list,hl);
  86. end;
  87. else
  88. cg.a_load_loc_reg(list,l,hregister);
  89. end;
  90. { reset hi part, take care of the signed bit of the current value }
  91. hregisterhi:=rg.getregisterint(list);
  92. if (dst_size=OS_S64) and
  93. (l.size in [OS_S8,OS_S16,OS_S32]) then
  94. begin
  95. if l.loc=LOC_CONSTANT then
  96. begin
  97. if (longint(l.value)<0) then
  98. cg.a_load_const_reg(list,OS_32,$ffffffff,hregisterhi)
  99. else
  100. cg.a_load_const_reg(list,OS_32,0,hregisterhi);
  101. end
  102. else
  103. begin
  104. cg.a_load_reg_reg(list,OS_32,hregister,hregisterhi);
  105. cg.a_op_const_reg(list,OP_SAR,31,hregisterhi);
  106. end;
  107. end
  108. else
  109. cg.a_load_const_reg(list,OS_32,0,hregisterhi);
  110. location_reset(l,LOC_REGISTER,dst_size);
  111. l.registerlow:=hregister;
  112. l.registerhigh:=hregisterhi;
  113. end
  114. else
  115. begin
  116. { 64bit to 64bit }
  117. if (l.loc=LOC_REGISTER) or
  118. ((l.loc=LOC_CREGISTER) and maybeconst) then
  119. begin
  120. hregister:=l.registerlow;
  121. hregisterhi:=l.registerhigh;
  122. end
  123. else
  124. begin
  125. hregister:=rg.getregisterint(list);
  126. hregisterhi:=rg.getregisterint(list);
  127. end;
  128. { load value in new register }
  129. tcg64f32(cg).a_load64_loc_reg(list,l,hregister,hregisterhi);
  130. location_reset(l,LOC_REGISTER,dst_size);
  131. l.registerlow:=hregister;
  132. l.registerhigh:=hregisterhi;
  133. end;
  134. end
  135. else
  136. begin
  137. { transformations to 32bit or smaller }
  138. if l.loc=LOC_REGISTER then
  139. begin
  140. { if the previous was 64bit release the high register }
  141. if l.size in [OS_64,OS_S64] then
  142. begin
  143. rg.ungetregisterint(list,l.registerhigh);
  144. l.registerhigh:=R_NO;
  145. end;
  146. hregister:=l.register;
  147. end
  148. else
  149. begin
  150. { get new register }
  151. if (l.loc=LOC_CREGISTER) and
  152. maybeconst and
  153. (TCGSize2Size[dst_size]=TCGSize2Size[l.size]) then
  154. hregister:=l.register
  155. else
  156. hregister:=rg.getregisterint(list);
  157. end;
  158. hregister:=rg.makeregsize(hregister,dst_size);
  159. { load value in new register }
  160. case l.loc of
  161. LOC_FLAGS :
  162. cg.g_flags2reg(list,l.resflags,hregister);
  163. LOC_JUMP :
  164. begin
  165. cg.a_label(list,truelabel);
  166. cg.a_load_const_reg(list,dst_size,1,hregister);
  167. getlabel(hl);
  168. cg.a_jmp_always(list,hl);
  169. cg.a_label(list,falselabel);
  170. cg.a_load_const_reg(list,dst_size,0,hregister);
  171. cg.a_label(list,hl);
  172. end;
  173. else
  174. begin
  175. { load_loc_reg can only handle size >= l.size, when the
  176. new size is smaller then we need to adjust the size
  177. of the orignal and maybe recalculate l.register for i386 }
  178. if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
  179. begin
  180. if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  181. l.register:=rg.makeregsize(l.register,dst_size);
  182. l.size:=dst_size;
  183. end;
  184. cg.a_load_loc_reg(list,l,hregister);
  185. end;
  186. end;
  187. location_reset(l,LOC_REGISTER,dst_size);
  188. l.register:=hregister;
  189. end;
  190. end;
  191. { 64-bit version }
  192. procedure location_force_reg64(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  193. var
  194. hregister : tregister;
  195. hl : tasmlabel;
  196. begin
  197. { handle transformations to 64bit separate }
  198. if dst_size in [OS_64,OS_S64] then
  199. begin
  200. { load a smaller size to OS_64 }
  201. if l.loc=LOC_REGISTER then
  202. hregister:=rg.makeregsize(l.register,OS_INT)
  203. else
  204. hregister:=rg.getregisterint(list);
  205. { load value in low register }
  206. case l.loc of
  207. LOC_FLAGS :
  208. cg.g_flags2reg(list,l.resflags,hregister);
  209. LOC_JUMP :
  210. begin
  211. cg.a_label(list,truelabel);
  212. cg.a_load_const_reg(list,OS_INT,1,hregister);
  213. getlabel(hl);
  214. cg.a_jmp_always(list,hl);
  215. cg.a_label(list,falselabel);
  216. cg.a_load_const_reg(list,OS_INT,0,hregister);
  217. cg.a_label(list,hl);
  218. end;
  219. else
  220. cg.a_load_loc_reg(list,l,hregister);
  221. end;
  222. location_reset(l,LOC_REGISTER,dst_size);
  223. l.register:=hregister;
  224. end
  225. else
  226. begin
  227. { transformations to 32bit or smaller }
  228. if l.loc=LOC_REGISTER then
  229. begin
  230. hregister:=l.register;
  231. end
  232. else
  233. begin
  234. { get new register }
  235. if (l.loc=LOC_CREGISTER) and
  236. maybeconst and
  237. (TCGSize2Size[dst_size]=TCGSize2Size[l.size]) then
  238. hregister:=l.register
  239. else
  240. hregister:=rg.getregisterint(list);
  241. end;
  242. hregister:=rg.makeregsize(hregister,dst_size);
  243. { load value in new register }
  244. case l.loc of
  245. LOC_FLAGS :
  246. cg.g_flags2reg(list,l.resflags,hregister);
  247. LOC_JUMP :
  248. begin
  249. cg.a_label(list,truelabel);
  250. cg.a_load_const_reg(list,dst_size,1,hregister);
  251. getlabel(hl);
  252. cg.a_jmp_always(list,hl);
  253. cg.a_label(list,falselabel);
  254. cg.a_load_const_reg(list,dst_size,0,hregister);
  255. cg.a_label(list,hl);
  256. end;
  257. else
  258. begin
  259. { load_loc_reg can only handle size >= l.size, when the
  260. new size is smaller then we need to adjust the size
  261. of the orignal and maybe recalculate l.register for i386 }
  262. if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
  263. begin
  264. if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  265. l.register:=rg.makeregsize(l.register,dst_size);
  266. l.size:=dst_size;
  267. end;
  268. cg.a_load_loc_reg(list,l,hregister);
  269. end;
  270. end;
  271. location_reset(l,LOC_REGISTER,dst_size);
  272. l.register:=hregister;
  273. end;
  274. end;
  275. procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  276. begin
  277. { release previous location before demanding a new register }
  278. if (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  279. begin
  280. location_freetemp(list,l);
  281. location_release(list,l);
  282. end;
  283. if sizeof(aword) < 8 then
  284. location_force_reg32(list, l, dst_size, maybeconst)
  285. else
  286. location_force_reg64(list, l, dst_size, maybeconst);
  287. end;
  288. procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
  289. var
  290. r : treference;
  291. begin
  292. case l.loc of
  293. LOC_FPUREGISTER,
  294. LOC_CFPUREGISTER :
  295. begin
  296. tg.gettempofsizereference(list,TCGSize2Size[l.size],r);
  297. cg.a_loadfpu_reg_ref(list,l.size,l.register,r);
  298. location_reset(l,LOC_REFERENCE,l.size);
  299. l.reference:=r;
  300. end;
  301. LOC_CONSTANT,
  302. LOC_REGISTER,
  303. LOC_CREGISTER :
  304. begin
  305. tg.gettempofsizereference(list,TCGSize2Size[l.size],r);
  306. if l.size in [OS_64,OS_S64] then
  307. tcg64f32(cg).a_load64_loc_ref(list,l,r)
  308. else
  309. cg.a_load_loc_ref(list,l,r);
  310. location_reset(l,LOC_REFERENCE,l.size);
  311. l.reference:=r;
  312. end;
  313. LOC_CREFERENCE,
  314. LOC_REFERENCE : ;
  315. else
  316. internalerror(200203219);
  317. end;
  318. end;
  319. procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
  320. {
  321. produces jumps to true respectively false labels using boolean expressions
  322. depending on whether the loading of regvars is currently being
  323. synchronized manually (such as in an if-node) or automatically (most of
  324. the other cases where this procedure is called), loadregvars can be
  325. "lr_load_regvars" or "lr_dont_load_regvars"
  326. }
  327. var
  328. opsize : tcgsize;
  329. storepos : tfileposinfo;
  330. begin
  331. if nf_error in p.flags then
  332. exit;
  333. storepos:=aktfilepos;
  334. aktfilepos:=p.fileinfo;
  335. if is_boolean(p.resulttype.def) then
  336. begin
  337. if loadregvars = lr_load_regvars then
  338. load_all_regvars(list);
  339. if is_constboolnode(p) then
  340. begin
  341. if tordconstnode(p).value<>0 then
  342. cg.a_jmp_always(list,truelabel)
  343. else
  344. cg.a_jmp_always(list,falselabel)
  345. end
  346. else
  347. begin
  348. opsize:=def_cgsize(p.resulttype.def);
  349. case p.location.loc of
  350. LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
  351. begin
  352. if (p.location.loc = LOC_CREGISTER) then
  353. load_regvar_reg(list,p.location.register);
  354. cg.a_cmp_const_loc_label(list,opsize,OC_NE,
  355. 0,p.location,truelabel);
  356. { !!! should happen right after cmp (JM) }
  357. location_release(list,p.location);
  358. cg.a_jmp_always(list,falselabel);
  359. end;
  360. LOC_FLAGS :
  361. begin
  362. cg.a_jmp_flags(list,p.location.resflags,
  363. truelabel);
  364. cg.a_jmp_always(list,falselabel);
  365. end;
  366. end;
  367. end;
  368. end
  369. else
  370. internalerror(200112305);
  371. aktfilepos:=storepos;
  372. end;
  373. {****************************************************************************
  374. Entry/Exit Code
  375. ****************************************************************************}
  376. procedure copyvalueparas(p : tnamedindexitem;arg:pointer);
  377. var
  378. href1,href2 : treference;
  379. list : taasmoutput;
  380. begin
  381. list:=taasmoutput(arg);
  382. if (tsym(p).typ=varsym) and
  383. (tvarsym(p).varspez=vs_value) and
  384. (push_addr_param(tvarsym(p).vartype.def)) then
  385. begin
  386. reference_reset_base(href1,procinfo^.framepointer,tvarsym(p).address+procinfo^.para_offset);
  387. if is_open_array(tvarsym(p).vartype.def) or
  388. is_array_of_const(tvarsym(p).vartype.def) then
  389. cg.g_copyvaluepara_openarray(list,href1,tarraydef(tvarsym(p).vartype.def).elesize)
  390. else
  391. begin
  392. reference_reset_base(href2,procinfo^.framepointer,-tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup);
  393. if is_shortstring(tvarsym(p).vartype.def) then
  394. cg.g_copyshortstring(list,href1,href2,tstringdef(tvarsym(p).vartype.def).len,false,true)
  395. else
  396. cg.g_concatcopy(list,href1,href2,tvarsym(p).vartype.def.size,true,true);
  397. end;
  398. end;
  399. end;
  400. procedure initialize_threadvar(p : tnamedindexitem;arg:pointer);
  401. var
  402. href : treference;
  403. list : taasmoutput;
  404. begin
  405. list:=taasmoutput(arg);
  406. if (tsym(p).typ=varsym) and
  407. (vo_is_thread_var in tvarsym(p).varoptions) then
  408. begin
  409. cg.a_param_const(list,OS_INT,tvarsym(p).getsize,2);
  410. reference_reset_symbol(href,newasmsymbol(tvarsym(p).mangledname),0);
  411. cg.a_paramaddr_ref(list,href,2);
  412. rg.saveregvars(list,all_registers);
  413. cg.a_call_name(list,'FPC_INIT_THREADVAR');
  414. end;
  415. end;
  416. { generates the code for initialisation of local data }
  417. procedure initialize_data(p : tnamedindexitem;arg:pointer);
  418. var
  419. href : treference;
  420. list : taasmoutput;
  421. begin
  422. list:=taasmoutput(arg);
  423. if (tsym(p).typ=varsym) and
  424. assigned(tvarsym(p).vartype.def) and
  425. not(is_class(tvarsym(p).vartype.def)) and
  426. tvarsym(p).vartype.def.needs_inittable then
  427. begin
  428. if assigned(procinfo) then
  429. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  430. if tsym(p).owner.symtabletype in [localsymtable,inlinelocalsymtable] then
  431. reference_reset_base(href,procinfo^.framepointer,-tvarsym(p).address+tvarsym(p).owner.address_fixup)
  432. else
  433. reference_reset_symbol(href,newasmsymbol(tvarsym(p).mangledname),0);
  434. cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
  435. end;
  436. end;
  437. { generates the code for finalisation of local data }
  438. procedure finalize_data(p : tnamedindexitem;arg:pointer);
  439. var
  440. href : treference;
  441. list : taasmoutput;
  442. begin
  443. list:=taasmoutput(arg);
  444. if (tsym(p).typ=varsym) and
  445. assigned(tvarsym(p).vartype.def) and
  446. not(is_class(tvarsym(p).vartype.def)) and
  447. tvarsym(p).vartype.def.needs_inittable then
  448. begin
  449. if tsym(p).owner.symtabletype in [localsymtable,inlinelocalsymtable] then
  450. reference_reset_base(href,procinfo^.framepointer,-tvarsym(p).address+tvarsym(p).owner.address_fixup)
  451. else
  452. reference_reset_symbol(href,newasmsymbol(tvarsym(p).mangledname),0);
  453. cg.g_finalize(list,tvarsym(p).vartype.def,href,false);
  454. end;
  455. end;
  456. { generates the code for incrementing the reference count of parameters and
  457. initialize out parameters }
  458. procedure init_paras(p : tnamedindexitem;arg:pointer);
  459. var
  460. href : treference;
  461. tmpreg : tregister;
  462. list : taasmoutput;
  463. begin
  464. list:=taasmoutput(arg);
  465. if (tsym(p).typ=varsym) and
  466. not is_class(tvarsym(p).vartype.def) and
  467. tvarsym(p).vartype.def.needs_inittable then
  468. begin
  469. case tvarsym(p).varspez of
  470. vs_value :
  471. begin
  472. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  473. if assigned(tvarsym(p).localvarsym) then
  474. reference_reset_base(href,procinfo^.framepointer,
  475. -tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup)
  476. else
  477. reference_reset_base(href,procinfo^.framepointer,tvarsym(p).address+procinfo^.para_offset);
  478. cg.g_incrrefcount(list,tvarsym(p).vartype.def,href);
  479. end;
  480. vs_out :
  481. begin
  482. reference_reset_base(href,procinfo^.framepointer,tvarsym(p).address+procinfo^.para_offset);
  483. tmpreg:=cg.get_scratch_reg(list);
  484. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  485. reference_reset_base(href,tmpreg,0);
  486. cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
  487. end;
  488. end;
  489. end;
  490. end;
  491. { generates the code for decrementing the reference count of parameters }
  492. procedure final_paras(p : tnamedindexitem;arg:pointer);
  493. var
  494. href : treference;
  495. list : taasmoutput;
  496. begin
  497. list:=taasmoutput(arg);
  498. if (tsym(p).typ=varsym) and
  499. not is_class(tvarsym(p).vartype.def) and
  500. tvarsym(p).vartype.def.needs_inittable then
  501. begin
  502. if (tvarsym(p).varspez=vs_value) then
  503. begin
  504. if assigned(tvarsym(p).localvarsym) then
  505. reference_reset_base(href,procinfo^.framepointer,
  506. -tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup)
  507. else
  508. reference_reset_base(href,procinfo^.framepointer,tvarsym(p).address+procinfo^.para_offset);
  509. cg.g_decrrefcount(list,tvarsym(p).vartype.def,href);
  510. end;
  511. end;
  512. end;
  513. { Initialize temp ansi/widestrings,interfaces }
  514. procedure inittempvariables(list:taasmoutput);
  515. var
  516. hp : ptemprecord;
  517. href : treference;
  518. begin
  519. hp:=tg.templist;
  520. while assigned(hp) do
  521. begin
  522. if hp^.temptype in [tt_ansistring,tt_freeansistring,
  523. tt_widestring,tt_freewidestring,
  524. tt_interfacecom] then
  525. begin
  526. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  527. reference_reset_base(href,procinfo^.framepointer,hp^.pos);
  528. cg.a_load_const_ref(list,OS_ADDR,0,href);
  529. end;
  530. hp:=hp^.next;
  531. end;
  532. end;
  533. procedure finalizetempvariables(list:taasmoutput);
  534. var
  535. hp : ptemprecord;
  536. href : treference;
  537. begin
  538. hp:=tg.templist;
  539. while assigned(hp) do
  540. begin
  541. case hp^.temptype of
  542. tt_ansistring,
  543. tt_freeansistring :
  544. begin
  545. reference_reset_base(href,procinfo^.framepointer,hp^.pos);
  546. cg.a_paramaddr_ref(list,href,1);
  547. cg.a_call_name(list,'FPC_ANSISTR_DECR_REF');
  548. end;
  549. tt_widestring,
  550. tt_freewidestring :
  551. begin
  552. reference_reset_base(href,procinfo^.framepointer,hp^.pos);
  553. cg.a_paramaddr_ref(list,href,1);
  554. cg.a_call_name(list,'FPC_WIDESTR_DECR_REF');
  555. end;
  556. tt_interfacecom :
  557. begin
  558. reference_reset_base(href,procinfo^.framepointer,hp^.pos);
  559. cg.a_paramaddr_ref(list,href,1);
  560. cg.a_call_name(list,'FPC_INTF_DECR_REF');
  561. end;
  562. end;
  563. hp:=hp^.next;
  564. end;
  565. end;
  566. procedure handle_return_value(list:TAAsmoutput; inlined : boolean;var uses_acc,uses_acchi : boolean);
  567. var
  568. href : treference;
  569. hreg : tregister;
  570. cgsize : TCGSize;
  571. begin
  572. if not is_void(aktprocdef.rettype.def) then
  573. begin
  574. if (tfuncretsym(aktprocdef.funcretsym).funcretstate<>vs_assigned) and
  575. (not inlined) then
  576. CGMessage(sym_w_function_result_not_set);
  577. reference_reset_base(href,procinfo^.framepointer,procinfo^.return_offset);
  578. cgsize:=def_cgsize(aktprocdef.rettype.def);
  579. case aktprocdef.rettype.def.deftype of
  580. orddef,
  581. enumdef :
  582. begin
  583. uses_acc:=true;
  584. cg.a_reg_alloc(list,accumulator);
  585. if cgsize in [OS_64,OS_S64] then
  586. begin
  587. uses_acchi:=true;
  588. cg.a_reg_alloc(list,accumulatorhigh);
  589. tcg64f32(cg).a_load64_ref_reg(list,href,accumulator,accumulatorhigh);
  590. end
  591. else
  592. begin
  593. hreg:=rg.makeregsize(accumulator,cgsize);
  594. cg.a_load_ref_reg(list,cgsize,href,hreg);
  595. end;
  596. end;
  597. floatdef :
  598. begin
  599. cg.a_loadfpu_ref_reg(list,cgsize,href,fpuresultreg);
  600. end;
  601. else
  602. begin
  603. if ret_in_acc(aktprocdef.rettype.def) then
  604. begin
  605. uses_acc:=true;
  606. cg.a_reg_alloc(list,accumulator);
  607. cg.a_load_ref_reg(list,cgsize,href,accumulator);
  608. end
  609. end;
  610. end;
  611. end;
  612. end;
  613. procedure handle_fast_exit_return_value(list:TAAsmoutput);
  614. var
  615. href : treference;
  616. hreg : tregister;
  617. cgsize : TCGSize;
  618. begin
  619. if not is_void(aktprocdef.rettype.def) then
  620. begin
  621. reference_reset_base(href,procinfo^.framepointer,procinfo^.return_offset);
  622. cgsize:=def_cgsize(aktprocdef.rettype.def);
  623. case aktprocdef.rettype.def.deftype of
  624. orddef,
  625. enumdef :
  626. begin
  627. if cgsize in [OS_64,OS_S64] then
  628. tcg64f32(cg).a_load64_reg_ref(list,accumulator,accumulatorhigh,href)
  629. else
  630. begin
  631. hreg:=rg.makeregsize(accumulator,cgsize);
  632. cg.a_load_reg_ref(list,cgsize,hreg,href);
  633. end;
  634. end;
  635. floatdef :
  636. begin
  637. cg.a_loadfpu_reg_ref(list,cgsize,fpuresultreg,href);
  638. end;
  639. else
  640. begin
  641. if ret_in_acc(aktprocdef.rettype.def) then
  642. cg.a_load_reg_ref(list,cgsize,accumulator,href);
  643. end;
  644. end;
  645. end;
  646. end;
  647. procedure genentrycode(list : TAAsmoutput;
  648. make_global:boolean;
  649. stackframe:longint;
  650. var parasize:longint;var nostackframe:boolean;
  651. inlined : boolean);
  652. var
  653. hs : string;
  654. href : treference;
  655. p : tsymtable;
  656. tempbuf : treference;
  657. begin
  658. { Insert alignment and assembler names }
  659. if not inlined then
  660. begin
  661. { Align, gprof uses 16 byte granularity }
  662. if (cs_profile in aktmoduleswitches) then
  663. list.concat(Tai_align.Create_op(16,$90))
  664. else
  665. list.concat(Tai_align.Create(aktalignment.procalign));
  666. if (cs_profile in aktmoduleswitches) or
  667. (aktprocdef.owner.symtabletype=globalsymtable) or
  668. (assigned(procinfo^._class) and (procinfo^._class.owner.symtabletype=globalsymtable)) then
  669. make_global:=true;
  670. if make_global or ((procinfo^.flags and pi_is_global) <> 0) then
  671. aktprocsym.is_global := True;
  672. {$ifdef GDB}
  673. if (cs_debuginfo in aktmoduleswitches) then
  674. begin
  675. aktprocdef.concatstabto(list);
  676. aktprocsym.isstabwritten:=true;
  677. end;
  678. {$endif GDB}
  679. repeat
  680. hs:=aktprocdef.aliasnames.getfirst;
  681. if hs='' then
  682. break;
  683. {$ifdef GDB}
  684. if (cs_debuginfo in aktmoduleswitches) and
  685. target_info.use_function_relative_addresses then
  686. list.concat(Tai_stab_function_name.Create(strpnew(hs)));
  687. {$endif GDB}
  688. if make_global then
  689. list.concat(Tai_symbol.Createname_global(hs,0))
  690. else
  691. list.concat(Tai_symbol.Createname(hs,0));
  692. until false;
  693. { omit stack frame ? }
  694. if (procinfo^.framepointer=STACK_POINTER_REG) then
  695. begin
  696. CGMessage(cg_d_stackframe_omited);
  697. nostackframe:=true;
  698. if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  699. parasize:=0
  700. else
  701. parasize:=aktprocdef.parast.datasize+procinfo^.para_offset-4;
  702. if stackframe<>0 then
  703. cg.a_op_const_reg(list,OP_SUB,stackframe,procinfo^.framepointer);
  704. end
  705. else
  706. begin
  707. nostackframe:=false;
  708. if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  709. parasize:=0
  710. else
  711. parasize:=aktprocdef.parast.datasize+procinfo^.para_offset-target_info.first_parm_offset;
  712. if (po_interrupt in aktprocdef.procoptions) then
  713. cg.g_interrupt_stackframe_entry(list);
  714. cg.g_stackframe_entry(list,stackframe);
  715. if (cs_check_stack in aktlocalswitches) then
  716. cg.g_stackcheck(list,stackframe);
  717. end;
  718. if (cs_profile in aktmoduleswitches) and
  719. not(po_assembler in aktprocdef.procoptions) then
  720. cg.g_profilecode(list);
  721. end;
  722. { for the save all registers we can simply use a pusha,popa which
  723. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  724. if (po_saveregisters in aktprocdef.procoptions) then
  725. cg.g_save_all_registers(list)
  726. else
  727. { should we save edi,esi,ebx like C ? }
  728. if (po_savestdregs in aktprocdef.procoptions) then
  729. cg.g_save_standard_registers(list);
  730. { a constructor needs a help procedure }
  731. if (aktprocdef.proctypeoption=potype_constructor) then
  732. cg.g_call_constructor_helper(list);
  733. { don't load ESI, does the caller }
  734. { we must do it for local function }
  735. { that can be called from a foreach_static }
  736. { of another object than self !! PM }
  737. if assigned(procinfo^._class) and { !!!!! shouldn't we load ESI always? }
  738. (lexlevel>normal_function_level) then
  739. cg.g_maybe_loadself(list);
  740. { When message method contains self as a parameter,
  741. we must load it into ESI }
  742. If (po_containsself in aktprocdef.procoptions) then
  743. begin
  744. list.concat(Tairegalloc.Alloc(self_pointer_reg));
  745. reference_reset_base(href,procinfo^.framepointer,procinfo^.selfpointer_offset);
  746. cg.a_load_ref_reg(list,OS_ADDR,href,self_pointer_reg);
  747. end;
  748. { initialize return value }
  749. if (not is_void(aktprocdef.rettype.def)) and
  750. (aktprocdef.rettype.def.needs_inittable) then
  751. begin
  752. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  753. reference_reset_base(href,procinfo^.framepointer,procinfo^.return_offset);
  754. cg.g_initialize(list,aktprocdef.rettype.def,href,ret_in_param(aktprocdef.rettype.def));
  755. end;
  756. { initialisize local data like ansistrings }
  757. case aktprocdef.proctypeoption of
  758. potype_unitinit:
  759. begin
  760. { using current_module.globalsymtable is hopefully }
  761. { more robust than symtablestack and symtablestack.next }
  762. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  763. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  764. end;
  765. { units have seperate code for initilization and finalization }
  766. potype_unitfinalize: ;
  767. else
  768. aktprocdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  769. end;
  770. { initialisizes temp. ansi/wide string data }
  771. inittempvariables(list);
  772. { generate copies of call by value parameters }
  773. if not(po_assembler in aktprocdef.procoptions) and
  774. not(aktprocdef.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_palmossyscall,pocall_system]) then
  775. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
  776. if assigned( aktprocdef.parast) then
  777. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
  778. if (not inlined) then
  779. begin
  780. { call startup helpers from main program }
  781. if (aktprocdef.proctypeoption=potype_proginit) then
  782. begin
  783. { initialize profiling for win32 }
  784. if (target_info.target in [target_I386_WIN32,target_I386_wdosx]) and
  785. (cs_profile in aktmoduleswitches) then
  786. cg.a_call_name(list,'__monstartup');
  787. { add local threadvars in units (only if needed because not all platforms
  788. have threadvar support) }
  789. if have_local_threadvars then
  790. cg.a_call_name(list,'FPC_INITIALIZELOCALTHREADVARS');
  791. { add global threadvars }
  792. p:=symtablestack;
  793. while assigned(p) do
  794. begin
  795. p.foreach_static({$ifndef TP}@{$endif}initialize_threadvar,list);
  796. p:=p.next;
  797. end;
  798. { initialize units }
  799. cg.a_call_name(list,'FPC_INITIALIZEUNITS');
  800. end;
  801. { do we need an exception frame because of ansi/widestrings/interfaces ? }
  802. if ((procinfo^.flags and pi_needs_implicit_finally)<>0) and
  803. { but it's useless in init/final code of units }
  804. not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  805. begin
  806. include(rg.usedinproc,accumulator);
  807. { allocate exception frame buffer }
  808. list.concat(Taicpu.op_const_reg(A_SUB,S_L,36,R_ESP));
  809. list.concat(Taicpu.op_reg_reg(A_MOV,S_L,R_ESP,R_EDI));
  810. reference_reset_base(tempbuf,R_EDI,0);
  811. cg.g_push_exception(list,tempbuf,1,aktexitlabel);
  812. { probably we've to reload self here }
  813. cg.g_maybe_loadself(list);
  814. end;
  815. {$ifdef GDB}
  816. if (cs_debuginfo in aktmoduleswitches) then
  817. list.concat(Tai_force_line.Create);
  818. {$endif GDB}
  819. end;
  820. if inlined then
  821. load_regvars(list,nil);
  822. end;
  823. procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe,inlined:boolean);
  824. var
  825. {$ifdef GDB}
  826. stabsendlabel : tasmlabel;
  827. mangled_length : longint;
  828. p : pchar;
  829. st : string[2];
  830. {$endif GDB}
  831. okexitlabel,
  832. noreraiselabel,nodestroycall : tasmlabel;
  833. tmpreg : tregister;
  834. href : treference;
  835. usesacc,
  836. usesacchi,
  837. usesself : boolean;
  838. pd : tprocdef;
  839. begin
  840. if aktexit2label.is_used and
  841. ((procinfo^.flags and (pi_needs_implicit_finally or pi_uses_exceptions)) <> 0) then
  842. begin
  843. cg.a_jmp_always(list,aktexitlabel);
  844. cg.a_label(list,aktexit2label);
  845. handle_fast_exit_return_value(list);
  846. end;
  847. if aktexitlabel.is_used then
  848. list.concat(Tai_label.Create(aktexitlabel));
  849. cleanup_regvars(list);
  850. { call the destructor help procedure }
  851. if (aktprocdef.proctypeoption=potype_destructor) and
  852. assigned(procinfo^._class) then
  853. cg.g_call_destructor_helper(list);
  854. { finalize temporary data }
  855. finalizetempvariables(list);
  856. { finalize local data like ansistrings}
  857. case aktprocdef.proctypeoption of
  858. potype_unitfinalize:
  859. begin
  860. { using current_module.globalsymtable is hopefully }
  861. { more robust than symtablestack and symtablestack.next }
  862. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  863. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  864. end;
  865. { units have seperate code for initialization and finalization }
  866. potype_unitinit: ;
  867. else
  868. aktprocdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  869. end;
  870. { finalize paras data }
  871. if assigned(aktprocdef.parast) then
  872. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
  873. { do we need to handle exceptions because of ansi/widestrings ? }
  874. if not inlined and
  875. ((procinfo^.flags and pi_needs_implicit_finally)<>0) and
  876. { but it's useless in init/final code of units }
  877. not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  878. begin
  879. { the exception helper routines modify all registers }
  880. aktprocdef.usedregisters:=all_registers;
  881. getlabel(noreraiselabel);
  882. cg.g_pop_exception(list,noreraiselabel);
  883. if (aktprocdef.proctypeoption=potype_constructor) then
  884. begin
  885. if assigned(procinfo^._class) then
  886. begin
  887. pd:=procinfo^._class.searchdestructor;
  888. if assigned(pd) then
  889. begin
  890. getlabel(nodestroycall);
  891. reference_reset_base(href,procinfo^.framepointer,procinfo^.selfpointer_offset);
  892. cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,nodestroycall);
  893. if is_class(procinfo^._class) then
  894. begin
  895. cg.a_param_const(list,OS_INT,1,2);
  896. cg.a_param_reg(list,OS_ADDR,self_pointer_reg,1);
  897. end
  898. else if is_object(procinfo^._class) then
  899. begin
  900. cg.a_param_reg(list,OS_ADDR,self_pointer_reg,2);
  901. reference_reset_symbol(href,newasmsymbol(procinfo^._class.vmt_mangledname),0);
  902. cg.a_paramaddr_ref(list,href,1);
  903. end
  904. else
  905. Internalerror(200006164);
  906. if (po_virtualmethod in pd.procoptions) then
  907. begin
  908. reference_reset_base(href,self_pointer_reg,0);
  909. tmpreg:=cg.get_scratch_reg(list);
  910. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  911. reference_reset_base(href,tmpreg,procinfo^._class.vmtmethodoffset(pd.extnumber));
  912. cg.free_scratch_reg(list,tmpreg);
  913. cg.a_call_ref(list,href);
  914. end
  915. else
  916. cg.a_call_name(list,pd.mangledname);
  917. { not necessary because the result is never assigned in the
  918. case of an exception (FK) }
  919. cg.a_label(list,nodestroycall);
  920. end;
  921. end
  922. end
  923. else
  924. begin
  925. { no constructor }
  926. { must be the return value finalized before reraising the exception? }
  927. if (not is_void(aktprocdef.rettype.def)) and
  928. (aktprocdef.rettype.def.needs_inittable) and
  929. ((aktprocdef.rettype.def.deftype<>objectdef) or
  930. not is_class(aktprocdef.rettype.def)) then
  931. begin
  932. reference_reset_base(href,procinfo^.framepointer,procinfo^.return_offset);
  933. cg.g_finalize(list,aktprocdef.rettype.def,href,ret_in_param(aktprocdef.rettype.def));
  934. end;
  935. end;
  936. cg.a_call_name(list,'FPC_RERAISE');
  937. cg.a_label(list,noreraiselabel);
  938. end;
  939. { call __EXIT for main program }
  940. if (not DLLsource) and
  941. (not inlined) and
  942. (aktprocdef.proctypeoption=potype_proginit) then
  943. cg.a_call_name(list,'FPC_DO_EXIT');
  944. { handle return value, this is not done for assembler routines when
  945. they didn't reference the result variable }
  946. usesacc:=false;
  947. usesacchi:=false;
  948. usesself:=false;
  949. if not(po_assembler in aktprocdef.procoptions) or
  950. (assigned(aktprocdef.funcretsym) and
  951. (tfuncretsym(aktprocdef.funcretsym).refcount>1)) then
  952. begin
  953. if (aktprocdef.proctypeoption<>potype_constructor) then
  954. handle_return_value(list,inlined,usesacc,usesacchi)
  955. else
  956. begin
  957. { successful constructor deletes the zero flag }
  958. { and returns self in eax }
  959. { eax must be set to zero if the allocation failed !!! }
  960. getlabel(okexitlabel);
  961. cg.a_jmp_always(list,okexitlabel);
  962. cg.a_label(list,faillabel);
  963. cg.g_call_fail_helper(list);
  964. cg.a_label(list,okexitlabel);
  965. { for classes this is done after the call to }
  966. { AfterConstruction }
  967. if is_object(procinfo^._class) then
  968. begin
  969. cg.a_reg_alloc(list,accumulator);
  970. cg.a_load_reg_reg(list,OS_ADDR,self_pointer_reg,accumulator);
  971. usesacc:=true;
  972. end;
  973. {$ifdef i386}
  974. list.concat(taicpu.op_reg_reg(A_TEST,S_L,R_ESI,R_ESI));
  975. {$else}
  976. {$warning constructor returns in flags for i386}
  977. {$endif i386}
  978. usesself:=true;
  979. end;
  980. end;
  981. if aktexit2label.is_used and not aktexit2label.is_set then
  982. cg.a_label(list,aktexit2label);
  983. {$ifdef GDB}
  984. if ((cs_debuginfo in aktmoduleswitches) and not inlined) then
  985. begin
  986. getlabel(stabsendlabel);
  987. cg.a_label(list,stabsendlabel);
  988. end;
  989. {$endif GDB}
  990. { for the save all registers we can simply use a pusha,popa which
  991. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  992. if (po_saveregisters in aktprocdef.procoptions) then
  993. cg.g_restore_all_registers(list,usesself,usesacc,usesacchi)
  994. else
  995. { should we restore edi ? }
  996. if (po_savestdregs in aktprocdef.procoptions) then
  997. cg.g_restore_standard_registers(list);
  998. { remove stackframe }
  999. if not inlined then
  1000. begin
  1001. if (not nostackframe) then
  1002. cg.g_restore_frame_pointer(list)
  1003. else
  1004. if (tg.gettempsize<>0) then
  1005. cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,R_ESP);
  1006. end;
  1007. { at last, the return is generated }
  1008. if not inlined then
  1009. begin
  1010. if (po_interrupt in aktprocdef.procoptions) then
  1011. cg.g_interrupt_stackframe_exit(list,usesself,usesacc,usesacchi)
  1012. else
  1013. cg.g_return_from_proc(list,parasize);
  1014. end;
  1015. if not inlined then
  1016. list.concat(Tai_symbol_end.Createname(aktprocdef.mangledname));
  1017. {$ifdef GDB}
  1018. if (cs_debuginfo in aktmoduleswitches) and not inlined then
  1019. begin
  1020. if assigned(procinfo^._class) then
  1021. if (not assigned(procinfo^.parent) or
  1022. not assigned(procinfo^.parent^._class)) then
  1023. begin
  1024. if (po_classmethod in aktprocdef.procoptions) or
  1025. ((po_virtualmethod in aktprocdef.procoptions) and
  1026. (potype_constructor=aktprocdef.proctypeoption)) or
  1027. (po_staticmethod in aktprocdef.procoptions) then
  1028. begin
  1029. list.concat(Tai_stabs.Create(strpnew(
  1030. '"pvmt:p'+tstoreddef(pvmttype.def).numberstring+'",'+
  1031. tostr(N_tsym)+',0,0,'+tostr(procinfo^.selfpointer_offset))));
  1032. end
  1033. else
  1034. begin
  1035. if not(is_class(procinfo^._class)) then
  1036. st:='v'
  1037. else
  1038. st:='p';
  1039. list.concat(Tai_stabs.Create(strpnew(
  1040. '"$t:'+st+procinfo^._class.numberstring+'",'+
  1041. tostr(N_tsym)+',0,0,'+tostr(procinfo^.selfpointer_offset))));
  1042. end;
  1043. end
  1044. else
  1045. begin
  1046. if not is_class(procinfo^._class) then
  1047. st:='*'
  1048. else
  1049. st:='';
  1050. list.concat(Tai_stabs.Create(strpnew(
  1051. '"$t:r'+st+procinfo^._class.numberstring+'",'+
  1052. tostr(N_RSYM)+',0,0,'+tostr(GDB_i386index[R_ESI]))));
  1053. end;
  1054. { define calling EBP as pseudo local var PM }
  1055. { this enables test if the function is a local one !! }
  1056. if assigned(procinfo^.parent) and (lexlevel>normal_function_level) then
  1057. list.concat(Tai_stabs.Create(strpnew(
  1058. '"parent_ebp:'+tstoreddef(voidpointertype.def).numberstring+'",'+
  1059. tostr(N_LSYM)+',0,0,'+tostr(procinfo^.framepointer_offset))));
  1060. if (not is_void(aktprocdef.rettype.def)) then
  1061. begin
  1062. if ret_in_param(aktprocdef.rettype.def) then
  1063. list.concat(Tai_stabs.Create(strpnew(
  1064. '"'+aktprocsym.name+':X*'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1065. tostr(N_tsym)+',0,0,'+tostr(procinfo^.return_offset))))
  1066. else
  1067. list.concat(Tai_stabs.Create(strpnew(
  1068. '"'+aktprocsym.name+':X'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1069. tostr(N_tsym)+',0,0,'+tostr(procinfo^.return_offset))));
  1070. if (m_result in aktmodeswitches) then
  1071. if ret_in_param(aktprocdef.rettype.def) then
  1072. list.concat(Tai_stabs.Create(strpnew(
  1073. '"RESULT:X*'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1074. tostr(N_tsym)+',0,0,'+tostr(procinfo^.return_offset))))
  1075. else
  1076. list.concat(Tai_stabs.Create(strpnew(
  1077. '"RESULT:X'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1078. tostr(N_tsym)+',0,0,'+tostr(procinfo^.return_offset))));
  1079. end;
  1080. mangled_length:=length(aktprocdef.mangledname);
  1081. getmem(p,2*mangled_length+50);
  1082. strpcopy(p,'192,0,0,');
  1083. strpcopy(strend(p),aktprocdef.mangledname);
  1084. if (target_info.use_function_relative_addresses) then
  1085. begin
  1086. strpcopy(strend(p),'-');
  1087. strpcopy(strend(p),aktprocdef.mangledname);
  1088. end;
  1089. list.concat(Tai_stabn.Create(strnew(p)));
  1090. {List.concat(Tai_stabn.Create(strpnew('192,0,0,'
  1091. +aktprocdef.mangledname))));
  1092. p[0]:='2';p[1]:='2';p[2]:='4';
  1093. strpcopy(strend(p),'_end');}
  1094. strpcopy(p,'224,0,0,'+stabsendlabel.name);
  1095. if (target_info.use_function_relative_addresses) then
  1096. begin
  1097. strpcopy(strend(p),'-');
  1098. strpcopy(strend(p),aktprocdef.mangledname);
  1099. end;
  1100. list.concatlist(withdebuglist);
  1101. list.concat(Tai_stabn.Create(strnew(p)));
  1102. { strpnew('224,0,0,'
  1103. +aktprocdef.mangledname+'_end'))));}
  1104. freemem(p,2*mangled_length+50);
  1105. end;
  1106. {$endif GDB}
  1107. if inlined then
  1108. cleanup_regvars(list);
  1109. end;
  1110. procedure genimplicitunitinit(list : TAAsmoutput);
  1111. begin
  1112. { using current_module.globalsymtable is hopefully }
  1113. { more robust than symtablestack and symtablestack.next }
  1114. tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1115. tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1116. list.insert(Tai_symbol.Createname_global('INIT$$'+current_module.modulename^,0));
  1117. list.insert(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_init',0));
  1118. {$ifdef GDB}
  1119. if (cs_debuginfo in aktmoduleswitches) and
  1120. target_info.use_function_relative_addresses then
  1121. list.insert(Tai_stab_function_name.Create(strpnew('INIT$$'+current_module.modulename^)));
  1122. {$endif GDB}
  1123. cg.g_return_from_proc(list,0);
  1124. end;
  1125. procedure genimplicitunitfinal(list : TAAsmoutput);
  1126. begin
  1127. { using current_module.globalsymtable is hopefully }
  1128. { more robust than symtablestack and symtablestack.next }
  1129. tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1130. tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1131. list.insert(Tai_symbol.Createname_global('FINALIZE$$'+current_module.modulename^,0));
  1132. list.insert(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_finalize',0));
  1133. {$ifdef GDB}
  1134. if (cs_debuginfo in aktmoduleswitches) and
  1135. target_info.use_function_relative_addresses then
  1136. list.insert(Tai_stab_function_name.Create(strpnew('FINALIZE$$'+current_module.modulename^)));
  1137. {$endif GDB}
  1138. cg.g_return_from_proc(list,0);
  1139. end;
  1140. end.
  1141. {
  1142. $Log$
  1143. Revision 1.12 2002-05-12 19:58:36 carl
  1144. * some small portability fixes
  1145. Revision 1.11 2002/05/12 16:53:07 peter
  1146. * moved entry and exitcode to ncgutil and cgobj
  1147. * foreach gets extra argument for passing local data to the
  1148. iterator function
  1149. * -CR checks also class typecasts at runtime by changing them
  1150. into as
  1151. * fixed compiler to cycle with the -CR option
  1152. * fixed stabs with elf writer, finally the global variables can
  1153. be watched
  1154. * removed a lot of routines from cga unit and replaced them by
  1155. calls to cgobj
  1156. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1157. u32bit then the other is typecasted also to u32bit without giving
  1158. a rangecheck warning/error.
  1159. * fixed pascal calling method with reversing also the high tree in
  1160. the parast, detected by tcalcst3 test
  1161. Revision 1.10 2002/04/21 19:02:03 peter
  1162. * removed newn and disposen nodes, the code is now directly
  1163. inlined from pexpr
  1164. * -an option that will write the secondpass nodes to the .s file, this
  1165. requires EXTDEBUG define to actually write the info
  1166. * fixed various internal errors and crashes due recent code changes
  1167. Revision 1.9 2002/04/21 15:24:38 carl
  1168. + a_jmp_cond -> a_jmp_always (a_jmp_cond is NOT portable)
  1169. + changeregsize -> rg.makeregsize
  1170. Revision 1.8 2002/04/19 15:39:34 peter
  1171. * removed some more routines from cga
  1172. * moved location_force_reg/mem to ncgutil
  1173. * moved arrayconstructnode secondpass to ncgld
  1174. Revision 1.7 2002/04/15 18:58:47 carl
  1175. + target_info.size_of_pointer -> pointer_Size
  1176. Revision 1.6 2002/04/06 18:10:42 jonas
  1177. * several powerpc-related additions and fixes
  1178. Revision 1.5 2002/04/04 19:05:57 peter
  1179. * removed unused units
  1180. * use tlocation.size in cg.a_*loc*() routines
  1181. Revision 1.4 2002/04/02 17:11:28 peter
  1182. * tlocation,treference update
  1183. * LOC_CONSTANT added for better constant handling
  1184. * secondadd splitted in multiple routines
  1185. * location_force_reg added for loading a location to a register
  1186. of a specified size
  1187. * secondassignment parses now first the right and then the left node
  1188. (this is compatible with Kylix). This saves a lot of push/pop especially
  1189. with string operations
  1190. * adapted some routines to use the new cg methods
  1191. Revision 1.3 2002/03/31 20:26:34 jonas
  1192. + a_loadfpu_* and a_loadmm_* methods in tcg
  1193. * register allocation is now handled by a class and is mostly processor
  1194. independent (+rgobj.pas and i386/rgcpu.pas)
  1195. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1196. * some small improvements and fixes to the optimizer
  1197. * some register allocation fixes
  1198. * some fpuvaroffset fixes in the unary minus node
  1199. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1200. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1201. also better optimizable)
  1202. * fixed and optimized register saving/restoring for new/dispose nodes
  1203. * LOC_FPU locations now also require their "register" field to be set to
  1204. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1205. - list field removed of the tnode class because it's not used currently
  1206. and can cause hard-to-find bugs
  1207. Revision 1.2 2002/03/04 19:10:11 peter
  1208. * removed compiler warnings
  1209. Revision 1.1 2001/12/30 17:24:48 jonas
  1210. * range checking is now processor independent (part in cgobj,
  1211. part in cg64f32) and should work correctly again (it needed
  1212. some changes after the changes of the low and high of
  1213. tordef's to int64)
  1214. * maketojumpbool() is now processor independent (in ncgutil)
  1215. * getregister32 is now called getregisterint
  1216. }