pmodules.pas 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  1. {
  2. $Id$
  3. Copyright (c) 1998 by Florian Klaempfl
  4. Handles the parsing and loading of the modules (ppufiles)
  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 pmodules;
  19. interface
  20. uses
  21. dos,strings,
  22. cobjects,globals,scanner,symtable,aasm,tree,pass_1,
  23. types,hcodegen,files,verbose,systems,link,assemble
  24. {$ifdef GDB}
  25. ,gdb
  26. {$endif GDB}
  27. { parser specific stuff }
  28. ,pbase,pdecl,pstatmnt,psub
  29. { processor specific stuff }
  30. {$ifdef i386}
  31. ,i386
  32. ,cgai386
  33. ,tgeni386
  34. ,cgi386
  35. ,aopt386
  36. {$endif}
  37. {$ifdef m68k}
  38. ,m68k
  39. ,cga68k
  40. ,tgen68k
  41. ,cg68k
  42. {$endif}
  43. ;
  44. function loadunit(const s : string;compile_system, in_uses : boolean) : pmodule;
  45. procedure proc_unit;
  46. procedure proc_program(islibrary : boolean);
  47. implementation
  48. uses
  49. parser;
  50. {$I innr.inc}
  51. procedure insertinternsyms(p : psymtable);
  52. begin
  53. p^.insert(new(psyssym,init('CONCAT',in_concat_x)));
  54. p^.insert(new(psyssym,init('WRITE',in_write_x)));
  55. p^.insert(new(psyssym,init('WRITELN',in_writeln_x)));
  56. p^.insert(new(psyssym,init('ASSIGNED',in_assigned_x)));
  57. p^.insert(new(psyssym,init('READ',in_read_x)));
  58. p^.insert(new(psyssym,init('READLN',in_readln_x)));
  59. p^.insert(new(psyssym,init('OFS',in_ofs_x)));
  60. p^.insert(new(psyssym,init('SIZEOF',in_sizeof_x)));
  61. p^.insert(new(psyssym,init('TYPEOF',in_typeof_x)));
  62. p^.insert(new(psyssym,init('LOW',in_low_x)));
  63. p^.insert(new(psyssym,init('HIGH',in_high_x)));
  64. p^.insert(new(psyssym,init('SEG',in_seg_x)));
  65. p^.insert(new(psyssym,init('ORD',in_ord_x)));
  66. p^.insert(new(psyssym,init('PRED',in_pred_x)));
  67. p^.insert(new(psyssym,init('SUCC',in_succ_x)));
  68. { for testing purpose }
  69. p^.insert(new(psyssym,init('DECI',in_dec_x)));
  70. p^.insert(new(psyssym,init('INCI',in_inc_x)));
  71. p^.insert(new(psyssym,init('STR',in_str_x_string)));
  72. end;
  73. procedure load_ppu(hp : pmodule;compile_system : boolean);
  74. var
  75. loaded_unit : pmodule;
  76. b : byte;
  77. checksum,
  78. count,
  79. nextmapentry : longint;
  80. hs : string;
  81. begin
  82. { init the map }
  83. new(hp^.map);
  84. nextmapentry:=1;
  85. { load the used units from interface }
  86. hp^.ppufile^.read_data(b,1,count);
  87. while (b=ibloadunit) do
  88. begin
  89. { read unit name }
  90. hp^.ppufile^.read_data(hs[0],1,count);
  91. hp^.ppufile^.read_data(hs[1],byte(hs[0]),count);
  92. hp^.ppufile^.read_data(checksum,4,count);
  93. loaded_unit:=loadunit(hs,false,false);
  94. if hp^.compiled then
  95. exit;
  96. { if the crc of a used unit is the same as }
  97. { written to the PPU file, we needn't to }
  98. { recompile the current unit }
  99. if (loaded_unit^.crc<>checksum) or
  100. (do_build and loaded_unit^.sources_avail) then
  101. begin
  102. { we have to compile the current unit }
  103. { remove stuff which isn't needed }
  104. { forget the map }
  105. dispose(hp^.map);
  106. hp^.map:=nil;
  107. hp^.ppufile^.close;
  108. dispose(hp^.ppufile,done);
  109. hp^.ppufile:=nil;
  110. compile(hp^.mainsource^,compile_system);
  111. exit;
  112. end;
  113. { setup the map entry for deref }
  114. hp^.map^[nextmapentry]:=loaded_unit^.symtable;
  115. inc(nextmapentry);
  116. if nextmapentry>maxunits then
  117. Message(unit_f_too_much_units);
  118. { read until ibend }
  119. hp^.ppufile^.read_data(b,1,count);
  120. end;
  121. { ok, now load the unit }
  122. hp^.symtable:=new(punitsymtable,load(hp^.unitname^));
  123. { if this is the system unit insert the intern }
  124. { symbols }
  125. if compile_system then
  126. insertinternsyms(psymtable(hp^.symtable));
  127. { now only read the implementation part }
  128. hp^.in_implementation:=true;
  129. { load the used units from implementation }
  130. hp^.ppufile^.read_data(b,1,count);
  131. while (b<>ibend) and (b=ibloadunit) do
  132. begin
  133. { read unit name }
  134. hp^.ppufile^.read_data(hs[0],1,count);
  135. hp^.ppufile^.read_data(hs[1],byte(hs[0]),count);
  136. hp^.ppufile^.read_data(checksum,4,count);
  137. loaded_unit:=loadunit(hs,false,false);
  138. if hp^.compiled then exit;
  139. { if the crc of a used unit is the same as }
  140. { written to the PPU file, we needn't to }
  141. { recompile the current unit }
  142. { but for the implementation part }
  143. { the written crc is false, because }
  144. { not defined when writing the ppufile !! }
  145. if {(loaded_unit^.crc<>checksum) or}
  146. (do_build and loaded_unit^.sources_avail) then
  147. begin
  148. { we have to compile the current unit }
  149. { remove stuff which isn't needed }
  150. { forget the map }
  151. dispose(hp^.map);
  152. hp^.map:=nil;
  153. hp^.ppufile^.close;
  154. dispose(hp^.ppufile,done);
  155. hp^.ppufile:=nil;
  156. compile(hp^.mainsource^,compile_system);
  157. exit;
  158. end;
  159. { read until ibend }
  160. hp^.ppufile^.read_data(b,1,count);
  161. end;
  162. hp^.ppufile^.close;
  163. dispose(hp^.map);
  164. hp^.map:=nil;
  165. end;
  166. function loadunit(const s : string;compile_system, in_uses : boolean) : pmodule;
  167. var
  168. st : punitsymtable;
  169. old_current_module,hp,nextmodule : pmodule;
  170. pu : pused_unit;
  171. a : pasmfile;
  172. hs : pstring;
  173. begin
  174. old_current_module:=current_module;
  175. { be sure not to mix lines from different files }
  176. { update_line; }
  177. { unit not found }
  178. st:=nil;
  179. { search all loaded units }
  180. hp:=pmodule(loaded_units.first);
  181. while assigned(hp) do
  182. begin
  183. if hp^.unitname^=s then
  184. begin
  185. { the unit is already registered }
  186. { and this means that the unit }
  187. { is already compiled }
  188. { else there is a cyclic unit use }
  189. if assigned(hp^.symtable) then
  190. st:=punitsymtable(hp^.symtable)
  191. else
  192. begin
  193. { recompile the unit ? }
  194. if (not current_module^.in_implementation) and (hp^.in_implementation) then
  195. Message(unit_f_circular_unit_reference);
  196. end;
  197. break;
  198. end;
  199. { the next unit }
  200. hp:=pmodule(hp^.next);
  201. end;
  202. { no error and the unit isn't loaded }
  203. if not(assigned(hp)) and (st=nil) then
  204. begin
  205. { generates a new unit info record }
  206. hp:=new(pmodule,init(s,true));
  207. { now we can register the unit }
  208. loaded_units.insert(hp);
  209. current_module:=hp;
  210. { force build ? }
  211. if (hp^.do_compile) or (hp^.sources_avail and do_build) then
  212. begin
  213. { we needn't the ppufile }
  214. if assigned(hp^.ppufile) then
  215. begin
  216. dispose(hp^.ppufile,done);
  217. hp^.ppufile:=nil;
  218. end;
  219. if not(hp^.sources_avail) then
  220. Message1(unit_f_cant_compile_unit,hp^.unitname^)
  221. else
  222. compile(hp^.mainsource^,compile_system);
  223. end
  224. else
  225. begin
  226. { only reassemble ? }
  227. if (hp^.do_assemble) then
  228. begin
  229. a:=new(PAsmFile,Init(hp^.asmfilename^));
  230. a^.DoAssemble;
  231. dispose(a,Done);
  232. end;
  233. { we should know there the PPU file else it's an error and
  234. we can't load the unit }
  235. if hp^.ppufile^.name^<>'' then
  236. begin
  237. if (hp^.flags and uf_in_library)=0 then
  238. Linker.AddObjectFile(hp^.objfilename^);
  239. load_ppu(hp,compile_system);
  240. end;
  241. end;
  242. { register the unit _once_ }
  243. usedunits.concat(new(pused_unit,init(hp,0)));
  244. { the unit is written, so we can set the symtable type }
  245. { to unitsymtable, else we get some dupid errors }
  246. { this is not the right place because of the }
  247. { ready label }
  248. { psymtable(hp^.symtable)^.symtabletype:=unitsymtable; }
  249. { placed at this end of proc_unit }
  250. psymtable(hp^.symtable)^.unitid:=0;
  251. { reset the unitnumbers for the other units }
  252. pu:=pused_unit(old_current_module^.used_units.first);
  253. while assigned(pu) do
  254. begin
  255. psymtable(pu^.u^.symtable)^.unitid:=pu^.unitid;
  256. pu:=pused_unit(pu^.next);
  257. end;
  258. end
  259. else
  260. if assigned(hp) and (st=nil) then
  261. begin
  262. { we have to compile the unit again, but it is already inserted !!}
  263. { we may have problem with the lost symtable !! }
  264. current_module:=hp;
  265. { we must preserve the unit chain }
  266. nextmodule:=pmodule(hp^.next);
  267. { we have to cleanup a little }
  268. hp^.special_done;
  269. new(hs);
  270. hs^:=hp^.mainsource^;
  271. hp^.init(hs^,true);
  272. dispose(hs);
  273. { we must preserve the unit chain }
  274. hp^.next:=nextmodule;
  275. if assigned(hp^.ppufile) then
  276. load_ppu(hp,compile_system)
  277. else
  278. begin
  279. Message1(parser_d_compiling_second_time,hp^.mainsource^);
  280. compile(hp^.mainsource^,compile_system);
  281. end;
  282. current_module^.compiled:=true;
  283. end;
  284. { set the old module }
  285. current_module:=old_current_module;
  286. { the current module uses the unit hp }
  287. current_module^.used_units.concat(new(pused_unit,init(hp,0)));
  288. pused_unit(current_module^.used_units.last)^.in_uses:=in_uses;
  289. if in_uses and not current_module^.in_implementation then
  290. pused_unit(current_module^.used_units.last)^.in_interface:=true;
  291. loadunit:=hp;
  292. end;
  293. procedure loadunits;
  294. var
  295. s : stringid;
  296. hp : pused_unit;
  297. hp2 : pmodule;
  298. hp3 : psymtable;
  299. oldprocsym:Pprocsym;
  300. begin
  301. oldprocsym:=aktprocsym;
  302. consume(_USES);
  303. {$ifdef DEBUG}
  304. test_symtablestack;
  305. {$endif DEBUG}
  306. repeat
  307. s:=pattern;
  308. consume(ID);
  309. hp2:=loadunit(s,false,true);
  310. if current_module^.compiled then
  311. exit;
  312. refsymtable^.insert(new(punitsym,init(s,hp2^.symtable)));
  313. if token=COMMA then
  314. begin
  315. pattern:='';
  316. consume(COMMA);
  317. end
  318. else
  319. break;
  320. until false;
  321. consume(SEMICOLON);
  322. { now insert the units in the symtablestack }
  323. hp:=pused_unit(current_module^.used_units.first);
  324. { set the symtable to systemunit so it gets reorderd correctly }
  325. symtablestack:=systemunit;
  326. while assigned(hp) do
  327. begin
  328. {$IfDef GDB}
  329. if (cs_debuginfo in aktswitches) and
  330. not hp^.is_stab_written then
  331. begin
  332. punitsymtable(hp^.u^.symtable)^.concattypestabto(debuglist);
  333. hp^.is_stab_written:=true;
  334. hp^.unitid:=psymtable(hp^.u^.symtable)^.unitid;
  335. end;
  336. {$EndIf GDB}
  337. if hp^.in_uses then
  338. begin
  339. hp3:=symtablestack;
  340. while assigned(hp3) do
  341. begin
  342. { insert units only once ! }
  343. if hp^.u^.symtable=hp3 then
  344. break;
  345. hp3:=hp3^.next;
  346. { unit isn't inserted }
  347. if hp3=nil then
  348. begin
  349. psymtable(hp^.u^.symtable)^.next:=symtablestack;
  350. symtablestack:=psymtable(hp^.u^.symtable);
  351. {$ifdef CHAINPROCSYMS}
  352. symtablestack^.chainprocsyms;
  353. {$endif CHAINPROCSYMS}
  354. {$ifdef DEBUG}
  355. test_symtablestack;
  356. {$endif DEBUG}
  357. end;
  358. end;
  359. end;
  360. hp:=pused_unit(hp^.next);
  361. end;
  362. aktprocsym:=oldprocsym;
  363. end;
  364. procedure parse_uses(symt:Psymtable);
  365. begin
  366. if token=_USES then
  367. begin
  368. current_module^.in_implementation:=true;
  369. symt^.symtabletype:=unitsymtable;
  370. loadunits;
  371. symt^.symtabletype:=globalsymtable;
  372. {$ifdef DEBUG}
  373. test_symtablestack;
  374. {$endif DEBUG}
  375. end;
  376. end;
  377. procedure proc_unit;
  378. var
  379. unitname : stringid;
  380. {$ifdef GDB}
  381. { several defs to simulate more or less C++ objects for GDB }
  382. vmtdef : precdef;
  383. pvmtdef : ppointerdef;
  384. vmtarraydef : parraydef;
  385. vmtsymtable : psymtable;
  386. {$endif GDB}
  387. names:Tstringcontainer;
  388. p : psymtable;
  389. unitst : punitsymtable;
  390. pu : pused_unit;
  391. { the output ppufile is written to this path }
  392. s1,s2,s3:^string; {Saves stack space, but only eats heap
  393. space when there is a lot of heap free.}
  394. begin
  395. consume(_UNIT);
  396. stringdispose(current_module^.objfilename);
  397. stringdispose(current_module^.ppufilename);
  398. { create filenames and check unit name }
  399. new(s1);
  400. new(s2);
  401. new(s3);
  402. s1^:=FixFileName(current_module^.current_inputfile^.path^+current_module^.current_inputfile^.name^);
  403. current_module^.objfilename:=stringdup(s1^+target_info.objext);
  404. current_module^.ppufilename:=stringdup(s1^+target_info.unitext);
  405. s1^:=upper(pattern);
  406. s2^:=upper(target_info.system_unit);
  407. s3^:=upper(current_module^.current_inputfile^.name^);
  408. if (cs_compilesystem in aktswitches) then
  409. begin
  410. if (cs_check_unit_name in aktswitches) and
  411. ((length(pattern)>8) or (s1^<>s2^) or (s1^<>s3^)) then
  412. Message1(unit_e_illegal_unit_name,s1^);
  413. end
  414. else
  415. if (s1^=s2^) then
  416. Message(unit_w_switch_us_missed);
  417. dispose(s3);
  418. dispose(s2);
  419. dispose(s1);
  420. { add object }
  421. Linker.AddObjectFile(current_module^.objfilename^);
  422. unitname:=pattern;
  423. consume(ID);
  424. consume(SEMICOLON);
  425. consume(_INTERFACE);
  426. { this should be placed after uses !!}
  427. {$ifndef UseNiceNames}
  428. procprefix:='_'+unitname+'$$';
  429. {$else UseNiceNames}
  430. procprefix:='_'+tostr(length(unitname))+lowercase(unitname)+'_';
  431. {$endif UseNiceNames}
  432. parse_only:=true;
  433. { generate now the global symboltable }
  434. p:=new(punitsymtable,init(globalsymtable,unitname));
  435. refsymtable:=p;
  436. unitst:=punitsymtable(p);
  437. { set the symbol table for the current unit }
  438. { this must be set later for interdependency }
  439. { current_module^.symtable:=psymtable(p); }
  440. { a unit compiled at command line must be inside the loaded_unit list }
  441. if (compile_level=1) then
  442. begin
  443. current_module^.unitname:=stringdup(unitname);
  444. loaded_units.insert(current_module);
  445. if cs_unit_to_lib in initswitches then
  446. begin
  447. current_module^.flags:=current_module^.flags or uf_in_library;
  448. if cs_shared_lib in initswitches then
  449. current_module^.flags:=current_module^.flags or uf_shared_library;
  450. end;
  451. end;
  452. { insert qualifier for the system unit (allows system.writeln) }
  453. if not(cs_compilesystem in aktswitches) then
  454. begin
  455. { insert the system unit }
  456. { it is allways the first }
  457. systemunit^.next:=nil;
  458. symtablestack:=systemunit;
  459. refsymtable^.insert(new(punitsym,init('SYSTEM',systemunit)));
  460. if token=_USES then
  461. begin
  462. unitst^.symtabletype:=unitsymtable;
  463. loadunits;
  464. { has it been compiled at a higher level ?}
  465. if current_module^.compiled then
  466. exit;
  467. unitst^.symtabletype:=globalsymtable;
  468. end;
  469. { ... but insert the symbol table later }
  470. p^.next:=symtablestack;
  471. symtablestack:=p;
  472. end
  473. else
  474. { while compiling a system unit, some types are directly inserted }
  475. begin
  476. p^.next:=symtablestack;
  477. symtablestack:=p;
  478. p^.insert(new(ptypesym,init('longint',s32bitdef)));
  479. p^.insert(new(ptypesym,init('ulong',u32bitdef)));
  480. p^.insert(new(ptypesym,init('void',voiddef)));
  481. p^.insert(new(ptypesym,init('char',cchardef)));
  482. {$ifdef i386}
  483. p^.insert(new(ptypesym,init('s64real',c64floatdef)));
  484. {$endif i386}
  485. p^.insert(new(ptypesym,init('s80real',s80floatdef)));
  486. p^.insert(new(ptypesym,init('cs32fixed',s32fixeddef)));
  487. p^.insert(new(ptypesym,init('byte',u8bitdef)));
  488. p^.insert(new(ptypesym,init('string',cstringdef)));
  489. p^.insert(new(ptypesym,init('word',u16bitdef)));
  490. p^.insert(new(ptypesym,init('boolean',booldef)));
  491. p^.insert(new(ptypesym,init('void_pointer',voidpointerdef)));
  492. p^.insert(new(ptypesym,init('file',cfiledef)));
  493. {$ifdef i386}
  494. p^.insert(new(ptypesym,init('REAL',new(pfloatdef,init(s64real)))));
  495. p^.insert(new(ptypesym,init('COMP',new(pfloatdef,init(s64bit)))));
  496. p^.insert(new(ptypesym,init('EXTENDED',new(pfloatdef,init(s80real)))));
  497. {$endif}
  498. {$ifdef m68k}
  499. { internal definitions }
  500. p^.insert(new(ptypesym,init('s32real',c64floatdef)));
  501. { mappings... }
  502. p^.insert(new(ptypesym,init('REAL',new(pfloatdef,init(s32real)))));
  503. if (cs_fp_emulation) in aktswitches then
  504. p^.insert(new(ptypesym,init('DOUBLE',new(pfloatdef,init(s32real)))))
  505. else
  506. p^.insert(new(ptypesym,init('DOUBLE',new(pfloatdef,init(s64real)))));
  507. { p^.insert(new(ptypesym,init('COMP',new(pfloatdef,init(s32real)))));}
  508. if (cs_fp_emulation) in aktswitches then
  509. p^.insert(new(ptypesym,init('EXTENDED',new(pfloatdef,init(s32real)))))
  510. else
  511. p^.insert(new(ptypesym,init('EXTENDED',new(pfloatdef,init(s80real)))));
  512. {$endif}
  513. p^.insert(new(ptypesym,init('SINGLE',new(pfloatdef,init(s32real)))));
  514. p^.insert(new(ptypesym,init('POINTER',new(ppointerdef,init(voiddef)))));
  515. p^.insert(new(ptypesym,init('STRING',cstringdef)));
  516. p^.insert(new(ptypesym,init('BOOLEAN',new(porddef,init(bool8bit,0,1)))));
  517. p^.insert(new(ptypesym,init('CHAR',new(porddef,init(uchar,0,255)))));
  518. p^.insert(new(ptypesym,init('TEXT',new(pfiledef,init(ft_text,nil)))));
  519. p^.insert(new(ptypesym,init('CARDINAL',new(porddef,init(u32bit,0,$ffffffff)))));
  520. p^.insert(new(ptypesym,init('FIXED',new(pfloatdef,init(f32bit)))));
  521. p^.insert(new(ptypesym,init('FIXED16',new(pfloatdef,init(f16bit)))));
  522. p^.insert(new(ptypesym,init('TYPEDFILE',new(pfiledef,init(ft_typed,voiddef)))));
  523. { !!!!!
  524. p^.insert(new(ptypesym,init('COMP',new(porddef,init(s64bit,0,0)))));
  525. p^.insert(new(ptypesym,init('SINGLE',new(porddef,init(s32real,0,0)))));
  526. p^.insert(new(ptypesym,init('EXTENDED',new(porddef,init(s80real,0,0)))));
  527. p^.insert(new(ptypesym,init('FILE',new(pfiledef,init(ft_untyped,nil)))));
  528. }
  529. { Add a type for virtual method tables in lowercase }
  530. { so it isn't reachable! }
  531. {$ifdef GDB}
  532. vmtsymtable:=new(psymtable,init(recordsymtable));
  533. vmtdef:=new(precdef,init(vmtsymtable));
  534. pvmtdef:=new(ppointerdef,init(vmtdef));
  535. vmtsymtable^.insert(new(pvarsym,init('parent',pvmtdef)));
  536. vmtsymtable^.insert(new(pvarsym,init('length',globaldef('longint'))));
  537. vmtsymtable^.insert(new(pvarsym,init('mlength',globaldef('longint'))));
  538. vmtarraydef:=new(parraydef,init(0,1,s32bitdef));
  539. vmtarraydef^.definition := voidpointerdef;
  540. vmtsymtable^.insert(new(pvarsym,init('__pfn',vmtarraydef)));
  541. p^.insert(new(ptypesym,init('__vtbl_ptr_type',vmtdef)));
  542. p^.insert(new(ptypesym,init('pvmt',pvmtdef)));
  543. vmtarraydef:=new(parraydef,init(0,1,s32bitdef));
  544. vmtarraydef^.definition := pvmtdef;
  545. p^.insert(new(ptypesym,init('vtblarray',vmtarraydef)));
  546. insertinternsyms(p);
  547. {$endif GDB}
  548. end;
  549. { displaced for inter-dependency considerations }
  550. current_module^.symtable:=psymtable(p);
  551. constsymtable:=symtablestack;
  552. { ... parse the declarations }
  553. read_interface_declarations;
  554. consume(_IMPLEMENTATION);
  555. parse_only:=false;
  556. refsymtable^.number_defs;
  557. {$ifdef GDB}
  558. { add all used definitions even for implementation}
  559. if (cs_debuginfo in aktswitches) then
  560. begin
  561. { all types }
  562. punitsymtable(refsymtable)^.concattypestabto(debuglist);
  563. { and all local symbols}
  564. refsymtable^.concatstabto(debuglist);
  565. end;
  566. {$endif GDB}
  567. { for interdependent units
  568. the crc is included in the ppufile
  569. but it is not known when writing the first ppufile
  570. so I tried to add a fake writing of the ppu
  571. just to get the CRC
  572. but the result is different for the real CRC
  573. it calculates after, I don't know why
  574. Answer:
  575. -------
  576. When reading the interface part, the compiler assumes
  577. that all registers are modified by a procedure
  578. usedinproc:=$ff !
  579. If the definition is read, the compiler determines
  580. the used registers and write the correct value
  581. to usedinproc
  582. only_calculate_crc:=true;
  583. writeunitas(current_module^.current_inputfile^.path^+current_module^.current_inputfile^.name^+
  584. +'.PPS',punitsymtable(symtablestack));
  585. only_calculate_crc:=false;
  586. }
  587. { generates static symbol table }
  588. p:=new(punitsymtable,init(staticsymtable,unitname));
  589. refsymtable:=p;
  590. {Generate a procsym.}
  591. aktprocsym:=new(Pprocsym,init(unitname+'_init'));
  592. aktprocsym^.definition:=new(Pprocdef,init);
  593. aktprocsym^.definition^.options:=aktprocsym^.definition^.options or pounitinit;
  594. aktprocsym^.definition^.setmangledname(unitname+'_init');
  595. {The generated procsym has a local symtable. Discard it and turn
  596. it into the static one.}
  597. dispose(aktprocsym^.definition^.localst,done);
  598. aktprocsym^.definition^.localst:=p;
  599. names.init;
  600. names.insert(unitname+'_init');
  601. { testing !!!!!!!!! }
  602. { we set the interface part as a unitsymtable }
  603. { for the case we need to compile another unit }
  604. { remove the globalsymtable from the symtable stack }
  605. { to reinsert it after loading the implementation units }
  606. symtablestack:=unitst^.next;
  607. parse_uses(unitst);
  608. { duplicated here to be sure }
  609. {$ifndef UseNiceNames}
  610. procprefix:='_'+unitname+'$$';
  611. {$else UseNiceNames}
  612. procprefix:='_'+tostr(length(unitname))+lowercase(unitname)+'_';
  613. {$endif UseNiceNames}
  614. { but reinsert the global symtable as lasts }
  615. unitst^.next:=symtablestack;
  616. symtablestack:=unitst;
  617. {$ifdef DEBUG}
  618. test_symtablestack;
  619. {$endif DEBUG}
  620. constsymtable:=symtablestack;
  621. {$ifdef Splitheap}
  622. if testsplit then
  623. begin
  624. Split_Heap;
  625. allow_special:=true;
  626. Switch_to_temp_heap;
  627. end;
  628. {$endif Splitheap}
  629. {$ifdef Splitheap}
  630. { it will report all crossings }
  631. allow_special:=false;
  632. {$endif Splitheap}
  633. { set some informations }
  634. procinfo.retdef:=voiddef;
  635. procinfo._class:=nil;
  636. procinfo.call_offset:=8;
  637. { for temporary values }
  638. procinfo.framepointer:=frame_pointer;
  639. { clear flags }
  640. procinfo.flags:=0;
  641. {Reset the codegenerator.}
  642. codegen_newprocedure;
  643. names.insert('INIT$$'+unitname);
  644. compile_proc_body(names,true,false);
  645. codegen_doneprocedure;
  646. consume(POINT);
  647. names.done;
  648. { size of the static data }
  649. datasize:=symtablestack^.datasize;
  650. { unsed static symbols ? }
  651. symtablestack^.allsymbolsused;
  652. {$ifdef GDB}
  653. { add all used definitions even for implementation}
  654. if (cs_debuginfo in aktswitches) then
  655. begin
  656. { all types }
  657. punitsymtable(symtablestack)^.concattypestabto(debuglist);
  658. { and all local symbols}
  659. symtablestack^.concatstabto(debuglist);
  660. end;
  661. {$endif GDB}
  662. current_module^.in_implementation:=false;
  663. { deletes all symtables generated in the implementation part }
  664. while symtablestack^.symtabletype<>globalsymtable do
  665. dellexlevel;
  666. { tests, if all forwards are resolved }
  667. symtablestack^.check_forwards;
  668. symtablestack^.symtabletype:=unitsymtable;
  669. punitsymtable(symtablestack)^.is_stab_written:=false;
  670. {Write out the unit if the compile was succesfull.}
  671. if errorcount=0 then
  672. writeunitas(current_module^.ppufilename^,punitsymtable(symtablestack));
  673. pu:=pused_unit(usedunits.first);
  674. while assigned(pu) do
  675. begin
  676. punitsymtable(pu^.u^.symtable)^.is_stab_written:=false;
  677. pu:=pused_unit(pu^.next);
  678. end;
  679. inc(datasize,symtablestack^.datasize);
  680. end;
  681. procedure proc_program(islibrary : boolean);
  682. var
  683. i : longint;
  684. st : psymtable;
  685. programname : stringid;
  686. names:Tstringcontainer;
  687. begin
  688. { Trying to compile the system unit... }
  689. { if no unit defined... then issue a }
  690. { fatal error (avoids pointer problems)}
  691. { when referencing the non-existant }
  692. { system unit. }
  693. if (cs_compilesystem in aktswitches) then
  694. Begin
  695. if token<>_UNIT then
  696. Message1(scan_f_syn_expected,'UNIT');
  697. consume(_UNIT);
  698. end;
  699. parse_only:=false;
  700. programname:='';
  701. if islibrary then
  702. begin
  703. consume(_LIBRARY);
  704. programname:=pattern;
  705. consume(ID);
  706. consume(SEMICOLON);
  707. end
  708. else
  709. { is there an program head ? }
  710. if token=_PROGRAM then
  711. begin
  712. consume(_PROGRAM);
  713. programname:=pattern;
  714. consume(ID);
  715. if token=LKLAMMER then
  716. begin
  717. consume(LKLAMMER);
  718. idlist;
  719. consume(RKLAMMER);
  720. end;
  721. consume(SEMICOLON);
  722. end;
  723. { insert after the unit symbol tables the static symbol table }
  724. { of the program }
  725. st:=new(punitsymtable,init(staticsymtable,programname));
  726. {Generate a procsym.}
  727. aktprocsym:=new(Pprocsym,init('main'));
  728. aktprocsym^.definition:=new(Pprocdef,init);
  729. aktprocsym^.definition^.options:=aktprocsym^.definition^.options or poproginit;
  730. aktprocsym^.definition^.setmangledname(target_info.Cprefix+'main');
  731. {The localst is a local symtable. Change it into the static
  732. symtable.}
  733. dispose(aktprocsym^.definition^.localst,done);
  734. aktprocsym^.definition^.localst:=st;
  735. names.init;
  736. names.insert('program_init');
  737. refsymtable:=st;
  738. {Insert the symbols of the system unit into the stack of symbol
  739. tables.}
  740. symtablestack:=systemunit;
  741. systemunit^.next:=nil;
  742. refsymtable^.insert(new(punitsym,init('SYSTEM',systemunit)));
  743. {Load the units used by the program we compile.}
  744. if token=_USES then loadunits;
  745. {Insert the name of the main program into the symbol table.}
  746. if programname<>'' then
  747. st^.insert(new(pprogramsym,init(programname)));
  748. { ...is also constsymtable, this is the symtable where }
  749. { the elements of enumeration types are inserted }
  750. constsymtable:=st;
  751. codegen_newprocedure;
  752. { set some informations about the main program }
  753. procinfo.retdef:=voiddef;
  754. procinfo._class:=nil;
  755. procinfo.call_offset:=8;
  756. {Set the framepointer of the program initialization to the
  757. default framepointer (EBP on i386).}
  758. procinfo.framepointer:=frame_pointer;
  759. { clear flags }
  760. procinfo.flags:=0;
  761. procprefix:='';
  762. in_except_block:=false;
  763. {The program intialization needs an alias, so it can be called
  764. from the bootstrap code.}
  765. case target_info.target of
  766. target_GO32V1,
  767. target_GO32V2,
  768. target_OS2,
  769. target_WIN32:
  770. names.insert('_main');
  771. target_LINUX:
  772. names.insert('main');
  773. end;
  774. names.insert('PASCALMAIN');
  775. compile_proc_body(names,true,false);
  776. codegen_doneprocedure;
  777. Linker.AddObjectFile(current_module^.unitname^);
  778. current_module^.linkofiles.insert(current_module^.unitname^);
  779. { On the Macintosh Classic M68k Architecture }
  780. { The Heap variable is simply a POINTER to the }
  781. { real HEAP. The HEAP must be set up by the RTL }
  782. { and must store the pointer in this value. }
  783. {On OS/2 the heap is also intialized by the RTL. We do
  784. not output a pointer.}
  785. if target_info.target<>target_OS2 then
  786. if (target_info.target = target_MAC68k) then
  787. bsssegment^.concat(new(pai_datablock,init_global('HEAP',4)))
  788. else
  789. bsssegment^.concat(new(pai_datablock,init_global('HEAP',heapsize)));
  790. if target_info.target=target_GO32V2 then
  791. begin
  792. { stacksize can be specified }
  793. datasegment^.concat(new(pai_symbol,init_global('__stklen')));
  794. datasegment^.concat(new(pai_const,init_32bit(stacksize)));
  795. end;
  796. if (target_info.target=target_WIN32) then
  797. begin
  798. { generate the last entry for the imports directory }
  799. if not(assigned(importssection)) then
  800. importssection:=new(paasmoutput,init);
  801. { $3 ensure that it is the last entry, all other entries }
  802. { are written to $2 }
  803. importssection^.concat(new(pai_section,init('.idata$3')));
  804. for i:=1 to 5 do
  805. importssection^.concat(new(pai_const,init_32bit(0)));
  806. end;
  807. {I prefer starting with a heapsize of 256K in OS/2. The heap can
  808. grow later until the size specified on the command line. Allocating
  809. four megs at once can hurt performance when more programs are in
  810. memory.}
  811. datasegment^.concat(new(pai_symbol,init_global('HEAPSIZE')));
  812. if target_info.target=target_OS2 then
  813. heapsize:=256*1024;
  814. datasegment^.concat(new(pai_const,init_32bit(heapsize)));
  815. datasize:=symtablestack^.datasize;
  816. names.done;
  817. consume(POINT);
  818. symtablestack^.check_forwards;
  819. symtablestack^.allsymbolsused;
  820. end;
  821. end.
  822. {
  823. $Log$
  824. Revision 1.4 1998-04-10 14:41:43 peter
  825. * removed some Hints
  826. * small speed optimization for AsmLn
  827. Revision 1.3 1998/04/03 09:51:00 daniel
  828. * Fixed heap allocation for OS/2.
  829. Revision 1.2 1998/03/30 15:53:01 florian
  830. * last changes before release:
  831. - gdb fixed
  832. - ratti386 warning removed (about unset function result)
  833. Revision 1.1.1.1 1998/03/25 11:18:15 root
  834. * Restored version
  835. Revision 1.43 1998/03/20 23:31:34 florian
  836. * bug0113 fixed
  837. * problem with interdepened units fixed ("options.pas problem")
  838. * two small extensions for future AMD 3D support
  839. Revision 1.42 1998/03/11 22:22:52 florian
  840. * Fixed circular unit uses, when the units are not in the current dir (from Peter)
  841. * -i shows correct info, not <lf> anymore (from Peter)
  842. * linking with shared libs works again (from Peter)
  843. Revision 1.41 1998/03/10 17:19:29 peter
  844. * fixed bug0108
  845. * better linebreak scanning (concentrated in nextchar(), it supports
  846. #10, #13, #10#13, #13#10
  847. Revision 1.40 1998/03/10 16:27:42 pierre
  848. * better line info in stabs debug
  849. * symtabletype and lexlevel separated into two fields of tsymtable
  850. + ifdef MAKELIB for direct library output, not complete
  851. + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  852. working
  853. + ifdef TESTFUNCRET for setting func result in underfunction, not
  854. working
  855. Revision 1.39 1998/03/10 01:17:24 peter
  856. * all files have the same header
  857. * messages are fully implemented, EXTDEBUG uses Comment()
  858. + AG... files for the Assembler generation
  859. Revision 1.38 1998/03/05 22:43:50 florian
  860. * some win32 support stuff added
  861. Revision 1.37 1998/03/04 01:35:08 peter
  862. * messages for unit-handling and assembler/linker
  863. * the compiler compiles without -dGDB, but doesn't work yet
  864. + -vh for Hint
  865. Revision 1.36 1998/03/03 23:18:45 florian
  866. * ret $8 problem with unit init/main program fixed
  867. Revision 1.35 1998/03/02 13:38:48 peter
  868. + importlib object
  869. * doesn't crash on a systemunit anymore
  870. * updated makefile and depend
  871. Revision 1.34 1998/03/02 01:49:04 peter
  872. * renamed target_DOS to target_GO32V1
  873. + new verbose system, merged old errors and verbose units into one new
  874. verbose.pas, so errors.pas is obsolete
  875. Revision 1.33 1998/03/01 22:46:20 florian
  876. + some win95 linking stuff
  877. * a couple of bugs fixed:
  878. bug0055,bug0058,bug0059,bug0064,bug0072,bug0093,bug0095,bug0098
  879. Revision 1.32 1998/02/28 09:30:58 florian
  880. + writing of win32 import section added
  881. Revision 1.31 1998/02/28 03:57:08 carl
  882. + replaced target_info.short_name by target_info.target (a bit faster)
  883. Revision 1.30 1998/02/27 09:25:58 daniel
  884. * Changed symtable handling so no junk symtable is put on the symtablestack.
  885. Revision 1.28 1998/02/24 14:20:54 peter
  886. + tstringcontainer.empty
  887. * ld -T option restored for linux
  888. * libraries are placed before the objectfiles in a .PPU file
  889. * removed 'uses link' from files.pas
  890. Revision 1.27 1998/02/24 00:19:19 peter
  891. * makefile works again (btw. linux does like any char after a \ )
  892. * removed circular unit with assemble and files
  893. * fixed a sigsegv in pexpr
  894. * pmodule init unit/program is the almost the same, merged them
  895. Revision 1.26 1998/02/22 23:55:18 peter
  896. * small fix
  897. Revision 1.25 1998/02/22 23:03:28 peter
  898. * renamed msource->mainsource and name->unitname
  899. * optimized filename handling, filename is not seperate anymore with
  900. path+name+ext, this saves stackspace and a lot of fsplit()'s
  901. * recompiling of some units in libraries fixed
  902. * shared libraries are working again
  903. + $LINKLIB <lib> to support automatic linking to libraries
  904. + libraries are saved/read from the ppufile, also allows more libraries
  905. per ppufile
  906. Revision 1.24 1998/02/22 18:51:06 carl
  907. * where the heck did the HEAP for m68k go??????? REINSTATED
  908. Revision 1.23 1998/02/21 05:50:14 carl
  909. * bugfix of crash with Us switch
  910. Revision 1.22 1998/02/19 00:11:08 peter
  911. * fixed -g to work again
  912. * fixed some typos with the scriptobject
  913. Revision 1.21 1998/02/17 21:20:57 peter
  914. + Script unit
  915. + __EXIT is called again to exit a program
  916. - target_info.link/assembler calls
  917. * linking works again for dos
  918. * optimized a few filehandling functions
  919. * fixed stabs generation for procedures
  920. Revision 1.20 1998/02/16 12:51:38 michael
  921. + Implemented linker object
  922. Revision 1.19 1998/02/14 01:45:29 peter
  923. * more fixes
  924. - pmode target is removed
  925. - search_as_ld is removed, this is done in the link.pas/assemble.pas
  926. + findexe() to search for an executable (linker,assembler,binder)
  927. Revision 1.18 1998/02/13 22:26:37 peter
  928. * fixed a few SigSegv's
  929. * INIT$$ was not written for linux!
  930. * assembling and linking works again for linux and dos
  931. + assembler object, only attasmi3 supported yet
  932. * restore pp.pas with AddPath etc.
  933. Revision 1.17 1998/02/13 10:35:27 daniel
  934. * Made Motorola version compilable.
  935. * Fixed optimizer
  936. Revision 1.16 1998/02/12 17:19:22 florian
  937. * fixed to get remake3 work, but needs additional fixes (output, I don't like
  938. also that aktswitches isn't a pointer)
  939. Revision 1.15 1998/02/12 11:50:28 daniel
  940. Yes! Finally! After three retries, my patch!
  941. Changes:
  942. Complete rewrite of psub.pas.
  943. Added support for DLL's.
  944. Compiler requires less memory.
  945. Platform units for each platform.
  946. Revision 1.14 1998/01/30 17:31:26 pierre
  947. * bug of cyclic symtablestack fixed
  948. Revision 1.13 1998/01/28 13:48:49 michael
  949. + Initial implementation for making libs from within FPC. Not tested, as compiler does not run
  950. Revision 1.12 1998/01/19 15:46:25 peter
  951. * fixed INIT$$lowercase generation
  952. Revision 1.11 1998/01/19 09:32:28 michael
  953. * Shared Lib and GDB/RHIDE Bufixes from Peter Vreman.
  954. Revision 1.10 1998/01/17 01:57:39 michael
  955. + Start of shared library support. First working version.
  956. Revision 1.9 1998/01/16 18:03:17 florian
  957. * small bug fixes, some stuff of delphi styled constructores added
  958. Revision 1.8 1998/01/13 23:11:15 florian
  959. + class methods
  960. Revision 1.7 1998/01/13 17:13:09 michael
  961. * File time handling and file searching is now done in an OS-independent way,
  962. using the new file treating functions in globals.pas.
  963. Revision 1.6 1998/01/13 16:16:03 pierre
  964. * bug in interdependent units handling
  965. - primary unit was not in loaded_units list
  966. - current_module^.symtable was assigned too early
  967. - donescanner must not call error if the compilation
  968. of the unit was done at a higher level.
  969. Revision 1.5 1998/01/12 13:03:32 florian
  970. + parsing of class methods implemented
  971. Revision 1.4 1998/01/11 10:54:24 florian
  972. + generic library support
  973. Revision 1.3 1998/01/11 04:17:36 carl
  974. + floating point support for m68k
  975. Revision 1.2 1998/01/09 09:10:01 michael
  976. + Initial implementation, second try
  977. }