psub.pas 48 KB

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