pstatmnt.pas 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Does the parsing of the statements
  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 pstatmnt;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. tokens,node;
  23. function statement_block(starttoken : ttoken) : tnode;
  24. { reads an assembler block }
  25. function assembler_block : tnode;
  26. implementation
  27. uses
  28. { common }
  29. cutils,
  30. { global }
  31. globtype,globals,verbose,
  32. systems,cpuinfo,
  33. { aasm }
  34. cpubase,aasmbase,aasmtai,aasmcpu,
  35. { symtable }
  36. symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
  37. paramgr,
  38. { pass 1 }
  39. pass_1,htypechk,
  40. nutils,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  41. { parser }
  42. scanner,
  43. pbase,pexpr,
  44. { codegen }
  45. tgobj,rgobj,cgbase
  46. ,ncgutil
  47. ,radirect
  48. {$ifdef i386}
  49. {$ifndef NoRa386Int}
  50. ,ra386int
  51. {$endif NoRa386Int}
  52. {$ifndef NoRa386Att}
  53. ,ra386att
  54. {$endif NoRa386Att}
  55. {$else}
  56. ,rasm
  57. {$endif i386}
  58. ;
  59. function statement : tnode;forward;
  60. function if_statement : tnode;
  61. var
  62. ex,if_a,else_a : tnode;
  63. begin
  64. consume(_IF);
  65. ex:=comp_expr(true);
  66. consume(_THEN);
  67. if token<>_ELSE then
  68. if_a:=statement
  69. else
  70. if_a:=nil;
  71. if try_to_consume(_ELSE) then
  72. else_a:=statement
  73. else
  74. else_a:=nil;
  75. if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  76. end;
  77. { creates a block (list) of statements, til the next END token }
  78. function statements_til_end : tnode;
  79. var
  80. first,last : tstatementnode;
  81. begin
  82. first:=nil;
  83. while token<>_END do
  84. begin
  85. if first=nil then
  86. begin
  87. last:=cstatementnode.create(statement,nil);
  88. first:=last;
  89. end
  90. else
  91. begin
  92. last.right:=cstatementnode.create(statement,nil);
  93. last:=tstatementnode(last.right);
  94. end;
  95. if not try_to_consume(_SEMICOLON) then
  96. break;
  97. consume_emptystats;
  98. end;
  99. consume(_END);
  100. statements_til_end:=cblocknode.create(first,true);
  101. end;
  102. function case_statement : tnode;
  103. var
  104. { contains the label number of currently parsed case block }
  105. aktcaselabel : tasmlabel;
  106. firstlabel : boolean;
  107. root : pcaserecord;
  108. { the typ of the case expression }
  109. casedef : tdef;
  110. procedure newcaselabel(l,h : TConstExprInt;first:boolean);
  111. var
  112. hcaselabel : pcaserecord;
  113. procedure insertlabel(var p : pcaserecord);
  114. begin
  115. if p=nil then p:=hcaselabel
  116. else
  117. if (p^._low>hcaselabel^._low) and
  118. (p^._low>hcaselabel^._high) then
  119. if (hcaselabel^.statement = p^.statement) and
  120. (p^._low = hcaselabel^._high + 1) then
  121. begin
  122. p^._low := hcaselabel^._low;
  123. dispose(hcaselabel);
  124. end
  125. else
  126. insertlabel(p^.less)
  127. else
  128. if (p^._high<hcaselabel^._low) and
  129. (p^._high<hcaselabel^._high) then
  130. if (hcaselabel^.statement = p^.statement) and
  131. (p^._high+1 = hcaselabel^._low) then
  132. begin
  133. p^._high := hcaselabel^._high;
  134. dispose(hcaselabel);
  135. end
  136. else
  137. insertlabel(p^.greater)
  138. else Message(parser_e_double_caselabel);
  139. end;
  140. begin
  141. new(hcaselabel);
  142. hcaselabel^.less:=nil;
  143. hcaselabel^.greater:=nil;
  144. hcaselabel^.statement:=aktcaselabel;
  145. hcaselabel^.firstlabel:=first;
  146. objectlibrary.getlabel(hcaselabel^._at);
  147. hcaselabel^._low:=l;
  148. hcaselabel^._high:=h;
  149. insertlabel(root);
  150. end;
  151. var
  152. code,caseexpr,p,instruc,elseblock : tnode;
  153. hl1,hl2 : TConstExprInt;
  154. casedeferror : boolean;
  155. begin
  156. consume(_CASE);
  157. caseexpr:=comp_expr(true);
  158. { determines result type }
  159. {$ifndef newra}
  160. rg.cleartempgen;
  161. {$endif}
  162. do_resulttypepass(caseexpr);
  163. casedeferror:=false;
  164. casedef:=caseexpr.resulttype.def;
  165. if (not assigned(casedef)) or
  166. not(is_ordinal(casedef)) then
  167. begin
  168. CGMessage(type_e_ordinal_expr_expected);
  169. { create a correct tree }
  170. caseexpr.free;
  171. caseexpr:=cordconstnode.create(0,u32bittype,false);
  172. { set error flag so no rangechecks are done }
  173. casedeferror:=true;
  174. end;
  175. consume(_OF);
  176. root:=nil;
  177. instruc:=nil;
  178. repeat
  179. objectlibrary.getlabel(aktcaselabel);
  180. firstlabel:=true;
  181. { maybe an instruction has more case labels }
  182. repeat
  183. p:=expr;
  184. if is_widechar(casedef) then
  185. begin
  186. if (p.nodetype=rangen) then
  187. begin
  188. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  189. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  190. do_resulttypepass(trangenode(p).left);
  191. do_resulttypepass(trangenode(p).right);
  192. end
  193. else
  194. begin
  195. p:=ctypeconvnode.create(p,cwidechartype);
  196. do_resulttypepass(p);
  197. end;
  198. end;
  199. hl1:=0;
  200. hl2:=0;
  201. if (p.nodetype=rangen) then
  202. begin
  203. { type checking for case statements }
  204. if is_subequal(casedef, trangenode(p).left.resulttype.def) and
  205. is_subequal(casedef, trangenode(p).right.resulttype.def) then
  206. begin
  207. hl1:=get_ordinal_value(trangenode(p).left);
  208. hl2:=get_ordinal_value(trangenode(p).right);
  209. if hl1>hl2 then
  210. CGMessage(parser_e_case_lower_less_than_upper_bound);
  211. if not casedeferror then
  212. begin
  213. testrange(casedef,hl1,false);
  214. testrange(casedef,hl2,false);
  215. end;
  216. end
  217. else
  218. CGMessage(parser_e_case_mismatch);
  219. newcaselabel(hl1,hl2,firstlabel);
  220. end
  221. else
  222. begin
  223. { type checking for case statements }
  224. if not is_subequal(casedef, p.resulttype.def) then
  225. CGMessage(parser_e_case_mismatch);
  226. hl1:=get_ordinal_value(p);
  227. if not casedeferror then
  228. testrange(casedef,hl1,false);
  229. newcaselabel(hl1,hl1,firstlabel);
  230. end;
  231. p.free;
  232. if token=_COMMA then
  233. consume(_COMMA)
  234. else
  235. break;
  236. firstlabel:=false;
  237. until false;
  238. consume(_COLON);
  239. { handles instruction block }
  240. p:=clabelnode.createcase(aktcaselabel,statement);
  241. { concats instruction }
  242. instruc:=cstatementnode.create(p,instruc);
  243. if not(token in [_ELSE,_OTHERWISE,_END]) then
  244. consume(_SEMICOLON);
  245. until (token in [_ELSE,_OTHERWISE,_END]);
  246. if (token in [_ELSE,_OTHERWISE]) then
  247. begin
  248. if not try_to_consume(_ELSE) then
  249. consume(_OTHERWISE);
  250. elseblock:=statements_til_end;
  251. end
  252. else
  253. begin
  254. elseblock:=nil;
  255. consume(_END);
  256. end;
  257. code:=ccasenode.create(caseexpr,instruc,root);
  258. tcasenode(code).elseblock:=elseblock;
  259. case_statement:=code;
  260. end;
  261. function repeat_statement : tnode;
  262. var
  263. first,last,p_e : tnode;
  264. begin
  265. consume(_REPEAT);
  266. first:=nil;
  267. while token<>_UNTIL do
  268. begin
  269. if first=nil then
  270. begin
  271. last:=cstatementnode.create(statement,nil);
  272. first:=last;
  273. end
  274. else
  275. begin
  276. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  277. last:=tstatementnode(last).right;
  278. end;
  279. if not try_to_consume(_SEMICOLON) then
  280. break;
  281. consume_emptystats;
  282. end;
  283. consume(_UNTIL);
  284. first:=cblocknode.create(first,true);
  285. p_e:=comp_expr(true);
  286. repeat_statement:=genloopnode(whilerepeatn,p_e,first,nil,true);
  287. end;
  288. function while_statement : tnode;
  289. var
  290. p_e,p_a : tnode;
  291. begin
  292. consume(_WHILE);
  293. p_e:=comp_expr(true);
  294. consume(_DO);
  295. p_a:=statement;
  296. while_statement:=genloopnode(whilerepeatn,p_e,p_a,nil,false);
  297. end;
  298. function for_statement : tnode;
  299. var
  300. p_e,tovalue,p_a : tnode;
  301. backward : boolean;
  302. begin
  303. { parse loop header }
  304. consume(_FOR);
  305. p_e:=expr;
  306. if token=_DOWNTO then
  307. begin
  308. consume(_DOWNTO);
  309. backward:=true;
  310. end
  311. else
  312. begin
  313. consume(_TO);
  314. backward:=false;
  315. end;
  316. tovalue:=comp_expr(true);
  317. consume(_DO);
  318. { ... now the instruction }
  319. p_a:=statement;
  320. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  321. end;
  322. function _with_statement : tnode;
  323. var
  324. right,p : tnode;
  325. i,levelcount : longint;
  326. withsymtable,symtab : tsymtable;
  327. obj : tobjectdef;
  328. hp : tnode;
  329. newblock : tblocknode;
  330. newstatement : tstatementnode;
  331. loadp : ttempcreatenode;
  332. refp : tnode;
  333. htype : ttype;
  334. hasimplicitderef : boolean;
  335. begin
  336. p:=comp_expr(true);
  337. do_resulttypepass(p);
  338. set_varstate(p,false);
  339. right:=nil;
  340. if (not codegenerror) and
  341. (p.resulttype.def.deftype in [objectdef,recorddef]) then
  342. begin
  343. newblock:=nil;
  344. { ignore nodes that don't add instructions in the tree }
  345. hp:=p;
  346. while { equal type conversions }
  347. (
  348. (hp.nodetype=typeconvn) and
  349. (ttypeconvnode(hp).convtype=tc_equal)
  350. ) or
  351. { constant array index }
  352. (
  353. (hp.nodetype=vecn) and
  354. (tvecnode(hp).right.nodetype=ordconstn)
  355. ) do
  356. hp:=tunarynode(hp).left;
  357. if (hp.nodetype=loadn) and
  358. (
  359. (tloadnode(hp).symtable=current_procdef.localst) or
  360. (tloadnode(hp).symtable=current_procdef.parast) or
  361. (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
  362. ) then
  363. begin
  364. { simple load, we can reference direct }
  365. loadp:=nil;
  366. refp:=p;
  367. end
  368. else
  369. begin
  370. { complex load, load in temp first }
  371. newblock:=internalstatements(newstatement,false);
  372. { classes and interfaces have implicit dereferencing }
  373. hasimplicitderef:=is_class_or_interface(p.resulttype.def);
  374. if hasimplicitderef then
  375. htype:=p.resulttype
  376. else
  377. htype.setdef(tpointerdef.create(p.resulttype));
  378. loadp:=ctempcreatenode.create(htype,POINTER_SIZE,tt_persistent);
  379. resulttypepass(loadp);
  380. if hasimplicitderef then
  381. begin
  382. hp:=p;
  383. refp:=ctemprefnode.create(loadp);
  384. end
  385. else
  386. begin
  387. hp:=caddrnode.create(p);
  388. refp:=cderefnode.create(ctemprefnode.create(loadp));
  389. end;
  390. addstatement(newstatement,loadp);
  391. addstatement(newstatement,cassignmentnode.create(
  392. ctemprefnode.create(loadp),
  393. hp));
  394. resulttypepass(refp);
  395. end;
  396. case p.resulttype.def.deftype of
  397. objectdef :
  398. begin
  399. obj:=tobjectdef(p.resulttype.def);
  400. withsymtable:=twithsymtable.Create(obj,obj.symtable.symsearch,refp);
  401. { include also all parent symtables }
  402. levelcount:=1;
  403. obj:=obj.childof;
  404. symtab:=withsymtable;
  405. while assigned(obj) do
  406. begin
  407. symtab.next:=twithsymtable.create(obj,obj.symtable.symsearch,refp);
  408. symtab:=symtab.next;
  409. obj:=obj.childof;
  410. inc(levelcount);
  411. end;
  412. symtab.next:=symtablestack;
  413. symtablestack:=withsymtable;
  414. end;
  415. recorddef :
  416. begin
  417. symtab:=trecorddef(p.resulttype.def).symtable;
  418. levelcount:=1;
  419. withsymtable:=twithsymtable.create(trecorddef(p.resulttype.def),symtab.symsearch,refp);
  420. withsymtable.next:=symtablestack;
  421. symtablestack:=withsymtable;
  422. end;
  423. end;
  424. if try_to_consume(_COMMA) then
  425. right:=_with_statement{$ifdef FPCPROCVAR}(){$endif}
  426. else
  427. begin
  428. consume(_DO);
  429. if token<>_SEMICOLON then
  430. right:=statement
  431. else
  432. right:=cerrornode.create;
  433. end;
  434. { remove symtables from the stack }
  435. for i:=1 to levelcount do
  436. symtablestack:=symtablestack.next;
  437. p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refp);
  438. { Finalize complex withnode with destroy of temp }
  439. if assigned(newblock) then
  440. begin
  441. addstatement(newstatement,p);
  442. addstatement(newstatement,ctempdeletenode.create(loadp));
  443. p:=newblock;
  444. end;
  445. _with_statement:=p;
  446. end
  447. else
  448. begin
  449. Message(parser_e_false_with_expr);
  450. { try to recover from error }
  451. if try_to_consume(_COMMA) then
  452. begin
  453. hp:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  454. if (hp=nil) then; { remove warning about unused }
  455. end
  456. else
  457. begin
  458. consume(_DO);
  459. { ignore all }
  460. if token<>_SEMICOLON then
  461. statement;
  462. end;
  463. _with_statement:=nil;
  464. end;
  465. end;
  466. function with_statement : tnode;
  467. begin
  468. consume(_WITH);
  469. with_statement:=_with_statement;
  470. end;
  471. function raise_statement : tnode;
  472. var
  473. p,pobj,paddr,pframe : tnode;
  474. begin
  475. pobj:=nil;
  476. paddr:=nil;
  477. pframe:=nil;
  478. consume(_RAISE);
  479. if not(token in endtokens) then
  480. begin
  481. { object }
  482. pobj:=comp_expr(true);
  483. if try_to_consume(_AT) then
  484. begin
  485. paddr:=comp_expr(true);
  486. if try_to_consume(_COMMA) then
  487. pframe:=comp_expr(true);
  488. end;
  489. end
  490. else
  491. begin
  492. if (block_type<>bt_except) then
  493. Message(parser_e_no_reraise_possible);
  494. end;
  495. p:=craisenode.create(pobj,paddr,pframe);
  496. raise_statement:=p;
  497. end;
  498. function try_statement : tnode;
  499. var
  500. p_try_block,p_finally_block,first,last,
  501. p_default,p_specific,hp : tnode;
  502. ot : ttype;
  503. sym : tvarsym;
  504. old_block_type : tblock_type;
  505. exceptsymtable : tsymtable;
  506. objname,objrealname : stringid;
  507. srsym : tsym;
  508. srsymtable : tsymtable;
  509. oldaktexceptblock: integer;
  510. begin
  511. include(current_procinfo.flags,pi_uses_exceptions);
  512. p_default:=nil;
  513. p_specific:=nil;
  514. { read statements to try }
  515. consume(_TRY);
  516. first:=nil;
  517. inc(exceptblockcounter);
  518. oldaktexceptblock := aktexceptblock;
  519. aktexceptblock := exceptblockcounter;
  520. while (token<>_FINALLY) and (token<>_EXCEPT) do
  521. begin
  522. if first=nil then
  523. begin
  524. last:=cstatementnode.create(statement,nil);
  525. first:=last;
  526. end
  527. else
  528. begin
  529. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  530. last:=tstatementnode(last).right;
  531. end;
  532. if not try_to_consume(_SEMICOLON) then
  533. break;
  534. consume_emptystats;
  535. end;
  536. p_try_block:=cblocknode.create(first,true);
  537. if try_to_consume(_FINALLY) then
  538. begin
  539. inc(exceptblockcounter);
  540. aktexceptblock := exceptblockcounter;
  541. p_finally_block:=statements_til_end;
  542. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  543. end
  544. else
  545. begin
  546. consume(_EXCEPT);
  547. old_block_type:=block_type;
  548. block_type:=bt_except;
  549. inc(exceptblockcounter);
  550. aktexceptblock := exceptblockcounter;
  551. ot:=generrortype;
  552. p_specific:=nil;
  553. if (idtoken=_ON) then
  554. { catch specific exceptions }
  555. begin
  556. repeat
  557. consume(_ID);
  558. if token=_ID then
  559. begin
  560. objname:=pattern;
  561. objrealname:=orgpattern;
  562. { can't use consume_sym here, because we need already
  563. to check for the colon }
  564. searchsym(objname,srsym,srsymtable);
  565. consume(_ID);
  566. { is a explicit name for the exception given ? }
  567. if try_to_consume(_COLON) then
  568. begin
  569. consume_sym(srsym,srsymtable);
  570. if (srsym.typ=typesym) and
  571. is_class(ttypesym(srsym).restype.def) then
  572. begin
  573. ot:=ttypesym(srsym).restype;
  574. sym:=tvarsym.create(objrealname,vs_value,ot);
  575. end
  576. else
  577. begin
  578. sym:=tvarsym.create(objrealname,vs_value,generrortype);
  579. if (srsym.typ=typesym) then
  580. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  581. else
  582. Message1(type_e_class_type_expected,ot.def.typename);
  583. end;
  584. exceptsymtable:=tstt_exceptsymtable.create;
  585. exceptsymtable.insert(sym);
  586. { insert the exception symtable stack }
  587. exceptsymtable.next:=symtablestack;
  588. symtablestack:=exceptsymtable;
  589. end
  590. else
  591. begin
  592. { check if type is valid, must be done here because
  593. with "e: Exception" the e is not necessary }
  594. if srsym=nil then
  595. begin
  596. identifier_not_found(objrealname);
  597. srsym:=generrorsym;
  598. end;
  599. { support unit.identifier }
  600. if srsym.typ=unitsym then
  601. begin
  602. consume(_POINT);
  603. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
  604. if srsym=nil then
  605. begin
  606. identifier_not_found(orgpattern);
  607. srsym:=generrorsym;
  608. end;
  609. consume(_ID);
  610. end;
  611. { check if type is valid, must be done here because
  612. with "e: Exception" the e is not necessary }
  613. if (srsym.typ=typesym) and
  614. is_class(ttypesym(srsym).restype.def) then
  615. ot:=ttypesym(srsym).restype
  616. else
  617. begin
  618. ot:=generrortype;
  619. if (srsym.typ=typesym) then
  620. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  621. else
  622. Message1(type_e_class_type_expected,ot.def.typename);
  623. end;
  624. exceptsymtable:=nil;
  625. end;
  626. end
  627. else
  628. consume(_ID);
  629. consume(_DO);
  630. hp:=connode.create(nil,statement);
  631. if ot.def.deftype=errordef then
  632. begin
  633. hp.free;
  634. hp:=cerrornode.create;
  635. end;
  636. if p_specific=nil then
  637. begin
  638. last:=hp;
  639. p_specific:=last;
  640. end
  641. else
  642. begin
  643. tonnode(last).left:=hp;
  644. last:=tonnode(last).left;
  645. end;
  646. { set the informations }
  647. { only if the creation of the onnode was succesful, it's possible }
  648. { that last and hp are errornodes (JM) }
  649. if last.nodetype = onn then
  650. begin
  651. tonnode(last).excepttype:=tobjectdef(ot.def);
  652. tonnode(last).exceptsymtable:=exceptsymtable;
  653. end;
  654. { remove exception symtable }
  655. if assigned(exceptsymtable) then
  656. begin
  657. symtablestack:=symtablestack.next;
  658. if last.nodetype <> onn then
  659. exceptsymtable.free;
  660. end;
  661. if not try_to_consume(_SEMICOLON) then
  662. break;
  663. consume_emptystats;
  664. until (token in [_END,_ELSE]);
  665. if try_to_consume(_ELSE) then
  666. begin
  667. { catch the other exceptions }
  668. p_default:=statements_til_end;
  669. end
  670. else
  671. consume(_END);
  672. end
  673. else
  674. begin
  675. { catch all exceptions }
  676. p_default:=statements_til_end;
  677. end;
  678. block_type:=old_block_type;
  679. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  680. end;
  681. aktexceptblock := oldaktexceptblock;
  682. end;
  683. function _asm_statement : tnode;
  684. var
  685. asmstat : tasmnode;
  686. Marker : tai;
  687. r : tregister;
  688. found : boolean;
  689. hs : string;
  690. begin
  691. Inside_asm_statement:=true;
  692. case aktasmmode of
  693. asmmode_none : ; { just be there to allow to compile a compiler without
  694. any assembler readers }
  695. {$ifdef i386}
  696. {$ifndef NoRA386Att}
  697. asmmode_i386_att:
  698. asmstat:=tasmnode(ra386att.assemble);
  699. {$endif NoRA386Att}
  700. {$ifndef NoRA386Int}
  701. asmmode_i386_intel:
  702. asmstat:=tasmnode(ra386int.assemble);
  703. {$endif NoRA386Int}
  704. {$else not i386}
  705. asmmode_standard:
  706. asmstat:=tasmnode(rasm.assemble);
  707. {$endif i386}
  708. asmmode_direct:
  709. begin
  710. if not target_asm.allowdirect then
  711. Message(parser_f_direct_assembler_not_allowed);
  712. if (current_procdef.proccalloption=pocall_inline) then
  713. Begin
  714. Message1(parser_w_not_supported_for_inline,'direct asm');
  715. Message(parser_w_inlining_disabled);
  716. current_procdef.proccalloption:=pocall_fpccall;
  717. End;
  718. asmstat:=tasmnode(radirect.assemble);
  719. end;
  720. else
  721. Message(parser_f_assembler_reader_not_supported);
  722. end;
  723. { Read first the _ASM statement }
  724. consume(_ASM);
  725. { END is read }
  726. if try_to_consume(_LECKKLAMMER) then
  727. begin
  728. if token<>_RECKKLAMMER then
  729. begin
  730. repeat
  731. { it's possible to specify the modified registers }
  732. hs:=upper(pattern);
  733. found:=false;
  734. for r.enum:=firstreg to lastreg do
  735. if hs=upper(std_reg2str[r.enum]) then
  736. begin
  737. include(rg.usedinproc,r.enum);
  738. include(rg.usedbyproc,r.enum);
  739. found:=true;
  740. break;
  741. end;
  742. if not(found) then
  743. Message(asmr_e_invalid_register);
  744. consume(_CSTRING);
  745. if not try_to_consume(_COMMA) then
  746. break;
  747. until false;
  748. end;
  749. consume(_RECKKLAMMER);
  750. end
  751. else
  752. begin
  753. rg.usedbyproc := ALL_REGISTERS;
  754. rg.usedinproc := ALL_REGISTERS;
  755. end;
  756. { mark the start and the end of the assembler block
  757. this is needed for the optimizer }
  758. If Assigned(AsmStat.p_asm) Then
  759. Begin
  760. Marker := Tai_Marker.Create(AsmBlockStart);
  761. AsmStat.p_asm.Insert(Marker);
  762. Marker := Tai_Marker.Create(AsmBlockEnd);
  763. AsmStat.p_asm.Concat(Marker);
  764. End;
  765. Inside_asm_statement:=false;
  766. _asm_statement:=asmstat;
  767. end;
  768. function statement : tnode;
  769. var
  770. p : tnode;
  771. code : tnode;
  772. filepos : tfileposinfo;
  773. srsym : tsym;
  774. srsymtable : tsymtable;
  775. s : stringid;
  776. begin
  777. filepos:=akttokenpos;
  778. case token of
  779. _GOTO :
  780. begin
  781. if not(cs_support_goto in aktmoduleswitches)then
  782. Message(sym_e_goto_and_label_not_supported);
  783. consume(_GOTO);
  784. if (token<>_INTCONST) and (token<>_ID) then
  785. begin
  786. Message(sym_e_label_not_found);
  787. code:=cerrornode.create;
  788. end
  789. else
  790. begin
  791. if token=_ID then
  792. consume_sym(srsym,srsymtable)
  793. else
  794. begin
  795. searchsym(pattern,srsym,srsymtable);
  796. if srsym=nil then
  797. begin
  798. identifier_not_found(pattern);
  799. srsym:=generrorsym;
  800. srsymtable:=nil;
  801. end;
  802. consume(token);
  803. end;
  804. if srsym.typ<>labelsym then
  805. begin
  806. Message(sym_e_id_is_no_label_id);
  807. code:=cerrornode.create;
  808. end
  809. else
  810. begin
  811. code:=cgotonode.create(tlabelsym(srsym));
  812. tgotonode(code).labsym:=tlabelsym(srsym);
  813. { set flag that this label is used }
  814. tlabelsym(srsym).used:=true;
  815. end;
  816. end;
  817. end;
  818. _BEGIN :
  819. code:=statement_block(_BEGIN);
  820. _IF :
  821. code:=if_statement;
  822. _CASE :
  823. code:=case_statement;
  824. _REPEAT :
  825. code:=repeat_statement;
  826. _WHILE :
  827. code:=while_statement;
  828. _FOR :
  829. code:=for_statement;
  830. _WITH :
  831. code:=with_statement;
  832. _TRY :
  833. code:=try_statement;
  834. _RAISE :
  835. code:=raise_statement;
  836. { semicolons,else until and end are ignored }
  837. _SEMICOLON,
  838. _ELSE,
  839. _UNTIL,
  840. _END:
  841. code:=cnothingnode.create;
  842. _FAIL :
  843. begin
  844. if (current_procdef.proctypeoption<>potype_constructor) then
  845. Message(parser_e_fail_only_in_constructor);
  846. consume(_FAIL);
  847. code:=call_fail_node;
  848. end;
  849. _ASM :
  850. code:=_asm_statement;
  851. _EOF :
  852. Message(scan_f_end_of_file);
  853. else
  854. begin
  855. p:=expr;
  856. { When a colon follows a intconst then transform it into a label }
  857. if try_to_consume(_COLON) then
  858. begin
  859. s:=tostr(tordconstnode(p).value);
  860. p.free;
  861. searchsym(s,srsym,srsymtable);
  862. if assigned(srsym) then
  863. begin
  864. if tlabelsym(srsym).defined then
  865. Message(sym_e_label_already_defined);
  866. tlabelsym(srsym).defined:=true;
  867. p:=clabelnode.create(tlabelsym(srsym),nil);
  868. end
  869. else
  870. begin
  871. Message1(sym_e_label_used_and_not_defined,s);
  872. p:=cnothingnode.create;
  873. end;
  874. end;
  875. if p.nodetype=labeln then
  876. begin
  877. { the pointer to the following instruction }
  878. { isn't a very clean way }
  879. tlabelnode(p).left:=statement{$ifdef FPCPROCVAR}(){$endif};
  880. { be sure to have left also resulttypepass }
  881. resulttypepass(tlabelnode(p).left);
  882. end;
  883. { blockn support because a read/write is changed into a blocknode }
  884. { with a separate statement for each read/write operation (JM) }
  885. { the same is true for val() if the third parameter is not 32 bit }
  886. if not(p.nodetype in [nothingn,calln,ifn,assignn,breakn,inlinen,
  887. continuen,labeln,blockn,exitn]) then
  888. Message(cg_e_illegal_expression);
  889. { specify that we don't use the value returned by the call }
  890. { Question : can this be also improtant
  891. for inlinen ??
  892. it is used for :
  893. - dispose of temp stack space
  894. - dispose on FPU stack }
  895. if p.nodetype=calln then
  896. exclude(p.flags,nf_return_value_used);
  897. code:=p;
  898. end;
  899. end;
  900. if assigned(code) then
  901. code.set_tree_filepos(filepos);
  902. statement:=code;
  903. end;
  904. function statement_block(starttoken : ttoken) : tnode;
  905. var
  906. first,last : tnode;
  907. filepos : tfileposinfo;
  908. begin
  909. first:=nil;
  910. filepos:=akttokenpos;
  911. consume(starttoken);
  912. while not(token in [_END,_FINALIZATION]) do
  913. begin
  914. if first=nil then
  915. begin
  916. last:=cstatementnode.create(statement,nil);
  917. first:=last;
  918. end
  919. else
  920. begin
  921. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  922. last:=tstatementnode(last).right;
  923. end;
  924. if (token in [_END,_FINALIZATION]) then
  925. break
  926. else
  927. begin
  928. { if no semicolon, then error and go on }
  929. if token<>_SEMICOLON then
  930. begin
  931. consume(_SEMICOLON);
  932. consume_all_until(_SEMICOLON);
  933. end;
  934. consume(_SEMICOLON);
  935. end;
  936. consume_emptystats;
  937. end;
  938. { don't consume the finalization token, it is consumed when
  939. reading the finalization block, but allow it only after
  940. an initalization ! }
  941. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  942. consume(_END);
  943. last:=cblocknode.create(first,true);
  944. last.set_tree_filepos(filepos);
  945. statement_block:=last;
  946. end;
  947. function assembler_block : tnode;
  948. {# Optimize the assembler block by removing all references
  949. which are via the frame pointer by replacing them with
  950. references via the stack pointer.
  951. This is only available to certain cpu targets where
  952. the frame pointer saving must be done explicitly.
  953. }
  954. procedure OptimizeFramePointer(p:tasmnode);
  955. var
  956. hp : tai;
  957. parafixup,
  958. i : longint;
  959. begin
  960. { replace framepointer with stackpointer }
  961. current_procinfo.framepointer.enum:=R_INTREGISTER;
  962. current_procinfo.framepointer.number:=NR_STACK_POINTER_REG;
  963. { set the right value for parameters }
  964. dec(current_procdef.parast.address_fixup,pointer_size);
  965. { replace all references to parameters in the instructions,
  966. the parameters can be identified by the parafixup option
  967. that is set. For normal user coded [ebp+4] this field is not
  968. set }
  969. parafixup:=current_procdef.parast.address_fixup;
  970. hp:=tai(p.p_asm.first);
  971. while assigned(hp) do
  972. begin
  973. if hp.typ=ait_instruction then
  974. begin
  975. { fixup the references }
  976. for i:=1 to taicpu(hp).ops do
  977. begin
  978. with taicpu(hp).oper[i-1] do
  979. if typ=top_ref then
  980. begin
  981. case ref^.options of
  982. ref_parafixup :
  983. begin
  984. ref^.offsetfixup:=parafixup;
  985. ref^.base.enum:=R_INTREGISTER;
  986. ref^.base.number:=NR_STACK_POINTER_REG;
  987. end;
  988. end;
  989. end;
  990. end;
  991. end;
  992. hp:=tai(hp.next);
  993. end;
  994. end;
  995. {$ifdef CHECKFORPUSH}
  996. function UsesPush(p:tasmnode):boolean;
  997. var
  998. hp : tai;
  999. begin
  1000. hp:=tai(p.p_asm.first);
  1001. while assigned(hp) do
  1002. begin
  1003. if (hp.typ=ait_instruction) and
  1004. (taicpu(hp).opcode=A_PUSH) then
  1005. begin
  1006. UsesPush:=true;
  1007. exit;
  1008. end;
  1009. hp:=tai(hp.next);
  1010. end;
  1011. UsesPush:=false;
  1012. end;
  1013. {$endif CHECKFORPUSH}
  1014. var
  1015. p : tnode;
  1016. begin
  1017. { Rename the funcret so that recursive calls are possible }
  1018. if not is_void(current_procdef.rettype.def) then
  1019. symtablestack.rename(current_procdef.resultname,'$hiddenresult');
  1020. { force the asm statement }
  1021. if token<>_ASM then
  1022. consume(_ASM);
  1023. include(current_procinfo.flags,pi_is_assembler);
  1024. p:=_asm_statement;
  1025. { set the framepointer to esp for assembler functions when the
  1026. following conditions are met:
  1027. - if the are no local variables (except the allocated result)
  1028. - if the are no parameters
  1029. - no reference to the result variable (refcount<=1)
  1030. - result is not stored as parameter
  1031. - target processor has optional frame pointer save
  1032. (vm, i386, vm only currently)
  1033. }
  1034. if (po_assembler in current_procdef.procoptions) and
  1035. {$ifndef powerpc}
  1036. { is this really necessary??? }
  1037. (current_procdef.parast.datasize=0) and
  1038. {$endif powerpc}
  1039. (current_procdef.localst.datasize=current_procdef.rettype.def.size) and
  1040. (current_procdef.owner.symtabletype<>objectsymtable) and
  1041. (not assigned(current_procdef.funcretsym) or
  1042. (tvarsym(current_procdef.funcretsym).refcount<=1)) and
  1043. not(paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption)) then
  1044. begin
  1045. { we don't need to allocate space for the locals }
  1046. current_procdef.localst.datasize:=0;
  1047. current_procinfo.firsttemp_offset:=0;
  1048. { only for cpus with different frame- and stack pointer the code must be changed }
  1049. if (NR_STACK_POINTER_REG<>NR_FRAME_POINTER_REG)
  1050. {$ifdef CHECKFORPUSH}
  1051. and not(UsesPush(tasmnode(p)))
  1052. {$endif CHECKFORPUSH}
  1053. then
  1054. OptimizeFramePointer(tasmnode(p));
  1055. end;
  1056. { Flag the result as assigned when it is returned in a
  1057. register.
  1058. }
  1059. if assigned(current_procdef.funcretsym) and
  1060. (not paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption)) then
  1061. tvarsym(current_procdef.funcretsym).varstate:=vs_assigned;
  1062. { because the END is already read we need to get the
  1063. last_endtoken_filepos here (PFV) }
  1064. last_endtoken_filepos:=akttokenpos;
  1065. assembler_block:=p;
  1066. end;
  1067. end.
  1068. {
  1069. $Log$
  1070. Revision 1.102 2003-05-23 22:33:48 florian
  1071. * fix some small flaws which prevent sparc linux system unit from compiling
  1072. * some reformatting done
  1073. Revision 1.101 2003/05/23 15:15:36 peter
  1074. * better error for undefined ordinal labels
  1075. Revision 1.100 2003/05/17 13:30:08 jonas
  1076. * changed tt_persistant to tt_persistent :)
  1077. * tempcreatenode now doesn't accept a boolean anymore for persistent
  1078. temps, but a ttemptype, so you can also create ansistring temps etc
  1079. Revision 1.99 2003/05/15 18:58:53 peter
  1080. * removed selfpointer_offset, vmtpointer_offset
  1081. * tvarsym.adjusted_address
  1082. * address in localsymtable is now in the real direction
  1083. * removed some obsolete globals
  1084. Revision 1.98 2003/05/13 19:14:41 peter
  1085. * failn removed
  1086. * inherited result code check moven to pexpr
  1087. Revision 1.97 2003/05/11 14:45:12 peter
  1088. * tloadnode does not support objectsymtable,withsymtable anymore
  1089. * withnode cleanup
  1090. * direct with rewritten to use temprefnode
  1091. Revision 1.96 2003/05/09 17:47:03 peter
  1092. * self moved to hidden parameter
  1093. * removed hdisposen,hnewn,selfn
  1094. Revision 1.95 2003/04/30 22:15:59 florian
  1095. * some 64 bit adaptions in ncgadd
  1096. * x86-64 now uses ncgadd
  1097. * tparamanager.ret_in_acc doesn't return true anymore for a void-def
  1098. Revision 1.94 2003/04/27 11:21:34 peter
  1099. * aktprocdef renamed to current_procdef
  1100. * procinfo renamed to current_procinfo
  1101. * procinfo will now be stored in current_module so it can be
  1102. cleaned up properly
  1103. * gen_main_procsym changed to create_main_proc and release_main_proc
  1104. to also generate a tprocinfo structure
  1105. * fixed unit implicit initfinal
  1106. Revision 1.93 2003/04/27 07:29:50 peter
  1107. * current_procdef cleanup, current_procdef is now always nil when parsing
  1108. a new procdef declaration
  1109. * aktprocsym removed
  1110. * lexlevel removed, use symtable.symtablelevel instead
  1111. * implicit init/final code uses the normal genentry/genexit
  1112. * funcret state checking updated for new funcret handling
  1113. Revision 1.92 2003/04/26 11:30:59 florian
  1114. * fixed the powerpc to work with the new function result handling
  1115. Revision 1.91 2003/04/25 20:59:34 peter
  1116. * removed funcretn,funcretsym, function result is now in varsym
  1117. and aliases for result and function name are added using absolutesym
  1118. * vs_hidden parameter for funcret passed in parameter
  1119. * vs_hidden fixes
  1120. * writenode changed to printnode and released from extdebug
  1121. * -vp option added to generate a tree.log with the nodetree
  1122. * nicer printnode for statements, callnode
  1123. Revision 1.90 2002/04/25 20:15:40 florian
  1124. * block nodes within expressions shouldn't release the used registers,
  1125. fixed using a flag till the new rg is ready
  1126. Revision 1.89 2003/04/25 08:25:26 daniel
  1127. * Ifdefs around a lot of calls to cleartempgen
  1128. * Fixed registers that are allocated but not freed in several nodes
  1129. * Tweak to register allocator to cause less spills
  1130. * 8-bit registers now interfere with esi,edi and ebp
  1131. Compiler can now compile rtl successfully when using new register
  1132. allocator
  1133. Revision 1.88 2003/03/28 19:16:57 peter
  1134. * generic constructor working for i386
  1135. * remove fixed self register
  1136. * esi added as address register for i386
  1137. Revision 1.87 2003/03/17 18:55:30 peter
  1138. * allow more tokens instead of only semicolon after inherited
  1139. Revision 1.86 2003/02/19 22:00:14 daniel
  1140. * Code generator converted to new register notation
  1141. - Horribily outdated todo.txt removed
  1142. Revision 1.85 2003/01/08 18:43:56 daniel
  1143. * Tregister changed into a record
  1144. Revision 1.84 2003/01/01 21:05:24 peter
  1145. * fixed assembler methods stackpointer optimization that was
  1146. broken after the previous change
  1147. Revision 1.83 2002/12/29 18:59:34 peter
  1148. * fixed parsing of declarations before asm statement
  1149. Revision 1.82 2002/12/27 18:18:56 peter
  1150. * check for else after empty raise statement
  1151. Revision 1.81 2002/11/27 02:37:14 peter
  1152. * case statement inlining added
  1153. * fixed inlining of write()
  1154. * switched statementnode left and right parts so the statements are
  1155. processed in the correct order when getcopy is used. This is
  1156. required for tempnodes
  1157. Revision 1.80 2002/11/25 17:43:22 peter
  1158. * splitted defbase in defutil,symutil,defcmp
  1159. * merged isconvertable and is_equal into compare_defs(_ext)
  1160. * made operator search faster by walking the list only once
  1161. Revision 1.79 2002/11/18 17:31:58 peter
  1162. * pass proccalloption to ret_in_xxx and push_xxx functions
  1163. Revision 1.78 2002/09/07 19:34:08 florian
  1164. + tcg.direction is used now
  1165. Revision 1.77 2002/09/07 15:25:07 peter
  1166. * old logs removed and tabs fixed
  1167. Revision 1.76 2002/09/07 12:16:03 carl
  1168. * second part bug report 1996 fix, testrange in cordconstnode
  1169. only called if option is set (also make parsing a tiny faster)
  1170. Revision 1.75 2002/09/02 18:40:52 peter
  1171. * fixed parsing of register names with lowercase
  1172. Revision 1.74 2002/09/01 14:43:12 peter
  1173. * fixed direct assembler for i386
  1174. Revision 1.73 2002/08/25 19:25:20 peter
  1175. * sym.insert_in_data removed
  1176. * symtable.insertvardata/insertconstdata added
  1177. * removed insert_in_data call from symtable.insert, it needs to be
  1178. called separatly. This allows to deref the address calculation
  1179. * procedures now calculate the parast addresses after the procedure
  1180. directives are parsed. This fixes the cdecl parast problem
  1181. * push_addr_param has an extra argument that specifies if cdecl is used
  1182. or not
  1183. Revision 1.72 2002/08/17 09:23:40 florian
  1184. * first part of procinfo rewrite
  1185. Revision 1.71 2002/08/16 14:24:58 carl
  1186. * issameref() to test if two references are the same (then emit no opcodes)
  1187. + ret_in_reg to replace ret_in_acc
  1188. (fix some register allocation bugs at the same time)
  1189. + save_std_register now has an extra parameter which is the
  1190. usedinproc registers
  1191. Revision 1.70 2002/08/11 14:32:27 peter
  1192. * renamed current_library to objectlibrary
  1193. Revision 1.69 2002/08/11 13:24:12 peter
  1194. * saving of asmsymbols in ppu supported
  1195. * asmsymbollist global is removed and moved into a new class
  1196. tasmlibrarydata that will hold the info of a .a file which
  1197. corresponds with a single module. Added librarydata to tmodule
  1198. to keep the library info stored for the module. In the future the
  1199. objectfiles will also be stored to the tasmlibrarydata class
  1200. * all getlabel/newasmsymbol and friends are moved to the new class
  1201. Revision 1.68 2002/08/10 14:46:30 carl
  1202. + moved target_cpu_string to cpuinfo
  1203. * renamed asmmode enum.
  1204. * assembler reader has now less ifdef's
  1205. * move from nppcmem.pas -> ncgmem.pas vec. node.
  1206. Revision 1.67 2002/08/09 19:11:44 carl
  1207. + reading of used registers in assembler routines is now
  1208. cpu-independent
  1209. Revision 1.66 2002/08/06 20:55:22 florian
  1210. * first part of ppc calling conventions fix
  1211. Revision 1.65 2002/07/28 20:45:22 florian
  1212. + added direct assembler reader for PowerPC
  1213. Revision 1.64 2002/07/20 11:57:56 florian
  1214. * types.pas renamed to defbase.pas because D6 contains a types
  1215. unit so this would conflicts if D6 programms are compiled
  1216. + Willamette/SSE2 instructions to assembler added
  1217. Revision 1.63 2002/07/19 11:41:36 daniel
  1218. * State tracker work
  1219. * The whilen and repeatn are now completely unified into whilerepeatn. This
  1220. allows the state tracker to change while nodes automatically into
  1221. repeat nodes.
  1222. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  1223. 'not(a>b)' is optimized into 'a<=b'.
  1224. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  1225. by removing the notn and later switchting the true and falselabels. The
  1226. same is done with 'repeat until not a'.
  1227. Revision 1.62 2002/07/16 15:34:20 florian
  1228. * exit is now a syssym instead of a keyword
  1229. Revision 1.61 2002/07/11 14:41:28 florian
  1230. * start of the new generic parameter handling
  1231. Revision 1.60 2002/07/04 20:43:01 florian
  1232. * first x86-64 patches
  1233. Revision 1.59 2002/07/01 18:46:25 peter
  1234. * internal linker
  1235. * reorganized aasm layer
  1236. Revision 1.58 2002/05/18 13:34:13 peter
  1237. * readded missing revisions
  1238. Revision 1.57 2002/05/16 19:46:44 carl
  1239. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1240. + try to fix temp allocation (still in ifdef)
  1241. + generic constructor calls
  1242. + start of tassembler / tmodulebase class cleanup
  1243. }