cgobj.pas 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323
  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. const
  173. max_scratch_regs = high(scratch_regs) - low(scratch_regs) + 1;
  174. {*****************************************************************************
  175. basic functionallity
  176. ******************************************************************************}
  177. constructor tcg.create;
  178. var
  179. i : longint;
  180. begin
  181. scratch_register_array_pointer:=1;
  182. for i:=low(scratch_regs) to high(scratch_regs) do
  183. include(unusedscratchregisters,scratch_regs[i]);
  184. end;
  185. procedure tcg.a_reg_alloc(list : taasmoutput;r : tregister);
  186. begin
  187. list.concat(tairegalloc.alloc(r));
  188. end;
  189. procedure tcg.a_reg_dealloc(list : taasmoutput;r : tregister);
  190. begin
  191. list.concat(tairegalloc.dealloc(r));
  192. end;
  193. procedure tcg.a_label(list : taasmoutput;l : tasmlabel);
  194. begin
  195. list.concat(tai_label.create(l));
  196. end;
  197. function tcg.get_scratch_reg(list : taasmoutput) : tregister;
  198. var
  199. r : tregister;
  200. i : longint;
  201. begin
  202. if unusedscratchregisters=[] then
  203. internalerror(68996);
  204. for i:=scratch_register_array_pointer to
  205. (scratch_register_array_pointer+max_scratch_regs-1) do
  206. if scratch_regs[(i mod max_scratch_regs)+1] in unusedscratchregisters then
  207. begin
  208. r:=scratch_regs[(i mod max_scratch_regs)+1];
  209. break;
  210. end;
  211. exclude(unusedscratchregisters,r);
  212. inc(scratch_register_array_pointer);
  213. if scratch_register_array_pointer>max_scratch_regs then
  214. scratch_register_array_pointer:=1;
  215. a_reg_alloc(list,r);
  216. get_scratch_reg:=r;
  217. end;
  218. procedure tcg.free_scratch_reg(list : taasmoutput;r : tregister);
  219. begin
  220. include(unusedscratchregisters,makereg32(r));
  221. a_reg_dealloc(list,r);
  222. end;
  223. {*****************************************************************************
  224. this methods must be overridden for extra functionality
  225. ******************************************************************************}
  226. procedure tcg.g_interrupt_stackframe_entry(list : taasmoutput);
  227. begin
  228. end;
  229. procedure tcg.g_interrupt_stackframe_exit(list : taasmoutput);
  230. begin
  231. end;
  232. procedure tcg.g_profilecode(list : taasmoutput);
  233. begin
  234. end;
  235. {*****************************************************************************
  236. for better code generation these methods should be overridden
  237. ******************************************************************************}
  238. procedure tcg.a_param_const(list : taasmoutput;size : tcgsize;a : aword;nr : longint);
  239. var
  240. hr : tregister;
  241. begin
  242. hr:=get_scratch_reg(list);
  243. a_load_const_reg(list,size,a,hr);
  244. a_param_reg(list,size,hr,nr);
  245. free_scratch_reg(list,hr);
  246. end;
  247. procedure tcg.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;nr : longint);
  248. var
  249. hr : tregister;
  250. begin
  251. hr:=get_scratch_reg(list);
  252. a_load_ref_reg(list,size,r,hr);
  253. a_param_reg(list,size,hr,nr);
  254. free_scratch_reg(list,hr);
  255. end;
  256. procedure tcg.a_paramaddr_ref(list : taasmoutput;const r : treference;nr : longint);
  257. var
  258. hr : tregister;
  259. begin
  260. hr:=get_scratch_reg(list);
  261. a_loadaddress_ref_reg(list,r,hr);
  262. a_param_reg(list,OS_ADDR,hr,nr);
  263. free_scratch_reg(list,hr);
  264. end;
  265. procedure tcg.g_stackcheck(list : taasmoutput;stackframesize : longint);
  266. begin
  267. a_param_const(list,OS_32,stackframesize,1);
  268. a_call_name(list,'FPC_STACKCHECK',0);
  269. end;
  270. {*****************************************************************************
  271. String helper routines
  272. *****************************************************************************}
  273. procedure tcg.g_removetemps(list : taasmoutput;p : tlinkedlist);
  274. (*
  275. var
  276. hp : ptemptodestroy;
  277. pushedregs : tpushed;
  278. *)
  279. begin
  280. (*
  281. hp:=ptemptodestroy(p^.first);
  282. if not(assigned(hp)) then
  283. exit;
  284. tg.pushusedregisters(pushedregs,$ff);
  285. while assigned(hp) do
  286. begin
  287. if is_ansistring(hp^.typ) then
  288. begin
  289. g_decrstrref(list,hp^.address,hp^.typ);
  290. tg.ungetiftemp(hp^.address);
  291. end;
  292. hp:=ptemptodestroy(hp^.next);
  293. end;
  294. tg.popusedregisters(pushedregs);
  295. *)
  296. runerror(211);
  297. end;
  298. procedure tcg.g_decrstrref(list : taasmoutput;const ref : treference;t : tdef);
  299. var
  300. pushedregs : tpushed;
  301. begin
  302. (*
  303. tg.pushusedregisters(pushedregs,$ff);
  304. a_param_ref_addr(list,ref,1);
  305. if is_ansistring(t) then
  306. a_call_name(list,'FPC_ANSISTR_DECR_REF',0)
  307. else if is_widestring(t) then
  308. a_call_name(list,'FPC_WIDESTR_DECR_REF',0)
  309. else internalerror(58993);
  310. tg.popusedregisters(pushedregs);
  311. *)
  312. runerror(211);
  313. end;
  314. {*****************************************************************************
  315. Code generation for subroutine entry- and exit code
  316. *****************************************************************************}
  317. { initilizes data of type t }
  318. { if is_already_ref is true then the routines assumes }
  319. { that r points to the data to initialize }
  320. procedure tcg.g_initialize(list : taasmoutput;t : tdef;const ref : treference;is_already_ref : boolean);
  321. var
  322. hr : treference;
  323. begin
  324. (*
  325. if is_ansistring(t) or
  326. is_widestring(t) then
  327. a_load_const_ref(list,OS_8,0,ref)
  328. else
  329. begin
  330. reset_reference(hr);
  331. hr.symbol:=t^.get_inittable_label;
  332. a_param_ref_addr(list,hr,2);
  333. if is_already_ref then
  334. a_param_ref(list,OS_ADDR,ref,1)
  335. else
  336. a_param_ref_addr(list,ref,1);
  337. a_call_name(list,'FPC_INITIALIZE',0);
  338. end;
  339. *)
  340. runerror(211);
  341. end;
  342. procedure tcg.g_finalize(list : taasmoutput;t : tdef;const ref : treference;is_already_ref : boolean);
  343. var
  344. r : treference;
  345. begin
  346. (*
  347. if is_ansistring(t) or
  348. is_widestring(t) then
  349. begin
  350. g_decrstrref(list,ref,t);
  351. end
  352. else
  353. begin
  354. reset_reference(r);
  355. r.symbol:=t^.get_inittable_label;
  356. a_param_ref_addr(list,r,2);
  357. if is_already_ref then
  358. a_paramaddr_ref(list,ref,1)
  359. else
  360. a_param_ref_addr(list,ref,1);
  361. a_call_name(list,'FPC_FINALIZE',0);
  362. end;
  363. *)
  364. runerror(211);
  365. end;
  366. { generates the code for initialisation of local data }
  367. procedure tcg.g_initialize_data(list : taasmoutput;p : tsym);
  368. var
  369. hr : treference;
  370. begin
  371. (*
  372. if (tsym(p)^.typ=varsym) and
  373. assigned(pvarsym(p)^.vartype.def) and
  374. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  375. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  376. pvarsym(p)^.vartype.def^.needs_inittable then
  377. begin
  378. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  379. reset_reference(hr);
  380. if tsym(p)^.owner^.symtabletype=localsymtable then
  381. begin
  382. hr.base:=procinfo^.framepointer;
  383. hr.offset:=-pvarsym(p)^.address;
  384. end
  385. else
  386. begin
  387. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  388. end;
  389. g_initialize(list,pvarsym(p)^.vartype.def,hr,false);
  390. end;
  391. *)
  392. runerror(211);
  393. end;
  394. { generates the code for incrementing the reference count of parameters }
  395. procedure tcg.g_incr_data(list : taasmoutput;p : tsym);
  396. var
  397. hr : treference;
  398. begin
  399. (*
  400. if (tsym(p)^.typ=varsym) and
  401. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  402. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  403. pvarsym(p)^.vartype.def^.needs_inittable and
  404. ((pvarsym(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)^.vartype.def^.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. *)
  418. runerror(211);
  419. end;
  420. { generates the code for finalisation of local data }
  421. procedure tcg.g_finalize_data(list : taasmoutput;p : tnamedindexitem);
  422. var
  423. hr : treference;
  424. begin
  425. (*
  426. if (tsym(p)^.typ=varsym) and
  427. assigned(pvarsym(p)^.vartype.def) and
  428. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  429. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  430. pvarsym(p)^.vartype.def^.needs_inittable then
  431. begin
  432. { not all kind of parameters need to be finalized }
  433. if (tsym(p)^.owner^.symtabletype=parasymtable) and
  434. ((pvarsym(p)^.varspez=vs_var) or
  435. (pvarsym(p)^.varspez=vs_const) { and
  436. (dont_copy_const_param(pvarsym(p)^.definition)) } ) then
  437. exit;
  438. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  439. reset_reference(hr);
  440. case tsym(p)^.owner^.symtabletype of
  441. localsymtable:
  442. begin
  443. hr.base:=procinfo^.framepointer;
  444. hr.offset:=-pvarsym(p)^.address;
  445. end;
  446. parasymtable:
  447. begin
  448. hr.base:=procinfo^.framepointer;
  449. hr.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  450. end;
  451. else
  452. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  453. end;
  454. g_finalize(list,pvarsym(p)^.vartype.def,hr,false);
  455. end;
  456. *)
  457. runerror(211);
  458. end;
  459. { generates the code to make local copies of the value parameters }
  460. procedure tcg.g_copyvalueparas(list : taasmoutput;p : tnamedindexitem);
  461. begin
  462. runerror(255);
  463. end;
  464. (*
  465. var
  466. _list : taasmoutput;
  467. { wrappers for the methods, because TP doesn't know procedures }
  468. { of objects }
  469. procedure _copyvalueparas(s : tnamedindexitem);{$ifndef FPC}far;{$endif}
  470. begin
  471. cg^.g_copyvalueparas(_list,s);
  472. end;
  473. *)
  474. procedure tcg.g_finalizetempansistrings(list : taasmoutput);
  475. (*
  476. var
  477. hp : ptemprecord;
  478. hr : treference;
  479. *)
  480. begin
  481. (*
  482. hp:=tg.templist;
  483. while assigned(hp) do
  484. begin
  485. if hp^.temptype in [tt_ansistring,tt_freeansistring] then
  486. begin
  487. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  488. reset_reference(hr);
  489. hr.base:=procinfo^.framepointer;
  490. hr.offset:=hp^.pos;
  491. a_param_ref_addr(list,hr,1);
  492. a_call_name(list,'FPC_ANSISTR_DECR_REF',0);
  493. end;
  494. hp:=hp^.next;
  495. end;
  496. *)
  497. runerror(211);
  498. end;
  499. (*
  500. procedure _finalize_data(s : tnamedindexitem);{$ifndef FPC}far;{$endif}
  501. begin
  502. cg^.g_finalize_data(_list,s);
  503. end;
  504. procedure _incr_data(s : tnamedindexitem);{$ifndef FPC}far;{$endif}
  505. begin
  506. cg^.g_incr_data(_list,tsym(s));
  507. end;
  508. procedure _initialize_data(s : tnamedindexitem);{$ifndef FPC}far;{$endif}
  509. begin
  510. cg^.g_initialize_data(_list,tsym(s));
  511. end;
  512. *)
  513. { generates the entry code for a procedure }
  514. procedure tcg.g_entrycode(alist : TAAsmoutput;make_global:boolean;
  515. stackframe:longint;
  516. var parasize:longint;var nostackframe:boolean;
  517. inlined : boolean);
  518. (*
  519. var
  520. hs : string;
  521. hp : pused_unit;
  522. initcode : taasmoutput;
  523. {$ifdef GDB}
  524. stab_function_name : Pai_stab_function_name;
  525. {$endif GDB}
  526. hr : treference;
  527. r : tregister;
  528. *)
  529. begin
  530. (*
  531. { Align }
  532. if (not inlined) then
  533. begin
  534. { gprof uses 16 byte granularity !! }
  535. if (cs_profile in aktmoduleswitches) then
  536. list^.insert(new(pai_align,init(16)))
  537. else
  538. if not(cs_littlesize in aktglobalswitches) then
  539. list^.insert(new(pai_align,init(4)));
  540. end;
  541. { save registers on cdecl }
  542. if (po_savestdregs in aktprocsym^.definition^.procoptions) then
  543. begin
  544. for r:=firstreg to lastreg do
  545. begin
  546. if (r in registers_saved_on_cdecl) then
  547. if (r in (tg.availabletempregsint+
  548. tg.availabletempregsfpu+
  549. tg.availabletempregsmm)) then
  550. begin
  551. if not(r in tg.usedinproc) then
  552. {!!!!!!!!!!!! a_push_reg(list,r) }
  553. end
  554. else
  555. {!!!!!!!! a_push_reg(list,r) };
  556. end;
  557. end;
  558. { omit stack frame ? }
  559. if not inlined then
  560. if procinfo^.framepointer=stack_pointer then
  561. begin
  562. CGMessage(cg_d_stackframe_omited);
  563. nostackframe:=true;
  564. if (aktprocsym^.definition^.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  565. parasize:=0
  566. else
  567. parasize:=aktprocsym^.definition^.parast^.datasize+procinfo^.para_offset-pointersize;
  568. end
  569. else
  570. begin
  571. if (aktprocsym^.definition^.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  572. parasize:=0
  573. else
  574. parasize:=aktprocsym^.definition^.parast^.datasize+procinfo^.para_offset-pointersize*2;
  575. nostackframe:=false;
  576. if (po_interrupt in aktprocsym^.definition^.procoptions) then
  577. g_interrupt_stackframe_entry(list);
  578. g_stackframe_entry(list,stackframe);
  579. if (cs_check_stack in aktlocalswitches) and
  580. (tf_supports_stack_checking in target_info.flags) then
  581. g_stackcheck(@initcode,stackframe);
  582. end;
  583. if cs_profile in aktmoduleswitches then
  584. g_profilecode(@initcode);
  585. if (not inlined) and (aktprocsym^.definition^.proctypeoption in [potype_unitinit]) then
  586. begin
  587. { needs the target a console flags ? }
  588. if tf_needs_isconsole in target_info.flags then
  589. begin
  590. hr.symbol:=newasmsymbol('U_'+target_info.system_unit+'_ISCONSOLE');
  591. if apptype=at_cui then
  592. a_load_const_ref(list,OS_8,1,hr)
  593. else
  594. a_load_const_ref(list,OS_8,0,hr);
  595. dispose(hr.symbol,done);
  596. end;
  597. hp:=pused_unit(usedunits.first);
  598. while assigned(hp) do
  599. begin
  600. { call the unit init code and make it external }
  601. if (hp^.u^.flags and uf_init)<>0 then
  602. a_call_name(list,
  603. 'INIT$$'+hp^.u^.modulename^,0);
  604. hp:=Pused_unit(hp^.next);
  605. end;
  606. end;
  607. {$ifdef dummy}
  608. { a constructor needs a help procedure }
  609. if (aktprocsym^.definition^.options and poconstructor)<>0 then
  610. begin
  611. if procinfo^._class^.isclass then
  612. begin
  613. list^.concat(new(paicpu,op_sym(A_CALL,S_NO,newasmsymbol('FPC_NEW_CLASS'))));
  614. list^.concat(new(paicpu,op_cond_sym(A_Jcc,C_Z,S_NO,quickexitlabel)));
  615. end
  616. else
  617. begin
  618. {
  619. list^.insert(new(pai_labeled,init(A_JZ,quickexitlabel)));
  620. list^.insert(new(paicpu,op_csymbol(A_CALL,S_NO,
  621. newcsymbol('FPC_HELP_CONSTRUCTOR',0))));
  622. list^.insert(new(paicpu,op_const_reg(A_MOV,S_L,procinfo^._class^.vmt_offset,R_EDI)));
  623. concat_external('FPC_HELP_CONSTRUCTOR',EXT_NEAR);
  624. }
  625. end;
  626. end;
  627. {$endif dummy}
  628. {$ifdef GDB}
  629. if (cs_debuginfo in aktmoduleswitches) then
  630. list^.insert(new(pai_force_line,init));
  631. {$endif GDB}
  632. { initialize return value }
  633. if assigned(procinfo^.returntype.def) and
  634. is_ansistring(procinfo^.returntype.def) or
  635. is_widestring(procinfo^.returntype.def) then
  636. begin
  637. reset_reference(hr);
  638. hr.offset:=procinfo^.return_offset;
  639. hr.base:=procinfo^.framepointer;
  640. a_load_const_ref(list,OS_32,0,hr);
  641. end;
  642. _list:=list;
  643. { generate copies of call by value parameters }
  644. if (po_assembler in aktprocsym^.definition^.procoptions) then
  645. aktprocsym^.definition^.parast^.foreach({$ifdef FPCPROCVAR}@{$endif}_copyvalueparas);
  646. { initialisizes local data }
  647. aktprocsym^.definition^.localst^.foreach({$ifdef FPCPROCVAR}@{$endif}_initialize_data);
  648. { add a reference to all call by value/const parameters }
  649. aktprocsym^.definition^.parast^.foreach({$ifdef FPCPROCVAR}@{$endif}_incr_data);
  650. if (cs_profile in aktmoduleswitches) or
  651. (aktprocsym^.definition^.owner^.symtabletype=globalsymtable) or
  652. (assigned(procinfo^._class) and (procinfo^._class^.owner^.symtabletype=globalsymtable)) then
  653. make_global:=true;
  654. if not inlined then
  655. begin
  656. hs:=proc_names.get;
  657. {$ifdef GDB}
  658. if (cs_debuginfo in aktmoduleswitches) and target_os.use_function_relative_addresses then
  659. stab_function_name := new(pai_stab_function_name,init(strpnew(hs)));
  660. {$endif GDB}
  661. { insert the names for the procedure }
  662. while hs<>'' do
  663. begin
  664. if make_global then
  665. exprasmlist^.insert(new(pai_symbol,initname_global(hs,0)))
  666. else
  667. exprasmlist^.insert(new(pai_symbol,initname(hs,0)));
  668. {$ifdef GDB}
  669. if (cs_debuginfo in aktmoduleswitches) then
  670. begin
  671. if target_os.use_function_relative_addresses then
  672. list^.insert(new(pai_stab_function_name,init(strpnew(hs))));
  673. end;
  674. {$endif GDB}
  675. hs:=proc_names.get;
  676. end;
  677. end;
  678. {$ifdef GDB}
  679. if (not inlined) and (cs_debuginfo in aktmoduleswitches) then
  680. begin
  681. if target_os.use_function_relative_addresses then
  682. list^.insert(stab_function_name);
  683. if make_global or ((procinfo^.flags and pi_is_global) <> 0) then
  684. aktprocsym^.is_global := True;
  685. list^.insert(new(pai_stabs,init(aktprocsym^.stabstring)));
  686. aktprocsym^.isstabwritten:=true;
  687. end;
  688. {$endif GDB}
  689. *)
  690. runerror(211);
  691. end;
  692. procedure tcg.g_exitcode(list : taasmoutput;parasize:longint;nostackframe,inlined:boolean);
  693. var
  694. {$ifdef GDB}
  695. mangled_length : longint;
  696. p : pchar;
  697. {$endif GDB}
  698. nofinal,noreraiselabel : tasmlabel;
  699. hr : treference;
  700. r : tregister;
  701. begin
  702. (*
  703. if aktexitlabel^.is_used then
  704. list^.insert(new(pai_label,init(aktexitlabel)));
  705. { call the destructor help procedure }
  706. if (aktprocsym^.definition^.proctypeoption=potype_destructor) then
  707. begin
  708. if procinfo^._class^.is_class then
  709. a_call_name(list,'FPC_DISPOSE_CLASS',0)
  710. else
  711. begin
  712. if procinfo^._class^.needs_inittable then
  713. begin
  714. getlabel(nofinal);
  715. {!!!!!!!!!!
  716. reset_reference(hr);
  717. hr.base:=R_EBP;
  718. hr.offset:=8;
  719. a_cmp_reg_const_label(list,OS_ADDR,OZ_EQ,
  720. }
  721. reset_reference(hr);
  722. hr.symbol:=procinfo^._class^.get_inittable_label;
  723. a_paramaddr_ref(list,hr,2);
  724. a_param_reg(list,OS_ADDR,self_pointer,1);
  725. a_call_name(list,'FPC_FINALIZE',0);
  726. a_label(list,nofinal);
  727. end;
  728. { vmt_offset_reg can be a scratch register, }
  729. { but it must be always the same }
  730. a_reg_alloc(list,vmt_offset_reg);
  731. a_load_const_reg(list,OS_32,procinfo^._class^.vmt_offset,vmt_offset_reg);
  732. a_call_name(list,'FPC_HELP_DESTRUCTOR',0);
  733. a_reg_dealloc(list,vmt_offset_reg);
  734. end;
  735. end;
  736. { finalize temporary data }
  737. g_finalizetempansistrings(list);
  738. _list:=list;
  739. { finalize local data }
  740. aktprocsym^.definition^.localst^.foreach({$ifdef FPCPROCVAR}@{$endif}_finalize_data);
  741. { finalize paras data }
  742. if assigned(aktprocsym^.definition^.parast) then
  743. aktprocsym^.definition^.parast^.foreach({$ifdef FPCPROCVAR}@{$endif}_finalize_data);
  744. { do we need to handle exceptions because of ansi/widestrings ? }
  745. if (procinfo^.flags and pi_needs_implicit_finally)<>0 then
  746. begin
  747. getlabel(noreraiselabel);
  748. a_call_name(list,'FPC_POPADDRSTACK',0);
  749. a_reg_alloc(list,accumulator);
  750. g_pop_exception_value_reg(list,accumulator);
  751. a_cmp_const_reg_label(list,OS_32,OC_EQ,0,accumulator,noreraiselabel);
  752. a_reg_dealloc(list,accumulator);
  753. { must be the return value finalized before reraising the exception? }
  754. if (procinfo^.returntype.def<>tdef(voiddef)) and
  755. (procinfo^.returntype.def^.needs_inittable) and
  756. ((procinfo^.returntype.def^.deftype<>objectdef) or
  757. not(pobjectdef(procinfo^.returntype.def)^.is_class)) then
  758. begin
  759. reset_reference(hr);
  760. hr.offset:=procinfo^.return_offset;
  761. hr.base:=procinfo^.framepointer;
  762. g_finalize(list,procinfo^.returntype.def,hr,ret_in_param(procinfo^.returntype.def));
  763. end;
  764. a_call_name(list,'FPC_RERAISE',0);
  765. a_label(list,noreraiselabel);
  766. end;
  767. { call __EXIT for main program }
  768. if (not DLLsource) and (not inlined) and (aktprocsym^.definition^.proctypeoption=potype_proginit) then
  769. a_call_name(list,'FPC_DO_EXIT',0);
  770. { handle return value }
  771. if not(po_assembler in aktprocsym^.definition^.procoptions) then
  772. if (aktprocsym^.definition^.proctypeoption<>potype_constructor) then
  773. { handle_return_value(inlined) }
  774. else
  775. begin
  776. { return self in EAX }
  777. a_label(list,quickexitlabel);
  778. a_reg_alloc(list,accumulator);
  779. a_load_reg_reg(list,OS_ADDR,self_pointer,accumulator);
  780. a_reg_dealloc(list,self_pointer);
  781. a_label(list,quickexitlabel);
  782. { we can't clear the zero flag because the Alpha }
  783. { for example doesn't have flags, we have to compare }
  784. { the accu. in the caller }
  785. end;
  786. { stabs uses the label also ! }
  787. if aktexit2label^.is_used or
  788. ((cs_debuginfo in aktmoduleswitches) and not inlined) then
  789. a_label(list,aktexit2label);
  790. {$ifdef dummy}
  791. { should we restore edi ? }
  792. { for all i386 gcc implementations }
  793. {!!!!!!!!!!! I don't know how to handle register saving yet }
  794. if (po_savestdregs in aktprocsym^.definition^.procoptions) then
  795. begin
  796. if (aktprocsym^.definition^.usedregisters and ($80 shr byte(R_EBX)))<>0 then
  797. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_EBX)));
  798. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ESI)));
  799. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_EDI)));
  800. { here we could reset R_EBX
  801. but that is risky because it only works
  802. if genexitcode is called after genentrycode
  803. so lets skip this for the moment PM
  804. aktprocsym^.definition^.usedregisters:=
  805. aktprocsym^.definition^.usedregisters or not ($80 shr byte(R_EBX));
  806. }
  807. end;
  808. {$endif dummy}
  809. if not(nostackframe) and not inlined then
  810. g_restore_frame_pointer(list);
  811. { at last, the return is generated }
  812. if not inlined then
  813. if po_interrupt in aktprocsym^.definition^.procoptions then
  814. g_interrupt_stackframe_exit(list)
  815. else
  816. g_return_from_proc(list,parasize);
  817. list^.concat(new(pai_symbol_end,initname(aktprocsym^.definition^.mangledname)));
  818. {$ifdef GDB}
  819. if (cs_debuginfo in aktmoduleswitches) and not inlined then
  820. begin
  821. aktprocsym^.concatstabto(list);
  822. if assigned(procinfo^._class) then
  823. if (not assigned(procinfo^.parent) or
  824. not assigned(procinfo^.parent^._class)) then
  825. list^.concat(new(pai_stabs,init(strpnew(
  826. '"$t:v'+procinfo^._class^.numberstring+'",'+
  827. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.selfpointer_offset)))));
  828. {!!!!!!!!!!!!
  829. else
  830. list^.concat(new(pai_stabs,init(strpnew(
  831. '"$t:r'+procinfo^._class^.numberstring+'",'+
  832. tostr(N_RSYM)+',0,0,'+tostr(GDB_i386index[R_ESI])))));
  833. }
  834. if (tdef(aktprocsym^.definition^.rettype.def) <> tdef(voiddef)) then
  835. begin
  836. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  837. list^.concat(new(pai_stabs,init(strpnew(
  838. '"'+aktprocsym^.name+':X*'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  839. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))))
  840. else
  841. list^.concat(new(pai_stabs,init(strpnew(
  842. '"'+aktprocsym^.name+':X'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  843. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))));
  844. if (m_result in aktmodeswitches) then
  845. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  846. list^.concat(new(pai_stabs,init(strpnew(
  847. '"RESULT:X*'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  848. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))))
  849. else
  850. list^.concat(new(pai_stabs,init(strpnew(
  851. '"RESULT:X'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  852. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))));
  853. end;
  854. mangled_length:=length(aktprocsym^.definition^.mangledname);
  855. getmem(p,mangled_length+50);
  856. strpcopy(p,'192,0,0,');
  857. strpcopy(strend(p),aktprocsym^.definition^.mangledname);
  858. list^.concat(new(pai_stabn,init(strnew(p))));
  859. {list^.concat(new(pai_stabn,init(strpnew('192,0,0,'
  860. +aktprocsym^.definition^.mangledname))));
  861. p[0]:='2';p[1]:='2';p[2]:='4';
  862. strpcopy(strend(p),'_end');}
  863. freemem(p,mangled_length+50);
  864. list^.concat(new(pai_stabn,init(
  865. strpnew('224,0,0,'+aktexit2label^.name))));
  866. { strpnew('224,0,0,'
  867. +aktprocsym^.definition^.mangledname+'_end'))));}
  868. end;
  869. {$endif GDB}
  870. *)
  871. runerror(211);
  872. end;
  873. {*****************************************************************************
  874. some generic implementations
  875. ****************************************************************************}
  876. procedure tcg.a_load_const_ref(list : taasmoutput;size : tcgsize;a : aword;const ref : treference);
  877. var
  878. tmpreg: tregister;
  879. begin
  880. tmpreg := get_scratch_reg(list);
  881. a_load_const_reg(list,size,a,tmpreg);
  882. a_load_reg_ref(list,size,tmpreg,ref);
  883. free_scratch_reg(list,tmpreg);
  884. end;
  885. procedure tcg.a_load_loc_reg(list : taasmoutput;size : tcgsize;const loc: tlocation; reg : tregister);
  886. begin
  887. case loc.loc of
  888. LOC_REFERENCE,LOC_MEM:
  889. a_load_ref_reg(list,size,loc.reference,reg);
  890. LOC_REGISTER,LOC_CREGISTER:
  891. a_load_reg_reg(list,size,loc.register,reg);
  892. else
  893. internalerror(200109092);
  894. end;
  895. end;
  896. procedure tcg.a_load_loc_ref(list : taasmoutput;size : tcgsize;const loc: tlocation; const ref : treference);
  897. var
  898. tmpreg: tregister;
  899. begin
  900. case loc.loc of
  901. LOC_REFERENCE,LOC_MEM:
  902. begin
  903. {$ifdef i386}
  904. case size of
  905. OS_8,OS_S8:
  906. tmpreg := reg32toreg8(getregister32);
  907. OS_16,OS_S16:
  908. tmpreg := reg32toreg16(get_scratch_reg(list));
  909. else
  910. tmpreg := get_scratch_reg(list);
  911. end;
  912. {$else i386}
  913. tmpreg := get_scratch_reg(list);
  914. {$endif i386}
  915. a_load_ref_reg(list,size,loc.reference,tmpreg);
  916. a_load_reg_ref(list,size,tmpreg,ref);
  917. {$ifdef i386}
  918. if not (size in [OS_32,OS_S32]) then
  919. ungetregister(tmpreg)
  920. else
  921. {$endif i386}
  922. free_scratch_reg(list,tmpreg);
  923. end;
  924. LOC_REGISTER,LOC_CREGISTER:
  925. a_load_reg_ref(list,size,loc.register,ref);
  926. else
  927. internalerror(200109302);
  928. end;
  929. end;
  930. procedure tcg.a_op_const_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; const ref: TReference);
  931. var
  932. tmpreg: tregister;
  933. begin
  934. tmpreg := get_scratch_reg(list);
  935. a_load_ref_reg(list,size,ref,tmpreg);
  936. a_op_const_reg(list,op,a,tmpreg);
  937. a_load_reg_ref(list,size,tmpreg,ref);
  938. free_scratch_reg(list,tmpreg);
  939. end;
  940. procedure tcg.a_op_const_loc(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; const loc: tlocation);
  941. begin
  942. case loc.loc of
  943. LOC_REGISTER, LOC_CREGISTER:
  944. a_op_const_reg(list,op,a,loc.register);
  945. LOC_REFERENCE, LOC_MEM:
  946. a_op_const_ref(list,op,size,a,loc.reference);
  947. else
  948. internalerror(200109061);
  949. end;
  950. end;
  951. procedure tcg.a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference);
  952. var
  953. tmpreg: tregister;
  954. begin
  955. tmpreg := get_scratch_reg(list);
  956. a_load_ref_reg(list,size,ref,tmpreg);
  957. a_op_reg_reg(list,op,size,reg,tmpreg);
  958. a_load_reg_ref(list,size,tmpreg,ref);
  959. free_scratch_reg(list,tmpreg);
  960. end;
  961. procedure tcg.a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister);
  962. var
  963. tmpreg: tregister;
  964. begin
  965. case op of
  966. OP_NOT,OP_NEG:
  967. { handle it as "load ref,reg; op reg" }
  968. begin
  969. a_load_ref_reg(list,size,ref,reg);
  970. a_op_reg_reg(list,op,size,reg,reg);
  971. end;
  972. else
  973. begin
  974. tmpreg := get_scratch_reg(list);
  975. a_load_ref_reg(list,size,ref,tmpreg);
  976. a_op_reg_reg(list,op,size,tmpreg,reg);
  977. free_scratch_reg(list,tmpreg);
  978. end;
  979. end;
  980. end;
  981. procedure tcg.a_op_reg_loc(list : taasmoutput; Op: TOpCG; size: TCGSize; reg: tregister; const loc: tlocation);
  982. begin
  983. case loc.loc of
  984. LOC_REGISTER, LOC_CREGISTER:
  985. a_op_reg_reg(list,op,size,reg,loc.register);
  986. LOC_REFERENCE, LOC_MEM:
  987. a_op_reg_ref(list,op,size,reg,loc.reference);
  988. else
  989. internalerror(200109061);
  990. end;
  991. end;
  992. procedure tcg.a_op_ref_loc(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; const loc: tlocation);
  993. var
  994. tmpreg: tregister;
  995. begin
  996. case loc.loc of
  997. LOC_REGISTER,LOC_CREGISTER:
  998. a_op_ref_reg(list,op,size,ref,loc.register);
  999. LOC_REFERENCE,LOC_MEM:
  1000. begin
  1001. tmpreg := get_scratch_reg(list);
  1002. {$ifdef i386}
  1003. makeregsize(tmpreg,size);
  1004. {$endif i386}
  1005. a_load_ref_reg(list,size,ref,tmpreg);
  1006. a_op_reg_ref(list,op,size,tmpreg,loc.reference);
  1007. free_scratch_reg(list,tmpreg);
  1008. end;
  1009. else
  1010. internalerror(200109061);
  1011. end;
  1012. end;
  1013. procedure tcg.a_cmp_const_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;const ref : treference;
  1014. l : tasmlabel);
  1015. var
  1016. tmpreg: tregister;
  1017. begin
  1018. tmpreg := get_scratch_reg(list);
  1019. a_load_ref_reg(list,size,ref,tmpreg);
  1020. a_cmp_const_reg_label(list,size,cmp_op,a,tmpreg,l);
  1021. free_scratch_reg(list,tmpreg);
  1022. end;
  1023. procedure tcg.a_cmp_const_loc_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;const loc : tlocation;
  1024. l : tasmlabel);
  1025. begin
  1026. case loc.loc of
  1027. LOC_REGISTER,LOC_CREGISTER:
  1028. a_cmp_const_reg_label(list,size,cmp_op,a,loc.register,l);
  1029. LOC_REFERENCE,LOC_MEM:
  1030. a_cmp_const_ref_label(list,size,cmp_op,a,loc.reference,l);
  1031. else
  1032. internalerror(200109061);
  1033. end;
  1034. end;
  1035. procedure tcg.a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const ref: treference; reg : tregister; l : tasmlabel);
  1036. var
  1037. tmpreg: tregister;
  1038. begin
  1039. tmpreg := get_scratch_reg(list);
  1040. a_load_ref_reg(list,size,ref,tmpreg);
  1041. a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
  1042. free_scratch_reg(list,tmpreg);
  1043. end;
  1044. procedure tcg.a_cmp_ref_loc_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;const ref: treference;const loc : tlocation;
  1045. l : tasmlabel);
  1046. var
  1047. tmpreg: tregister;
  1048. begin
  1049. case loc.loc of
  1050. LOC_REGISTER,LOC_CREGISTER:
  1051. a_cmp_ref_reg_label(list,size,cmp_op,ref,loc.register,l);
  1052. LOC_REFERENCE,LOC_MEM:
  1053. begin
  1054. {$ifdef i386}
  1055. { the following is done with defines to avoid a speed penalty, }
  1056. { since all this is only necessary for the 80x86 (because EDI }
  1057. { doesn't have an 8bit component which is directly addressable) }
  1058. if size in [OS_8,OS_S8] then
  1059. tmpreg := getregister32
  1060. else
  1061. {$endif i386}
  1062. tmpreg := get_scratch_reg(list);
  1063. {$ifdef i386}
  1064. makeregsize(tmpreg,size);
  1065. {$endif i386}
  1066. a_load_ref_reg(list,size,loc.reference,tmpreg);
  1067. a_cmp_ref_reg_label(list,size,cmp_op,ref,tmpreg,l);
  1068. {$ifdef i386}
  1069. if makereg32(tmpreg) <> R_EDI then
  1070. ungetregister(tmpreg)
  1071. else
  1072. {$endif i386}
  1073. free_scratch_reg(list,tmpreg);
  1074. end
  1075. else
  1076. internalerror(200109061);
  1077. end;
  1078. end;
  1079. finalization
  1080. cg.free;
  1081. end.
  1082. {
  1083. $Log$
  1084. Revision 1.4 2001-09-30 21:26:42 peter
  1085. * removed obsolete newst defines
  1086. Revision 1.3 2001/09/30 16:17:17 jonas
  1087. * made most constant and mem handling processor independent
  1088. Revision 1.2 2001/09/28 20:39:32 jonas
  1089. * changed all flow control structures (except for exception handling
  1090. related things) to processor independent code (in new ncgflw unit)
  1091. + generic cgobj unit which contains lots of code generator helpers with
  1092. global "cg" class instance variable
  1093. + cgcpu unit for i386 (implements processor specific routines of the above
  1094. unit)
  1095. * updated cgbase and cpubase for the new code generator units
  1096. * include ncgflw unit in cpunode unit
  1097. Revision 1.5 2001/09/09 17:10:26 jonas
  1098. * some more things implemented
  1099. Revision 1.4 2001/09/06 15:25:55 jonas
  1100. * changed type of tcg from object to class -> abstract methods are now
  1101. a lot cleaner :)
  1102. + more updates: load_*_loc methods, op_*_* methods, g_flags2reg method
  1103. (if possible with geenric implementation and necessary ppc
  1104. implementations)
  1105. * worked a bit further on cgflw, now working on exitnode
  1106. Revision 1.3 2001/09/05 20:21:03 jonas
  1107. * new cgflow based on n386flw with all nodes until forn "translated"
  1108. + a_cmp_loc_*_label methods for tcg
  1109. + base implementatino for a_cmp_ref_*_label methods
  1110. * small bugfixes to powerpc cg
  1111. Revision 1.2 2001/08/26 13:37:04 florian
  1112. * some cg reorganisation
  1113. * some PPC updates
  1114. Revision 1.1 2000/07/13 06:30:07 michael
  1115. + Initial import
  1116. }