psub.pas 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466
  1. {
  2. $Id$
  3. Copyright (c) 1998 by Florian Klaempfl, Daniel Mantione
  4. Does the parsing of the procedures/functions
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit psub;
  19. interface
  20. uses cobjects,symtable;
  21. const
  22. pd_global = $1; { directive must be global }
  23. pd_body = $2; { directive needs a body }
  24. pd_implemen = $4; { directive can be used implementation section }
  25. pd_interface = $8; { directive can be used interface section }
  26. pd_object = $10; { directive can be used object declaration }
  27. pd_procvar = $20; { directive can be used procvar declaration }
  28. procedure compile_proc_body(const proc_names:Tstringcontainer;
  29. make_global,parent_has_class:boolean);
  30. procedure parse_proc_head(options : word);
  31. procedure parse_proc_dec;
  32. procedure parse_var_proc_directives(var sym : ptypesym);
  33. procedure read_proc;
  34. implementation
  35. uses
  36. globtype,systems,tokens,
  37. strings,globals,verbose,comphook,files,
  38. scanner,aasm,tree,types,
  39. import,gendef,
  40. hcodegen,temp_gen,pass_1,pass_2
  41. {$ifdef GDB}
  42. ,gdb
  43. {$endif GDB}
  44. {$ifdef i386}
  45. ,i386,tgeni386
  46. {$ifndef NoOpt}
  47. ,aopt386
  48. {$endif}
  49. {$endif}
  50. {$ifdef m68k}
  51. ,m68k,tgen68k,cga68k
  52. {$endif}
  53. { parser specific stuff }
  54. ,pbase,pdecl,pexpr,pstatmnt
  55. ;
  56. var
  57. realname:string; { contains the real name of a procedure as it's typed }
  58. procedure formal_parameter_list;
  59. {
  60. handle_procvar needs the same changes
  61. }
  62. var
  63. sc : Pstringcontainer;
  64. s : string;
  65. filepos : tfileposinfo;
  66. p : Pdef;
  67. vs : Pvarsym;
  68. {$ifdef VALUEPARA}
  69. l : longint;
  70. {$endif}
  71. hs1,hs2 : string;
  72. varspez : Tvarspez;
  73. begin
  74. consume(LKLAMMER);
  75. inc(testcurobject);
  76. repeat
  77. case token of
  78. _VAR : begin
  79. consume(_VAR);
  80. varspez:=vs_var;
  81. end;
  82. _CONST : begin
  83. consume(_CONST);
  84. varspez:=vs_const;
  85. end;
  86. else
  87. varspez:=vs_value;
  88. end;
  89. { read identifiers }
  90. sc:=idlist;
  91. { read type declaration, force reading for value and const paras }
  92. if (token=COLON) or (varspez=vs_value) then
  93. begin
  94. consume(COLON);
  95. { check for an open array }
  96. if token=_ARRAY then
  97. begin
  98. consume(_ARRAY);
  99. consume(_OF);
  100. { define range and type of range }
  101. p:=new(Parraydef,init(0,-1,s32bitdef));
  102. { array of const ? }
  103. if (token=_CONST) and (m_objpas in aktmodeswitches) then
  104. begin
  105. consume(_CONST);
  106. srsym:=nil;
  107. if assigned(objpasunit) then
  108. getsymonlyin(objpasunit,'TVARREC');
  109. if not assigned(srsym) then
  110. InternalError(1234124);
  111. Parraydef(p)^.definition:=ptypesym(srsym)^.definition;
  112. Parraydef(p)^.IsArrayOfConst:=true;
  113. hs1:='array_of_const';
  114. end
  115. else
  116. begin
  117. { define field type }
  118. Parraydef(p)^.definition:=single_type(hs1);
  119. hs1:='array_of_'+hs1;
  120. end;
  121. end
  122. { open string ? }
  123. else if ((token=_STRING) or (idtoken=_SHORTSTRING)) and
  124. (varspez=vs_var) and
  125. (cs_openstring in aktmoduleswitches) and
  126. not(cs_ansistrings in aktlocalswitches) then
  127. begin
  128. consume(token);
  129. p:=openshortstringdef;
  130. hs1:='openstring';
  131. end
  132. { everything else }
  133. else
  134. p:=single_type(hs1);
  135. end
  136. else
  137. begin
  138. {$ifndef UseNiceNames}
  139. hs1:='$$$';
  140. {$else UseNiceNames}
  141. hs1:='var';
  142. {$endif UseNiceNames}
  143. p:=new(Pformaldef,init);
  144. end;
  145. hs2:=aktprocsym^.definition^.mangledname;
  146. while not sc^.empty do
  147. begin
  148. s:=sc^.get_with_tokeninfo(filepos);
  149. aktprocsym^.definition^.concatdef(p,varspez);
  150. {$ifndef UseNiceNames}
  151. hs2:=hs2+'$'+hs1;
  152. {$else UseNiceNames}
  153. hs2:=hs2+tostr(length(hs1))+hs1;
  154. {$endif UseNiceNames}
  155. vs:=new(Pvarsym,init(s,p));
  156. vs^.fileinfo:=filepos;
  157. vs^.varspez:=varspez;
  158. { we have to add this to avoid var param to be in registers !!!}
  159. {$ifndef VALUEPARA}
  160. if (varspez in [vs_var,vs_const]) and dont_copy_const_param(p) then
  161. vs^.var_options := vs^.var_options or vo_regable;
  162. { search for duplicate ids in object members/methods }
  163. { but only the current class, I don't know why ... }
  164. { at least TP and Delphi do it in that way (FK) }
  165. if assigned(procinfo._class) and (lexlevel=normal_function_level) and
  166. (procinfo._class^.publicsyms^.search(vs^.name)<>nil) then
  167. { (search_class_member(procinfo._class,vs^.name)<>nil) then }
  168. Message1(sym_e_duplicate_id,vs^.name);
  169. aktprocsym^.definition^.parast^.insert(vs);
  170. {$else}
  171. if (varspez in [vs_var,vs_const]) and push_addr_param(p) then
  172. vs^.var_options := vs^.var_options or vo_regable;
  173. { search for duplicate ids in object members/methods }
  174. { but only the current class, I don't know why ... }
  175. { at least TP and Delphi do it in that way (FK) }
  176. if assigned(procinfo._class) and (lexlevel=normal_function_level) and
  177. (procinfo._class^.publicsyms^.search(vs^.name)<>nil) then
  178. { (search_class_member(procinfo._class,vs^.name)<>nil) then }
  179. Message1(sym_e_duplicate_id,vs^.name);
  180. { when it is a value para and it needs a local copy then rename
  181. the parameter and insert a copy in the localst }
  182. if (varspez=vs_value) and push_addr_param(p) then
  183. begin
  184. vs^.islocalcopy:=true;
  185. aktprocsym^.definition^.localst^.insert(vs);
  186. vs^.is_valid:=1;
  187. l:=vs^.address; { save local address }
  188. vs:=new(Pvarsym,init('val'+s,p));
  189. vs^.fileinfo:=filepos;
  190. vs^.varspez:=varspez;
  191. vs^.localaddress:=l;
  192. aktprocsym^.definition^.parast^.insert(vs);
  193. end
  194. else
  195. aktprocsym^.definition^.parast^.insert(vs);
  196. {$endif}
  197. end;
  198. dispose(sc,done);
  199. aktprocsym^.definition^.setmangledname(hs2);
  200. if token=SEMICOLON then
  201. consume(SEMICOLON)
  202. else
  203. break;
  204. until false;
  205. dec(testcurobject);
  206. consume(RKLAMMER);
  207. end;
  208. procedure parse_proc_head(options : word);
  209. var sp:stringid;
  210. pd:Pprocdef;
  211. paramoffset:longint;
  212. sym:Psym;
  213. hs:string;
  214. overloaded_level:word;
  215. realfilepos : tfileposinfo;
  216. begin
  217. if (options and pooperator) <> 0 then
  218. begin
  219. sp:=overloaded_names[optoken];
  220. realname:=sp;
  221. end
  222. else
  223. begin
  224. sp:=pattern;
  225. realname:=orgpattern;
  226. realfilepos:=aktfilepos;
  227. consume(ID);
  228. end;
  229. { method ? }
  230. if (token=POINT) and not(parse_only) then
  231. begin
  232. consume(POINT);
  233. getsym(sp,true);
  234. sym:=srsym;
  235. { qualifier is class name ? }
  236. if (sym^.typ<>typesym) or
  237. (ptypesym(sym)^.definition^.deftype<>objectdef) then
  238. begin
  239. Message(parser_e_class_id_expected);
  240. aktprocsym:=nil;
  241. consume(ID);
  242. end
  243. else
  244. begin
  245. { used to allow private syms to be seen }
  246. aktobjectdef:=pobjectdef(ptypesym(sym)^.definition);
  247. sp:=pattern;
  248. realname:=orgpattern;
  249. consume(ID);
  250. procinfo._class:=pobjectdef(ptypesym(sym)^.definition);
  251. aktprocsym:=pprocsym(procinfo._class^.publicsyms^.search(sp));
  252. aktobjectdef:=nil;
  253. { we solve this below }
  254. if not(assigned(aktprocsym)) then
  255. Message(parser_e_methode_id_expected);
  256. end;
  257. end
  258. else
  259. begin
  260. { check for constructor/destructor which is not allowed here }
  261. if (not parse_only) and
  262. ((options and (poconstructor or podestructor))<>0) then
  263. Message(parser_e_constructors_always_objects);
  264. aktprocsym:=pprocsym(symtablestack^.search(sp));
  265. if lexlevel=normal_function_level then
  266. {$ifdef UseNiceNames}
  267. hs:=procprefix+'_'+tostr(length(sp))+sp
  268. {$else UseNiceNames}
  269. hs:=procprefix+'_'+sp
  270. {$endif UseNiceNames}
  271. else
  272. {$ifdef UseNiceNames}
  273. hs:=lowercase(procprefix)+'_'+tostr(length(sp))+sp;
  274. {$else UseNiceNames}
  275. hs:=procprefix+'_$'+sp;
  276. {$endif UseNiceNames}
  277. if not(parse_only) then
  278. begin
  279. {The procedure we prepare for is in the implementation
  280. part of the unit we compile. It is also possible that we
  281. are compiling a program, which is also some kind of
  282. implementaion part.
  283. We need to find out if the procedure is global. If it is
  284. global, it is in the global symtable.}
  285. if not assigned(aktprocsym) then
  286. begin
  287. {Search the procedure in the global symtable.}
  288. aktprocsym:=Pprocsym(search_a_symtable(sp,globalsymtable));
  289. if assigned(aktprocsym) then
  290. begin
  291. {Check if it is a procedure.}
  292. if aktprocsym^.typ<>procsym then
  293. Message1(sym_e_duplicate_id,aktprocsym^.Name);
  294. {The procedure has been found. So it is
  295. a global one. Set the flags to mark this.}
  296. procinfo.flags:=procinfo.flags or pi_is_global;
  297. end;
  298. end;
  299. end;
  300. end;
  301. { problem with procedures inside methods }
  302. {$ifndef UseNiceNames}
  303. if assigned(procinfo._class) then
  304. if (pos('_$$_',procprefix)=0) then
  305. hs:=procprefix+'_$$_'+procinfo._class^.name^+'_'+sp
  306. else
  307. hs:=procprefix+'_$'+sp;
  308. {$else UseNiceNames}
  309. if assigned(procinfo._class) then
  310. if (pos('_5Class_',procprefix)=0) then
  311. hs:=procprefix+'_5Class_'+procinfo._class^.name^+'_'+tostr(length(sp))+sp
  312. else
  313. hs:=procprefix+'_'+tostr(length(sp))+sp;
  314. {$endif UseNiceNames}
  315. if assigned(aktprocsym) then
  316. begin
  317. { Check if overloading is enabled }
  318. if not(m_fpc in aktmodeswitches) then
  319. begin
  320. if aktprocsym^.typ<>procsym then
  321. begin
  322. Message1(sym_e_duplicate_id,aktprocsym^.name);
  323. { try to recover by creating a new aktprocsym }
  324. aktprocsym:=new(pprocsym,init(sp));
  325. end
  326. else
  327. begin
  328. if not(aktprocsym^.definition^.forwarddef) then
  329. Message(parser_e_procedure_overloading_is_off);
  330. end;
  331. end
  332. else
  333. begin
  334. { Check if the overloaded sym is realy a procsym }
  335. if aktprocsym^.typ<>procsym then
  336. begin
  337. Message1(parser_e_overloaded_no_procedure,aktprocsym^.name);
  338. { try to recover by creating a new aktprocsym }
  339. aktprocsym:=new(pprocsym,init(sp));
  340. end;
  341. end;
  342. end
  343. else
  344. begin
  345. { create a new procsym and set the real filepos }
  346. aktprocsym:=new(pprocsym,init(sp));
  347. aktprocsym^.fileinfo:=realfilepos;
  348. { for operator we have only one definition for each overloaded
  349. operation }
  350. if ((options and pooperator) <> 0) then
  351. begin
  352. { the only problem is that nextoverloaded might not be in a unit
  353. known for the unit itself }
  354. if assigned(overloaded_operators[optoken]) then
  355. aktprocsym^.definition:=overloaded_operators[optoken]^.definition;
  356. end;
  357. symtablestack^.insert(aktprocsym);
  358. end;
  359. { create a new procdef }
  360. pd:=new(pprocdef,init);
  361. if assigned(procinfo._class) then
  362. pd^._class := procinfo._class;
  363. { set the options from the caller (podestructor or poconstructor) }
  364. pd^.options:=pd^.options or options;
  365. { calculate the offset of the parameters }
  366. paramoffset:=8;
  367. { calculate frame pointer offset }
  368. if lexlevel>normal_function_level then
  369. begin
  370. procinfo.framepointer_offset:=paramoffset;
  371. inc(paramoffset,target_os.size_of_pointer);
  372. end;
  373. if assigned (Procinfo._Class) and not(procinfo._class^.isclass) and
  374. (((pd^.options and poconstructor)<>0) or ((pd^.options and podestructor)<>0)) then
  375. inc(paramoffset,target_os.size_of_pointer);
  376. { self pointer offset }
  377. { self isn't pushed in nested procedure of methods }
  378. if assigned(procinfo._class) and (lexlevel=normal_function_level) then
  379. begin
  380. procinfo.ESI_offset:=paramoffset;
  381. inc(paramoffset,target_os.size_of_pointer);
  382. end;
  383. procinfo.call_offset:=paramoffset;
  384. pd^.parast^.datasize:=0;
  385. pd^.nextoverloaded:=aktprocsym^.definition;
  386. aktprocsym^.definition:=pd;
  387. aktprocsym^.definition^.setmangledname(hs);
  388. overloaded_level:=1;
  389. if assigned(pd^.nextoverloaded) and
  390. (pd^.nextoverloaded^.owner^.symtabletype in [globalsymtable,staticsymtable]) then
  391. begin
  392. { we need another procprefix !!! }
  393. { count, but only those in the same unit !!}
  394. while assigned(pd^.nextoverloaded) and
  395. (pd^.nextoverloaded^.owner^.symtabletype in [globalsymtable,staticsymtable]) do
  396. begin
  397. { only count already implemented functions }
  398. if not(pd^.forwarddef) then
  399. inc(overloaded_level);
  400. pd:=pd^.nextoverloaded;
  401. end;
  402. end;
  403. if not parse_only then
  404. procprefix:=hs+'$'+tostr(overloaded_level)+'$';
  405. if token=LKLAMMER then
  406. formal_parameter_list;
  407. if ((options and pooperator)<>0) {and (overloaded_operators[optoken]=nil) } then
  408. overloaded_operators[optoken]:=aktprocsym;
  409. end;
  410. procedure parse_proc_dec;
  411. var
  412. hs : string;
  413. isclassmethod : boolean;
  414. begin
  415. inc(lexlevel);
  416. { read class method }
  417. if token=_CLASS then
  418. begin
  419. consume(_CLASS);
  420. isclassmethod:=true;
  421. end
  422. else
  423. isclassmethod:=false;
  424. case token of
  425. _FUNCTION : begin
  426. consume(_FUNCTION);
  427. parse_proc_head(0);
  428. if token<>COLON then
  429. begin
  430. if not(aktprocsym^.definition^.forwarddef) and
  431. not(m_repeat_forward in aktmodeswitches) then
  432. begin
  433. consume(COLON);
  434. consume_all_until(SEMICOLON);
  435. end;
  436. end
  437. else
  438. begin
  439. consume(COLON);
  440. aktprocsym^.definition^.retdef:=single_type(hs);
  441. aktprocsym^.definition^.test_if_fpu_result;
  442. end;
  443. end;
  444. _PROCEDURE : begin
  445. consume(_PROCEDURE);
  446. parse_proc_head(0);
  447. aktprocsym^.definition^.retdef:=voiddef;
  448. end;
  449. _CONSTRUCTOR : begin
  450. consume(_CONSTRUCTOR);
  451. parse_proc_head(poconstructor);
  452. if (procinfo._class^.options and oo_is_class)<>0 then
  453. begin
  454. { CLASS constructors return the created instance }
  455. aktprocsym^.definition^.retdef:=procinfo._class;
  456. end
  457. else
  458. begin
  459. { OBJECT constructors return a boolean }
  460. {$IfDef GDB}
  461. { GDB doesn't like unnamed types !}
  462. aktprocsym^.definition^.retdef:=globaldef('boolean');
  463. {$Else GDB}
  464. aktprocsym^.definition^.retdef:=new(porddef,init(bool8bit,0,1));
  465. {$Endif GDB}
  466. end;
  467. end;
  468. _DESTRUCTOR : begin
  469. consume(_DESTRUCTOR);
  470. parse_proc_head(podestructor);
  471. aktprocsym^.definition^.retdef:=voiddef;
  472. end;
  473. _OPERATOR : begin
  474. if lexlevel>normal_function_level then
  475. Message(parser_e_no_local_operator);
  476. consume(_OPERATOR);
  477. if not(token in [PLUS..last_overloaded]) then
  478. Message(parser_e_overload_operator_failed);
  479. optoken:=token;
  480. consume(Token);
  481. procinfo.flags:=procinfo.flags or pi_operator;
  482. parse_proc_head(pooperator);
  483. if token<>ID then
  484. consume(ID)
  485. else
  486. begin
  487. opsym:=new(pvarsym,init(pattern,voiddef));
  488. consume(ID);
  489. end;
  490. if token<>COLON then
  491. begin
  492. consume(COLON);
  493. aktprocsym^.definition^.retdef:=generrordef;
  494. consume_all_until(SEMICOLON);
  495. end
  496. else
  497. begin
  498. consume(COLON);
  499. aktprocsym^.definition^.retdef:=
  500. single_type(hs);
  501. aktprocsym^.definition^.test_if_fpu_result;
  502. if (optoken in [EQUAL,GT,LT,GTE,LTE]) and
  503. ((aktprocsym^.definition^.retdef^.deftype<>
  504. orddef) or (porddef(aktprocsym^.definition^.
  505. retdef)^.typ<>bool8bit)) then
  506. Message(parser_e_comparative_operator_return_boolean);
  507. opsym^.definition:=aktprocsym^.definition^.retdef;
  508. end;
  509. end;
  510. end;
  511. if isclassmethod and
  512. assigned(aktprocsym) then
  513. aktprocsym^.definition^.options:=aktprocsym^.definition^.options or poclassmethod;
  514. consume(SEMICOLON);
  515. dec(lexlevel);
  516. end;
  517. {****************************************************************************
  518. Procedure directive handlers
  519. ****************************************************************************}
  520. {$ifdef tp}
  521. {$F+}
  522. {$endif}
  523. procedure pd_far(const procnames:Tstringcontainer);
  524. begin
  525. Message(parser_w_proc_far_ignored);
  526. end;
  527. procedure pd_near(const procnames:Tstringcontainer);
  528. begin
  529. Message(parser_w_proc_near_ignored);
  530. end;
  531. procedure pd_export(const procnames:Tstringcontainer);
  532. begin
  533. procnames.insert(realname);
  534. procinfo.exported:=true;
  535. if cs_link_deffile in aktglobalswitches then
  536. deffile.AddExport(aktprocsym^.definition^.mangledname);
  537. if assigned(procinfo._class) then
  538. Message(parser_e_methods_dont_be_export);
  539. if lexlevel<>normal_function_level then
  540. Message(parser_e_dont_nest_export);
  541. end;
  542. procedure pd_inline(const procnames:Tstringcontainer);
  543. begin
  544. if not(cs_support_inline in aktmoduleswitches) then
  545. Message(parser_e_proc_inline_not_supported);
  546. end;
  547. procedure pd_forward(const procnames:Tstringcontainer);
  548. begin
  549. aktprocsym^.definition^.forwarddef:=true;
  550. aktprocsym^.properties:=aktprocsym^.properties or sp_forwarddef;
  551. end;
  552. procedure pd_stdcall(const procnames:Tstringcontainer);
  553. begin
  554. end;
  555. procedure pd_alias(const procnames:Tstringcontainer);
  556. begin
  557. consume(COLON);
  558. procnames.insert(get_stringconst);
  559. end;
  560. procedure pd_asmname(const procnames:Tstringcontainer);
  561. begin
  562. aktprocsym^.definition^.setmangledname(target_os.Cprefix+pattern);
  563. if token=CCHAR then
  564. consume(CCHAR)
  565. else
  566. consume(CSTRING);
  567. { we don't need anything else }
  568. aktprocsym^.definition^.forwarddef:=false;
  569. end;
  570. procedure pd_intern(const procnames:Tstringcontainer);
  571. begin
  572. consume(COLON);
  573. aktprocsym^.definition^.extnumber:=get_intconst;
  574. end;
  575. procedure pd_system(const procnames:Tstringcontainer);
  576. begin
  577. aktprocsym^.definition^.setmangledname(realname);
  578. end;
  579. procedure pd_cdecl(const procnames:Tstringcontainer);
  580. begin
  581. if aktprocsym^.definition^.deftype<>procvardef then
  582. aktprocsym^.definition^.setmangledname(target_os.Cprefix+realname);
  583. end;
  584. procedure pd_register(const procnames:Tstringcontainer);
  585. begin
  586. Message(parser_w_proc_register_ignored);
  587. end;
  588. procedure pd_syscall(const procnames:Tstringcontainer);
  589. begin
  590. aktprocsym^.definition^.options:=aktprocsym^.definition^.options or poclearstack;
  591. aktprocsym^.definition^.forwarddef:=false;
  592. aktprocsym^.definition^.extnumber:=get_intconst;
  593. end;
  594. procedure pd_external(const procnames:Tstringcontainer);
  595. {
  596. If import_dll=nil the procedure is assumed to be in another
  597. object file. In that object file it should have the name to
  598. which import_name is pointing to. Otherwise, the procedure is
  599. assumed to be in the DLL to which import_dll is pointing to. In
  600. that case either import_nr<>0 or import_name<>nil is true, so
  601. the procedure is either imported by number or by name. (DM)
  602. }
  603. var
  604. import_dll,
  605. import_name : string;
  606. import_nr : word;
  607. begin
  608. aktprocsym^.definition^.forwarddef:=false;
  609. { If the procedure should be imported from a DLL, a constant string follows.
  610. This isn't really correct, an contant string expression follows
  611. so we check if an semicolon follows, else a string constant have to
  612. follow (FK) }
  613. import_nr:=0;
  614. import_name:='';
  615. if not(token=SEMICOLON) and not(idtoken=_NAME) then
  616. begin
  617. import_dll:=get_stringconst;
  618. if (idtoken=_NAME) then
  619. begin
  620. consume(_NAME);
  621. import_name:=get_stringconst;
  622. end;
  623. if (idtoken=_INDEX) then
  624. begin
  625. {After the word index follows the index number in the DLL.}
  626. consume(_INDEX);
  627. import_nr:=get_intconst;
  628. end;
  629. if (import_nr=0) and (import_name='') then
  630. Message(parser_w_empty_import_name);
  631. if not(current_module^.uses_imports) then
  632. begin
  633. current_module^.uses_imports:=true;
  634. importlib^.preparelib(current_module^.modulename^);
  635. end;
  636. importlib^.importprocedure(aktprocsym^.mangledname,import_dll,import_nr,import_name)
  637. end
  638. else
  639. begin
  640. if (idtoken=_NAME) then
  641. begin
  642. consume(_NAME);
  643. aktprocsym^.definition^.setmangledname(get_stringconst);
  644. end
  645. else
  646. begin
  647. { external shouldn't override the cdecl/system name }
  648. if (aktprocsym^.definition^.options and poclearstack)=0 then
  649. aktprocsym^.definition^.setmangledname(aktprocsym^.name);
  650. externals^.concat(new(pai_external,init(aktprocsym^.mangledname,EXT_NEAR)));
  651. end;
  652. end;
  653. end;
  654. {$ifdef TP}
  655. {$F-}
  656. {$endif}
  657. function parse_proc_direc(const name:string;const proc_names:Tstringcontainer;var pdflags:word):boolean;
  658. {
  659. Parse the procedure directive, returns true if a correct directive is found
  660. }
  661. const
  662. namelength=15;
  663. type
  664. pd_handler=procedure(const procnames:Tstringcontainer);
  665. proc_dir_rec=record
  666. name : string[namelength]; {15 letters should be enough.}
  667. handler : pd_handler; {Handler.}
  668. flag : longint; {Procedure flag. May be zero}
  669. pd_flags : longint; {Parse options}
  670. mut_excl : longint; {List of mutually exclusive flags.}
  671. end;
  672. const
  673. {Should contain the number of procedure directives we support.}
  674. num_proc_directives=21;
  675. {Should contain the largest power of 2 lower than
  676. num_proc_directives, the int value of the 2-log of it. Cannot be
  677. calculated using an constant expression, as far as I know.}
  678. num_proc_directives_2log=16;
  679. proc_direcdata:array[1..num_proc_directives] of proc_dir_rec=
  680. ((name:'ALIAS' ;handler:{$ifdef FPC}@{$endif}pd_alias;
  681. flag:0 ;pd_flags:pd_implemen+pd_body;
  682. mut_excl:poinline+poexternal),
  683. (name:'ASMNAME' ;handler:{$ifdef FPC}@{$endif}pd_asmname;
  684. flag:pocdecl+poclearstack+poexternal;pd_flags:pd_interface+pd_implemen;
  685. mut_excl:pointernproc+poexternal),
  686. (name:'ASSEMBLER' ;handler:nil;
  687. flag:poassembler ;pd_flags:pd_implemen+pd_body;
  688. mut_excl:pointernproc+poexternal),
  689. (name:'CDECL' ;handler:{$ifdef FPC}@{$endif}pd_cdecl;
  690. flag:pocdecl+poclearstack;pd_flags:pd_interface+pd_implemen+pd_body+pd_procvar;
  691. mut_excl:poleftright+poinline+poassembler+pointernproc+poexternal),
  692. (name:'EXPORT' ;handler:{$ifdef FPC}@{$endif}pd_export;
  693. flag:poexports ;pd_flags:pd_body+pd_global+pd_interface+pd_implemen{??};
  694. mut_excl:poexternal+poinline+pointernproc+pointerrupt),
  695. (name:'EXTERNAL' ;handler:{$ifdef FPC}@{$endif}pd_external;
  696. flag:poexternal ;pd_flags:pd_implemen;
  697. mut_excl:poexports+poinline+pointernproc+pointerrupt+poassembler+popalmossyscall),
  698. (name:'FAR' ;handler:{$ifdef FPC}@{$endif}pd_far;
  699. flag:0 ;pd_flags:pd_implemen+pd_body+pd_interface+pd_procvar;
  700. mut_excl:pointernproc),
  701. (name:'FORWARD' ;handler:{$ifdef FPC}@{$endif}pd_forward;
  702. flag:0 ;pd_flags:pd_implemen;
  703. mut_excl:pointernproc+poexternal),
  704. (name:'INLINE' ;handler:{$ifdef FPC}@{$endif}pd_inline;
  705. flag:poinline ;pd_flags:pd_implemen+pd_body;
  706. mut_excl:poexports+poexternal+pointernproc+pointerrupt+poconstructor+podestructor),
  707. (name:'INTERNCONST';handler:{$ifdef FPC}@{$endif}pd_intern;
  708. flag:pointernconst;pd_flags:pd_implemen+pd_body;
  709. mut_excl:pointernproc+pooperator),
  710. (name:'INTERNPROC';handler:{$ifdef FPC}@{$endif}pd_intern;
  711. flag:pointernproc ;pd_flags:pd_implemen;
  712. mut_excl:poexports+poexternal+pointerrupt+poassembler+poclearstack+poleftright+poiocheck+
  713. poconstructor+podestructor+pooperator),
  714. (name:'INTERRUPT' ;handler:nil;
  715. flag:pointerrupt ;pd_flags:pd_implemen+pd_body;
  716. mut_excl:pointernproc+poclearstack+poleftright+poinline+
  717. poconstructor+podestructor+pooperator+poexternal),
  718. (name:'IOCHECK' ;handler:nil;
  719. flag:poiocheck ;pd_flags:pd_implemen+pd_body;
  720. mut_excl:pointernproc+poexternal),
  721. (name:'NEAR' ;handler:{$ifdef FPC}@{$endif}pd_near;
  722. flag:0 ;pd_flags:pd_implemen+pd_body+pd_procvar;
  723. mut_excl:pointernproc),
  724. (name:'PASCAL' ;handler:nil;
  725. flag:poleftright ;pd_flags:pd_implemen+pd_body+pd_procvar;
  726. mut_excl:pointernproc+poexternal),
  727. (name:'POPSTACK' ;handler:nil;
  728. flag:poclearstack ;pd_flags:pd_interface+pd_implemen+pd_body+pd_procvar;
  729. mut_excl:poinline+pointernproc+poassembler+poexternal),
  730. (name:'PUBLIC' ;handler:nil;
  731. flag:0 ;pd_flags:pd_implemen+pd_body+pd_global;
  732. mut_excl:pointernproc+poinline+poexternal),
  733. (name:'REGISTER' ;handler:{$ifdef FPC}@{$endif}pd_register;
  734. flag:poregister ;pd_flags:pd_interface+pd_implemen+pd_body+pd_procvar;
  735. mut_excl:poleftright+pocdecl+pointernproc+poexternal),
  736. (name:'STDCALL' ;handler:{$ifdef FPC}@{$endif}pd_stdcall;
  737. flag:postdcall ;pd_flags:pd_interface+pd_implemen+pd_body+pd_procvar;
  738. mut_excl:poleftright+pocdecl+pointernproc+poinline+poexternal),
  739. (name:'SYSCALL' ;handler:{$ifdef FPC}@{$endif}pd_syscall;
  740. flag:popalmossyscall;pd_flags:pd_interface;
  741. mut_excl:poexports+poinline+pointernproc+pointerrupt+poassembler+poexternal),
  742. (name:'SYSTEM' ;handler:{$ifdef FPC}@{$endif}pd_system;
  743. flag:poclearstack ;pd_flags:pd_implemen;
  744. mut_excl:poleftright+poinline+poassembler+pointernproc+poexternal));
  745. var
  746. p,w : longint;
  747. begin
  748. parse_proc_direc:=false;
  749. { Search the procedure directive in the array. We shoot with a bazooka
  750. on a bug, that is, we release a binary search }
  751. p:=1;
  752. if (length(name)<=namelength) then
  753. begin
  754. w:=num_proc_directives_2log;
  755. while w<>0 do
  756. begin
  757. if proc_direcdata[p+w].name<=name then
  758. inc(p,w);
  759. w:=w shr 1;
  760. while p+w>num_proc_directives do
  761. w:=w shr 1;
  762. end;
  763. end;
  764. { Check if the procedure directive is known }
  765. if name<>proc_direcdata[p].name then
  766. begin
  767. { parsing a procvar type the name can be any
  768. next variable !! }
  769. if (pdflags and pd_procvar)=0 then
  770. Message1(parser_w_unknown_proc_directive_ignored,name);
  771. exit;
  772. end;
  773. { consume directive, and turn flag on }
  774. consume(token);
  775. parse_proc_direc:=true;
  776. { Conflicts between directives ? }
  777. if (aktprocsym^.definition^.options and proc_direcdata[p].mut_excl)<>0 then
  778. begin
  779. Message1(parser_e_proc_dir_conflict,name);
  780. exit;
  781. end;
  782. { Check the pd_flags if the directive should be allowed }
  783. if ((pdflags and pd_interface)<>0) and
  784. ((proc_direcdata[p].pd_flags and pd_interface)=0) then
  785. begin
  786. Message1(parser_e_proc_dir_not_allowed_in_interface,name);
  787. exit;
  788. end;
  789. if ((pdflags and pd_implemen)<>0) and
  790. ((proc_direcdata[p].pd_flags and pd_implemen)=0) then
  791. begin
  792. Message1(parser_e_proc_dir_not_allowed_in_implementation,name);
  793. exit;
  794. end;
  795. if ((pdflags and pd_procvar)<>0) and
  796. ((proc_direcdata[p].pd_flags and pd_procvar)=0) then
  797. begin
  798. Message1(parser_e_proc_dir_not_allowed_in_procvar,name);
  799. exit;
  800. end;
  801. { Return the new pd_flags }
  802. if (proc_direcdata[p].pd_flags and pd_body)=0 then
  803. pdflags:=pdflags and (not pd_body);
  804. if (proc_direcdata[p].pd_flags and pd_global)<>0 then
  805. pdflags:=pdflags or pd_global;
  806. { Add the correct flag }
  807. aktprocsym^.definition^.options:=aktprocsym^.definition^.options or proc_direcdata[p].flag;
  808. { Call the handler }
  809. if pointer({$ifndef FPC}@{$endif}proc_direcdata[p].handler)<>nil then
  810. proc_direcdata[p].handler(proc_names);
  811. end;
  812. {***************************************************************************}
  813. function check_identical:boolean;
  814. {
  815. Search for idendical definitions,
  816. if there is a forward, then kill this.
  817. Returns the result of the forward check.
  818. Removed from unter_dec to keep the source readable
  819. }
  820. const
  821. {List of procedure options that affect the procedure type.}
  822. po_type_params=poconstructor+podestructor+pooperator;
  823. po_call_params=pocdecl+poclearstack+poleftright+poregister;
  824. var
  825. hd,pd : Pprocdef;
  826. storeparast : psymtable;
  827. ad,fd : psym;
  828. begin
  829. check_identical:=false;
  830. pd:=aktprocsym^.definition;
  831. if assigned(pd) then
  832. begin
  833. { Is there an overload/forward ? }
  834. if assigned(pd^.nextoverloaded) then
  835. begin
  836. { walk the procdef list }
  837. while (assigned(pd)) and (assigned(pd^.nextoverloaded)) do
  838. begin
  839. if not(m_repeat_forward in aktmodeswitches) or
  840. equal_paras(aktprocsym^.definition^.para1,pd^.nextoverloaded^.para1,false) then
  841. begin
  842. if pd^.nextoverloaded^.forwarddef then
  843. { remove the forward definition but don't delete it, }
  844. { the symtable is the owner !! }
  845. begin
  846. hd:=pd^.nextoverloaded;
  847. { Check if the procedure type and return type are correct }
  848. if ((hd^.options and po_type_params)<>(aktprocsym^.definition^.options and po_type_params)) or
  849. (not(is_equal(hd^.retdef,aktprocsym^.definition^.retdef)) and
  850. (m_repeat_forward in aktmodeswitches)) then
  851. begin
  852. Message1(parser_e_header_dont_match_forward,aktprocsym^.demangledName);
  853. exit;
  854. end;
  855. { Check calling convention }
  856. if ((hd^.options and po_call_params)<>(aktprocsym^.definition^.options and po_call_params)) then
  857. begin
  858. { only trigger a error, becuase it doesn't hurt }
  859. Message(parser_e_call_convention_dont_match_forward);
  860. end;
  861. { manglednames are equal? }
  862. if (m_repeat_forward in aktmodeswitches) or
  863. assigned(aktprocsym^.definition^.parast^.root) then
  864. if (hd^.mangledname<>aktprocsym^.definition^.mangledname) then
  865. begin
  866. if (aktprocsym^.definition^.options and poexternal)=0 then
  867. Message(parser_n_interface_name_diff_implementation_name);
  868. { reset the mangledname of the interface part to be sure }
  869. { this is wrong because the mangled name might have been used already !! }
  870. { hd^.setmangledname(aktprocsym^.definition^.mangledname);}
  871. { so we need to keep the name of interface !! }
  872. aktprocsym^.definition^.setmangledname(hd^.mangledname);
  873. end
  874. else
  875. begin
  876. { If mangled names are equal, therefore }
  877. { they have the same number of parameters }
  878. { Therefore we can check the name of these }
  879. { parameters... }
  880. if hd^.forwarddef and aktprocsym^.definition^.forwarddef then
  881. begin
  882. Message1(parser_e_function_already_declared_public_forward,aktprocsym^.demangledName);
  883. Check_identical:=true;
  884. { Remove other forward from the list to reduce errors }
  885. pd^.nextoverloaded:=pd^.nextoverloaded^.nextoverloaded;
  886. exit;
  887. end;
  888. ad:=hd^.parast^.root;
  889. fd:=aktprocsym^.definition^.parast^.root;
  890. if assigned(ad) and assigned(fd) then
  891. begin
  892. while assigned(ad) and assigned(fd) do
  893. begin
  894. if ad^.name<>fd^.name then
  895. begin
  896. Message3(parser_e_header_different_var_names,
  897. aktprocsym^.name,ad^.name,fd^.name);
  898. break;
  899. end;
  900. { it is impossible to have a nil pointer }
  901. { for only one parameter - since they }
  902. { have the same number of parameters. }
  903. { Left = next parameter. }
  904. ad:=ad^.left;
  905. fd:=fd^.left;
  906. end;
  907. end;
  908. end;
  909. { also the call_offset }
  910. hd^.parast^.call_offset:=aktprocsym^.definition^.parast^.call_offset;
  911. { remove pd^.nextoverloaded from the list }
  912. { and add aktprocsym^.definition }
  913. pd^.nextoverloaded:=pd^.nextoverloaded^.nextoverloaded;
  914. hd^.nextoverloaded:=aktprocsym^.definition^.nextoverloaded;
  915. { Alert! All fields of aktprocsym^.definition that are modified
  916. by the procdir handlers must be copied here!.}
  917. hd^.forwarddef:=false;
  918. hd^.options:=hd^.options or aktprocsym^.definition^.options;
  919. if aktprocsym^.definition^.extnumber=-1 then
  920. aktprocsym^.definition^.extnumber:=hd^.extnumber
  921. else
  922. if hd^.extnumber=-1 then
  923. hd^.extnumber:=aktprocsym^.definition^.extnumber;
  924. { switch parast for warning in implementation PM }
  925. if (m_repeat_forward in aktmodeswitches) or
  926. assigned(aktprocsym^.definition^.parast^.root) then
  927. begin
  928. storeparast:=hd^.parast;
  929. hd^.parast:=aktprocsym^.definition^.parast;
  930. aktprocsym^.definition^.parast:=storeparast;
  931. end;
  932. aktprocsym^.definition:=hd;
  933. check_identical:=true;
  934. end
  935. else
  936. { abstract methods aren't forward defined, but this }
  937. { needs another error message }
  938. if (pd^.nextoverloaded^.options and poabstractmethod)=0 then
  939. Message(parser_e_overloaded_have_same_parameters)
  940. else
  941. Message(parser_e_abstract_no_definition);
  942. break;
  943. end;
  944. pd:=pd^.nextoverloaded;
  945. end;
  946. end
  947. else
  948. begin
  949. { there is no overloaded, so its always identical with itself }
  950. check_identical:=true;
  951. end;
  952. end;
  953. { insert opsym only in the right symtable }
  954. if ((procinfo.flags and pi_operator)<>0) and not parse_only then
  955. begin
  956. if ret_in_param(aktprocsym^.definition^.retdef) then
  957. begin
  958. pprocdef(aktprocsym^.definition)^.parast^.insert(opsym);
  959. { this increases the data size }
  960. { correct this to get the right ret $value }
  961. dec(pprocdef(aktprocsym^.definition)^.parast^.datasize,opsym^.getsize);
  962. { this allows to read the funcretoffset }
  963. opsym^.address:=-4;
  964. opsym^.varspez:=vs_var;
  965. end
  966. else
  967. pprocdef(aktprocsym^.definition)^.localst^.insert(opsym);
  968. end;
  969. end;
  970. procedure compile_proc_body(const proc_names:Tstringcontainer;
  971. make_global,parent_has_class:boolean);
  972. {
  973. Compile the body of a procedure
  974. }
  975. var
  976. oldexitlabel,oldexit2label,oldquickexitlabel:Plabel;
  977. _class,hp:Pobjectdef;
  978. { switches can change inside the procedure }
  979. entryswitches, exitswitches : tlocalswitches;
  980. { code for the subroutine as tree }
  981. code:ptree;
  982. { size of the local strackframe }
  983. stackframe:longint;
  984. { true when no stackframe is required }
  985. nostackframe:boolean;
  986. { number of bytes which have to be cleared by RET }
  987. parasize:longint;
  988. { filepositions }
  989. entrypos,
  990. savepos,
  991. exitpos : tfileposinfo;
  992. begin
  993. { calculate the lexical level }
  994. inc(lexlevel);
  995. if lexlevel>32 then
  996. Message(parser_e_too_much_lexlevel);
  997. { save old labels }
  998. oldexitlabel:=aktexitlabel;
  999. oldexit2label:=aktexit2label;
  1000. oldquickexitlabel:=quickexitlabel;
  1001. { get new labels }
  1002. getlabel(aktexitlabel);
  1003. getlabel(aktexit2label);
  1004. { exit for fail in constructors }
  1005. if (aktprocsym^.definition^.options and poconstructor)<>0 then
  1006. getlabel(quickexitlabel);
  1007. { reset break and continue labels }
  1008. in_except_block:=false;
  1009. aktbreaklabel:=nil;
  1010. aktcontinuelabel:=nil;
  1011. { insert symtables for the class, by only if it is no nested function }
  1012. if assigned(procinfo._class) and not(parent_has_class) then
  1013. begin
  1014. { insert them in the reverse order ! }
  1015. hp:=nil;
  1016. repeat
  1017. _class:=procinfo._class;
  1018. while _class^.childof<>hp do
  1019. _class:=_class^.childof;
  1020. hp:=_class;
  1021. _class^.publicsyms^.next:=symtablestack;
  1022. symtablestack:=_class^.publicsyms;
  1023. until hp=procinfo._class;
  1024. end;
  1025. { insert parasymtable in symtablestack}
  1026. { only if lexlevel > 1 !!! global symtable should be right after staticsymtazble
  1027. for checking of same names used in interface and implementation !! }
  1028. if lexlevel>=normal_function_level then
  1029. begin
  1030. aktprocsym^.definition^.parast^.next:=symtablestack;
  1031. symtablestack:=aktprocsym^.definition^.parast;
  1032. symtablestack^.symtablelevel:=lexlevel;
  1033. end;
  1034. { insert localsymtable in symtablestack}
  1035. aktprocsym^.definition^.localst^.next:=symtablestack;
  1036. symtablestack:=aktprocsym^.definition^.localst;
  1037. symtablestack^.symtablelevel:=lexlevel;
  1038. { constant symbols are inserted in this symboltable }
  1039. constsymtable:=symtablestack;
  1040. { reset the temporary memory }
  1041. cleartempgen;
  1042. { no registers are used }
  1043. usedinproc:=0;
  1044. { save entry info }
  1045. entrypos:=aktfilepos;
  1046. entryswitches:=aktlocalswitches;
  1047. { parse the code ... }
  1048. if (aktprocsym^.definition^.options and poassembler)<> 0 then
  1049. code:=assembler_block
  1050. else
  1051. code:=block(current_module^.islibrary);
  1052. { get a better entry point }
  1053. if assigned(code) then
  1054. entrypos:=code^.fileinfo;
  1055. { save exit info }
  1056. exitswitches:=aktlocalswitches;
  1057. exitpos:=last_endtoken_filepos;
  1058. { save current filepos }
  1059. savepos:=aktfilepos;
  1060. {When we are called to compile the body of a unit, aktprocsym should
  1061. point to the unit initialization. If the unit has no initialization,
  1062. aktprocsym=nil. But in that case code=nil. hus we should check for
  1063. code=nil, when we use aktprocsym.}
  1064. { set the framepointer to esp for assembler functions }
  1065. { but only if the are no local variables }
  1066. { already done in assembler_block }
  1067. setfirsttemp(procinfo.firsttemp);
  1068. { ... and generate assembler }
  1069. { but set the right switches for entry !! }
  1070. aktlocalswitches:=entryswitches;
  1071. if assigned(code) then
  1072. generatecode(code);
  1073. { set switches to status at end of procedure }
  1074. aktlocalswitches:=exitswitches;
  1075. if assigned(code) then
  1076. begin
  1077. aktprocsym^.definition^.code:=code;
  1078. { the procedure is now defined }
  1079. aktprocsym^.definition^.forwarddef:=false;
  1080. aktprocsym^.definition^.usedregisters:=usedinproc;
  1081. end;
  1082. stackframe:=gettempsize;
  1083. { only now we can remove the temps }
  1084. resettempgen;
  1085. { first generate entry code with the correct position and switches }
  1086. aktfilepos:=entrypos;
  1087. aktlocalswitches:=entryswitches;
  1088. if assigned(code) then
  1089. genentrycode(procinfo.aktentrycode,proc_names,make_global,stackframe,parasize,nostackframe,false);
  1090. { now generate exit code with the correct position and switches }
  1091. aktfilepos:=exitpos;
  1092. aktlocalswitches:=exitswitches;
  1093. if assigned(code) then
  1094. begin
  1095. genexitcode(procinfo.aktexitcode,parasize,nostackframe,false);
  1096. procinfo.aktproccode^.insertlist(procinfo.aktentrycode);
  1097. procinfo.aktproccode^.concatlist(procinfo.aktexitcode);
  1098. {$ifdef i386}
  1099. {$ifndef NoOpt}
  1100. if (cs_optimize in aktglobalswitches) and
  1101. { no asm block allowed }
  1102. ((procinfo.flags and pi_uses_asm)=0) then
  1103. Optimize(procinfo.aktproccode);
  1104. {$endif NoOpt}
  1105. {$endif}
  1106. { save local data (casetable) also in the same file }
  1107. if assigned(procinfo.aktlocaldata) and
  1108. (not procinfo.aktlocaldata^.empty) then
  1109. begin
  1110. procinfo.aktproccode^.concat(new(pai_section,init(sec_data)));
  1111. procinfo.aktproccode^.concatlist(procinfo.aktlocaldata);
  1112. end;
  1113. { now we can insert a cut }
  1114. if (cs_smartlink in aktmoduleswitches) then
  1115. codesegment^.concat(new(pai_cut,init));
  1116. { add the procedure to the codesegment }
  1117. codesegment^.concatlist(procinfo.aktproccode);
  1118. end;
  1119. { ... remove symbol tables, for the browser leave the static table }
  1120. { if (cs_browser in aktmoduleswitches) and (symtablestack^.symtabletype=staticsymtable) then
  1121. symtablestack^.next:=symtablestack^.next^.next
  1122. else }
  1123. if lexlevel>=normal_function_level then
  1124. symtablestack:=symtablestack^.next^.next
  1125. else
  1126. symtablestack:=symtablestack^.next;
  1127. { ... check for unused symbols }
  1128. { but only if there is no asm block }
  1129. if assigned(code) then
  1130. begin
  1131. if (status.errorcount=0) then
  1132. begin
  1133. aktprocsym^.definition^.localst^.check_forwards;
  1134. aktprocsym^.definition^.localst^.checklabels;
  1135. end;
  1136. if (procinfo.flags and pi_uses_asm)=0 then
  1137. begin
  1138. { not for unit init, becuase the var can be used in finalize,
  1139. it will be done in proc_unit }
  1140. if (aktprocsym^.definition^.options and (pounitinit or pounitfinalize))=0 then
  1141. aktprocsym^.definition^.localst^.allsymbolsused;
  1142. aktprocsym^.definition^.parast^.allsymbolsused;
  1143. end;
  1144. end;
  1145. { the local symtables can be deleted, but the parast }
  1146. { doesn't, (checking definitons when calling a }
  1147. { function }
  1148. { not for a inline procedure !! (PM) }
  1149. { at lexlevel = 1 localst is the staticsymtable itself }
  1150. { so no dispose here !! }
  1151. if assigned(code) and
  1152. not(cs_browser in aktmoduleswitches) and
  1153. ((aktprocsym^.definition^.options and poinline)=0) then
  1154. begin
  1155. if lexlevel>=normal_function_level then
  1156. dispose(aktprocsym^.definition^.localst,done);
  1157. aktprocsym^.definition^.localst:=nil;
  1158. end;
  1159. { remove code tree, if not inline procedure }
  1160. if assigned(code) and ((aktprocsym^.definition^.options and poinline)=0) then
  1161. disposetree(code);
  1162. { remove class member symbol tables }
  1163. while symtablestack^.symtabletype=objectsymtable do
  1164. symtablestack:=symtablestack^.next;
  1165. { restore filepos, the switches are already set }
  1166. aktfilepos:=savepos;
  1167. { free labels }
  1168. freelabel(aktexitlabel);
  1169. freelabel(aktexit2label);
  1170. if (aktprocsym^.definition^.options and poconstructor)<>0 then
  1171. freelabel(quickexitlabel);
  1172. { restore labels }
  1173. aktexitlabel:=oldexitlabel;
  1174. aktexit2label:=oldexit2label;
  1175. quickexitlabel:=oldquickexitlabel;
  1176. { previous lexlevel }
  1177. dec(lexlevel);
  1178. end;
  1179. procedure parse_proc_directives(Anames:Pstringcontainer;var pdflags:word);
  1180. {
  1181. Parse the procedure directives. It does not matter if procedure directives
  1182. are written using ;procdir; or ['procdir'] syntax.
  1183. }
  1184. var
  1185. name : string;
  1186. res : boolean;
  1187. begin
  1188. while token in [ID,LECKKLAMMER] do
  1189. begin
  1190. if token=LECKKLAMMER then
  1191. begin
  1192. consume(LECKKLAMMER);
  1193. repeat
  1194. name:=pattern;
  1195. { consume(ID);
  1196. now done in the function }
  1197. parse_proc_direc(name,Anames^,pdflags);
  1198. if token=COMMA then
  1199. consume(COMMA)
  1200. else
  1201. break;
  1202. until false;
  1203. consume(RECKKLAMMER);
  1204. { we always expect at least '[];' }
  1205. res:=true;
  1206. end
  1207. else
  1208. begin
  1209. name:=pattern;
  1210. res:=parse_proc_direc(name,Anames^,pdflags);
  1211. end;
  1212. { A procedure directive is always followed by a semicolon }
  1213. if res then
  1214. consume(SEMICOLON)
  1215. else
  1216. break;
  1217. end;
  1218. end;
  1219. procedure parse_var_proc_directives(var sym : ptypesym);
  1220. var
  1221. anames : pstringcontainer;
  1222. pdflags : word;
  1223. oldsym : pprocsym;
  1224. begin
  1225. oldsym:=aktprocsym;
  1226. anames:=new(pstringcontainer,init);
  1227. pdflags:=pd_procvar;
  1228. { we create a temporary aktprocsym to read the directives }
  1229. aktprocsym:=new(pprocsym,init(sym^.name));
  1230. aktprocsym^.definition:=pprocdef(sym^.definition);
  1231. { anmes should never be used anyway }
  1232. inc(lexlevel);
  1233. parse_proc_directives(anames,pdflags);
  1234. dec(lexlevel);
  1235. aktprocsym^.definition:=nil;
  1236. dispose(aktprocsym,done);
  1237. dispose(anames,done);
  1238. aktprocsym:=oldsym;
  1239. end;
  1240. procedure read_proc;
  1241. {
  1242. Parses the procedure directives, then parses the procedure body, then
  1243. generates the code for it
  1244. }
  1245. var
  1246. oldprefix : string;
  1247. oldprocsym : Pprocsym;
  1248. oldprocinfo : tprocinfo;
  1249. oldconstsymtable : Psymtable;
  1250. names : Pstringcontainer;
  1251. pdflags : word;
  1252. begin
  1253. { save old state }
  1254. oldprocsym:=aktprocsym;
  1255. oldprefix:=procprefix;
  1256. oldconstsymtable:=constsymtable;
  1257. oldprocinfo:=procinfo;
  1258. { create a new procedure }
  1259. new(names,init);
  1260. codegen_newprocedure;
  1261. with procinfo do
  1262. begin
  1263. parent:=@oldprocinfo;
  1264. { clear flags }
  1265. flags:=0;
  1266. { standard frame pointer }
  1267. framepointer:=frame_pointer;
  1268. funcret_is_valid:=false;
  1269. { is this a nested function of a method ? }
  1270. _class:=oldprocinfo._class;
  1271. end;
  1272. parse_proc_dec;
  1273. { set the default function options }
  1274. if parse_only then
  1275. begin
  1276. aktprocsym^.properties:=aktprocsym^.properties or sp_forwarddef;
  1277. aktprocsym^.definition^.forwarddef:=true;
  1278. pdflags:=pd_interface;
  1279. end
  1280. else
  1281. begin
  1282. pdflags:=pd_body;
  1283. if current_module^.in_implementation then
  1284. pdflags:=pdflags or pd_implemen;
  1285. if (not current_module^.is_unit) or (cs_smartlink in aktmoduleswitches) then
  1286. pdflags:=pdflags or pd_global;
  1287. procinfo.exported:=false;
  1288. aktprocsym^.definition^.forwarddef:=false;
  1289. end;
  1290. { parse the directives that may follow }
  1291. inc(lexlevel);
  1292. parse_proc_directives(names,pdflags);
  1293. dec(lexlevel);
  1294. { search for forward declarations }
  1295. if (not check_identical) then
  1296. begin
  1297. { A method must be forward defined (in the object declaration) }
  1298. if assigned(procinfo._class) and (not assigned(oldprocinfo._class)) then
  1299. Message(parser_e_header_dont_match_any_member);
  1300. { check the global flag }
  1301. if (procinfo.flags and pi_is_global)<>0 then
  1302. Message(parser_e_overloaded_must_be_all_global);
  1303. end;
  1304. { set return type here, becuase the aktprocsym^.definition can be
  1305. changed by check_identical (PFV) }
  1306. procinfo.retdef:=aktprocsym^.definition^.retdef;
  1307. { pointer to the return value ? }
  1308. if ret_in_param(procinfo.retdef) then
  1309. begin
  1310. procinfo.retoffset:=procinfo.call_offset;
  1311. inc(procinfo.call_offset,target_os.size_of_pointer);
  1312. end;
  1313. { allows to access the parameters of main functions in nested functions }
  1314. aktprocsym^.definition^.parast^.call_offset:=procinfo.call_offset;
  1315. { compile procedure when a body is needed }
  1316. if (pdflags and pd_body)<>0 then
  1317. begin
  1318. Message1(parser_p_procedure_start,aktprocsym^.demangledname);
  1319. names^.insert(aktprocsym^.definition^.mangledname);
  1320. { set _FAIL as keyword if constructor }
  1321. if (aktprocsym^.definition^.options and poconstructor)<>0 then
  1322. tokeninfo[_FAIL].keyword:=m_all;
  1323. if assigned(aktprocsym^.definition^._class) then
  1324. tokeninfo[_SELF].keyword:=m_all;
  1325. compile_proc_body(names^,((pdflags and pd_global)<>0),assigned(oldprocinfo._class));
  1326. { reset _FAIL as normal }
  1327. if (aktprocsym^.definition^.options and poconstructor)<>0 then
  1328. tokeninfo[_FAIL].keyword:=m_none;
  1329. if assigned(aktprocsym^.definition^._class) and (lexlevel=main_program_level) then
  1330. tokeninfo[_SELF].keyword:=m_none;
  1331. consume(SEMICOLON);
  1332. end;
  1333. { close }
  1334. dispose(names,done);
  1335. codegen_doneprocedure;
  1336. { Restore old state }
  1337. constsymtable:=oldconstsymtable;
  1338. aktprocsym:=oldprocsym;
  1339. procprefix:=oldprefix;
  1340. procinfo:=oldprocinfo;
  1341. opsym:=nil;
  1342. end;
  1343. end.
  1344. {
  1345. $Log$
  1346. Revision 1.1 1998-12-26 15:20:31 florian
  1347. + more changes for the new version
  1348. }