PageRenderTime 230ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/MicroFrameworkPK_v4_2/CLR/Diagnostics/Info_Win32.cpp

https://bitbucket.org/pmfsampaio/netmf-lpc
C++ | 1137 lines | 807 code | 211 blank | 119 comment | 107 complexity | 2d365d231318c361de0a01d43da3c70d 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_Header_Begin[] =
  327. "\n"
  328. "#include \"%S_native.h\"\n"
  329. "\n"
  330. "\n";
  331. static const CHAR c_Include_Interop_h[] =
  332. "#include <TinyCLR_Interop.h>\n";
  333. //--//
  334. static const CHAR c_Type_Begin[] =
  335. "struct Library_%S_%s\n" \
  336. "{\n";
  337. static const CHAR c_Type_Field_Static[] =
  338. " static const int FIELD_STATIC__%s = %d;\n";
  339. static const CHAR c_Type_Field_Instance[] =
  340. " static const int FIELD__%s = %d;\n";
  341. static const CHAR c_Type_Method[] =
  342. " TINYCLR_NATIVE_DECLARE(%s);\n";
  343. static const CHAR c_Type_End[] =
  344. "\n"
  345. " //--//\n"
  346. "\n"
  347. "};\n\n";
  348. //--//
  349. static const CHAR c_Definition_Begin[] =
  350. "#include \"%S.h\"\n"
  351. "\n"
  352. "\n"
  353. "static const CLR_RT_MethodHandler method_lookup[] =\n"
  354. "{\n";
  355. static const CHAR c_Definition_Body[] = " Library_%S_%s::%s,\n";
  356. static const CHAR c_Definition_End[] =
  357. "};\n"
  358. "\n"
  359. "const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_%s =\n"
  360. "{\n"
  361. " \"%s\", \n"
  362. " 0x%08X,\n"
  363. " method_lookup\n"
  364. "};\n\n";
  365. static const CHAR c_Method[] =
  366. "\nHRESULT Library_%S_%s::%s( CLR_RT_StackFrame& stack )\n"
  367. "{\n"
  368. "%s"
  369. "}\n";
  370. static const CHAR c_MethodStub[] =
  371. " TINYCLR_HEADER();\n"
  372. "\n"
  373. " TINYCLR_SET_AND_LEAVE(stack.NotImplementedStub());\n"
  374. "\n"
  375. " TINYCLR_NOCLEANUP();\n";
  376. //--//
  377. static const CHAR c_Project_Gen_Project_Open[] = "<Project DefaultTargets=\"Build\" ToolsVersion=\"3.5\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n";
  378. static const CHAR c_Project_Gen_Project_Close[] = "</Project>\n";
  379. static const CHAR c_Project_Gen_Import_Project[] = "<Import Project=\"$(SPOCLIENT)\\tools\\targets\\Microsoft.SPOT.System.Targets\" />\n";
  380. static const CHAR c_Project_Gen_Property_Group []=
  381. " <PropertyGroup>\n"
  382. " <Directory>DeviceCode\\Targets\\Native\\Interop\\%S</Directory>\n"
  383. " <AssemblyName>%S</AssemblyName>\n"
  384. " </PropertyGroup>\n"
  385. " <Import Project=\"$(SPOCLIENT)\\tools\\targets\\Microsoft.SPOT.System.Settings\" />\n"
  386. " <PropertyGroup>\n"
  387. " <OutputType>Library</OutputType>\n"
  388. " </PropertyGroup>\n";
  389. static const CHAR c_Project_Gen_Item_Group_Open[] = "<ItemGroup>\n";
  390. static const CHAR c_Project_Gen_Item_Group_Close[] = "</ItemGroup>\n";
  391. //--//
  392. void CLR_RT_Assembly::BuildClassName( const CLR_RECORD_TYPEREF* tr, string& cls_name, bool fEscape )
  393. {
  394. cls_name.clear();
  395. if(tr->scope & 0x8000) // Flag for TypeRef
  396. {
  397. const CLR_RECORD_TYPEREF* trS = GetTypeRef( tr->scope & 0x7FFF );
  398. BuildClassName( GetTypeRef( tr->scope & 0x7FFF ), cls_name, fEscape );
  399. cls_name += ".";
  400. }
  401. else
  402. {
  403. const CLR_RECORD_ASSEMBLYREF* ar = GetAssemblyRef( tr->scope );
  404. cls_name = GetString( ar->name );
  405. cls_name += ".";
  406. }
  407. if(tr->nameSpace != CLR_EmptyIndex)
  408. {
  409. cls_name += GetString( tr->nameSpace );
  410. cls_name += ".";
  411. }
  412. cls_name += GetString( tr->name );
  413. if(fEscape) RemoveDots( cls_name );
  414. }
  415. void CLR_RT_Assembly::BuildClassName( const CLR_RECORD_TYPEDEF* td, string& cls_name, bool fEscape )
  416. {
  417. cls_name.clear();
  418. if(td->enclosingType != CLR_EmptyIndex)
  419. {
  420. BuildClassName( GetTypeDef( td->enclosingType ), cls_name, fEscape );
  421. cls_name += ".";
  422. }
  423. if(td->nameSpace != CLR_EmptyIndex)
  424. {
  425. cls_name += GetString( td->nameSpace );
  426. cls_name += ".";
  427. }
  428. cls_name += GetString( td->name );
  429. if(fEscape) RemoveDots( cls_name );
  430. }
  431. void CLR_RT_Assembly::BuildTypeName( const CLR_RECORD_TYPEDEF* td, std::string& type_name )
  432. {
  433. type_name.clear();
  434. if(td->enclosingType != CLR_EmptyIndex)
  435. {
  436. BuildTypeName( GetTypeDef( td->enclosingType ), type_name );
  437. type_name += "_";
  438. }
  439. if(td->nameSpace != CLR_EmptyIndex)
  440. {
  441. std::string strNameSpace = GetString( td->nameSpace );
  442. // Avoid creation of extra dot if namespace is empty.
  443. if ( !strNameSpace.empty() )
  444. {
  445. type_name += strNameSpace;
  446. type_name += ".";
  447. }
  448. }
  449. type_name += GetString( td->name );
  450. }
  451. void CLR_RT_Assembly::BuildParametersList( CLR_PMETADATA pMetaData, CLR_RT_VectorOfManagedElements &elemPtrArray )
  452. {
  453. pMetaData++; // Skip Calling convention.
  454. CLR_UINT32 elemCount = *pMetaData++ + 1;
  455. // Iterates until end of information with paramenters types.
  456. for ( CLR_UINT32 curElem = 0; curElem < elemCount; curElem++ )
  457. {
  458. CLR_RT_ManagedElementType *pNewElement = NULL;
  459. // Get next element type.
  460. CLR_DataType opt = CLR_UncompressElementType( pMetaData );
  461. switch ( opt )
  462. {
  463. // In case or array or reference we extract the type of element.
  464. case DATATYPE_BYREF : pNewElement = new CLR_RT_ManagedElementTypeByRef( CLR_UncompressElementType( pMetaData ) ); break;
  465. case DATATYPE_SZARRAY: pNewElement = new CLR_RT_ManagedElementTypeArray( CLR_UncompressElementType( pMetaData ) ); break;
  466. case DATATYPE_VALUETYPE :
  467. {
  468. CLR_UINT32 token = CLR_TkFromStream( pMetaData );
  469. const CLR_RECORD_TYPEDEF *pTypeDef = GetTypeDef( CLR_DataFromTk( token ) );
  470. pNewElement = new CLR_RT_ManagedElementType( (CLR_DataType)pTypeDef->dataType );
  471. }
  472. break;
  473. // If it is not a reference or object - means basic type, we create CLR_RT_ManagedElementType
  474. default : pNewElement = new CLR_RT_ManagedElementType( opt );
  475. }
  476. // Adds pointer to new element to array.
  477. elemPtrArray.push_back( pNewElement );
  478. }
  479. }
  480. void CLR_RT_Assembly::BuildMethodName( const CLR_RECORD_METHODDEF* md, std::string& name, CLR_RT_StringMap& mapMethods )
  481. {
  482. CHAR buffer[ 256 ];
  483. CLR_PMETADATA p = GetSignature( md->sig ); p++; // Skip Calling convention.
  484. CLR_UINT32 len = *p++ + 1;
  485. name = GetString( md->name ); RemoveDots( name );
  486. for(CLR_UINT32 a=0; a<len; a++)
  487. {
  488. bool fContinue = true;
  489. if(a == 0)
  490. {
  491. name += "___";
  492. if(md->flags & CLR_RECORD_METHODDEF::MD_Static)
  493. {
  494. name += "STATIC__";
  495. }
  496. }
  497. while(fContinue)
  498. {
  499. CLR_DataType opt = CLR_UncompressElementType( p );
  500. switch(opt)
  501. {
  502. case DATATYPE_VOID : name += "VOID" ; break;
  503. case DATATYPE_BOOLEAN : name += "BOOLEAN" ; break;
  504. case DATATYPE_CHAR : name += "CHAR" ; break;
  505. case DATATYPE_I1 : name += "I1" ; break;
  506. case DATATYPE_U1 : name += "U1" ; break;
  507. case DATATYPE_I2 : name += "I2" ; break;
  508. case DATATYPE_U2 : name += "U2" ; break;
  509. case DATATYPE_I4 : name += "I4" ; break;
  510. case DATATYPE_U4 : name += "U4" ; break;
  511. case DATATYPE_I8 : name += "I8" ; break;
  512. case DATATYPE_U8 : name += "U8" ; break;
  513. case DATATYPE_R4 : name += "R4" ; break;
  514. case DATATYPE_R8 : name += "R8" ; break;
  515. case DATATYPE_STRING : name += "STRING" ; break;
  516. case DATATYPE_BYREF : name += "BYREF" ; break;
  517. case DATATYPE_VALUETYPE : ; break;
  518. case DATATYPE_CLASS : ; break;
  519. case DATATYPE_OBJECT : name += "OBJECT" ; break;
  520. case DATATYPE_SZARRAY : name += "SZARRAY" ; break;
  521. }
  522. fContinue = false;
  523. switch(opt)
  524. {
  525. case DATATYPE_BYREF :
  526. case DATATYPE_SZARRAY:
  527. fContinue = true;
  528. name += "_";
  529. break;
  530. case DATATYPE_VALUETYPE:
  531. case DATATYPE_CLASS :
  532. {
  533. CLR_UINT32 tk = CLR_TkFromStream( p );
  534. std::string cls;
  535. switch(CLR_TypeFromTk(tk))
  536. {
  537. case TBL_TypeDef : BuildClassName( GetTypeDef( CLR_DataFromTk( tk ) ), cls, true ); break;
  538. case TBL_TypeRef : BuildClassName( GetTypeRef( CLR_DataFromTk( tk ) ), cls, true ); break;
  539. case TBL_TypeSpec: sprintf_s( buffer, ARRAYSIZE(buffer), "_%08X", tk ); cls = buffer; break;
  540. }
  541. while(true)
  542. {
  543. std::string::size_type pos = cls.find( '_' ); if(pos == cls.npos) break;
  544. cls.erase( pos, 1 );
  545. }
  546. name += cls;
  547. }
  548. break;
  549. }
  550. }
  551. if(a != len-1) name += "__";
  552. }
  553. int num = mapMethods[name];
  554. if(num++)
  555. {
  556. sprintf_s( buffer, ARRAYSIZE(buffer), "_%d", num ); name += buffer;
  557. }
  558. mapMethods[name] = num;
  559. }
  560. static string ReplaceDotWithString( string strName, string strReplace )
  561. {
  562. for ( string::iterator strp_Iter = strName.begin();
  563. strp_Iter != strName.end();
  564. strp_Iter++
  565. )
  566. {
  567. if ( *strp_Iter == '.' )
  568. {
  569. string::iterator thisPos = strp_Iter;
  570. strName.replace( thisPos, ++strp_Iter, strReplace );
  571. }
  572. }
  573. return strName;
  574. }
  575. static string BuildHeaderDefMacro( LPCWSTR lpwzHeaderFilePath )
  576. {
  577. WCHAR swDrive[ _MAX_DRIVE ], swDir[ _MAX_DIR ], swName[ _MAX_FNAME ], swExt[ _MAX_EXT ];
  578. // Breaks path into pieces to find the name of header file.
  579. _wsplitpath_s( lpwzHeaderFilePath, swDrive, ARRAYSIZE(swDrive), swDir, ARRAYSIZE(swDir), swName, ARRAYSIZE(swName), swExt, ARRAYSIZE(swExt) );
  580. // Convert to ASCII and build macro name.
  581. CHAR szHeaderDefMacro[ _MAX_PATH + 5 ];
  582. sprintf_s( szHeaderDefMacro, sizeof( szHeaderDefMacro ), "_%S_H_", swName );
  583. // Converts file name to uppper case.
  584. _strupr_s( szHeaderDefMacro, sizeof( szHeaderDefMacro ) );
  585. return string( szHeaderDefMacro );
  586. }
  587. // Generate the call to native stublike like in example:
  588. // "INT64 AddValues( param0, param1, param3, hr );"
  589. static string BuildCalltoNativeStub( bool bStaticMember, string strMethodName, string strAssemblyName, CLR_RT_VectorOfManagedElements &elemPtrArray )
  590. {
  591. // Return type with function name like "INT64 AddValues("
  592. string strClassNames = ReplaceDotWithString( strAssemblyName, "::" );
  593. string strCall;
  594. // Add return value if native type is not "void".
  595. // If we do not check for void type, we get code like "void retVal = ...".
  596. if ( !elemPtrArray[ 0 ]->IsVoidType() )
  597. {
  598. strCall += elemPtrArray[ 0 ]->GetNativeType() + " retVal = ";
  599. }
  600. // Add function call. We pre-pend class name to the function name
  601. strCall += strClassNames + "::" + strMethodName + "(";
  602. if ( !bStaticMember )
  603. {
  604. // For non-static member functions we add one more parameter - managed "fields"
  605. strCall += " pMngObj, ";
  606. }
  607. // Now parameters.
  608. for ( UINT32 i = 1; i < elemPtrArray.size(); i++ )
  609. {
  610. // For each parameter add string like " INT8 param0,"
  611. strCall += " param" + CLR_RT_ManagedElementType::GetParamIndexAsText( i - 1 ) + ",";
  612. }
  613. // The last parameter is " hr );"
  614. strCall += " hr );";
  615. return strCall;
  616. }
  617. static string BuildDeclarationOfNativeStub( string strMethodName, string strAssemblyName, CLR_RT_VectorOfManagedElements &elemPtrArray, bool bStaticMethod )
  618. {
  619. // Return type with function name like "INT64 AddValues("
  620. string strCall = elemPtrArray[ 0 ]->GetNativeType() + " ";
  621. // Include class name if passed - example : "INT64 TestBasicTypes::AddValues(
  622. if ( strAssemblyName.length() > 0 )
  623. {
  624. strCall += strAssemblyName + "::";
  625. }
  626. strCall += strMethodName + "( ";
  627. // For non-static methods we need to add CLR_RT_HeapBlock *pMngObj parameter.
  628. // The pMngObj is actually pointer to managed object
  629. if ( !bStaticMethod )
  630. {
  631. strCall += "CLR_RT_HeapBlock* pMngObj, ";
  632. }
  633. // Now parameters.
  634. for ( UINT32 i = 1; i < elemPtrArray.size(); i++ )
  635. {
  636. // For each parameter add string like " INT8 param0,"
  637. strCall += elemPtrArray[ i ]->GetVariableDecl() + " param" + CLR_RT_ManagedElementType::GetParamIndexAsText( i - 1 ) + ", ";
  638. }
  639. // The last parameter is " hr );"
  640. strCall += "HRESULT &hr )";
  641. return strCall;
  642. }
  643. static void BuildNameSpaceVector( string strNameSpace, vector<string> &vectNameSpace )
  644. {
  645. // Need a copy of the string, since strtok actually modifies the string
  646. LPSTR lpszNameSpace = new char[ strNameSpace.length() + 1 ];
  647. strcpy_s( lpszNameSpace, strNameSpace.length() + 1, strNameSpace.c_str() );
  648. LPSTR lpszContext;
  649. // Finds each token separated by "." and adds as separate string to vectNameSpace
  650. LPCSTR lpszName = strtok_s( lpszNameSpace, ".", &lpszContext );
  651. while ( lpszName != NULL )
  652. {
  653. vectNameSpace.push_back( string( lpszName ) );
  654. lpszName = strtok_s( NULL, ".", &lpszContext );
  655. }
  656. delete [] lpszNameSpace;
  657. }
  658. static std::wstring GetFNameWithExtFromFilePath( LPCWSTR lpwFilePath )
  659. {
  660. // Split full path into pieces.
  661. wchar_t szDrive[ _MAX_DRIVE ], szDir[ _MAX_DIR ], szFileName[ _MAX_FNAME ], szExt[ _MAX_EXT ];
  662. _wsplitpath_s( lpwFilePath, szDrive, ARRAYSIZE(szDrive), szDir, ARRAYSIZE(szDir), szFileName, ARRAYSIZE(szFileName), szExt, ARRAYSIZE(szExt) );
  663. // Adds file name and extention.
  664. return std::wstring( szFileName ) + szExt;
  665. }
  666. static std::wstring GetDirPathFromFilePath( LPCWSTR lpwFilePath )
  667. {
  668. // Split full path into pieces.
  669. wchar_t szDrive[ _MAX_DRIVE ], szDir[ _MAX_DIR ], szFileName[ _MAX_FNAME ], szExt[ _MAX_EXT ];
  670. _wsplitpath_s( lpwFilePath, szDrive, ARRAYSIZE(szDrive), szDir, ARRAYSIZE(szDir), szFileName, ARRAYSIZE(szFileName), szExt, ARRAYSIZE(szExt) );
  671. // Adds drive name and directory name.
  672. return std::wstring( szDrive ) + szDir;
  673. }
  674. static void UpdateCRC( UINT32& crc, LPCSTR str )
  675. {
  676. crc = SUPPORT_ComputeCRC( str, (int)hal_strlen_s( str ), crc );
  677. }
  678. UINT32 CLR_RT_Assembly::GenerateSignatureForNativeMethods()
  679. {
  680. UINT32 crc = 0;
  681. const CLR_RECORD_TYPEDEF* td = GetTypeDef( 0 );
  682. for(int i=0; i<m_pTablesSize[ TBL_TypeDef ]; i++, td++)
  683. {
  684. int totMethods = td->vMethods_Num + td->iMethods_Num + td->sMethods_Num;
  685. if(totMethods)
  686. {
  687. string cls_name; BuildClassName( td, cls_name, true );
  688. string name;
  689. CLR_RT_StringMap mapMethods;
  690. const CLR_RECORD_METHODDEF* md = GetMethodDef( td->methods_First );
  691. for(int j=0; j<totMethods; j++, md++)
  692. {
  693. if(IncludeInStub( td ) && IncludeInStub( md ))
  694. {
  695. BuildMethodName( md, name, mapMethods );
  696. UpdateCRC( crc, m_szName );
  697. UpdateCRC( crc, cls_name.c_str() );
  698. UpdateCRC( crc, name .c_str() );
  699. }
  700. else
  701. {
  702. UpdateCRC( crc, "NULL" );
  703. }
  704. }
  705. }
  706. }
  707. return crc;
  708. }
  709. bool CLR_RT_Assembly::AreInternalMethodsPresent( const CLR_RECORD_TYPEDEF* td )
  710. {
  711. // If type in not included in stub, no code generation
  712. if ( !IncludeInStub( td ) )
  713. {
  714. return false;
  715. }
  716. // This type is included into stub. Check if it has internal methods
  717. // that require marshaling code.
  718. const CLR_RECORD_METHODDEF* md = GetMethodDef( td->methods_First );
  719. int totMethods = td->vMethods_Num + td->iMethods_Num + td->sMethods_Num;
  720. // Iterates on all methods and checks if at least one requires marshaling code.
  721. for ( int i = 0; i < totMethods; i++, md++ )
  722. { // If at least one method require stub - return true
  723. if ( IncludeInStub( md ) )
  724. {
  725. return true;
  726. }
  727. }
  728. return false;
  729. }
  730. void CLR_RT_Assembly::GenerateSkeletonStubFieldsDef( const CLR_RECORD_TYPEDEF *pClsType, FILE *pFileStubHead, string strIndent, string strNameSpace )
  731. {
  732. if ( pClsType->iFields_Num ) // If fields are present.
  733. {
  734. // Retrieve data with definition of the field.
  735. const CLR_RECORD_FIELDDEF* fd = GetFieldDef( pClsType->iFields_First );
  736. // Iterates over all fields.
  737. string strCtorMembInit;
  738. for ( int curFld =0; curFld < pClsType->iFields_Num; curFld++, fd++ )
  739. {
  740. // Signature parser is able to retrive type of the field from fd->sig
  741. CLR_RT_SignatureParser sigParser;
  742. sigParser.Initialize_FieldDef( this, fd );
  743. // Now sigParser.m_sig is actually points to the type of the field.
  744. // Construct CLR_RT_ManagedElementType which retrive name of type from ID.
  745. CLR_PMETADATA pMetaData = sigParser.m_sig;
  746. CLR_DataType opt = CLR_UncompressElementType( pMetaData );
  747. if ( opt == DATATYPE_VALUETYPE )
  748. {
  749. CLR_UINT32 token = CLR_TkFromStream( pMetaData );
  750. CLR_UINT32 dataToken = CLR_DataFromTk( token );
  751. const CLR_RECORD_TYPEDEF *pTypeDef = GetTypeDef( CLR_DataFromTk( token ) );
  752. opt = (CLR_DataType)pTypeDef->dataType;
  753. }
  754. CLR_RT_ManagedElementType elemType( opt );
  755. // Generates function that retrieves the managed field
  756. // First function declaration
  757. string strFieldDef = strIndent + "static " + elemType.GetNativeType() + "& Get_" + GetString( fd->name ) + "( CLR_RT_HeapBlock* pMngObj ) ";
  758. // Now generates the body of the function.
  759. strFieldDef += "{ return Interop_Marshal_GetField_" + elemType.GetNativeType() + "( pMngObj, " + strNameSpace + "::FIELD__" + GetString( fd->name ) + " ); }\n\n";
  760. // Print field definition to header file.
  761. Dump_Printf( pFileStubHead, strFieldDef.c_str() );
  762. }
  763. }
  764. }
  765. void CLR_RT_Assembly::GenerateSkeletonStubCode( LPCWSTR szFilePath, FILE *pFileDotNetProj )
  766. {
  767. /*
  768. ** Creates 3 files.
  769. ** 1. Create <assembly>_<type>_mshl.cpp, with the marshalling code.
  770. ** 2. Create <assembly>_<type>.h with the declarations of native stub functions for developer.
  771. ** 3. Create <assembly>_<type>.cpp with the defintioins of native stub functions for developer.
  772. */
  773. const CLR_RECORD_TYPEDEF* td = GetTypeDef( 0 );
  774. WCHAR rgFiles[ 2*MAX_PATH ];
  775. LPCWSTR szName;
  776. CHAR szCharName[ MAX_PATH ];
  777. // Finds the file name name out of szFilePath
  778. for ( szName = szFilePath + wcslen( szFilePath ); szName != szFilePath; szName-- )
  779. {
  780. if ( *(szName-1) == '\\' || *(szName-1) == '/' ) break;
  781. }
  782. sprintf_s( szCharName, sizeof( szCharName ), "%S", szName );
  783. // Iterates over all classes in assembly.
  784. for ( int i=0; i < m_pTablesSize[ TBL_TypeDef ]; i++, td++ )
  785. {
  786. // Calculate count of methods in the class.
  787. int totMethods = td->vMethods_Num + td->iMethods_Num + td->sMethods_Num;
  788. // Enter "if" statement only if internal methods requiring marshaling code are present.
  789. // Thus we skip classes that do not have internal methods.
  790. if ( totMethods && AreInternalMethodsPresent( td ) )
  791. {
  792. string cls_name;
  793. BuildClassName( td, cls_name, true );
  794. CLR_RT_StringMap mapMethods;
  795. const CLR_RECORD_METHODDEF* md = GetMethodDef( td->methods_First );
  796. // File with marshaling code. ( *.cpp )
  797. swprintf( rgFiles, ARRAYSIZE(rgFiles), L"%s_%S_mshl.cpp", szFilePath, cls_name.c_str() );
  798. FILE *pFileMshlSrc = NULL; Dump_SetDevice( pFileMshlSrc, rgFiles);
  799. // Adds file to the dotNetMF.proj file.
  800. Dump_Printf( pFileDotNetProj, "<Compile Include=\"%S\" />\n", GetFNameWithExtFromFilePath( rgFiles ).c_str() );
  801. // File with declaration ( *.h ) of native stub functions for developer
  802. swprintf( rgFiles, ARRAYSIZE(rgFiles), L"%s_%S.h", szFilePath, cls_name.c_str() );
  803. FILE *pFileStubHead = NULL; Dump_SetDevice( pFileStubHead, rgFiles );
  804. // Adds file to the dotNetMF.proj file.
  805. Dump_Printf( pFileDotNetProj, "<HFile Include=\"%S\" />\n", GetFNameWithExtFromFilePath( rgFiles ).c_str() );
  806. string strHeaderDefineMacro = BuildHeaderDefMacro( rgFiles );
  807. // File with definition ( *.cpp ) of native stub functions for developer
  808. swprintf( rgFiles, ARRAYSIZE(rgFiles), L"%s_%S.cpp", szFilePath, cls_name.c_str() );
  809. FILE *pFileStubSrc = NULL; Dump_SetDevice( pFileStubSrc, rgFiles );
  810. // Adds file to the dotNetMF.proj file.
  811. Dump_Printf( pFileDotNetProj, "<Compile Include=\"%S\" />\n", GetFNameWithExtFromFilePath( rgFiles ).c_str() );
  812. // Put Comments header into each file
  813. Dump_Printf( pFileMshlSrc, c_DO_NOT_EDIT_THIS_FILE_Header );
  814. Dump_Printf( pFileStubSrc, c_WARNING_FILE_OVERWRITE_Header );
  815. Dump_Printf( pFileStubHead, c_WARNING_FILE_OVERWRITE_Header );
  816. // In header file prevention of multople inclusion.
  817. Dump_Printf( pFileStubHead, "#ifndef %s\n", strHeaderDefineMacro.c_str() );
  818. Dump_Printf( pFileStubHead, "#define %s\n\n", strHeaderDefineMacro.c_str() );
  819. // Include file with Interop table declaration like "InteropSample_Native.h"
  820. Dump_Printf( pFileMshlSrc, "#include \"%S.h\"\n", szName );
  821. // Include file with with declaration ( *.h ) of native stub functions for developer
  822. Dump_Printf( pFileMshlSrc, "#include \"%S_%s.h\"\n\n", szName, cls_name.c_str() );
  823. // Include file with Interop table declaration like "InteropSample_Native.h"
  824. Dump_Printf( pFileStubSrc, "#include \"%S.h\"\n", szName );
  825. // Include file with with declaration ( *.h ) of native stub functions for developer
  826. Dump_Printf( pFileStubSrc, "#include \"%S_%s.h\"\n\n", szName, cls_name.c_str() );
  827. //************************* Add enclosure of stub functions declarations with namespace ***********
  828. string strNameSpace;
  829. BuildTypeName( td, strNameSpace );
  830. string strUsingNamesSpace = "using namespace ";
  831. vector<string> vectNameSpace;
  832. BuildNameSpaceVector( strNameSpace, vectNameSpace );
  833. string strMngClassName = (*--vectNameSpace.end()).c_str();
  834. // Array of closing brackets for namespaces.
  835. vector<string> vectClosingBrackets;
  836. string strIndent;
  837. // Add namespace strings
  838. for ( UINT32 i = 0; i < vectNameSpace.size() - 1; i++, strIndent += " " )
  839. {
  840. string strSingleNameSpace = strIndent + "namespace " + vectNameSpace[ i ].c_str();
  841. string strSingleOpenBracket = strIndent + "{";
  842. Dump_Printf( pFileStubHead, "%s\n%s\n", strSingleNameSpace.c_str(), strSingleOpenBracket.c_str() );
  843. // Insert closing bracket into array. Added at the end of the file.
  844. vectClosingBrackets.insert( vectClosingBrackets.begin(), strIndent + "}\n" );
  845. // Build "using namespace" string. Example : "using namespace Microsoft::SPOT::InteropSample;"
  846. strUsingNamesSpace += vectNameSpace[ i ].c_str();
  847. // Adds "::" separator between namespaces and ";" after last namespace.
  848. strUsingNamesSpace += i < vectNameSpace.size() - 2 ? "::" : ";\n\n";
  849. }
  850. // Add string with "struct"
  851. Dump_Printf( pFileStubHead, "%sstruct %s\n%s{\n", strIndent.c_str(), strMngClassName.c_str(), strIndent.c_str() );
  852. vectClosingBrackets.insert( vectClosingBrackets.begin(), strIndent + "};\n" );
  853. strIndent += " ";
  854. // Add definitions of fields (data members ) to the declaration of native structure.
  855. Dump_Printf( pFileStubHead, ( strIndent + "// Helper Functions to access fields of managed object\n" ).c_str() );
  856. GenerateSkeletonStubFieldsDef( td, pFileStubHead, strIndent, "Library_" + string( szCharName ) + "_" + cls_name );
  857. //************** Add using namespace statement to source files.
  858. Dump_Printf( pFileMshlSrc, strUsingNamesSpace.c_str() );
  859. Dump_Printf( pFileStubSrc, strUsingNamesSpace.c_str() );
  860. // Add methods declarations and definitions.
  861. Dump_Printf( pFileStubHead, ( strIndent + "// Declaration of stubs. These functions are implemented by Interop code developers\n" ).c_str() );
  862. for ( int j=0; j < totMethods; j++, md++) // Iterates over all methods in class.
  863. {
  864. if ( IncludeInStub( md ) ) // Test if it is internal method.
  865. {
  866. // Test if this is static function of the class.
  867. bool bStaticMethod( (md->flags & CLR_RECORD_METHODDEF::MD_Static) != 0 );
  868. string strNativeStubName = ReplaceDotWithString( GetString( md->name ), "_" );
  869. // elemPtrArray represents parameters to the funtion. One element for each parameter.
  870. CLR_RT_VectorOfManagedElements elemPtrArray;
  871. BuildParametersList( GetSignature( md->sig ), elemPtrArray );
  872. // Here we generate implementation for the function that receives the managed stack frame.
  873. // This function retrieves and marshal all parameters from stack frame, then calls stub
  874. // implemented by native code developer.
  875. // Name for the function that receives managed stack frame
  876. string strFuncName;
  877. BuildMethodName( md, strFuncName, mapMethods );
  878. // Generate the implementation for the function.
  879. // Everything that goes inside of curly brackets.
  880. string strFuncImpl = " TINYCLR_HEADER(); hr = S_OK;\n {\n";
  881. // If function is not static - we need to retrieve adresses ( in form of references ) of all member variables.
  882. if ( !bStaticMethod )
  883. { // Retrieve pointer to first field ( member varialbe ) in the managed class.
  884. const CLR_RECORD_FIELDDEF* fd = GetFieldDef( td->iFields_First );
  885. strFuncImpl += " CLR_RT_HeapBlock* pMngObj = Interop_Marshal_RetrieveManagedObject( stack );\n\n";
  886. strFuncImpl += " FAULT_ON_NULL(pMngObj);\n\n";
  887. }
  888. // Add marshaling code for each parameter:
  889. for ( UINT32 i = 1; i < elemPtrArray.size(); i++ )
  890. {
  891. // For non-static member function zero param is "this" pointer.
  892. // bStaticMethod is used to adjust index for slot used by "this" pointer.
  893. strFuncImpl += elemPtrArray[ i ]->GetMarshalCodeBeforeNativeCall( bStaticMethod, i - 1 ) + "\n";
  894. }
  895. // Add call for native stub implemented by developer.
  896. // Example: "INT32 retVal = TestBasicTypes::Add_Values_Array_double( param0, arraySize0, hr );"
  897. strFuncImpl += " " + BuildCalltoNativeStub( bStaticMethod, strNativeStubName.c_str(), strMngClassName, elemPtrArray ) + "\n";
  898. //****************** Declaration and definition for the stub method. ******************
  899. // Example: "INT32 TestBasicTypes::Add_Values_Array_double( param0, arraySize0, hr );"
  900. string strNativeStub = BuildDeclarationOfNativeStub( strNativeStubName.c_str(), string(), elemPtrArray, bStaticMethod );
  901. // Creates string with "static" modifier.
  902. Dump_Printf( pFileStubHead, "%sstatic %s;\n", strIndent.c_str(), strNativeStub.c_str() );
  903. // Add empty definition of the stub implemented by developer to *.cpp file.
  904. Dump_Printf( pFileStubSrc, BuildDeclarationOfNativeStub( strNativeStubName.c_str(), strMngClassName, elemPtrArray, bStaticMethod ).c_str() );
  905. // Now the stub implementation.
  906. // If function is not void, we just declare return value equal to zero and return it.
  907. if ( !elemPtrArray[ 0 ]->IsVoidType() )
  908. {
  909. Dump_Printf( pFileStubSrc, "\n{\n %s retVal = 0; \n return retVal;\n}\n\n", elemPtrArray[ 0 ]->GetNativeType().c_str() );
  910. }
  911. else
  912. { // In case of void function we just have empty "{}" implementation
  913. Dump_Printf( pFileStubSrc,"\n{\n}\n\n" );
  914. }
  915. //****************** Add Check for hr returned by stub function:
  916. strFuncImpl += " TINYCLR_CHECK_HRESULT( hr );\n";
  917. // Adds call to SetResult, like "SetResult_UINT16( stack, retVal );
  918. // We need to set result only if managed method is not void.
  919. if ( !elemPtrArray[ 0 ]->IsVoidType() )
  920. {
  921. strFuncImpl += " SetResult_" + elemPtrArray[ 0 ]->GetNativeType() + "( stack, retVal );\n\n";
  922. }
  923. // Add code for storing of references.
  924. for ( UINT32 i = 1; i < elemPtrArray.size(); i++ )
  925. {
  926. strFuncImpl += elemPtrArray[