rtti.inc 12 KB

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