types.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. {
  2. $Id$
  3. Copyright (C) 1993-98 by Florian Klaempfl
  4. This unit provides some help routines for type handling
  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 types;
  19. interface
  20. uses
  21. cobjects,globals,symtable;
  22. type
  23. tmmxtype = (mmxno,mmxu8bit,mmxs8bit,mmxu16bit,mmxs16bit,
  24. mmxu32bit,mmxs32bit,mmxfixed16,mmxsingle);
  25. { returns true, if def defines an ordinal type }
  26. function is_ordinal(def : pdef) : boolean;
  27. { true if p points to an open array def }
  28. function is_open_array(p : pdef) : boolean;
  29. { true if o is an ansi string def }
  30. function is_ansistring(p : pdef) : boolean;
  31. { true if o is a long string def }
  32. function is_longstring(p : pdef) : boolean;
  33. { true if o is a wide string def }
  34. function is_widestring(p : pdef) : boolean;
  35. { true if o is a short string def }
  36. function is_shortstring(p : pdef) : boolean;
  37. { returns true, if def defines a signed data type (only for ordinal types) }
  38. function is_signed(def : pdef) : boolean;
  39. { returns true, if def uses FPU }
  40. function is_fpu(def : pdef) : boolean;
  41. { true if the return value is in EAX }
  42. function ret_in_acc(def : pdef) : boolean;
  43. { true if uses a parameter as return value }
  44. function ret_in_param(def : pdef) : boolean;
  45. { true if a const parameter is too large to copy }
  46. function dont_copy_const_param(def : pdef) : boolean;
  47. { true if we must never copy this parameter }
  48. const
  49. never_copy_const_param : boolean = false;
  50. { true, if def1 and def2 are semantical the same }
  51. function is_equal(def1,def2 : pdef) : boolean;
  52. { checks for type compatibility (subgroups of type) }
  53. { used for case statements... probably missing stuff }
  54. { to use on other types }
  55. function is_subequal(def1, def2: pdef): boolean;
  56. { true, if two parameter lists are equal }
  57. { if value_equal_const is true, call by value }
  58. { and call by const parameter are assumed as }
  59. { equal }
  60. function equal_paras(def1,def2 : pdefcoll;value_equal_const : boolean) : boolean;
  61. { true if a function can be assigned to a procvar }
  62. function proc_to_procvar_equal(def1,def2 : pabstractprocdef) : boolean;
  63. { if l isn't in the range of def a range check error is generated }
  64. procedure testrange(def : pdef;l : longint);
  65. { returns the range of def }
  66. procedure getrange(def : pdef;var l : longint;var h : longint);
  67. { generates a VMT for _class }
  68. procedure genvmt(_class : pobjectdef);
  69. { some type helper routines for MMX support }
  70. function is_mmx_able_array(p : pdef) : boolean;
  71. { returns the mmx type }
  72. function mmx_type(p : pdef) : tmmxtype;
  73. implementation
  74. uses verbose,aasm;
  75. function equal_paras(def1,def2 : pdefcoll;value_equal_const : boolean) : boolean;
  76. begin
  77. while (assigned(def1)) and (assigned(def2)) do
  78. begin
  79. if value_equal_const then
  80. begin
  81. if not(is_equal(def1^.data,def2^.data)) or
  82. ((def1^.paratyp<>def2^.paratyp) and
  83. ((def1^.paratyp=vs_var) or
  84. (def1^.paratyp=vs_var)
  85. )
  86. ) then
  87. begin
  88. equal_paras:=false;
  89. exit;
  90. end;
  91. end
  92. else
  93. begin
  94. if not(is_equal(def1^.data,def2^.data)) or
  95. (def1^.paratyp<>def2^.paratyp) then
  96. begin
  97. equal_paras:=false;
  98. exit;
  99. end;
  100. end;
  101. def1:=def1^.next;
  102. def2:=def2^.next;
  103. end;
  104. if (def1=nil) and (def2=nil) then
  105. equal_paras:=true
  106. else
  107. equal_paras:=false;
  108. end;
  109. { true if a function can be assigned to a procvar }
  110. function proc_to_procvar_equal(def1,def2 : pabstractprocdef) : boolean;
  111. begin
  112. if is_equal(def1^.retdef,def2^.retdef) and
  113. equal_paras(def1^.para1,def2^.para1,false) and
  114. ((def1^.options and po_comptatibility_options)=
  115. (def2^.options and po_comptatibility_options)) then
  116. proc_to_procvar_equal:=true
  117. else
  118. proc_to_procvar_equal:=false;
  119. end;
  120. { returns true, if def uses FPU }
  121. function is_fpu(def : pdef) : boolean;
  122. begin
  123. is_fpu:=(def^.deftype=floatdef) and (pfloatdef(def)^.typ<>f32bit);
  124. end;
  125. function is_ordinal(def : pdef) : boolean;
  126. var
  127. dt : tbasetype;
  128. begin
  129. case def^.deftype of
  130. orddef : begin
  131. dt:=porddef(def)^.typ;
  132. is_ordinal:=dt in [uchar,u8bit,u16bit,u32bit,s8bit,s16bit,s32bit,bool8bit,bool16bit,bool32bit];
  133. end;
  134. enumdef : is_ordinal:=true;
  135. else
  136. is_ordinal:=false;
  137. end;
  138. end;
  139. function is_signed(def : pdef) : boolean;
  140. var
  141. dt : tbasetype;
  142. begin
  143. case def^.deftype of
  144. orddef : begin
  145. dt:=porddef(def)^.typ;
  146. is_signed:=(dt in [s8bit,s16bit,s32bit]);
  147. end;
  148. enumdef : is_signed:=false;
  149. else
  150. is_signed:=false;
  151. end;
  152. end;
  153. { true, if p points to an open array def }
  154. function is_open_array(p : pdef) : boolean;
  155. begin
  156. is_open_array:=(p^.deftype=arraydef) and
  157. (parraydef(p)^.lowrange=0) and
  158. (parraydef(p)^.highrange=-1);
  159. end;
  160. { true if o is an ansi string def }
  161. function is_ansistring(p : pdef) : boolean;
  162. begin
  163. is_ansistring:=(p^.deftype=stringdef) and
  164. (pstringdef(p)^.string_typ=st_ansistring);
  165. end;
  166. { true if o is an long string def }
  167. function is_longstring(p : pdef) : boolean;
  168. begin
  169. is_longstring:=(p^.deftype=stringdef) and
  170. (pstringdef(p)^.string_typ=st_longstring);
  171. end;
  172. { true if o is an wide string def }
  173. function is_widestring(p : pdef) : boolean;
  174. begin
  175. is_widestring:=(p^.deftype=stringdef) and
  176. (pstringdef(p)^.string_typ=st_widestring);
  177. end;
  178. { true if o is an short string def }
  179. function is_shortstring(p : pdef) : boolean;
  180. begin
  181. is_shortstring:=(p^.deftype=stringdef) and
  182. (pstringdef(p)^.string_typ=st_shortstring);
  183. end;
  184. { true if the return value is in accumulator (EAX for i386), D0 for 68k }
  185. function ret_in_acc(def : pdef) : boolean;
  186. begin
  187. ret_in_acc:=(def^.deftype in [orddef,pointerdef,enumdef,classrefdef]) or
  188. ((def^.deftype=stringdef) and (pstringdef(def)^.string_typ in [st_ansistring,st_widestring])) or
  189. ((def^.deftype=procvardef) and ((pprocvardef(def)^.options and pomethodpointer)=0)) or
  190. ((def^.deftype=objectdef) and pobjectdef(def)^.isclass) or
  191. ((def^.deftype=setdef) and (psetdef(def)^.settype=smallset)) or
  192. ((def^.deftype=floatdef) and (pfloatdef(def)^.typ=f32bit));
  193. end;
  194. { true if uses a parameter as return value }
  195. function ret_in_param(def : pdef) : boolean;
  196. begin
  197. ret_in_param:=(def^.deftype in [arraydef,recorddef]) or
  198. ((def^.deftype=stringdef) and (pstringdef(def)^.string_typ in [st_shortstring,st_longstring])) or
  199. ((def^.deftype=procvardef) and ((pprocvardef(def)^.options and pomethodpointer)<>0)) or
  200. ((def^.deftype=objectdef) and ((pobjectdef(def)^.options and oois_class)=0)) or
  201. ((def^.deftype=setdef) and (psetdef(def)^.settype<>smallset));
  202. end;
  203. { true if a const parameter is too large to copy }
  204. function dont_copy_const_param(def : pdef) : boolean;
  205. begin
  206. dont_copy_const_param:=(def^.deftype in [arraydef,objectdef,formaldef,recorddef]) or
  207. ((def^.deftype=stringdef) and (pstringdef(def)^.string_typ in [st_shortstring,st_longstring])) or
  208. ((def^.deftype=procvardef) and ((pprocvardef(def)^.options and pomethodpointer)<>0)) or
  209. ((def^.deftype=setdef) and (psetdef(def)^.settype<>smallset));
  210. end;
  211. procedure testrange(def : pdef;l : longint);
  212. var
  213. lv,hv: longint;
  214. begin
  215. getrange(def,lv,hv);
  216. if (def^.deftype=orddef) and
  217. (porddef(def)^.typ=u32bit) then
  218. begin
  219. if lv<=hv then
  220. begin
  221. if (l<lv) or (l>hv) then
  222. Message(parser_e_range_check_error);
  223. end
  224. else
  225. { this happens with the wrap around problem }
  226. { if lv is positive and hv is over $7ffffff }
  227. { so it seems negative }
  228. begin
  229. if ((l>=0) and (l<lv)) or
  230. ((l<0) and (l>hv)) then
  231. Message(parser_e_range_check_error);
  232. end;
  233. end
  234. else if (l<lv) or (l>hv) then
  235. Message(parser_e_range_check_error);
  236. end;
  237. procedure getrange(def : pdef;var l : longint;var h : longint);
  238. begin
  239. case def^.deftype of
  240. orddef : begin
  241. l:=porddef(def)^.low;
  242. h:=porddef(def)^.high;
  243. end;
  244. enumdef : begin
  245. l:=penumdef(def)^.min;
  246. h:=penumdef(def)^.max;
  247. end;
  248. end;
  249. end;
  250. function mmx_type(p : pdef) : tmmxtype;
  251. begin
  252. mmx_type:=mmxno;
  253. if is_mmx_able_array(p) then
  254. begin
  255. if parraydef(p)^.definition^.deftype=floatdef then
  256. case pfloatdef(parraydef(p)^.definition)^.typ of
  257. s32real:
  258. mmx_type:=mmxsingle;
  259. f16bit:
  260. mmx_type:=mmxfixed16
  261. end
  262. else
  263. case porddef(parraydef(p)^.definition)^.typ of
  264. u8bit:
  265. mmx_type:=mmxu8bit;
  266. s8bit:
  267. mmx_type:=mmxs8bit;
  268. u16bit:
  269. mmx_type:=mmxu16bit;
  270. s16bit:
  271. mmx_type:=mmxs16bit;
  272. u32bit:
  273. mmx_type:=mmxu32bit;
  274. s32bit:
  275. mmx_type:=mmxs32bit;
  276. end;
  277. end;
  278. end;
  279. function is_mmx_able_array(p : pdef) : boolean;
  280. begin
  281. {$ifdef SUPPORT_MMX}
  282. if (cs_mmx_saturation in aktlocalswitches) then
  283. begin
  284. is_mmx_able_array:=(p^.deftype=arraydef) and
  285. (
  286. ((parraydef(p)^.definition^.deftype=orddef) and
  287. (
  288. (parraydef(p)^.lowrange=0) and
  289. (parraydef(p)^.highrange=1) and
  290. (porddef(parraydef(p)^.definition)^.typ in [u32bit,s32bit])
  291. ) or
  292. (
  293. (parraydef(p)^.lowrange=0) and
  294. (parraydef(p)^.highrange=3) and
  295. (porddef(parraydef(p)^.definition)^.typ in [u16bit,s16bit])
  296. )
  297. )
  298. ) or
  299. (
  300. ((parraydef(p)^.definition^.deftype=floatdef) and
  301. (
  302. (parraydef(p)^.lowrange=0) and
  303. (parraydef(p)^.highrange=3) and
  304. (pfloatdef(parraydef(p)^.definition)^.typ=f16bit)
  305. ) or
  306. (
  307. (parraydef(p)^.lowrange=0) and
  308. (parraydef(p)^.highrange=1) and
  309. (pfloatdef(parraydef(p)^.definition)^.typ=s32real)
  310. )
  311. )
  312. );
  313. end
  314. else
  315. begin
  316. is_mmx_able_array:=(p^.deftype=arraydef) and
  317. (
  318. ((parraydef(p)^.definition^.deftype=orddef) and
  319. (
  320. (parraydef(p)^.lowrange=0) and
  321. (parraydef(p)^.highrange=1) and
  322. (porddef(parraydef(p)^.definition)^.typ in [u32bit,s32bit])
  323. ) or
  324. (
  325. (parraydef(p)^.lowrange=0) and
  326. (parraydef(p)^.highrange=3) and
  327. (porddef(parraydef(p)^.definition)^.typ in [u16bit,s16bit])
  328. ) or
  329. (
  330. (parraydef(p)^.lowrange=0) and
  331. (parraydef(p)^.highrange=7) and
  332. (porddef(parraydef(p)^.definition)^.typ in [u8bit,s8bit])
  333. )
  334. )
  335. ) or
  336. (
  337. ((parraydef(p)^.definition^.deftype=floatdef) and
  338. (
  339. (parraydef(p)^.lowrange=0) and
  340. (parraydef(p)^.highrange=3) and
  341. (pfloatdef(parraydef(p)^.definition)^.typ=f32bit)
  342. )
  343. or
  344. (
  345. (parraydef(p)^.lowrange=0) and
  346. (parraydef(p)^.highrange=1) and
  347. (pfloatdef(parraydef(p)^.definition)^.typ=s32real)
  348. )
  349. )
  350. );
  351. end;
  352. {$else SUPPORT_MMX}
  353. is_mmx_able_array:=false;
  354. {$endif SUPPORT_MMX}
  355. end;
  356. function is_equal(def1,def2 : pdef) : boolean;
  357. var
  358. b : boolean;
  359. hd : pdef;
  360. hp1,hp2 : pdefcoll;
  361. begin
  362. { both types must exists }
  363. if not (assigned(def1) and assigned(def2)) then
  364. begin
  365. is_equal:=false;
  366. exit;
  367. end;
  368. { be sure, that if there is a stringdef, that this is def1 }
  369. if def2^.deftype=stringdef then
  370. begin
  371. hd:=def1;
  372. def1:=def2;
  373. def2:=hd;
  374. end;
  375. b:=false;
  376. { wenn beide auf die gleiche Definition zeigen sind sie wohl gleich...}
  377. if def1=def2 then
  378. b:=true
  379. else
  380. { pointer with an equal definition are equal }
  381. if (def1^.deftype=pointerdef) and (def2^.deftype=pointerdef) then
  382. { here a problem detected in tabsolutesym }
  383. { the types can be forward type !! }
  384. begin
  385. if assigned(def1^.sym) and ((def1^.sym^.properties and sp_forwarddef)<>0) then
  386. b:=(def1^.sym=def2^.sym)
  387. else
  388. b:=is_equal(ppointerdef(def1)^.definition,ppointerdef(def2)^.definition);
  389. end
  390. else
  391. { ordinals are equal only when the ordinal type is equal }
  392. if (def1^.deftype=orddef) and (def2^.deftype=orddef) then
  393. begin
  394. case porddef(def1)^.typ of
  395. u8bit,u16bit,u32bit,
  396. s8bit,s16bit,s32bit:
  397. b:=((porddef(def1)^.typ=porddef(def2)^.typ) and
  398. (porddef(def1)^.low=porddef(def2)^.low) and
  399. (porddef(def1)^.high=porddef(def2)^.high));
  400. uvoid,uchar,
  401. bool8bit,bool16bit,bool32bit:
  402. b:=(porddef(def1)^.typ=porddef(def2)^.typ);
  403. end;
  404. end
  405. else
  406. if (def1^.deftype=floatdef) and (def2^.deftype=floatdef) then
  407. b:=pfloatdef(def1)^.typ=pfloatdef(def2)^.typ
  408. else
  409. { strings with the same length are equal }
  410. if (def1^.deftype=stringdef) and (def2^.deftype=stringdef) and
  411. (pstringdef(def1)^.string_typ=pstringdef(def2)^.string_typ) then
  412. begin
  413. b:=not(is_shortstring(def1)) or
  414. (pstringdef(def1)^.len=pstringdef(def2)^.len);
  415. end
  416. { STRING[N] ist equivalent zu ARRAY[0..N] OF CHAR (N<256) }
  417. {
  418. else if ((def1^.deftype=stringdef) and (def2^.deftype=arraydef)) and
  419. (parraydef(def2)^.definition^.deftype=orddef) and
  420. (porddef(parraydef(def1)^.definition)^.typ=uchar) and
  421. (parraydef(def2)^.lowrange=0) and
  422. (parraydef(def2)^.highrange=pstringdef(def1)^.len) then
  423. b:=true }
  424. else
  425. if (def1^.deftype=formaldef) and (def2^.deftype=formaldef) then
  426. b:=true
  427. { file types with the same file element type are equal }
  428. { this is a problem for assign !! }
  429. { changed to allow if one is untyped }
  430. { all typed files are equal to the special }
  431. { typed file that has voiddef as elemnt type }
  432. { but must NOT match for text file !!! }
  433. else
  434. if (def1^.deftype=filedef) and (def2^.deftype=filedef) then
  435. b:=(pfiledef(def1)^.filetype=pfiledef(def2)^.filetype) and
  436. ((
  437. ((pfiledef(def1)^.typed_as=nil) and
  438. (pfiledef(def2)^.typed_as=nil)) or
  439. (
  440. (pfiledef(def1)^.typed_as<>nil) and
  441. (pfiledef(def2)^.typed_as<>nil) and
  442. is_equal(pfiledef(def1)^.typed_as,pfiledef(def2)^.typed_as)
  443. ) or
  444. ( (pfiledef(def1)^.typed_as=pdef(voiddef)) or
  445. (pfiledef(def2)^.typed_as=pdef(voiddef))
  446. )))
  447. { sets with the same element type are equal }
  448. else
  449. if (def1^.deftype=setdef) and (def2^.deftype=setdef) then
  450. begin
  451. if assigned(psetdef(def1)^.setof) and
  452. assigned(psetdef(def2)^.setof) then
  453. b:=(psetdef(def1)^.setof^.deftype=psetdef(def2)^.setof^.deftype)
  454. else
  455. b:=true;
  456. end
  457. else
  458. if (def1^.deftype=procvardef) and (def2^.deftype=procvardef) then
  459. begin
  460. { poassembler isn't important for compatibility }
  461. b:=((pprocvardef(def1)^.options and not(poassembler))=
  462. (pprocvardef(def2)^.options and not(poassembler))
  463. ) and
  464. is_equal(pprocvardef(def1)^.retdef,pprocvardef(def2)^.retdef);
  465. { now evalute the parameters }
  466. if b then
  467. begin
  468. hp1:=pprocvardef(def1)^.para1;
  469. hp2:=pprocvardef(def1)^.para1;
  470. while assigned(hp1) and assigned(hp2) do
  471. begin
  472. if not(is_equal(hp1^.data,hp2^.data)) or
  473. not(hp1^.paratyp=hp2^.paratyp) then
  474. begin
  475. b:=false;
  476. break;
  477. end;
  478. hp1:=hp1^.next;
  479. hp2:=hp2^.next;
  480. end;
  481. b:=(hp1=nil) and (hp2=nil);
  482. end;
  483. end
  484. else
  485. if (def1^.deftype=arraydef) and (def2^.deftype=arraydef) and
  486. (is_open_array(def1) or is_open_array(def2)) then
  487. begin
  488. b:=is_equal(parraydef(def1)^.definition,parraydef(def2)^.definition);
  489. end
  490. else
  491. if (def1^.deftype=classrefdef) and (def2^.deftype=classrefdef) then
  492. begin
  493. { similar to pointerdef: }
  494. if assigned(def1^.sym) and ((def1^.sym^.properties and sp_forwarddef)<>0) then
  495. b:=(def1^.sym=def2^.sym)
  496. else
  497. b:=is_equal(pclassrefdef(def1)^.definition,pclassrefdef(def2)^.definition);
  498. end;
  499. is_equal:=b;
  500. end;
  501. function is_subequal(def1, def2: pdef): boolean;
  502. Begin
  503. if assigned(def1) and assigned(def2) then
  504. Begin
  505. is_subequal := FALSE;
  506. if (def1^.deftype = orddef) and (def2^.deftype = orddef) then
  507. Begin
  508. { see p.47 of Turbo Pascal 7.01 manual for the separation of types }
  509. { range checking for case statements is done with testrange }
  510. case porddef(def1)^.typ of
  511. u8bit,u16bit,u32bit,
  512. s8bit,s16bit,s32bit : is_subequal:=(porddef(def2)^.typ in [s32bit,u32bit,u8bit,s8bit,s16bit,u16bit]);
  513. bool8bit,bool16bit,bool32bit : is_subequal:=(porddef(def2)^.typ in [bool8bit,bool16bit,bool32bit]);
  514. uchar : is_subequal:=(porddef(def2)^.typ=uchar);
  515. end;
  516. end
  517. else
  518. Begin
  519. { I assume that both enumerations are equal when the first }
  520. { pointers are equal. }
  521. if (def1^.deftype = enumdef) and (def2^.deftype =enumdef) then
  522. Begin
  523. if penumdef(def1)^.first = penumdef(def2)^.first then
  524. is_subequal := TRUE;
  525. end;
  526. end;
  527. end; { endif assigned ... }
  528. end;
  529. type
  530. pprocdefcoll = ^tprocdefcoll;
  531. tprocdefcoll = record
  532. next : pprocdefcoll;
  533. data : pprocdef;
  534. end;
  535. psymcoll = ^tsymcoll;
  536. tsymcoll = record
  537. next : psymcoll;
  538. name : pstring;
  539. data : pprocdefcoll;
  540. end;
  541. var
  542. wurzel : psymcoll;
  543. nextvirtnumber : longint;
  544. _c : pobjectdef;
  545. has_constructor,has_virtual_method : boolean;
  546. procedure eachsym(sym : psym);{$ifndef FPC}far;{$endif}
  547. var
  548. procdefcoll : pprocdefcoll;
  549. hp : pprocdef;
  550. symcoll : psymcoll;
  551. _name : string;
  552. stored : boolean;
  553. { creates a new entry in the procsym list }
  554. procedure newentry;
  555. begin
  556. { if not, generate a new symbol item }
  557. new(symcoll);
  558. symcoll^.name:=stringdup(sym^.name);
  559. symcoll^.next:=wurzel;
  560. symcoll^.data:=nil;
  561. wurzel:=symcoll;
  562. hp:=pprocsym(sym)^.definition;
  563. { inserts all definitions }
  564. while assigned(hp) do
  565. begin
  566. new(procdefcoll);
  567. procdefcoll^.data:=hp;
  568. procdefcoll^.next:=symcoll^.data;
  569. symcoll^.data:=procdefcoll;
  570. { if it's a virtual method }
  571. if (hp^.options and povirtualmethod)<>0 then
  572. begin
  573. { then it gets a number ... }
  574. hp^.extnumber:=nextvirtnumber;
  575. { and we inc the number }
  576. inc(nextvirtnumber);
  577. has_virtual_method:=true;
  578. end;
  579. if (hp^.options and poconstructor)<>0 then
  580. has_constructor:=true;
  581. { check, if a method should be overridden }
  582. if (hp^.options and pooverridingmethod)<>0 then
  583. Message1(parser_e_nothing_to_be_overridden,_c^.name^+'.'+_name);
  584. { next overloaded method }
  585. hp:=hp^.nextoverloaded;
  586. end;
  587. end;
  588. begin
  589. { put only sub routines into the VMT }
  590. if sym^.typ=procsym then
  591. begin
  592. _name:=sym^.name;
  593. symcoll:=wurzel;
  594. while assigned(symcoll) do
  595. begin
  596. { does the symbol already exist in the list ? }
  597. if _name=symcoll^.name^ then
  598. begin
  599. { walk through all defs of the symbol }
  600. hp:=pprocsym(sym)^.definition;
  601. while assigned(hp) do
  602. begin
  603. { compare with all stored definitions }
  604. procdefcoll:=symcoll^.data;
  605. stored:=false;
  606. while assigned(procdefcoll) do
  607. begin
  608. { compare parameters }
  609. if equal_paras(procdefcoll^.data^.para1,hp^.para1,false) and
  610. (
  611. ((procdefcoll^.data^.options and povirtualmethod)<>0) or
  612. ((hp^.options and povirtualmethod)<>0)
  613. ) then
  614. begin
  615. { wenn sie gleich sind }
  616. { und eine davon virtual deklariert ist }
  617. { Fehler falls nur eine VIRTUAL }
  618. if (procdefcoll^.data^.options and povirtualmethod)<>
  619. (hp^.options and povirtualmethod) then
  620. begin
  621. { in classes, we hide the old method }
  622. if _c^.isclass then
  623. begin
  624. { warn only if it is the first time,
  625. we hide the method }
  626. if _c=hp^._class then
  627. Message1(parser_w_should_use_override,_c^.name^+'.'+_name);
  628. newentry;
  629. exit;
  630. end
  631. else
  632. begin
  633. Message1(parser_e_overloaded_are_not_both_virtual,_c^.name^+'.'+_name);
  634. end;
  635. end;
  636. { check, if the overridden directive is set }
  637. { (povirtualmethod is set! }
  638. { class ? }
  639. if _c^.isclass and
  640. ((hp^.options and pooverridingmethod)=0) then
  641. begin
  642. { warn only if it is the first time,
  643. we hide the method }
  644. if _c=hp^._class then
  645. Message1(parser_w_should_use_override,_c^.name^+'.'+_name);
  646. newentry;
  647. exit;
  648. end;
  649. { error, if the return types aren't equal }
  650. if not(is_equal(procdefcoll^.data^.retdef,hp^.retdef)) then
  651. Message1(parser_e_overloaded_methodes_not_same_ret,_c^.name^+'.'+_name);
  652. { the flags have to match }
  653. { except abstract and override }
  654. if (procdefcoll^.data^.options and not(poabstractmethod or pooverridingmethod))<>
  655. (hp^.options and not(poabstractmethod or pooverridingmethod)) then
  656. Message1(parser_e_header_dont_match_forward,_c^.name^+'.'+_name);
  657. { now set the number }
  658. hp^.extnumber:=procdefcoll^.data^.extnumber;
  659. { and exchange }
  660. procdefcoll^.data:=hp;
  661. stored:=true;
  662. end;
  663. procdefcoll:=procdefcoll^.next;
  664. end;
  665. { if it isn't saved in the list }
  666. { we create a new entry }
  667. if not(stored) then
  668. begin
  669. new(procdefcoll);
  670. procdefcoll^.data:=hp;
  671. procdefcoll^.next:=symcoll^.data;
  672. symcoll^.data:=procdefcoll;
  673. { if the method is virtual ... }
  674. if (hp^.options and povirtualmethod)<>0 then
  675. begin
  676. { ... it will get a number }
  677. hp^.extnumber:=nextvirtnumber;
  678. inc(nextvirtnumber);
  679. end;
  680. { check, if a method should be overridden }
  681. if (hp^.options and pooverridingmethod)<>0 then
  682. Message1(parser_e_nothing_to_be_overridden,_c^.name^+'.'+_name);
  683. end;
  684. hp:=hp^.nextoverloaded;
  685. end;
  686. exit;
  687. end;
  688. symcoll:=symcoll^.next;
  689. end;
  690. newentry;
  691. end;
  692. end;
  693. procedure genvmt(_class : pobjectdef);
  694. procedure do_genvmt(p : pobjectdef);
  695. begin
  696. { start with the base class }
  697. if assigned(p^.childof) then
  698. do_genvmt(p^.childof);
  699. { walk through all public syms }
  700. _c:=_class;
  701. {$ifdef tp}
  702. p^.publicsyms^.foreach(eachsym);
  703. {$else}
  704. p^.publicsyms^.foreach(@eachsym);
  705. {$endif}
  706. end;
  707. var
  708. symcoll : psymcoll;
  709. procdefcoll : pprocdefcoll;
  710. i : longint;
  711. begin
  712. wurzel:=nil;
  713. nextvirtnumber:=0;
  714. has_constructor:=false;
  715. has_virtual_method:=false;
  716. { generates a tree of all used methods }
  717. do_genvmt(_class);
  718. if has_virtual_method and not(has_constructor) then
  719. Message1(parser_w_virtual_without_constructor,_class^.name^);
  720. { generates the VMT }
  721. { walk trough all numbers for virtual methods and search }
  722. { the method }
  723. for i:=0 to nextvirtnumber-1 do
  724. begin
  725. symcoll:=wurzel;
  726. { walk trough all symbols }
  727. while assigned(symcoll) do
  728. begin
  729. { walk trough all methods }
  730. procdefcoll:=symcoll^.data;
  731. while assigned(procdefcoll) do
  732. begin
  733. { writes the addresses to the VMT }
  734. { but only this which are declared as virtual }
  735. if procdefcoll^.data^.extnumber=i then
  736. begin
  737. if (procdefcoll^.data^.options and povirtualmethod)<>0 then
  738. begin
  739. { if a method is abstract, then is also the }
  740. { class abstract and it's not allow to }
  741. { generates an instance }
  742. if (procdefcoll^.data^.options and poabstractmethod)<>0 then
  743. begin
  744. _class^.options:=_class^.options or oois_abstract;
  745. datasegment^.concat(new(pai_const,init_symbol('ABSTRACTERROR')));
  746. end
  747. else
  748. begin
  749. datasegment^.concat(new(pai_const,init_symbol(
  750. strpnew(procdefcoll^.data^.mangledname))));
  751. maybe_concat_external(procdefcoll^.data^.owner,
  752. procdefcoll^.data^.mangledname);
  753. end;
  754. end;
  755. end;
  756. procdefcoll:=procdefcoll^.next;
  757. end;
  758. symcoll:=symcoll^.next;
  759. end;
  760. end;
  761. { disposes the above generated tree }
  762. symcoll:=wurzel;
  763. while assigned(symcoll) do
  764. begin
  765. wurzel:=symcoll^.next;
  766. stringdispose(symcoll^.name);
  767. procdefcoll:=symcoll^.data;
  768. while assigned(procdefcoll) do
  769. begin
  770. symcoll^.data:=procdefcoll^.next;
  771. dispose(procdefcoll);
  772. procdefcoll:=symcoll^.data;
  773. end;
  774. dispose(symcoll);
  775. symcoll:=wurzel;
  776. end;
  777. end;
  778. end.
  779. {
  780. $Log$
  781. Revision 1.21 1998-08-19 00:42:45 peter
  782. + subrange types for enums
  783. + checking for bounds type with ranges
  784. Revision 1.20 1998/08/18 14:17:14 pierre
  785. * bug about assigning the return value of a function to
  786. a procvar fixed : warning
  787. assigning a proc to a procvar need @ in FPC mode !!
  788. * missing file/line info restored
  789. Revision 1.19 1998/08/18 09:24:48 pierre
  790. * small warning position bug fixed
  791. * support_mmx switches splitting was missing
  792. * rhide error and warning output corrected
  793. Revision 1.18 1998/08/14 18:18:49 peter
  794. + dynamic set contruction
  795. * smallsets are now working (always longint size)
  796. Revision 1.17 1998/08/05 16:00:17 florian
  797. * some fixes for ansi strings
  798. * $log$ to $Log$
  799. * $log$ to Revision 1.21 1998-08-19 00:42:45 peter
  800. * $log$ to + subrange types for enums
  801. * $log$ to + checking for bounds type with ranges
  802. * $log$ to
  803. * $log$ to Revision 1.20 1998/08/18 14:17:14 pierre
  804. * $log$ to * bug about assigning the return value of a function to
  805. * $log$ to a procvar fixed : warning
  806. * $log$ to assigning a proc to a procvar need @ in FPC mode !!
  807. * $log$ to * missing file/line info restored
  808. * $log$ to
  809. * $log$ to Revision 1.19 1998/08/18 09:24:48 pierre
  810. * $log$ to * small warning position bug fixed
  811. * $log$ to * support_mmx switches splitting was missing
  812. * $log$ to * rhide error and warning output corrected
  813. * $log$ to
  814. * $log$ to Revision 1.18 1998/08/14 18:18:49 peter
  815. * $log$ to + dynamic set contruction
  816. * $log$ to * smallsets are now working (always longint size)
  817. * $log$ to changed
  818. Revision 1.16 1998/07/20 23:35:50 michael
  819. Const ansistrings are not copied.
  820. Revision 1.15 1998/07/18 22:54:32 florian
  821. * some ansi/wide/longstring support fixed:
  822. o parameter passing
  823. o returning as result from functions
  824. Revision 1.14 1998/06/12 14:50:50 peter
  825. * removed the tree dependency to types.pas
  826. * long_fil.pas support (not fully tested yet)
  827. Revision 1.13 1998/06/03 22:49:07 peter
  828. + wordbool,longbool
  829. * rename bis,von -> high,low
  830. * moved some systemunit loading/creating to psystem.pas
  831. Revision 1.12 1998/05/12 10:47:00 peter
  832. * moved printstatus to verb_def
  833. + V_Normal which is between V_Error and V_Warning and doesn't have a
  834. prefix like error: warning: and is included in V_Default
  835. * fixed some messages
  836. * first time parameter scan is only for -v and -T
  837. - removed old style messages
  838. Revision 1.11 1998/05/01 16:38:46 florian
  839. * handling of private and protected fixed
  840. + change_keywords_to_tp implemented to remove
  841. keywords which aren't supported by tp
  842. * break and continue are now symbols of the system unit
  843. + widestring, longstring and ansistring type released
  844. Revision 1.10 1998/04/29 10:34:08 pierre
  845. + added some code for ansistring (not complete nor working yet)
  846. * corrected operator overloading
  847. * corrected nasm output
  848. + started inline procedures
  849. + added starstarn : use ** for exponentiation (^ gave problems)
  850. + started UseTokenInfo cond to get accurate positions
  851. Revision 1.9 1998/04/21 10:16:49 peter
  852. * patches from strasbourg
  853. * objects is not used anymore in the fpc compiled version
  854. Revision 1.8 1998/04/12 22:39:44 florian
  855. * problem with read access to properties solved
  856. * correct handling of hidding methods via virtual (COM)
  857. * correct result type of constructor calls (COM), the resulttype
  858. depends now on the type of the class reference
  859. Revision 1.7 1998/04/10 21:36:56 florian
  860. + some stuff to support method pointers (procedure of object) added
  861. (declaration, parameter handling)
  862. Revision 1.6 1998/04/10 15:39:49 florian
  863. * more fixes to get classes.pas compiled
  864. Revision 1.5 1998/04/09 23:02:16 florian
  865. * small problems solved to get remake3 work
  866. Revision 1.4 1998/04/08 16:58:09 pierre
  867. * several bugfixes
  868. ADD ADC and AND are also sign extended
  869. nasm output OK (program still crashes at end
  870. and creates wrong assembler files !!)
  871. procsym types sym in tdef removed !!
  872. Revision 1.3 1998/04/08 11:34:22 peter
  873. * nasm works (linux only tested)
  874. }