pstatmnt.pas 49 KB

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