PageRenderTime 30ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/MicroFrameworkPK_v4_1/CLR/Diagnostics/Info_Win32.cpp

https://bitbucket.org/pmfsampaio/netmf-lpc
C++ | 1128 lines | 798 code | 210 blank | 120 comment | 107 complexity | 2fa61db13e0a89d4fb2a2728c374111d MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4. #include "Diagnostics.h"
  5. #include "ManagedElementTypes_Win32.h"
  6. ////////////////////////////////////////////////////////////////////////////////////////////////////
  7. FILE* CLR_RT_Assembly::s_output = NULL;
  8. void CLR_RT_Assembly::Dump_SetDevice( LPCWSTR szFileName )
  9. {
  10. Dump_SetDevice( s_output, szFileName );
  11. }
  12. void CLR_RT_Assembly::Dump_SetDevice( FILE *&outputDeviceFile, LPCWSTR szFileName )
  13. {
  14. if(szFileName)
  15. {
  16. if(_wfopen_s( &outputDeviceFile, szFileName, L"w" ) != 0)
  17. {
  18. wprintf( L"Cannot open '%s' for writing!\n", szFileName );
  19. }
  20. }
  21. }
  22. void CLR_RT_Assembly::Dump_CloseDevice()
  23. {
  24. Dump_CloseDevice( s_output );
  25. }
  26. void CLR_RT_Assembly::Dump_CloseDevice( FILE *&outputDeviceFile )
  27. {
  28. if(outputDeviceFile)
  29. {
  30. fclose( outputDeviceFile ); outputDeviceFile = NULL;
  31. }
  32. }
  33. void CLR_RT_Assembly::Dump_Printf( const char *format, ... )
  34. {
  35. va_list arg;
  36. va_start( arg, format );
  37. if(s_output)
  38. {
  39. vfprintf( s_output, format, arg );
  40. }
  41. else
  42. {
  43. CLR_Debug::PrintfV( format, arg );
  44. }
  45. va_end( arg );
  46. }
  47. void CLR_RT_Assembly::Dump_Printf( FILE *outputDeviceFile, const char *format, ... )
  48. {
  49. va_list arg;
  50. va_start( arg, format );
  51. if(outputDeviceFile)
  52. {
  53. vfprintf( outputDeviceFile, format, arg );
  54. }
  55. else
  56. {
  57. CLR_Debug::PrintfV( format, arg );
  58. }
  59. va_end( arg );
  60. }
  61. //--//
  62. void CLR_RT_Assembly::Dump_Indent( const CLR_RECORD_METHODDEF* md, size_t offset, size_t level )
  63. {
  64. Dump_Printf( " IL_%04x(%04x): ", offset, md->RVA + offset );
  65. while(level--)
  66. {
  67. Dump_Printf( " " );
  68. }
  69. }
  70. void CLR_RT_Assembly::Dump( bool fNoByteCode )
  71. {
  72. int i;
  73. Dump_Printf( "Assembly: %s (%d.%d.%d.%d)\n\n", m_szName, m_header->version.iMajorVersion, m_header->version.iMinorVersion, m_header->version.iBuildNumber, m_header->version.iRevisionNumber );
  74. Dump_Printf( "Size: AssemblyRef %6d byte(s) %6d item(s) [Runtime: %6d]\n", m_pTablesSize[ TBL_AssemblyRef ] * sizeof(CLR_RECORD_ASSEMBLYREF ), m_pTablesSize[ TBL_AssemblyRef ], m_pTablesSize[ TBL_AssemblyRef ] * sizeof(CLR_RT_AssemblyRef_CrossReference) );
  75. Dump_Printf( "Size: TypeRef %6d byte(s) %6d item(s) [Runtime: %6d]\n", m_pTablesSize[ TBL_TypeRef ] * sizeof(CLR_RECORD_TYPEREF ), m_pTablesSize[ TBL_TypeRef ], m_pTablesSize[ TBL_TypeRef ] * sizeof(CLR_RT_TypeRef_CrossReference ) );
  76. Dump_Printf( "Size: FieldRef %6d byte(s) %6d item(s) [Runtime: %6d]\n", m_pTablesSize[ TBL_FieldRef ] * sizeof(CLR_RECORD_FIELDREF ), m_pTablesSize[ TBL_FieldRef ], m_pTablesSize[ TBL_FieldRef ] * sizeof(CLR_RT_FieldRef_CrossReference ) );
  77. Dump_Printf( "Size: MethodRef %6d byte(s) %6d item(s) [Runtime: %6d]\n", m_pTablesSize[ TBL_MethodRef ] * sizeof(CLR_RECORD_METHODREF ), m_pTablesSize[ TBL_MethodRef ], m_pTablesSize[ TBL_MethodRef ] * sizeof(CLR_RT_MethodRef_CrossReference ) );
  78. Dump_Printf( "Size: TypeDef %6d byte(s) %6d item(s) [Runtime: %6d]\n", m_pTablesSize[ TBL_TypeDef ] * sizeof(CLR_RECORD_TYPEDEF ), m_pTablesSize[ TBL_TypeDef ], m_pTablesSize[ TBL_TypeDef ] * sizeof(CLR_RT_TypeDef_CrossReference ) );
  79. Dump_Printf( "Size: FieldDef %6d byte(s) %6d item(s) [Runtime: %6d]\n", m_pTablesSize[ TBL_FieldDef ] * sizeof(CLR_RECORD_FIELDDEF ), m_pTablesSize[ TBL_FieldDef ], m_pTablesSize[ TBL_FieldDef ] * sizeof(CLR_RT_FieldDef_CrossReference ) );
  80. Dump_Printf( "Size: MethodDef %6d byte(s) %6d item(s) [Runtime: %6d]\n", m_pTablesSize[ TBL_MethodDef ] * sizeof(CLR_RECORD_METHODDEF ), m_pTablesSize[ TBL_MethodDef ], m_pTablesSize[ TBL_MethodDef ] * sizeof(CLR_RT_MethodDef_CrossReference ) );
  81. Dump_Printf( "Size: Attributes %6d byte(s) %6d item(s)\n" , m_pTablesSize[ TBL_Attributes ] * sizeof(CLR_RECORD_ATTRIBUTE ), m_pTablesSize[ TBL_Attributes ] );
  82. Dump_Printf( "Size: TypeSpec %6d byte(s) %6d item(s)\n" , m_pTablesSize[ TBL_TypeSpec ] * sizeof(CLR_RECORD_TYPESPEC ), m_pTablesSize[ TBL_TypeSpec ] );
  83. Dump_Printf( "Size: Resources Files %6d byte(s) %6d item(s)\n" , m_pTablesSize[ TBL_ResourcesFiles ] * sizeof(CLR_RECORD_RESOURCE_FILE), m_pTablesSize[ TBL_ResourcesFiles ] );
  84. Dump_Printf( "Size: Resources %6d byte(s) %6d item(s)\n" , m_pTablesSize[ TBL_Resources ] * sizeof(CLR_RECORD_RESOURCE ), m_pTablesSize[ TBL_Resources ] );
  85. Dump_Printf( "Size: ResourcesData %6d byte(s)\n" , m_pTablesSize[ TBL_ResourcesData ] );
  86. Dump_Printf( "Size: Strings %6d byte(s)\n" , m_pTablesSize[ TBL_Strings ] );
  87. Dump_Printf( "Size: Signatures %6d byte(s)\n" , m_pTablesSize[ TBL_Signatures ] );
  88. Dump_Printf( "Size: ByteCode %6d byte(s)\n\n\n" , m_pTablesSize[ TBL_ByteCode ] );
  89. #define ASMOFF(x) (UINT32)((size_t)x - (size_t)m_header)
  90. for(i=0; i<m_pTablesSize[ TBL_AssemblyRef ]; i++)
  91. {
  92. const CLR_RECORD_ASSEMBLYREF* p = GetAssemblyRef( i );
  93. Dump_Printf( "AssemblyRef: %04x[%08x] %s (%d.%d.%d.%d)\n", i, ASMOFF(p), GetString( p->name ), p->version.iMajorVersion, p->version.iMinorVersion, p->version.iBuildNumber, p->version.iRevisionNumber );
  94. }
  95. if(i) Dump_Printf( "\n" );
  96. for(i=0; i<m_pTablesSize[ TBL_TypeRef ]; i++)
  97. {
  98. const CLR_RECORD_TYPEREF* p = GetTypeRef( i );
  99. Dump_Printf( "TypeRef %04x[%08x] [Scope: %04x] %s %s\n", i, ASMOFF(p), p->scope, GetString( p->nameSpace ), GetString( p->name ) );
  100. }
  101. if(i) Dump_Printf( "\n" );
  102. for(i=0; i<m_pTablesSize[ TBL_FieldRef ]; i++)
  103. {
  104. const CLR_RECORD_FIELDREF* p = GetFieldRef( i );
  105. Dump_Printf ( "FieldRef %04x[%08x] [Type: %04x] %s [", i, ASMOFF(p), p->container, GetString( p->name ) );
  106. Dump_Signature( p->sig );
  107. Dump_Printf ( "]\n" );
  108. }
  109. if(i) Dump_Printf( "\n" );
  110. for(i=0; i<m_pTablesSize[ TBL_MethodRef ]; i++)
  111. {
  112. const CLR_RECORD_METHODREF* p = GetMethodRef( i );
  113. Dump_Printf ( "MethodRef %04x[%08x] [Type: %04x] %s [", i, ASMOFF(p), p->container, GetString( p->name ) );
  114. Dump_Signature( p->sig );
  115. Dump_Printf ( "]\n" );
  116. }
  117. if(i) Dump_Printf( "\n" );
  118. for(i=0; i<m_pTablesSize[ TBL_TypeDef ]; i++)
  119. {
  120. const CLR_RECORD_TYPEDEF* p = GetTypeDef( i );
  121. Dump_Printf( "TypeDef %04x[%08x] [Extends: %04x] [Enclosed: %04x] [Flags: %08x] %s %s\n", i, ASMOFF(p), p->extends, p->enclosingType, p->flags, GetString( p->nameSpace ), GetString( p->name ) );
  122. }
  123. if(i) Dump_Printf( "\n" );
  124. for(i=0; i<m_pTablesSize[ TBL_FieldDef ]; i++)
  125. {
  126. const CLR_RECORD_FIELDDEF* p = GetFieldDef( i );
  127. Dump_Printf ( "FieldDef %04x[%08x] [Flags: %08x] ", i, ASMOFF(p), p->flags );
  128. Dump_FieldOwner( i );
  129. Dump_Printf ( "::%s [", GetString( p->name ) );
  130. Dump_Signature ( p->sig );
  131. Dump_Printf ( "]\n" );
  132. }
  133. if(i) Dump_Printf( "\n" );
  134. for(i=0; i<m_pTablesSize[ TBL_MethodDef ]; i++)
  135. {
  136. const CLR_RECORD_METHODDEF* p = GetMethodDef( i );
  137. Dump_Printf ( "MethodDef %04x[%08x] [Flags: %08x] [RVA: %04x] ", i, ASMOFF(p), p->flags, p->RVA );
  138. Dump_MethodOwner( i );
  139. Dump_Printf ( "::%s [", GetString( p->name ) );
  140. Dump_Signature ( p->sig );
  141. Dump_Printf ( "]\n" );
  142. }
  143. for(i=0; i<m_pTablesSize[ TBL_Attributes ]; i++)
  144. {
  145. const CLR_RECORD_ATTRIBUTE* p = GetAttribute( i );
  146. Dump_Printf( "Attribute %04x[%08x] [%04x:%04x] %04x %04x\n", i, ASMOFF(p), p->ownerType, p->ownerIdx, p->constructor, p->data );
  147. }
  148. if(i) Dump_Printf( "\n" );
  149. for(i=0; i<m_pTablesSize[ TBL_Resources ]-1; i++)
  150. {
  151. const CLR_RECORD_RESOURCE* p = GetResource( i );
  152. const CLR_RECORD_RESOURCE* pNext = GetResource( i+1 );
  153. CLR_UINT16 size = pNext->offset - p->offset;
  154. Dump_Printf( "Resource %04x[%08x] [%08x:%1d] %04x %08x[%08x]\n", i, ASMOFF(p), p->id, p->kind, size, p->offset, ASMOFF(GetResourceData( p->offset )) );
  155. }
  156. if(i) Dump_Printf( "\n" );
  157. #undef ASMOFF
  158. }
  159. //--//
  160. void CLR_RT_Assembly::Dump_FieldOwner( CLR_UINT32 idx )
  161. {
  162. const CLR_RECORD_TYPEDEF* td = GetTypeDef( 0 );
  163. for(CLR_IDX i=0; i<m_pTablesSize[TBL_TypeDef]; i++, td++)
  164. {
  165. if((idx >= td->iFields_First && idx < (CLR_UINT32)(td->iFields_First + td->iFields_Num)) ||
  166. (idx >= td->sFields_First && idx < (CLR_UINT32)(td->sFields_First + td->sFields_Num)) )
  167. {
  168. Dump_Token( CLR_TkFromType( TBL_TypeDef, i ) );
  169. return;
  170. }
  171. }
  172. }
  173. void CLR_RT_Assembly::Dump_MethodOwner( CLR_UINT32 idx )
  174. {
  175. const CLR_RECORD_TYPEDEF* td = GetTypeDef( 0 );
  176. for(CLR_IDX i=0; i<m_pTablesSize[ TBL_TypeDef ]; i++, td++)
  177. {
  178. if(idx >= td->methods_First && idx < (CLR_UINT32)(td->methods_First + td->sMethods_Num + td->iMethods_Num + td->vMethods_Num))
  179. {
  180. Dump_Token( CLR_TkFromType( TBL_TypeDef, i ) );
  181. return;
  182. }
  183. }
  184. }
  185. void CLR_RT_Assembly::Dump_Token( CLR_UINT32 tk )
  186. {
  187. CLR_UINT32 idx = CLR_DataFromTk( tk );
  188. switch(CLR_TypeFromTk(tk))
  189. {
  190. case TBL_AssemblyRef: { const CLR_RECORD_ASSEMBLYREF* p = GetAssemblyRef( idx ); Dump_Printf( "[%s]" , GetString( p->name ) ); break; }
  191. case TBL_TypeRef : { const CLR_RECORD_TYPEREF * p = GetTypeRef ( idx ); Dump_Printf( "%s.%s", GetString( p->nameSpace ), GetString( p->name ) ); break; }
  192. case TBL_FieldRef : { const CLR_RECORD_FIELDREF * p = GetFieldRef ( idx ); Dump_Token( CLR_TkFromType( TBL_TypeRef, p->container ) ); Dump_Printf( "::%s" , GetString( p->name ) ); break; }
  193. case TBL_MethodRef : { const CLR_RECORD_METHODREF * p = GetMethodRef ( idx ); Dump_Token( CLR_TkFromType( TBL_TypeRef, p->container ) ); Dump_Printf( "::%s" , GetString( p->name ) ); break; }
  194. case TBL_TypeDef : { const CLR_RECORD_TYPEDEF * p = GetTypeDef ( idx ); if(p->enclosingType != CLR_EmptyIndex) Dump_Token( CLR_TkFromType( TBL_TypeDef, p->enclosingType ) ); Dump_Printf( "%s.%s", GetString( p->nameSpace ), GetString( p->name ) ); break; }
  195. case TBL_FieldDef : { const CLR_RECORD_FIELDDEF * p = GetFieldDef ( idx ); Dump_FieldOwner ( idx ); Dump_Printf( "::%s" , GetString( p->name ) ); break; }
  196. case TBL_MethodDef : { const CLR_RECORD_METHODDEF * p = GetMethodDef ( idx ); Dump_MethodOwner( idx ); Dump_Printf( "::%s" , GetString( p->name ) ); break; }
  197. case TBL_Strings : { LPCSTR p = GetString ( idx ); Dump_Printf( "'%s'" , p ); break; }
  198. default:
  199. Dump_Printf( "[%08x]", tk );
  200. }
  201. }
  202. void CLR_RT_Assembly::Dump_Signature( CLR_SIG sig )
  203. {
  204. const CLR_UINT8* p = GetSignature( sig );
  205. CLR_UINT32 len;
  206. CLR_CorCallingConvention cc = (CLR_CorCallingConvention)*p++;
  207. switch(cc & PIMAGE_CEE_CS_CALLCONV_MASK)
  208. {
  209. case PIMAGE_CEE_CS_CALLCONV_FIELD:
  210. Dump_Printf ( "FIELD " );
  211. Dump_Signature( p );
  212. break;
  213. case PIMAGE_CEE_CS_CALLCONV_LOCAL_SIG:
  214. break;
  215. case PIMAGE_CEE_CS_CALLCONV_DEFAULT:
  216. len = *p++;
  217. Dump_Printf ( "METHOD " );
  218. Dump_Signature( p );
  219. Dump_Printf ( "(" );
  220. while(len-- > 0)
  221. {
  222. Dump_Printf ( " " );
  223. Dump_Signature( p );
  224. if(len) Dump_Printf( "," );
  225. else Dump_Printf( " " );
  226. }
  227. Dump_Printf( ")" );
  228. break;
  229. }
  230. }
  231. void CLR_RT_Assembly::Dump_Signature( const CLR_UINT8*& p )
  232. {
  233. CLR_DataType opt = CLR_UncompressElementType( p );
  234. switch(opt)
  235. {
  236. case DATATYPE_VOID : Dump_Printf( "VOID" ); break;
  237. case DATATYPE_BOOLEAN : Dump_Printf( "BOOLEAN" ); break;
  238. case DATATYPE_CHAR : Dump_Printf( "CHAR" ); break;
  239. case DATATYPE_I1 : Dump_Printf( "I1" ); break;
  240. case DATATYPE_U1 : Dump_Printf( "U1" ); break;
  241. case DATATYPE_I2 : Dump_Printf( "I2" ); break;
  242. case DATATYPE_U2 : Dump_Printf( "U2" ); break;
  243. case DATATYPE_I4 : Dump_Printf( "I4" ); break;
  244. case DATATYPE_U4 : Dump_Printf( "U4" ); break;
  245. case DATATYPE_I8 : Dump_Printf( "I8" ); break;
  246. case DATATYPE_U8 : Dump_Printf( "U8" ); break;
  247. case DATATYPE_R4 : Dump_Printf( "R4" ); break;
  248. case DATATYPE_R8 : Dump_Printf( "R8" ); break;
  249. case DATATYPE_STRING : Dump_Printf( "STRING" ); break;
  250. case DATATYPE_BYREF : Dump_Printf( "BYREF " ); Dump_Signature ( p ); break;
  251. case DATATYPE_VALUETYPE : Dump_Printf( "VALUETYPE " ); Dump_SignatureToken( p ); break;
  252. case DATATYPE_CLASS : Dump_Printf( "CLASS " ); Dump_SignatureToken( p ); break;
  253. case DATATYPE_OBJECT : Dump_Printf( "OBJECT" ); break;
  254. case DATATYPE_SZARRAY : Dump_Printf( "SZARRAY " ); Dump_Signature ( p ); break;
  255. default : Dump_Printf( "[UNKNOWN: %08x]", opt ); break;
  256. }
  257. }
  258. void CLR_RT_Assembly::Dump_SignatureToken( const CLR_UINT8*& p )
  259. {
  260. CLR_UINT32 tk = CLR_TkFromStream( p );
  261. Dump_Printf( "[%08x]", tk );
  262. }
  263. //--//
  264. void CLR_RT_TypeSystem::Dump( LPCWSTR szFileName, bool fNoByteCode )
  265. {
  266. CLR_RT_Assembly::Dump_SetDevice( szFileName );
  267. TINYCLR_FOREACH_ASSEMBLY(*this)
  268. {
  269. pASSM->Dump( fNoByteCode );
  270. }
  271. TINYCLR_FOREACH_ASSEMBLY_END();
  272. CLR_RT_Assembly::Dump_CloseDevice();
  273. }
  274. //--//
  275. static void RemoveDots( string& str )
  276. {
  277. while(true)
  278. {
  279. string::size_type pos = str.find( '.' ); if(pos == str.npos) break;
  280. str[ pos ] = '_';
  281. }
  282. }
  283. static bool IncludeInStub( const CLR_RECORD_TYPEDEF* td )
  284. {
  285. //
  286. // Only generate a stub for classes and value types.
  287. //
  288. if(td->flags & (CLR_RECORD_TYPEDEF::TD_Delegate | CLR_RECORD_TYPEDEF::TD_MulticastDelegate)) return false;
  289. switch(td->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask)
  290. {
  291. case CLR_RECORD_TYPEDEF::TD_Semantics_Class:
  292. case CLR_RECORD_TYPEDEF::TD_Semantics_ValueType:
  293. return true;
  294. default:
  295. return false;
  296. }
  297. }
  298. static bool IncludeInStub( const CLR_RECORD_METHODDEF* md )
  299. {
  300. return (md->RVA == CLR_EmptyIndex) && ((md->flags & md->MD_Abstract) == 0);
  301. }
  302. //--//
  303. static const CHAR c_DO_NOT_EDIT_THIS_FILE_Header[] =
  304. "//-----------------------------------------------------------------------------\n"
  305. "//\n"
  306. "// ** DO NOT EDIT THIS FILE! **\n"
  307. "// This file was generated by a tool\n"
  308. "// re-running the tool will overwrite this file.\n"
  309. "//\n"
  310. "//-----------------------------------------------------------------------------\n"
  311. "\n\n";
  312. //--//
  313. static const CHAR c_WARNING_FILE_OVERWRITE_Header[] =
  314. "//-----------------------------------------------------------------------------\n"
  315. "//\n"
  316. "// ** WARNING! ** \n"
  317. "// This file was generated automatically by a tool.\n"
  318. "// Re-running the tool will overwrite this file.\n"
  319. "// You should copy this file to a custom location\n"
  320. "// before adding any customization in the copy to\n"
  321. "// prevent loss of your changes when the tool is\n"
  322. "// re-run.\n"
  323. "//\n"
  324. "//-----------------------------------------------------------------------------\n"
  325. "\n\n";
  326. static const CHAR c_Include_Interop_h[] =
  327. "#include <TinyCLR_Interop.h>\n";
  328. //--//
  329. static const CHAR c_Type_Begin[] =
  330. "struct Library_%S_%s\n" \
  331. "{\n";
  332. static const CHAR c_Type_Field_Static[] =
  333. " static const int FIELD_STATIC__%s = %d;\n";
  334. static const CHAR c_Type_Field_Instance[] =
  335. " static const int FIELD__%s = %d;\n";
  336. static const CHAR c_Type_Method[] =
  337. " TINYCLR_NATIVE_DECLARE(%s);\n";
  338. static const CHAR c_Type_End[] =
  339. "\n"
  340. " //--//\n"
  341. "\n"
  342. "};\n\n";
  343. //--//
  344. static const CHAR c_Definition_Begin[] =
  345. "#include \"%S.h\"\n"
  346. "\n"
  347. "\n"
  348. "static const CLR_RT_MethodHandler method_lookup[] =\n"
  349. "{\n";
  350. static const CHAR c_Definition_Body[] = " Library_%S_%s::%s,\n";
  351. static const CHAR c_Definition_End[] =
  352. "};\n"
  353. "\n"
  354. "const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_%s =\n"
  355. "{\n"
  356. " \"%s\", \n"
  357. " 0x%08X,\n"
  358. " method_lookup\n"
  359. "};\n\n";
  360. static const CHAR c_Method[] =
  361. "\nHRESULT Library_%S_%s::%s( CLR_RT_StackFrame& stack )\n"
  362. "{\n"
  363. "%s"
  364. "}\n";
  365. //--//
  366. static const CHAR c_Project_Gen_Project_Open[] = "<Project DefaultTargets=\"Build\" ToolsVersion=\"3.5\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n";
  367. static const CHAR c_Project_Gen_Project_Close[] = "</Project>\n";
  368. static const CHAR c_Project_Gen_Import_Project[] = "<Import Project=\"$(SPOCLIENT)\\tools\\targets\\Microsoft.SPOT.System.Targets\" />\n";
  369. static const CHAR c_Project_Gen_Property_Group []=
  370. " <PropertyGroup>\n"
  371. " <Directory>DeviceCode\\Targets\\Native\\Interop\\%S</Directory>\n"
  372. " <AssemblyName>%S</AssemblyName>\n"
  373. " </PropertyGroup>\n"
  374. " <Import Project=\"$(SPOCLIENT)\\tools\\targets\\Microsoft.SPOT.System.Settings\" />\n"
  375. " <PropertyGroup>\n"
  376. " <OutputType>Library</OutputType>\n"
  377. " </PropertyGroup>\n";
  378. static const CHAR c_Project_Gen_Item_Group_Open[] = "<ItemGroup>\n";
  379. static const CHAR c_Project_Gen_Item_Group_Close[] = "</ItemGroup>\n";
  380. //--//
  381. void CLR_RT_Assembly::BuildClassName( const CLR_RECORD_TYPEREF* tr, string& cls_name, bool fEscape )
  382. {
  383. cls_name.clear();
  384. if(tr->scope & 0x8000) // Flag for TypeRef
  385. {
  386. const CLR_RECORD_TYPEREF* trS = GetTypeRef( tr->scope & 0x7FFF );
  387. BuildClassName( GetTypeRef( tr->scope & 0x7FFF ), cls_name, fEscape );
  388. cls_name += ".";
  389. }
  390. else
  391. {
  392. const CLR_RECORD_ASSEMBLYREF* ar = GetAssemblyRef( tr->scope );
  393. cls_name = GetString( ar->name );
  394. cls_name += ".";
  395. }
  396. if(tr->nameSpace != CLR_EmptyIndex)
  397. {
  398. cls_name += GetString( tr->nameSpace );
  399. cls_name += ".";
  400. }
  401. cls_name += GetString( tr->name );
  402. if(fEscape) RemoveDots( cls_name );
  403. }
  404. void CLR_RT_Assembly::BuildClassName( const CLR_RECORD_TYPEDEF* td, string& cls_name, bool fEscape )
  405. {
  406. cls_name.clear();
  407. if(td->enclosingType != CLR_EmptyIndex)
  408. {
  409. BuildClassName( GetTypeDef( td->enclosingType ), cls_name, fEscape );
  410. cls_name += ".";
  411. }
  412. if(td->nameSpace != CLR_EmptyIndex)
  413. {
  414. cls_name += GetString( td->nameSpace );
  415. cls_name += ".";
  416. }
  417. cls_name += GetString( td->name );
  418. if(fEscape) RemoveDots( cls_name );
  419. }
  420. void CLR_RT_Assembly::BuildTypeName( const CLR_RECORD_TYPEDEF* td, std::string& type_name )
  421. {
  422. type_name.clear();
  423. if(td->enclosingType != CLR_EmptyIndex)
  424. {
  425. BuildTypeName( GetTypeDef( td->enclosingType ), type_name );
  426. type_name += "_";
  427. }
  428. if(td->nameSpace != CLR_EmptyIndex)
  429. {
  430. std::string strNameSpace = GetString( td->nameSpace );
  431. // Avoid creation of extra dot if namespace is empty.
  432. if ( !strNameSpace.empty() )
  433. {
  434. type_name += strNameSpace;
  435. type_name += ".";
  436. }
  437. }
  438. type_name += GetString( td->name );
  439. }
  440. void CLR_RT_Assembly::BuildParametersList( CLR_PMETADATA pMetaData, CLR_RT_VectorOfManagedElements &elemPtrArray )
  441. {
  442. pMetaData++; // Skip Calling convention.
  443. CLR_UINT32 elemCount = *pMetaData++ + 1;
  444. // Iterates until end of information with paramenters types.
  445. for ( CLR_UINT32 curElem = 0; curElem < elemCount; curElem++ )
  446. {
  447. CLR_RT_ManagedElementType *pNewElement = NULL;
  448. // Get next element type.
  449. CLR_DataType opt = CLR_UncompressElementType( pMetaData );
  450. switch ( opt )
  451. {
  452. // In case or array or reference we extract the type of element.
  453. case DATATYPE_BYREF : pNewElement = new CLR_RT_ManagedElementTypeByRef( CLR_UncompressElementType( pMetaData ) ); break;
  454. case DATATYPE_SZARRAY: pNewElement = new CLR_RT_ManagedElementTypeArray( CLR_UncompressElementType( pMetaData ) ); break;
  455. case DATATYPE_VALUETYPE :
  456. {
  457. CLR_UINT32 token = CLR_TkFromStream( pMetaData );
  458. const CLR_RECORD_TYPEDEF *pTypeDef = GetTypeDef( CLR_DataFromTk( token ) );
  459. pNewElement = new CLR_RT_ManagedElementType( (CLR_DataType)pTypeDef->dataType );
  460. }
  461. break;
  462. // If it is not a reference or object - means basic type, we create CLR_RT_ManagedElementType
  463. default : pNewElement = new CLR_RT_ManagedElementType( opt );
  464. }
  465. // Adds pointer to new element to array.
  466. elemPtrArray.push_back( pNewElement );
  467. }
  468. }
  469. void CLR_RT_Assembly::BuildMethodName( const CLR_RECORD_METHODDEF* md, std::string& name, CLR_RT_StringMap& mapMethods )
  470. {
  471. CHAR buffer[ 256 ];
  472. CLR_PMETADATA p = GetSignature( md->sig ); p++; // Skip Calling convention.
  473. CLR_UINT32 len = *p++ + 1;
  474. name = GetString( md->name ); RemoveDots( name );
  475. for(CLR_UINT32 a=0; a<len; a++)
  476. {
  477. bool fContinue = true;
  478. if(a == 0)
  479. {
  480. name += "___";
  481. if(md->flags & CLR_RECORD_METHODDEF::MD_Static)
  482. {
  483. name += "STATIC__";
  484. }
  485. }
  486. while(fContinue)
  487. {
  488. CLR_DataType opt = CLR_UncompressElementType( p );
  489. switch(opt)
  490. {
  491. case DATATYPE_VOID : name += "VOID" ; break;
  492. case DATATYPE_BOOLEAN : name += "BOOLEAN" ; break;
  493. case DATATYPE_CHAR : name += "CHAR" ; break;
  494. case DATATYPE_I1 : name += "I1" ; break;
  495. case DATATYPE_U1 : name += "U1" ; break;
  496. case DATATYPE_I2 : name += "I2" ; break;
  497. case DATATYPE_U2 : name += "U2" ; break;
  498. case DATATYPE_I4 : name += "I4" ; break;
  499. case DATATYPE_U4 : name += "U4" ; break;
  500. case DATATYPE_I8 : name += "I8" ; break;
  501. case DATATYPE_U8 : name += "U8" ; break;
  502. case DATATYPE_R4 : name += "R4" ; break;
  503. case DATATYPE_R8 : name += "R8" ; break;
  504. case DATATYPE_STRING : name += "STRING" ; break;
  505. case DATATYPE_BYREF : name += "BYREF" ; break;
  506. case DATATYPE_VALUETYPE : ; break;
  507. case DATATYPE_CLASS : ; break;
  508. case DATATYPE_OBJECT : name += "OBJECT" ; break;
  509. case DATATYPE_SZARRAY : name += "SZARRAY" ; break;
  510. }
  511. fContinue = false;
  512. switch(opt)
  513. {
  514. case DATATYPE_BYREF :
  515. case DATATYPE_SZARRAY:
  516. fContinue = true;
  517. name += "_";
  518. break;
  519. case DATATYPE_VALUETYPE:
  520. case DATATYPE_CLASS :
  521. {
  522. CLR_UINT32 tk = CLR_TkFromStream( p );
  523. std::string cls;
  524. switch(CLR_TypeFromTk(tk))
  525. {
  526. case TBL_TypeDef : BuildClassName( GetTypeDef( CLR_DataFromTk( tk ) ), cls, true ); break;
  527. case TBL_TypeRef : BuildClassName( GetTypeRef( CLR_DataFromTk( tk ) ), cls, true ); break;
  528. case TBL_TypeSpec: sprintf_s( buffer, ARRAYSIZE(buffer), "_%08X", tk ); cls = buffer; break;
  529. }
  530. while(true)
  531. {
  532. std::string::size_type pos = cls.find( '_' ); if(pos == cls.npos) break;
  533. cls.erase( pos, 1 );
  534. }
  535. name += cls;
  536. }
  537. break;
  538. }
  539. }
  540. if(a != len-1) name += "__";
  541. }
  542. int num = mapMethods[name];
  543. if(num++)
  544. {
  545. sprintf_s( buffer, ARRAYSIZE(buffer), "_%d", num ); name += buffer;
  546. }
  547. mapMethods[name] = num;
  548. }
  549. static string ReplaceDotWithString( string strName, string strReplace )
  550. {
  551. for ( string::iterator strp_Iter = strName.begin();
  552. strp_Iter != strName.end();
  553. strp_Iter++
  554. )
  555. {
  556. if ( *strp_Iter == '.' )
  557. {
  558. string::iterator thisPos = strp_Iter;
  559. strName.replace( thisPos, ++strp_Iter, strReplace );
  560. }
  561. }
  562. return strName;
  563. }
  564. static string BuildHeaderDefMacro( LPCWSTR lpwzHeaderFilePath )
  565. {
  566. WCHAR swDrive[ _MAX_DRIVE ], swDir[ _MAX_DIR ], swName[ _MAX_FNAME ], swExt[ _MAX_EXT ];
  567. // Breaks path into pieces to find the name of header file.
  568. _wsplitpath_s( lpwzHeaderFilePath, swDrive, ARRAYSIZE(swDrive), swDir, ARRAYSIZE(swDir), swName, ARRAYSIZE(swName), swExt, ARRAYSIZE(swExt) );
  569. // Convert to ASCII and build macro name.
  570. CHAR szHeaderDefMacro[ _MAX_PATH + 5 ];
  571. sprintf_s( szHeaderDefMacro, sizeof( szHeaderDefMacro ), "_%S_H_", swName );
  572. // Converts file name to uppper case.
  573. _strupr_s( szHeaderDefMacro, sizeof( szHeaderDefMacro ) );
  574. return string( szHeaderDefMacro );
  575. }
  576. // Generate the call to native stublike like in example:
  577. // "INT64 AddValues( param0, param1, param3, hr );"
  578. static string BuildCalltoNativeStub( bool bStaticMember, string strMethodName, string strAssemblyName, CLR_RT_VectorOfManagedElements &elemPtrArray )
  579. {
  580. // Return type with function name like "INT64 AddValues("
  581. string strClassNames = ReplaceDotWithString( strAssemblyName, "::" );
  582. string strCall;
  583. // Add return value if native type is not "void".
  584. // If we do not check for void type, we get code like "void retVal = ...".
  585. if ( !elemPtrArray[ 0 ]->IsVoidType() )
  586. {
  587. strCall += elemPtrArray[ 0 ]->GetNativeType() + " retVal = ";
  588. }
  589. // Add function call. We pre-pend class name to the function name
  590. strCall += strClassNames + "::" + strMethodName + "(";
  591. if ( !bStaticMember )
  592. {
  593. // For non-static member functions we add one more parameter - managed "fields"
  594. strCall += " pMngObj, ";
  595. }
  596. // Now parameters.
  597. for ( UINT32 i = 1; i < elemPtrArray.size(); i++ )
  598. {
  599. // For each parameter add string like " INT8 param0,"
  600. strCall += " param" + CLR_RT_ManagedElementType::GetParamIndexAsText( i - 1 ) + ",";
  601. }
  602. // The last parameter is " hr );"
  603. strCall += " hr );";
  604. return strCall;
  605. }
  606. static string BuildDeclarationOfNativeStub( string strMethodName, string strAssemblyName, CLR_RT_VectorOfManagedElements &elemPtrArray, bool bStaticMethod )
  607. {
  608. // Return type with function name like "INT64 AddValues("
  609. string strCall = elemPtrArray[ 0 ]->GetNativeType() + " ";
  610. // Include class name if passed - example : "INT64 TestBasicTypes::AddValues(
  611. if ( strAssemblyName.length() > 0 )
  612. {
  613. strCall += strAssemblyName + "::";
  614. }
  615. strCall += strMethodName + "( ";
  616. // For non-static methods we need to add CLR_RT_HeapBlock *pMngObj parameter.
  617. // The pMngObj is actually pointer to managed object
  618. if ( !bStaticMethod )
  619. {
  620. strCall += "CLR_RT_HeapBlock* pMngObj, ";
  621. }
  622. // Now parameters.
  623. for ( UINT32 i = 1; i < elemPtrArray.size(); i++ )
  624. {
  625. // For each parameter add string like " INT8 param0,"
  626. strCall += elemPtrArray[ i ]->GetVariableDecl() + " param" + CLR_RT_ManagedElementType::GetParamIndexAsText( i - 1 ) + ", ";
  627. }
  628. // The last parameter is " hr );"
  629. strCall += "HRESULT &hr )";
  630. return strCall;
  631. }
  632. static void BuildNameSpaceVector( string strNameSpace, vector<string> &vectNameSpace )
  633. {
  634. // Need a copy of the string, since strtok actually modifies the string
  635. LPSTR lpszNameSpace = new char[ strNameSpace.length() + 1 ];
  636. strcpy_s( lpszNameSpace, strNameSpace.length() + 1, strNameSpace.c_str() );
  637. LPSTR lpszContext;
  638. // Finds each token separated by "." and adds as separate string to vectNameSpace
  639. LPCSTR lpszName = strtok_s( lpszNameSpace, ".", &lpszContext );
  640. while ( lpszName != NULL )
  641. {
  642. vectNameSpace.push_back( string( lpszName ) );
  643. lpszName = strtok_s( NULL, ".", &lpszContext );
  644. }
  645. delete [] lpszNameSpace;
  646. }
  647. static std::wstring GetFNameWithExtFromFilePath( LPCWSTR lpwFilePath )
  648. {
  649. // Split full path into pieces.
  650. wchar_t szDrive[ _MAX_DRIVE ], szDir[ _MAX_DIR ], szFileName[ _MAX_FNAME ], szExt[ _MAX_EXT ];
  651. _wsplitpath_s( lpwFilePath, szDrive, ARRAYSIZE(szDrive), szDir, ARRAYSIZE(szDir), szFileName, ARRAYSIZE(szFileName), szExt, ARRAYSIZE(szExt) );
  652. // Adds file name and extention.
  653. return std::wstring( szFileName ) + szExt;
  654. }
  655. static std::wstring GetDirPathFromFilePath( LPCWSTR lpwFilePath )
  656. {
  657. // Split full path into pieces.
  658. wchar_t szDrive[ _MAX_DRIVE ], szDir[ _MAX_DIR ], szFileName[ _MAX_FNAME ], szExt[ _MAX_EXT ];
  659. _wsplitpath_s( lpwFilePath, szDrive, ARRAYSIZE(szDrive), szDir, ARRAYSIZE(szDir), szFileName, ARRAYSIZE(szFileName), szExt, ARRAYSIZE(szExt) );
  660. // Adds drive name and directory name.
  661. return std::wstring( szDrive ) + szDir;
  662. }
  663. static void UpdateCRC( UINT32& crc, LPCSTR str )
  664. {
  665. crc = SUPPORT_ComputeCRC( str, (int)hal_strlen_s( str ), crc );
  666. }
  667. UINT32 CLR_RT_Assembly::GenerateSignatureForNativeMethods()
  668. {
  669. UINT32 crc = 0;
  670. const CLR_RECORD_TYPEDEF* td = GetTypeDef( 0 );
  671. for(int i=0; i<m_pTablesSize[ TBL_TypeDef ]; i++, td++)
  672. {
  673. int totMethods = td->vMethods_Num + td->iMethods_Num + td->sMethods_Num;
  674. if(totMethods)
  675. {
  676. string cls_name; BuildClassName( td, cls_name, true );
  677. string name;
  678. CLR_RT_StringMap mapMethods;
  679. const CLR_RECORD_METHODDEF* md = GetMethodDef( td->methods_First );
  680. for(int j=0; j<totMethods; j++, md++)
  681. {
  682. if(IncludeInStub( td ) && IncludeInStub( md ))
  683. {
  684. BuildMethodName( md, name, mapMethods );
  685. UpdateCRC( crc, m_szName );
  686. UpdateCRC( crc, cls_name.c_str() );
  687. UpdateCRC( crc, name .c_str() );
  688. }
  689. else
  690. {
  691. UpdateCRC( crc, "NULL" );
  692. }
  693. }
  694. }
  695. }
  696. return crc;
  697. }
  698. bool CLR_RT_Assembly::AreInternalMethodsPresent( const CLR_RECORD_TYPEDEF* td )
  699. {
  700. // If type in not included in stub, no code generation
  701. if ( !IncludeInStub( td ) )
  702. {
  703. return false;
  704. }
  705. // This type is included into stub. Check if it has internal methods
  706. // that require marshaling code.
  707. const CLR_RECORD_METHODDEF* md = GetMethodDef( td->methods_First );
  708. int totMethods = td->vMethods_Num + td->iMethods_Num + td->sMethods_Num;
  709. // Iterates on all methods and checks if at least one requires marshaling code.
  710. for ( int i = 0; i < totMethods; i++, md++ )
  711. { // If at least one method require stub - return true
  712. if ( IncludeInStub( md ) )
  713. {
  714. return true;
  715. }
  716. }
  717. return false;
  718. }
  719. void CLR_RT_Assembly::GenerateSkeletonStubFieldsDef( const CLR_RECORD_TYPEDEF *pClsType, FILE *pFileStubHead, string strIndent, string strNameSpace )
  720. {
  721. if ( pClsType->iFields_Num ) // If fields are present.
  722. {
  723. // Retrieve data with definition of the field.
  724. const CLR_RECORD_FIELDDEF* fd = GetFieldDef( pClsType->iFields_First );
  725. // Iterates over all fields.
  726. string strCtorMembInit;
  727. for ( int curFld =0; curFld < pClsType->iFields_Num; curFld++, fd++ )
  728. {
  729. // Signature parser is able to retrive type of the field from fd->sig
  730. CLR_RT_SignatureParser sigParser;
  731. sigParser.Initialize_FieldDef( this, fd );
  732. // Now sigParser.m_sig is actually points to the type of the field.
  733. // Construct CLR_RT_ManagedElementType which retrive name of type from ID.
  734. CLR_PMETADATA pMetaData = sigParser.m_sig;
  735. CLR_DataType opt = CLR_UncompressElementType( pMetaData );
  736. if ( opt == DATATYPE_VALUETYPE )
  737. {
  738. CLR_UINT32 token = CLR_TkFromStream( pMetaData );
  739. CLR_UINT32 dataToken = CLR_DataFromTk( token );
  740. const CLR_RECORD_TYPEDEF *pTypeDef = GetTypeDef( CLR_DataFromTk( token ) );
  741. opt = (CLR_DataType)pTypeDef->dataType;
  742. }
  743. CLR_RT_ManagedElementType elemType( opt );
  744. // Generates function that retrieves the managed field
  745. // First function declaration
  746. string strFieldDef = strIndent + "static " + elemType.GetNativeType() + "& Get_" + GetString( fd->name ) + "( CLR_RT_HeapBlock* pMngObj ) ";
  747. // Now generates the body of the function.
  748. strFieldDef += "{ return Interop_Marshal_GetField_" + elemType.GetNativeType() + "( pMngObj, " + strNameSpace + "::FIELD__" + GetString( fd->name ) + " ); }\n\n";
  749. // Print field definition to header file.
  750. Dump_Printf( pFileStubHead, strFieldDef.c_str() );
  751. }
  752. }
  753. }
  754. void CLR_RT_Assembly::GenerateSkeletonStubCode( LPCWSTR szFilePath, FILE *pFileDotNetProj )
  755. {
  756. /*
  757. ** Creates 3 files.
  758. ** 1. Create <assembly>_<type>_mshl.cpp, with the marshalling code.
  759. ** 2. Create <assembly>_<type>.h with the declarations of native stub functions for developer.
  760. ** 3. Create <assembly>_<type>.cpp with the defintioins of native stub functions for developer.
  761. */
  762. const CLR_RECORD_TYPEDEF* td = GetTypeDef( 0 );
  763. WCHAR rgFiles[ 2*MAX_PATH ];
  764. LPCWSTR szName;
  765. CHAR szCharName[ MAX_PATH ];
  766. // Finds the file name name out of szFilePath
  767. for ( szName = szFilePath + wcslen( szFilePath ); szName != szFilePath; szName-- )
  768. {
  769. if ( *(szName-1) == '\\' || *(szName-1) == '/' ) break;
  770. }
  771. sprintf_s( szCharName, sizeof( szCharName ), "%S", szName );
  772. // Iterates over all classes in assembly.
  773. for ( int i=0; i < m_pTablesSize[ TBL_TypeDef ]; i++, td++ )
  774. {
  775. // Calculate count of methods in the class.
  776. int totMethods = td->vMethods_Num + td->iMethods_Num + td->sMethods_Num;
  777. // Enter "if" statement only if internal methods requiring marshaling code are present.
  778. // Thus we skip classes that do not have internal methods.
  779. if ( totMethods && AreInternalMethodsPresent( td ) )
  780. {
  781. string cls_name;
  782. BuildClassName( td, cls_name, true );
  783. CLR_RT_StringMap mapMethods;
  784. const CLR_RECORD_METHODDEF* md = GetMethodDef( td->methods_First );
  785. // File with marshaling code. ( *.cpp )
  786. swprintf( rgFiles, ARRAYSIZE(rgFiles), L"%s_%S_mshl.cpp", szFilePath, cls_name.c_str() );
  787. FILE *pFileMshlSrc = NULL; Dump_SetDevice( pFileMshlSrc, rgFiles);
  788. // Adds file to the dotNetMF.proj file.
  789. Dump_Printf( pFileDotNetProj, "<Compile Include=\"%S\" />\n", GetFNameWithExtFromFilePath( rgFiles ).c_str() );
  790. // File with declaration ( *.h ) of native stub functions for developer
  791. swprintf( rgFiles, ARRAYSIZE(rgFiles), L"%s_%S.h", szFilePath, cls_name.c_str() );
  792. FILE *pFileStubHead = NULL; Dump_SetDevice( pFileStubHead, rgFiles );
  793. // Adds file to the dotNetMF.proj file.
  794. Dump_Printf( pFileDotNetProj, "<HFile Include=\"%S\" />\n", GetFNameWithExtFromFilePath( rgFiles ).c_str() );
  795. string strHeaderDefineMacro = BuildHeaderDefMacro( rgFiles );
  796. // File with definition ( *.cpp ) of native stub functions for developer
  797. swprintf( rgFiles, ARRAYSIZE(rgFiles), L"%s_%S.cpp", szFilePath, cls_name.c_str() );
  798. FILE *pFileStubSrc = NULL; Dump_SetDevice( pFileStubSrc, rgFiles );
  799. // Adds file to the dotNetMF.proj file.
  800. Dump_Printf( pFileDotNetProj, "<Compile Include=\"%S\" />\n", GetFNameWithExtFromFilePath( rgFiles ).c_str() );
  801. // Put Comments header into each file
  802. Dump_Printf( pFileMshlSrc, c_DO_NOT_EDIT_THIS_FILE_Header );
  803. Dump_Printf( pFileStubSrc, c_WARNING_FILE_OVERWRITE_Header );
  804. Dump_Printf( pFileStubHead, c_WARNING_FILE_OVERWRITE_Header );
  805. // In header file prevention of multople inclusion.
  806. Dump_Printf( pFileStubHead, "#ifndef %s\n", strHeaderDefineMacro.c_str() );
  807. Dump_Printf( pFileStubHead, "#define %s\n\n", strHeaderDefineMacro.c_str() );
  808. // Include file with Interop table declaration like "InteropSample_Native.h"
  809. Dump_Printf( pFileMshlSrc, "#include \"%S.h\"\n", szName );
  810. // Include file with with declaration ( *.h ) of native stub functions for developer
  811. Dump_Printf( pFileMshlSrc, "#include \"%S_%s.h\"\n\n", szName, cls_name.c_str() );
  812. // Include file with Interop table declaration like "InteropSample_Native.h"
  813. Dump_Printf( pFileStubSrc, "#include \"%S.h\"\n", szName );
  814. // Include file with with declaration ( *.h ) of native stub functions for developer
  815. Dump_Printf( pFileStubSrc, "#include \"%S_%s.h\"\n\n", szName, cls_name.c_str() );
  816. //************************* Add enclosure of stub functions declarations with namespace ***********
  817. string strNameSpace;
  818. BuildTypeName( td, strNameSpace );
  819. string strUsingNamesSpace = "using namespace ";
  820. vector<string> vectNameSpace;
  821. BuildNameSpaceVector( strNameSpace, vectNameSpace );
  822. string strMngClassName = (*--vectNameSpace.end()).c_str();
  823. // Array of closing brackets for namespaces.
  824. vector<string> vectClosingBrackets;
  825. string strIndent;
  826. // Add namespace strings
  827. for ( UINT32 i = 0; i < vectNameSpace.size() - 1; i++, strIndent += " " )
  828. {
  829. string strSingleNameSpace = strIndent + "namespace " + vectNameSpace[ i ].c_str();
  830. string strSingleOpenBracket = strIndent + "{";
  831. Dump_Printf( pFileStubHead, "%s\n%s\n", strSingleNameSpace.c_str(), strSingleOpenBracket.c_str() );
  832. // Insert closing bracket into array. Added at the end of the file.
  833. vectClosingBrackets.insert( vectClosingBrackets.begin(), strIndent + "}\n" );
  834. // Build "using namespace" string. Example : "using namespace Microsoft::SPOT::InteropSample;"
  835. strUsingNamesSpace += vectNameSpace[ i ].c_str();
  836. // Adds "::" separator between namespaces and ";" after last namespace.
  837. strUsingNamesSpace += i < vectNameSpace.size() - 2 ? "::" : ";\n\n";
  838. }
  839. // Add string with "struct"
  840. Dump_Printf( pFileStubHead, "%sstruct %s\n%s{\n", strIndent.c_str(), strMngClassName.c_str(), strIndent.c_str() );
  841. vectClosingBrackets.insert( vectClosingBrackets.begin(), strIndent + "};\n" );
  842. strIndent += " ";
  843. // Add definitions of fields (data members ) to the declaration of native structure.
  844. Dump_Printf( pFileStubHead, ( strIndent + "// Helper Functions to access fields of managed object\n" ).c_str() );
  845. GenerateSkeletonStubFieldsDef( td, pFileStubHead, strIndent, "Library_" + string( szCharName ) + "_" + cls_name );
  846. //************** Add using namespace statement to source files.
  847. Dump_Printf( pFileMshlSrc, strUsingNamesSpace.c_str() );
  848. Dump_Printf( pFileStubSrc, strUsingNamesSpace.c_str() );
  849. // Add methods declarations and definitions.
  850. Dump_Printf( pFileStubHead, ( strIndent + "// Declaration of stubs. These functions are implemented by Interop code developers\n" ).c_str() );
  851. for ( int j=0; j < totMethods; j++, md++) // Iterates over all methods in class.
  852. {
  853. if ( IncludeInStub( md ) ) // Test if it is internal method.
  854. {
  855. // Test if this is static function of the class.
  856. bool bStaticMethod( (md->flags & CLR_RECORD_METHODDEF::MD_Static) != 0 );
  857. string strNativeStubName = ReplaceDotWithString( GetString( md->name ), "_" );
  858. // elemPtrArray represents parameters to the funtion. One element for each parameter.
  859. CLR_RT_VectorOfManagedElements elemPtrArray;
  860. BuildParametersList( GetSignature( md->sig ), elemPtrArray );
  861. // Here we generate implementation for the function that receives the managed stack frame.
  862. // This function retrieves and marshal all parameters from stack frame, then calls stub
  863. // implemented by native code developer.
  864. // Name for the function that receives managed stack frame
  865. string strFuncName;
  866. BuildMethodName( md, strFuncName, mapMethods );
  867. // Generate the implementation for the function.
  868. // Everything that goes inside of curly brackets.
  869. string strFuncImpl = " TINYCLR_HEADER(); hr = S_OK;\n {\n";
  870. // If function is not static - we need to retrieve adresses ( in form of references ) of all member variables.
  871. if ( !bStaticMethod )
  872. { // Retrieve pointer to first field ( member varialbe ) in the managed class.
  873. const CLR_RECORD_FIELDDEF* fd = GetFieldDef( td->iFields_First );
  874. strFuncImpl += " CLR_RT_HeapBlock* pMngObj = Interop_Marshal_RetrieveManagedObject( stack );\n\n";
  875. strFuncImpl += " FAULT_ON_NULL(pMngObj);\n\n";
  876. }
  877. // Add marshaling code for each parameter:
  878. for ( UINT32 i = 1; i < elemPtrArray.size(); i++ )
  879. {
  880. // For non-static member function zero param is "this" pointer.
  881. // bStaticMethod is used to adjust index for slot used by "this" pointer.
  882. strFuncImpl += elemPtrArray[ i ]->GetMarshalCodeBeforeNativeCall( bStaticMethod, i - 1 ) + "\n";
  883. }
  884. // Add call for native stub implemented by developer.
  885. // Example: "INT32 retVal = TestBasicTypes::Add_Values_Array_double( param0, arraySize0, hr );"
  886. strFuncImpl += " " + BuildCalltoNativeStub( bStaticMethod, strNativeStubName.c_str(), strMngClassName, elemPtrArray ) + "\n";
  887. //****************** Declaration and definition for the stub method. ******************
  888. // Example: "INT32 TestBasicTypes::Add_Values_Array_double( param0, arraySize0, hr );"
  889. string strNativeStub = BuildDeclarationOfNativeStub( strNativeStubName.c_str(), string(), elemPtrArray, bStaticMethod );
  890. // Creates string with "static" modifier.
  891. Dump_Printf( pFileStubHead, "%sstatic %s;\n", strIndent.c_str(), strNativeStub.c_str() );
  892. // Add empty definition of the stub implemented by developer to *.cpp file.
  893. Dump_Printf( pFileStubSrc, BuildDeclarationOfNativeStub( strNativeStubName.c_str(), strMngClassName, elemPtrArray, bStaticMethod ).c_str() );
  894. // Now the stub implementation.
  895. // If function is not void, we just declare return value equal to zero and return it.
  896. if ( !elemPtrArray[ 0 ]->IsVoidType() )
  897. {
  898. Dump_Printf( pFileStubSrc, "\n{\n %s retVal = 0; \n return retVal;\n}\n\n", elemPtrArray[ 0 ]->GetNativeType().c_str() );
  899. }
  900. else
  901. { // In case of void function we just have empty "{}" implementation
  902. Dump_Printf( pFileStubSrc,"\n{\n}\n\n" );
  903. }
  904. //****************** Add Check for hr returned by stub function:
  905. strFuncImpl += " TINYCLR_CHECK_HRESULT( hr );\n";
  906. // Adds call to SetResult, like "SetResult_UINT16( stack, retVal );
  907. // We need to set result only if managed method is not void.
  908. if ( !elemPtrArray[ 0 ]->IsVoidType() )
  909. {
  910. strFuncImpl += " SetResult_" + elemPtrArray[ 0 ]->GetNativeType() + "( stack, retVal );\n\n";
  911. }
  912. // Add code for storing of references.
  913. for ( UINT32 i = 1; i < elemPtrArray.size(); i++ )
  914. {
  915. strFuncImpl += elemPtrArray[ i ]->GetMashalCodeAfterNativeCall( i - 1, bStaticMethod );
  916. }
  917. // Closing TINYCLR_NOCLEANUP(); macro. Defines label and returns "hr"
  918. strFuncImpl += " }\n TINYCLR_NOCLEANUP();\n