pstatmnt.pas 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Does the parsing of the statements
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit pstatmnt;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. tokens,node;
  22. function statement_block(starttoken : ttoken) : tnode;
  23. { reads an assembler block }
  24. function assembler_block : tnode;
  25. implementation
  26. uses
  27. { common }
  28. cutils,cclasses,
  29. { global }
  30. globtype,globals,verbose,constexp,
  31. systems,
  32. { aasm }
  33. cpubase,aasmbase,aasmtai,aasmdata,
  34. { symtable }
  35. symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
  36. paramgr,symutil,
  37. { pass 1 }
  38. pass_1,htypechk,
  39. nutils,ngenutil,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  40. { parser }
  41. scanner,
  42. pbase,pexpr,
  43. { codegen }
  44. procinfo,cgbase,
  45. { assembler reader }
  46. rabase,
  47. { wide- and unicodestrings}
  48. widestr
  49. ;
  50. function statement : tnode;forward;
  51. function if_statement : tnode;
  52. var
  53. ex,if_a,else_a : tnode;
  54. begin
  55. consume(_IF);
  56. ex:=comp_expr(true,false);
  57. consume(_THEN);
  58. if token<>_ELSE then
  59. if_a:=statement
  60. else
  61. if_a:=nil;
  62. if try_to_consume(_ELSE) then
  63. else_a:=statement
  64. else
  65. else_a:=nil;
  66. result:=cifnode.create(ex,if_a,else_a);
  67. end;
  68. { creates a block (list) of statements, til the next END token }
  69. function statements_til_end : tnode;
  70. var
  71. first,last : tstatementnode;
  72. begin
  73. first:=nil;
  74. while token<>_END do
  75. begin
  76. if first=nil then
  77. begin
  78. last:=cstatementnode.create(statement,nil);
  79. first:=last;
  80. end
  81. else
  82. begin
  83. last.right:=cstatementnode.create(statement,nil);
  84. last:=tstatementnode(last.right);
  85. end;
  86. if not try_to_consume(_SEMICOLON) then
  87. break;
  88. consume_emptystats;
  89. end;
  90. consume(_END);
  91. statements_til_end:=cblocknode.create(first);
  92. end;
  93. function case_statement : tnode;
  94. var
  95. casedef : tdef;
  96. caseexpr,p : tnode;
  97. blockid : longint;
  98. hl1,hl2 : TConstExprInt;
  99. sl1,sl2 : tstringconstnode;
  100. casedeferror, caseofstring : boolean;
  101. casenode : tcasenode;
  102. begin
  103. consume(_CASE);
  104. caseexpr:=comp_expr(true,false);
  105. { determines result type }
  106. do_typecheckpass(caseexpr);
  107. { variants must be accepted, but first they must be converted to integer }
  108. if caseexpr.resultdef.typ=variantdef then
  109. begin
  110. caseexpr:=ctypeconvnode.create_internal(caseexpr,sinttype);
  111. do_typecheckpass(caseexpr);
  112. end;
  113. set_varstate(caseexpr,vs_read,[vsf_must_be_valid]);
  114. casedeferror:=false;
  115. casedef:=caseexpr.resultdef;
  116. { case of string must be rejected in delphi-, }
  117. { tp7/bp7-, mac-compatibility modes. }
  118. caseofstring :=
  119. ([m_delphi, m_mac, m_tp7] * current_settings.modeswitches = []) and
  120. is_string(casedef);
  121. if (not assigned(casedef)) or
  122. ( not(is_ordinal(casedef)) and (not caseofstring) ) then
  123. begin
  124. CGMessage(type_e_ordinal_or_string_expr_expected);
  125. { create a correct tree }
  126. caseexpr.free;
  127. caseexpr:=cordconstnode.create(0,u32inttype,false);
  128. { set error flag so no rangechecks are done }
  129. casedeferror:=true;
  130. end;
  131. { Create casenode }
  132. casenode:=ccasenode.create(caseexpr);
  133. consume(_OF);
  134. { Parse all case blocks }
  135. blockid:=0;
  136. repeat
  137. { maybe an instruction has more case labels }
  138. repeat
  139. p:=expr(true);
  140. if is_widechar(casedef) then
  141. begin
  142. if (p.nodetype=rangen) then
  143. begin
  144. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  145. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  146. do_typecheckpass(trangenode(p).left);
  147. do_typecheckpass(trangenode(p).right);
  148. end
  149. else
  150. begin
  151. p:=ctypeconvnode.create(p,cwidechartype);
  152. do_typecheckpass(p);
  153. end;
  154. end;
  155. hl1:=0;
  156. hl2:=0;
  157. sl1:=nil;
  158. sl2:=nil;
  159. if (p.nodetype=rangen) then
  160. begin
  161. { type check for string case statements }
  162. if caseofstring and
  163. is_conststring_or_constcharnode(trangenode(p).left) and
  164. is_conststring_or_constcharnode(trangenode(p).right) then
  165. begin
  166. { we need stringconstnodes, even if expression contains single chars }
  167. sl1 := get_string_value(trangenode(p).left, tstringdef(casedef));
  168. sl2 := get_string_value(trangenode(p).right, tstringdef(casedef));
  169. if sl1.fullcompare(sl2) > 0 then
  170. CGMessage(parser_e_case_lower_less_than_upper_bound);
  171. end
  172. { type checking for ordinal case statements }
  173. else if (not caseofstring) and
  174. is_subequal(casedef, trangenode(p).left.resultdef) and
  175. is_subequal(casedef, trangenode(p).right.resultdef) then
  176. begin
  177. hl1:=get_ordinal_value(trangenode(p).left);
  178. hl2:=get_ordinal_value(trangenode(p).right);
  179. if hl1>hl2 then
  180. CGMessage(parser_e_case_lower_less_than_upper_bound);
  181. if not casedeferror then
  182. begin
  183. testrange(casedef,hl1,false,false);
  184. testrange(casedef,hl2,false,false);
  185. end;
  186. end
  187. else
  188. CGMessage(parser_e_case_mismatch);
  189. if caseofstring then
  190. casenode.addlabel(blockid,sl1,sl2)
  191. else
  192. casenode.addlabel(blockid,hl1,hl2);
  193. end
  194. else
  195. begin
  196. { type check for string case statements }
  197. if (caseofstring and (not is_conststring_or_constcharnode(p))) or
  198. { type checking for ordinal case statements }
  199. ((not caseofstring) and (not is_subequal(casedef, p.resultdef))) then
  200. CGMessage(parser_e_case_mismatch);
  201. if caseofstring then
  202. begin
  203. sl1:=get_string_value(p, tstringdef(casedef));
  204. casenode.addlabel(blockid,sl1,sl1);
  205. end
  206. else
  207. begin
  208. hl1:=get_ordinal_value(p);
  209. if not casedeferror then
  210. testrange(casedef,hl1,false,false);
  211. casenode.addlabel(blockid,hl1,hl1);
  212. end;
  213. end;
  214. p.free;
  215. sl1.free;
  216. sl2.free;
  217. if token=_COMMA then
  218. consume(_COMMA)
  219. else
  220. break;
  221. until false;
  222. consume(_COLON);
  223. { add instruction block }
  224. casenode.addblock(blockid,statement);
  225. { next block }
  226. inc(blockid);
  227. if not(token in [_ELSE,_OTHERWISE,_END]) then
  228. consume(_SEMICOLON);
  229. until (token in [_ELSE,_OTHERWISE,_END]);
  230. if (token in [_ELSE,_OTHERWISE]) then
  231. begin
  232. if not try_to_consume(_ELSE) then
  233. consume(_OTHERWISE);
  234. casenode.addelseblock(statements_til_end);
  235. end
  236. else
  237. consume(_END);
  238. result:=casenode;
  239. end;
  240. function repeat_statement : tnode;
  241. var
  242. first,last,p_e : tnode;
  243. begin
  244. consume(_REPEAT);
  245. first:=nil;
  246. while token<>_UNTIL do
  247. begin
  248. if first=nil then
  249. begin
  250. last:=cstatementnode.create(statement,nil);
  251. first:=last;
  252. end
  253. else
  254. begin
  255. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  256. last:=tstatementnode(last).right;
  257. end;
  258. if not try_to_consume(_SEMICOLON) then
  259. break;
  260. consume_emptystats;
  261. end;
  262. consume(_UNTIL);
  263. first:=cblocknode.create(first);
  264. p_e:=comp_expr(true,false);
  265. result:=cwhilerepeatnode.create(p_e,first,false,true);
  266. end;
  267. function while_statement : tnode;
  268. var
  269. p_e,p_a : tnode;
  270. begin
  271. consume(_WHILE);
  272. p_e:=comp_expr(true,false);
  273. consume(_DO);
  274. p_a:=statement;
  275. result:=cwhilerepeatnode.create(p_e,p_a,true,false);
  276. end;
  277. function for_statement : tnode;
  278. procedure check_range(hp:tnode; fordef: tdef);
  279. begin
  280. if (hp.nodetype=ordconstn) and
  281. (fordef.typ<>errordef) then
  282. testrange(fordef,tordconstnode(hp).value,false,true);
  283. end;
  284. function for_loop_create(hloopvar: tnode): tnode;
  285. var
  286. hp,
  287. hblock,
  288. hto,hfrom : tnode;
  289. backward : boolean;
  290. loopvarsym : tabstractvarsym;
  291. begin
  292. { Check loop variable }
  293. loopvarsym:=nil;
  294. { variable must be an ordinal, int64 is not allowed for 32bit targets }
  295. if not(is_ordinal(hloopvar.resultdef))
  296. {$ifndef cpu64bitaddr}
  297. or is_64bitint(hloopvar.resultdef)
  298. {$endif not cpu64bitaddr}
  299. then
  300. MessagePos(hloopvar.fileinfo,type_e_ordinal_expr_expected);
  301. hp:=hloopvar;
  302. while assigned(hp) and
  303. (
  304. { record/object fields and array elements are allowed }
  305. { in tp7 mode only }
  306. (
  307. (m_tp7 in current_settings.modeswitches) and
  308. (
  309. ((hp.nodetype=subscriptn) and
  310. ((tsubscriptnode(hp).left.resultdef.typ=recorddef) or
  311. is_object(tsubscriptnode(hp).left.resultdef))
  312. ) or
  313. { constant array index }
  314. (
  315. (hp.nodetype=vecn) and
  316. is_constintnode(tvecnode(hp).right)
  317. )
  318. )
  319. ) or
  320. { equal typeconversions }
  321. (
  322. (hp.nodetype=typeconvn) and
  323. (ttypeconvnode(hp).convtype=tc_equal)
  324. )
  325. ) do
  326. begin
  327. { Use the recordfield for loopvarsym }
  328. if not assigned(loopvarsym) and
  329. (hp.nodetype=subscriptn) then
  330. loopvarsym:=tsubscriptnode(hp).vs;
  331. hp:=tunarynode(hp).left;
  332. end;
  333. if assigned(hp) and
  334. (hp.nodetype=loadn) then
  335. begin
  336. case tloadnode(hp).symtableentry.typ of
  337. staticvarsym,
  338. localvarsym,
  339. paravarsym :
  340. begin
  341. { we need a simple loadn:
  342. 1. The load must be in a global symtable or
  343. in the same level as the para of the current proc.
  344. 2. value variables (no const,out or var)
  345. 3. No threadvar, readonly or typedconst
  346. }
  347. if (
  348. (tloadnode(hp).symtable.symtablelevel=main_program_level) or
  349. (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
  350. ) and
  351. (tabstractvarsym(tloadnode(hp).symtableentry).varspez=vs_value) and
  352. ([vo_is_thread_var,vo_is_typed_const] * tabstractvarsym(tloadnode(hp).symtableentry).varoptions=[]) then
  353. begin
  354. { Assigning for-loop variable is only allowed in tp7 and macpas }
  355. if ([m_tp7,m_mac] * current_settings.modeswitches = []) then
  356. begin
  357. if not assigned(loopvarsym) then
  358. loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
  359. include(loopvarsym.varoptions,vo_is_loop_counter);
  360. end;
  361. end
  362. else
  363. begin
  364. { Typed const is allowed in tp7 }
  365. if not(m_tp7 in current_settings.modeswitches) or
  366. not(vo_is_typed_const in tabstractvarsym(tloadnode(hp).symtableentry).varoptions) then
  367. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  368. end;
  369. end;
  370. else
  371. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  372. end;
  373. end
  374. else
  375. MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
  376. hfrom:=comp_expr(true,false);
  377. if try_to_consume(_DOWNTO) then
  378. backward:=true
  379. else
  380. begin
  381. consume(_TO);
  382. backward:=false;
  383. end;
  384. hto:=comp_expr(true,false);
  385. consume(_DO);
  386. { Check if the constants fit in the range }
  387. check_range(hfrom,hloopvar.resultdef);
  388. check_range(hto,hloopvar.resultdef);
  389. { first set the varstate for from and to, so
  390. uses of loopvar in those expressions will also
  391. trigger a warning when it is not used yet. This
  392. needs to be done before the instruction block is
  393. parsed to have a valid hloopvar }
  394. typecheckpass(hfrom);
  395. set_varstate(hfrom,vs_read,[vsf_must_be_valid]);
  396. typecheckpass(hto);
  397. set_varstate(hto,vs_read,[vsf_must_be_valid]);
  398. typecheckpass(hloopvar);
  399. { in two steps, because vs_readwritten may turn on vsf_must_be_valid }
  400. { for some subnodes }
  401. set_varstate(hloopvar,vs_written,[]);
  402. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  403. { ... now the instruction block }
  404. hblock:=statement;
  405. { variable is not used for loop counter anymore }
  406. if assigned(loopvarsym) then
  407. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  408. result:=cfornode.create(hloopvar,hfrom,hto,hblock,backward);
  409. end;
  410. function for_in_loop_create(hloopvar: tnode): tnode;
  411. var
  412. expr: tnode;
  413. begin
  414. expr:=comp_expr(true,false);
  415. consume(_DO);
  416. set_varstate(hloopvar,vs_written,[]);
  417. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  418. result:=create_for_in_loop(hloopvar,statement,expr);
  419. expr.free;
  420. end;
  421. var
  422. hloopvar: tnode;
  423. begin
  424. { parse loop header }
  425. consume(_FOR);
  426. hloopvar:=factor(false,false);
  427. valid_for_loopvar(hloopvar,true);
  428. if try_to_consume(_ASSIGNMENT) then
  429. result:=for_loop_create(hloopvar)
  430. else if try_to_consume(_IN) then
  431. result:=for_in_loop_create(hloopvar)
  432. else
  433. consume(_ASSIGNMENT); // fail
  434. end;
  435. function _with_statement : tnode;
  436. var
  437. p : tnode;
  438. i : longint;
  439. st : TSymtable;
  440. newblock : tblocknode;
  441. newstatement : tstatementnode;
  442. calltempnode,
  443. tempnode : ttempcreatenode;
  444. valuenode,
  445. hp,
  446. refnode : tnode;
  447. hdef : tdef;
  448. extendeddef : tabstractrecorddef;
  449. helperdef : tobjectdef;
  450. hasimplicitderef : boolean;
  451. withsymtablelist : TFPObjectList;
  452. procedure pushobjchild(withdef,obj:tobjectdef);
  453. var
  454. parenthelperdef : tobjectdef;
  455. begin
  456. if not assigned(obj) then
  457. exit;
  458. pushobjchild(withdef,obj.childof);
  459. { we need to look for helpers that were defined for the parent
  460. class as well }
  461. search_last_objectpascal_helper(obj,current_structdef,parenthelperdef);
  462. { push the symtables of the helper's parents in reverse order }
  463. if assigned(parenthelperdef) then
  464. pushobjchild(withdef,parenthelperdef.childof);
  465. { keep the original tobjectdef as owner, because that is used for
  466. visibility of the symtable }
  467. st:=twithsymtable.create(withdef,obj.symtable.SymList,refnode.getcopy);
  468. symtablestack.push(st);
  469. withsymtablelist.add(st);
  470. { push the symtable of the helper }
  471. if assigned(parenthelperdef) then
  472. begin
  473. st:=twithsymtable.create(withdef,parenthelperdef.symtable.SymList,refnode.getcopy);
  474. symtablestack.push(st);
  475. withsymtablelist.add(st);
  476. end;
  477. end;
  478. begin
  479. p:=comp_expr(true,false);
  480. do_typecheckpass(p);
  481. if (p.nodetype=vecn) and
  482. (nf_memseg in p.flags) then
  483. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  484. { "with procvar" can never mean anything, so always try
  485. to call it in case it returns a record/object/... }
  486. maybe_call_procvar(p,false);
  487. if (p.resultdef.typ in [objectdef,recorddef,classrefdef]) then
  488. begin
  489. newblock:=nil;
  490. valuenode:=nil;
  491. tempnode:=nil;
  492. { ignore nodes that don't add instructions in the tree }
  493. hp:=p;
  494. while { equal type conversions }
  495. (
  496. (hp.nodetype=typeconvn) and
  497. (ttypeconvnode(hp).convtype=tc_equal)
  498. ) or
  499. { constant array index }
  500. (
  501. (hp.nodetype=vecn) and
  502. (tvecnode(hp).right.nodetype=ordconstn)
  503. ) do
  504. hp:=tunarynode(hp).left;
  505. if (hp.nodetype=loadn) and
  506. (
  507. (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
  508. (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
  509. (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
  510. ) and
  511. { MacPas objects are mapped to classes, and the MacPas compilers
  512. interpret with-statements with MacPas objects the same way
  513. as records (the object referenced by the with-statement
  514. must remain constant)
  515. }
  516. not(is_class(hp.resultdef) and
  517. (m_mac in current_settings.modeswitches)) then
  518. begin
  519. { simple load, we can reference direct }
  520. refnode:=p;
  521. end
  522. else
  523. begin
  524. calltempnode:=nil;
  525. { complex load, load in temp first }
  526. newblock:=internalstatements(newstatement);
  527. { when we can't take the address of p, load it in a temp }
  528. { since we may need its address later on }
  529. if not valid_for_addr(p,false) then
  530. begin
  531. calltempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent,true);
  532. addstatement(newstatement,calltempnode);
  533. addstatement(newstatement,cassignmentnode.create(
  534. ctemprefnode.create(calltempnode),
  535. p));
  536. p:=ctemprefnode.create(calltempnode);
  537. typecheckpass(p);
  538. end;
  539. { several object types have implicit dereferencing }
  540. hasimplicitderef:=is_implicit_pointer_object_type(p.resultdef) or
  541. (p.resultdef.typ = classrefdef);
  542. if hasimplicitderef then
  543. hdef:=p.resultdef
  544. else
  545. hdef:=tpointerdef.create(p.resultdef);
  546. { load address of the value in a temp }
  547. tempnode:=ctempcreatenode.create_withnode(hdef,sizeof(pint),tt_persistent,true,p);
  548. typecheckpass(tnode(tempnode));
  549. valuenode:=p;
  550. refnode:=ctemprefnode.create(tempnode);
  551. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  552. { add address call for valuenode and deref for refnode if this
  553. is not done implicitly }
  554. if not hasimplicitderef then
  555. begin
  556. valuenode:=caddrnode.create_internal_nomark(valuenode);
  557. include(valuenode.flags,nf_typedaddr);
  558. refnode:=cderefnode.create(refnode);
  559. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  560. end;
  561. addstatement(newstatement,tempnode);
  562. addstatement(newstatement,cassignmentnode.create(
  563. ctemprefnode.create(tempnode),
  564. valuenode));
  565. typecheckpass(refnode);
  566. end;
  567. { do we have a helper for this type? }
  568. if p.resultdef.typ=classrefdef then
  569. extendeddef:=tobjectdef(tclassrefdef(p.resultdef).pointeddef)
  570. else
  571. extendeddef:=tabstractrecorddef(p.resultdef);
  572. search_last_objectpascal_helper(extendeddef,current_structdef,helperdef);
  573. { Note: the symtable of the helper is pushed after the following
  574. "case", the symtables of the helper's parents are passed in
  575. the "case" branches }
  576. withsymtablelist:=TFPObjectList.create(true);
  577. case p.resultdef.typ of
  578. objectdef :
  579. begin
  580. { push symtables of all parents in reverse order }
  581. pushobjchild(tobjectdef(p.resultdef),tobjectdef(p.resultdef).childof);
  582. { push symtables of all parents of the helper in reverse order }
  583. if assigned(helperdef) then
  584. pushobjchild(helperdef,helperdef.childof);
  585. { push object symtable }
  586. st:=twithsymtable.Create(tobjectdef(p.resultdef),tobjectdef(p.resultdef).symtable.SymList,refnode);
  587. symtablestack.push(st);
  588. withsymtablelist.add(st);
  589. end;
  590. classrefdef :
  591. begin
  592. { push symtables of all parents in reverse order }
  593. pushobjchild(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).childof);
  594. { push symtables of all parents of the helper in reverse order }
  595. if assigned(helperdef) then
  596. pushobjchild(helperdef,helperdef.childof);
  597. { push object symtable }
  598. st:=twithsymtable.Create(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).symtable.SymList,refnode);
  599. symtablestack.push(st);
  600. withsymtablelist.add(st);
  601. end;
  602. recorddef :
  603. begin
  604. { push symtables of all parents of the helper in reverse order }
  605. if assigned(helperdef) then
  606. pushobjchild(helperdef,helperdef.childof);
  607. { push record symtable }
  608. st:=twithsymtable.create(trecorddef(p.resultdef),trecorddef(p.resultdef).symtable.SymList,refnode);
  609. symtablestack.push(st);
  610. withsymtablelist.add(st);
  611. end;
  612. else
  613. internalerror(200601271);
  614. end;
  615. { push helper symtable }
  616. if assigned(helperdef) then
  617. begin
  618. st:=twithsymtable.Create(helperdef,helperdef.symtable.SymList,refnode.getcopy);
  619. symtablestack.push(st);
  620. withsymtablelist.add(st);
  621. end;
  622. if try_to_consume(_COMMA) then
  623. p:=_with_statement()
  624. else
  625. begin
  626. consume(_DO);
  627. if token<>_SEMICOLON then
  628. p:=statement
  629. else
  630. p:=cnothingnode.create;
  631. end;
  632. { remove symtables in reverse order from the stack }
  633. for i:=withsymtablelist.count-1 downto 0 do
  634. symtablestack.pop(TSymtable(withsymtablelist[i]));
  635. withsymtablelist.free;
  636. // p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refnode);
  637. { Finalize complex withnode with destroy of temp }
  638. if assigned(newblock) then
  639. begin
  640. addstatement(newstatement,p);
  641. if assigned(tempnode) then
  642. addstatement(newstatement,ctempdeletenode.create(tempnode));
  643. if assigned(calltempnode) then
  644. addstatement(newstatement,ctempdeletenode.create(calltempnode));
  645. p:=newblock;
  646. end;
  647. result:=p;
  648. end
  649. else
  650. begin
  651. p.free;
  652. Message(parser_e_false_with_expr);
  653. { try to recover from error }
  654. if try_to_consume(_COMMA) then
  655. begin
  656. hp:=_with_statement();
  657. if (hp=nil) then; { remove warning about unused }
  658. end
  659. else
  660. begin
  661. consume(_DO);
  662. { ignore all }
  663. if token<>_SEMICOLON then
  664. statement;
  665. end;
  666. result:=nil;
  667. end;
  668. end;
  669. function with_statement : tnode;
  670. begin
  671. consume(_WITH);
  672. with_statement:=_with_statement();
  673. end;
  674. function raise_statement : tnode;
  675. var
  676. p,pobj,paddr,pframe : tnode;
  677. begin
  678. pobj:=nil;
  679. paddr:=nil;
  680. pframe:=nil;
  681. consume(_RAISE);
  682. if not(token in endtokens) then
  683. begin
  684. { object }
  685. pobj:=comp_expr(true,false);
  686. if try_to_consume(_AT) then
  687. begin
  688. paddr:=comp_expr(true,false);
  689. if try_to_consume(_COMMA) then
  690. pframe:=comp_expr(true,false);
  691. end;
  692. end
  693. else
  694. begin
  695. if (block_type<>bt_except) then
  696. Message(parser_e_no_reraise_possible);
  697. end;
  698. p:=craisenode.create(pobj,paddr,pframe);
  699. raise_statement:=p;
  700. end;
  701. function try_statement : tnode;
  702. var
  703. p_try_block,p_finally_block,first,last,
  704. p_default,p_specific,hp : tnode;
  705. ot : tDef;
  706. sym : tlocalvarsym;
  707. old_block_type : tblock_type;
  708. excepTSymtable : TSymtable;
  709. objname,objrealname : TIDString;
  710. srsym : tsym;
  711. srsymtable : TSymtable;
  712. oldcurrent_exceptblock: integer;
  713. begin
  714. include(current_procinfo.flags,pi_uses_exceptions);
  715. p_default:=nil;
  716. p_specific:=nil;
  717. { read statements to try }
  718. consume(_TRY);
  719. first:=nil;
  720. inc(exceptblockcounter);
  721. oldcurrent_exceptblock := current_exceptblock;
  722. current_exceptblock := exceptblockcounter;
  723. while (token<>_FINALLY) and (token<>_EXCEPT) do
  724. begin
  725. if first=nil then
  726. begin
  727. last:=cstatementnode.create(statement,nil);
  728. first:=last;
  729. end
  730. else
  731. begin
  732. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  733. last:=tstatementnode(last).right;
  734. end;
  735. if not try_to_consume(_SEMICOLON) then
  736. break;
  737. consume_emptystats;
  738. end;
  739. p_try_block:=cblocknode.create(first);
  740. if try_to_consume(_FINALLY) then
  741. begin
  742. inc(exceptblockcounter);
  743. current_exceptblock := exceptblockcounter;
  744. p_finally_block:=statements_til_end;
  745. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  746. end
  747. else
  748. begin
  749. consume(_EXCEPT);
  750. old_block_type:=block_type;
  751. block_type:=bt_except;
  752. inc(exceptblockcounter);
  753. current_exceptblock := exceptblockcounter;
  754. ot:=generrordef;
  755. p_specific:=nil;
  756. if (idtoken=_ON) then
  757. { catch specific exceptions }
  758. begin
  759. repeat
  760. consume(_ON);
  761. if token=_ID then
  762. begin
  763. objname:=pattern;
  764. objrealname:=orgpattern;
  765. { can't use consume_sym here, because we need already
  766. to check for the colon }
  767. searchsym(objname,srsym,srsymtable);
  768. consume(_ID);
  769. { is a explicit name for the exception given ? }
  770. if try_to_consume(_COLON) then
  771. begin
  772. consume_sym(srsym,srsymtable);
  773. if (srsym.typ=typesym) and
  774. (is_class(ttypesym(srsym).typedef) or
  775. is_javaclass(ttypesym(srsym).typedef)) then
  776. begin
  777. ot:=ttypesym(srsym).typedef;
  778. sym:=tlocalvarsym.create(objrealname,vs_value,ot,[]);
  779. end
  780. else
  781. begin
  782. sym:=tlocalvarsym.create(objrealname,vs_value,generrordef,[]);
  783. if (srsym.typ=typesym) then
  784. Message1(type_e_class_type_expected,ttypesym(srsym).typedef.typename)
  785. else
  786. Message1(type_e_class_type_expected,ot.typename);
  787. end;
  788. end
  789. else
  790. begin
  791. { check if type is valid, must be done here because
  792. with "e: Exception" the e is not necessary }
  793. if srsym=nil then
  794. begin
  795. identifier_not_found(objrealname);
  796. srsym:=generrorsym;
  797. end;
  798. { support unit.identifier }
  799. if srsym.typ=unitsym then
  800. begin
  801. consume(_POINT);
  802. searchsym_in_module(tunitsym(srsym).module,pattern,srsym,srsymtable);
  803. if srsym=nil then
  804. begin
  805. identifier_not_found(orgpattern);
  806. srsym:=generrorsym;
  807. end;
  808. consume(_ID);
  809. end;
  810. { check if type is valid, must be done here because
  811. with "e: Exception" the e is not necessary }
  812. if (srsym.typ=typesym) and
  813. (is_class(ttypesym(srsym).typedef) or
  814. is_javaclass(ttypesym(srsym).typedef)) then
  815. ot:=ttypesym(srsym).typedef
  816. else
  817. begin
  818. ot:=generrordef;
  819. if (srsym.typ=typesym) then
  820. Message1(type_e_class_type_expected,ttypesym(srsym).typedef.typename)
  821. else
  822. Message1(type_e_class_type_expected,ot.typename);
  823. end;
  824. { create dummy symbol so we don't need a special
  825. case in ncgflw, and so that we always know the
  826. type }
  827. sym:=tlocalvarsym.create('$exceptsym',vs_value,ot,[]);
  828. end;
  829. excepTSymtable:=tstt_excepTSymtable.create;
  830. excepTSymtable.insert(sym);
  831. symtablestack.push(excepTSymtable);
  832. end
  833. else
  834. consume(_ID);
  835. consume(_DO);
  836. hp:=connode.create(nil,statement);
  837. if ot.typ=errordef then
  838. begin
  839. hp.free;
  840. hp:=cerrornode.create;
  841. end;
  842. if p_specific=nil then
  843. begin
  844. last:=hp;
  845. p_specific:=last;
  846. end
  847. else
  848. begin
  849. tonnode(last).left:=hp;
  850. last:=tonnode(last).left;
  851. end;
  852. { set the informations }
  853. { only if the creation of the onnode was succesful, it's possible }
  854. { that last and hp are errornodes (JM) }
  855. if last.nodetype = onn then
  856. begin
  857. tonnode(last).excepttype:=tobjectdef(ot);
  858. tonnode(last).excepTSymtable:=excepTSymtable;
  859. end;
  860. { remove exception symtable }
  861. if assigned(excepTSymtable) then
  862. begin
  863. symtablestack.pop(excepTSymtable);
  864. if last.nodetype <> onn then
  865. excepTSymtable.free;
  866. end;
  867. if not try_to_consume(_SEMICOLON) then
  868. break;
  869. consume_emptystats;
  870. until (token in [_END,_ELSE]);
  871. if try_to_consume(_ELSE) then
  872. begin
  873. { catch the other exceptions }
  874. p_default:=statements_til_end;
  875. end
  876. else
  877. consume(_END);
  878. end
  879. else
  880. begin
  881. { catch all exceptions }
  882. p_default:=statements_til_end;
  883. end;
  884. block_type:=old_block_type;
  885. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  886. end;
  887. current_exceptblock := oldcurrent_exceptblock;
  888. end;
  889. function _asm_statement : tnode;
  890. var
  891. asmstat : tasmnode;
  892. Marker : tai;
  893. reg : tregister;
  894. asmreader : tbaseasmreader;
  895. begin
  896. Inside_asm_statement:=true;
  897. if assigned(asmmodeinfos[current_settings.asmmode]) then
  898. begin
  899. asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
  900. asmstat:=casmnode.create(asmreader.assemble as TAsmList);
  901. asmreader.free;
  902. end
  903. else
  904. Message(parser_f_assembler_reader_not_supported);
  905. { Mark procedure that it has assembler blocks }
  906. include(current_procinfo.flags,pi_has_assembler_block);
  907. { Read first the _ASM statement }
  908. consume(_ASM);
  909. { END is read, got a list of changed registers? }
  910. if try_to_consume(_LECKKLAMMER) then
  911. begin
  912. {$ifdef cpunofpu}
  913. asmstat.used_regs_fpu:=[0..first_int_imreg-1];
  914. {$else cpunofpu}
  915. asmstat.used_regs_fpu:=[0..first_fpu_imreg-1];
  916. {$endif cpunofpu}
  917. if token<>_RECKKLAMMER then
  918. begin
  919. if po_assembler in current_procinfo.procdef.procoptions then
  920. Message(parser_w_register_list_ignored);
  921. repeat
  922. { it's possible to specify the modified registers }
  923. reg:=std_regnum_search(lower(cstringpattern));
  924. if reg<>NR_NO then
  925. begin
  926. if (getregtype(reg)=R_INTREGISTER) and not(po_assembler in current_procinfo.procdef.procoptions) then
  927. include(asmstat.used_regs_int,getsupreg(reg));
  928. end
  929. else
  930. Message(asmr_e_invalid_register);
  931. consume(_CSTRING);
  932. if not try_to_consume(_COMMA) then
  933. break;
  934. until false;
  935. end;
  936. consume(_RECKKLAMMER);
  937. end
  938. else
  939. begin
  940. asmstat.used_regs_int:=paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
  941. asmstat.used_regs_fpu:=paramanager.get_volatile_registers_fpu(current_procinfo.procdef.proccalloption);
  942. end;
  943. { mark the start and the end of the assembler block
  944. this is needed for the optimizer }
  945. If Assigned(AsmStat.p_asm) Then
  946. Begin
  947. Marker := Tai_Marker.Create(mark_AsmBlockStart);
  948. AsmStat.p_asm.Insert(Marker);
  949. Marker := Tai_Marker.Create(mark_AsmBlockEnd);
  950. AsmStat.p_asm.Concat(Marker);
  951. End;
  952. Inside_asm_statement:=false;
  953. _asm_statement:=asmstat;
  954. end;
  955. function statement : tnode;
  956. var
  957. p,
  958. code : tnode;
  959. filepos : tfileposinfo;
  960. srsym : tsym;
  961. srsymtable : TSymtable;
  962. s : TIDString;
  963. begin
  964. filepos:=current_tokenpos;
  965. case token of
  966. _GOTO :
  967. begin
  968. if not(cs_support_goto in current_settings.moduleswitches) then
  969. Message(sym_e_goto_and_label_not_supported);
  970. consume(_GOTO);
  971. if (token<>_INTCONST) and (token<>_ID) then
  972. begin
  973. Message(sym_e_label_not_found);
  974. code:=cerrornode.create;
  975. end
  976. else
  977. begin
  978. if token=_ID then
  979. consume_sym(srsym,srsymtable)
  980. else
  981. begin
  982. if token<>_INTCONST then
  983. internalerror(201008021);
  984. { strip leading 0's in iso mode }
  985. if m_iso in current_settings.modeswitches then
  986. while pattern[1]='0' do
  987. delete(pattern,1,1);
  988. searchsym(pattern,srsym,srsymtable);
  989. if srsym=nil then
  990. begin
  991. identifier_not_found(pattern);
  992. srsym:=generrorsym;
  993. srsymtable:=nil;
  994. end;
  995. consume(token);
  996. end;
  997. if srsym.typ<>labelsym then
  998. begin
  999. Message(sym_e_id_is_no_label_id);
  1000. code:=cerrornode.create;
  1001. end
  1002. else
  1003. begin
  1004. { goto outside the current scope? }
  1005. if srsym.owner<>current_procinfo.procdef.localst then
  1006. begin
  1007. { allowed? }
  1008. if not(m_non_local_goto in current_settings.modeswitches) then
  1009. Message(parser_e_goto_outside_proc);
  1010. end;
  1011. code:=cgotonode.create(tlabelsym(srsym));
  1012. tgotonode(code).labelsym:=tlabelsym(srsym);
  1013. { set flag that this label is used }
  1014. tlabelsym(srsym).used:=true;
  1015. end;
  1016. end;
  1017. end;
  1018. _BEGIN :
  1019. code:=statement_block(_BEGIN);
  1020. _IF :
  1021. code:=if_statement;
  1022. _CASE :
  1023. code:=case_statement;
  1024. _REPEAT :
  1025. code:=repeat_statement;
  1026. _WHILE :
  1027. code:=while_statement;
  1028. _FOR :
  1029. code:=for_statement;
  1030. _WITH :
  1031. code:=with_statement;
  1032. _TRY :
  1033. code:=try_statement;
  1034. _RAISE :
  1035. code:=raise_statement;
  1036. { semicolons,else until and end are ignored }
  1037. _SEMICOLON,
  1038. _ELSE,
  1039. _UNTIL,
  1040. _END:
  1041. code:=cnothingnode.create;
  1042. _FAIL :
  1043. begin
  1044. if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  1045. Message(parser_e_fail_only_in_constructor);
  1046. consume(_FAIL);
  1047. code:=cnodeutils.call_fail_node;
  1048. end;
  1049. _ASM :
  1050. code:=_asm_statement;
  1051. _EOF :
  1052. Message(scan_f_end_of_file);
  1053. else
  1054. begin
  1055. { don't typecheck yet, because that will also simplify, which may
  1056. result in not detecting certain kinds of syntax errors --
  1057. see mantis #15594 }
  1058. p:=expr(false);
  1059. { save the pattern here for latter usage, the label could be "000",
  1060. even if we read an expression, the pattern is still valid if it's really
  1061. a label (FK)
  1062. if you want to mess here, take care of
  1063. tests/webtbs/tw3546.pp
  1064. }
  1065. s:=pattern;
  1066. { When a colon follows a intconst then transform it into a label }
  1067. if (p.nodetype=ordconstn) and
  1068. try_to_consume(_COLON) then
  1069. begin
  1070. { in iso mode, 0003: is equal to 3: }
  1071. if m_iso in current_settings.modeswitches then
  1072. searchsym(tostr(tordconstnode(p).value),srsym,srsymtable)
  1073. else
  1074. searchsym(s,srsym,srsymtable);
  1075. p.free;
  1076. if assigned(srsym) and
  1077. (srsym.typ=labelsym) then
  1078. begin
  1079. if tlabelsym(srsym).defined then
  1080. Message(sym_e_label_already_defined);
  1081. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1082. begin
  1083. tlabelsym(srsym).nonlocal:=true;
  1084. exclude(current_procinfo.procdef.procoptions,po_inline);
  1085. end;
  1086. if tlabelsym(srsym).nonlocal and
  1087. (current_procinfo.procdef.proctypeoption in [potype_unitinit,potype_unitfinalize]) then
  1088. Message(sym_e_interprocgoto_into_init_final_code_not_allowed);
  1089. tlabelsym(srsym).defined:=true;
  1090. p:=clabelnode.create(nil,tlabelsym(srsym));
  1091. tlabelsym(srsym).code:=p;
  1092. end
  1093. else
  1094. begin
  1095. Message1(sym_e_label_used_and_not_defined,s);
  1096. p:=cnothingnode.create;
  1097. end;
  1098. end;
  1099. if p.nodetype=labeln then
  1100. begin
  1101. { the pointer to the following instruction }
  1102. { isn't a very clean way }
  1103. if token in endtokens then
  1104. tlabelnode(p).left:=cnothingnode.create
  1105. else
  1106. tlabelnode(p).left:=statement();
  1107. { be sure to have left also typecheckpass }
  1108. typecheckpass(tlabelnode(p).left);
  1109. end
  1110. else
  1111. { change a load of a procvar to a call. this is also
  1112. supported in fpc mode }
  1113. if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
  1114. maybe_call_procvar(p,false);
  1115. { blockn support because a read/write is changed into a blocknode }
  1116. { with a separate statement for each read/write operation (JM) }
  1117. { the same is true for val() if the third parameter is not 32 bit }
  1118. if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
  1119. continuen,labeln,blockn,exitn]) or
  1120. ((p.nodetype=inlinen) and
  1121. not is_void(p.resultdef)) or
  1122. ((p.nodetype=calln) and
  1123. (assigned(tcallnode(p).procdefinition)) and
  1124. (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
  1125. Message(parser_e_illegal_expression);
  1126. if not assigned(p.resultdef) then
  1127. do_typecheckpass(p);
  1128. { Specify that we don't use the value returned by the call.
  1129. This is used for :
  1130. - dispose of temp stack space
  1131. - dispose on FPU stack
  1132. - extended syntax checking }
  1133. if (p.nodetype=calln) then
  1134. begin
  1135. exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
  1136. { in $x- state, the function result must not be ignored }
  1137. if not(cs_extsyntax in current_settings.moduleswitches) and
  1138. not(is_void(p.resultdef)) and
  1139. { can be nil in case there was an error in the expression }
  1140. assigned(tcallnode(p).procdefinition) and
  1141. not((tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
  1142. is_object(tprocdef(tcallnode(p).procdefinition).struct)) then
  1143. Message(parser_e_illegal_expression);
  1144. end;
  1145. code:=p;
  1146. end;
  1147. end;
  1148. if assigned(code) then
  1149. begin
  1150. typecheckpass(code);
  1151. code.fileinfo:=filepos;
  1152. end;
  1153. statement:=code;
  1154. end;
  1155. function statement_block(starttoken : ttoken) : tnode;
  1156. var
  1157. first,last : tnode;
  1158. filepos : tfileposinfo;
  1159. begin
  1160. first:=nil;
  1161. filepos:=current_tokenpos;
  1162. consume(starttoken);
  1163. while not(token in [_END,_FINALIZATION]) do
  1164. begin
  1165. if first=nil then
  1166. begin
  1167. last:=cstatementnode.create(statement,nil);
  1168. first:=last;
  1169. end
  1170. else
  1171. begin
  1172. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  1173. last:=tstatementnode(last).right;
  1174. end;
  1175. if (token in [_END,_FINALIZATION]) then
  1176. break
  1177. else
  1178. begin
  1179. { if no semicolon, then error and go on }
  1180. if token<>_SEMICOLON then
  1181. begin
  1182. consume(_SEMICOLON);
  1183. consume_all_until(_SEMICOLON);
  1184. end;
  1185. consume(_SEMICOLON);
  1186. end;
  1187. consume_emptystats;
  1188. end;
  1189. { don't consume the finalization token, it is consumed when
  1190. reading the finalization block, but allow it only after
  1191. an initalization ! }
  1192. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1193. consume(_END);
  1194. last:=cblocknode.create(first);
  1195. last.fileinfo:=filepos;
  1196. statement_block:=last;
  1197. end;
  1198. function assembler_block : tnode;
  1199. var
  1200. p : tnode;
  1201. {$ifndef arm}
  1202. locals : longint;
  1203. {$endif arm}
  1204. srsym : tsym;
  1205. begin
  1206. { Rename the funcret so that recursive calls are possible }
  1207. if not is_void(current_procinfo.procdef.returndef) then
  1208. begin
  1209. srsym:=TSym(current_procinfo.procdef.localst.Find(current_procinfo.procdef.procsym.name));
  1210. if assigned(srsym) then
  1211. srsym.realname:='$hiddenresult';
  1212. end;
  1213. { delphi uses register calling for assembler methods }
  1214. if (m_delphi in current_settings.modeswitches) and
  1215. (po_assembler in current_procinfo.procdef.procoptions) and
  1216. not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
  1217. current_procinfo.procdef.proccalloption:=pocall_register;
  1218. { force the asm statement }
  1219. if token<>_ASM then
  1220. consume(_ASM);
  1221. include(current_procinfo.flags,pi_is_assembler);
  1222. p:=_asm_statement;
  1223. {$if not(defined(sparc)) and not(defined(arm)) and not(defined(avr))}
  1224. if (po_assembler in current_procinfo.procdef.procoptions) then
  1225. begin
  1226. { set the framepointer to esp for assembler functions when the
  1227. following conditions are met:
  1228. - if the are no local variables and parameters (except the allocated result)
  1229. - no reference to the result variable (refcount<=1)
  1230. - result is not stored as parameter
  1231. - target processor has optional frame pointer save
  1232. (vm, i386, vm only currently)
  1233. }
  1234. locals:=tabstractlocalsymtable(current_procinfo.procdef.parast).count_locals;
  1235. if (current_procinfo.procdef.localst.symtabletype=localsymtable) then
  1236. inc(locals,tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals);
  1237. if (locals=0) and
  1238. not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
  1239. (not assigned(current_procinfo.procdef.funcretsym) or
  1240. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
  1241. not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
  1242. begin
  1243. { Only need to set the framepointer, the locals will
  1244. be inserted with the correct reference in tcgasmnode.pass_generate_code }
  1245. current_procinfo.framepointer:=NR_STACK_POINTER_REG;
  1246. end;
  1247. end;
  1248. {$endif not(defined(sparc)) and not(defined(arm)) and not(defined(avr))}
  1249. { Flag the result as assigned when it is returned in a
  1250. register.
  1251. }
  1252. if assigned(current_procinfo.procdef.funcretsym) and
  1253. (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
  1254. tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
  1255. { because the END is already read we need to get the
  1256. last_endtoken_filepos here (PFV) }
  1257. last_endtoken_filepos:=current_tokenpos;
  1258. assembler_block:=p;
  1259. end;
  1260. end.