rtti.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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);saveregisters;[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. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  112. move(PRecRec(Temp)^.Count,Count,sizeof(Count)); // get element Count
  113. For I:=1 to count Do
  114. begin
  115. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(TRecElem));
  116. int_Initialize (Data+RecElem.Offset,RecElem.Info);
  117. end;
  118. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  119. Count:=PRecRec(Temp)^.Count; // get element Count
  120. For I:=1 to count Do
  121. With PRecRec(Temp)^.elements[I] do
  122. int_Initialize (Data+Offset,Info);
  123. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  124. end;
  125. {$ifdef HASVARIANT}
  126. tkVariant:
  127. variant_init(Variant(PVarData(Data)^))
  128. {$endif HASVARIANT}
  129. end;
  130. end;
  131. Procedure fpc_finalize (Data,TypeInfo: Pointer);saveregisters;[Public,Alias : 'FPC_FINALIZE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  132. { this definition is sometimes (depending on switches)
  133. already defined or not so define it locally to avoid problems PM }
  134. Var Temp : PByte;
  135. I,Count : longint;
  136. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  137. ArrayRec : TArrayRec;
  138. RecElem : TRecElem;
  139. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  140. Size : longint;
  141. TInfo : Pointer;
  142. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  143. begin
  144. Temp:=PByte(TypeInfo);
  145. case temp^ of
  146. tkAstring :
  147. fpc_AnsiStr_Decr_Ref(PPointer(Data)^);
  148. {$ifdef HASWIDESTRING}
  149. tkWstring :
  150. fpc_WideStr_Decr_Ref(PPointer(Data)^);
  151. {$endif HASWIDESTRING}
  152. tkArray :
  153. begin
  154. inc(Temp);
  155. I:=temp^;
  156. inc(temp,I+1); // skip name string;
  157. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  158. move(PArrayRec(Temp)^,ArrayRec,sizeof(ArrayRec));
  159. for I:=0 to ArrayRec.Count-1 do
  160. int_Finalize (Data+(I*ArrayRec.size),ArrayRec.Info);
  161. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  162. Size:=PArrayRec(Temp)^.Size; // get element size
  163. Count:=PArrayRec(Temp)^.Count; // get element Count
  164. TInfo:=PArrayRec(Temp)^.Info; // Get element info
  165. For I:=0 to Count-1 do
  166. int_Finalize (Data+(I*size),TInfo);
  167. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  168. end;
  169. tkObject,
  170. tkRecord:
  171. begin
  172. inc(Temp);
  173. I:=Temp^;
  174. inc(temp,I+1); // skip name string;
  175. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  176. move(PRecRec(Temp)^.Count,Count,sizeof(Count)); // get element Count
  177. For I:=1 to count Do
  178. begin
  179. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(TRecElem));
  180. int_Finalize (Data+RecElem.Offset,RecElem.Info);
  181. end;
  182. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  183. Count:=PRecRec(Temp)^.Count; // get element Count
  184. For I:=1 to count do
  185. With PRecRec(Temp)^.elements[I] do
  186. int_Finalize (Data+Offset,Info);
  187. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  188. end;
  189. {$ifdef HASINTF}
  190. tkInterface:
  191. Intf_Decr_Ref(PPointer(Data)^);
  192. {$endif HASINTF}
  193. tkDynArray:
  194. fpc_dynarray_decr_ref(PPointer(Data)^,TypeInfo);
  195. {$ifdef HASVARIANT}
  196. tkVariant:
  197. variant_clear(Variant(PVarData(Data)^))
  198. {$endif HASVARIANT}
  199. end;
  200. end;
  201. Procedure fpc_Addref (Data,TypeInfo : Pointer);saveregisters; [Public,alias : 'FPC_ADDREF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  202. { this definition is sometimes (depending on switches)
  203. already defined or not so define it locally to avoid problems PM }
  204. Var Temp : PByte;
  205. I,Count : longint;
  206. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  207. ArrayRec : TArrayRec;
  208. RecElem : TRecElem;
  209. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  210. Size : longint;
  211. TInfo : Pointer;
  212. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  213. begin
  214. Temp:=PByte(TypeInfo);
  215. case temp^ of
  216. tkAstring :
  217. fpc_AnsiStr_Incr_Ref(PPointer(Data)^);
  218. {$ifdef HASWIDESTRING}
  219. tkWstring :
  220. fpc_WideStr_Incr_Ref(PPointer(Data)^);
  221. {$endif HASWIDESTRING}
  222. tkArray :
  223. begin
  224. Inc(Temp);
  225. I:=temp^;
  226. inc(temp,I+1); // skip name string;
  227. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  228. move(PArrayRec(Temp)^,ArrayRec,sizeof(ArrayRec));
  229. for I:=0 to ArrayRec.Count-1 do
  230. int_AddRef (Data+(I*ArrayRec.size),ArrayRec.Info);
  231. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  232. Size:=PArrayRec(Temp)^.Size; // get element size
  233. Count:=PArrayRec(Temp)^.Count; // get element Count
  234. TInfo:=PArrayRec(Temp)^.Info; // Get element info
  235. For I:=0 to Count-1 do
  236. int_AddRef (Data+(I*size),TInfo);
  237. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  238. end;
  239. tkobject,
  240. tkrecord :
  241. begin
  242. Inc(Temp);
  243. I:=Temp^;
  244. temp:=temp+(I+1); // skip name string;
  245. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  246. move(PRecRec(Temp)^.Count,Count,sizeof(Count)); // get element Count
  247. For I:=1 to count Do
  248. begin
  249. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(TRecElem));
  250. int_AddRef (Data+RecElem.Offset,RecElem.Info);
  251. end;
  252. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  253. Count:=PRecRec(Temp)^.Count; // get element Count
  254. For I:=1 to count do
  255. With PRecRec(Temp)^.elements[I] do
  256. int_AddRef (Data+Offset,Info);
  257. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  258. end;
  259. tkDynArray:
  260. fpc_dynarray_incr_ref(PPointer(Data)^);
  261. {$ifdef HASINTF}
  262. tkInterface:
  263. Intf_Incr_Ref(PPointer(Data)^);
  264. {$endif HASINTF}
  265. end;
  266. end;
  267. { alias for internal use }
  268. { we use another name else the compiler gets puzzled because of the wrong forward def }
  269. procedure fpc_systemDecRef (Data, TypeInfo : Pointer);saveregisters;[external name 'FPC_DECREF'];
  270. Procedure fpc_DecRef (Data, TypeInfo : Pointer);saveregisters;[Public,alias : 'FPC_DECREF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  271. { this definition is sometimes (depending on switches)
  272. already defined or not so define it locally to avoid problems PM }
  273. Var Temp : PByte;
  274. I,Count : longint;
  275. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  276. ArrayRec : TArrayRec;
  277. RecElem : TRecElem;
  278. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  279. Size : longint;
  280. TInfo : Pointer;
  281. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  282. begin
  283. Temp:=PByte(TypeInfo);
  284. case temp^ of
  285. { see AddRef for comment about below construct (JM) }
  286. tkAstring:
  287. fpc_AnsiStr_Decr_Ref(PPointer(Data)^);
  288. {$ifdef HASWIDESTRING}
  289. tkWstring:
  290. fpc_WideStr_Decr_Ref(PPointer(Data)^);
  291. {$endif HASWIDESTRING}
  292. tkArray:
  293. begin
  294. inc(Temp);
  295. I:=temp^;
  296. inc(temp,I+1); // skip name string;
  297. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  298. move(PArrayRec(Temp)^,ArrayRec,sizeof(ArrayRec));
  299. for I:=0 to ArrayRec.Count-1 do
  300. fpc_systemDecRef (Data+(I*ArrayRec.size),ArrayRec.Info);
  301. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  302. Size:=PArrayRec(Temp)^.Size; // get element size
  303. Count:=PArrayRec(Temp)^.Count; // get element Count
  304. TInfo:=PArrayRec(Temp)^.Info; // Get element info
  305. For I:=0 to Count-1 do
  306. fpc_systemDecRef (Data+(I*size),TInfo);
  307. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  308. end;
  309. tkobject,
  310. tkrecord:
  311. begin
  312. inc(Temp);
  313. I:=temp^;
  314. inc(temp,I+1); // skip name string;
  315. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  316. move(PRecRec(Temp)^.Count,Count,sizeof(Count)); // get element Count
  317. For I:=1 to count Do
  318. begin
  319. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(TRecElem));
  320. fpc_systemDecRef (Data+RecElem.Offset,RecElem.Info);
  321. end;
  322. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  323. Count:=PRecRec(Temp)^.Count; // get element Count
  324. For I:=1 to count do
  325. With PRecRec(Temp)^.elements[I] do
  326. fpc_systemDecRef (Data+Offset,Info);
  327. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  328. end;
  329. tkDynArray:
  330. fpc_dynarray_decr_ref(PPointer(Data)^,TypeInfo);
  331. {$ifdef HASINTF}
  332. tkInterface:
  333. Intf_Decr_Ref(PPointer(Data)^);
  334. {$endif HASINTF}
  335. end;
  336. end;
  337. procedure fpc_finalize_array(data,typeinfo : pointer;count,size : longint); [Public,Alias:'FPC_FINALIZEARRAY']; {$ifdef hascompilerproc} compilerproc; {$endif}
  338. var
  339. i : longint;
  340. begin
  341. for i:=0 to count-1 do
  342. int_finalize(data+size*i,typeinfo);
  343. end;
  344. {
  345. $Log$
  346. Revision 1.12 2004-05-31 20:25:04 peter
  347. * removed warnings
  348. Revision 1.11 2004/03/27 23:22:38 florian
  349. * fixed alignment issues
  350. Revision 1.10 2004/02/26 16:19:01 peter
  351. * tkclass removed from finalize()
  352. * cleanupinstance now parses the tkclass rtti entry itself and
  353. calls finalize() for the rtti members
  354. Revision 1.9 2004/02/26 12:42:34 michael
  355. + Patch from peter to fix finalize (bug 2975)
  356. Revision 1.8 2004/01/22 22:09:05 peter
  357. * finalize needs to reset to nil after decr_ref
  358. Revision 1.7 2002/09/07 15:07:46 peter
  359. * old logs removed and tabs fixed
  360. Revision 1.6 2002/09/02 18:42:41 peter
  361. * moved genrtti.inc code to rtti
  362. * removed rttip.inc, the generic code is almost as fast and
  363. much easier to maintain and has less risks on bugs
  364. }