2
0

pstatmnt.pas 43 KB

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