cgobj.pas 57 KB

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