pstatmnt.pas 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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 defines.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,cobjects,
  30. { global }
  31. globtype,globals,verbose,
  32. systems,cpuinfo,
  33. { aasm }
  34. cpubase,aasm,
  35. { symtable }
  36. symconst,symtable,types,
  37. ppu,fmodule,
  38. { pass 1 }
  39. pass_1,htypechk,
  40. nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  41. { parser }
  42. scanner,
  43. pbase,pexpr,
  44. {$ifdef i386}
  45. {$ifndef NoRa386Int}
  46. ra386int,
  47. {$endif NoRa386Int}
  48. {$ifndef NoRa386Att}
  49. ra386att,
  50. {$endif NoRa386Att}
  51. {$ifndef NoRa386Dir}
  52. ra386dir,
  53. {$endif NoRa386Dir}
  54. {$endif i386}
  55. {$ifdef m68k}
  56. {$ifndef NoRa68kMot}
  57. ra68kmot,
  58. {$endif NoRa68kMot}
  59. {$endif m68k}
  60. { codegen }
  61. {$ifdef newcg}
  62. cgbase
  63. {$else newcg}
  64. hcodegen
  65. {$ifdef i386}
  66. ,tgeni386
  67. {$endif i386}
  68. {$ifdef m68k}
  69. ,tgen68k
  70. {$endif m68k}
  71. {$endif newcg}
  72. ;
  73. const
  74. statement_level : longint = 0;
  75. function statement : tnode;forward;
  76. function if_statement : tnode;
  77. var
  78. ex,if_a,else_a : tnode;
  79. begin
  80. consume(_IF);
  81. ex:=comp_expr(true);
  82. consume(_THEN);
  83. if token<>_ELSE then
  84. if_a:=statement
  85. else
  86. if_a:=nil;
  87. if try_to_consume(_ELSE) then
  88. else_a:=statement
  89. else
  90. else_a:=nil;
  91. if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  92. end;
  93. { creates a block (list) of statements, til the next END token }
  94. function statements_til_end : tnode;
  95. var
  96. first,last : tstatementnode;
  97. begin
  98. first:=nil;
  99. while token<>_END do
  100. begin
  101. if first=nil then
  102. begin
  103. last:=cstatementnode.create(nil,statement);
  104. first:=last;
  105. end
  106. else
  107. begin
  108. last.left:=cstatementnode.create(nil,statement);
  109. last:=tstatementnode(last.left);
  110. end;
  111. if not try_to_consume(_SEMICOLON) then
  112. break;
  113. emptystats;
  114. end;
  115. consume(_END);
  116. statements_til_end:=cblocknode.create(first);
  117. end;
  118. function case_statement : tnode;
  119. var
  120. { contains the label number of currently parsed case block }
  121. aktcaselabel : pasmlabel;
  122. firstlabel : boolean;
  123. root : pcaserecord;
  124. { the typ of the case expression }
  125. casedef : pdef;
  126. procedure newcaselabel(l,h : longint;first:boolean);
  127. var
  128. hcaselabel : pcaserecord;
  129. procedure insertlabel(var p : pcaserecord);
  130. begin
  131. if p=nil then p:=hcaselabel
  132. else
  133. if (p^._low>hcaselabel^._low) and
  134. (p^._low>hcaselabel^._high) then
  135. if (hcaselabel^.statement = p^.statement) and
  136. (p^._low = hcaselabel^._high + 1) then
  137. begin
  138. p^._low := hcaselabel^._low;
  139. dispose(hcaselabel);
  140. end
  141. else
  142. insertlabel(p^.less)
  143. else
  144. if (p^._high<hcaselabel^._low) and
  145. (p^._high<hcaselabel^._high) then
  146. if (hcaselabel^.statement = p^.statement) and
  147. (p^._high+1 = hcaselabel^._low) then
  148. begin
  149. p^._high := hcaselabel^._high;
  150. dispose(hcaselabel);
  151. end
  152. else
  153. insertlabel(p^.greater)
  154. else Message(parser_e_double_caselabel);
  155. end;
  156. begin
  157. new(hcaselabel);
  158. hcaselabel^.less:=nil;
  159. hcaselabel^.greater:=nil;
  160. hcaselabel^.statement:=aktcaselabel;
  161. hcaselabel^.firstlabel:=first;
  162. getlabel(hcaselabel^._at);
  163. hcaselabel^._low:=l;
  164. hcaselabel^._high:=h;
  165. insertlabel(root);
  166. end;
  167. var
  168. code,caseexpr,p,instruc,elseblock : tnode;
  169. hl1,hl2 : TConstExprInt;
  170. casedeferror : boolean;
  171. begin
  172. consume(_CASE);
  173. caseexpr:=comp_expr(true);
  174. { determines result type }
  175. cleartempgen;
  176. do_firstpass(caseexpr);
  177. casedeferror:=false;
  178. casedef:=caseexpr.resulttype;
  179. if (not assigned(casedef)) or
  180. not(is_ordinal(casedef)) then
  181. begin
  182. CGMessage(type_e_ordinal_expr_expected);
  183. { create a correct tree }
  184. caseexpr.free;
  185. caseexpr:=genordinalconstnode(0,u32bitdef);
  186. { set error flag so no rangechecks are done }
  187. casedeferror:=true;
  188. end;
  189. consume(_OF);
  190. inc(statement_level);
  191. root:=nil;
  192. instruc:=nil;
  193. repeat
  194. getlabel(aktcaselabel);
  195. firstlabel:=true;
  196. { may be an instruction has more case labels }
  197. repeat
  198. p:=expr;
  199. cleartempgen;
  200. do_firstpass(p);
  201. hl1:=0;
  202. hl2:=0;
  203. if (p.nodetype=rangen) then
  204. begin
  205. { type checking for case statements }
  206. if is_subequal(casedef, trangenode(p).left.resulttype) and
  207. is_subequal(casedef, trangenode(p).right.resulttype) then
  208. begin
  209. hl1:=get_ordinal_value(trangenode(p).left);
  210. hl2:=get_ordinal_value(trangenode(p).right);
  211. if hl1>hl2 then
  212. CGMessage(parser_e_case_lower_less_than_upper_bound);
  213. if not casedeferror then
  214. begin
  215. testrange(casedef,hl1);
  216. testrange(casedef,hl2);
  217. end;
  218. end
  219. else
  220. CGMessage(parser_e_case_mismatch);
  221. newcaselabel(hl1,hl2,firstlabel);
  222. end
  223. else
  224. begin
  225. { type checking for case statements }
  226. if not is_subequal(casedef, p.resulttype) then
  227. CGMessage(parser_e_case_mismatch);
  228. hl1:=get_ordinal_value(p);
  229. if not casedeferror then
  230. testrange(casedef,hl1);
  231. newcaselabel(hl1,hl1,firstlabel);
  232. end;
  233. p.free;
  234. if token=_COMMA then
  235. consume(_COMMA)
  236. else
  237. break;
  238. firstlabel:=false;
  239. until false;
  240. consume(_COLON);
  241. { handles instruction block }
  242. p:=clabelnode.create(aktcaselabel,statement);
  243. { concats instruction }
  244. instruc:=cstatementnode.create(instruc,p);
  245. if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
  246. consume(_SEMICOLON);
  247. until (token=_ELSE) or (token=_OTHERWISE) or (token=_END);
  248. if (token=_ELSE) or (token=_OTHERWISE) then
  249. begin
  250. if not try_to_consume(_ELSE) then
  251. consume(_OTHERWISE);
  252. elseblock:=statements_til_end;
  253. end
  254. else
  255. begin
  256. elseblock:=nil;
  257. consume(_END);
  258. end;
  259. dec(statement_level);
  260. code:=ccasenode.create(caseexpr,instruc,root);
  261. tcasenode(code).elseblock:=elseblock;
  262. case_statement:=code;
  263. end;
  264. function repeat_statement : tnode;
  265. var
  266. first,last,p_e : tnode;
  267. begin
  268. consume(_REPEAT);
  269. first:=nil;
  270. inc(statement_level);
  271. while token<>_UNTIL do
  272. begin
  273. if first=nil then
  274. begin
  275. last:=cstatementnode.create(nil,statement);
  276. first:=last;
  277. end
  278. else
  279. begin
  280. tstatementnode(last).left:=cstatementnode.create(nil,statement);
  281. last:=tstatementnode(last).left;
  282. end;
  283. if not try_to_consume(_SEMICOLON) then
  284. break;
  285. emptystats;
  286. end;
  287. consume(_UNTIL);
  288. dec(statement_level);
  289. first:=cblocknode.create(first);
  290. p_e:=comp_expr(true);
  291. repeat_statement:=genloopnode(repeatn,p_e,first,nil,false);
  292. end;
  293. function while_statement : tnode;
  294. var
  295. p_e,p_a : tnode;
  296. begin
  297. consume(_WHILE);
  298. p_e:=comp_expr(true);
  299. consume(_DO);
  300. p_a:=statement;
  301. while_statement:=genloopnode(whilen,p_e,p_a,nil,false);
  302. end;
  303. function for_statement : tnode;
  304. var
  305. p_e,tovalue,p_a : tnode;
  306. backward : boolean;
  307. begin
  308. { parse loop header }
  309. consume(_FOR);
  310. p_e:=expr;
  311. if token=_DOWNTO then
  312. begin
  313. consume(_DOWNTO);
  314. backward:=true;
  315. end
  316. else
  317. begin
  318. consume(_TO);
  319. backward:=false;
  320. end;
  321. tovalue:=comp_expr(true);
  322. consume(_DO);
  323. { ... now the instruction }
  324. p_a:=statement;
  325. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  326. end;
  327. function _with_statement : tnode;
  328. var
  329. right,p : tnode;
  330. i,levelcount : longint;
  331. withsymtable,symtab : psymtable;
  332. obj : pobjectdef;
  333. hp : tnode;
  334. begin
  335. p:=comp_expr(true);
  336. do_firstpass(p);
  337. set_varstate(p,false);
  338. right:=nil;
  339. if (not codegenerror) and
  340. (p.resulttype^.deftype in [objectdef,recorddef]) then
  341. begin
  342. case p.resulttype^.deftype of
  343. objectdef : begin
  344. obj:=pobjectdef(p.resulttype);
  345. withsymtable:=new(pwithsymtable,init);
  346. withsymtable^.symsearch:=obj^.symtable^.symsearch;
  347. withsymtable^.defowner:=obj;
  348. symtab:=withsymtable;
  349. if (p.nodetype=loadn) and
  350. (tloadnode(p).symtable=aktprocsym^.definition^.localst) then
  351. pwithsymtable(symtab)^.direct_with:=true;
  352. {symtab^.withnode:=p; not yet allocated !! }
  353. pwithsymtable(symtab)^.withrefnode:=p;
  354. levelcount:=1;
  355. obj:=obj^.childof;
  356. while assigned(obj) do
  357. begin
  358. symtab^.next:=new(pwithsymtable,init);
  359. symtab:=symtab^.next;
  360. symtab^.symsearch:=obj^.symtable^.symsearch;
  361. if (p.nodetype=loadn) and
  362. (tloadnode(p).symtable=aktprocsym^.definition^.localst) then
  363. pwithsymtable(symtab)^.direct_with:=true;
  364. {symtab^.withnode:=p; not yet allocated !! }
  365. pwithsymtable(symtab)^.withrefnode:=p;
  366. symtab^.defowner:=obj;
  367. obj:=obj^.childof;
  368. inc(levelcount);
  369. end;
  370. symtab^.next:=symtablestack;
  371. symtablestack:=withsymtable;
  372. end;
  373. recorddef : begin
  374. symtab:=precorddef(p.resulttype)^.symtable;
  375. levelcount:=1;
  376. withsymtable:=new(pwithsymtable,init);
  377. withsymtable^.symsearch:=symtab^.symsearch;
  378. withsymtable^.next:=symtablestack;
  379. if (p.nodetype=loadn) and
  380. (tloadnode(p).symtable=aktprocsym^.definition^.localst) then
  381. pwithsymtable(withsymtable)^.direct_with:=true;
  382. {symtab^.withnode:=p; not yet allocated !! }
  383. pwithsymtable(withsymtable)^.withrefnode:=p;
  384. withsymtable^.defowner:=precorddef(p.resulttype);
  385. symtablestack:=withsymtable;
  386. end;
  387. end;
  388. if token=_COMMA then
  389. begin
  390. consume(_COMMA);
  391. right:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  392. end
  393. else
  394. begin
  395. consume(_DO);
  396. if token<>_SEMICOLON then
  397. right:=statement
  398. else
  399. right:=nil;
  400. end;
  401. for i:=1 to levelcount do
  402. symtablestack:=symtablestack^.next;
  403. _with_statement:=genwithnode(pwithsymtable(withsymtable),p,right,levelcount);
  404. end
  405. else
  406. begin
  407. Message(parser_e_false_with_expr);
  408. { try to recover from error }
  409. if token=_COMMA then
  410. begin
  411. consume(_COMMA);
  412. hp:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  413. if (hp=nil) then; { remove warning about unused }
  414. end
  415. else
  416. begin
  417. consume(_DO);
  418. { ignore all }
  419. if token<>_SEMICOLON then
  420. statement;
  421. end;
  422. _with_statement:=nil;
  423. end;
  424. end;
  425. function with_statement : tnode;
  426. begin
  427. consume(_WITH);
  428. with_statement:=_with_statement;
  429. end;
  430. function raise_statement : tnode;
  431. var
  432. p,pobj,paddr,pframe : tnode;
  433. begin
  434. pobj:=nil;
  435. paddr:=nil;
  436. pframe:=nil;
  437. consume(_RAISE);
  438. if not(token in [_SEMICOLON,_END]) then
  439. begin
  440. { object }
  441. pobj:=comp_expr(true);
  442. if try_to_consume(_AT) then
  443. begin
  444. paddr:=comp_expr(true);
  445. if try_to_consume(_COMMA) then
  446. pframe:=comp_expr(true);
  447. end;
  448. end
  449. else
  450. begin
  451. if (block_type<>bt_except) then
  452. Message(parser_e_no_reraise_possible);
  453. end;
  454. p:=craisenode.create(pobj,paddr,pframe);
  455. raise_statement:=p;
  456. end;
  457. function try_statement : tnode;
  458. var
  459. p_try_block,p_finally_block,first,last,
  460. p_default,p_specific,hp : tnode;
  461. ot : pobjectdef;
  462. sym : pvarsym;
  463. old_block_type : tblock_type;
  464. exceptsymtable : psymtable;
  465. objname : stringid;
  466. begin
  467. procinfo^.flags:=procinfo^.flags or
  468. pi_uses_exceptions;
  469. p_default:=nil;
  470. p_specific:=nil;
  471. { read statements to try }
  472. consume(_TRY);
  473. first:=nil;
  474. inc(statement_level);
  475. while (token<>_FINALLY) and (token<>_EXCEPT) do
  476. begin
  477. if first=nil then
  478. begin
  479. last:=cstatementnode.create(nil,statement);
  480. first:=last;
  481. end
  482. else
  483. begin
  484. tstatementnode(last).left:=cstatementnode.create(nil,statement);
  485. last:=tstatementnode(last).left;
  486. end;
  487. if not try_to_consume(_SEMICOLON) then
  488. break;
  489. emptystats;
  490. end;
  491. p_try_block:=cblocknode.create(first);
  492. if try_to_consume(_FINALLY) then
  493. begin
  494. p_finally_block:=statements_til_end;
  495. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  496. dec(statement_level);
  497. end
  498. else
  499. begin
  500. consume(_EXCEPT);
  501. old_block_type:=block_type;
  502. block_type:=bt_except;
  503. p_specific:=nil;
  504. if token=_ON then
  505. { catch specific exceptions }
  506. begin
  507. repeat
  508. consume(_ON);
  509. if token=_ID then
  510. begin
  511. objname:=pattern;
  512. getsym(objname,false);
  513. consume(_ID);
  514. { is a explicit name for the exception given ? }
  515. if try_to_consume(_COLON) then
  516. begin
  517. getsym(pattern,true);
  518. consume(_ID);
  519. if srsym^.typ=unitsym then
  520. begin
  521. consume(_POINT);
  522. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  523. consume(_ID);
  524. end;
  525. if (srsym^.typ=typesym) and
  526. (ptypesym(srsym)^.restype.def^.deftype=objectdef) and
  527. pobjectdef(ptypesym(srsym)^.restype.def)^.is_class then
  528. begin
  529. ot:=pobjectdef(ptypesym(srsym)^.restype.def);
  530. sym:=new(pvarsym,initdef(objname,ot));
  531. end
  532. else
  533. begin
  534. sym:=new(pvarsym,initdef(objname,new(perrordef,init)));
  535. if (srsym^.typ=typesym) then
  536. Message1(type_e_class_type_expected,ptypesym(srsym)^.restype.def^.typename)
  537. else
  538. Message1(type_e_class_type_expected,ot^.typename);
  539. end;
  540. exceptsymtable:=new(psymtable,init(stt_exceptsymtable));
  541. exceptsymtable^.insert(sym);
  542. { insert the exception symtable stack }
  543. exceptsymtable^.next:=symtablestack;
  544. symtablestack:=exceptsymtable;
  545. end
  546. else
  547. begin
  548. { check if type is valid, must be done here because
  549. with "e: Exception" the e is not necessary }
  550. if srsym=nil then
  551. begin
  552. Message1(sym_e_id_not_found,objname);
  553. srsym:=generrorsym;
  554. end;
  555. { only exception type }
  556. if srsym^.typ=unitsym then
  557. begin
  558. consume(_POINT);
  559. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  560. consume(_ID);
  561. end;
  562. if (srsym^.typ=typesym) and
  563. (ptypesym(srsym)^.restype.def^.deftype=objectdef) and
  564. pobjectdef(ptypesym(srsym)^.restype.def)^.is_class then
  565. ot:=pobjectdef(ptypesym(srsym)^.restype.def)
  566. else
  567. begin
  568. ot:=pobjectdef(generrordef);
  569. if (srsym^.typ=typesym) then
  570. Message1(type_e_class_type_expected,ptypesym(srsym)^.restype.def^.typename)
  571. else
  572. Message1(type_e_class_type_expected,ot^.typename);
  573. end;
  574. exceptsymtable:=nil;
  575. end;
  576. end
  577. else
  578. consume(_ID);
  579. consume(_DO);
  580. hp:=connode.create(nil,statement);
  581. if ot^.deftype=errordef then
  582. begin
  583. hp.free;
  584. hp:=cerrornode.create;
  585. end;
  586. if p_specific=nil then
  587. begin
  588. last:=hp;
  589. p_specific:=last;
  590. end
  591. else
  592. begin
  593. tonnode(last).left:=hp;
  594. last:=tonnode(last).left;
  595. end;
  596. { set the informations }
  597. tonnode(last).excepttype:=ot;
  598. tonnode(last).exceptsymtable:=exceptsymtable;
  599. { remove exception symtable }
  600. if assigned(exceptsymtable) then
  601. dellexlevel;
  602. if not try_to_consume(_SEMICOLON) then
  603. break;
  604. emptystats;
  605. until (token=_END) or (token=_ELSE);
  606. if token=_ELSE then
  607. { catch the other exceptions }
  608. begin
  609. consume(_ELSE);
  610. p_default:=statements_til_end;
  611. end
  612. else
  613. consume(_END);
  614. end
  615. else
  616. { catch all exceptions }
  617. begin
  618. p_default:=statements_til_end;
  619. end;
  620. dec(statement_level);
  621. block_type:=old_block_type;
  622. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  623. end;
  624. end;
  625. function exit_statement : tnode;
  626. var
  627. p : tnode;
  628. begin
  629. consume(_EXIT);
  630. if try_to_consume(_LKLAMMER) then
  631. begin
  632. p:=comp_expr(true);
  633. consume(_RKLAMMER);
  634. if (block_type=bt_except) then
  635. Message(parser_e_exit_with_argument_not__possible);
  636. if procinfo^.returntype.def=pdef(voiddef) then
  637. Message(parser_e_void_function);
  638. end
  639. else
  640. p:=nil;
  641. p:=cexitnode.create(p);
  642. // p.resulttype:=procinfo^.returntype.def;
  643. p.resulttype:=voiddef;
  644. exit_statement:=p;
  645. end;
  646. function _asm_statement : tnode;
  647. var
  648. asmstat : tasmnode;
  649. Marker : Pai;
  650. begin
  651. Inside_asm_statement:=true;
  652. case aktasmmode of
  653. asmmode_none : ; { just be there to allow to a compile without
  654. any assembler readers }
  655. {$ifdef i386}
  656. {$ifndef NoRA386Att}
  657. asmmode_i386_att:
  658. asmstat:=tasmnode(ra386att.assemble);
  659. {$endif NoRA386Att}
  660. {$ifndef NoRA386Int}
  661. asmmode_i386_intel:
  662. asmstat:=tasmnode(ra386int.assemble);
  663. {$endif NoRA386Int}
  664. {$ifndef NoRA386Dir}
  665. asmmode_i386_direct:
  666. begin
  667. if not target_asm.allowdirect then
  668. Message(parser_f_direct_assembler_not_allowed);
  669. if (pocall_inline in aktprocsym^.definition^.proccalloptions) then
  670. Begin
  671. Message1(parser_w_not_supported_for_inline,'direct asm');
  672. Message(parser_w_inlining_disabled);
  673. exclude(aktprocsym^.definition^.proccalloptions,pocall_inline);
  674. End;
  675. asmstat:=tasmnode(ra386dir.assemble);
  676. end;
  677. {$endif NoRA386Dir}
  678. {$endif}
  679. {$ifdef m68k}
  680. {$ifndef NoRA68kMot}
  681. asmmode_m68k_mot:
  682. asmstat:=tasmnode(ra68kmot.assemble);
  683. {$endif NoRA68kMot}
  684. {$endif}
  685. else
  686. Message(parser_f_assembler_reader_not_supported);
  687. end;
  688. { Read first the _ASM statement }
  689. consume(_ASM);
  690. {$ifndef newcg}
  691. { END is read }
  692. if try_to_consume(_LECKKLAMMER) then
  693. begin
  694. { it's possible to specify the modified registers }
  695. include(asmstat.flags,nf_object_preserved);
  696. if token<>_RECKKLAMMER then
  697. repeat
  698. { uppercase, because it's a CSTRING }
  699. uppervar(pattern);
  700. {$ifdef i386}
  701. if pattern='EAX' then
  702. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  703. else if pattern='EBX' then
  704. usedinproc:=usedinproc or ($80 shr byte(R_EBX))
  705. else if pattern='ECX' then
  706. usedinproc:=usedinproc or ($80 shr byte(R_ECX))
  707. else if pattern='EDX' then
  708. usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  709. else if pattern='ESI' then
  710. begin
  711. usedinproc:=usedinproc or ($80 shr byte(R_ESI));
  712. exclude(asmstat.flags,nf_object_preserved);
  713. end
  714. else if pattern='EDI' then
  715. usedinproc:=usedinproc or ($80 shr byte(R_EDI))
  716. {$endif i386}
  717. {$ifdef m68k}
  718. if pattern='D0' then
  719. usedinproc:=usedinproc or ($800 shr word(R_D0))
  720. else if pattern='D1' then
  721. usedinproc:=usedinproc or ($800 shr word(R_D1))
  722. else if pattern='D6' then
  723. usedinproc:=usedinproc or ($800 shr word(R_D6))
  724. else if pattern='A0' then
  725. usedinproc:=usedinproc or ($800 shr word(R_A0))
  726. else if pattern='A1' then
  727. usedinproc:=usedinproc or ($800 shr word(R_A1))
  728. {$endif m68k}
  729. else consume(_RECKKLAMMER);
  730. consume(_CSTRING);
  731. if not try_to_consume(_COMMA) then
  732. break;
  733. until false;
  734. consume(_RECKKLAMMER);
  735. end
  736. else usedinproc:=$ff;
  737. {$endif newcg}
  738. { mark the start and the end of the assembler block
  739. this is needed for the optimizer }
  740. If Assigned(AsmStat.p_asm) Then
  741. Begin
  742. Marker := New(Pai_Marker, Init(AsmBlockStart));
  743. AsmStat.p_asm^.Insert(Marker);
  744. Marker := New(Pai_Marker, Init(AsmBlockEnd));
  745. AsmStat.p_asm^.Concat(Marker);
  746. End;
  747. Inside_asm_statement:=false;
  748. _asm_statement:=asmstat;
  749. end;
  750. function new_dispose_statement : tnode;
  751. var
  752. p,p2 : tnode;
  753. again : boolean; { dummy for do_proc_call }
  754. destructorname : stringid;
  755. sym : psym;
  756. classh : pobjectdef;
  757. pd,pd2 : pdef;
  758. destructorpos,
  759. storepos : tfileposinfo;
  760. is_new : boolean;
  761. begin
  762. if try_to_consume(_NEW) then
  763. is_new:=true
  764. else
  765. begin
  766. consume(_DISPOSE);
  767. is_new:=false;
  768. end;
  769. consume(_LKLAMMER);
  770. p:=comp_expr(true);
  771. { calc return type }
  772. cleartempgen;
  773. do_firstpass(p);
  774. set_varstate(p,(not is_new));
  775. { constructor,destructor specified }
  776. if try_to_consume(_COMMA) then
  777. begin
  778. { extended syntax of new and dispose }
  779. { function styled new is handled in factor }
  780. { destructors have no parameters }
  781. destructorname:=pattern;
  782. destructorpos:=tokenpos;
  783. consume(_ID);
  784. pd:=p.resulttype;
  785. if pd=nil then
  786. pd:=generrordef;
  787. pd2:=pd;
  788. if (pd^.deftype<>pointerdef) then
  789. begin
  790. Message1(type_e_pointer_type_expected,pd^.typename);
  791. p.free;
  792. p:=factor(false);
  793. p.free;
  794. consume(_RKLAMMER);
  795. new_dispose_statement:=cerrornode.create;
  796. exit;
  797. end;
  798. { first parameter must be an object or class }
  799. if ppointerdef(pd)^.pointertype.def^.deftype<>objectdef then
  800. begin
  801. Message(parser_e_pointer_to_class_expected);
  802. p.free;
  803. new_dispose_statement:=factor(false);
  804. consume_all_until(_RKLAMMER);
  805. consume(_RKLAMMER);
  806. exit;
  807. end;
  808. { check, if the first parameter is a pointer to a _class_ }
  809. classh:=pobjectdef(ppointerdef(pd)^.pointertype.def);
  810. if classh^.is_class then
  811. begin
  812. Message(parser_e_no_new_or_dispose_for_classes);
  813. new_dispose_statement:=factor(false);
  814. consume_all_until(_RKLAMMER);
  815. consume(_RKLAMMER);
  816. exit;
  817. end;
  818. { search cons-/destructor, also in parent classes }
  819. storepos:=tokenpos;
  820. tokenpos:=destructorpos;
  821. sym:=search_class_member(classh,destructorname);
  822. tokenpos:=storepos;
  823. { the second parameter of new/dispose must be a call }
  824. { to a cons-/destructor }
  825. if (not assigned(sym)) or (sym^.typ<>procsym) then
  826. begin
  827. if is_new then
  828. Message(parser_e_expr_have_to_be_constructor_call)
  829. else
  830. Message(parser_e_expr_have_to_be_destructor_call);
  831. p.free;
  832. new_dispose_statement:=cerrornode.create;
  833. end
  834. else
  835. begin
  836. if is_new then
  837. p2:=chnewnode.create
  838. else
  839. p2:=chdisposenode.create(p);
  840. if is_new then
  841. begin
  842. { Constructors can take parameters.}
  843. p2.resulttype:=ppointerdef(pd)^.pointertype.def;
  844. do_member_read(false,sym,p2,pd,again);
  845. end
  846. else
  847. begin
  848. if (m_tp in aktmodeswitches) then
  849. begin
  850. { Constructors can take parameters.}
  851. p2.resulttype:=ppointerdef(pd)^.pointertype.def;
  852. do_member_read(false,sym,p2,pd,again);
  853. end
  854. else
  855. begin
  856. p2:=ccallnode.create(pprocsym(sym),srsymtable,p2);
  857. { support dispose(p,done()); }
  858. if try_to_consume(_LKLAMMER) then
  859. begin
  860. if not try_to_consume(_RKLAMMER) then
  861. begin
  862. Message(parser_e_no_paras_for_destructor);
  863. consume_all_until(_RKLAMMER);
  864. consume(_RKLAMMER);
  865. end;
  866. end;
  867. end;
  868. end;
  869. { we need the real called method }
  870. cleartempgen;
  871. do_firstpass(p2);
  872. if not codegenerror then
  873. begin
  874. if is_new then
  875. begin
  876. if (tcallnode(p2).procdefinition^.proctypeoption<>potype_constructor) then
  877. Message(parser_e_expr_have_to_be_constructor_call);
  878. p2:=cassignmentnode.create(p,cnewnode.create(p2));
  879. tassignmentnode(p2).right.resulttype:=pd2;
  880. end
  881. else
  882. begin
  883. if (tcallnode(p2).procdefinition^.proctypeoption<>potype_destructor) then
  884. Message(parser_e_expr_have_to_be_destructor_call);
  885. end;
  886. end;
  887. new_dispose_statement:=p2;
  888. end;
  889. end
  890. else
  891. begin
  892. if p.resulttype=nil then
  893. p.resulttype:=generrordef;
  894. if (p.resulttype^.deftype<>pointerdef) then
  895. Begin
  896. Message1(type_e_pointer_type_expected,p.resulttype^.typename);
  897. new_dispose_statement:=cerrornode.create;
  898. end
  899. else
  900. begin
  901. if (ppointerdef(p.resulttype)^.pointertype.def^.deftype=objectdef) and
  902. (oo_has_vmt in pobjectdef(ppointerdef(p.resulttype)^.pointertype.def)^.objectoptions) then
  903. Message(parser_w_use_extended_syntax_for_objects);
  904. if (ppointerdef(p.resulttype)^.pointertype.def^.deftype=orddef) and
  905. (porddef(ppointerdef(p.resulttype)^.pointertype.def)^.typ=uvoid) then
  906. begin
  907. if (m_tp in aktmodeswitches) or
  908. (m_delphi in aktmodeswitches) then
  909. Message(parser_w_no_new_dispose_on_void_pointers)
  910. else
  911. Message(parser_e_no_new_dispose_on_void_pointers);
  912. end;
  913. if is_new then
  914. new_dispose_statement:=csimplenewdisposenode.create(simplenewn,p)
  915. else
  916. new_dispose_statement:=csimplenewdisposenode.create(simpledisposen,p);
  917. end;
  918. end;
  919. consume(_RKLAMMER);
  920. end;
  921. function statement : tnode;
  922. var
  923. p : tnode;
  924. code : tnode;
  925. filepos : tfileposinfo;
  926. sr : plabelsym;
  927. label
  928. ready;
  929. begin
  930. filepos:=tokenpos;
  931. case token of
  932. _GOTO :
  933. begin
  934. if not(cs_support_goto in aktmoduleswitches)then
  935. Message(sym_e_goto_and_label_not_supported);
  936. consume(_GOTO);
  937. if (token<>_INTCONST) and (token<>_ID) then
  938. begin
  939. Message(sym_e_label_not_found);
  940. code:=cerrornode.create;
  941. end
  942. else
  943. begin
  944. getsym(pattern,true);
  945. consume(token);
  946. if srsym^.typ<>labelsym then
  947. begin
  948. Message(sym_e_id_is_no_label_id);
  949. code:=cerrornode.create;
  950. end
  951. else
  952. begin
  953. code:=cgotonode.create(plabelsym(srsym)^.lab);
  954. tgotonode(code).labsym:=plabelsym(srsym);
  955. { set flag that this label is used }
  956. plabelsym(srsym)^.used:=true;
  957. end;
  958. end;
  959. end;
  960. _BEGIN :
  961. code:=statement_block(_BEGIN);
  962. _IF :
  963. code:=if_statement;
  964. _CASE :
  965. code:=case_statement;
  966. _REPEAT :
  967. code:=repeat_statement;
  968. _WHILE :
  969. code:=while_statement;
  970. _FOR :
  971. code:=for_statement;
  972. _NEW,
  973. _DISPOSE :
  974. code:=new_dispose_statement;
  975. _WITH :
  976. code:=with_statement;
  977. _TRY :
  978. code:=try_statement;
  979. _RAISE :
  980. code:=raise_statement;
  981. { semicolons,else until and end are ignored }
  982. _SEMICOLON,
  983. _ELSE,
  984. _UNTIL,
  985. _END:
  986. code:=cnothingnode.create;
  987. _FAIL :
  988. begin
  989. if (aktprocsym^.definition^.proctypeoption<>potype_constructor) then
  990. Message(parser_e_fail_only_in_constructor);
  991. consume(_FAIL);
  992. code:=cfailnode.create;
  993. end;
  994. _EXIT :
  995. code:=exit_statement;
  996. _ASM :
  997. code:=_asm_statement;
  998. _EOF :
  999. Message(scan_f_end_of_file);
  1000. else
  1001. begin
  1002. if (token in [_INTCONST,_ID]) then
  1003. begin
  1004. getsym(pattern,true);
  1005. lastsymknown:=true;
  1006. lastsrsym:=srsym;
  1007. { it is NOT necessarily the owner
  1008. it can be a withsymtable !!! }
  1009. lastsrsymtable:=srsymtable;
  1010. if assigned(srsym) and (srsym^.typ=labelsym) then
  1011. begin
  1012. consume(token);
  1013. consume(_COLON);
  1014. { we must preserve srsym to set code later }
  1015. sr:=plabelsym(srsym);
  1016. if sr^.defined then
  1017. Message(sym_e_label_already_defined);
  1018. sr^.defined:=true;
  1019. { statement modifies srsym }
  1020. lastsymknown:=false;
  1021. { the pointer to the following instruction }
  1022. { isn't a very clean way }
  1023. code:=clabelnode.create(sr^.lab,statement{$ifdef FPCPROCVAR}(){$endif});
  1024. sr^.code:=code;
  1025. { sorry, but here is a jump the easiest way }
  1026. goto ready;
  1027. end;
  1028. end;
  1029. p:=expr;
  1030. if not(p.nodetype in [calln,assignn,breakn,inlinen,continuen]) then
  1031. Message(cg_e_illegal_expression);
  1032. { specify that we don't use the value returned by the call }
  1033. { Question : can this be also improtant
  1034. for inlinen ??
  1035. it is used for :
  1036. - dispose of temp stack space
  1037. - dispose on FPU stack }
  1038. if p.nodetype=calln then
  1039. exclude(p.flags,nf_return_value_used);
  1040. code:=p;
  1041. end;
  1042. end;
  1043. ready:
  1044. if assigned(code) then
  1045. code.set_tree_filepos(filepos);
  1046. statement:=code;
  1047. end;
  1048. function statement_block(starttoken : ttoken) : tnode;
  1049. var
  1050. first,last : tnode;
  1051. filepos : tfileposinfo;
  1052. begin
  1053. first:=nil;
  1054. filepos:=tokenpos;
  1055. consume(starttoken);
  1056. inc(statement_level);
  1057. while not(token in [_END,_FINALIZATION]) do
  1058. begin
  1059. if first=nil then
  1060. begin
  1061. last:=cstatementnode.create(nil,statement);
  1062. first:=last;
  1063. end
  1064. else
  1065. begin
  1066. tstatementnode(last).left:=cstatementnode.create(nil,statement);
  1067. last:=tstatementnode(last).left;
  1068. end;
  1069. if (token in [_END,_FINALIZATION]) then
  1070. break
  1071. else
  1072. begin
  1073. { if no semicolon, then error and go on }
  1074. if token<>_SEMICOLON then
  1075. begin
  1076. consume(_SEMICOLON);
  1077. consume_all_until(_SEMICOLON);
  1078. end;
  1079. consume(_SEMICOLON);
  1080. end;
  1081. emptystats;
  1082. end;
  1083. { don't consume the finalization token, it is consumed when
  1084. reading the finalization block, but allow it only after
  1085. an initalization ! }
  1086. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1087. consume(_END);
  1088. dec(statement_level);
  1089. last:=cblocknode.create(first);
  1090. last.set_tree_filepos(filepos);
  1091. statement_block:=last;
  1092. end;
  1093. function assembler_block : tnode;
  1094. begin
  1095. { temporary space is set, while the BEGIN of the procedure }
  1096. if symtablestack^.symtabletype=localsymtable then
  1097. procinfo^.firsttemp_offset := -symtablestack^.datasize
  1098. else
  1099. procinfo^.firsttemp_offset := 0;
  1100. { assembler code does not allocate }
  1101. { space for the return value }
  1102. if procinfo^.returntype.def<>pdef(voiddef) then
  1103. begin
  1104. if ret_in_acc(procinfo^.returntype.def) then
  1105. begin
  1106. { in assembler code the result should be directly in %eax
  1107. procinfo^.retoffset:=procinfo^.firsttemp-procinfo^.retdef^.size;
  1108. procinfo^.firsttemp:=procinfo^.retoffset; }
  1109. {$ifndef newcg}
  1110. {$ifdef i386}
  1111. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1112. {$endif}
  1113. {$ifdef m68k}
  1114. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1115. {$endif}
  1116. {$endif newcg}
  1117. end
  1118. {
  1119. else if not is_fpu(procinfo^.retdef) then
  1120. should we allow assembler functions of big elements ?
  1121. YES (FK)!!
  1122. Message(parser_e_asm_incomp_with_function_return);
  1123. }
  1124. end;
  1125. { set the framepointer to esp for assembler functions }
  1126. { but only if the are no local variables }
  1127. { added no parameter also (PM) }
  1128. { disable for methods, because self pointer is expected }
  1129. { at -8(%ebp) (JM) }
  1130. { why if se use %esp then self is still at the correct address PM }
  1131. if {not(assigned(procinfo^._class)) and}
  1132. (po_assembler in aktprocsym^.definition^.procoptions) and
  1133. (aktprocsym^.definition^.localst^.datasize=0) and
  1134. (aktprocsym^.definition^.parast^.datasize=0) and
  1135. not(ret_in_param(aktprocsym^.definition^.rettype.def)) then
  1136. begin
  1137. procinfo^.framepointer:=stack_pointer;
  1138. { set the right value for parameters }
  1139. dec(aktprocsym^.definition^.parast^.address_fixup,target_os.size_of_pointer);
  1140. dec(procinfo^.para_offset,target_os.size_of_pointer);
  1141. end;
  1142. { force the asm statement }
  1143. if token<>_ASM then
  1144. consume(_ASM);
  1145. procinfo^.Flags := procinfo^.Flags Or pi_is_assembler;
  1146. assembler_block:=_asm_statement;
  1147. { becuase the END is already read we need to get the
  1148. last_endtoken_filepos here (PFV) }
  1149. last_endtoken_filepos:=tokenpos;
  1150. end;
  1151. end.
  1152. {
  1153. $Log$
  1154. Revision 1.11 2000-10-14 21:52:56 peter
  1155. * fixed memory leaks
  1156. Revision 1.10 2000/10/14 10:14:52 peter
  1157. * moehrendorf oct 2000 rewrite
  1158. Revision 1.9 2000/10/01 19:48:25 peter
  1159. * lot of compile updates for cg11
  1160. Revision 1.8 2000/09/24 21:19:50 peter
  1161. * delphi compile fixes
  1162. Revision 1.7 2000/09/24 15:06:24 peter
  1163. * use defines.inc
  1164. Revision 1.6 2000/08/27 16:11:52 peter
  1165. * moved some util functions from globals,cobjects to cutils
  1166. * splitted files into finput,fmodule
  1167. Revision 1.5 2000/08/12 15:41:15 peter
  1168. * fixed bug 1096 (merged)
  1169. Revision 1.4 2000/08/12 06:46:06 florian
  1170. + case statement for int64/qword implemented
  1171. Revision 1.3 2000/07/13 12:08:27 michael
  1172. + patched to 1.1.0 with former 1.09patch from peter
  1173. Revision 1.2 2000/07/13 11:32:45 michael
  1174. + removed logs
  1175. }