PageRenderTime 60ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/src/Boo.Lang.Compiler/Steps/EmitAssembly.cs

http://github.com/bamboo/boo
C# | 5680 lines | 4675 code | 807 blank | 198 comment | 887 complexity | af1838b67c0ca4a5b3a2b75e2abbb7b1 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. #region license
  2. // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without modification,
  6. // are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Rodrigo B. de Oliveira nor the names of its
  14. // contributors may be used to endorse or promote products derived from this
  15. // software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  18. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  21. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  25. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #endregion
  28. using System;
  29. using System.Collections;
  30. using System.Diagnostics;
  31. using System.Diagnostics.SymbolStore;
  32. using System.IO;
  33. using System.Linq;
  34. using System.Reflection;
  35. using System.Reflection.Emit;
  36. using System.Resources;
  37. using System.Text;
  38. using System.Text.RegularExpressions;
  39. using System.Threading;
  40. using System.Security;
  41. using Boo.Lang.Compiler.Ast;
  42. using Boo.Lang.Compiler.TypeSystem.Services;
  43. using Boo.Lang.Compiler.Util;
  44. using Boo.Lang.Compiler.TypeSystem;
  45. using Boo.Lang.Compiler.TypeSystem.Generics;
  46. using Boo.Lang.Compiler.TypeSystem.Internal;
  47. using Boo.Lang.Compiler.TypeSystem.Reflection;
  48. using Boo.Lang.Runtime;
  49. using Attribute = Boo.Lang.Compiler.Ast.Attribute;
  50. using Module = Boo.Lang.Compiler.Ast.Module;
  51. using System.Collections.Generic;
  52. using Method = Boo.Lang.Compiler.Ast.Method;
  53. using ExceptionHandler = Boo.Lang.Compiler.Ast.ExceptionHandler;
  54. namespace Boo.Lang.Compiler.Steps
  55. {
  56. sealed class LoopInfo
  57. {
  58. public Label BreakLabel;
  59. public Label ContinueLabel;
  60. public int TryBlockDepth;
  61. public LoopInfo(Label breakLabel, Label continueLabel, int tryBlockDepth)
  62. {
  63. BreakLabel = breakLabel;
  64. ContinueLabel = continueLabel;
  65. TryBlockDepth = tryBlockDepth;
  66. }
  67. }
  68. public class EmitAssembly : AbstractFastVisitorCompilerStep
  69. {
  70. static ConstructorInfo DebuggableAttribute_Constructor = Methods.ConstructorOf(() => new DebuggableAttribute(DebuggableAttribute.DebuggingModes.Default));
  71. static ConstructorInfo RuntimeCompatibilityAttribute_Constructor = Methods.ConstructorOf(() => new System.Runtime.CompilerServices.RuntimeCompatibilityAttribute());
  72. static ConstructorInfo SerializableAttribute_Constructor = Methods.ConstructorOf(() => new SerializableAttribute());
  73. static PropertyInfo[] RuntimeCompatibilityAttribute_Property = new[] { Properties.Of<System.Runtime.CompilerServices.RuntimeCompatibilityAttribute, bool>(a => a.WrapNonExceptionThrows) };
  74. static ConstructorInfo DuckTypedAttribute_Constructor = Methods.ConstructorOf(() => new DuckTypedAttribute());
  75. static ConstructorInfo ParamArrayAttribute_Constructor = Methods.ConstructorOf(() => new ParamArrayAttribute());
  76. static MethodInfo RuntimeServices_NormalizeArrayIndex = Methods.Of<Array, int, int>(RuntimeServices.NormalizeArrayIndex);
  77. static MethodInfo RuntimeServices_ToBool_Object = Types.RuntimeServices.GetMethod("ToBool", new Type[] { Types.Object });
  78. static MethodInfo RuntimeServices_ToBool_Decimal = Types.RuntimeServices.GetMethod("ToBool", new Type[] { Types.Decimal });
  79. static MethodInfo Builtins_ArrayTypedConstructor = Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.Int });
  80. static MethodInfo Builtins_ArrayGenericConstructor = Types.Builtins.GetMethod("array", new Type[] { Types.Int });
  81. static MethodInfo Builtins_ArrayTypedCollectionConstructor = Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.ICollection });
  82. private static MethodInfo Array_get_Length = Methods.GetterOf<Array, int>(a => a.Length);
  83. static MethodInfo Math_Pow = Methods.Of<double, double, double>(Math.Pow);
  84. static ConstructorInfo List_EmptyConstructor = Types.List.GetConstructor(Type.EmptyTypes);
  85. static ConstructorInfo List_ArrayBoolConstructor = Types.List.GetConstructor(new Type[] { Types.ObjectArray, Types.Bool });
  86. static ConstructorInfo Hash_Constructor = Types.Hash.GetConstructor(Type.EmptyTypes);
  87. static ConstructorInfo Regex_Constructor = typeof(Regex).GetConstructor(new Type[] { Types.String });
  88. static ConstructorInfo Regex_Constructor_Options = typeof(Regex).GetConstructor(new Type[] { Types.String, typeof(RegexOptions) });
  89. static MethodInfo Hash_Add = Types.Hash.GetMethod("Add", new Type[] { typeof(object), typeof(object) });
  90. private static ConstructorInfo TimeSpan_LongConstructor = Methods.ConstructorOf(() => new TimeSpan(default(long)));
  91. private static MethodInfo Type_GetTypeFromHandle = Methods.Of<RuntimeTypeHandle, Type>(Type.GetTypeFromHandle);
  92. static MethodInfo String_IsNullOrEmpty = Methods.Of<string, bool>(string.IsNullOrEmpty);
  93. static MethodInfo RuntimeHelpers_InitializeArray = Methods.Of<Array, RuntimeFieldHandle>(System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray);
  94. AssemblyBuilder _asmBuilder;
  95. ModuleBuilder _moduleBuilder;
  96. Hashtable _symbolDocWriters = new Hashtable();
  97. // IL generation state
  98. ILGenerator _il;
  99. Method _method; //current method
  100. int _returnStatements;//number of return statements in current method
  101. bool _hasLeaveWithStoredValue;//has a explicit return inside a try block (a `leave')
  102. bool _returnImplicit; //method ends with an implicit return
  103. Label _returnLabel; //label for `ret'
  104. Label _implicitLabel; //label for implicit return (with default value)
  105. Label _leaveLabel; //label to load the stored return value (because of a `leave')
  106. IType _returnType;
  107. int _tryBlock; // are we in a try block?
  108. bool _checked = true;
  109. bool _rawArrayIndexing = false;
  110. bool _perModuleRawArrayIndexing = false;
  111. Dictionary<IType, Type> _typeCache = new Dictionary<IType, Type>();
  112. // keeps track of types on the IL stack
  113. readonly Stack<IType> _types = new Stack<IType>();
  114. readonly Stack<LoopInfo> _loopInfoStack = new Stack<LoopInfo>();
  115. readonly AttributeCollection _assemblyAttributes = new AttributeCollection();
  116. LoopInfo _currentLoopInfo;
  117. void EnterLoop(Label breakLabel, Label continueLabel)
  118. {
  119. _loopInfoStack.Push(_currentLoopInfo);
  120. _currentLoopInfo = new LoopInfo(breakLabel, continueLabel, _tryBlock);
  121. }
  122. bool InTryInLoop()
  123. {
  124. return _tryBlock > _currentLoopInfo.TryBlockDepth;
  125. }
  126. void LeaveLoop()
  127. {
  128. _currentLoopInfo = _loopInfoStack.Pop();
  129. }
  130. void PushType(IType type)
  131. {
  132. _types.Push(type);
  133. }
  134. void PushBool()
  135. {
  136. PushType(TypeSystemServices.BoolType);
  137. }
  138. void PushVoid()
  139. {
  140. PushType(TypeSystemServices.VoidType);
  141. }
  142. IType PopType()
  143. {
  144. return _types.Pop();
  145. }
  146. IType PeekTypeOnStack()
  147. {
  148. return (_types.Count != 0) ? _types.Peek() : null;
  149. }
  150. override public void Run()
  151. {
  152. if (Errors.Count > 0)
  153. return;
  154. GatherAssemblyAttributes();
  155. SetUpAssembly();
  156. DefineTypes();
  157. DefineResources();
  158. DefineAssemblyAttributes();
  159. DefineEntryPoint();
  160. // Define the unmanaged version information resource, which
  161. // contains the attribute informaion applied earlier
  162. _asmBuilder.DefineVersionInfoResource();
  163. _moduleBuilder.CreateGlobalFunctions(); //setup global .data
  164. }
  165. void GatherAssemblyAttributes()
  166. {
  167. foreach (var module in CompileUnit.Modules)
  168. foreach (var attribute in module.AssemblyAttributes)
  169. _assemblyAttributes.Add(attribute);
  170. }
  171. void DefineTypes()
  172. {
  173. if (CompileUnit.Modules.Count == 0)
  174. return;
  175. var types = CollectTypes();
  176. foreach (var type in types)
  177. DefineType(type);
  178. foreach (var type in types)
  179. {
  180. DefineGenericParameters(type);
  181. DefineTypeMembers(type);
  182. }
  183. foreach (var module in CompileUnit.Modules)
  184. OnModule(module);
  185. EmitAttributes();
  186. CreateTypes(types);
  187. }
  188. sealed class AttributeEmitVisitor : FastDepthFirstVisitor
  189. {
  190. EmitAssembly _emitter;
  191. public AttributeEmitVisitor(EmitAssembly emitter)
  192. {
  193. _emitter = emitter;
  194. }
  195. public override void OnField(Field node)
  196. {
  197. _emitter.EmitFieldAttributes(node);
  198. }
  199. public override void OnEnumMember(EnumMember node)
  200. {
  201. _emitter.EmitFieldAttributes(node);
  202. }
  203. public override void OnEvent(Event node)
  204. {
  205. _emitter.EmitEventAttributes(node);
  206. }
  207. public override void OnProperty(Property node)
  208. {
  209. Visit(node.Getter);
  210. Visit(node.Setter);
  211. _emitter.EmitPropertyAttributes(node);
  212. }
  213. public override void OnConstructor(Constructor node)
  214. {
  215. Visit(node.Parameters);
  216. _emitter.EmitConstructorAttributes(node);
  217. }
  218. public override void OnMethod(Method node)
  219. {
  220. Visit(node.Parameters);
  221. _emitter.EmitMethodAttributes(node);
  222. }
  223. public override void OnParameterDeclaration(ParameterDeclaration node)
  224. {
  225. _emitter.EmitParameterAttributes(node);
  226. }
  227. public override void OnClassDefinition(ClassDefinition node)
  228. {
  229. base.OnClassDefinition(node);
  230. _emitter.EmitTypeAttributes(node);
  231. }
  232. public override void OnInterfaceDefinition(InterfaceDefinition node)
  233. {
  234. base.OnInterfaceDefinition(node);
  235. _emitter.EmitTypeAttributes(node);
  236. }
  237. public override void OnEnumDefinition(EnumDefinition node)
  238. {
  239. base.OnEnumDefinition(node);
  240. _emitter.EmitTypeAttributes(node);
  241. }
  242. }
  243. delegate void CustomAttributeSetter(CustomAttributeBuilder attribute);
  244. void EmitAttributes(INodeWithAttributes node, CustomAttributeSetter setCustomAttribute)
  245. {
  246. foreach (Attribute attribute in node.Attributes)
  247. setCustomAttribute(GetCustomAttributeBuilder(attribute));
  248. }
  249. void EmitPropertyAttributes(Property node)
  250. {
  251. PropertyBuilder builder = GetPropertyBuilder(node);
  252. EmitAttributes(node, builder.SetCustomAttribute);
  253. }
  254. void EmitParameterAttributes(ParameterDeclaration node)
  255. {
  256. ParameterBuilder builder = (ParameterBuilder)GetBuilder(node);
  257. EmitAttributes(node, builder.SetCustomAttribute);
  258. }
  259. void EmitEventAttributes(Event node)
  260. {
  261. EventBuilder builder = (EventBuilder)GetBuilder(node);
  262. EmitAttributes(node, builder.SetCustomAttribute);
  263. }
  264. void EmitConstructorAttributes(Constructor node)
  265. {
  266. ConstructorBuilder builder = (ConstructorBuilder)GetBuilder(node);
  267. EmitAttributes(node, builder.SetCustomAttribute);
  268. }
  269. void EmitMethodAttributes(Method node)
  270. {
  271. MethodBuilder builder = GetMethodBuilder(node);
  272. EmitAttributes(node, builder.SetCustomAttribute);
  273. }
  274. void EmitTypeAttributes(TypeDefinition node)
  275. {
  276. TypeBuilder builder = GetTypeBuilder(node);
  277. EmitAttributes(node, builder.SetCustomAttribute);
  278. }
  279. void EmitFieldAttributes(TypeMember node)
  280. {
  281. FieldBuilder builder = GetFieldBuilder(node);
  282. EmitAttributes(node, builder.SetCustomAttribute);
  283. }
  284. void EmitAttributes()
  285. {
  286. AttributeEmitVisitor visitor = new AttributeEmitVisitor(this);
  287. foreach (Module module in CompileUnit.Modules)
  288. module.Accept(visitor);
  289. }
  290. void CreateTypes(List<TypeDefinition> types)
  291. {
  292. new TypeCreator(this, types).Run();
  293. }
  294. /// <summary>
  295. /// Ensures that all types are created in the correct order.
  296. /// </summary>
  297. sealed class TypeCreator
  298. {
  299. EmitAssembly _emitter;
  300. Set<TypeDefinition> _created;
  301. List<TypeDefinition> _types;
  302. TypeDefinition _current;
  303. public TypeCreator(EmitAssembly emitter, List<TypeDefinition> types)
  304. {
  305. _emitter = emitter;
  306. _types = types;
  307. _created = new Set<TypeDefinition>();
  308. }
  309. public void Run()
  310. {
  311. AppDomain domain = Thread.GetDomain();
  312. try
  313. {
  314. domain.TypeResolve += OnTypeResolve;
  315. CreateTypes();
  316. }
  317. finally
  318. {
  319. domain.TypeResolve -= OnTypeResolve;
  320. }
  321. }
  322. private Assembly OnTypeResolve(object sender, ResolveEventArgs args)
  323. {
  324. Trace("OnTypeResolve('{0}') during '{1}' creation.", args.Name, _current);
  325. EnsureInternalFieldDependencies(_current);
  326. return _emitter._asmBuilder;
  327. }
  328. private void CreateTypes()
  329. {
  330. foreach (var type in _types)
  331. CreateType(type);
  332. }
  333. void CreateType(TypeDefinition type)
  334. {
  335. if (_created.Contains(type))
  336. return;
  337. _created.Add(type);
  338. var saved = _current;
  339. _current = type;
  340. try
  341. {
  342. HandleTypeCreation(type);
  343. }
  344. catch (Exception e)
  345. {
  346. throw CompilerErrorFactory.InternalError(type, string.Format("Failed to create '{0}' type.", type), e);
  347. }
  348. _current = saved;
  349. }
  350. private void HandleTypeCreation(TypeDefinition type)
  351. {
  352. Trace("creating type '{0}'", type);
  353. if (IsNestedType(type))
  354. CreateOuterTypeOf(type);
  355. CreateRelatedTypes(type);
  356. var typeBuilder = (TypeBuilder)_emitter.GetBuilder(type);
  357. typeBuilder.CreateType();
  358. Trace("type '{0}' successfully created", type);
  359. }
  360. private void CreateOuterTypeOf(TypeMember type)
  361. {
  362. CreateType(type.DeclaringType);
  363. }
  364. private void CreateRelatedTypes(TypeDefinition typedef)
  365. {
  366. CreateRelatedTypes(typedef.BaseTypes);
  367. foreach (var gpd in typedef.GenericParameters)
  368. CreateRelatedTypes(gpd.BaseTypes);
  369. }
  370. private void EnsureInternalFieldDependencies(TypeDefinition typedef)
  371. {
  372. foreach (var field in typedef.Members.OfType<Field>())
  373. EnsureInternalDependencies((IType)field.Type.Entity);
  374. }
  375. private void CreateRelatedTypes(IEnumerable<TypeReference> typerefs)
  376. {
  377. foreach (var typeref in typerefs)
  378. {
  379. var type = _emitter.GetType(typeref);
  380. EnsureInternalDependencies(type);
  381. }
  382. }
  383. private void EnsureInternalDependencies(IType type)
  384. {
  385. var internalType = type as AbstractInternalType;
  386. if (null != internalType)
  387. {
  388. CreateType(internalType.TypeDefinition);
  389. return;
  390. }
  391. if (type.ConstructedInfo != null)
  392. {
  393. EnsureInternalDependencies(type.ConstructedInfo.GenericDefinition);
  394. foreach (var typeArg in type.ConstructedInfo.GenericArguments)
  395. EnsureInternalDependencies(typeArg);
  396. }
  397. }
  398. static bool IsNestedType(TypeMember type)
  399. {
  400. switch (type.ParentNode.NodeType)
  401. {
  402. case NodeType.ClassDefinition:
  403. case NodeType.InterfaceDefinition:
  404. return true;
  405. }
  406. return false;
  407. }
  408. void Trace(string format, params object[] args)
  409. {
  410. _emitter.Context.TraceVerbose(format, args);
  411. }
  412. }
  413. List<TypeDefinition> CollectTypes()
  414. {
  415. var types = new List<TypeDefinition>();
  416. foreach (Module module in CompileUnit.Modules)
  417. CollectTypes(types, module.Members);
  418. return types;
  419. }
  420. void CollectTypes(List<TypeDefinition> types, TypeMemberCollection members)
  421. {
  422. foreach (var member in members)
  423. {
  424. switch (member.NodeType)
  425. {
  426. case NodeType.InterfaceDefinition:
  427. case NodeType.ClassDefinition:
  428. {
  429. var typeDefinition = ((TypeDefinition)member);
  430. types.Add(typeDefinition);
  431. CollectTypes(types, typeDefinition.Members);
  432. break;
  433. }
  434. case NodeType.EnumDefinition:
  435. {
  436. types.Add((TypeDefinition) member);
  437. break;
  438. }
  439. }
  440. }
  441. }
  442. override public void Dispose()
  443. {
  444. base.Dispose();
  445. _asmBuilder = null;
  446. _moduleBuilder = null;
  447. _symbolDocWriters.Clear();
  448. _il = null;
  449. _returnStatements = 0;
  450. _hasLeaveWithStoredValue = false;
  451. _returnImplicit = false;
  452. _returnType = null;
  453. _tryBlock = 0;
  454. _checked = true;
  455. _rawArrayIndexing = false;
  456. _types.Clear();
  457. _typeCache.Clear();
  458. _builders.Clear();
  459. _assemblyAttributes.Clear();
  460. _defaultValueHolders.Clear();
  461. _packedArrays.Clear();
  462. }
  463. override public void OnAttribute(Attribute node)
  464. {
  465. }
  466. override public void OnModule(Module module)
  467. {
  468. _perModuleRawArrayIndexing = AstAnnotations.IsRawIndexing(module);
  469. _checked = AstAnnotations.IsChecked(module, Parameters.Checked);
  470. Visit(module.Members);
  471. }
  472. override public void OnEnumDefinition(EnumDefinition node)
  473. {
  474. var typeBuilder = GetTypeBuilder(node);
  475. foreach (EnumMember member in node.Members)
  476. {
  477. var field = typeBuilder.DefineField(member.Name, typeBuilder,
  478. FieldAttributes.Public |
  479. FieldAttributes.Static |
  480. FieldAttributes.Literal);
  481. field.SetConstant(InitializerValueOf(member, node));
  482. SetBuilder(member, field);
  483. }
  484. }
  485. private object InitializerValueOf(EnumMember enumMember, EnumDefinition enumType)
  486. {
  487. return Convert.ChangeType(((IntegerLiteralExpression) enumMember.Initializer).Value,
  488. GetEnumUnderlyingType(enumType));
  489. }
  490. override public void OnArrayTypeReference(ArrayTypeReference node)
  491. {
  492. }
  493. override public void OnClassDefinition(ClassDefinition node)
  494. {
  495. EmitTypeDefinition(node);
  496. }
  497. override public void OnField(Field node)
  498. {
  499. FieldBuilder builder = GetFieldBuilder(node);
  500. if (builder.IsLiteral)
  501. {
  502. builder.SetConstant(GetInternalFieldStaticValue((InternalField)node.Entity));
  503. }
  504. }
  505. override public void OnInterfaceDefinition(InterfaceDefinition node)
  506. {
  507. TypeBuilder builder = GetTypeBuilder(node);
  508. foreach (TypeReference baseType in node.BaseTypes)
  509. {
  510. builder.AddInterfaceImplementation(GetSystemType(baseType));
  511. }
  512. }
  513. override public void OnMacroStatement(MacroStatement node)
  514. {
  515. NotImplemented(node, "Unexpected macro: " + node.ToCodeString());
  516. }
  517. override public void OnCallableDefinition(CallableDefinition node)
  518. {
  519. NotImplemented(node, "Unexpected callable definition!");
  520. }
  521. void EmitTypeDefinition(TypeDefinition node)
  522. {
  523. TypeBuilder current = GetTypeBuilder(node);
  524. EmitBaseTypesAndAttributes(node, current);
  525. Visit(node.Members);
  526. }
  527. override public void OnMethod(Method method)
  528. {
  529. if (method.IsRuntime) return;
  530. if (IsPInvoke(method)) return;
  531. MethodBuilder methodBuilder = GetMethodBuilder(method);
  532. DefineExplicitImplementationInfo(method);
  533. EmitMethod(method, methodBuilder.GetILGenerator());
  534. }
  535. private void DefineExplicitImplementationInfo(Method method)
  536. {
  537. if (null == method.ExplicitInfo)
  538. return;
  539. IMethod ifaceMethod = (IMethod)method.ExplicitInfo.Entity;
  540. MethodInfo ifaceInfo = GetMethodInfo(ifaceMethod);
  541. MethodInfo implInfo = GetMethodInfo((IMethod)method.Entity);
  542. TypeBuilder typeBuilder = GetTypeBuilder(method.DeclaringType);
  543. typeBuilder.DefineMethodOverride(implInfo, ifaceInfo);
  544. }
  545. void EmitMethod(Method method, ILGenerator generator)
  546. {
  547. _il = generator;
  548. _method = method;
  549. DefineLabels(method);
  550. Visit(method.Locals);
  551. BeginMethodBody(GetEntity(method).ReturnType);
  552. Visit(method.Body);
  553. EndMethodBody(method);
  554. }
  555. void BeginMethodBody(IType returnType)
  556. {
  557. _defaultValueHolders.Clear();
  558. _returnType = returnType;
  559. _returnStatements = 0;
  560. _returnImplicit = IsVoid(returnType);
  561. _hasLeaveWithStoredValue = false;
  562. //we may not actually use (any/all of) them, but at least they're ready
  563. _returnLabel = _il.DefineLabel();
  564. _leaveLabel = _il.DefineLabel();
  565. _implicitLabel = _il.DefineLabel();
  566. }
  567. void EndMethodBody(Method method)
  568. {
  569. if (!_returnImplicit)
  570. _returnImplicit = !AstUtil.AllCodePathsReturnOrRaise(method.Body);
  571. //At most a method epilogue contains 3 independent load instructions:
  572. //1) load of the value of an actual return (emitted elsewhere and branched to _returnLabel)
  573. //2) load of a default value (implicit returns [e.g return without expression])
  574. //3) load of the `leave' stored value
  575. bool hasDefaultValueReturn = _returnImplicit && !IsVoid(_returnType);
  576. if (hasDefaultValueReturn)
  577. {
  578. if (_returnStatements == -1) //emit branch only if instructed to do so (-1)
  579. _il.Emit(OpCodes.Br_S, _returnLabel);
  580. //load default return value for implicit return
  581. _il.MarkLabel(_implicitLabel);
  582. EmitDefaultValue(_returnType);
  583. PopType();
  584. }
  585. if (_hasLeaveWithStoredValue)
  586. {
  587. if (hasDefaultValueReturn || _returnStatements == -1)
  588. _il.Emit(OpCodes.Br_S, _returnLabel);
  589. //load the stored return value and `ret'
  590. _il.MarkLabel(_leaveLabel);
  591. _il.Emit(OpCodes.Ldloc, GetDefaultValueHolder(_returnType));
  592. }
  593. if (_returnImplicit || _returnStatements != 0)
  594. {
  595. _il.MarkLabel(_returnLabel);
  596. _il.Emit(OpCodes.Ret);
  597. }
  598. }
  599. private bool IsPInvoke(Method method)
  600. {
  601. return GetEntity(method).IsPInvoke;
  602. }
  603. override public void OnBlock(Block block)
  604. {
  605. var currentChecked = _checked;
  606. _checked = AstAnnotations.IsChecked(block, currentChecked);
  607. var currentArrayIndexing = _rawArrayIndexing;
  608. _rawArrayIndexing = _perModuleRawArrayIndexing || AstAnnotations.IsRawIndexing(block);
  609. Visit(block.Statements);
  610. _rawArrayIndexing = currentArrayIndexing;
  611. _checked = currentChecked;
  612. }
  613. void DefineLabels(Method method)
  614. {
  615. foreach (var label in LabelsOn(method))
  616. label.Label = _il.DefineLabel();
  617. }
  618. private InternalLabel[] LabelsOn(Method method)
  619. {
  620. return ((InternalMethod) method.Entity).Labels;
  621. }
  622. override public void OnConstructor(Constructor constructor)
  623. {
  624. if (constructor.IsRuntime) return;
  625. ConstructorBuilder builder = GetConstructorBuilder(constructor);
  626. EmitMethod(constructor, builder.GetILGenerator());
  627. }
  628. override public void OnLocal(Local local)
  629. {
  630. InternalLocal info = GetInternalLocal(local);
  631. info.LocalBuilder = _il.DeclareLocal(GetSystemType(local), info.Type.IsPointer);
  632. if (Parameters.Debug)
  633. {
  634. info.LocalBuilder.SetLocalSymInfo(local.Name);
  635. }
  636. }
  637. override public void OnForStatement(ForStatement node)
  638. {
  639. NotImplemented("ForStatement");
  640. }
  641. override public void OnReturnStatement(ReturnStatement node)
  642. {
  643. EmitDebugInfo(node);
  644. var retOpCode = _tryBlock > 0 ? OpCodes.Leave : OpCodes.Br;
  645. var label = _returnLabel;
  646. var expression = node.Expression;
  647. if (expression != null)
  648. {
  649. ++_returnStatements;
  650. LoadExpressionWithType(_returnType, expression);
  651. if (retOpCode == OpCodes.Leave)
  652. {
  653. //`leave' clears the stack, so we have to store return value temporarily
  654. //we can use a default value holder for that since it won't be read afterwards
  655. //of course this is necessary only if return type is not void
  656. LocalBuilder temp = GetDefaultValueHolder(_returnType);
  657. _il.Emit(OpCodes.Stloc, temp);
  658. label = _leaveLabel;
  659. _hasLeaveWithStoredValue = true;
  660. }
  661. }
  662. else if (_returnType != TypeSystemServices.VoidType)
  663. {
  664. _returnImplicit = true;
  665. label = _implicitLabel;
  666. }
  667. if (_method.Body.LastStatement != node)
  668. _il.Emit(retOpCode, label);
  669. else if (null != expression)
  670. _returnStatements = -1; //instruct epilogue to branch last ret only if necessary
  671. }
  672. private void LoadExpressionWithType(IType expectedType, Expression expression)
  673. {
  674. Visit(expression);
  675. EmitCastIfNeeded(expectedType, PopType());
  676. }
  677. override public void OnRaiseStatement(RaiseStatement node)
  678. {
  679. EmitDebugInfo(node);
  680. if (node.Exception == null)
  681. {
  682. _il.Emit(OpCodes.Rethrow);
  683. }
  684. else
  685. {
  686. Visit(node.Exception); PopType();
  687. _il.Emit(OpCodes.Throw);
  688. }
  689. }
  690. override public void OnTryStatement(TryStatement node)
  691. {
  692. ++_tryBlock;
  693. Label end = _il.BeginExceptionBlock();
  694. // The fault handler isn't very well supported by the
  695. // the ILGenerator. Thus, when there is a failure block
  696. // in the same try as an except or ensure block, we
  697. // need to do some special brute forcing with the exception
  698. // block context in the ILGenerator.
  699. if(null != node.FailureBlock && null != node.EnsureBlock)
  700. {
  701. ++_tryBlock;
  702. _il.BeginExceptionBlock();
  703. }
  704. if(null != node.FailureBlock && node.ExceptionHandlers.Count > 0)
  705. {
  706. ++_tryBlock;
  707. _il.BeginExceptionBlock();
  708. }
  709. Visit(node.ProtectedBlock);
  710. Visit(node.ExceptionHandlers);
  711. if(null != node.FailureBlock)
  712. {
  713. // Logic to back out of the manually forced blocks
  714. if(node.ExceptionHandlers.Count > 0)
  715. {
  716. _il.EndExceptionBlock();
  717. --_tryBlock;
  718. }
  719. _il.BeginFaultBlock();
  720. Visit(node.FailureBlock);
  721. // Logic to back out of the manually forced blocks once more
  722. if(null != node.EnsureBlock)
  723. {
  724. _il.EndExceptionBlock();
  725. --_tryBlock;
  726. }
  727. }
  728. if (null != node.EnsureBlock)
  729. {
  730. _il.BeginFinallyBlock();
  731. Visit(node.EnsureBlock);
  732. }
  733. _il.EndExceptionBlock();
  734. --_tryBlock;
  735. }
  736. override public void OnExceptionHandler(ExceptionHandler node)
  737. {
  738. if((node.Flags & ExceptionHandlerFlags.Filter) == ExceptionHandlerFlags.Filter)
  739. {
  740. _il.BeginExceptFilterBlock();
  741. Label endLabel = _il.DefineLabel();
  742. // If the filter is not untyped, then test the exception type
  743. // before testing the filter condition
  744. if((node.Flags & ExceptionHandlerFlags.Untyped) == ExceptionHandlerFlags.None)
  745. {
  746. Label filterCondition = _il.DefineLabel();
  747. // Test the type of the exception.
  748. _il.Emit(OpCodes.Isinst, GetSystemType(node.Declaration.Type));
  749. // Duplicate it. If it is null, then it will be used to
  750. // skip the filter.
  751. Dup();
  752. // If the exception is of the right type, branch
  753. // to test the filter condition.
  754. _il.Emit(OpCodes.Brtrue_S, filterCondition);
  755. // Otherwise, clean up the stack and prepare the stack
  756. // to skip the filter.
  757. EmitStoreOrPopException(node);
  758. _il.Emit(OpCodes.Ldc_I4_0);
  759. _il.Emit(OpCodes.Br, endLabel);
  760. _il.MarkLabel(filterCondition);
  761. }
  762. else if((node.Flags & ExceptionHandlerFlags.Anonymous) == ExceptionHandlerFlags.None)
  763. {
  764. // Cast the exception to the default except type
  765. _il.Emit(OpCodes.Isinst, GetSystemType(node.Declaration.Type));
  766. }
  767. EmitStoreOrPopException(node);
  768. // Test the condition and convert to boolean if needed.
  769. node.FilterCondition.Accept(this);
  770. PopType();
  771. EmitToBoolIfNeeded(node.FilterCondition);
  772. // If the type is right and the condition is true,
  773. // proceed with the handler.
  774. _il.MarkLabel(endLabel);
  775. _il.Emit(OpCodes.Ldc_I4_0);
  776. _il.Emit(OpCodes.Cgt_Un);
  777. _il.BeginCatchBlock(null);
  778. }
  779. else
  780. {
  781. // Begin a normal catch block of the appropriate type.
  782. _il.BeginCatchBlock(GetSystemType(node.Declaration.Type));
  783. // Clean up the stack or store the exception if not anonymous.
  784. EmitStoreOrPopException(node);
  785. }
  786. Visit(node.Block);
  787. }
  788. private void EmitStoreOrPopException(ExceptionHandler node)
  789. {
  790. if((node.Flags & ExceptionHandlerFlags.Anonymous) == ExceptionHandlerFlags.None)
  791. {
  792. _il.Emit(OpCodes.Stloc, GetLocalBuilder(node.Declaration));
  793. }
  794. else
  795. {
  796. _il.Emit(OpCodes.Pop);
  797. }
  798. }
  799. override public void OnUnpackStatement(UnpackStatement node)
  800. {
  801. NotImplemented("Unpacking");
  802. }
  803. override public void OnExpressionStatement(ExpressionStatement node)
  804. {
  805. EmitDebugInfo(node);
  806. base.OnExpressionStatement(node);
  807. // if the type of the inner expression is not
  808. // void we need to pop its return value to leave
  809. // the stack sane
  810. DiscardValueOnStack();
  811. }
  812. void DiscardValueOnStack()
  813. {
  814. if (!IsVoid(PopType()))
  815. _il.Emit(OpCodes.Pop);
  816. }
  817. bool IsVoid(IType type)
  818. {
  819. return type == TypeSystemServices.VoidType;
  820. }
  821. override public void OnUnlessStatement(UnlessStatement node)
  822. {
  823. Label endLabel = _il.DefineLabel();
  824. EmitDebugInfo(node);
  825. EmitBranchTrue(node.Condition, endLabel);
  826. node.Block.Accept(this);
  827. _il.MarkLabel(endLabel);
  828. }
  829. void OnSwitch(MethodInvocationExpression node)
  830. {
  831. var args = node.Arguments;
  832. LoadExpressionWithType(TypeSystemServices.IntType, args[0]);
  833. _il.Emit(OpCodes.Switch, args.Skip(1).Select(e => LabelFor(e)).ToArray());
  834. PushVoid();
  835. }
  836. private static Label LabelFor(Expression expression)
  837. {
  838. return ((InternalLabel) expression.Entity).Label;
  839. }
  840. override public void OnGotoStatement(GotoStatement node)
  841. {
  842. EmitDebugInfo(node);
  843. InternalLabel label = (InternalLabel)GetEntity(node.Label);
  844. int gotoDepth = AstAnnotations.GetTryBlockDepth(node);
  845. int targetDepth = AstAnnotations.GetTryBlockDepth(label.LabelStatement);
  846. if (targetDepth == gotoDepth)
  847. {
  848. _il.Emit(OpCodes.Br, label.Label);
  849. }
  850. else
  851. {
  852. _il.Emit(OpCodes.Leave, label.Label);
  853. }
  854. }
  855. override public void OnLabelStatement(LabelStatement node)
  856. {
  857. EmitDebugInfo(node);
  858. _il.MarkLabel(((InternalLabel)node.Entity).Label);
  859. }
  860. override public void OnConditionalExpression(ConditionalExpression node)
  861. {
  862. var type = GetExpressionType(node);
  863. var endLabel = _il.DefineLabel();
  864. EmitBranchFalse(node.Condition, endLabel);
  865. LoadExpressionWithType(type, node.TrueValue);
  866. var elseEndLabel = _il.DefineLabel();
  867. _il.Emit(OpCodes.Br, elseEndLabel);
  868. _il.MarkLabel(endLabel);
  869. endLabel = elseEndLabel;
  870. LoadExpressionWithType(type, node.FalseValue);
  871. _il.MarkLabel(endLabel);
  872. PushType(type);
  873. }
  874. override public void OnIfStatement(IfStatement node)
  875. {
  876. Label endLabel = _il.DefineLabel();
  877. EmitDebugInfo(node);
  878. EmitBranchFalse(node.Condition, endLabel);
  879. node.TrueBlock.Accept(this);
  880. if (null != node.FalseBlock)
  881. {
  882. Label elseEndLabel = _il.DefineLabel();
  883. if (!node.TrueBlock.EndsWith<ReturnStatement>() && !node.TrueBlock.EndsWith<RaiseStatement>())
  884. _il.Emit(OpCodes.Br, elseEndLabel);
  885. _il.MarkLabel(endLabel);
  886. endLabel = elseEndLabel;
  887. node.FalseBlock.Accept(this);
  888. }
  889. _il.MarkLabel(endLabel);
  890. }
  891. void EmitBranchTrue(Expression expression, Label label)
  892. {
  893. EmitBranch(true, expression, label);
  894. }
  895. void EmitBranchFalse(Expression expression, Label label)
  896. {
  897. EmitBranch(false, expression, label);
  898. }
  899. void EmitBranch(bool branchOnTrue, BinaryExpression expression, Label label)
  900. {
  901. switch (expression.Operator)
  902. {
  903. case BinaryOperatorType.TypeTest:
  904. EmitTypeTest(expression);
  905. _il.Emit(branchOnTrue ? OpCodes.Brtrue : OpCodes.Brfalse, label);
  906. break;
  907. case BinaryOperatorType.Or:
  908. if (branchOnTrue)
  909. {
  910. EmitBranch(true, expression.Left, label);
  911. EmitBranch(true, expression.Right, label);
  912. }
  913. else
  914. {
  915. Label skipRhs = _il.DefineLabel();
  916. EmitBranch(true, expression.Left, skipRhs);
  917. EmitBranch(false, expression.Right, label);
  918. _il.MarkLabel(skipRhs);
  919. }
  920. break;
  921. case BinaryOperatorType.And:
  922. if (branchOnTrue)
  923. {
  924. Label skipRhs = _il.DefineLabel();
  925. EmitBranch(false, expression.Left, skipRhs);
  926. EmitBranch(true, expression.Right, label);
  927. _il.MarkLabel(skipRhs);
  928. }
  929. else
  930. {
  931. EmitBranch(false, expression.Left, label);
  932. EmitBranch(false, expression.Right, label);
  933. }
  934. break;
  935. case BinaryOperatorType.Equality:
  936. if (IsZeroEquivalent(expression.Left))
  937. EmitBranch(!branchOnTrue, expression.Right, label);
  938. else if (IsZeroEquivalent(expression.Right))
  939. EmitBranch(!branchOnTrue, expression.Left, label);
  940. else
  941. {
  942. LoadCmpOperands(expression);
  943. _il.Emit(branchOnTrue ? OpCodes.Beq : OpCodes.Bne_Un, label);
  944. }
  945. break;
  946. case BinaryOperatorType.Inequality:
  947. if (IsZeroEquivalent(expression.Left))
  948. {
  949. EmitBranch(branchOnTrue, expression.Right, label);
  950. }
  951. else if (IsZeroEquivalent(expression.Right))
  952. {
  953. EmitBranch(branchOnTrue, expression.Left, label);
  954. }
  955. else
  956. {
  957. LoadCmpOperands(expression);
  958. _il.Emit(branchOnTrue ? OpCodes.Bne_Un : OpCodes.Beq, label);
  959. }
  960. break;
  961. case BinaryOperatorType.ReferenceEquality:
  962. if (IsNull(expression.Left))
  963. {
  964. EmitRawBranch(!branchOnTrue, expression.Right, label);
  965. break;
  966. }
  967. if (IsNull(expression.Right))
  968. {
  969. EmitRawBranch(!branchOnTrue, expression.Left, label);
  970. break;
  971. }
  972. Visit(expression.Left); PopType();
  973. Visit(expression.Right); PopType();
  974. _il.Emit(branchOnTrue ? OpCodes.Beq : OpCodes.Bne_Un, label);
  975. break;
  976. case BinaryOperatorType.ReferenceInequality:
  977. if (IsNull(expression.Left))
  978. {
  979. EmitRawBranch(branchOnTrue, expression.Right, label);
  980. break;
  981. }
  982. if (IsNull(expression.Right))
  983. {
  984. EmitRawBranch(branchOnTrue, expression.Left, label);
  985. break;
  986. }
  987. Visit(expression.Left); PopType();
  988. Visit(expression.Right); PopType();
  989. _il.Emit(branchOnTrue ? OpCodes.Bne_Un : OpCodes.Beq, label);
  990. break;
  991. case BinaryOperatorType.GreaterThan:
  992. LoadCmpOperands(expression);
  993. _il.Emit(branchOnTrue ? OpCodes.Bgt : OpCodes.Ble, label);
  994. break;
  995. case BinaryOperatorType.GreaterThanOrEqual:
  996. LoadCmpOperands(expression);
  997. _il.Emit(branchOnTrue ? OpCodes.Bge : OpCodes.Blt, label);
  998. break;
  999. case BinaryOperatorType.LessThan:
  1000. LoadCmpOperands(expression);
  1001. _il.Emit(branchOnTrue ? OpCodes.Blt : OpCodes.Bge, label);
  1002. break;
  1003. case BinaryOperatorType.LessThanOrEqual:
  1004. LoadCmpOperands(expression);
  1005. _il.Emit(branchOnTrue ? OpCodes.Ble : OpCodes.Bgt, label);
  1006. break;
  1007. default:
  1008. EmitDefaultBranch(branchOnTrue, expression, label);
  1009. break;
  1010. }
  1011. }
  1012. void EmitBranch(bool branchOnTrue, UnaryExpression expression, Label label)
  1013. {
  1014. if (UnaryOperatorType.LogicalNot == expression.Operator)
  1015. {
  1016. EmitBranch(!branchOnTrue, expression.Operand, label);
  1017. }
  1018. else
  1019. {
  1020. EmitDefaultBranch(branchOnTrue, expression, label);
  1021. }
  1022. }
  1023. void EmitBranch(bool branchOnTrue, Expression expression, Label label)
  1024. {
  1025. switch (expression.NodeType)
  1026. {
  1027. case NodeType.BinaryExpression:
  1028. {
  1029. EmitBranch(branchOnTrue, (BinaryExpression)expression, label);
  1030. break;
  1031. }
  1032. case NodeType.UnaryExpression:
  1033. {
  1034. EmitBranch(branchOnTrue, (UnaryExpression)expression, label);
  1035. break;
  1036. }
  1037. default:
  1038. {
  1039. EmitDefaultBranch(branchOnTrue, expression, label);
  1040. break;
  1041. }
  1042. }
  1043. }
  1044. void EmitRawBranch(bool branch, Expression condition, Label label)
  1045. {
  1046. condition.Accept(this); PopType();
  1047. _il.Emit(branch ? OpCodes.Brtrue : OpCodes.Brfalse, label);
  1048. }
  1049. void EmitDefaultBranch(bool branch, Expression condition, Label label)
  1050. {
  1051. if (branch && IsOneEquivalent(condition))
  1052. {
  1053. _il.Emit(OpCodes.Br, label);
  1054. return;
  1055. }
  1056. if (!branch && IsZeroEquivalent(condition))
  1057. {
  1058. _il.Emit(OpCodes.Br, label);
  1059. return;
  1060. }
  1061. condition.Accept(this);
  1062. var type = PopType();
  1063. if (TypeSystemServices.IsFloatingPointNumber(type))
  1064. {
  1065. EmitDefaultValue(type);
  1066. _il.Emit(branch ? OpCodes.Bne_Un : OpCodes.Beq, label);
  1067. return;
  1068. }
  1069. EmitToBoolIfNeeded(condition);
  1070. _il.Emit(branch ? OpCodes.Brtrue : OpCodes.Brfalse, label);
  1071. }
  1072. private static bool IsZeroEquivalent(Expression expression)
  1073. {
  1074. return (IsNull(expression) || IsZero(expression) || IsFalse(expression));
  1075. }
  1076. private static bool IsOneEquivalent(Expression expression)
  1077. {
  1078. return IsBooleanLiteral(expression, true) || IsNumberLiteral(expression, 1);
  1079. }
  1080. private static bool IsNull(Expression expression)
  1081. {
  1082. return NodeType.NullLiteralExpression == expression.NodeType;
  1083. }
  1084. private static bool IsFalse(Expression expression)
  1085. {
  1086. return IsBooleanLiteral(expression, false);
  1087. }
  1088. private static bool IsBooleanLiteral(Expression expression, bool value)
  1089. {
  1090. return NodeType.BoolLiteralExpression == expression.NodeType
  1091. && (value == ((BoolLiteralExpression)expression).Value);
  1092. }
  1093. private static bool IsZero(Expression expression)
  1094. {
  1095. return IsNumberLiteral(expression, 0);
  1096. }
  1097. private static bool IsNumberLiteral(Expression expression, int value)
  1098. {
  1099. return (NodeType.IntegerLiteralExpression == expression.NodeType
  1100. && (value == ((IntegerLiteralExpression)expression).Value))
  1101. ||
  1102. (NodeType.DoubleLiteralExpression == expression.NodeType
  1103. && (value == ((DoubleLiteralExpression)expression).Value));
  1104. }
  1105. override public void OnBreakStatement(BreakStatement node)
  1106. {
  1107. EmitGoTo(_currentLoopInfo.BreakLabel, node);
  1108. }
  1109. private void EmitGoTo(Label label, Node debugInfo)
  1110. {
  1111. EmitDebugInfo(debugInfo);
  1112. _il.Emit(InTryInLoop() ? OpCodes.Leave : OpCodes.Br, label);
  1113. }
  1114. override public void OnContinueStatement(ContinueStatement node)
  1115. {
  1116. EmitGoTo(_currentLoopInfo.ContinueLabel, node);
  1117. }
  1118. override public void OnWhileStatement(WhileStatement node)
  1119. {
  1120. Label endLabel = _il.DefineLabel();
  1121. Label bodyLabel = _il.DefineLabel();
  1122. Label conditionLabel = _il.DefineLabel();
  1123. _il.Emit(OpCodes.Br, conditionLabel);
  1124. _il.MarkLabel(bodyLabel);
  1125. EnterLoop(endLabel, conditionLabel);
  1126. node.Block.Accept(this);
  1127. LeaveLoop();
  1128. _il.MarkLabel(conditionLabel);
  1129. EmitDebugInfo(node);
  1130. EmitBranchTrue(node.Condition, bodyLabel);
  1131. Visit(node.OrBlock);
  1132. Visit(node.ThenBlock);
  1133. _il.MarkLabel(endLabel);
  1134. }
  1135. void EmitIntNot()
  1136. {
  1137. _il.Emit(OpCodes.Ldc_I4_0);
  1138. _il.Emit(OpCodes.Ceq);
  1139. }
  1140. void EmitGenericNot()
  1141. {
  1142. // bool codification:
  1143. // value_on_stack ? 0 : 1
  1144. Label wasTrue = _il.DefineLabel();
  1145. Label wasFalse = _il.DefineLabel();
  1146. _il.Emit(OpCodes.Brfalse_S, wasFalse);
  1147. _il.Emit(OpCodes.Ldc_I4_0);
  1148. _il.Emit(OpCodes.Br_S, wasTrue);
  1149. _il.MarkLabel(wasFalse);
  1150. _il.Emit(OpCodes.Ldc_I4_1);
  1151. _il.MarkLabel(wasTrue);
  1152. }
  1153. override public void OnUnaryExpression(UnaryExpression node)
  1154. {
  1155. switch (node.Operator)
  1156. {
  1157. case UnaryOperatorType.LogicalNot:
  1158. {
  1159. EmitLogicalNot(node);
  1160. break;
  1161. }
  1162. case UnaryOperatorType.UnaryNegation:
  1163. {
  1164. EmitUnaryNegation(node);
  1165. break;
  1166. }
  1167. case UnaryOperatorType.OnesComplement:
  1168. {
  1169. EmitOnesComplement(node);
  1170. break;
  1171. }
  1172. case UnaryOperatorType.AddressOf:
  1173. {
  1174. EmitAddressOf(node);
  1175. break;
  1176. }
  1177. case UnaryOperatorType.Indirection:
  1178. {
  1179. EmitIndirection(node);
  1180. break;
  1181. }
  1182. default:
  1183. {
  1184. NotImplemented(node, "unary operator not supported");
  1185. break;
  1186. }
  1187. }
  1188. }
  1189. IType _byAddress = null;
  1190. bool IsByAddress(IType type)
  1191. {
  1192. return (_byAddress == type);
  1193. }
  1194. void EmitDefaultValue(IType type)
  1195. {
  1196. var isGenericParameter = GenericsServices.IsGenericParameter(type);
  1197. if (!type.IsValueType && !isGenericParameter)
  1198. _il.Emit(OpCodes.Ldnull);
  1199. else if (type == TypeSystemServices.BoolType)
  1200. _il.Emit(OpCodes.Ldc_I4_0);
  1201. else if (TypeSystemServices.IsFloatingPointNumber(type))
  1202. EmitLoadLiteral(type, 0.0);
  1203. else if (TypeSystemServices.IsPrimitiveNumber(type) || type == TypeSystemServices.CharType)
  1204. EmitLoadLiteral(type, 0);
  1205. else if (isGenericParameter && TypeSystemServices.IsReferenceType(type))
  1206. {
  1207. _il.Emit(OpCodes.Ldnull);
  1208. _il.Emit(OpCodes.Unbox_Any, GetSystemType(type));
  1209. }
  1210. else //valuetype or valuetype/unconstrained generic parameter
  1211. {
  1212. //TODO: if MethodBody.InitLocals is false
  1213. //_il.Emit(OpCodes.Ldloca, GetDefaultValueHolder(type));
  1214. //_il.Emit(OpCodes.Initobj, GetSystemType(type));
  1215. _il.Emit(OpCodes.Ldloc, GetDefaultValueHolder(type));
  1216. }
  1217. PushType(type);
  1218. }
  1219. Dictionary<IType, LocalBuilder> _defaultValueHolders = new Dictionary<IType, LocalBuilder>();
  1220. //get the default value holder (a local actually) for a given type
  1221. //default value holder pool is cleared before each method body processing
  1222. LocalBuilder GetDefaultValueHolder(IType type)
  1223. {
  1224. LocalBuilder holder;
  1225. if (_defaultValueHolders.TryGetValue(type, out holder))
  1226. return holder;
  1227. holder = _il.DeclareLocal(GetSystemType(type));
  1228. _defaultValueHolders.Add(type, holder);
  1229. return holder;
  1230. }
  1231. private void EmitOnesComplement(UnaryExpression node)
  1232. {
  1233. node.Operand.Accept(this);
  1234. _il.Emit(OpCodes.Not);
  1235. }
  1236. private void EmitLogicalNot(UnaryExpression node)
  1237. {
  1238. Expression operand = node.Operand;
  1239. operand.Accept(this);
  1240. IType typeOnStack = PopType();
  1241. bool notContext = true;
  1242. if (IsBoolOrInt(typeOnStack))
  1243. {
  1244. EmitIntNot();
  1245. }
  1246. else if (EmitToBoolIfNeeded(operand, ref notContext))
  1247. {
  1248. if (!notContext) //we are in a not context and emit to bool is also in a not context
  1249. EmitIntNot();//so we do not need any not (false && false => true)
  1250. }
  1251. else
  1252. {
  1253. EmitGenericNot();
  1254. }
  1255. PushBool();
  1256. }
  1257. private void EmitUnaryNegation(UnaryExpression node)
  1258. {
  1259. var operandType = GetExpressionType(node.Operand);
  1260. if (IsCheckedIntegerOperand(operandType))
  1261. {
  1262. _il.Emit(OpCodes.Ldc_I4_0);
  1263. if (IsLong(operandType) || operandType == TypeSystemServices.ULongType)
  1264. _il.Emit(OpCodes.Conv_I8);
  1265. node.Operand.Accept(this);
  1266. _il.Emit(TypeSystemServices.IsSignedNumber(operandType)
  1267. ? OpCodes.Sub_Ovf
  1268. : OpCodes.Sub_Ovf_Un);
  1269. if (!IsLong(operandType) && operandType != TypeSystemServices.ULongType)
  1270. EmitCastIfNeeded(operandType, TypeSystemServices.IntType);
  1271. }
  1272. else
  1273. {
  1274. //a single/double unary negation never overflow
  1275. node.Operand.Accept(this);
  1276. _il.Emit(OpCodes.Neg);
  1277. }
  1278. }
  1279. private bool IsCheckedIntegerOperand(IType operandType)
  1280. {
  1281. return _checked && IsInteger(operandType);
  1282. }
  1283. void EmitAddressOf(UnaryExpression node)
  1284. {
  1285. _byAddress = GetExpressionType(node.Operand);
  1286. node.Operand.Accept(this);
  1287. PushType(PopType().MakePointerType());
  1288. _byAddress = null;
  1289. }
  1290. void EmitIndirection(UnaryExpression node)
  1291. {
  1292. node.Operand.Accept(this);
  1293. if (node.Operand.NodeType != NodeType.ReferenceExpression
  1294. && node.ParentNode.NodeType != NodeType.MemberReferenceExpression)
  1295. {
  1296. //pointer arithmetic, need to load the address
  1297. IType et = PeekTypeOnStack().ElementType;
  1298. OpCode code = GetLoadRefParamCode(et);
  1299. if (code == OpCodes.Ldobj)
  1300. _il.Emit(code, GetSystemType(et));
  1301. else
  1302. _il.Emit(code);
  1303. PopType();
  1304. PushType(et);
  1305. }
  1306. }
  1307. static bool ShouldLeaveValueOnStack(Expression node)
  1308. {
  1309. return node.ParentNode.NodeType != NodeType.ExpressionStatement;
  1310. }
  1311. void OnReferenceComparison(BinaryExpression node)
  1312. {
  1313. node.Left.Accept(this); PopType();
  1314. node.Right.Accept(this); PopType();
  1315. _il.Emit(OpCodes.Ceq);
  1316. if (BinaryOperatorType.ReferenceInequality == node.Operator)
  1317. {
  1318. EmitIntNot();
  1319. }
  1320. PushBool();
  1321. }
  1322. void OnAssignmentToSlice(BinaryExpression node)
  1323. {
  1324. var slice = (SlicingExpression)node.Left;
  1325. Visit(slice.Target);
  1326. var arrayType = (IArrayType)PopType();
  1327. if (arrayType.Rank == 1)
  1328. EmitAssignmentToSingleDimensionalArrayElement(arrayType, slice, node);
  1329. else
  1330. EmitAssignmentToMultiDimensionalArrayElement(arrayType, slice, node);
  1331. }
  1332. private void EmitAssignmentToMultiDimensionalArrayElement(IArrayType arrayType, SlicingExpression slice, BinaryExpression node)
  1333. {
  1334. var elementType = arrayType.ElementType;
  1335. LoadArrayIndices(slice);
  1336. var temp = LoadAssignmentOperand(elementType, node);
  1337. CallArrayMethod(arrayType, "Set", typeof(void), ParameterTypesForArraySet(arrayType));
  1338. FlushAssignmentOperand(elementType, temp);
  1339. }
  1340. private void EmitAssignmentToSingleDimensionalArrayElement(IArrayType arrayType, SlicingExpression slice, BinaryExpression node)
  1341. {
  1342. var elementType = arrayType.ElementType;
  1343. var index = slice.Indices[0];
  1344. EmitNormalizedArrayIndex(slice, index.Begin);
  1345. var opcode = GetStoreEntityOpCode(elementType);
  1346. bool stobj = IsStobj(opcode);
  1347. if (stobj) _il.Emit(OpCodes.Ldelema, GetSystemType(elementType));
  1348. var temp = LoadAssignmentOperand(elementType, node);
  1349. if (stobj)
  1350. _il.Emit(opcode, GetSystemType(elementType));
  1351. else
  1352. _il.Emit(opcode);
  1353. FlushAssignmentOperand(elementType, temp);
  1354. }
  1355. private void FlushAssignmentOperand(IType elementType, LocalBuilder temp)
  1356. {
  1357. if (temp != null)
  1358. LoadLocal(temp, elementType);
  1359. else
  1360. PushVoid();
  1361. }
  1362. private LocalBuilder LoadAssignmentOperand(IType elementType, BinaryExpression node)
  1363. {
  1364. LoadExpressionWithType(elementType, node.Right);
  1365. var leaveValueOnStack = ShouldLeaveValueOnStack(node);
  1366. LocalBuilder temp = null;
  1367. if (leaveValueOnStack)
  1368. {
  1369. Dup();
  1370. temp = StoreTempLocal(elementType);
  1371. }
  1372. return temp;
  1373. }
  1374. LocalBuilder _currentLocal = null;
  1375. void LoadLocal(LocalBuilder local, IType localType)
  1376. {
  1377. _il.Emit(OpCodes.Ldloc, local);
  1378. PushType(localType);
  1379. _currentLocal = local;
  1380. }
  1381. void LoadLocal(InternalLocal local)
  1382. {
  1383. LoadLocal(local, false);
  1384. }
  1385. void LoadLocal(InternalLocal local, bool byAddress)
  1386. {
  1387. _il.Emit(IsByAddress(local.Type) ? OpCodes.Ldloca : OpCodes.Ldloc, local.LocalBuilder);
  1388. PushType(local.Type);
  1389. _currentLocal = local.LocalBuilder;
  1390. }
  1391. void LoadIndirectLocal(InternalLocal local)
  1392. {
  1393. LoadLocal(local);
  1394. IType et = local.Type.ElementType;
  1395. PopType();
  1396. PushType(et);
  1397. OpCode code = GetLoadRefParamCode(et);
  1398. if (code == OpCodes.Ldobj)
  1399. _il.Emit(code, GetSystemType(et));
  1400. else
  1401. _il.Emit(code);
  1402. }
  1403. private LocalBuilder StoreTempLocal(IType elementType)
  1404. {
  1405. LocalBuilder temp;
  1406. temp = _il.DeclareLocal(GetSystemType(elementType));
  1407. _il.Emit(OpCodes.Stloc, temp);
  1408. return temp;
  1409. }
  1410. void OnAssignment(BinaryExpression node)
  1411. {
  1412. if (NodeType.SlicingExpression == node.Left.NodeType)
  1413. {
  1414. OnAssignmentToSlice(node);
  1415. return;
  1416. }
  1417. // when the parent is not a statement we need to leave
  1418. // the value on the stack
  1419. bool leaveValueOnStack = ShouldLeaveValueOnStack(node);
  1420. IEntity tag = TypeSystemServices.GetEntity(node.Left);
  1421. switch (tag.EntityType)
  1422. {
  1423. case EntityType.Local:
  1424. {
  1425. SetLocal(node, (InternalLocal)tag, leaveValueOnStack);
  1426. break;
  1427. }
  1428. case EntityType.Parameter:
  1429. {
  1430. InternalParameter param = (InternalParameter)tag;
  1431. if (param.Parameter.IsByRef)
  1432. {
  1433. SetByRefParam(param, node.Right, leaveValueOnStack);
  1434. break;
  1435. }
  1436. LoadExpressionWithType(param.Type, node.Right);
  1437. if (leaveValueOnStack)
  1438. {
  1439. Dup();
  1440. PushType(param.Type);
  1441. }
  1442. _il.Emit(OpCodes.Starg, param.Index);
  1443. break;
  1444. }
  1445. case EntityType.Field:
  1446. {
  1447. IField field = (IField)tag;
  1448. SetField(node, field, node.Left, node.Right, leaveValueOnStack);
  1449. break;
  1450. }
  1451. case EntityType.Property:
  1452. {
  1453. SetProperty((IProperty)tag, node.Left, node.Right, leaveValueOnStack);
  1454. break;
  1455. }
  1456. case EntityType.Event: //event=null (always internal in this context)
  1457. {
  1458. InternalEvent e = (InternalEvent) tag;
  1459. OpCode opcode = e.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld;
  1460. _il.Emit(OpCodes.Ldnull);
  1461. _il.Emit(opcode, GetFieldBuilder(e.BackingField.Field));
  1462. break;
  1463. }
  1464. default:
  1465. {
  1466. NotImplemented(node, tag.ToString());
  1467. break;
  1468. }
  1469. }
  1470. if (!leaveValueOnStack)
  1471. {
  1472. PushVoid();
  1473. }
  1474. }
  1475. private void SetByRefParam(InternalParameter param, Expression right, bool leaveValueOnStack)
  1476. {
  1477. LocalBuilder temp = null;
  1478. IType tempType = null;
  1479. if (leaveValueOnStack)
  1480. {
  1481. Visit(right);
  1482. tempType = PopType();
  1483. temp = StoreTempLocal(tempType);
  1484. }
  1485. LoadParam(param);
  1486. if (temp != null)
  1487. {
  1488. LoadLocal(temp, tempType);
  1489. PopType();
  1490. }
  1491. else
  1492. LoadExpressionWithType(param.Type, right);
  1493. var storecode = GetStoreRefParamCode(param.Type);
  1494. if (IsStobj(storecode)) //passing struct/decimal byref
  1495. _il.Emit(storecode, GetSystemType(param.Type));
  1496. else
  1497. _il.Emit(storecode);
  1498. if (null != temp)
  1499. LoadLocal(temp, tempType);
  1500. }
  1501. void EmitTypeTest(BinaryExpression node)
  1502. {
  1503. Visit(node.Left);
  1504. IType actualType = PopType();
  1505. EmitBoxIfNeeded(TypeSy

Large files files are truncated, but you can click here to view the full file