hcodegen.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. This unit exports some help routines for the code generation
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit hcodegen;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. { common }
  23. cobjects,
  24. { global }
  25. globals,verbose,
  26. { symtable }
  27. symconst,symtype,symdef,symsym,
  28. { aasm }
  29. aasm,cpubase
  30. ;
  31. const
  32. pi_uses_asm = $1; { set, if the procedure uses asm }
  33. pi_is_global = $2; { set, if the procedure is exported by an unit }
  34. pi_do_call = $4; { set, if the procedure does a call }
  35. pi_operator = $8; { set, if the procedure is an operator }
  36. pi_C_import = $10; { set, if the procedure is an external C function }
  37. pi_uses_exceptions = $20;{ set, if the procedure has a try statement => }
  38. { no register variables }
  39. pi_is_assembler = $40; { set if the procedure is declared as ASSEMBLER
  40. => don't optimize}
  41. pi_needs_implicit_finally = $80; { set, if the procedure contains data which }
  42. { needs to be finalized }
  43. type
  44. pprocinfo = ^tprocinfo;
  45. tprocinfo = object
  46. { pointer to parent in nested procedures }
  47. parent : pprocinfo;
  48. { current class, if we are in a method }
  49. _class : pobjectdef;
  50. { return type }
  51. returntype : ttype;
  52. { symbol of the function, and the sym for result variable }
  53. resultfuncretsym,
  54. funcretsym : pfuncretsym;
  55. funcret_state : tvarstate;
  56. { the definition of the proc itself }
  57. def : pprocdef;
  58. sym : pprocsym;
  59. { frame pointer offset }
  60. framepointer_offset : longint;
  61. { self pointer offset }
  62. selfpointer_offset : longint;
  63. { result value offset }
  64. return_offset : longint;
  65. { firsttemp position }
  66. firsttemp_offset : longint;
  67. { parameter offset }
  68. para_offset : longint;
  69. { some collected informations about the procedure }
  70. { see pi_xxxx above }
  71. flags : longint;
  72. { register used as frame pointer }
  73. framepointer : tregister;
  74. { true, if the procedure is exported by an unit }
  75. globalsymbol : boolean;
  76. { true, if the procedure should be exported (only OS/2) }
  77. exported : boolean;
  78. { true, if we can not use fast exit code }
  79. no_fast_exit : boolean;
  80. { code for the current procedure }
  81. aktproccode,aktentrycode,
  82. aktexitcode,aktlocaldata : taasmoutput;
  83. { local data is used for smartlink }
  84. constructor init;
  85. destructor done;
  86. end;
  87. pregvarinfo = ^tregvarinfo;
  88. tregvarinfo = record
  89. regvars : array[1..maxvarregs] of pvarsym;
  90. regvars_para : array[1..maxvarregs] of boolean;
  91. regvars_refs : array[1..maxvarregs] of longint;
  92. fpuregvars : array[1..maxfpuvarregs] of pvarsym;
  93. fpuregvars_para : array[1..maxfpuvarregs] of boolean;
  94. fpuregvars_refs : array[1..maxfpuvarregs] of longint;
  95. end;
  96. var
  97. { info about the current sub routine }
  98. procinfo : pprocinfo;
  99. { labels for BREAK and CONTINUE }
  100. aktbreaklabel,aktcontinuelabel : pasmlabel;
  101. { label when the result is true or false }
  102. truelabel,falselabel : pasmlabel;
  103. { label to leave the sub routine }
  104. aktexitlabel : pasmlabel;
  105. { also an exit label, only used we need to clear only the stack }
  106. aktexit2label : pasmlabel;
  107. { only used in constructor for fail or if getmem fails }
  108. faillabel,quickexitlabel : pasmlabel;
  109. { Boolean, wenn eine loadn kein Assembler erzeugt hat }
  110. simple_loadn : boolean;
  111. { true, if an error while code generation occurs }
  112. codegenerror : boolean;
  113. { save the size of pushed parameter, needed for aligning }
  114. pushedparasize : longint;
  115. make_const_global : boolean;
  116. { message calls with codegenerror support }
  117. procedure cgmessage(t : longint);
  118. procedure cgmessage1(t : longint;const s : string);
  119. procedure cgmessage2(t : longint;const s1,s2 : string);
  120. procedure cgmessage3(t : longint;const s1,s2,s3 : string);
  121. procedure CGMessagePos(const pos:tfileposinfo;t:longint);
  122. procedure CGMessagePos1(const pos:tfileposinfo;t:longint;const s1:string);
  123. procedure CGMessagePos2(const pos:tfileposinfo;t:longint;const s1,s2:string);
  124. procedure CGMessagePos3(const pos:tfileposinfo;t:longint;const s1,s2,s3:string);
  125. { initialize respectively terminates the code generator }
  126. { for a new module or procedure }
  127. procedure codegen_doneprocedure;
  128. procedure codegen_donemodule;
  129. procedure codegen_newmodule;
  130. procedure codegen_newprocedure;
  131. implementation
  132. uses
  133. systems,
  134. cresstr
  135. {$ifdef fixLeaksOnError}
  136. ,comphook
  137. {$endif fixLeaksOnError}
  138. ;
  139. {$ifdef fixLeaksOnError}
  140. var procinfoStack: TStack;
  141. hcodegen_old_do_stop: tstopprocedure;
  142. {$endif fixLeaksOnError}
  143. {*****************************************************************************
  144. override the message calls to set codegenerror
  145. *****************************************************************************}
  146. procedure cgmessage(t : longint);
  147. var
  148. olderrorcount : longint;
  149. begin
  150. if not(codegenerror) then
  151. begin
  152. olderrorcount:=Errorcount;
  153. verbose.Message(t);
  154. codegenerror:=olderrorcount<>Errorcount;
  155. end;
  156. end;
  157. procedure cgmessage1(t : longint;const s : string);
  158. var
  159. olderrorcount : longint;
  160. begin
  161. if not(codegenerror) then
  162. begin
  163. olderrorcount:=Errorcount;
  164. verbose.Message1(t,s);
  165. codegenerror:=olderrorcount<>Errorcount;
  166. end;
  167. end;
  168. procedure cgmessage2(t : longint;const s1,s2 : string);
  169. var
  170. olderrorcount : longint;
  171. begin
  172. if not(codegenerror) then
  173. begin
  174. olderrorcount:=Errorcount;
  175. verbose.Message2(t,s1,s2);
  176. codegenerror:=olderrorcount<>Errorcount;
  177. end;
  178. end;
  179. procedure cgmessage3(t : longint;const s1,s2,s3 : string);
  180. var
  181. olderrorcount : longint;
  182. begin
  183. if not(codegenerror) then
  184. begin
  185. olderrorcount:=Errorcount;
  186. verbose.Message3(t,s1,s2,s3);
  187. codegenerror:=olderrorcount<>Errorcount;
  188. end;
  189. end;
  190. procedure cgmessagepos(const pos:tfileposinfo;t : longint);
  191. var
  192. olderrorcount : longint;
  193. begin
  194. if not(codegenerror) then
  195. begin
  196. olderrorcount:=Errorcount;
  197. verbose.MessagePos(pos,t);
  198. codegenerror:=olderrorcount<>Errorcount;
  199. end;
  200. end;
  201. procedure cgmessagepos1(const pos:tfileposinfo;t : longint;const s1 : string);
  202. var
  203. olderrorcount : longint;
  204. begin
  205. if not(codegenerror) then
  206. begin
  207. olderrorcount:=Errorcount;
  208. verbose.MessagePos1(pos,t,s1);
  209. codegenerror:=olderrorcount<>Errorcount;
  210. end;
  211. end;
  212. procedure cgmessagepos2(const pos:tfileposinfo;t : longint;const s1,s2 : string);
  213. var
  214. olderrorcount : longint;
  215. begin
  216. if not(codegenerror) then
  217. begin
  218. olderrorcount:=Errorcount;
  219. verbose.MessagePos2(pos,t,s1,s2);
  220. codegenerror:=olderrorcount<>Errorcount;
  221. end;
  222. end;
  223. procedure cgmessagepos3(const pos:tfileposinfo;t : longint;const s1,s2,s3 : string);
  224. var
  225. olderrorcount : longint;
  226. begin
  227. if not(codegenerror) then
  228. begin
  229. olderrorcount:=Errorcount;
  230. verbose.MessagePos3(pos,t,s1,s2,s3);
  231. codegenerror:=olderrorcount<>Errorcount;
  232. end;
  233. end;
  234. {****************************************************************************
  235. TProcInfo
  236. ****************************************************************************}
  237. constructor tprocinfo.init;
  238. begin
  239. parent:=nil;
  240. _class:=nil;
  241. returntype.reset;
  242. resultfuncretsym:=nil;
  243. funcretsym:=nil;
  244. funcret_state:=vs_none;
  245. def:=nil;
  246. sym:=nil;
  247. framepointer_offset:=0;
  248. selfpointer_offset:=0;
  249. return_offset:=0;
  250. firsttemp_offset:=0;
  251. para_offset:=0;
  252. flags:=0;
  253. framepointer:=R_NO;
  254. globalsymbol:=false;
  255. exported:=false;
  256. no_fast_exit:=false;
  257. aktentrycode:=Taasmoutput.Create;
  258. aktexitcode:=Taasmoutput.Create;
  259. aktproccode:=Taasmoutput.Create;
  260. aktlocaldata:=Taasmoutput.Create;
  261. end;
  262. destructor tprocinfo.done;
  263. begin
  264. aktentrycode.free;
  265. aktexitcode.free;
  266. aktproccode.free;
  267. aktlocaldata.free;
  268. end;
  269. {*****************************************************************************
  270. initialize/terminate the codegen for procedure and modules
  271. *****************************************************************************}
  272. procedure codegen_newprocedure;
  273. begin
  274. aktbreaklabel:=nil;
  275. aktcontinuelabel:=nil;
  276. { aktexitlabel:=0; is store in oldaktexitlabel
  277. so it must not be reset to zero before this storage !}
  278. { new procinfo }
  279. new(procinfo,init);
  280. {$ifdef fixLeaksOnError}
  281. procinfoStack.push(procinfo);
  282. {$endif fixLeaksOnError}
  283. end;
  284. procedure codegen_doneprocedure;
  285. begin
  286. {$ifdef fixLeaksOnError}
  287. if procinfo <> procinfoStack.pop then
  288. writeln('problem with procinfoStack!');
  289. {$endif fixLeaksOnError}
  290. dispose(procinfo,done);
  291. procinfo:=nil;
  292. end;
  293. procedure codegen_newmodule;
  294. begin
  295. exprasmlist:=taasmoutput.create;
  296. datasegment:=taasmoutput.create;
  297. codesegment:=taasmoutput.create;
  298. bsssegment:=taasmoutput.create;
  299. debuglist:=taasmoutput.create;
  300. withdebuglist:=taasmoutput.create;
  301. consts:=taasmoutput.create;
  302. rttilist:=taasmoutput.create;
  303. ResourceStringList:=Nil;
  304. importssection:=nil;
  305. exportssection:=nil;
  306. resourcesection:=nil;
  307. { assembler symbols }
  308. asmsymbollist:=new(pdictionary,init);
  309. asmsymbollist^.usehash;
  310. { resourcestrings }
  311. ResourceStrings:=TResourceStrings.Create;
  312. end;
  313. procedure codegen_donemodule;
  314. {$ifdef MEMDEBUG}
  315. var
  316. d : tmemdebug;
  317. {$endif}
  318. begin
  319. {$ifdef MEMDEBUG}
  320. d.init('asmlist');
  321. {$endif}
  322. exprasmlist.free;
  323. codesegment.free;
  324. bsssegment.free;
  325. datasegment.free;
  326. debuglist.free;
  327. withdebuglist.free;
  328. consts.free;
  329. rttilist.free;
  330. if assigned(ResourceStringList) then
  331. ResourceStringList.free;
  332. if assigned(importssection) then
  333. importssection.free;
  334. if assigned(exportssection) then
  335. exportssection.free;
  336. if assigned(resourcesection) then
  337. resourcesection.free;
  338. {$ifdef MEMDEBUG}
  339. d.done;
  340. {$endif}
  341. { assembler symbols }
  342. {$ifdef MEMDEBUG}
  343. d.init('asmsymbol');
  344. {$endif}
  345. dispose(asmsymbollist,done);
  346. {$ifdef MEMDEBUG}
  347. d.done;
  348. {$endif}
  349. { resource strings }
  350. ResourceStrings.free;
  351. end;
  352. {$ifdef fixLeaksOnError}
  353. procedure hcodegen_do_stop;
  354. var p: pprocinfo;
  355. begin
  356. p := pprocinfo(procinfoStack.pop);
  357. while p <> nil Do
  358. begin
  359. dispose(p,done);
  360. p := pprocinfo(procinfoStack.pop);
  361. end;
  362. procinfoStack.done;
  363. do_stop := hcodegen_old_do_stop;
  364. do_stop{$ifdef FPCPROCVAR}(){$endif};
  365. end;
  366. begin
  367. hcodegen_old_do_stop := do_stop;
  368. do_stop := {$ifdef FPCPROCVAR}@{$endif}hcodegen_do_stop;
  369. procinfoStack.init;
  370. {$endif fixLeaksOnError}
  371. end.
  372. {
  373. $Log$
  374. Revision 1.9 2000-12-25 00:07:26 peter
  375. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  376. tlinkedlist objects)
  377. Revision 1.8 2000/11/30 22:16:49 florian
  378. * moved to i386
  379. Revision 1.7 2000/10/31 22:02:47 peter
  380. * symtable splitted, no real code changes
  381. Revision 1.6 2000/09/24 15:06:17 peter
  382. * use defines.inc
  383. Revision 1.5 2000/08/27 16:11:51 peter
  384. * moved some util functions from globals,cobjects to cutils
  385. * splitted files into finput,fmodule
  386. Revision 1.4 2000/08/12 15:34:22 peter
  387. + usedasmsymbollist to check and reset only the used symbols (merged)
  388. Revision 1.3 2000/08/03 13:17:26 jonas
  389. + allow regvars to be used inside inlined procs, which required the
  390. following changes:
  391. + load regvars in genentrycode/free them in genexitcode (cgai386)
  392. * moved all regvar related code to new regvars unit
  393. + added pregvarinfo type to hcodegen
  394. + added regvarinfo field to tprocinfo (symdef/symdefh)
  395. * deallocate the regvars of the caller in secondprocinline before
  396. inlining the called procedure and reallocate them afterwards
  397. Revision 1.2 2000/07/13 11:32:41 michael
  398. + removed logs
  399. }