pstatmnt.pas 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709
  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,aasmtai,aasmdata,aasmbase,
  34. { symtable }
  35. symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
  36. paramgr,
  37. { pass 1 }
  38. pass_1,htypechk,
  39. nutils,ngenutil,nbas,ncal,nmem,nset,ncnv,ncon,nld,nflw,ninl,
  40. { parser }
  41. scanner,
  42. pbase,ptype,pexpr,
  43. { codegen }
  44. procinfo,cgbase,
  45. { assembler reader }
  46. rabase,
  47. { scanner }
  48. switches;
  49. function statement : tnode;forward;
  50. function if_statement : tnode;
  51. var
  52. ex,if_a,else_a : tnode;
  53. begin
  54. consume(_IF);
  55. ex:=comp_expr([ef_accept_equal]);
  56. consume(_THEN);
  57. if not(token in endtokens) then
  58. if_a:=statement
  59. else
  60. if_a:=nil;
  61. if try_to_consume(_ELSE) then
  62. else_a:=statement
  63. else
  64. else_a:=nil;
  65. result:=cifnode.create(ex,if_a,else_a);
  66. end;
  67. { creates a block (list) of statements, til the next END token }
  68. function statements_til_end : tnode;
  69. var
  70. first,last : tstatementnode;
  71. begin
  72. first:=nil;
  73. last:=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. if assigned(first) then
  93. statements_til_end.fileinfo:=first.fileinfo;
  94. end;
  95. function case_statement : tnode;
  96. var
  97. casedef : tdef;
  98. caseexpr,p : tnode;
  99. blockid : longint;
  100. hl1,hl2 : TConstExprInt;
  101. sl1,sl2 : tstringconstnode;
  102. casedeferror, caseofstring : boolean;
  103. casenode : tcasenode;
  104. begin
  105. consume(_CASE);
  106. caseexpr:=comp_expr([ef_accept_equal]);
  107. { determines result type }
  108. do_typecheckpass(caseexpr);
  109. { variants must be accepted, but first they must be converted to integer }
  110. if caseexpr.resultdef.typ=variantdef then
  111. begin
  112. caseexpr:=ctypeconvnode.create_internal(caseexpr,sinttype);
  113. do_typecheckpass(caseexpr);
  114. end;
  115. set_varstate(caseexpr,vs_read,[vsf_must_be_valid]);
  116. casedeferror:=false;
  117. casedef:=caseexpr.resultdef;
  118. { case of string must be rejected in delphi-, }
  119. { tp7/bp7-, mac-compatibility modes. }
  120. caseofstring :=
  121. ([m_delphi, m_mac, m_tp7] * current_settings.modeswitches = []) and
  122. is_string(casedef);
  123. if (not assigned(casedef)) or
  124. ( not(is_ordinal(casedef)) and (not caseofstring) ) then
  125. begin
  126. CGMessage(type_e_ordinal_or_string_expr_expected);
  127. { create a correct tree }
  128. caseexpr.free;
  129. caseexpr:=cordconstnode.create(0,u32inttype,false);
  130. { set error flag so no rangechecks are done }
  131. casedeferror:=true;
  132. end;
  133. { Create casenode }
  134. casenode:=ccasenode.create(caseexpr);
  135. consume(_OF);
  136. { Parse all case blocks }
  137. blockid:=0;
  138. repeat
  139. { maybe an instruction has more case labels }
  140. repeat
  141. p:=expr(true);
  142. if is_widechar(casedef) then
  143. begin
  144. if (p.nodetype=rangen) then
  145. begin
  146. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  147. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  148. do_typecheckpass(trangenode(p).left);
  149. do_typecheckpass(trangenode(p).right);
  150. end
  151. else
  152. begin
  153. p:=ctypeconvnode.create(p,cwidechartype);
  154. do_typecheckpass(p);
  155. end;
  156. end
  157. else
  158. begin
  159. if is_char(casedef) and is_widechar(p.resultdef) then
  160. begin
  161. if (p.nodetype=ordconstn) then
  162. begin
  163. p:=ctypeconvnode.create(p,cansichartype);
  164. do_typecheckpass(p);
  165. end
  166. else if (p.nodetype=rangen) then
  167. begin
  168. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cansichartype);
  169. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cansichartype);
  170. do_typecheckpass(trangenode(p).left);
  171. do_typecheckpass(trangenode(p).right);
  172. end;
  173. end;
  174. end;
  175. hl1:=0;
  176. hl2:=0;
  177. sl1:=nil;
  178. sl2:=nil;
  179. if (p.nodetype=rangen) then
  180. begin
  181. { type check for string case statements }
  182. if caseofstring and
  183. is_conststring_or_constcharnode(trangenode(p).left) and
  184. is_conststring_or_constcharnode(trangenode(p).right) then
  185. begin
  186. { we need stringconstnodes, even if expression contains single chars }
  187. sl1 := get_string_value(trangenode(p).left, tstringdef(casedef));
  188. sl2 := get_string_value(trangenode(p).right, tstringdef(casedef));
  189. if sl1.fullcompare(sl2) > 0 then
  190. CGMessage(parser_e_case_lower_less_than_upper_bound);
  191. end
  192. { type checking for ordinal case statements }
  193. else if (not caseofstring) and
  194. is_subequal(casedef, trangenode(p).left.resultdef) and
  195. is_subequal(casedef, trangenode(p).right.resultdef) then
  196. begin
  197. hl1:=get_ordinal_value(trangenode(p).left);
  198. hl2:=get_ordinal_value(trangenode(p).right);
  199. if hl1>hl2 then
  200. CGMessage(parser_e_case_lower_less_than_upper_bound);
  201. if not casedeferror then
  202. begin
  203. adaptrange(casedef,hl1,false,false,cs_check_range in current_settings.localswitches);
  204. adaptrange(casedef,hl2,false,false,cs_check_range in current_settings.localswitches);
  205. end;
  206. end
  207. else
  208. CGMessage(parser_e_case_mismatch);
  209. if caseofstring then
  210. casenode.addlabel(blockid,sl1,sl2)
  211. else
  212. casenode.addlabel(blockid,hl1,hl2);
  213. end
  214. else
  215. begin
  216. { type check for string case statements }
  217. if (caseofstring and (not is_conststring_or_constcharnode(p))) or
  218. { type checking for ordinal case statements }
  219. ((not caseofstring) and (not is_subequal(casedef, p.resultdef))) then
  220. CGMessage(parser_e_case_mismatch);
  221. if caseofstring then
  222. begin
  223. sl1:=get_string_value(p, tstringdef(casedef));
  224. casenode.addlabel(blockid,sl1,sl1);
  225. end
  226. else
  227. begin
  228. hl1:=get_ordinal_value(p);
  229. if not casedeferror then
  230. adaptrange(casedef,hl1,false,false,cs_check_range in current_settings.localswitches);
  231. casenode.addlabel(blockid,hl1,hl1);
  232. end;
  233. end;
  234. p.free;
  235. p := nil;
  236. sl1.free;
  237. sl1 := nil;
  238. sl2.free;
  239. sl2 := nil;
  240. if token=_COMMA then
  241. consume(_COMMA)
  242. else
  243. break;
  244. until false;
  245. consume(_COLON);
  246. { add instruction block }
  247. casenode.addblock(blockid,statement);
  248. { next block }
  249. inc(blockid);
  250. if not(token in [_ELSE,_OTHERWISE,_END]) then
  251. consume(_SEMICOLON);
  252. until (token in [_ELSE,_OTHERWISE,_END]);
  253. if (token in [_ELSE,_OTHERWISE]) then
  254. begin
  255. if not try_to_consume(_ELSE) then
  256. consume(_OTHERWISE);
  257. casenode.addelseblock(statements_til_end);
  258. end
  259. else
  260. consume(_END);
  261. result:=casenode;
  262. end;
  263. function repeat_statement : tnode;
  264. var
  265. first,last,p_e : tnode;
  266. begin
  267. consume(_REPEAT);
  268. first:=nil;
  269. last:=nil;
  270. while token<>_UNTIL do
  271. begin
  272. if first=nil then
  273. begin
  274. last:=cstatementnode.create(statement,nil);
  275. first:=last;
  276. end
  277. else
  278. begin
  279. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  280. last:=tstatementnode(last).right;
  281. end;
  282. if not try_to_consume(_SEMICOLON) then
  283. break;
  284. consume_emptystats;
  285. end;
  286. consume(_UNTIL);
  287. first:=cblocknode.create(first);
  288. p_e:=comp_expr([ef_accept_equal]);
  289. result:=cwhilerepeatnode.create(p_e,first,false,true);
  290. end;
  291. function while_statement : tnode;
  292. var
  293. p_e,p_a : tnode;
  294. begin
  295. consume(_WHILE);
  296. p_e:=comp_expr([ef_accept_equal]);
  297. consume(_DO);
  298. p_a:=statement;
  299. result:=cwhilerepeatnode.create(p_e,p_a,true,false);
  300. end;
  301. { a helper function which is used both by "with" and "for-in loop" nodes }
  302. function skip_nodes_before_load(p: tnode): tnode;
  303. begin
  304. { ignore nodes that don't add instructions in the tree }
  305. while assigned(p) and
  306. { equal type conversions }
  307. (
  308. (p.nodetype=typeconvn) and
  309. (ttypeconvnode(p).convtype=tc_equal)
  310. ) or
  311. { constant array index }
  312. (
  313. (p.nodetype=vecn) and
  314. (tvecnode(p).right.nodetype=ordconstn)
  315. ) do
  316. p:=tunarynode(p).left;
  317. result:=p;
  318. end;
  319. function for_statement : tnode;
  320. procedure check_range(hp:tnode; fordef: tdef);
  321. begin
  322. if (hp.nodetype=ordconstn) and
  323. (fordef.typ<>errordef) and
  324. { the node was derived from a generic parameter so ignore range check }
  325. not(nf_generic_para in hp.flags) then
  326. adaptrange(fordef,tordconstnode(hp).value,false,false,true);
  327. end;
  328. function for_loop_create(hloopvar: tnode): tnode;
  329. var
  330. hp,
  331. hblock,
  332. hto,hfrom : tnode;
  333. backward : boolean;
  334. loopvarsym : tabstractvarsym;
  335. begin
  336. { Check loop variable }
  337. loopvarsym:=nil;
  338. { variable must be an ordinal, int64 is not allowed for 32bit targets }
  339. if (
  340. not(is_ordinal(hloopvar.resultdef))
  341. {$if not defined(cpu64bitaddr) and not defined(cpu64bitalu)}
  342. or is_64bitint(hloopvar.resultdef)
  343. {$endif not cpu64bitaddr and not cpu64bitalu}
  344. ) and
  345. (hloopvar.resultdef.typ<>undefineddef)
  346. then
  347. begin
  348. MessagePos(hloopvar.fileinfo,type_e_ordinal_expr_expected);
  349. hloopvar.resultdef:=generrordef;
  350. end;
  351. hp:=hloopvar;
  352. while assigned(hp) and
  353. (
  354. { record/object fields and array elements are allowed }
  355. { in tp7 mode only }
  356. (
  357. (m_tp7 in current_settings.modeswitches) and
  358. (
  359. ((hp.nodetype=subscriptn) and
  360. ((tsubscriptnode(hp).left.resultdef.typ=recorddef) or
  361. is_object(tsubscriptnode(hp).left.resultdef))
  362. ) or
  363. { constant array index }
  364. (
  365. (hp.nodetype=vecn) and
  366. is_constintnode(tvecnode(hp).right)
  367. )
  368. )
  369. ) or
  370. { equal typeconversions }
  371. (
  372. (hp.nodetype=typeconvn) and
  373. (ttypeconvnode(hp).convtype=tc_equal)
  374. )
  375. ) do
  376. begin
  377. { Use the recordfield for loopvarsym }
  378. if not assigned(loopvarsym) and
  379. (hp.nodetype=subscriptn) then
  380. loopvarsym:=tsubscriptnode(hp).vs;
  381. hp:=tunarynode(hp).left;
  382. end;
  383. if assigned(hp) and
  384. (hp.nodetype=loadn) then
  385. begin
  386. case tloadnode(hp).symtableentry.typ of
  387. staticvarsym,
  388. localvarsym,
  389. paravarsym :
  390. begin
  391. { we need a simple loadn:
  392. 1. The load must be in a global symtable or
  393. in the same level as the para of the current proc.
  394. 2. value variables (no const,out or var)
  395. 3. No threadvar, readonly or typedconst
  396. }
  397. if (
  398. (tloadnode(hp).symtable.symtablelevel=main_program_level) or
  399. (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
  400. ) and
  401. (tabstractvarsym(tloadnode(hp).symtableentry).varspez=vs_value) and
  402. ([vo_is_thread_var,vo_is_typed_const] * tabstractvarsym(tloadnode(hp).symtableentry).varoptions=[]) then
  403. begin
  404. { Assigning for-loop variable is only allowed in tp7 and macpas }
  405. if ([m_tp7,m_mac] * current_settings.modeswitches = []) then
  406. begin
  407. if not assigned(loopvarsym) then
  408. loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
  409. include(loopvarsym.varoptions,vo_is_loop_counter);
  410. end;
  411. end
  412. else
  413. begin
  414. { Typed const is allowed in tp7 }
  415. if not(m_tp7 in current_settings.modeswitches) or
  416. not(vo_is_typed_const in tabstractvarsym(tloadnode(hp).symtableentry).varoptions) then
  417. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  418. end;
  419. end;
  420. else
  421. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  422. end;
  423. end
  424. else
  425. MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
  426. hfrom:=comp_expr([ef_accept_equal]);
  427. if try_to_consume(_DOWNTO) then
  428. backward:=true
  429. else
  430. begin
  431. consume(_TO);
  432. backward:=false;
  433. end;
  434. hto:=comp_expr([ef_accept_equal]);
  435. consume(_DO);
  436. { Check if the constants fit in the range }
  437. check_range(hfrom,hloopvar.resultdef);
  438. check_range(hto,hloopvar.resultdef);
  439. { first set the varstate for from and to, so
  440. uses of loopvar in those expressions will also
  441. trigger a warning when it is not used yet. This
  442. needs to be done before the instruction block is
  443. parsed to have a valid hloopvar }
  444. typecheckpass(hfrom);
  445. set_varstate(hfrom,vs_read,[vsf_must_be_valid]);
  446. typecheckpass(hto);
  447. set_varstate(hto,vs_read,[vsf_must_be_valid]);
  448. typecheckpass(hloopvar);
  449. { in two steps, because vs_readwritten may turn on vsf_must_be_valid }
  450. { for some subnodes }
  451. set_varstate(hloopvar,vs_written,[]);
  452. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  453. { ... now the instruction block }
  454. hblock:=statement;
  455. { variable is not used for loop counter anymore }
  456. if assigned(loopvarsym) then
  457. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  458. result:=cfornode.create(hloopvar,hfrom,hto,hblock,backward);
  459. { only in tp and mac pascal mode, we care about the value of the loop counter on loop exit
  460. I am not sure though, if this is the right rule, at least in delphi the loop counter is undefined
  461. on loop exit, we assume the same in all FPC modes }
  462. if ([m_objfpc,m_fpc,m_delphi]*current_settings.modeswitches)<>[] then
  463. Include(tfornode(Result).loopflags,lnf_dont_mind_loopvar_on_exit);
  464. end;
  465. function for_in_loop_create(hloopvar: tnode): tnode;
  466. var
  467. expr,hloopbody,hp: tnode;
  468. loopvarsym: tabstractvarsym;
  469. begin
  470. hp:=skip_nodes_before_load(hloopvar);
  471. if assigned(hp)and(hp.nodetype=loadn) then
  472. begin
  473. loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
  474. include(loopvarsym.varoptions,vo_is_loop_counter);
  475. end
  476. else
  477. loopvarsym:=nil;
  478. expr:=comp_expr([ef_accept_equal]);
  479. consume(_DO);
  480. set_varstate(hloopvar,vs_written,[]);
  481. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  482. hloopbody:=statement;
  483. if assigned(loopvarsym) then
  484. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  485. result:=create_for_in_loop(hloopvar,hloopbody,expr);
  486. expr.free;
  487. expr := nil;
  488. end;
  489. var
  490. hloopvar: tnode;
  491. begin
  492. { parse loop header }
  493. consume(_FOR);
  494. hloopvar:=factor(false,[]);
  495. valid_for_loopvar(hloopvar,true);
  496. if try_to_consume(_ASSIGNMENT) then
  497. result:=for_loop_create(hloopvar)
  498. else if try_to_consume(_IN) then
  499. result:=for_in_loop_create(hloopvar)
  500. else
  501. begin
  502. consume(_ASSIGNMENT); // fail
  503. result:=cerrornode.create;
  504. end;
  505. end;
  506. function _with_statement : tnode;
  507. var
  508. p : tnode;
  509. i : longint;
  510. st : TSymtable;
  511. newblock : tblocknode;
  512. newstatement : tstatementnode;
  513. calltempnode,
  514. tempnode : ttempcreatenode;
  515. valuenode,
  516. hp,
  517. refnode : tnode;
  518. hdef : tdef;
  519. helperdef : tobjectdef;
  520. hasimplicitderef : boolean;
  521. withsymtablelist : TFPObjectList;
  522. procedure pushobjchild(withdef,obj:tobjectdef);
  523. var
  524. parenthelperdef : tobjectdef;
  525. begin
  526. if not assigned(obj) then
  527. exit;
  528. pushobjchild(withdef,obj.childof);
  529. { we need to look for helpers that were defined for the parent
  530. class as well }
  531. search_last_objectpascal_helper(obj,current_structdef,parenthelperdef);
  532. { push the symtables of the helper's parents in reverse order }
  533. if assigned(parenthelperdef) then
  534. pushobjchild(withdef,parenthelperdef.childof);
  535. { keep the original tobjectdef as owner, because that is used for
  536. visibility of the symtable }
  537. st:=twithsymtable.create(withdef,obj.symtable.SymList,refnode.getcopy);
  538. symtablestack.push(st);
  539. withsymtablelist.add(st);
  540. { push the symtable of the helper }
  541. if assigned(parenthelperdef) then
  542. begin
  543. st:=twithsymtable.create(withdef,parenthelperdef.symtable.SymList,refnode.getcopy);
  544. symtablestack.push(st);
  545. withsymtablelist.add(st);
  546. end;
  547. end;
  548. begin
  549. calltempnode:=nil;
  550. p:=comp_expr([ef_accept_equal]);
  551. do_typecheckpass(p);
  552. if (p.nodetype=vecn) and
  553. (vnf_memseg in tvecnode(p).vecnodeflags) then
  554. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  555. { "with procvar" can never mean anything, so always try
  556. to call it in case it returns a record/object/... }
  557. maybe_call_procvar(p,false);
  558. if (p.resultdef.typ in [objectdef,recorddef,classrefdef]) or
  559. ((p.resultdef.typ=undefineddef) and (df_generic in current_procinfo.procdef.defoptions)) then
  560. begin
  561. newblock:=nil;
  562. valuenode:=nil;
  563. tempnode:=nil;
  564. hp:=skip_nodes_before_load(p);
  565. if (hp.nodetype=loadn) and
  566. (
  567. (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
  568. (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
  569. (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
  570. ) and
  571. { MacPas objects are mapped to classes, and the MacPas compilers
  572. interpret with-statements with MacPas objects the same way
  573. as records (the object referenced by the with-statement
  574. must remain constant)
  575. }
  576. not(is_class(hp.resultdef) and
  577. (m_mac in current_settings.modeswitches)) then
  578. begin
  579. { simple load, we can reference direct }
  580. refnode:=p;
  581. end
  582. else
  583. begin
  584. { complex load, load in temp first }
  585. newblock:=internalstatements(newstatement);
  586. { when we can't take the address of p, load it in a temp }
  587. { since we may need its address later on }
  588. if not valid_for_addr(p,false) then
  589. begin
  590. calltempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent,true);
  591. addstatement(newstatement,calltempnode);
  592. addstatement(newstatement,cassignmentnode.create(
  593. ctemprefnode.create(calltempnode),
  594. p));
  595. p:=ctemprefnode.create(calltempnode);
  596. typecheckpass(p);
  597. end;
  598. { several object types have implicit dereferencing }
  599. { is_implicit_pointer_object_type() returns true for records
  600. on the JVM target because they are implemented as classes
  601. there, but we definitely have to take their address here
  602. since otherwise a deep copy is made and changes are made to
  603. this copy rather than to the original one }
  604. hasimplicitderef:=
  605. (is_implicit_pointer_object_type(p.resultdef) or
  606. (p.resultdef.typ=classrefdef)) and
  607. not((target_info.system in systems_jvm) and
  608. ((p.resultdef.typ=recorddef) or
  609. is_object(p.resultdef)));
  610. if hasimplicitderef then
  611. hdef:=p.resultdef
  612. else
  613. hdef:=cpointerdef.create(p.resultdef);
  614. { load address of the value in a temp }
  615. tempnode:=ctempcreatenode.create_withnode(hdef,sizeof(pint),tt_persistent,true,p);
  616. typecheckpass(tnode(tempnode));
  617. valuenode:=p;
  618. refnode:=ctemprefnode.create(tempnode);
  619. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  620. { add address call for valuenode and deref for refnode if this
  621. is not done implicitly }
  622. if not hasimplicitderef then
  623. begin
  624. valuenode:=caddrnode.create_internal_nomark(valuenode);
  625. include(taddrnode(valuenode).addrnodeflags,anf_typedaddr);
  626. refnode:=cderefnode.create(refnode);
  627. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  628. end;
  629. addstatement(newstatement,tempnode);
  630. addstatement(newstatement,cassignmentnode.create(
  631. ctemprefnode.create(tempnode),
  632. valuenode));
  633. typecheckpass(refnode);
  634. end;
  635. { Note: the symtable of the helper is pushed after the following
  636. "case", the symtables of the helper's parents are passed in
  637. the "case" branches }
  638. withsymtablelist:=TFPObjectList.create(true);
  639. case p.resultdef.typ of
  640. objectdef :
  641. begin
  642. { do we have a helper for this type? }
  643. search_last_objectpascal_helper(tabstractrecorddef(p.resultdef),current_structdef,helperdef);
  644. { push symtables of all parents in reverse order }
  645. pushobjchild(tobjectdef(p.resultdef),tobjectdef(p.resultdef).childof);
  646. { push symtables of all parents of the helper in reverse order }
  647. if assigned(helperdef) then
  648. pushobjchild(helperdef,helperdef.childof);
  649. { push object symtable }
  650. st:=twithsymtable.Create(tobjectdef(p.resultdef),tobjectdef(p.resultdef).symtable.SymList,refnode);
  651. symtablestack.push(st);
  652. withsymtablelist.add(st);
  653. end;
  654. classrefdef :
  655. begin
  656. { do we have a helper for this type? }
  657. search_last_objectpascal_helper(tobjectdef(tclassrefdef(p.resultdef).pointeddef),current_structdef,helperdef);
  658. { push symtables of all parents in reverse order }
  659. pushobjchild(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).childof);
  660. { push symtables of all parents of the helper in reverse order }
  661. if assigned(helperdef) then
  662. pushobjchild(helperdef,helperdef.childof);
  663. { push object symtable }
  664. st:=twithsymtable.Create(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).symtable.SymList,refnode);
  665. symtablestack.push(st);
  666. withsymtablelist.add(st);
  667. end;
  668. recorddef :
  669. begin
  670. { do we have a helper for this type? }
  671. search_last_objectpascal_helper(tabstractrecorddef(p.resultdef),current_structdef,helperdef);
  672. { push symtables of all parents of the helper in reverse order }
  673. if assigned(helperdef) then
  674. pushobjchild(helperdef,helperdef.childof);
  675. { push record symtable }
  676. st:=twithsymtable.create(trecorddef(p.resultdef),trecorddef(p.resultdef).symtable.SymList,refnode);
  677. symtablestack.push(st);
  678. withsymtablelist.add(st);
  679. end;
  680. undefineddef :
  681. begin
  682. if not(df_generic in current_procinfo.procdef.defoptions) then
  683. internalerror(2012122802);
  684. helperdef:=nil;
  685. { push record symtable }
  686. st:=twithsymtable.create(p.resultdef,nil,refnode);
  687. symtablestack.push(st);
  688. withsymtablelist.add(st);
  689. end;
  690. else
  691. internalerror(200601271);
  692. end;
  693. { push helper symtable }
  694. if assigned(helperdef) then
  695. begin
  696. st:=twithsymtable.Create(helperdef,helperdef.symtable.SymList,refnode.getcopy);
  697. symtablestack.push(st);
  698. withsymtablelist.add(st);
  699. end;
  700. if try_to_consume(_COMMA) then
  701. p:=_with_statement()
  702. else
  703. begin
  704. consume(_DO);
  705. if token<>_SEMICOLON then
  706. p:=statement
  707. else
  708. p:=cnothingnode.create;
  709. end;
  710. { remove symtables in reverse order from the stack }
  711. for i:=withsymtablelist.count-1 downto 0 do
  712. symtablestack.pop(TSymtable(withsymtablelist[i]));
  713. withsymtablelist.free;
  714. withsymtablelist := nil;
  715. { Finalize complex withnode with destroy of temp }
  716. if assigned(newblock) then
  717. begin
  718. addstatement(newstatement,p);
  719. if assigned(tempnode) then
  720. addstatement(newstatement,ctempdeletenode.create(tempnode));
  721. if assigned(calltempnode) then
  722. addstatement(newstatement,ctempdeletenode.create(calltempnode));
  723. p:=newblock;
  724. end;
  725. result:=p;
  726. end
  727. else
  728. begin
  729. p.free;
  730. p := nil;
  731. Message1(parser_e_false_with_expr,p.resultdef.GetTypeName);
  732. { try to recover from error }
  733. if try_to_consume(_COMMA) then
  734. begin
  735. hp:=_with_statement();
  736. if (hp=nil) then; { remove warning about unused }
  737. end
  738. else
  739. begin
  740. consume(_DO);
  741. { ignore all }
  742. if token<>_SEMICOLON then
  743. statement;
  744. end;
  745. result:=cerrornode.create;
  746. end;
  747. end;
  748. function with_statement : tnode;
  749. begin
  750. consume(_WITH);
  751. with_statement:=_with_statement();
  752. end;
  753. function raise_statement : tnode;
  754. var
  755. p,pobj,paddr,pframe : tnode;
  756. begin
  757. pobj:=nil;
  758. paddr:=nil;
  759. pframe:=nil;
  760. consume(_RAISE);
  761. if not(token in endtokens) then
  762. begin
  763. { object }
  764. pobj:=comp_expr([ef_accept_equal]);
  765. if try_to_consume(_AT) then
  766. begin
  767. paddr:=comp_expr([ef_accept_equal]);
  768. if try_to_consume(_COMMA) then
  769. pframe:=comp_expr([ef_accept_equal]);
  770. end;
  771. end
  772. else
  773. begin
  774. if (block_type<>bt_except) then
  775. Message(parser_e_no_reraise_possible);
  776. end;
  777. if (po_noreturn in current_procinfo.procdef.procoptions) and (exceptblockcounter=0) then
  778. Message(parser_e_raise_with_noreturn_not_allowed);
  779. p:=craisenode.create(pobj,paddr,pframe);
  780. raise_statement:=p;
  781. end;
  782. function try_statement : tnode;
  783. procedure check_type_valid(var def: tdef);
  784. begin
  785. if not (is_class(def) or is_javaclass(def) or
  786. { skip showing error message the second time }
  787. (def.typ=errordef)) then
  788. begin
  789. Message1(type_e_class_type_expected,def.typename);
  790. def:=generrordef;
  791. end;
  792. end;
  793. var
  794. p_try_block,p_finally_block,first,last,
  795. p_default,p_specific,hp : tnode;
  796. ot : tDef;
  797. sym : tlocalvarsym;
  798. old_block_type : tblock_type;
  799. excepTSymtable : TSymtable;
  800. objname,objrealname : TIDString;
  801. srsym : tsym;
  802. srsymtable : TSymtable;
  803. t:ttoken;
  804. unit_found:boolean;
  805. oldcurrent_exceptblock: integer;
  806. filepostry : tfileposinfo;
  807. begin
  808. p_default:=nil;
  809. p_specific:=nil;
  810. excepTSymtable:=nil;
  811. last:=nil;
  812. { read statements to try }
  813. consume(_TRY);
  814. filepostry:=current_filepos;
  815. first:=nil;
  816. inc(exceptblockcounter);
  817. oldcurrent_exceptblock := current_exceptblock;
  818. current_exceptblock := exceptblockcounter;
  819. old_block_type := block_type;
  820. block_type := bt_body;
  821. while (token<>_FINALLY) and (token<>_EXCEPT) do
  822. begin
  823. if first=nil then
  824. begin
  825. last:=cstatementnode.create(statement,nil);
  826. first:=last;
  827. end
  828. else
  829. begin
  830. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  831. last:=tstatementnode(last).right;
  832. end;
  833. if not try_to_consume(_SEMICOLON) then
  834. break;
  835. consume_emptystats;
  836. end;
  837. p_try_block:=cblocknode.create(first);
  838. if try_to_consume(_FINALLY) then
  839. begin
  840. inc(exceptblockcounter);
  841. current_exceptblock := exceptblockcounter;
  842. p_finally_block:=statements_til_end;
  843. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  844. try_statement.fileinfo:=filepostry;
  845. end
  846. else
  847. begin
  848. consume(_EXCEPT);
  849. block_type:=bt_except;
  850. inc(exceptblockcounter);
  851. current_exceptblock := exceptblockcounter;
  852. ot:=generrordef;
  853. p_specific:=nil;
  854. if (idtoken=_ON) then
  855. { catch specific exceptions }
  856. begin
  857. repeat
  858. consume(_ON);
  859. if token=_ID then
  860. begin
  861. objname:=pattern;
  862. objrealname:=orgpattern;
  863. { can't use consume_sym here, because we need already
  864. to check for the colon }
  865. searchsym(objname,srsym,srsymtable);
  866. consume(_ID);
  867. { is a explicit name for the exception given ? }
  868. if try_to_consume(_COLON) then
  869. begin
  870. single_type(ot,[]);
  871. check_type_valid(ot);
  872. sym:=clocalvarsym.create(objrealname,vs_value,ot,[]);
  873. end
  874. else
  875. begin
  876. { check if type is valid, must be done here because
  877. with "e: Exception" the e is not necessary }
  878. { support unit.identifier }
  879. unit_found:=try_consume_unitsym_no_specialize(srsym,srsymtable,t,[],objname);
  880. if srsym=nil then
  881. begin
  882. identifier_not_found(objrealname);
  883. srsym:=generrorsym;
  884. end;
  885. if unit_found then
  886. consume(t);
  887. { check if type is valid, must be done here because
  888. with "e: Exception" the e is not necessary }
  889. if (srsym.typ=typesym) then
  890. begin
  891. ot:=ttypesym(srsym).typedef;
  892. parse_nested_types(ot,false,false,nil);
  893. check_type_valid(ot);
  894. end
  895. else
  896. begin
  897. Message(type_e_type_id_expected);
  898. ot:=generrordef;
  899. end;
  900. { create dummy symbol so we don't need a special
  901. case in ncgflw, and so that we always know the
  902. type }
  903. sym:=clocalvarsym.create('$exceptsym',vs_value,ot,[]);
  904. end;
  905. excepTSymtable:=tstt_excepTSymtable.create;
  906. excepTSymtable.defowner:=current_procinfo.procdef;
  907. excepTSymtable.insertsym(sym);
  908. symtablestack.push(excepTSymtable);
  909. end
  910. else
  911. consume(_ID);
  912. consume(_DO);
  913. hp:=connode.create(nil,statement);
  914. if ot.typ=errordef then
  915. begin
  916. hp.free;
  917. hp:=cerrornode.create;
  918. end;
  919. if p_specific=nil then
  920. begin
  921. last:=hp;
  922. p_specific:=last;
  923. end
  924. else
  925. begin
  926. tonnode(last).left:=hp;
  927. last:=tonnode(last).left;
  928. end;
  929. { set the informations }
  930. { only if the creation of the onnode was succesful, it's possible }
  931. { that last and hp are errornodes (JM) }
  932. if last.nodetype = onn then
  933. begin
  934. tonnode(last).excepttype:=tobjectdef(ot);
  935. tonnode(last).excepTSymtable:=excepTSymtable;
  936. end;
  937. { remove exception symtable }
  938. if assigned(excepTSymtable) then
  939. begin
  940. symtablestack.pop(excepTSymtable);
  941. if last.nodetype <> onn then
  942. begin
  943. excepTSymtable.free;
  944. excepTSymtable := nil;
  945. end;
  946. end;
  947. if not try_to_consume(_SEMICOLON) then
  948. break;
  949. consume_emptystats;
  950. until (token in [_END,_ELSE]);
  951. if try_to_consume(_ELSE) then
  952. begin
  953. { catch the other exceptions }
  954. p_default:=statements_til_end;
  955. end
  956. else
  957. consume(_END);
  958. end
  959. else
  960. begin
  961. { catch all exceptions }
  962. p_default:=statements_til_end;
  963. end;
  964. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  965. end;
  966. block_type:=old_block_type;
  967. current_exceptblock := oldcurrent_exceptblock;
  968. end;
  969. function _asm_statement : tnode;
  970. var
  971. asmstat : tasmnode;
  972. reg : tregister;
  973. asmreader : tbaseasmreader;
  974. entrypos : tfileposinfo;
  975. hl : TAsmList;
  976. begin
  977. Inside_asm_statement:=true;
  978. asmstat:=nil;
  979. hl:=nil;
  980. { apply all switch changes as the assembler readers doesn't do so }
  981. flushpendingswitchesstate;
  982. if assigned(asmmodeinfos[current_settings.asmmode]) then
  983. begin
  984. asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
  985. entrypos:=current_filepos;
  986. hl:=asmreader.assemble as TAsmList;
  987. if (not hl.empty) then
  988. begin
  989. { mark boundaries of assembler block, this is necessary for optimizer }
  990. hl.insert(tai_marker.create(mark_asmblockstart));
  991. hl.concat(tai_marker.create(mark_asmblockend));
  992. end;
  993. asmstat:=casmnode.create(hl);
  994. asmstat.fileinfo:=entrypos;
  995. asmreader.free;
  996. asmreader := nil;
  997. end
  998. else
  999. Message(parser_f_assembler_reader_not_supported);
  1000. { Mark procedure that it has assembler blocks }
  1001. include(current_procinfo.flags,pi_has_assembler_block);
  1002. {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
  1003. { We assume the function result is always used in the TP mode }
  1004. if (m_tp7 in current_settings.modeswitches) and
  1005. not (po_assembler in current_procinfo.procdef.procoptions) and
  1006. assigned(current_procinfo.procdef.funcretsym) then
  1007. current_procinfo.procdef.funcretsym.IncRefCount;
  1008. {$endif}
  1009. { Read first the _ASM statement }
  1010. consume(_ASM);
  1011. { Force an empty register list for pure assembler routines,
  1012. so that pass2 won't allocate volatile registers for them. }
  1013. if (po_assembler in current_procinfo.procdef.procoptions) then
  1014. Include(asmstat.asmnodeflags,asmnf_has_registerlist);
  1015. { END is read, got a list of changed registers? }
  1016. if try_to_consume(_LECKKLAMMER) then
  1017. begin
  1018. if token<>_RECKKLAMMER then
  1019. begin
  1020. if po_assembler in current_procinfo.procdef.procoptions then
  1021. Message(parser_w_register_list_ignored);
  1022. repeat
  1023. { it's possible to specify the modified registers }
  1024. if token=_CSTRING then
  1025. reg:=std_regnum_search(lower(cstringpattern))
  1026. else if token=_CCHAR then
  1027. reg:=std_regnum_search(lower(pattern))
  1028. else
  1029. reg:=NR_NO;
  1030. { is_extra_reg is not exported on all architectures from cpubase }
  1031. {$if defined(RISCV)}
  1032. if (reg=NR_NO) and (token=_CSTRING) then
  1033. reg:=is_extra_reg(upper(cstringpattern));
  1034. {$endif defined(RISCV)}
  1035. if reg<>NR_NO then
  1036. begin
  1037. if not(po_assembler in current_procinfo.procdef.procoptions) and assigned(hl) then
  1038. begin
  1039. hl.Insert(tai_regalloc.alloc(reg,nil));
  1040. hl.Insert(tai_regalloc.markused(reg));
  1041. hl.Concat(tai_regalloc.dealloc(reg,nil));
  1042. end;
  1043. end
  1044. else
  1045. Message(asmr_e_invalid_register);
  1046. if token=_CCHAR then
  1047. consume(_CCHAR)
  1048. else
  1049. consume(_CSTRING);
  1050. if not try_to_consume(_COMMA) then
  1051. break;
  1052. until false;
  1053. Include(asmstat.asmnodeflags,asmnf_has_registerlist);
  1054. end;
  1055. consume(_RECKKLAMMER);
  1056. end;
  1057. Inside_asm_statement:=false;
  1058. _asm_statement:=asmstat;
  1059. end;
  1060. { Old Turbo Pascal INLINE(data/data/...) }
  1061. function tp_inline_statement : tnode;
  1062. var
  1063. actype : taiconst_type;
  1064. function eval_intconst: asizeint;
  1065. var
  1066. cv : Tconstexprint;
  1067. def: tdef;
  1068. begin
  1069. cv:=get_intconst;
  1070. case actype of
  1071. aitconst_8bit:
  1072. def:=s8inttype;
  1073. aitconst_16bit:
  1074. def:=s16inttype;
  1075. else
  1076. def:=sizesinttype;
  1077. end;
  1078. if cv.uvalue>get_max_value(def).uvalue then
  1079. def:=get_unsigned_inttype(def);
  1080. adaptrange(def,cv,rc_implicit);
  1081. result:=cv.svalue;
  1082. end;
  1083. var
  1084. cur_line : longint;
  1085. w : asizeint;
  1086. hl : TAsmList;
  1087. asmstat : tasmnode;
  1088. sym : tsym;
  1089. symtable : TSymtable;
  1090. s : tsymstr;
  1091. ac : tai_const;
  1092. nesting : integer;
  1093. tokenbuf : tdynamicarray;
  1094. begin
  1095. consume(_INLINE);
  1096. consume(_LKLAMMER);
  1097. hl:=TAsmList.create;
  1098. asmstat:=casmnode.create(hl);
  1099. asmstat.fileinfo:=current_filepos;
  1100. tokenbuf:=tdynamicarray.Create(16);
  1101. cur_line:=0;
  1102. { Parse data blocks }
  1103. repeat
  1104. { Record one data block for further replaying.
  1105. This is needed since / is used as a data block delimiter and cause troubles
  1106. with constant evaluation which is allowed inside a data block. }
  1107. tokenbuf.reset;
  1108. current_scanner.startrecordtokens(tokenbuf);
  1109. nesting:=0;
  1110. while token<>_SLASH do
  1111. begin
  1112. case token of
  1113. _LKLAMMER:
  1114. inc(nesting);
  1115. _RKLAMMER:
  1116. begin
  1117. dec(nesting);
  1118. if nesting<0 then
  1119. break;
  1120. end;
  1121. _SEMICOLON:
  1122. consume(_RKLAMMER); { error }
  1123. else
  1124. ; {no action}
  1125. end;
  1126. consume(token);
  1127. end;
  1128. current_scanner.stoprecordtokens;
  1129. { Set the current token to ; to make the constant evaluator happy }
  1130. token:=_SEMICOLON;
  1131. { Parse recorded tokens }
  1132. current_scanner.startreplaytokens(tokenbuf,false);
  1133. if cur_line<>current_filepos.line then
  1134. begin
  1135. hl.concat(tai_force_line.Create);
  1136. cur_line:=current_filepos.line;
  1137. end;
  1138. { Data size override }
  1139. if try_to_consume(_GT) then
  1140. actype:=aitconst_16bit
  1141. else
  1142. if try_to_consume(_LT) then
  1143. actype:=aitconst_8bit
  1144. else
  1145. actype:=aitconst_128bit; { default size }
  1146. sym:=nil;
  1147. if token=_ID then
  1148. begin
  1149. if searchsym(pattern,sym,symtable) then
  1150. begin
  1151. if sym.typ in [staticvarsym,localvarsym,paravarsym] then
  1152. begin
  1153. { Address of the static symbol or base offset for local symbols }
  1154. consume(_ID);
  1155. if (sym.typ=staticvarsym) and not (actype in [aitconst_128bit,aitconst_ptr]) then
  1156. Message1(type_e_integer_expr_expected,sym.name);
  1157. { Additional offset }
  1158. if token in [_PLUS,_MINUS] then
  1159. w:=eval_intconst
  1160. else
  1161. w:=0;
  1162. if sym.typ=staticvarsym then
  1163. s:=sym.mangledname
  1164. else
  1165. s:=sym.name;
  1166. ac:=tai_const.Createname(s,w);
  1167. if actype=aitconst_128bit then
  1168. ac.consttype:=aitconst_ptr
  1169. else
  1170. ac.consttype:=actype;
  1171. { For a local symbol it is needed to generate a constant with the symbols's stack offset.
  1172. The stack offset is unavailable rigth now and will be resolved later in tcgasmnode.pass_generate_code.
  1173. Set sym.bind:=AB_NONE to indicate that this is a local symbol. }
  1174. if sym.typ<>staticvarsym then
  1175. ac.sym.bind:=AB_NONE;
  1176. hl.concat(ac);
  1177. end
  1178. else
  1179. if sym.typ=constsym then
  1180. sym:=nil
  1181. else
  1182. begin
  1183. consume(_ID);
  1184. Message(asmr_e_wrong_sym_type);
  1185. end;
  1186. end;
  1187. end;
  1188. if sym=nil then
  1189. begin
  1190. { Integer constant expression }
  1191. w:=eval_intconst;
  1192. case actype of
  1193. aitconst_8bit:
  1194. hl.concat(tai_const.Create_8bit(w));
  1195. aitconst_16bit:
  1196. hl.concat(tai_const.Create_16bit(w));
  1197. else
  1198. if w<$100 then
  1199. hl.concat(tai_const.Create_8bit(w))
  1200. else
  1201. hl.concat(tai_const.Create_sizeint(w));
  1202. end;
  1203. end;
  1204. if not try_to_consume(_SEMICOLON) then
  1205. consume(_RKLAMMER); {error}
  1206. until nesting<0;
  1207. tokenbuf.free;
  1208. tokenbuf := nil;
  1209. { mark boundaries of assembler block, this is necessary for optimizer }
  1210. hl.insert(tai_marker.create(mark_asmblockstart));
  1211. hl.concat(tai_marker.create(mark_asmblockend));
  1212. { Mark procedure that it has assembler blocks }
  1213. include(current_procinfo.flags,pi_has_assembler_block);
  1214. { Assume the function result is always used }
  1215. if assigned(current_procinfo.procdef.funcretsym) then
  1216. current_procinfo.procdef.funcretsym.IncRefCount;
  1217. result:=asmstat;
  1218. end;
  1219. function statement : tnode;
  1220. var
  1221. p,
  1222. astatement,
  1223. code : tnode;
  1224. filepos : tfileposinfo;
  1225. srsym : tsym;
  1226. srsymtable : TSymtable;
  1227. s : TIDString;
  1228. begin
  1229. filepos:=current_tokenpos;
  1230. code:=nil;
  1231. case token of
  1232. _GOTO :
  1233. begin
  1234. if not(cs_support_goto in current_settings.moduleswitches) then
  1235. Message(sym_e_goto_and_label_not_supported);
  1236. consume(_GOTO);
  1237. if (token<>_INTCONST) and (token<>_ID) then
  1238. begin
  1239. Message(sym_e_label_not_found);
  1240. code:=cerrornode.create;
  1241. end
  1242. else
  1243. begin
  1244. if token=_ID then
  1245. consume_sym(srsym,srsymtable)
  1246. else
  1247. begin
  1248. if token<>_INTCONST then
  1249. internalerror(201008021);
  1250. { strip leading 0's in iso mode }
  1251. if (([m_iso,m_extpas]*current_settings.modeswitches)<>[]) then
  1252. while (length(pattern)>1) and (pattern[1]='0') do
  1253. delete(pattern,1,1);
  1254. searchsym(pattern,srsym,srsymtable);
  1255. if srsym=nil then
  1256. begin
  1257. identifier_not_found(pattern);
  1258. srsym:=generrorsym;
  1259. srsymtable:=nil;
  1260. end;
  1261. consume(token);
  1262. end;
  1263. if srsym.typ<>labelsym then
  1264. begin
  1265. Message(sym_e_id_is_no_label_id);
  1266. code:=cerrornode.create;
  1267. end
  1268. else
  1269. begin
  1270. { goto outside the current scope? }
  1271. if srsym.owner<>current_procinfo.procdef.localst then
  1272. begin
  1273. { allowed? }
  1274. if not(m_non_local_goto in current_settings.modeswitches) then
  1275. Message(parser_e_goto_outside_proc);
  1276. include(current_procinfo.flags,pi_has_global_goto);
  1277. if is_nested_pd(current_procinfo.procdef) then
  1278. current_procinfo.set_needs_parentfp(srsym.owner.symtablelevel);
  1279. end;
  1280. code:=cgotonode.create(tlabelsym(srsym));
  1281. tgotonode(code).labelsym:=tlabelsym(srsym);
  1282. { set flag that this label is used }
  1283. tlabelsym(srsym).used:=true;
  1284. end;
  1285. end;
  1286. end;
  1287. _BEGIN :
  1288. begin
  1289. code:=statement_block(_BEGIN);
  1290. Include(TBlockNode(code).blocknodeflags, bnf_strippable);
  1291. end;
  1292. _IF :
  1293. code:=if_statement;
  1294. _CASE :
  1295. code:=case_statement;
  1296. _REPEAT :
  1297. code:=repeat_statement;
  1298. _WHILE :
  1299. code:=while_statement;
  1300. _FOR :
  1301. code:=for_statement;
  1302. _WITH :
  1303. code:=with_statement;
  1304. _TRY :
  1305. code:=try_statement;
  1306. _RAISE :
  1307. code:=raise_statement;
  1308. { semicolons,else until and end are ignored }
  1309. _SEMICOLON,
  1310. _ELSE,
  1311. _UNTIL,
  1312. _END:
  1313. code:=cnothingnode.create;
  1314. _FAIL :
  1315. begin
  1316. if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  1317. Message(parser_e_fail_only_in_constructor);
  1318. consume(_FAIL);
  1319. code:=cnodeutils.call_fail_node;
  1320. end;
  1321. _ASM :
  1322. begin
  1323. if parse_generic then
  1324. Message(parser_e_no_assembler_in_generic);
  1325. code:=_asm_statement;
  1326. end;
  1327. _PLUS:
  1328. begin
  1329. Message(parser_e_syntax_error);
  1330. consume(_PLUS);
  1331. end;
  1332. _INLINE:
  1333. begin
  1334. code:=tp_inline_statement;
  1335. end;
  1336. _EOF :
  1337. if current_scanner.had_multiline_string then
  1338. Message2(scan_f_unterminated_multiline_string,
  1339. tostr(current_scanner.multiline_start_line),
  1340. tostr(current_scanner.multiline_start_column))
  1341. else
  1342. Message(scan_f_end_of_file);
  1343. else
  1344. begin
  1345. { don't typecheck yet, because that will also simplify, which may
  1346. result in not detecting certain kinds of syntax errors --
  1347. see mantis #15594 }
  1348. p:=expr(false);
  1349. { save the pattern here for latter usage, the label could be "000",
  1350. even if we read an expression, the pattern is still valid if it's really
  1351. a label (FK)
  1352. if you want to mess here, take care of
  1353. tests/webtbs/tw3546.pp
  1354. }
  1355. s:=pattern;
  1356. { When a colon follows a intconst then transform it into a label }
  1357. if (p.nodetype=ordconstn) and
  1358. try_to_consume(_COLON) then
  1359. begin
  1360. { in iso mode, 0003: is equal to 3: }
  1361. if (([m_iso,m_extpas]*current_settings.modeswitches)<>[]) then
  1362. searchsym(tostr(tordconstnode(p).value),srsym,srsymtable)
  1363. else
  1364. searchsym(s,srsym,srsymtable);
  1365. p.free;
  1366. p := nil;
  1367. if assigned(srsym) and
  1368. (srsym.typ=labelsym) then
  1369. begin
  1370. if tlabelsym(srsym).defined then
  1371. Message(sym_e_label_already_defined);
  1372. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1373. begin
  1374. include(current_procinfo.flags,pi_has_interproclabel);
  1375. if (current_procinfo.procdef.proctypeoption in [potype_unitinit,potype_unitfinalize]) then
  1376. Message(sym_e_interprocgoto_into_init_final_code_not_allowed);
  1377. end;
  1378. tlabelsym(srsym).defined:=true;
  1379. p:=clabelnode.create(nil,tlabelsym(srsym));
  1380. tlabelsym(srsym).code:=p;
  1381. end
  1382. else
  1383. begin
  1384. Message1(sym_e_label_used_and_not_defined,s);
  1385. p:=cnothingnode.create;
  1386. end;
  1387. end;
  1388. if p.nodetype=labeln then
  1389. begin
  1390. if not(token in endtokens) then
  1391. begin
  1392. astatement:=statement();
  1393. typecheckpass(astatement);
  1394. p:=cblocknode.create(cstatementnode.create(p,cstatementnode.create(astatement,nil)));
  1395. Include(TBlockNode(p).blocknodeflags, bnf_strippable);
  1396. end;
  1397. end
  1398. else
  1399. { change a load of a procvar to a call. this is also
  1400. supported in fpc mode }
  1401. if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
  1402. maybe_call_procvar(p,false);
  1403. { blockn support because a read/write is changed into a blocknode
  1404. with a separate statement for each read/write operation (JM)
  1405. the same is true for val() if the third parameter is not 32 bit
  1406. goto nodes are created by the compiler for non local exit statements, so
  1407. include them as well
  1408. }
  1409. if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
  1410. continuen,labeln,blockn,exitn,goton]) or
  1411. ((p.nodetype=inlinen) and
  1412. not tinlinenode(p).may_ignore_result) or
  1413. ((p.nodetype=calln) and
  1414. (assigned(tcallnode(p).procdefinition)) and
  1415. (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
  1416. Message(parser_e_illegal_expression);
  1417. if not assigned(p.resultdef) then
  1418. do_typecheckpass(p);
  1419. { Specify that we don't use the value returned by the call.
  1420. This is used for :
  1421. - dispose of temp stack space
  1422. - dispose on FPU stack
  1423. - extended syntax checking }
  1424. if (p.nodetype=calln) then
  1425. begin
  1426. exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
  1427. { in $x- state, the function result must not be ignored }
  1428. if not(cs_extsyntax in current_settings.moduleswitches) and
  1429. not(is_void(p.resultdef)) and
  1430. { can be nil in case there was an error in the expression }
  1431. assigned(tcallnode(p).procdefinition) and
  1432. { allow constructor calls to drop the result if they are
  1433. called as instance methods instead of class methods }
  1434. not(
  1435. (tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
  1436. is_class_or_object(tprocdef(tcallnode(p).procdefinition).struct) and
  1437. assigned(tcallnode(p).methodpointer) and
  1438. (tnode(tcallnode(p).methodpointer).resultdef.typ=objectdef)
  1439. ) then
  1440. Message(parser_e_illegal_expression);
  1441. end;
  1442. code:=p;
  1443. end;
  1444. end;
  1445. if assigned(code) then
  1446. begin
  1447. typecheckpass(code);
  1448. code.fileinfo:=filepos;
  1449. end;
  1450. statement:=code;
  1451. end;
  1452. function statement_block(starttoken : ttoken) : tnode;
  1453. var
  1454. first,last : tnode;
  1455. filepos : tfileposinfo;
  1456. begin
  1457. first:=nil;
  1458. last:=nil;
  1459. filepos:=current_tokenpos;
  1460. consume(starttoken);
  1461. while not((token=_END) or (token=_FINALIZATION)) do
  1462. begin
  1463. if first=nil then
  1464. begin
  1465. last:=cstatementnode.create(statement,nil);
  1466. first:=last;
  1467. end
  1468. else
  1469. begin
  1470. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  1471. last:=tstatementnode(last).right;
  1472. end;
  1473. if ((token=_END) or (token=_FINALIZATION)) then
  1474. break
  1475. else
  1476. begin
  1477. { if no semicolon, then error and go on }
  1478. if token<>_SEMICOLON then
  1479. begin
  1480. consume(_SEMICOLON);
  1481. consume_all_until(_SEMICOLON);
  1482. end;
  1483. consume(_SEMICOLON);
  1484. end;
  1485. consume_emptystats;
  1486. end;
  1487. { don't consume the finalization token, it is consumed when
  1488. reading the finalization block, but allow it only after
  1489. an initalization ! }
  1490. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1491. consume(_END);
  1492. last:=cblocknode.create(first);
  1493. last.fileinfo:=filepos;
  1494. statement_block:=last;
  1495. end;
  1496. function assembler_block : tnode;
  1497. var
  1498. p : tnode;
  1499. {$if not(defined(sparcgen)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1500. locals : longint;
  1501. {$endif not(defined(sparcgen)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1502. srsym : tsym;
  1503. begin
  1504. if parse_generic then
  1505. message(parser_e_no_assembler_in_generic);
  1506. { Rename the funcret so that recursive calls are possible }
  1507. if not is_void(current_procinfo.procdef.returndef) then
  1508. begin
  1509. srsym:=TSym(current_procinfo.procdef.localst.Find(current_procinfo.procdef.procsym.name));
  1510. if assigned(srsym) then
  1511. srsym.realname:='$hiddenresult';
  1512. end;
  1513. { delphi uses register calling for assembler methods }
  1514. if (m_delphi in current_settings.modeswitches) and
  1515. (po_assembler in current_procinfo.procdef.procoptions) and
  1516. not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
  1517. current_procinfo.procdef.proccalloption:=pocall_register;
  1518. { force the asm statement }
  1519. if token<>_ASM then
  1520. consume(_ASM);
  1521. include(current_procinfo.flags,pi_is_assembler);
  1522. p:=_asm_statement;
  1523. {$if not(defined(sparcgen)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1524. if (po_assembler in current_procinfo.procdef.procoptions) then
  1525. begin
  1526. { set the framepointer to esp for assembler functions when the
  1527. following conditions are met:
  1528. - if the are no local variables and parameters (except the allocated result)
  1529. - no reference to the result variable (refcount<=1)
  1530. - result is not stored as parameter
  1531. - target processor has optional frame pointer save
  1532. (vm, i386, vm only currently)
  1533. }
  1534. locals:=tabstractlocalsymtable(current_procinfo.procdef.parast).count_locals;
  1535. if (current_procinfo.procdef.localst.symtabletype=localsymtable) then
  1536. inc(locals,tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals);
  1537. if (locals=0) and
  1538. not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
  1539. (not assigned(current_procinfo.procdef.funcretsym) or
  1540. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
  1541. not (df_generic in current_procinfo.procdef.defoptions) and
  1542. not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1543. begin
  1544. { Only need to set the framepointer, the locals will
  1545. be inserted with the correct reference in tcgasmnode.pass_generate_code }
  1546. current_procinfo.framepointer:=NR_STACK_POINTER_REG;
  1547. end;
  1548. end;
  1549. {$endif not(defined(sparcgen)) and not(defined(arm)) and not(defined(avr)) not(defined(mipsel))}
  1550. { Flag the result as assigned when it is returned in a
  1551. register.
  1552. }
  1553. if assigned(current_procinfo.procdef.funcretsym) and
  1554. not (df_generic in current_procinfo.procdef.defoptions) and
  1555. (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1556. tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
  1557. { because the END is already read we need to get the
  1558. last_endtoken_filepos here (PFV) }
  1559. last_endtoken_filepos:=current_tokenpos;
  1560. assembler_block:=p;
  1561. end;
  1562. end.