rtti.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Michael Van Canneyt
  5. member of the Free Pascal development team
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { Run-Time type information routines }
  13. { The RTTI is implemented through a series of constants : }
  14. Const
  15. tkUnknown = 0;
  16. tkInteger = 1;
  17. tkChar = 2;
  18. tkEnumeration = 3;
  19. tkFloat = 4;
  20. tkSet = 5;
  21. tkMethod = 6;
  22. tkSString = 7;
  23. tkString = tkSString;
  24. tkLString = 8;
  25. tkAString = 9;
  26. tkWString = 10;
  27. tkVariant = 11;
  28. tkArray = 12;
  29. tkRecord = 13;
  30. tkInterface = 14;
  31. tkClass = 15;
  32. tkObject = 16;
  33. tkWChar = 17;
  34. tkBool = 18;
  35. tkInt64 = 19;
  36. tkQWord = 20;
  37. tkDynArray = 21;
  38. { A record is designed as follows :
  39. 1 : tkrecord
  40. 2 : Length of name string (n);
  41. 3 : name string;
  42. 3+n : record size;
  43. 7+n : number of elements (N)
  44. 11+n : N times : Pointer to type info
  45. Offset in record
  46. }
  47. Type
  48. TRecElem = Record
  49. Info : Pointer;
  50. Offset : Longint;
  51. end;
  52. TRecElemArray = Array[1..Maxint] of TRecElem;
  53. PRecRec = ^TRecRec;
  54. TRecRec = record
  55. Size,Count : Longint;
  56. Elements : TRecElemArray;
  57. end;
  58. { An array is designed as follows :
  59. 1 : tkArray;
  60. 2 : length of name string (n);
  61. 3 : NAme string
  62. 3+n : Element Size
  63. 7+n : Number of elements
  64. 11+n : Pointer to type of elements
  65. }
  66. PArrayRec = ^TArrayRec;
  67. TArrayRec = record
  68. Size,Count : Longint;
  69. Info : Pointer;
  70. end;
  71. Procedure fpc_Initialize (Data,TypeInfo : pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[Public,Alias : 'FPC_INITIALIZE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  72. { this definition is sometimes (depending on switches)
  73. already defined or not so define it locally to avoid problems PM }
  74. Var Temp : PByte;
  75. I,Count : longint;
  76. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  77. ArrayRec : TArrayRec;
  78. RecElem : TRecElem;
  79. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  80. Size : longint;
  81. TInfo : Pointer;
  82. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  83. begin
  84. Temp:=PByte(TypeInfo);
  85. case temp^ of
  86. tkAstring,tkWstring,tkInterface,tkDynArray:
  87. PPchar(Data)^:=Nil;
  88. tkArray:
  89. begin
  90. inc(temp);
  91. I:=temp^;
  92. inc(temp,(I+1)); // skip name string;
  93. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  94. move(PArrayRec(Temp)^,ArrayRec,sizeof(ArrayRec));
  95. for I:=0 to ArrayRec.Count-1 do
  96. int_Initialize (Data+(I*ArrayRec.size),ArrayRec.Info);
  97. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  98. Size:=PArrayRec(Temp)^.Size; // get element size
  99. Count:=PArrayRec(Temp)^.Count; // get element Count
  100. TInfo:=PArrayRec(Temp)^.Info; // Get element info
  101. For I:=0 to Count-1 do
  102. int_Initialize (Data+(I*size),TInfo);
  103. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  104. end;
  105. tkObject,
  106. tkRecord:
  107. begin
  108. inc(Temp);
  109. I:=Temp^;
  110. inc(temp,I+1); // skip name string;
  111. temp:=aligntoptr(temp);
  112. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  113. move(PRecRec(Temp)^.Count,Count,sizeof(Count)); // get element Count
  114. For I:=1 to count Do
  115. begin
  116. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(TRecElem));
  117. int_Initialize (Data+RecElem.Offset,RecElem.Info);
  118. end;
  119. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  120. Count:=PRecRec(Temp)^.Count; // get element Count
  121. For I:=1 to count Do
  122. With PRecRec(Temp)^.elements[I] do
  123. int_Initialize (Data+Offset,Info);
  124. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  125. end;
  126. {$ifdef HASVARIANT}
  127. tkVariant:
  128. variant_init(Variant(PVarData(Data)^))
  129. {$endif HASVARIANT}
  130. end;
  131. end;
  132. Procedure fpc_finalize (Data,TypeInfo: Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[Public,Alias : 'FPC_FINALIZE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  133. { this definition is sometimes (depending on switches)
  134. already defined or not so define it locally to avoid problems PM }
  135. Var Temp : PByte;
  136. I,Count : longint;
  137. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  138. ArrayRec : TArrayRec;
  139. RecElem : TRecElem;
  140. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  141. Size : longint;
  142. TInfo : Pointer;
  143. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  144. begin
  145. Temp:=PByte(TypeInfo);
  146. case temp^ of
  147. tkAstring :
  148. begin
  149. fpc_AnsiStr_Decr_Ref(PPointer(Data)^);
  150. PPointer(Data)^:=nil;
  151. end;
  152. {$ifdef HASWIDESTRING}
  153. tkWstring :
  154. begin
  155. fpc_WideStr_Decr_Ref(PPointer(Data)^);
  156. PPointer(Data)^:=nil;
  157. end;
  158. {$endif HASWIDESTRING}
  159. tkArray :
  160. begin
  161. inc(Temp);
  162. I:=temp^;
  163. inc(temp,I+1); // skip name string;
  164. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  165. move(PArrayRec(Temp)^,ArrayRec,sizeof(ArrayRec));
  166. for I:=0 to ArrayRec.Count-1 do
  167. int_Finalize (Data+(I*ArrayRec.size),ArrayRec.Info);
  168. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  169. Size:=PArrayRec(Temp)^.Size; // get element size
  170. Count:=PArrayRec(Temp)^.Count; // get element Count
  171. TInfo:=PArrayRec(Temp)^.Info; // Get element info
  172. For I:=0 to Count-1 do
  173. int_Finalize (Data+(I*size),TInfo);
  174. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  175. end;
  176. tkObject,
  177. tkRecord:
  178. begin
  179. inc(Temp);
  180. I:=Temp^;
  181. inc(temp,I+1); // skip name string;
  182. temp:=aligntoptr(temp);
  183. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  184. move(PRecRec(Temp)^.Count,Count,sizeof(Count)); // get element Count
  185. For I:=1 to count Do
  186. begin
  187. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(TRecElem));
  188. int_Finalize (Data+RecElem.Offset,RecElem.Info);
  189. end;
  190. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  191. Count:=PRecRec(Temp)^.Count; // get element Count
  192. For I:=1 to count do
  193. With PRecRec(Temp)^.elements[I] do
  194. int_Finalize (Data+Offset,Info);
  195. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  196. end;
  197. {$ifdef HASINTF}
  198. tkInterface:
  199. begin
  200. Intf_Decr_Ref(PPointer(Data)^);
  201. PPointer(Data)^:=nil;
  202. end;
  203. {$endif HASINTF}
  204. tkDynArray:
  205. fpc_dynarray_decr_ref(PPointer(Data)^,TypeInfo);
  206. {$ifdef HASVARIANT}
  207. tkVariant:
  208. variant_clear(Variant(PVarData(Data)^))
  209. {$endif HASVARIANT}
  210. end;
  211. end;
  212. Procedure fpc_Addref (Data,TypeInfo : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif} [Public,alias : 'FPC_ADDREF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  213. { this definition is sometimes (depending on switches)
  214. already defined or not so define it locally to avoid problems PM }
  215. Var Temp : PByte;
  216. I,Count : longint;
  217. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  218. ArrayRec : TArrayRec;
  219. RecElem : TRecElem;
  220. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  221. Size : longint;
  222. TInfo : Pointer;
  223. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  224. begin
  225. Temp:=PByte(TypeInfo);
  226. case temp^ of
  227. tkAstring :
  228. fpc_AnsiStr_Incr_Ref(PPointer(Data)^);
  229. {$ifdef HASWIDESTRING}
  230. tkWstring :
  231. fpc_WideStr_Incr_Ref(PPointer(Data)^);
  232. {$endif HASWIDESTRING}
  233. tkArray :
  234. begin
  235. Inc(Temp);
  236. I:=temp^;
  237. inc(temp,I+1); // skip name string;
  238. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  239. move(PArrayRec(Temp)^,ArrayRec,sizeof(ArrayRec));
  240. for I:=0 to ArrayRec.Count-1 do
  241. int_AddRef (Data+(I*ArrayRec.size),ArrayRec.Info);
  242. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  243. Size:=PArrayRec(Temp)^.Size; // get element size
  244. Count:=PArrayRec(Temp)^.Count; // get element Count
  245. TInfo:=PArrayRec(Temp)^.Info; // Get element info
  246. For I:=0 to Count-1 do
  247. int_AddRef (Data+(I*size),TInfo);
  248. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  249. end;
  250. tkobject,
  251. tkrecord :
  252. begin
  253. Inc(Temp);
  254. I:=Temp^;
  255. temp:=temp+(I+1); // skip name string;
  256. temp:=aligntoptr(temp);
  257. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  258. move(PRecRec(Temp)^.Count,Count,sizeof(Count)); // get element Count
  259. For I:=1 to count Do
  260. begin
  261. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(TRecElem));
  262. int_AddRef (Data+RecElem.Offset,RecElem.Info);
  263. end;
  264. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  265. Count:=PRecRec(Temp)^.Count; // get element Count
  266. For I:=1 to count do
  267. With PRecRec(Temp)^.elements[I] do
  268. int_AddRef (Data+Offset,Info);
  269. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  270. end;
  271. tkDynArray:
  272. fpc_dynarray_incr_ref(PPointer(Data)^);
  273. {$ifdef HASINTF}
  274. tkInterface:
  275. Intf_Incr_Ref(PPointer(Data)^);
  276. {$endif HASINTF}
  277. end;
  278. end;
  279. { alias for internal use }
  280. { we use another name else the compiler gets puzzled because of the wrong forward def }
  281. procedure fpc_systemDecRef (Data, TypeInfo : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[external name 'FPC_DECREF'];
  282. Procedure fpc_DecRef (Data, TypeInfo : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[Public,alias : 'FPC_DECREF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  283. { this definition is sometimes (depending on switches)
  284. already defined or not so define it locally to avoid problems PM }
  285. Var Temp : PByte;
  286. I,Count : longint;
  287. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  288. ArrayRec : TArrayRec;
  289. RecElem : TRecElem;
  290. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  291. Size : longint;
  292. TInfo : Pointer;
  293. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  294. begin
  295. Temp:=PByte(TypeInfo);
  296. case temp^ of
  297. { see AddRef for comment about below construct (JM) }
  298. tkAstring:
  299. fpc_AnsiStr_Decr_Ref(PPointer(Data)^);
  300. {$ifdef HASWIDESTRING}
  301. tkWstring:
  302. fpc_WideStr_Decr_Ref(PPointer(Data)^);
  303. {$endif HASWIDESTRING}
  304. tkArray:
  305. begin
  306. inc(Temp);
  307. I:=temp^;
  308. inc(temp,I+1); // skip name string;
  309. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  310. move(PArrayRec(Temp)^,ArrayRec,sizeof(ArrayRec));
  311. for I:=0 to ArrayRec.Count-1 do
  312. fpc_systemDecRef (Data+(I*ArrayRec.size),ArrayRec.Info);
  313. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  314. Size:=PArrayRec(Temp)^.Size; // get element size
  315. Count:=PArrayRec(Temp)^.Count; // get element Count
  316. TInfo:=PArrayRec(Temp)^.Info; // Get element info
  317. For I:=0 to Count-1 do
  318. fpc_systemDecRef (Data+(I*size),TInfo);
  319. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  320. end;
  321. tkobject,
  322. tkrecord:
  323. begin
  324. inc(Temp);
  325. I:=temp^;
  326. inc(temp,I+1); // skip name string;
  327. temp:=aligntoptr(temp);
  328. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  329. move(PRecRec(Temp)^.Count,Count,sizeof(Count)); // get element Count
  330. For I:=1 to count Do
  331. begin
  332. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(TRecElem));
  333. fpc_systemDecRef (Data+RecElem.Offset,RecElem.Info);
  334. end;
  335. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  336. Count:=PRecRec(Temp)^.Count; // get element Count
  337. For I:=1 to count do
  338. With PRecRec(Temp)^.elements[I] do
  339. fpc_systemDecRef (Data+Offset,Info);
  340. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  341. end;
  342. tkDynArray:
  343. fpc_dynarray_decr_ref(PPointer(Data)^,TypeInfo);
  344. {$ifdef HASINTF}
  345. tkInterface:
  346. Intf_Decr_Ref(PPointer(Data)^);
  347. {$endif HASINTF}
  348. end;
  349. end;
  350. procedure fpc_finalize_array(data,typeinfo : pointer;count,size : longint); [Public,Alias:'FPC_FINALIZEARRAY']; {$ifdef hascompilerproc} compilerproc; {$endif}
  351. var
  352. i : longint;
  353. begin
  354. for i:=0 to count-1 do
  355. int_finalize(data+size*i,typeinfo);
  356. end;
  357. {
  358. $Log$
  359. Revision 1.16 2004-10-24 20:01:42 peter
  360. * saveregisters calling convention is obsolete
  361. Revision 1.15 2004/10/04 21:26:16 florian
  362. * rtti alignment fixed
  363. Revision 1.14 2004/08/18 21:03:35 florian
  364. * sparc uses wait4 as well
  365. Revision 1.13 2004/07/02 21:21:09 peter
  366. * decr ref doesn't reset pointer
  367. * finalize resets pointer for astring,wstring
  368. Revision 1.12 2004/05/31 20:25:04 peter
  369. * removed warnings
  370. Revision 1.11 2004/03/27 23:22:38 florian
  371. * fixed alignment issues
  372. Revision 1.10 2004/02/26 16:19:01 peter
  373. * tkclass removed from finalize()
  374. * cleanupinstance now parses the tkclass rtti entry itself and
  375. calls finalize() for the rtti members
  376. Revision 1.9 2004/02/26 12:42:34 michael
  377. + Patch from peter to fix finalize (bug 2975)
  378. Revision 1.8 2004/01/22 22:09:05 peter
  379. * finalize needs to reset to nil after decr_ref
  380. Revision 1.7 2002/09/07 15:07:46 peter
  381. * old logs removed and tabs fixed
  382. Revision 1.6 2002/09/02 18:42:41 peter
  383. * moved genrtti.inc code to rtti
  384. * removed rttip.inc, the generic code is almost as fast and
  385. much easier to maintain and has less risks on bugs
  386. }