pstatmnt.pas 44 KB

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