cgobj.pas 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Member of the Free Pascal development team
  5. This unit implements the basic code generator object
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit cgobj;
  20. interface
  21. uses
  22. cobjects,aasm,symtable,cpuasm,cpubase,cgbase,cpuinfo,tainst
  23. {$IFDEF NEWST}
  24. {$ELSE}
  25. ,symconst
  26. {$ENDIF NEWST};
  27. type
  28. talignment = (AM_NATURAL,AM_NONE,AM_2BYTE,AM_4BYTE,AM_8BYTE);
  29. pcg = ^tcg;
  30. tcg = object
  31. scratch_register_array_pointer : aword;
  32. unusedscratchregisters : tregisterset;
  33. alignment : talignment;
  34. {************************************************}
  35. { basic routines }
  36. constructor init;
  37. destructor done;virtual;
  38. procedure a_label(list : paasmoutput;l : pasmlabel);virtual;
  39. { allocates register r by inserting a pai_realloc record }
  40. procedure a_reg_alloc(list : paasmoutput;r : tregister);
  41. { deallocates register r by inserting a pa_regdealloc record}
  42. procedure a_reg_dealloc(list : paasmoutput;r : tregister);
  43. { returns a register for use as scratch register }
  44. function get_scratch_reg(list : paasmoutput) : tregister;
  45. { releases a scratch register }
  46. procedure free_scratch_reg(list : paasmoutput;r : tregister);
  47. {************************************************}
  48. { code generation for subroutine entry/exit code }
  49. { initilizes data of type t }
  50. { if is_already_ref is true then the routines assumes }
  51. { that r points to the data to initialize }
  52. procedure g_initialize(list : paasmoutput;t : pdef;const ref : treference;is_already_ref : boolean);
  53. { finalizes data of type t }
  54. { if is_already_ref is true then the routines assumes }
  55. { that r points to the data to finalizes }
  56. procedure g_finalize(list : paasmoutput;t : pdef;const ref : treference;is_already_ref : boolean);
  57. { helper routines }
  58. procedure g_initialize_data(list : paasmoutput;p : psym);
  59. procedure g_incr_data(list : paasmoutput;p : psym);
  60. procedure g_finalize_data(list : paasmoutput;p : pnamedindexobject);
  61. procedure g_copyvalueparas(list : paasmoutput;p : pnamedindexobject);
  62. procedure g_finalizetempansistrings(list : paasmoutput);
  63. procedure g_entrycode(list : paasmoutput;
  64. const proc_names : tstringcontainer;make_global : boolean;
  65. stackframe : longint;var parasize : longint;
  66. var nostackframe : boolean;inlined : boolean);
  67. procedure g_exitcode(list : paasmoutput;parasize : longint;
  68. nostackframe,inlined : boolean);
  69. { string helper routines }
  70. procedure g_decrstrref(list : paasmoutput;const ref : treference;t : pdef);
  71. procedure g_removetemps(list : paasmoutput;p : plinkedlist);
  72. { passing parameters, per default the parameter is pushed }
  73. { nr gives the number of the parameter (enumerated from }
  74. { left to right), this allows to move the parameter to }
  75. { register, if the cpu supports register calling }
  76. { conventions }
  77. procedure a_param_reg(list : paasmoutput;size : tcgsize;r : tregister;nr : longint);virtual;
  78. procedure a_param_const(list : paasmoutput;size : tcgsize;a : aword;nr : longint);virtual;
  79. procedure a_param_ref(list : paasmoutput;size : tcgsize;const r : treference;nr : longint);virtual;
  80. procedure a_paramaddr_ref(list : paasmoutput;const r : treference;nr : longint);virtual;
  81. {**********************************}
  82. { these methods must be overriden: }
  83. { Remarks:
  84. * If a method specifies a size you have only to take care
  85. of that number of bits, i.e. load_const_reg with OP_8 must
  86. only load the lower 8 bit of the specified register
  87. the rest of the register can be undefined
  88. if necessary the compiler will call a method
  89. to zero or sign extend the register
  90. * The a_load_XX_XX with OP_64 needn't to be
  91. implemented for 32 bit
  92. processors, the code generator takes care of that
  93. * the addr size is for work with the natural pointer
  94. size
  95. * the procedures without fpu/mm are only for integer usage
  96. * normally the first location is the source and the
  97. second the destination
  98. }
  99. procedure a_call_name(list : paasmoutput;const s : string;
  100. offset : longint);virtual;
  101. { move instructions }
  102. procedure a_load_const_reg(list : paasmoutput;size : tcgsize;a : aword;register : tregister);virtual;
  103. procedure a_load_const_ref(list : paasmoutput;size : tcgsize;a : aword;const ref : treference);virtual;
  104. procedure a_load_reg_ref(list : paasmoutput;size : tcgsize;register : tregister;const ref : treference);virtual;
  105. procedure a_load_ref_reg(list : paasmoutput;size : tcgsize;const ref : treference;register : tregister);virtual;
  106. procedure a_load_reg_reg(list : paasmoutput;size : tcgsize;reg1,reg2 : tregister);virtual;
  107. { comparison operations }
  108. procedure a_cmp_reg_const_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  109. l : pasmlabel);virtual;
  110. procedure a_cmp_reg_reg_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : pasmlabel);
  111. procedure a_cmp_reg_ref_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;reg : tregister;l : pasmlabel);
  112. procedure a_cmp_ref_const_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  113. l : pasmlabel);
  114. procedure a_jmp_cond(list : paasmoutput;cond : TOpCmp;l: pasmlabel);
  115. procedure a_loadaddress_ref_reg(list : paasmoutput;const ref : treference;r : tregister);virtual;
  116. procedure g_stackframe_entry(list : paasmoutput;localsize : longint);virtual;
  117. { restores the frame pointer at procedure exit, for the }
  118. { i386 it generates a simple leave }
  119. procedure g_restore_frame_pointer(list : paasmoutput);virtual;
  120. { some processors like the PPC doesn't allow to change the stack in }
  121. { a procedure, so we need to maintain an extra stack for the }
  122. { result values of setjmp in exception code }
  123. { this two procedures are for pushing an exception value, }
  124. { they can use the scratch registers }
  125. procedure g_push_exception_value_reg(list : paasmoutput;reg : tregister);virtual;
  126. procedure g_push_exception_value_const(list : paasmoutput;reg : tregister);virtual;
  127. { that procedure pops a exception value }
  128. procedure g_pop_exception_value_reg(list : paasmoutput;reg : tregister);virtual;
  129. procedure g_return_from_proc(list : paasmoutput;parasize : aword);virtual;
  130. {********************************************************}
  131. { these methods can be overriden for extra functionality }
  132. { the following methods do nothing: }
  133. procedure g_interrupt_stackframe_entry(list : paasmoutput);virtual;
  134. procedure g_interrupt_stackframe_exit(list : paasmoutput);virtual;
  135. procedure g_profilecode(list : paasmoutput);virtual;
  136. procedure g_stackcheck(list : paasmoutput;stackframesize : longint);virtual;
  137. procedure g_maybe_loadself(list : paasmoutput);virtual;
  138. { copies len bytes from the source to destination, if }
  139. { loadref is true, it assumes that it first must load }
  140. { the source address from the memory location where }
  141. { source points to }
  142. procedure g_concatcopy(list : paasmoutput;const source,dest : treference;len : aword;loadref : boolean);virtual;
  143. { uses the addr of ref as param, was emitpushreferenceaddr }
  144. procedure a_param_ref_addr(list : paasmoutput;r : treference;nr : longint);virtual;
  145. end;
  146. var
  147. cg : pcg; { this is the main code generator class }
  148. implementation
  149. uses
  150. strings,globals,globtype,options,files,gdb,systems,
  151. ppu,verbose,types,tgobj,tgcpu
  152. {$IFDEF NEWST}
  153. ,symbols,defs,symtablt
  154. {$ENDIF NEWST};
  155. {*****************************************************************************
  156. basic functionallity
  157. ******************************************************************************}
  158. constructor tcg.init;
  159. var
  160. i : longint;
  161. begin
  162. scratch_register_array_pointer:=1;
  163. for i:=1 to max_scratch_regs do
  164. include(unusedscratchregisters,scratch_regs[i]);
  165. end;
  166. destructor tcg.done;
  167. begin
  168. end;
  169. procedure tcg.a_reg_alloc(list : paasmoutput;r : tregister);
  170. begin
  171. list^.concat(new(pairegalloc,alloc(r)));
  172. end;
  173. procedure tcg.a_reg_dealloc(list : paasmoutput;r : tregister);
  174. begin
  175. list^.concat(new(pairegalloc,dealloc(r)));
  176. end;
  177. procedure tcg.a_label(list : paasmoutput;l : pasmlabel);
  178. begin
  179. list^.concat(new(pai_label,init(l)));
  180. end;
  181. function tcg.get_scratch_reg(list : paasmoutput) : tregister;
  182. var
  183. r : tregister;
  184. i : longint;
  185. begin
  186. if unusedscratchregisters=[] then
  187. internalerror(68996);
  188. for i:=scratch_register_array_pointer to
  189. (scratch_register_array_pointer+max_scratch_regs) do
  190. if scratch_regs[(i mod max_scratch_regs)+1] in unusedscratchregisters then
  191. begin
  192. r:=scratch_regs[(i mod max_scratch_regs)+1];
  193. break;
  194. end;
  195. exclude(unusedscratchregisters,r);
  196. inc(scratch_register_array_pointer);
  197. if scratch_register_array_pointer>max_scratch_regs then
  198. scratch_register_array_pointer:=1;
  199. a_reg_alloc(list,r);
  200. get_scratch_reg:=r;
  201. end;
  202. procedure tcg.free_scratch_reg(list : paasmoutput;r : tregister);
  203. begin
  204. include(unusedscratchregisters,r);
  205. a_reg_dealloc(list,r);
  206. end;
  207. {*****************************************************************************
  208. this methods must be overridden for extra functionality
  209. ******************************************************************************}
  210. procedure tcg.g_interrupt_stackframe_entry(list : paasmoutput);
  211. begin
  212. end;
  213. procedure tcg.g_interrupt_stackframe_exit(list : paasmoutput);
  214. begin
  215. end;
  216. procedure tcg.g_profilecode(list : paasmoutput);
  217. begin
  218. end;
  219. {*****************************************************************************
  220. for better code generation these methods should be overridden
  221. ******************************************************************************}
  222. procedure tcg.a_param_const(list : paasmoutput;size : tcgsize;a : aword;nr : longint);
  223. var
  224. hr : tregister;
  225. begin
  226. hr:=get_scratch_reg(list);
  227. a_load_const_reg(list,size,a,hr);
  228. a_param_reg(list,size,hr,nr);
  229. free_scratch_reg(list,hr);
  230. end;
  231. procedure tcg.a_param_ref(list : paasmoutput;size : tcgsize;const r : treference;nr : longint);
  232. var
  233. hr : tregister;
  234. begin
  235. hr:=get_scratch_reg(list);
  236. a_load_ref_reg(list,size,r,hr);
  237. a_param_reg(list,size,hr,nr);
  238. free_scratch_reg(list,hr);
  239. end;
  240. procedure tcg.a_param_ref_addr(list : paasmoutput;r : treference;nr : longint);
  241. var
  242. hr : tregister;
  243. begin
  244. hr:=get_scratch_reg(list);
  245. a_loadaddress_ref_reg(list,r,hr);
  246. a_param_reg(list,OS_ADDR,hr,nr);
  247. free_scratch_reg(list,hr);
  248. end;
  249. procedure tcg.g_stackcheck(list : paasmoutput;stackframesize : longint);
  250. begin
  251. a_param_const(list,OS_32,stackframesize,1);
  252. a_call_name(list,'FPC_STACKCHECK',0);
  253. end;
  254. procedure tcg.a_load_const_ref(list : paasmoutput;size : tcgsize;a : aword;const ref : treference);
  255. var
  256. hr : tregister;
  257. begin
  258. hr:=get_scratch_reg(list);
  259. a_load_const_reg(list,size,a,hr);
  260. a_load_reg_ref(list,size,hr,ref);
  261. free_scratch_reg(list,hr);
  262. end;
  263. procedure tcg.g_concatcopy(list : paasmoutput;const source,dest : treference;len : aword;loadref : boolean);
  264. begin
  265. abstract;
  266. end;
  267. {*****************************************************************************
  268. String helper routines
  269. *****************************************************************************}
  270. procedure tcg.g_removetemps(list : paasmoutput;p : plinkedlist);
  271. var
  272. hp : ptemptodestroy;
  273. pushedregs : tpushed;
  274. begin
  275. hp:=ptemptodestroy(p^.first);
  276. if not(assigned(hp)) then
  277. exit;
  278. tg.pushusedregisters(pushedregs,$ff);
  279. while assigned(hp) do
  280. begin
  281. if is_ansistring(hp^.typ) then
  282. begin
  283. g_decrstrref(list,hp^.address,hp^.typ);
  284. tg.ungetiftemp(hp^.address);
  285. end;
  286. hp:=ptemptodestroy(hp^.next);
  287. end;
  288. tg.popusedregisters(pushedregs);
  289. end;
  290. procedure tcg.g_decrstrref(list : paasmoutput;const ref : treference;t : pdef);
  291. var
  292. pushedregs : tpushed;
  293. begin
  294. tg.pushusedregisters(pushedregs,$ff);
  295. a_param_ref_addr(list,ref,1);
  296. if is_ansistring(t) then
  297. a_call_name(list,'FPC_ANSISTR_DECR_REF',0)
  298. else if is_widestring(t) then
  299. a_call_name(list,'FPC_WIDESTR_DECR_REF',0)
  300. else internalerror(58993);
  301. tg.popusedregisters(pushedregs);
  302. end;
  303. {*****************************************************************************
  304. Code generation for subroutine entry- and exit code
  305. *****************************************************************************}
  306. { initilizes data of type t }
  307. { if is_already_ref is true then the routines assumes }
  308. { that r points to the data to initialize }
  309. procedure tcg.g_initialize(list : paasmoutput;t : pdef;const ref : treference;is_already_ref : boolean);
  310. var
  311. hr : treference;
  312. begin
  313. if is_ansistring(t) or
  314. is_widestring(t) then
  315. a_load_const_ref(list,OS_8,0,ref)
  316. else
  317. begin
  318. reset_reference(hr);
  319. hr.symbol:=t^.get_inittable_label;
  320. a_param_ref_addr(list,hr,2);
  321. if is_already_ref then
  322. a_param_ref(list,OS_ADDR,ref,1)
  323. else
  324. a_param_ref_addr(list,ref,1);
  325. a_call_name(list,'FPC_INITIALIZE',0);
  326. end;
  327. end;
  328. procedure tcg.g_finalize(list : paasmoutput;t : pdef;const ref : treference;is_already_ref : boolean);
  329. var
  330. r : treference;
  331. begin
  332. if is_ansistring(t) or
  333. is_widestring(t) then
  334. begin
  335. g_decrstrref(list,ref,t);
  336. end
  337. else
  338. begin
  339. reset_reference(r);
  340. r.symbol:=t^.get_inittable_label;
  341. a_param_ref_addr(list,r,2);
  342. if is_already_ref then
  343. a_paramaddr_ref(list,ref,1)
  344. else
  345. a_param_ref_addr(list,ref,1);
  346. a_call_name(list,'FPC_FINALIZE',0);
  347. end;
  348. end;
  349. { generates the code for initialisation of local data }
  350. procedure tcg.g_initialize_data(list : paasmoutput;p : psym);
  351. var
  352. hr : treference;
  353. begin
  354. {$IFDEF NEWST}
  355. if (typeof(p^)=typeof(Tvarsym)) and
  356. assigned(pvarsym(p)^.definition) and
  357. not((typeof((pvarsym(p)^.definition^))=typeof(Tobjectdef)) and
  358. (oo_is_class in pobjectdef(pvarsym(p)^.definition)^.options)) and
  359. pvarsym(p)^.definition^.needs_inittable then
  360. begin
  361. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  362. reset_reference(hr);
  363. if typeof((psym(p)^.owner^))=typeof(Tprocsymtable) then
  364. begin
  365. hr.base:=procinfo^.framepointer;
  366. hr.offset:=-pvarsym(p)^.address;
  367. end
  368. else
  369. begin
  370. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  371. end;
  372. g_initialize(list,pvarsym(p)^.definition,hr,false);
  373. end;
  374. {$ELSE}
  375. if (psym(p)^.typ=varsym) and
  376. assigned(pvarsym(p)^.vartype.def) and
  377. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  378. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  379. pvarsym(p)^.vartype.def^.needs_inittable then
  380. begin
  381. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  382. reset_reference(hr);
  383. if psym(p)^.owner^.symtabletype=localsymtable then
  384. begin
  385. hr.base:=procinfo^.framepointer;
  386. hr.offset:=-pvarsym(p)^.address;
  387. end
  388. else
  389. begin
  390. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  391. end;
  392. g_initialize(list,pvarsym(p)^.vartype.def,hr,false);
  393. end;
  394. {$ENDIF NEWST}
  395. end;
  396. { generates the code for incrementing the reference count of parameters }
  397. procedure tcg.g_incr_data(list : paasmoutput;p : psym);
  398. var
  399. hr : treference;
  400. begin
  401. {$IFDEF NEWST}
  402. if (typeof((psym(p)^))=typeof(Tparamsym)) and
  403. not((typeof((Pparamsym(p)^.definition^))=typeof(Tobjectdef)) and
  404. (oo_is_class in pobjectdef(pvarsym(p)^.definition)^.options)) and
  405. Pparamsym(p)^.definition^.needs_inittable and
  406. ((Pparamsym(p)^.varspez=vs_value)) then
  407. begin
  408. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  409. reset_reference(hr);
  410. hr.symbol:=pvarsym(p)^.definition^.get_inittable_label;
  411. a_param_ref_addr(list,hr,2);
  412. reset_reference(hr);
  413. hr.base:=procinfo^.framepointer;
  414. hr.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  415. a_param_ref_addr(list,hr,1);
  416. reset_reference(hr);
  417. a_call_name(list,'FPC_ADDREF',0);
  418. end;
  419. {$ELSE}
  420. if (psym(p)^.typ=varsym) and
  421. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  422. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  423. pvarsym(p)^.vartype.def^.needs_inittable and
  424. ((pvarsym(p)^.varspez=vs_value)) then
  425. begin
  426. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  427. reset_reference(hr);
  428. hr.symbol:=pvarsym(p)^.vartype.def^.get_inittable_label;
  429. a_param_ref_addr(list,hr,2);
  430. reset_reference(hr);
  431. hr.base:=procinfo^.framepointer;
  432. hr.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  433. a_param_ref_addr(list,hr,1);
  434. reset_reference(hr);
  435. a_call_name(list,'FPC_ADDREF',0);
  436. end;
  437. {$ENDIF NEWST}
  438. end;
  439. { generates the code for finalisation of local data }
  440. procedure tcg.g_finalize_data(list : paasmoutput;p : pnamedindexobject);
  441. var
  442. hr : treference;
  443. begin
  444. {$IFDEF NEWST}
  445. if (typeof((psym(p)^))=typeof(Tvarsym)) and
  446. assigned(pvarsym(p)^.definition) and
  447. not((typeof((pvarsym(p)^.definition^))=typeof(Tobjectdef)) and
  448. (oo_is_class in pobjectdef(pvarsym(p)^.definition)^.options)) and
  449. pvarsym(p)^.definition^.needs_inittable then
  450. begin
  451. { not all kind of parameters need to be finalized }
  452. if (typeof((psym(p)^.owner^))=typeof(Tprocsymtable)) and
  453. ((pparamsym(p)^.varspez=vs_var) or
  454. (Pparamsym(p)^.varspez=vs_const) { and
  455. (dont_copy_const_param(pvarsym(p)^.definition)) } ) then
  456. exit;
  457. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  458. reset_reference(hr);
  459. if typeof((Psym(p)^.owner^))=typeof(Tprocsymtable) then
  460. begin
  461. hr.base:=procinfo^.framepointer;
  462. hr.offset:=-pvarsym(p)^.address;
  463. end
  464. else if typeof((Psym(p)^.owner^))=typeof(Tprocsymtable) then
  465. begin
  466. hr.base:=procinfo^.framepointer;
  467. hr.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  468. end
  469. else
  470. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  471. g_finalize(list,pvarsym(p)^.definition,hr,false);
  472. end;
  473. {$ELSE}
  474. if (psym(p)^.typ=varsym) and
  475. assigned(pvarsym(p)^.vartype.def) and
  476. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  477. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  478. pvarsym(p)^.vartype.def^.needs_inittable then
  479. begin
  480. { not all kind of parameters need to be finalized }
  481. if (psym(p)^.owner^.symtabletype=parasymtable) and
  482. ((pvarsym(p)^.varspez=vs_var) or
  483. (pvarsym(p)^.varspez=vs_const) { and
  484. (dont_copy_const_param(pvarsym(p)^.definition)) } ) then
  485. exit;
  486. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  487. reset_reference(hr);
  488. case psym(p)^.owner^.symtabletype of
  489. localsymtable:
  490. begin
  491. hr.base:=procinfo^.framepointer;
  492. hr.offset:=-pvarsym(p)^.address;
  493. end;
  494. parasymtable:
  495. begin
  496. hr.base:=procinfo^.framepointer;
  497. hr.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  498. end;
  499. else
  500. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  501. end;
  502. g_finalize(list,pvarsym(p)^.vartype.def,hr,false);
  503. end;
  504. {$ENDIF NEWST}
  505. end;
  506. { generates the code to make local copies of the value parameters }
  507. procedure tcg.g_copyvalueparas(list : paasmoutput;p : pnamedindexobject);
  508. begin
  509. runerror(255);
  510. end;
  511. var
  512. _list : paasmoutput;
  513. { wrappers for the methods, because TP doesn't know procedures }
  514. { of objects }
  515. {$IFNDEF NEWST}
  516. procedure _copyvalueparas(s : pnamedindexobject);{$ifndef FPC}far;{$endif}
  517. begin
  518. cg^.g_copyvalueparas(_list,s);
  519. end;
  520. {$ENDIF NEWST}
  521. procedure tcg.g_finalizetempansistrings(list : paasmoutput);
  522. var
  523. hp : ptemprecord;
  524. hr : treference;
  525. begin
  526. hp:=tg.templist;
  527. while assigned(hp) do
  528. begin
  529. if hp^.temptype in [tt_ansistring,tt_freeansistring] then
  530. begin
  531. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  532. reset_reference(hr);
  533. hr.base:=procinfo^.framepointer;
  534. hr.offset:=hp^.pos;
  535. a_param_ref_addr(list,hr,1);
  536. a_call_name(list,'FPC_ANSISTR_DECR_REF',0);
  537. end;
  538. hp:=hp^.next;
  539. end;
  540. end;
  541. {$IFDEF NEWST}
  542. procedure _initialize_local(s:Pnamedindexobject);{$IFNDEF FPC}far;{$ENDIF}
  543. begin
  544. if typeof(s^)=typeof(Tparamsym) then
  545. cg^.g_incr_data(_list,Psym(s))
  546. else
  547. cg^.g_initialize_data(_list,Psym(s));
  548. end;
  549. procedure _finalize_data(s : pnamedindexobject);{$ifndef FPC}far;{$endif}
  550. begin
  551. if typeof(s^)=typeof(Tvarsym) then
  552. cg^.g_finalize_data(_list,s);
  553. end;
  554. {$ELSE}
  555. procedure _finalize_data(s : pnamedindexobject);{$ifndef FPC}far;{$endif}
  556. begin
  557. cg^.g_finalize_data(_list,s);
  558. end;
  559. procedure _incr_data(s : pnamedindexobject);{$ifndef FPC}far;{$endif}
  560. begin
  561. cg^.g_incr_data(_list,psym(s));
  562. end;
  563. procedure _initialize_data(s : pnamedindexobject);{$ifndef FPC}far;{$endif}
  564. begin
  565. cg^.g_initialize_data(_list,psym(s));
  566. end;
  567. {$ENDIF NEWST}
  568. { generates the entry code for a procedure }
  569. procedure tcg.g_entrycode(list : paasmoutput;const proc_names:Tstringcontainer;make_global:boolean;
  570. stackframe:longint;var parasize:longint;var nostackframe:boolean;
  571. inlined : boolean);
  572. {$IFDEF NEWST}
  573. procedure _copyvalueparas(s:Pparamsym);{$ifndef FPC}far;{$endif}
  574. begin
  575. cg^.g_copyvalueparas(_list,s);
  576. end;
  577. {$ENDIF NEWST}
  578. var
  579. hs : string;
  580. hp : pused_unit;
  581. initcode : taasmoutput;
  582. {$ifdef GDB}
  583. stab_function_name : Pai_stab_function_name;
  584. {$endif GDB}
  585. hr : treference;
  586. r : tregister;
  587. begin
  588. { Align }
  589. if (not inlined) then
  590. begin
  591. { gprof uses 16 byte granularity !! }
  592. if (cs_profile in aktmoduleswitches) then
  593. list^.insert(new(pai_align,init(16)))
  594. else
  595. if not(cs_littlesize in aktglobalswitches) then
  596. list^.insert(new(pai_align,init(4)));
  597. end;
  598. { save registers on cdecl }
  599. {$IFDEF NEWST}
  600. if (posavestdregs in aktprocdef^.options) then
  601. {$ELSE}
  602. if (po_savestdregs in aktprocsym^.definition^.procoptions) then
  603. {$ENDIF NEWST}
  604. begin
  605. for r:=firstreg to lastreg do
  606. begin
  607. if (r in registers_saved_on_cdecl) then
  608. if (r in (tg.availabletempregsint+
  609. tg.availabletempregsfpu+
  610. tg.availabletempregsmm)) then
  611. begin
  612. if not(r in tg.usedinproc) then
  613. {!!!!!!!!!!!! a_push_reg(list,r) }
  614. end
  615. else
  616. {!!!!!!!! a_push_reg(list,r) };
  617. end;
  618. end;
  619. { omit stack frame ? }
  620. if not inlined then
  621. if procinfo^.framepointer=stack_pointer then
  622. begin
  623. CGMessage(cg_d_stackframe_omited);
  624. nostackframe:=true;
  625. {$IFDEF NEWST}
  626. if (aktprocdef^.proctype in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  627. parasize:=0
  628. else
  629. parasize:=aktprocdef^.localst^.paramdatasize+procinfo^.para_offset-pointersize;
  630. {$ELSE}
  631. if (aktprocsym^.definition^.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  632. parasize:=0
  633. else
  634. parasize:=aktprocsym^.definition^.parast^.datasize+procinfo^.para_offset-pointersize;
  635. {$ENDIF NEWST}
  636. end
  637. else
  638. begin
  639. {$IFDEF NEWST}
  640. if (aktprocdef^.proctype in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  641. parasize:=0
  642. else
  643. parasize:=aktprocdef^.localst^.paramdatasize+procinfo^.para_offset-pointersize*2;
  644. {$ELSE}
  645. if (aktprocsym^.definition^.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  646. parasize:=0
  647. else
  648. parasize:=aktprocsym^.definition^.parast^.datasize+procinfo^.para_offset-pointersize*2;
  649. {$ENDIF}
  650. nostackframe:=false;
  651. {$IFDEF NEWST}
  652. if (pointerrupt in aktprocdef^.options) then
  653. g_interrupt_stackframe_entry(list);
  654. {$ELSE}
  655. if (po_interrupt in aktprocsym^.definition^.procoptions) then
  656. g_interrupt_stackframe_entry(list);
  657. {$ENDIF NEWST}
  658. g_stackframe_entry(list,stackframe);
  659. if (cs_check_stack in aktlocalswitches) and
  660. (tf_supports_stack_checking in target_info.flags) then
  661. g_stackcheck(@initcode,stackframe);
  662. end;
  663. if cs_profile in aktmoduleswitches then
  664. g_profilecode(@initcode);
  665. {$IFDEF NEWST}
  666. if (not inlined) and (aktprocdef^.proctype in [potype_unitinit]) then
  667. {$ELSE}
  668. if (not inlined) and (aktprocsym^.definition^.proctypeoption in [potype_unitinit]) then
  669. {$ENDIF NEWST}
  670. begin
  671. { needs the target a console flags ? }
  672. if tf_needs_isconsole in target_info.flags then
  673. begin
  674. hr.symbol:=newasmsymbol('U_'+target_info.system_unit+'_ISCONSOLE');
  675. if apptype=at_cui then
  676. a_load_const_ref(list,OS_8,1,hr)
  677. else
  678. a_load_const_ref(list,OS_8,0,hr);
  679. dispose(hr.symbol,done);
  680. end;
  681. hp:=pused_unit(usedunits.first);
  682. while assigned(hp) do
  683. begin
  684. { call the unit init code and make it external }
  685. if (hp^.u^.flags and uf_init)<>0 then
  686. a_call_name(list,
  687. 'INIT$$'+hp^.u^.modulename^,0);
  688. hp:=Pused_unit(hp^.next);
  689. end;
  690. end;
  691. {$ifdef dummy}
  692. { a constructor needs a help procedure }
  693. if (aktprocsym^.definition^.options and poconstructor)<>0 then
  694. begin
  695. if procinfo^._class^.isclass then
  696. begin
  697. list^.concat(new(paicpu,op_sym(A_CALL,S_NO,newasmsymbol('FPC_NEW_CLASS'))));
  698. list^.concat(new(paicpu,op_cond_sym(A_Jcc,C_Z,S_NO,quickexitlabel)));
  699. end
  700. else
  701. begin
  702. {
  703. list^.insert(new(pai_labeled,init(A_JZ,quickexitlabel)));
  704. list^.insert(new(paicpu,op_csymbol(A_CALL,S_NO,
  705. newcsymbol('FPC_HELP_CONSTRUCTOR',0))));
  706. list^.insert(new(paicpu,op_const_reg(A_MOV,S_L,procinfo^._class^.vmt_offset,R_EDI)));
  707. concat_external('FPC_HELP_CONSTRUCTOR',EXT_NEAR);
  708. }
  709. end;
  710. end;
  711. {$endif dummy}
  712. {$ifdef GDB}
  713. if (cs_debuginfo in aktmoduleswitches) then
  714. list^.insert(new(pai_force_line,init));
  715. {$endif GDB}
  716. {$IFDEF NEWST}
  717. { initialize return value }
  718. if assigned(procinfo^.retdef) and
  719. is_ansistring(procinfo^.retdef) or
  720. is_widestring(procinfo^.retdef) then
  721. begin
  722. reset_reference(hr);
  723. hr.offset:=procinfo^.return_offset;
  724. hr.base:=procinfo^.framepointer;
  725. a_load_const_ref(list,OS_32,0,hr);
  726. end;
  727. {$ELSE}
  728. { initialize return value }
  729. if assigned(procinfo^.returntype.def) and
  730. is_ansistring(procinfo^.returntype.def) or
  731. is_widestring(procinfo^.returntype.def) then
  732. begin
  733. reset_reference(hr);
  734. hr.offset:=procinfo^.return_offset;
  735. hr.base:=procinfo^.framepointer;
  736. a_load_const_ref(list,OS_32,0,hr);
  737. end;
  738. {$ENDIF}
  739. _list:=list;
  740. { generate copies of call by value parameters }
  741. {$IFDEF NEWST}
  742. if (poassembler in aktprocdef^.options) then
  743. aktprocdef^.parameters^.foreach(@_copyvalueparas);
  744. {$ELSE}
  745. if (po_assembler in aktprocsym^.definition^.procoptions) then
  746. aktprocsym^.definition^.parast^.foreach({$ifdef FPC}@{$endif FPC}_copyvalueparas);
  747. {$ENDIF NEWST}
  748. {$IFDEF NEWST}
  749. { initialisizes local data }
  750. aktprocdef^.localst^.foreach({$ifdef FPC}@{$endif FPC}_initialize_local);
  751. {$ELSE}
  752. { initialisizes local data }
  753. aktprocsym^.definition^.localst^.foreach({$ifdef FPC}@{$endif FPC}_initialize_data);
  754. { add a reference to all call by value/const parameters }
  755. aktprocsym^.definition^.parast^.foreach({$ifdef FPC}@{$endif FPC}_incr_data);
  756. {$ENDIF NEWST}
  757. {$IFDEF NEWST}
  758. if (cs_profile in aktmoduleswitches) or
  759. (typeof(aktprocdef^.owner^)=typeof(Tglobalsymtable)) or
  760. (typeof(aktprocdef^.owner^)=typeof(Timplsymtable)) or
  761. (assigned(procinfo^._class) and
  762. (typeof(procinfo^._class^.owner^)=typeof(Tglobalsymtable)) or
  763. (typeof(procinfo^._class^.owner^)=typeof(Timplsymtable))) then
  764. make_global:=true;
  765. {$ELSE}
  766. if (cs_profile in aktmoduleswitches) or
  767. (aktprocsym^.definition^.owner^.symtabletype=globalsymtable) or
  768. (assigned(procinfo^._class) and (procinfo^._class^.owner^.symtabletype=globalsymtable)) then
  769. make_global:=true;
  770. {$ENDIF NEWST}
  771. if not inlined then
  772. begin
  773. hs:=proc_names.get;
  774. {$ifdef GDB}
  775. if (cs_debuginfo in aktmoduleswitches) and target_os.use_function_relative_addresses then
  776. stab_function_name := new(pai_stab_function_name,init(strpnew(hs)));
  777. {$endif GDB}
  778. { insert the names for the procedure }
  779. while hs<>'' do
  780. begin
  781. if make_global then
  782. exprasmlist^.insert(new(pai_symbol,initname_global(hs,0)))
  783. else
  784. exprasmlist^.insert(new(pai_symbol,initname(hs,0)));
  785. {$ifdef GDB}
  786. if (cs_debuginfo in aktmoduleswitches) then
  787. begin
  788. if target_os.use_function_relative_addresses then
  789. list^.insert(new(pai_stab_function_name,init(strpnew(hs))));
  790. end;
  791. {$endif GDB}
  792. hs:=proc_names.get;
  793. end;
  794. end;
  795. {$ifdef GDB}
  796. if (not inlined) and (cs_debuginfo in aktmoduleswitches) then
  797. begin
  798. if target_os.use_function_relative_addresses then
  799. list^.insert(stab_function_name);
  800. if make_global or ((procinfo^.flags and pi_is_global) <> 0) then
  801. aktprocsym^.is_global := True;
  802. list^.insert(new(pai_stabs,init(aktprocsym^.stabstring)));
  803. aktprocsym^.isstabwritten:=true;
  804. end;
  805. {$endif GDB}
  806. end;
  807. procedure tcg.g_exitcode(list : paasmoutput;parasize:longint;nostackframe,inlined:boolean);
  808. var
  809. {$ifdef GDB}
  810. mangled_length : longint;
  811. p : pchar;
  812. {$endif GDB}
  813. nofinal,noreraiselabel : pasmlabel;
  814. hr : treference;
  815. r : tregister;
  816. begin
  817. if aktexitlabel^.is_used then
  818. list^.insert(new(pai_label,init(aktexitlabel)));
  819. { call the destructor help procedure }
  820. {$IFDEF NEWST}
  821. if (aktprocdef^.proctype=potype_destructor) then
  822. {$ELSE}
  823. if (aktprocsym^.definition^.proctypeoption=potype_destructor) then
  824. {$ENDIF}
  825. begin
  826. {$IFDEF NEWST}
  827. if oo_is_class in procinfo^._class^.options then
  828. {$ELSE NEWST}
  829. if procinfo^._class^.is_class then
  830. {$ENDIF}
  831. a_call_name(list,'FPC_DISPOSE_CLASS',0)
  832. else
  833. begin
  834. if procinfo^._class^.needs_inittable then
  835. begin
  836. getlabel(nofinal);
  837. {!!!!!!!!!!
  838. reset_reference(hr);
  839. hr.base:=R_EBP;
  840. hr.offset:=8;
  841. a_cmp_reg_const_label(list,OS_ADDR,OZ_EQ,
  842. }
  843. reset_reference(hr);
  844. hr.symbol:=procinfo^._class^.get_inittable_label;
  845. a_paramaddr_ref(list,hr,2);
  846. a_param_reg(list,OS_ADDR,self_pointer,1);
  847. a_call_name(list,'FPC_FINALIZE',0);
  848. a_label(list,nofinal);
  849. end;
  850. { vmt_offset_reg can be a scratch register, }
  851. { but it must be always the same }
  852. a_reg_alloc(list,vmt_offset_reg);
  853. a_load_const_reg(list,OS_32,procinfo^._class^.vmt_offset,vmt_offset_reg);
  854. a_call_name(list,'FPC_HELP_DESTRUCTOR',0);
  855. a_reg_dealloc(list,vmt_offset_reg);
  856. end;
  857. end;
  858. { finalize temporary data }
  859. g_finalizetempansistrings(list);
  860. _list:=list;
  861. { finalize local data }
  862. {$IFDEF NEWST}
  863. aktprocdef^.localst^.foreach({$ifndef TP}@{$endif}_finalize_data);
  864. {$ELSE}
  865. aktprocsym^.definition^.localst^.foreach({$ifndef TP}@{$endif}_finalize_data);
  866. {$ENDIF}
  867. {$IFNDEF NEWST}
  868. { finalize paras data }
  869. if assigned(aktprocsym^.definition^.parast) then
  870. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}_finalize_data);
  871. {$ENDIF NEWST}
  872. { do we need to handle exceptions because of ansi/widestrings ? }
  873. if (procinfo^.flags and pi_needs_implicit_finally)<>0 then
  874. begin
  875. getlabel(noreraiselabel);
  876. a_call_name(list,'FPC_POPADDRSTACK',0);
  877. a_reg_alloc(list,accumulator);
  878. g_pop_exception_value_reg(list,accumulator);
  879. a_cmp_reg_const_label(list,OS_32,OC_EQ,0,accumulator,noreraiselabel);
  880. a_reg_dealloc(list,accumulator);
  881. {$IFDEF NEWST}
  882. { must be the return value finalized before reraising the exception? }
  883. if (procinfo^.retdef<>pdef(voiddef)) and
  884. (procinfo^.retdef^.needs_inittable) and
  885. ((typeof(procinfo^.retdef^)<>typeof(Tobjectdef)) or
  886. not(oo_is_class in pobjectdef(procinfo^.retdef)^.options)) then
  887. begin
  888. reset_reference(hr);
  889. hr.offset:=procinfo^.return_offset;
  890. hr.base:=procinfo^.framepointer;
  891. g_finalize(list,procinfo^.retdef,hr,not (dp_ret_in_acc in procinfo^.retdef^.properties));
  892. end;
  893. {$ELSE}
  894. { must be the return value finalized before reraising the exception? }
  895. if (procinfo^.returntype.def<>pdef(voiddef)) and
  896. (procinfo^.returntype.def^.needs_inittable) and
  897. ((procinfo^.returntype.def^.deftype<>objectdef) or
  898. not(pobjectdef(procinfo^.returntype.def)^.is_class)) then
  899. begin
  900. reset_reference(hr);
  901. hr.offset:=procinfo^.return_offset;
  902. hr.base:=procinfo^.framepointer;
  903. g_finalize(list,procinfo^.returntype.def,hr,ret_in_param(procinfo^.returntype.def));
  904. end;
  905. {$ENDIF}
  906. a_call_name(list,'FPC_RERAISE',0);
  907. a_label(list,noreraiselabel);
  908. end;
  909. { call __EXIT for main program }
  910. {$IFDEF NEWST}
  911. if (not DLLsource) and (not inlined) and (aktprocdef^.proctype=potype_proginit) then
  912. a_call_name(list,'FPC_DO_EXIT',0);
  913. {$ELSE}
  914. if (not DLLsource) and (not inlined) and (aktprocsym^.definition^.proctypeoption=potype_proginit) then
  915. a_call_name(list,'FPC_DO_EXIT',0);
  916. {$ENDIF NEWST}
  917. { handle return value }
  918. {$IFDEF NEWST}
  919. if not(poassembler in aktprocdef^.options) then
  920. if (aktprocdef^.proctype<>potype_constructor) then
  921. {$ELSE}
  922. if not(po_assembler in aktprocsym^.definition^.procoptions) then
  923. if (aktprocsym^.definition^.proctypeoption<>potype_constructor) then
  924. {$ENDIF NEWST}
  925. { handle_return_value(inlined) }
  926. else
  927. begin
  928. { return self in EAX }
  929. a_label(list,quickexitlabel);
  930. a_reg_alloc(list,accumulator);
  931. a_load_reg_reg(list,OS_ADDR,self_pointer,accumulator);
  932. a_reg_dealloc(list,self_pointer);
  933. a_label(list,quickexitlabel);
  934. { we can't clear the zero flag because the Alpha }
  935. { for example doesn't have flags, we have to compare }
  936. { the accu. in the caller }
  937. end;
  938. { stabs uses the label also ! }
  939. if aktexit2label^.is_used or
  940. ((cs_debuginfo in aktmoduleswitches) and not inlined) then
  941. a_label(list,aktexit2label);
  942. {$ifdef dummy}
  943. { should we restore edi ? }
  944. { for all i386 gcc implementations }
  945. {!!!!!!!!!!! I don't know how to handle register saving yet }
  946. if (po_savestdregs in aktprocsym^.definition^.procoptions) then
  947. begin
  948. if (aktprocsym^.definition^.usedregisters and ($80 shr byte(R_EBX)))<>0 then
  949. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_EBX)));
  950. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ESI)));
  951. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_EDI)));
  952. { here we could reset R_EBX
  953. but that is risky because it only works
  954. if genexitcode is called after genentrycode
  955. so lets skip this for the moment PM
  956. aktprocsym^.definition^.usedregisters:=
  957. aktprocsym^.definition^.usedregisters or not ($80 shr byte(R_EBX));
  958. }
  959. end;
  960. {$endif dummy}
  961. if not(nostackframe) and not inlined then
  962. g_restore_frame_pointer(list);
  963. { at last, the return is generated }
  964. if not inlined then
  965. {$IFDEF NEWST}
  966. if pointerrupt in aktprocdef^.options then
  967. {$ELSE}
  968. if po_interrupt in aktprocsym^.definition^.procoptions then
  969. {$ENDIF NEWST}
  970. g_interrupt_stackframe_exit(list)
  971. else
  972. g_return_from_proc(list,parasize);
  973. {$IFDEF NEWST}
  974. list^.concat(new(pai_symbol_end,initname(aktprocdef^.mangledname)));
  975. {$ELSE NEWST}
  976. list^.concat(new(pai_symbol_end,initname(aktprocsym^.definition^.mangledname)));
  977. {$ENDIF NEWST}
  978. {$ifdef GDB}
  979. if (cs_debuginfo in aktmoduleswitches) and not inlined then
  980. begin
  981. aktprocsym^.concatstabto(list);
  982. if assigned(procinfo^._class) then
  983. if (not assigned(procinfo^.parent) or
  984. not assigned(procinfo^.parent^._class)) then
  985. list^.concat(new(pai_stabs,init(strpnew(
  986. '"$t:v'+procinfo^._class^.numberstring+'",'+
  987. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.selfpointer_offset)))));
  988. {!!!!!!!!!!!!
  989. else
  990. list^.concat(new(pai_stabs,init(strpnew(
  991. '"$t:r'+procinfo^._class^.numberstring+'",'+
  992. tostr(N_RSYM)+',0,0,'+tostr(GDB_i386index[R_ESI])))));
  993. }
  994. if (pdef(aktprocsym^.definition^.rettype.def) <> pdef(voiddef)) then
  995. begin
  996. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  997. list^.concat(new(pai_stabs,init(strpnew(
  998. '"'+aktprocsym^.name+':X*'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  999. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))))
  1000. else
  1001. list^.concat(new(pai_stabs,init(strpnew(
  1002. '"'+aktprocsym^.name+':X'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  1003. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))));
  1004. if (m_result in aktmodeswitches) then
  1005. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  1006. list^.concat(new(pai_stabs,init(strpnew(
  1007. '"RESULT:X*'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  1008. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))))
  1009. else
  1010. list^.concat(new(pai_stabs,init(strpnew(
  1011. '"RESULT:X'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  1012. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))));
  1013. end;
  1014. mangled_length:=length(aktprocsym^.definition^.mangledname);
  1015. getmem(p,mangled_length+50);
  1016. strpcopy(p,'192,0,0,');
  1017. strpcopy(strend(p),aktprocsym^.definition^.mangledname);
  1018. list^.concat(new(pai_stabn,init(strnew(p))));
  1019. {list^.concat(new(pai_stabn,init(strpnew('192,0,0,'
  1020. +aktprocsym^.definition^.mangledname))));
  1021. p[0]:='2';p[1]:='2';p[2]:='4';
  1022. strpcopy(strend(p),'_end');}
  1023. freemem(p,mangled_length+50);
  1024. list^.concat(new(pai_stabn,init(
  1025. strpnew('224,0,0,'+aktexit2label^.name))));
  1026. { strpnew('224,0,0,'
  1027. +aktprocsym^.definition^.mangledname+'_end'))));}
  1028. end;
  1029. {$endif GDB}
  1030. end;
  1031. {*****************************************************************************
  1032. some abstract definitions
  1033. ****************************************************************************}
  1034. procedure tcg.a_call_name(list : paasmoutput;const s : string;
  1035. offset : longint);
  1036. begin
  1037. abstract;
  1038. end;
  1039. procedure tcg.g_stackframe_entry(list : paasmoutput;localsize : longint);
  1040. begin
  1041. abstract;
  1042. end;
  1043. procedure tcg.g_maybe_loadself(list : paasmoutput);
  1044. begin
  1045. abstract;
  1046. end;
  1047. procedure tcg.g_restore_frame_pointer(list : paasmoutput);
  1048. begin
  1049. abstract;
  1050. end;
  1051. procedure g_return_from_proc(list : paasmoutput;parasize : aword);
  1052. begin
  1053. abstract;
  1054. end;
  1055. procedure tcg.a_loadaddress_ref_reg(list : paasmoutput;const ref : treference;r : tregister);
  1056. begin
  1057. abstract;
  1058. end;
  1059. procedure tcg.g_push_exception_value_reg(list : paasmoutput;reg : tregister);
  1060. begin
  1061. abstract;
  1062. end;
  1063. procedure tcg.g_push_exception_value_const(list : paasmoutput;reg : tregister);
  1064. begin
  1065. abstract;
  1066. end;
  1067. procedure tcg.g_pop_exception_value_reg(list : paasmoutput;reg : tregister);
  1068. begin
  1069. abstract;
  1070. end;
  1071. procedure tcg.a_load_const_reg(list : paasmoutput;size : tcgsize;a : aword;register : tregister);
  1072. begin
  1073. abstract;
  1074. end;
  1075. procedure tcg.a_load_reg_ref(list : paasmoutput;size : tcgsize;register : tregister;const ref : treference);
  1076. begin
  1077. abstract;
  1078. end;
  1079. procedure tcg.a_load_ref_reg(list : paasmoutput;size : tcgsize;const ref : treference;register : tregister);
  1080. begin
  1081. abstract;
  1082. end;
  1083. procedure tcg.a_load_reg_reg(list : paasmoutput;size : tcgsize;reg1,reg2 : tregister);
  1084. begin
  1085. abstract;
  1086. end;
  1087. procedure tcg.a_cmp_reg_const_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  1088. l : pasmlabel);
  1089. begin
  1090. abstract;
  1091. end;
  1092. procedure tcg.a_cmp_reg_reg_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : pasmlabel);
  1093. begin
  1094. abstract;
  1095. end;
  1096. procedure tcg.a_cmp_reg_ref_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;reg : tregister;l : pasmlabel);
  1097. begin
  1098. abstract;
  1099. end;
  1100. procedure tcg.a_cmp_ref_const_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  1101. l : pasmlabel);
  1102. begin
  1103. abstract;
  1104. end;
  1105. procedure tcg.a_jmp_cond(list : paasmoutput;cond : TOpCmp;l: pasmlabel);
  1106. begin
  1107. abstract;
  1108. end;
  1109. procedure tcg.g_return_from_proc(list : paasmoutput;parasize : aword);
  1110. begin
  1111. abstract;
  1112. end;
  1113. procedure tcg.a_param_reg(list : paasmoutput;size : tcgsize;r : tregister;nr : longint);
  1114. begin
  1115. abstract;
  1116. end;
  1117. procedure tcg.a_paramaddr_ref(list : paasmoutput;const r : treference;nr : longint);
  1118. begin
  1119. abstract;
  1120. end;
  1121. end.
  1122. {
  1123. $Log$
  1124. Revision 1.1 2000-07-13 06:30:07 michael
  1125. + Initial import
  1126. Revision 1.38 2000/04/29 09:01:06 jonas
  1127. * nmem compiles again (at least for powerpc)
  1128. Revision 1.37 2000/04/22 14:25:03 jonas
  1129. * aasm.pas: pai_align instead of pai_align_abstract if cpu <> i386
  1130. + systems.pas: info for macos/ppc
  1131. * new/cgobj.pas: compiles again without newst define
  1132. * new/powerpc/cgcpu: generate different entry/exit code depending on
  1133. whether target_os is MacOs or Linux
  1134. Revision 1.36 2000/03/11 21:11:24 daniel
  1135. * Ported hcgdata to new symtable.
  1136. * Alignment code changed as suggested by Peter
  1137. + Usage of my is operator replacement, is_object
  1138. Revision 1.35 2000/03/01 15:36:13 florian
  1139. * some new stuff for the new cg
  1140. Revision 1.34 2000/02/20 20:49:46 florian
  1141. * newcg is compiling
  1142. * fixed the dup id problem reported by Paul Y.
  1143. Revision 1.33 2000/01/07 01:14:53 peter
  1144. * updated copyright to 2000
  1145. Revision 1.32 1999/12/01 12:42:33 peter
  1146. * fixed bug 698
  1147. * removed some notes about unused vars
  1148. Revision 1.31 1999/11/05 13:15:00 florian
  1149. * some fixes to get the new cg compiling again
  1150. Revision 1.30 1999/11/05 07:05:56 jonas
  1151. + a_jmp_cond()
  1152. Revision 1.29 1999/10/21 16:41:41 florian
  1153. * problems with readln fixed: esi wasn't restored correctly when
  1154. reading ordinal fields of objects futher the register allocation
  1155. didn't take care of the extra register when reading ordinal values
  1156. * enumerations can now be used in constant indexes of properties
  1157. Revision 1.28 1999/10/12 21:20:46 florian
  1158. * new codegenerator compiles again
  1159. Revision 1.27 1999/09/29 11:46:20 florian
  1160. * fixed bug 292 from bugs directory
  1161. Revision 1.26 1999/09/14 11:16:09 florian
  1162. * only small updates to work with the current compiler
  1163. Revision 1.25 1999/09/03 13:09:09 jonas
  1164. * fixed typo regarding scratchregs pointer
  1165. Revision 1.24 1999/08/26 14:51:54 jonas
  1166. * changed get_scratch_reg so it actually uses the
  1167. scratch_reg_array_pointer
  1168. Revision 1.23 1999/08/25 12:00:11 jonas
  1169. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  1170. Revision 1.22 1999/08/18 17:05:55 florian
  1171. + implemented initilizing of data for the new code generator
  1172. so it should compile now simple programs
  1173. Revision 1.21 1999/08/07 14:21:08 florian
  1174. * some small problems fixed
  1175. Revision 1.20 1999/08/06 18:05:52 florian
  1176. * implemented some stuff for assignments
  1177. Revision 1.19 1999/08/06 17:00:54 florian
  1178. + definition of concatcopy
  1179. Revision 1.18 1999/08/06 16:37:45 jonas
  1180. * completed bugfix done by Florian o I wouldn't get conflicts :)
  1181. Revision 1.17 1999/08/06 16:27:26 florian
  1182. * for Jonas: else he will get conflicts
  1183. Revision 1.16 1999/08/06 16:04:05 michael
  1184. + introduced tainstruction
  1185. Revision 1.15 1999/08/06 15:53:50 florian
  1186. * made the alpha version compilable
  1187. Revision 1.14 1999/08/06 14:15:51 florian
  1188. * made the alpha version compilable
  1189. Revision 1.13 1999/08/06 13:26:50 florian
  1190. * more changes ...
  1191. Revision 1.12 1999/08/05 17:10:56 florian
  1192. * some more additions, especially procedure
  1193. exit code generation
  1194. Revision 1.11 1999/08/05 14:58:11 florian
  1195. * some fixes for the floating point registers
  1196. * more things for the new code generator
  1197. Revision 1.10 1999/08/04 00:23:52 florian
  1198. * renamed i386asm and i386base to cpuasm and cpubase
  1199. Revision 1.9 1999/08/02 23:13:21 florian
  1200. * more changes to compile for the Alpha
  1201. Revision 1.8 1999/08/02 17:14:07 florian
  1202. + changed the temp. generator to an object
  1203. Revision 1.7 1999/08/01 23:05:55 florian
  1204. * changes to compile with FPC
  1205. Revision 1.6 1999/08/01 18:22:33 florian
  1206. * made it again compilable
  1207. Revision 1.5 1999/01/23 23:29:46 florian
  1208. * first running version of the new code generator
  1209. * when compiling exceptions under Linux fixed
  1210. Revision 1.4 1999/01/13 22:52:36 florian
  1211. + YES, finally the new code generator is compilable, but it doesn't run yet :(
  1212. Revision 1.3 1998/12/26 15:20:30 florian
  1213. + more changes for the new version
  1214. Revision 1.2 1998/12/15 22:18:55 florian
  1215. * some code added
  1216. Revision 1.1 1998/12/15 16:32:58 florian
  1217. + first version, derived from old routines
  1218. }