2
0

CodeGenerator.cs 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. // ***NOTE*** If this code is changed, make corresponding changes in System.Runtime.Serialization.CodeGenerator also
  5. namespace System.ServiceModel.Dispatcher
  6. {
  7. using System;
  8. using System.Collections;
  9. using System.Diagnostics;
  10. using System.Globalization;
  11. using System.Reflection;
  12. using System.Reflection.Emit;
  13. using System.Runtime;
  14. using System.Security;
  15. using System.ServiceModel.Diagnostics;
  16. [Fx.Tag.SecurityNote(Critical = "Generates IL into an ILGenerator that was created under an Assert."
  17. + "Generated IL must be correct and must not subvert the type system.")]
  18. #pragma warning disable 618 // have not moved to the v4 security model yet
  19. [SecurityCritical(SecurityCriticalScope.Everything)]
  20. #pragma warning restore 618
  21. internal class CodeGenerator
  22. {
  23. static MethodInfo getTypeFromHandle;
  24. static MethodInfo stringConcat2;
  25. static MethodInfo objectToString;
  26. static MethodInfo boxPointer;
  27. static MethodInfo unboxPointer;
  28. #if USE_REFEMIT
  29. AssemblyBuilder assemblyBuilder;
  30. ModuleBuilder moduleBuilder;
  31. TypeBuilder typeBuilder;
  32. static int typeCounter;
  33. MethodBuilder methodBuilder;
  34. #else
  35. static Module SerializationModule = typeof(CodeGenerator).Module; // Can be replaced by different assembly with SkipVerification set to false
  36. DynamicMethod dynamicMethod;
  37. #if DEBUG
  38. bool allowPrivateMemberAccess;
  39. #endif
  40. #endif
  41. Type delegateType;
  42. ILGenerator ilGen;
  43. ArrayList argList;
  44. Stack blockStack;
  45. Label methodEndLabel;
  46. Hashtable localNames;
  47. int lineNo = 1;
  48. enum CodeGenTrace { None, Save, Tron };
  49. CodeGenTrace codeGenTrace;
  50. internal CodeGenerator()
  51. {
  52. SourceSwitch codeGenSwitch = OperationInvokerTrace.CodeGenerationSwitch;
  53. if ((codeGenSwitch.Level & SourceLevels.Verbose) == SourceLevels.Verbose)
  54. codeGenTrace = CodeGenTrace.Tron;
  55. else if ((codeGenSwitch.Level & SourceLevels.Information) == SourceLevels.Information)
  56. codeGenTrace = CodeGenTrace.Save;
  57. else
  58. codeGenTrace = CodeGenTrace.None;
  59. }
  60. static MethodInfo GetTypeFromHandle
  61. {
  62. get
  63. {
  64. if (getTypeFromHandle == null)
  65. getTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle");
  66. return getTypeFromHandle;
  67. }
  68. }
  69. static MethodInfo StringConcat2
  70. {
  71. get
  72. {
  73. if (stringConcat2 == null)
  74. stringConcat2 = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
  75. return stringConcat2;
  76. }
  77. }
  78. static MethodInfo ObjectToString
  79. {
  80. get
  81. {
  82. if (objectToString == null)
  83. objectToString = typeof(object).GetMethod("ToString", new Type[0]);
  84. return objectToString;
  85. }
  86. }
  87. static MethodInfo BoxPointer
  88. {
  89. get
  90. {
  91. if (boxPointer == null)
  92. boxPointer = typeof(Pointer).GetMethod("Box");
  93. return boxPointer;
  94. }
  95. }
  96. static MethodInfo UnboxPointer
  97. {
  98. get
  99. {
  100. if (unboxPointer == null)
  101. unboxPointer = typeof(Pointer).GetMethod("Unbox");
  102. return unboxPointer;
  103. }
  104. }
  105. internal void BeginMethod(string methodName, Type delegateType, bool allowPrivateMemberAccess)
  106. {
  107. MethodInfo signature = delegateType.GetMethod("Invoke");
  108. ParameterInfo[] parameters = signature.GetParameters();
  109. Type[] paramTypes = new Type[parameters.Length];
  110. for (int i = 0; i < parameters.Length; i++)
  111. paramTypes[i] = parameters[i].ParameterType;
  112. BeginMethod(signature.ReturnType, methodName, paramTypes, allowPrivateMemberAccess);
  113. this.delegateType = delegateType;
  114. }
  115. void BeginMethod(Type returnType, string methodName, Type[] argTypes, bool allowPrivateMemberAccess)
  116. {
  117. #if USE_REFEMIT
  118. string typeName = "Type" + (typeCounter++);
  119. InitAssemblyBuilder(typeName + "." + methodName);
  120. this.typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
  121. this.methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Public|MethodAttributes.Static, returnType, argTypes);
  122. this.ilGen = this.methodBuilder.GetILGenerator();
  123. #else
  124. this.dynamicMethod = new DynamicMethod(methodName, returnType, argTypes, SerializationModule, allowPrivateMemberAccess);
  125. this.ilGen = this.dynamicMethod.GetILGenerator();
  126. #if DEBUG
  127. this.allowPrivateMemberAccess = allowPrivateMemberAccess;
  128. #endif
  129. #endif
  130. this.methodEndLabel = ilGen.DefineLabel();
  131. this.blockStack = new Stack();
  132. this.argList = new ArrayList();
  133. for (int i = 0; i < argTypes.Length; i++)
  134. argList.Add(new ArgBuilder(i, argTypes[i]));
  135. if (codeGenTrace != CodeGenTrace.None)
  136. EmitSourceLabel("Begin method " + methodName + " {");
  137. }
  138. internal Delegate EndMethod()
  139. {
  140. MarkLabel(methodEndLabel);
  141. if (codeGenTrace != CodeGenTrace.None)
  142. EmitSourceLabel("} End method");
  143. Ret();
  144. Delegate retVal = null;
  145. #if USE_REFEMIT
  146. Type type = typeBuilder.CreateType();
  147. if (codeGenTrace != CodeGenTrace.None)
  148. assemblyBuilder.Save(assemblyBuilder.GetName().Name+".dll");
  149. MethodInfo method = type.GetMethod(methodBuilder.Name);
  150. retVal = Delegate.CreateDelegate(delegateType, method);
  151. methodBuilder = null;
  152. #else
  153. retVal = dynamicMethod.CreateDelegate(delegateType);
  154. dynamicMethod = null;
  155. #endif
  156. delegateType = null;
  157. ilGen = null;
  158. blockStack = null;
  159. argList = null;
  160. return retVal;
  161. }
  162. internal MethodInfo CurrentMethod
  163. {
  164. get
  165. {
  166. #if USE_REFEMIT
  167. return methodBuilder;
  168. #else
  169. return dynamicMethod;
  170. #endif
  171. }
  172. }
  173. internal ArgBuilder GetArg(int index)
  174. {
  175. return (ArgBuilder)argList[index];
  176. }
  177. internal Type GetVariableType(object var)
  178. {
  179. if (var is ArgBuilder)
  180. return ((ArgBuilder)var).ArgType;
  181. else if (var is LocalBuilder)
  182. return ((LocalBuilder)var).LocalType;
  183. else
  184. return var.GetType();
  185. }
  186. internal LocalBuilder DeclareLocal(Type type, string name)
  187. {
  188. return DeclareLocal(type, name, false);
  189. }
  190. internal LocalBuilder DeclareLocal(Type type, string name, bool isPinned)
  191. {
  192. LocalBuilder local = ilGen.DeclareLocal(type, isPinned);
  193. if (codeGenTrace != CodeGenTrace.None)
  194. {
  195. LocalNames[local] = name;
  196. EmitSourceComment("Declare local '" + name + "' of type " + type);
  197. }
  198. return local;
  199. }
  200. internal void If()
  201. {
  202. InternalIf(false);
  203. }
  204. internal void IfNot()
  205. {
  206. InternalIf(true);
  207. }
  208. internal void Else()
  209. {
  210. IfState ifState = PopIfState();
  211. Br(ifState.EndIf);
  212. MarkLabel(ifState.ElseBegin);
  213. ifState.ElseBegin = ifState.EndIf;
  214. blockStack.Push(ifState);
  215. }
  216. internal void EndIf()
  217. {
  218. IfState ifState = PopIfState();
  219. if (!ifState.ElseBegin.Equals(ifState.EndIf))
  220. MarkLabel(ifState.ElseBegin);
  221. MarkLabel(ifState.EndIf);
  222. }
  223. internal void Call(MethodInfo methodInfo)
  224. {
  225. if (methodInfo.IsVirtual)
  226. {
  227. if (codeGenTrace != CodeGenTrace.None)
  228. EmitSourceInstruction("Callvirt " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
  229. ilGen.Emit(OpCodes.Callvirt, methodInfo);
  230. }
  231. else if (methodInfo.IsStatic)
  232. {
  233. if (codeGenTrace != CodeGenTrace.None)
  234. EmitSourceInstruction("Static Call " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
  235. ilGen.Emit(OpCodes.Call, methodInfo);
  236. }
  237. else
  238. {
  239. if (codeGenTrace != CodeGenTrace.None)
  240. EmitSourceInstruction("Call " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
  241. ilGen.Emit(OpCodes.Call, methodInfo);
  242. }
  243. }
  244. internal void New(ConstructorInfo constructor)
  245. {
  246. if (codeGenTrace != CodeGenTrace.None)
  247. EmitSourceInstruction("Newobj " + constructor.ToString() + " on type " + constructor.DeclaringType.ToString());
  248. ilGen.Emit(OpCodes.Newobj, constructor);
  249. }
  250. internal void InitObj(Type valueType)
  251. {
  252. if (codeGenTrace != CodeGenTrace.None)
  253. EmitSourceInstruction("Initobj " + valueType);
  254. ilGen.Emit(OpCodes.Initobj, valueType);
  255. }
  256. internal void LoadArrayElement(object obj, object arrayIndex)
  257. {
  258. Type objType = GetVariableType(obj).GetElementType();
  259. Load(obj);
  260. Load(arrayIndex);
  261. if (IsStruct(objType))
  262. {
  263. Ldelema(objType);
  264. Ldobj(objType);
  265. }
  266. else
  267. Ldelem(objType);
  268. }
  269. internal void StoreArrayElement(object obj, object arrayIndex, object value)
  270. {
  271. Type objType = GetVariableType(obj).GetElementType();
  272. Load(obj);
  273. Load(arrayIndex);
  274. if (IsStruct(objType))
  275. Ldelema(objType);
  276. Load(value);
  277. ConvertValue(GetVariableType(value), objType);
  278. if (IsStruct(objType))
  279. Stobj(objType);
  280. else
  281. Stelem(objType);
  282. }
  283. static bool IsStruct(Type objType)
  284. {
  285. return objType.IsValueType && !objType.IsPrimitive;
  286. }
  287. internal void Load(object obj)
  288. {
  289. if (obj == null)
  290. {
  291. if (codeGenTrace != CodeGenTrace.None)
  292. EmitSourceInstruction("Ldnull");
  293. ilGen.Emit(OpCodes.Ldnull);
  294. }
  295. else if (obj is ArgBuilder)
  296. Ldarg((ArgBuilder)obj);
  297. else if (obj is LocalBuilder)
  298. Ldloc((LocalBuilder)obj);
  299. else
  300. Ldc(obj);
  301. }
  302. internal void Store(object var)
  303. {
  304. if (var is ArgBuilder)
  305. Starg((ArgBuilder)var);
  306. else if (var is LocalBuilder)
  307. Stloc((LocalBuilder)var);
  308. else
  309. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCodeGenCanOnlyStoreIntoArgOrLocGot0, var.GetType().FullName)));
  310. }
  311. internal void LoadAddress(object obj)
  312. {
  313. if (obj is ArgBuilder)
  314. LdargAddress((ArgBuilder)obj);
  315. else if (obj is LocalBuilder)
  316. LdlocAddress((LocalBuilder)obj);
  317. else
  318. Load(obj);
  319. }
  320. internal void ConvertAddress(Type source, Type target)
  321. {
  322. InternalConvert(source, target, true);
  323. }
  324. internal void ConvertValue(Type source, Type target)
  325. {
  326. InternalConvert(source, target, false);
  327. }
  328. internal void Castclass(Type target)
  329. {
  330. if (codeGenTrace != CodeGenTrace.None)
  331. EmitSourceInstruction("Castclass " + target);
  332. ilGen.Emit(OpCodes.Castclass, target);
  333. }
  334. internal void Box(Type type)
  335. {
  336. if (codeGenTrace != CodeGenTrace.None)
  337. EmitSourceInstruction("Box " + type);
  338. ilGen.Emit(OpCodes.Box, type);
  339. }
  340. internal void Unbox(Type type)
  341. {
  342. if (codeGenTrace != CodeGenTrace.None)
  343. EmitSourceInstruction("Unbox " + type);
  344. ilGen.Emit(OpCodes.Unbox, type);
  345. }
  346. internal void Ldobj(Type type)
  347. {
  348. OpCode opCode = GetLdindOpCode(Type.GetTypeCode(type));
  349. if (!opCode.Equals(OpCodes.Nop))
  350. {
  351. if (codeGenTrace != CodeGenTrace.None)
  352. EmitSourceInstruction(opCode.ToString());
  353. ilGen.Emit(opCode);
  354. }
  355. else
  356. {
  357. if (codeGenTrace != CodeGenTrace.None)
  358. EmitSourceInstruction("Ldobj " + type);
  359. ilGen.Emit(OpCodes.Ldobj, type);
  360. }
  361. }
  362. internal void Stobj(Type type)
  363. {
  364. if (codeGenTrace != CodeGenTrace.None)
  365. EmitSourceInstruction("Stobj " + type);
  366. ilGen.Emit(OpCodes.Stobj, type);
  367. }
  368. internal void Ldtoken(Type t)
  369. {
  370. if (codeGenTrace != CodeGenTrace.None)
  371. EmitSourceInstruction("Ldtoken " + t);
  372. ilGen.Emit(OpCodes.Ldtoken, t);
  373. }
  374. internal void Ldc(object o)
  375. {
  376. Type valueType = o.GetType();
  377. if (o is Type)
  378. {
  379. Ldtoken((Type)o);
  380. Call(GetTypeFromHandle);
  381. }
  382. else if (valueType.IsEnum)
  383. {
  384. if (codeGenTrace != CodeGenTrace.None)
  385. EmitSourceComment("Ldc " + o.GetType() + "." + o);
  386. Ldc(((IConvertible)o).ToType(Enum.GetUnderlyingType(valueType), null));
  387. }
  388. else
  389. {
  390. switch (Type.GetTypeCode(valueType))
  391. {
  392. case TypeCode.Boolean:
  393. Ldc((bool)o);
  394. break;
  395. case TypeCode.Char:
  396. Ldc((int)(char)o);
  397. break;
  398. case TypeCode.SByte:
  399. case TypeCode.Byte:
  400. case TypeCode.Int16:
  401. case TypeCode.UInt16:
  402. Ldc(((IConvertible)o).ToInt32(CultureInfo.InvariantCulture));
  403. break;
  404. case TypeCode.Int32:
  405. Ldc((int)o);
  406. break;
  407. case TypeCode.UInt32:
  408. Ldc((int)(uint)o);
  409. break;
  410. case TypeCode.String:
  411. Ldstr((string)o);
  412. break;
  413. case TypeCode.UInt64:
  414. case TypeCode.Int64:
  415. case TypeCode.Single:
  416. case TypeCode.Double:
  417. case TypeCode.Object:
  418. case TypeCode.Decimal:
  419. case TypeCode.DateTime:
  420. case TypeCode.Empty:
  421. case TypeCode.DBNull:
  422. default:
  423. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCodeGenUnknownConstantType, valueType.FullName)));
  424. }
  425. }
  426. }
  427. internal void Ldc(bool boolVar)
  428. {
  429. if (boolVar)
  430. {
  431. if (codeGenTrace != CodeGenTrace.None)
  432. EmitSourceInstruction("Ldc.i4 1");
  433. ilGen.Emit(OpCodes.Ldc_I4_1);
  434. }
  435. else
  436. {
  437. if (codeGenTrace != CodeGenTrace.None)
  438. EmitSourceInstruction("Ldc.i4 0");
  439. ilGen.Emit(OpCodes.Ldc_I4_0);
  440. }
  441. }
  442. internal void Ldc(int intVar)
  443. {
  444. if (codeGenTrace != CodeGenTrace.None)
  445. EmitSourceInstruction("Ldc.i4 " + intVar);
  446. switch (intVar)
  447. {
  448. case -1:
  449. ilGen.Emit(OpCodes.Ldc_I4_M1);
  450. break;
  451. case 0:
  452. ilGen.Emit(OpCodes.Ldc_I4_0);
  453. break;
  454. case 1:
  455. ilGen.Emit(OpCodes.Ldc_I4_1);
  456. break;
  457. case 2:
  458. ilGen.Emit(OpCodes.Ldc_I4_2);
  459. break;
  460. case 3:
  461. ilGen.Emit(OpCodes.Ldc_I4_3);
  462. break;
  463. case 4:
  464. ilGen.Emit(OpCodes.Ldc_I4_4);
  465. break;
  466. case 5:
  467. ilGen.Emit(OpCodes.Ldc_I4_5);
  468. break;
  469. case 6:
  470. ilGen.Emit(OpCodes.Ldc_I4_6);
  471. break;
  472. case 7:
  473. ilGen.Emit(OpCodes.Ldc_I4_7);
  474. break;
  475. case 8:
  476. ilGen.Emit(OpCodes.Ldc_I4_8);
  477. break;
  478. default:
  479. ilGen.Emit(OpCodes.Ldc_I4, intVar);
  480. break;
  481. }
  482. }
  483. internal void Ldstr(string strVar)
  484. {
  485. if (codeGenTrace != CodeGenTrace.None)
  486. EmitSourceInstruction("Ldstr " + strVar);
  487. ilGen.Emit(OpCodes.Ldstr, strVar);
  488. }
  489. internal void LdlocAddress(LocalBuilder localBuilder)
  490. {
  491. if (localBuilder.LocalType.IsValueType)
  492. Ldloca(localBuilder);
  493. else
  494. Ldloc(localBuilder);
  495. }
  496. internal void Ldloc(LocalBuilder localBuilder)
  497. {
  498. if (codeGenTrace != CodeGenTrace.None)
  499. EmitSourceInstruction("Ldloc " + LocalNames[localBuilder]);
  500. ilGen.Emit(OpCodes.Ldloc, localBuilder);
  501. EmitStackTop(localBuilder.LocalType);
  502. }
  503. internal void Stloc(LocalBuilder local)
  504. {
  505. if (codeGenTrace != CodeGenTrace.None)
  506. EmitSourceInstruction("Stloc " + LocalNames[local]);
  507. EmitStackTop(local.LocalType);
  508. ilGen.Emit(OpCodes.Stloc, local);
  509. }
  510. internal void Ldloc(int slot)
  511. {
  512. if (codeGenTrace != CodeGenTrace.None)
  513. EmitSourceInstruction("Ldloc " + slot);
  514. switch (slot)
  515. {
  516. case 0:
  517. ilGen.Emit(OpCodes.Ldloc_0);
  518. break;
  519. case 1:
  520. ilGen.Emit(OpCodes.Ldloc_1);
  521. break;
  522. case 2:
  523. ilGen.Emit(OpCodes.Ldloc_2);
  524. break;
  525. case 3:
  526. ilGen.Emit(OpCodes.Ldloc_3);
  527. break;
  528. default:
  529. if (slot <= 255)
  530. ilGen.Emit(OpCodes.Ldloc_S, slot);
  531. else
  532. ilGen.Emit(OpCodes.Ldloc, slot);
  533. break;
  534. }
  535. }
  536. internal void Stloc(int slot)
  537. {
  538. if (codeGenTrace != CodeGenTrace.None)
  539. EmitSourceInstruction("Stloc " + slot);
  540. switch (slot)
  541. {
  542. case 0:
  543. ilGen.Emit(OpCodes.Stloc_0);
  544. break;
  545. case 1:
  546. ilGen.Emit(OpCodes.Stloc_1);
  547. break;
  548. case 2:
  549. ilGen.Emit(OpCodes.Stloc_2);
  550. break;
  551. case 3:
  552. ilGen.Emit(OpCodes.Stloc_3);
  553. break;
  554. default:
  555. if (slot <= 255)
  556. ilGen.Emit(OpCodes.Stloc_S, slot);
  557. else
  558. ilGen.Emit(OpCodes.Stloc, slot);
  559. break;
  560. }
  561. }
  562. internal void Ldloca(LocalBuilder localBuilder)
  563. {
  564. if (codeGenTrace != CodeGenTrace.None)
  565. EmitSourceInstruction("Ldloca " + LocalNames[localBuilder]);
  566. ilGen.Emit(OpCodes.Ldloca, localBuilder);
  567. EmitStackTop(localBuilder.LocalType);
  568. }
  569. internal void Ldloca(int slot)
  570. {
  571. if (codeGenTrace != CodeGenTrace.None)
  572. EmitSourceInstruction("Ldloca " + slot);
  573. if (slot <= 255)
  574. ilGen.Emit(OpCodes.Ldloca_S, slot);
  575. else
  576. ilGen.Emit(OpCodes.Ldloca, slot);
  577. }
  578. internal void LdargAddress(ArgBuilder argBuilder)
  579. {
  580. if (argBuilder.ArgType.IsValueType)
  581. Ldarga(argBuilder);
  582. else
  583. Ldarg(argBuilder);
  584. }
  585. internal void Ldarg(ArgBuilder arg)
  586. {
  587. Ldarg(arg.Index);
  588. }
  589. internal void Starg(ArgBuilder arg)
  590. {
  591. Starg(arg.Index);
  592. }
  593. internal void Ldarg(int slot)
  594. {
  595. if (codeGenTrace != CodeGenTrace.None)
  596. EmitSourceInstruction("Ldarg " + slot);
  597. switch (slot)
  598. {
  599. case 0:
  600. ilGen.Emit(OpCodes.Ldarg_0);
  601. break;
  602. case 1:
  603. ilGen.Emit(OpCodes.Ldarg_1);
  604. break;
  605. case 2:
  606. ilGen.Emit(OpCodes.Ldarg_2);
  607. break;
  608. case 3:
  609. ilGen.Emit(OpCodes.Ldarg_3);
  610. break;
  611. default:
  612. if (slot <= 255)
  613. ilGen.Emit(OpCodes.Ldarg_S, slot);
  614. else
  615. ilGen.Emit(OpCodes.Ldarg, slot);
  616. break;
  617. }
  618. }
  619. internal void Starg(int slot)
  620. {
  621. if (codeGenTrace != CodeGenTrace.None)
  622. EmitSourceInstruction("Starg " + slot);
  623. if (slot <= 255)
  624. ilGen.Emit(OpCodes.Starg_S, slot);
  625. else
  626. ilGen.Emit(OpCodes.Starg, slot);
  627. }
  628. internal void Ldarga(ArgBuilder argBuilder)
  629. {
  630. Ldarga(argBuilder.Index);
  631. }
  632. internal void Ldarga(int slot)
  633. {
  634. if (codeGenTrace != CodeGenTrace.None)
  635. EmitSourceInstruction("Ldarga " + slot);
  636. if (slot <= 255)
  637. ilGen.Emit(OpCodes.Ldarga_S, slot);
  638. else
  639. ilGen.Emit(OpCodes.Ldarga, slot);
  640. }
  641. internal void Ldelem(Type arrayElementType)
  642. {
  643. if (arrayElementType.IsEnum)
  644. {
  645. Ldelem(Enum.GetUnderlyingType(arrayElementType));
  646. }
  647. else
  648. {
  649. OpCode opCode = GetLdelemOpCode(Type.GetTypeCode(arrayElementType));
  650. if (opCode.Equals(OpCodes.Nop))
  651. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCodeGenArrayTypeIsNotSupported, arrayElementType.FullName)));
  652. if (codeGenTrace != CodeGenTrace.None)
  653. EmitSourceInstruction(opCode.ToString());
  654. ilGen.Emit(opCode);
  655. EmitStackTop(arrayElementType);
  656. }
  657. }
  658. internal void Ldelema(Type arrayElementType)
  659. {
  660. OpCode opCode = OpCodes.Ldelema;
  661. if (codeGenTrace != CodeGenTrace.None)
  662. EmitSourceInstruction(opCode.ToString());
  663. ilGen.Emit(opCode, arrayElementType);
  664. EmitStackTop(arrayElementType);
  665. }
  666. internal void Stelem(Type arrayElementType)
  667. {
  668. if (arrayElementType.IsEnum)
  669. Stelem(Enum.GetUnderlyingType(arrayElementType));
  670. else
  671. {
  672. OpCode opCode = GetStelemOpCode(Type.GetTypeCode(arrayElementType));
  673. if (opCode.Equals(OpCodes.Nop))
  674. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCodeGenArrayTypeIsNotSupported, arrayElementType.FullName)));
  675. if (codeGenTrace != CodeGenTrace.None)
  676. EmitSourceInstruction(opCode.ToString());
  677. EmitStackTop(arrayElementType);
  678. ilGen.Emit(opCode);
  679. }
  680. }
  681. internal Label DefineLabel()
  682. {
  683. return ilGen.DefineLabel();
  684. }
  685. internal void MarkLabel(Label label)
  686. {
  687. ilGen.MarkLabel(label);
  688. if (codeGenTrace != CodeGenTrace.None)
  689. EmitSourceLabel(label.GetHashCode() + ":");
  690. }
  691. internal void Ret()
  692. {
  693. if (codeGenTrace != CodeGenTrace.None)
  694. EmitSourceInstruction("Ret");
  695. ilGen.Emit(OpCodes.Ret);
  696. }
  697. internal void Br(Label label)
  698. {
  699. if (codeGenTrace != CodeGenTrace.None)
  700. EmitSourceInstruction("Br " + label.GetHashCode());
  701. ilGen.Emit(OpCodes.Br, label);
  702. }
  703. internal void Brfalse(Label label)
  704. {
  705. if (codeGenTrace != CodeGenTrace.None)
  706. EmitSourceInstruction("Brfalse " + label.GetHashCode());
  707. ilGen.Emit(OpCodes.Brfalse, label);
  708. }
  709. internal void Brtrue(Label label)
  710. {
  711. if (codeGenTrace != CodeGenTrace.None)
  712. EmitSourceInstruction("Brtrue " + label.GetHashCode());
  713. ilGen.Emit(OpCodes.Brtrue, label);
  714. }
  715. internal void Pop()
  716. {
  717. if (codeGenTrace != CodeGenTrace.None)
  718. EmitSourceInstruction("Pop");
  719. ilGen.Emit(OpCodes.Pop);
  720. }
  721. internal void Dup()
  722. {
  723. if (codeGenTrace != CodeGenTrace.None)
  724. EmitSourceInstruction("Dup");
  725. ilGen.Emit(OpCodes.Dup);
  726. }
  727. void InternalIf(bool negate)
  728. {
  729. IfState ifState = new IfState();
  730. ifState.EndIf = DefineLabel();
  731. ifState.ElseBegin = DefineLabel();
  732. if (negate)
  733. Brtrue(ifState.ElseBegin);
  734. else
  735. Brfalse(ifState.ElseBegin);
  736. blockStack.Push(ifState);
  737. }
  738. void InternalConvert(Type source, Type target, bool isAddress)
  739. {
  740. if (target == source)
  741. return;
  742. if (target.IsValueType)
  743. {
  744. if (source.IsValueType)
  745. {
  746. OpCode opCode = GetConvOpCode(Type.GetTypeCode(target));
  747. if (opCode.Equals(OpCodes.Nop))
  748. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCodeGenNoConversionPossibleTo, target.FullName)));
  749. else
  750. {
  751. if (codeGenTrace != CodeGenTrace.None)
  752. EmitSourceInstruction(opCode.ToString());
  753. ilGen.Emit(opCode);
  754. }
  755. }
  756. else if (source.IsAssignableFrom(target))
  757. {
  758. Unbox(target);
  759. if (!isAddress)
  760. Ldobj(target);
  761. }
  762. else
  763. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCodeGenIsNotAssignableFrom, target.FullName, source.FullName)));
  764. }
  765. else if (target.IsPointer)
  766. {
  767. Call(UnboxPointer);
  768. }
  769. else if (source.IsPointer)
  770. {
  771. Load(source);
  772. Call(BoxPointer);
  773. }
  774. else if (target.IsAssignableFrom(source))
  775. {
  776. if (source.IsValueType)
  777. {
  778. if (isAddress)
  779. Ldobj(source);
  780. Box(source);
  781. }
  782. }
  783. else if (source.IsAssignableFrom(target))
  784. {
  785. //assert(source.IsValueType == false);
  786. Castclass(target);
  787. }
  788. else if (target.IsInterface || source.IsInterface)
  789. {
  790. Castclass(target);
  791. }
  792. else
  793. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCodeGenIsNotAssignableFrom, target.FullName, source.FullName)));
  794. }
  795. IfState PopIfState()
  796. {
  797. object stackTop = blockStack.Pop();
  798. IfState ifState = stackTop as IfState;
  799. if (ifState == null)
  800. ThrowMismatchException(stackTop);
  801. return ifState;
  802. }
  803. #if USE_REFEMIT
  804. void InitAssemblyBuilder(string methodName)
  805. {
  806. //if (assemblyBuilder == null) {
  807. AssemblyName name = new AssemblyName();
  808. name.Name = "Microsoft.GeneratedCode."+methodName;
  809. bool saveAssembly = false;
  810. if (codeGenTrace != CodeGenTrace.None)
  811. saveAssembly = true;
  812. if (saveAssembly)
  813. {
  814. assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
  815. moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name, name.Name + ".dll", false);
  816. }
  817. else
  818. {
  819. assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
  820. moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name, false);
  821. }
  822. //}
  823. }
  824. #endif
  825. void ThrowMismatchException(object expected)
  826. {
  827. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCodeGenExpectingEnd, expected.ToString())));
  828. }
  829. Hashtable LocalNames
  830. {
  831. get
  832. {
  833. if (localNames == null)
  834. localNames = new Hashtable();
  835. return localNames;
  836. }
  837. }
  838. OpCode GetConvOpCode(TypeCode typeCode)
  839. {
  840. switch (typeCode)
  841. {
  842. case TypeCode.Boolean:
  843. return OpCodes.Conv_I1; // TypeCode.Boolean:
  844. case TypeCode.Char:
  845. return OpCodes.Conv_I2; // TypeCode.Char:
  846. case TypeCode.SByte:
  847. return OpCodes.Conv_I1; // TypeCode.SByte:
  848. case TypeCode.Byte:
  849. return OpCodes.Conv_U1; // TypeCode.Byte:
  850. case TypeCode.Int16:
  851. return OpCodes.Conv_I2; // TypeCode.Int16:
  852. case TypeCode.UInt16:
  853. return OpCodes.Conv_U2; // TypeCode.UInt16:
  854. case TypeCode.Int32:
  855. return OpCodes.Conv_I4; // TypeCode.Int32:
  856. case TypeCode.UInt32:
  857. return OpCodes.Conv_U4; // TypeCode.UInt32:
  858. case TypeCode.Int64:
  859. return OpCodes.Conv_I8; // TypeCode.Int64:
  860. case TypeCode.UInt64:
  861. return OpCodes.Conv_I8; // TypeCode.UInt64:
  862. case TypeCode.Single:
  863. return OpCodes.Conv_R4; // TypeCode.Single:
  864. case TypeCode.Double:
  865. return OpCodes.Conv_R8; // TypeCode.Double:
  866. default:
  867. return OpCodes.Nop;
  868. }
  869. }
  870. OpCode GetLdindOpCode(TypeCode typeCode)
  871. {
  872. switch (typeCode)
  873. {
  874. case TypeCode.Boolean:
  875. return OpCodes.Ldind_I1; // TypeCode.Boolean:
  876. case TypeCode.Char:
  877. return OpCodes.Ldind_I2; // TypeCode.Char:
  878. case TypeCode.SByte:
  879. return OpCodes.Ldind_I1; // TypeCode.SByte:
  880. case TypeCode.Byte:
  881. return OpCodes.Ldind_U1; // TypeCode.Byte:
  882. case TypeCode.Int16:
  883. return OpCodes.Ldind_I2; // TypeCode.Int16:
  884. case TypeCode.UInt16:
  885. return OpCodes.Ldind_U2; // TypeCode.UInt16:
  886. case TypeCode.Int32:
  887. return OpCodes.Ldind_I4; // TypeCode.Int32:
  888. case TypeCode.UInt32:
  889. return OpCodes.Ldind_U4; // TypeCode.UInt32:
  890. case TypeCode.Int64:
  891. return OpCodes.Ldind_I8; // TypeCode.Int64:
  892. case TypeCode.UInt64:
  893. return OpCodes.Ldind_I8; // TypeCode.UInt64:
  894. case TypeCode.Single:
  895. return OpCodes.Ldind_R4; // TypeCode.Single:
  896. case TypeCode.Double:
  897. return OpCodes.Ldind_R8; // TypeCode.Double:
  898. case TypeCode.String:
  899. return OpCodes.Ldind_Ref; // TypeCode.String:
  900. default:
  901. return OpCodes.Nop;
  902. }
  903. //
  904. }
  905. OpCode GetLdelemOpCode(TypeCode typeCode)
  906. {
  907. switch (typeCode)
  908. {
  909. case TypeCode.Object:
  910. return OpCodes.Ldelem_Ref; // TypeCode.Object:
  911. case TypeCode.Boolean:
  912. return OpCodes.Ldelem_I1; // TypeCode.Boolean:
  913. case TypeCode.Char:
  914. return OpCodes.Ldelem_I2; // TypeCode.Char:
  915. case TypeCode.SByte:
  916. return OpCodes.Ldelem_I1; // TypeCode.SByte:
  917. case TypeCode.Byte:
  918. return OpCodes.Ldelem_U1; // TypeCode.Byte:
  919. case TypeCode.Int16:
  920. return OpCodes.Ldelem_I2; // TypeCode.Int16:
  921. case TypeCode.UInt16:
  922. return OpCodes.Ldelem_U2; // TypeCode.UInt16:
  923. case TypeCode.Int32:
  924. return OpCodes.Ldelem_I4; // TypeCode.Int32:
  925. case TypeCode.UInt32:
  926. return OpCodes.Ldelem_U4; // TypeCode.UInt32:
  927. case TypeCode.Int64:
  928. return OpCodes.Ldelem_I8; // TypeCode.Int64:
  929. case TypeCode.UInt64:
  930. return OpCodes.Ldelem_I8; // TypeCode.UInt64:
  931. case TypeCode.Single:
  932. return OpCodes.Ldelem_R4; // TypeCode.Single:
  933. case TypeCode.Double:
  934. return OpCodes.Ldelem_R8; // TypeCode.Double:
  935. case TypeCode.String:
  936. return OpCodes.Ldelem_Ref; // TypeCode.String:
  937. default:
  938. return OpCodes.Nop;
  939. }
  940. }
  941. OpCode GetStelemOpCode(TypeCode typeCode)
  942. {
  943. switch (typeCode)
  944. {
  945. case TypeCode.Object:
  946. return OpCodes.Stelem_Ref; // TypeCode.Object:
  947. case TypeCode.Boolean:
  948. return OpCodes.Stelem_I1; // TypeCode.Boolean:
  949. case TypeCode.Char:
  950. return OpCodes.Stelem_I2; // TypeCode.Char:
  951. case TypeCode.SByte:
  952. return OpCodes.Stelem_I1; // TypeCode.SByte:
  953. case TypeCode.Byte:
  954. return OpCodes.Stelem_I1; // TypeCode.Byte:
  955. case TypeCode.Int16:
  956. return OpCodes.Stelem_I2; // TypeCode.Int16:
  957. case TypeCode.UInt16:
  958. return OpCodes.Stelem_I2; // TypeCode.UInt16:
  959. case TypeCode.Int32:
  960. return OpCodes.Stelem_I4; // TypeCode.Int32:
  961. case TypeCode.UInt32:
  962. return OpCodes.Stelem_I4; // TypeCode.UInt32:
  963. case TypeCode.Int64:
  964. return OpCodes.Stelem_I8; // TypeCode.Int64:
  965. case TypeCode.UInt64:
  966. return OpCodes.Stelem_I8; // TypeCode.UInt64:
  967. case TypeCode.Single:
  968. return OpCodes.Stelem_R4; // TypeCode.Single:
  969. case TypeCode.Double:
  970. return OpCodes.Stelem_R8; // TypeCode.Double:
  971. case TypeCode.String:
  972. return OpCodes.Stelem_Ref; // TypeCode.String:
  973. default:
  974. return OpCodes.Nop;
  975. }
  976. }
  977. internal void EmitSourceInstruction(string line)
  978. {
  979. EmitSourceLine(" " + line);
  980. }
  981. internal void EmitSourceLabel(string line)
  982. {
  983. EmitSourceLine(line);
  984. }
  985. internal void EmitSourceComment(string comment)
  986. {
  987. EmitSourceInstruction("// " + comment);
  988. }
  989. internal void EmitSourceLine(string line)
  990. {
  991. if (codeGenTrace != CodeGenTrace.None)
  992. OperationInvokerTrace.WriteInstruction(lineNo++, line);
  993. if (ilGen != null && codeGenTrace == CodeGenTrace.Tron)
  994. {
  995. ilGen.Emit(OpCodes.Ldstr, string.Format(CultureInfo.InvariantCulture, "{0:00000}: {1}", lineNo - 1, line));
  996. ilGen.Emit(OpCodes.Call, OperationInvokerTrace.TraceInstructionMethod);
  997. }
  998. }
  999. internal void EmitStackTop(Type stackTopType)
  1000. {
  1001. if (codeGenTrace != CodeGenTrace.Tron)
  1002. return;
  1003. codeGenTrace = CodeGenTrace.None;
  1004. Dup();
  1005. ToString(stackTopType);
  1006. LocalBuilder topValue = DeclareLocal(typeof(string), "topValue");
  1007. Store(topValue);
  1008. Load("//value = ");
  1009. Load(topValue);
  1010. Concat2();
  1011. Call(OperationInvokerTrace.TraceInstructionMethod);
  1012. codeGenTrace = CodeGenTrace.Tron;
  1013. }
  1014. internal void ToString(Type type)
  1015. {
  1016. if (type.IsValueType)
  1017. {
  1018. Box(type);
  1019. Call(ObjectToString);
  1020. }
  1021. else
  1022. {
  1023. Dup();
  1024. IfNot();
  1025. Pop();
  1026. Load("<null>");
  1027. Else();
  1028. Call(ObjectToString);
  1029. EndIf();
  1030. }
  1031. }
  1032. internal void Concat2()
  1033. {
  1034. Call(StringConcat2);
  1035. }
  1036. internal void LoadZeroValueIntoLocal(Type type, LocalBuilder local)
  1037. {
  1038. if (type.IsValueType)
  1039. {
  1040. switch (Type.GetTypeCode(type))
  1041. {
  1042. case TypeCode.Boolean:
  1043. case TypeCode.Char:
  1044. case TypeCode.SByte:
  1045. case TypeCode.Byte:
  1046. case TypeCode.Int16:
  1047. case TypeCode.UInt16:
  1048. case TypeCode.Int32:
  1049. case TypeCode.UInt32:
  1050. ilGen.Emit(OpCodes.Ldc_I4_0);
  1051. Store(local);
  1052. break;
  1053. case TypeCode.Int64:
  1054. case TypeCode.UInt64:
  1055. ilGen.Emit(OpCodes.Ldc_I4_0);
  1056. ilGen.Emit(OpCodes.Conv_I8);
  1057. Store(local);
  1058. break;
  1059. case TypeCode.Single:
  1060. ilGen.Emit(OpCodes.Ldc_R4, 0.0F);
  1061. Store(local);
  1062. break;
  1063. case TypeCode.Double:
  1064. ilGen.Emit(OpCodes.Ldc_R8, 0.0);
  1065. Store(local);
  1066. break;
  1067. case TypeCode.Decimal:
  1068. case TypeCode.DateTime:
  1069. default:
  1070. LoadAddress(local);
  1071. InitObj(type);
  1072. break;
  1073. }
  1074. }
  1075. else
  1076. {
  1077. Load(null);
  1078. Store(local);
  1079. }
  1080. }
  1081. }
  1082. internal class ArgBuilder
  1083. {
  1084. internal int Index;
  1085. internal Type ArgType;
  1086. internal ArgBuilder(int index, Type argType)
  1087. {
  1088. this.Index = index;
  1089. this.ArgType = argType;
  1090. }
  1091. }
  1092. internal class IfState
  1093. {
  1094. Label elseBegin;
  1095. Label endIf;
  1096. internal Label EndIf
  1097. {
  1098. get
  1099. {
  1100. return this.endIf;
  1101. }
  1102. set
  1103. {
  1104. this.endIf = value;
  1105. }
  1106. }
  1107. internal Label ElseBegin
  1108. {
  1109. get
  1110. {
  1111. return this.elseBegin;
  1112. }
  1113. set
  1114. {
  1115. this.elseBegin = value;
  1116. }
  1117. }
  1118. }
  1119. }