cgobj.pas 54 KB

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