PageRenderTime 62ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/WCFWebApi/prototype/Microsoft.ApplicationServer.HttpEnhancements/System/ServiceModel/Dispatcher/CodeGenerator.cs

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