psub.pas 49 KB

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