PageRenderTime 60ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 2ms

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

https://github.com/w4x/boolangstudio
C# | 5083 lines | 4246 code | 661 blank | 176 comment | 657 complexity | 3e45febc9971fe9c8c2caf56aeaa552b 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.Reflection;
  34. using System.Reflection.Emit;
  35. using System.Resources;
  36. using System.Text;
  37. using System.Text.RegularExpressions;
  38. using System.Threading;
  39. using Boo.Lang.Compiler.Ast;
  40. using Boo.Lang.Compiler.TypeSystem;
  41. using Boo.Lang.Runtime;
  42. using Attribute = Boo.Lang.Compiler.Ast.Attribute;
  43. using Module = Boo.Lang.Compiler.Ast.Module;
  44. namespace Boo.Lang.Compiler.Steps
  45. {
  46. class LoopInfo
  47. {
  48. public Label BreakLabel;
  49. public Label ContinueLabel;
  50. public int TryBlockDepth;
  51. public LoopInfo(Label breakLabel, Label continueLabel, int tryBlockDepth)
  52. {
  53. BreakLabel = breakLabel;
  54. ContinueLabel = continueLabel;
  55. TryBlockDepth = tryBlockDepth;
  56. }
  57. }
  58. public class EmitAssembly : AbstractVisitorCompilerStep
  59. {
  60. static ConstructorInfo DebuggableAttribute_Constructor = typeof(DebuggableAttribute).GetConstructor(new Type[] { Types.Bool, Types.Bool });
  61. static ConstructorInfo RuntimeCompatibilityAttribute_Constructor = typeof(System.Runtime.CompilerServices.RuntimeCompatibilityAttribute).GetConstructor(new Type[0]);
  62. static PropertyInfo[] RuntimeCompatibilityAttribute_Property = new PropertyInfo[] { typeof(System.Runtime.CompilerServices.RuntimeCompatibilityAttribute).GetProperty("WrapNonExceptionThrows") };
  63. static ConstructorInfo DuckTypedAttribute_Constructor = Types.DuckTypedAttribute.GetConstructor(new Type[0]);
  64. static ConstructorInfo ParamArrayAttribute_Constructor = Types.ParamArrayAttribute.GetConstructor(new Type[0]);
  65. static MethodInfo RuntimeServices_NormalizeArrayIndex = Types.RuntimeServices.GetMethod("NormalizeArrayIndex");
  66. static MethodInfo RuntimeServices_ToBool_Object = Types.RuntimeServices.GetMethod("ToBool", new Type[] { Types.Object });
  67. static MethodInfo RuntimeServices_ToBool_Decimal = Types.RuntimeServices.GetMethod("ToBool", new Type[] { Types.Decimal });
  68. static MethodInfo RuntimeServices_ToBool_Single = Types.RuntimeServices.GetMethod("ToBool", new Type[] { Types.Single });
  69. static MethodInfo RuntimeServices_ToBool_Double = Types.RuntimeServices.GetMethod("ToBool", new Type[] { Types.Double });
  70. static MethodInfo Builtins_ArrayTypedConstructor = Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.Int });
  71. static MethodInfo Builtins_ArrayTypedCollectionConstructor = Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.ICollection });
  72. static MethodInfo Math_Pow = typeof(Math).GetMethod("Pow");
  73. static ConstructorInfo List_EmptyConstructor = Types.List.GetConstructor(Type.EmptyTypes);
  74. static ConstructorInfo List_ArrayBoolConstructor = Types.List.GetConstructor(new Type[] { Types.ObjectArray, Types.Bool });
  75. static ConstructorInfo Hash_Constructor = Types.Hash.GetConstructor(new Type[0]);
  76. static ConstructorInfo Regex_Constructor = typeof(Regex).GetConstructor(new Type[] { Types.String });
  77. static MethodInfo Hash_Add = Types.Hash.GetMethod("Add", new Type[] { typeof(object), typeof(object) });
  78. static ConstructorInfo TimeSpan_LongConstructor = Types.TimeSpan.GetConstructor(new Type[] { typeof(long) });
  79. static MethodInfo Type_GetTypeFromHandle = Types.Type.GetMethod("GetTypeFromHandle");
  80. AssemblyBuilder _asmBuilder;
  81. ModuleBuilder _moduleBuilder;
  82. Hashtable _symbolDocWriters = new Hashtable();
  83. // IL generation state
  84. ILGenerator _il;
  85. Label _returnLabel; // current label for method return
  86. LocalBuilder _returnValueLocal; // returnValueLocal
  87. IType _returnType;
  88. int _tryBlock; // are we in a try block?
  89. bool _checked = true;
  90. bool _rawArrayIndexing = false;
  91. Hashtable _typeCache = new Hashtable();
  92. // keeps track of types on the IL stack
  93. Stack _types = new Stack();
  94. Stack _loopInfoStack = new Stack();
  95. AttributeCollection _assemblyAttributes = new AttributeCollection();
  96. LoopInfo _currentLoopInfo;
  97. void EnterLoop(Label breakLabel, Label continueLabel)
  98. {
  99. _loopInfoStack.Push(_currentLoopInfo);
  100. _currentLoopInfo = new LoopInfo(breakLabel, continueLabel, _tryBlock);
  101. }
  102. bool InTryInLoop()
  103. {
  104. return _tryBlock > _currentLoopInfo.TryBlockDepth;
  105. }
  106. void LeaveLoop()
  107. {
  108. _currentLoopInfo = (LoopInfo)_loopInfoStack.Pop();
  109. }
  110. void PushType(IType type)
  111. {
  112. _types.Push(type);
  113. }
  114. void PushBool()
  115. {
  116. PushType(TypeSystemServices.BoolType);
  117. }
  118. void PushVoid()
  119. {
  120. PushType(TypeSystemServices.VoidType);
  121. }
  122. IType PopType()
  123. {
  124. return (IType)_types.Pop();
  125. }
  126. IType PeekTypeOnStack()
  127. {
  128. return (IType)_types.Peek();
  129. }
  130. void AssertStackIsEmpty(string message)
  131. {
  132. if (0 != _types.Count)
  133. {
  134. throw new ApplicationException(
  135. string.Format("{0}: {1} items still on the stack.", message, _types.Count)
  136. );
  137. }
  138. }
  139. override public void Run()
  140. {
  141. if (Errors.Count > 0)
  142. {
  143. return;
  144. }
  145. GatherAssemblyAttributes();
  146. SetUpAssembly();
  147. DefineTypes();
  148. DefineResources();
  149. DefineAssemblyAttributes();
  150. DefineEntryPoint();
  151. }
  152. void GatherAssemblyAttributes()
  153. {
  154. foreach (Module module in CompileUnit.Modules)
  155. {
  156. foreach (Attribute attribute in module.AssemblyAttributes)
  157. {
  158. _assemblyAttributes.Add(attribute);
  159. }
  160. }
  161. }
  162. void DefineTypes()
  163. {
  164. if (CompileUnit.Modules.Count > 0)
  165. {
  166. List types = CollectTypes();
  167. foreach (TypeDefinition type in types)
  168. {
  169. DefineType(type);
  170. }
  171. foreach (TypeDefinition type in types)
  172. {
  173. DefineTypeMembers(type);
  174. }
  175. foreach (Module module in CompileUnit.Modules)
  176. {
  177. OnModule(module);
  178. }
  179. EmitAttributes();
  180. CreateTypes(types);
  181. }
  182. }
  183. class AttributeEmitVisitor : DepthFirstVisitor
  184. {
  185. EmitAssembly _emitter;
  186. public AttributeEmitVisitor(EmitAssembly emitter)
  187. {
  188. _emitter = emitter;
  189. }
  190. public override void OnField(Field node)
  191. {
  192. _emitter.EmitFieldAttributes(node);
  193. }
  194. public override void OnEnumMember(EnumMember node)
  195. {
  196. _emitter.EmitFieldAttributes(node);
  197. }
  198. public override void OnEvent(Event node)
  199. {
  200. _emitter.EmitEventAttributes(node);
  201. }
  202. public override void OnProperty(Property node)
  203. {
  204. Visit(node.Getter);
  205. Visit(node.Setter);
  206. _emitter.EmitPropertyAttributes(node);
  207. }
  208. public override void OnConstructor(Constructor node)
  209. {
  210. Visit(node.Parameters);
  211. _emitter.EmitConstructorAttributes(node);
  212. }
  213. public override void OnMethod(Method node)
  214. {
  215. Visit(node.Parameters);
  216. _emitter.EmitMethodAttributes(node);
  217. }
  218. public override void OnParameterDeclaration(ParameterDeclaration node)
  219. {
  220. _emitter.EmitParameterAttributes(node);
  221. }
  222. public override void LeaveClassDefinition(ClassDefinition node)
  223. {
  224. _emitter.EmitTypeAttributes(node);
  225. }
  226. public override void LeaveInterfaceDefinition(InterfaceDefinition node)
  227. {
  228. _emitter.EmitTypeAttributes(node);
  229. }
  230. public override void LeaveEnumDefinition(EnumDefinition node)
  231. {
  232. _emitter.EmitTypeAttributes(node);
  233. }
  234. }
  235. delegate void CustomAttributeSetter(CustomAttributeBuilder attribute);
  236. void EmitAttributes(INodeWithAttributes node, CustomAttributeSetter setCustomAttribute)
  237. {
  238. foreach (Attribute attribute in node.Attributes)
  239. {
  240. setCustomAttribute(GetCustomAttributeBuilder(attribute));
  241. }
  242. }
  243. void EmitPropertyAttributes(Property node)
  244. {
  245. PropertyBuilder builder = GetPropertyBuilder(node);
  246. EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute));
  247. }
  248. void EmitParameterAttributes(ParameterDeclaration node)
  249. {
  250. ParameterBuilder builder = (ParameterBuilder)GetBuilder(node);
  251. EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute));
  252. }
  253. void EmitEventAttributes(Event node)
  254. {
  255. EventBuilder builder = (EventBuilder)GetBuilder(node);
  256. EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute));
  257. }
  258. void EmitConstructorAttributes(Constructor node)
  259. {
  260. ConstructorBuilder builder = (ConstructorBuilder)GetBuilder(node);
  261. EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute));
  262. }
  263. void EmitMethodAttributes(Method node)
  264. {
  265. MethodBuilder builder = GetMethodBuilder(node);
  266. EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute));
  267. }
  268. void EmitTypeAttributes(TypeDefinition node)
  269. {
  270. TypeBuilder builder = GetTypeBuilder(node);
  271. EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute));
  272. }
  273. void EmitFieldAttributes(TypeMember node)
  274. {
  275. FieldBuilder builder = GetFieldBuilder(node);
  276. EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute));
  277. }
  278. void EmitAttributes()
  279. {
  280. AttributeEmitVisitor visitor = new AttributeEmitVisitor(this);
  281. foreach (Module module in CompileUnit.Modules)
  282. {
  283. module.Accept(visitor);
  284. }
  285. }
  286. void CreateTypes(List types)
  287. {
  288. new TypeCreator(this, types).Run();
  289. }
  290. /// <summary>
  291. /// Ensures that all types are created in the correct order.
  292. /// </summary>
  293. class TypeCreator
  294. {
  295. EmitAssembly _emitter;
  296. Hashtable _created;
  297. List _types;
  298. TypeMember _current;
  299. public TypeCreator(EmitAssembly emitter, List types)
  300. {
  301. _emitter = emitter;
  302. _types = types;
  303. _created = new Hashtable();
  304. }
  305. public void Run()
  306. {
  307. ResolveEventHandler resolveHandler = new ResolveEventHandler(OnTypeResolve);
  308. AppDomain current = Thread.GetDomain();
  309. try
  310. {
  311. current.TypeResolve += resolveHandler;
  312. CreateTypes();
  313. }
  314. finally
  315. {
  316. current.TypeResolve -= resolveHandler;
  317. }
  318. }
  319. void CreateTypes()
  320. {
  321. foreach (TypeMember type in _types)
  322. {
  323. CreateType(type);
  324. }
  325. }
  326. void CreateType(TypeMember type)
  327. {
  328. if (!_created.ContainsKey(type))
  329. {
  330. TypeMember saved = _current;
  331. _current = type;
  332. _created.Add(type, type);
  333. Trace("creating type '{0}'", type);
  334. if (IsNestedType(type))
  335. {
  336. CreateType((TypeMember)type.ParentNode);
  337. }
  338. TypeDefinition typedef = type as TypeDefinition;
  339. if (null != typedef)
  340. {
  341. foreach (TypeReference baseTypeRef in typedef.BaseTypes)
  342. {
  343. IType baseType = _emitter.GetType(baseTypeRef);
  344. EnsureInternalDependency(baseType);
  345. // If base type is a constructed generic type, create any internal
  346. // parameters it might have
  347. if (baseType.ConstructedInfo != null)
  348. {
  349. foreach (IType argument in baseType.ConstructedInfo.GenericArguments)
  350. {
  351. EnsureInternalDependency(argument);
  352. }
  353. }
  354. }
  355. }
  356. _emitter.GetTypeBuilder(type).CreateType();
  357. Trace("type '{0}' successfully created", type);
  358. _current = saved;
  359. }
  360. }
  361. private void EnsureInternalDependency(IType type)
  362. {
  363. AbstractInternalType tag = type as AbstractInternalType;
  364. if (null != tag)
  365. {
  366. CreateType(tag.TypeDefinition);
  367. }
  368. else
  369. {
  370. GenericConstructedType gtag = type as GenericConstructedType;
  371. if(null != gtag)
  372. {
  373. EnsureInternalDependency(gtag.GenericDefinition);
  374. }
  375. }
  376. }
  377. bool IsNestedType(TypeMember type)
  378. {
  379. NodeType parent = type.ParentNode.NodeType;
  380. return (NodeType.ClassDefinition == parent) ||
  381. (NodeType.InterfaceDefinition == parent);
  382. }
  383. Assembly OnTypeResolve(object sender, ResolveEventArgs args)
  384. {
  385. Trace("OnTypeResolve('{0}') during '{1}' creation.", args.Name, _current);
  386. // TypeResolve is generated whenever a type
  387. // contains fields of a value type not created yet.
  388. // All we need to do is look for value type fields
  389. // and create them all.
  390. ClassDefinition classdef = _current as ClassDefinition;
  391. foreach (TypeMember member in classdef.Members)
  392. {
  393. if (NodeType.Field == member.NodeType)
  394. {
  395. AbstractInternalType type = _emitter.GetType(((Field)member).Type) as AbstractInternalType;
  396. if (type != null && type.IsValueType)
  397. {
  398. CreateType(type.TypeDefinition);
  399. }
  400. }
  401. }
  402. return _emitter._asmBuilder;
  403. }
  404. void Trace(string format, params object[] args)
  405. {
  406. _emitter.Context.TraceVerbose(format, args);
  407. }
  408. }
  409. List CollectTypes()
  410. {
  411. List types = new List();
  412. foreach (Module module in CompileUnit.Modules)
  413. {
  414. CollectTypes(types, module.Members);
  415. }
  416. return types;
  417. }
  418. void CollectTypes(List types, TypeMemberCollection members)
  419. {
  420. foreach (TypeMember member in members)
  421. {
  422. switch (member.NodeType)
  423. {
  424. case NodeType.InterfaceDefinition:
  425. case NodeType.ClassDefinition:
  426. {
  427. types.Add(member);
  428. CollectTypes(types, ((TypeDefinition)member).Members);
  429. break;
  430. }
  431. case NodeType.EnumDefinition:
  432. {
  433. types.Add(member);
  434. break;
  435. }
  436. }
  437. }
  438. }
  439. override public void Dispose()
  440. {
  441. base.Dispose();
  442. _asmBuilder = null;
  443. _moduleBuilder = null;
  444. _symbolDocWriters.Clear();
  445. _il = null;
  446. _returnValueLocal = null;
  447. _returnType = null;
  448. _tryBlock = 0;
  449. _checked = true;
  450. _rawArrayIndexing = false;
  451. _types.Clear();
  452. _typeCache.Clear();
  453. _builders.Clear();
  454. _assemblyAttributes.Clear();
  455. }
  456. override public void OnAttribute(Attribute node)
  457. {
  458. }
  459. override public void OnModule(Module module)
  460. {
  461. Visit(module.Members);
  462. }
  463. override public void OnEnumDefinition(EnumDefinition node)
  464. {
  465. TypeBuilder builder = GetTypeBuilder(node);
  466. foreach (EnumMember member in node.Members)
  467. {
  468. FieldBuilder field = builder.DefineField(member.Name, builder,
  469. FieldAttributes.Public |
  470. FieldAttributes.Static |
  471. FieldAttributes.Literal);
  472. field.SetConstant((int)member.Initializer.Value);
  473. SetBuilder(member, field);
  474. }
  475. }
  476. override public void OnArrayTypeReference(ArrayTypeReference node)
  477. {
  478. }
  479. override public void OnClassDefinition(ClassDefinition node)
  480. {
  481. EmitTypeDefinition(node);
  482. }
  483. override public void OnField(Field node)
  484. {
  485. FieldBuilder builder = GetFieldBuilder(node);
  486. if (builder.IsLiteral)
  487. {
  488. builder.SetConstant(GetInternalFieldStaticValue((InternalField)node.Entity));
  489. }
  490. }
  491. override public void OnInterfaceDefinition(InterfaceDefinition node)
  492. {
  493. TypeBuilder builder = GetTypeBuilder(node);
  494. foreach (TypeReference baseType in node.BaseTypes)
  495. {
  496. builder.AddInterfaceImplementation(GetSystemType(baseType));
  497. }
  498. }
  499. override public void OnMacroStatement(MacroStatement node)
  500. {
  501. NotImplemented(node, "Unexpected macro: " + node.ToCodeString());
  502. }
  503. override public void OnCallableDefinition(CallableDefinition node)
  504. {
  505. NotImplemented(node, "Unexpected callable definition!");
  506. }
  507. void EmitTypeDefinition(TypeDefinition node)
  508. {
  509. TypeBuilder current = GetTypeBuilder(node);
  510. EmitBaseTypesAndAttributes(node, current);
  511. Visit(node.Members);
  512. }
  513. override public void OnMethod(Method method)
  514. {
  515. if (method.IsRuntime) return;
  516. if (IsPInvoke(method)) return;
  517. MethodBuilder methodBuilder = GetMethodBuilder(method);
  518. if (null != method.ExplicitInfo)
  519. {
  520. IMethod ifaceMethod = (IMethod)method.ExplicitInfo.Entity;
  521. MethodInfo ifaceInfo = GetMethodInfo(ifaceMethod);
  522. MethodInfo implInfo = GetMethodInfo((IMethod)method.Entity);
  523. TypeBuilder typeBuilder = GetTypeBuilder(method.DeclaringType);
  524. typeBuilder.DefineMethodOverride(implInfo, ifaceInfo);
  525. }
  526. EmitMethod(method, methodBuilder.GetILGenerator());
  527. }
  528. void EmitMethod(Method method, ILGenerator generator)
  529. {
  530. _il = generator;
  531. DefineLabels(method);
  532. Visit(method.Locals);
  533. BeginMethodBody(GetEntity(method).ReturnType);
  534. Visit(method.Body);
  535. EndMethodBody();
  536. }
  537. void BeginMethodBody(IType returnType)
  538. {
  539. _returnType = returnType;
  540. _returnLabel = _il.DefineLabel();
  541. if (TypeSystemServices.VoidType != _returnType)
  542. {
  543. _returnValueLocal = _il.DeclareLocal(GetSystemType(_returnType));
  544. }
  545. }
  546. void EndMethodBody()
  547. {
  548. _il.MarkLabel(_returnLabel);
  549. if (null != _returnValueLocal)
  550. {
  551. _il.Emit(OpCodes.Ldloc, _returnValueLocal);
  552. _returnValueLocal = null;
  553. }
  554. _il.Emit(OpCodes.Ret);
  555. }
  556. private bool IsPInvoke(Method method)
  557. {
  558. return GetEntity(method).IsPInvoke;
  559. }
  560. override public void OnBlock(Block block)
  561. {
  562. bool currentChecked = _checked;
  563. _checked = AstAnnotations.IsChecked(block, Parameters.Checked);
  564. bool currentArrayIndexing = _rawArrayIndexing;
  565. _rawArrayIndexing = AstAnnotations.IsRawIndexing(block);
  566. Visit(block.Statements);
  567. _rawArrayIndexing = currentArrayIndexing;
  568. _checked = currentChecked;
  569. }
  570. void DefineLabels(Method method)
  571. {
  572. foreach (InternalLabel label in ((InternalMethod)method.Entity).Labels)
  573. {
  574. label.Label = _il.DefineLabel();
  575. }
  576. }
  577. override public void OnConstructor(Constructor constructor)
  578. {
  579. if (constructor.IsRuntime) return;
  580. ConstructorBuilder builder = GetConstructorBuilder(constructor);
  581. EmitMethod(constructor, builder.GetILGenerator());
  582. }
  583. override public void OnLocal(Local local)
  584. {
  585. InternalLocal info = GetInternalLocal(local);
  586. info.LocalBuilder = _il.DeclareLocal(GetSystemType(local));
  587. if (Parameters.Debug)
  588. {
  589. info.LocalBuilder.SetLocalSymInfo(local.Name);
  590. }
  591. }
  592. override public void OnForStatement(ForStatement node)
  593. {
  594. NotImplemented("ForStatement");
  595. }
  596. override public void OnReturnStatement(ReturnStatement node)
  597. {
  598. EmitDebugInfo(node);
  599. OpCode retOpCode = _tryBlock > 0 ? OpCodes.Leave : OpCodes.Br;
  600. if (null != node.Expression)
  601. {
  602. Visit(node.Expression);
  603. EmitCastIfNeeded(_returnType, PopType());
  604. _il.Emit(OpCodes.Stloc, _returnValueLocal);
  605. }
  606. _il.Emit(retOpCode, _returnLabel);
  607. }
  608. override public void OnRaiseStatement(RaiseStatement node)
  609. {
  610. EmitDebugInfo(node);
  611. if (node.Exception == null)
  612. {
  613. _il.Emit(OpCodes.Rethrow);
  614. }
  615. else
  616. {
  617. Visit(node.Exception); PopType();
  618. _il.Emit(OpCodes.Throw);
  619. }
  620. }
  621. override public void OnTryStatement(TryStatement node)
  622. {
  623. ++_tryBlock;
  624. Label end = _il.BeginExceptionBlock();
  625. // The fault handler isn't very well supported by the
  626. // the ILGenerator. Thus, when there is a failure block
  627. // in the same try as an except or ensure block, we
  628. // need to do some special brute forcing with the exception
  629. // block context in the ILGenerator.
  630. if(null != node.FailureBlock && null != node.EnsureBlock)
  631. {
  632. ++_tryBlock;
  633. _il.BeginExceptionBlock();
  634. }
  635. if(null != node.FailureBlock && node.ExceptionHandlers.Count > 0)
  636. {
  637. ++_tryBlock;
  638. _il.BeginExceptionBlock();
  639. }
  640. Visit(node.ProtectedBlock);
  641. Visit(node.ExceptionHandlers);
  642. if(null != node.FailureBlock)
  643. {
  644. // Logic to back out of the manually forced blocks
  645. if(node.ExceptionHandlers.Count > 0)
  646. {
  647. _il.EndExceptionBlock();
  648. --_tryBlock;
  649. }
  650. _il.BeginFaultBlock();
  651. Visit(node.FailureBlock);
  652. // Logic to back out of the manually forced blocks once more
  653. if(null != node.EnsureBlock)
  654. {
  655. _il.EndExceptionBlock();
  656. --_tryBlock;
  657. }
  658. }
  659. if (null != node.EnsureBlock)
  660. {
  661. _il.BeginFinallyBlock();
  662. Visit(node.EnsureBlock);
  663. }
  664. _il.EndExceptionBlock();
  665. --_tryBlock;
  666. }
  667. override public void OnExceptionHandler(ExceptionHandler node)
  668. {
  669. if((node.Flags & ExceptionHandlerFlags.Filter) == ExceptionHandlerFlags.Filter)
  670. {
  671. _il.BeginExceptFilterBlock();
  672. Label endLabel = _il.DefineLabel();
  673. // If the filter is not untyped, then test the exception type
  674. // before testing the filter condition
  675. if((node.Flags & ExceptionHandlerFlags.Untyped) == ExceptionHandlerFlags.None)
  676. {
  677. Label filterCondition = _il.DefineLabel();
  678. // Test the type of the exception.
  679. _il.Emit(OpCodes.Isinst, GetSystemType(node.Declaration.Type));
  680. // Duplicate it. If it is null, then it will be used to
  681. // skip the filter.
  682. _il.Emit(OpCodes.Dup);
  683. // If the exception is of the right type, branch
  684. // to test the filter condition.
  685. _il.Emit(OpCodes.Brtrue, filterCondition);
  686. // Otherwise, clean up the stack and prepare the stack
  687. // to skip the filter.
  688. EmitStoreOrPopException(node);
  689. _il.Emit(OpCodes.Ldc_I4_0);
  690. _il.Emit(OpCodes.Br, endLabel);
  691. _il.MarkLabel(filterCondition);
  692. }
  693. else if((node.Flags & ExceptionHandlerFlags.Anonymous) == ExceptionHandlerFlags.None)
  694. {
  695. // Cast the exception to the default except type
  696. _il.Emit(OpCodes.Isinst, GetSystemType(node.Declaration.Type));
  697. }
  698. EmitStoreOrPopException(node);
  699. // Test the condition and convert to boolean if needed.
  700. node.FilterCondition.Accept(this);
  701. PopType();
  702. EmitToBoolIfNeeded(node.FilterCondition);
  703. // If the type is right and the condition is true,
  704. // proceed with the handler.
  705. _il.MarkLabel(endLabel);
  706. _il.Emit(OpCodes.Ldc_I4_0);
  707. _il.Emit(OpCodes.Cgt_Un);
  708. _il.BeginCatchBlock(null);
  709. }
  710. else
  711. {
  712. // Begin a normal catch block of the appropriate type.
  713. _il.BeginCatchBlock(GetSystemType(node.Declaration.Type));
  714. // Clean up the stack or store the exception if not anonymous.
  715. EmitStoreOrPopException(node);
  716. }
  717. Visit(node.Block);
  718. }
  719. private void EmitStoreOrPopException(ExceptionHandler node)
  720. {
  721. if((node.Flags & ExceptionHandlerFlags.Anonymous) == ExceptionHandlerFlags.None)
  722. {
  723. _il.Emit(OpCodes.Stloc, GetLocalBuilder(node.Declaration));
  724. }
  725. else
  726. {
  727. _il.Emit(OpCodes.Pop);
  728. }
  729. }
  730. override public void OnUnpackStatement(UnpackStatement node)
  731. {
  732. NotImplemented("Unpacking");
  733. }
  734. override public bool EnterExpressionStatement(ExpressionStatement node)
  735. {
  736. EmitDebugInfo(node);
  737. return true;
  738. }
  739. override public void LeaveExpressionStatement(ExpressionStatement node)
  740. {
  741. // if the type of the inner expression is not
  742. // void we need to pop its return value to leave
  743. // the stack sane
  744. DiscardValueOnStack();
  745. AssertStackIsEmpty("stack must be empty after a statement! Offending statement: '" + node.ToCodeString() + "'");
  746. }
  747. void DiscardValueOnStack()
  748. {
  749. if (PopType() != TypeSystemServices.VoidType)
  750. {
  751. _il.Emit(OpCodes.Pop);
  752. }
  753. }
  754. override public void OnUnlessStatement(UnlessStatement node)
  755. {
  756. Label endLabel = _il.DefineLabel();
  757. EmitDebugInfo(node);
  758. EmitBranchTrue(node.Condition, endLabel);
  759. node.Block.Accept(this);
  760. _il.MarkLabel(endLabel);
  761. }
  762. void OnSwitch(MethodInvocationExpression node)
  763. {
  764. ExpressionCollection args = node.Arguments;
  765. Visit(args[0]);
  766. EmitCastIfNeeded(TypeSystemServices.IntType, PopType());
  767. Label[] labels = new Label[args.Count-1];
  768. for (int i=0; i<labels.Length; ++i)
  769. {
  770. labels[i] = ((InternalLabel)args[i+1].Entity).Label;
  771. }
  772. _il.Emit(OpCodes.Switch, labels);
  773. PushVoid();
  774. }
  775. override public void OnGotoStatement(GotoStatement node)
  776. {
  777. EmitDebugInfo(node);
  778. InternalLabel label = (InternalLabel)GetEntity(node.Label);
  779. int gotoDepth = AstAnnotations.GetTryBlockDepth(node);
  780. int targetDepth = AstAnnotations.GetTryBlockDepth(label.LabelStatement);
  781. if (targetDepth == gotoDepth)
  782. {
  783. _il.Emit(OpCodes.Br, label.Label);
  784. }
  785. else
  786. {
  787. _il.Emit(OpCodes.Leave, label.Label);
  788. }
  789. }
  790. override public void OnLabelStatement(LabelStatement node)
  791. {
  792. EmitDebugInfo(node);
  793. _il.MarkLabel(((InternalLabel)node.Entity).Label);
  794. }
  795. override public void OnConditionalExpression(ConditionalExpression node)
  796. {
  797. IType type = GetExpressionType(node);
  798. Label endLabel = _il.DefineLabel();
  799. EmitBranchFalse(node.Condition, endLabel);
  800. node.TrueValue.Accept(this);
  801. EmitCastIfNeeded(type, PopType());
  802. Label elseEndLabel = _il.DefineLabel();
  803. _il.Emit(OpCodes.Br, elseEndLabel);
  804. _il.MarkLabel(endLabel);
  805. endLabel = elseEndLabel;
  806. node.FalseValue.Accept(this);
  807. EmitCastIfNeeded(type, PopType());
  808. _il.MarkLabel(endLabel);
  809. PushType(type);
  810. }
  811. override public void OnIfStatement(IfStatement node)
  812. {
  813. Label endLabel = _il.DefineLabel();
  814. EmitDebugInfo(node);
  815. EmitBranchFalse(node.Condition, endLabel);
  816. node.TrueBlock.Accept(this);
  817. if (null != node.FalseBlock)
  818. {
  819. Label elseEndLabel = _il.DefineLabel();
  820. _il.Emit(OpCodes.Br, elseEndLabel);
  821. _il.MarkLabel(endLabel);
  822. endLabel = elseEndLabel;
  823. node.FalseBlock.Accept(this);
  824. }
  825. _il.MarkLabel(endLabel);
  826. }
  827. void EmitBranchTrue(UnaryExpression expression, Label label)
  828. {
  829. if (UnaryOperatorType.LogicalNot == expression.Operator)
  830. {
  831. EmitBranchFalse(expression.Operand, label);
  832. }
  833. else
  834. {
  835. DefaultBranchTrue(expression, label);
  836. }
  837. }
  838. void EmitBranchTrue(BinaryExpression expression, Label label)
  839. {
  840. switch (expression.Operator)
  841. {
  842. case BinaryOperatorType.TypeTest:
  843. {
  844. EmitTypeTest(expression);
  845. _il.Emit(OpCodes.Brtrue, label);
  846. break;
  847. }
  848. case BinaryOperatorType.Or:
  849. {
  850. EmitBranchTrue(expression.Left, label);
  851. EmitBranchTrue(expression.Right, label);
  852. break;
  853. }
  854. case BinaryOperatorType.And:
  855. {
  856. Label skipRhs = _il.DefineLabel();
  857. EmitBranchFalse(expression.Left, skipRhs);
  858. EmitBranchTrue(expression.Right, label);
  859. _il.MarkLabel(skipRhs);
  860. break;
  861. }
  862. case BinaryOperatorType.Equality:
  863. {
  864. LoadCmpOperands(expression);
  865. _il.Emit(OpCodes.Beq, label);
  866. break;
  867. }
  868. case BinaryOperatorType.ReferenceEquality:
  869. {
  870. Visit(expression.Left); PopType();
  871. Visit(expression.Right); PopType();
  872. _il.Emit(OpCodes.Beq, label);
  873. break;
  874. }
  875. case BinaryOperatorType.ReferenceInequality:
  876. {
  877. if (IsNull(expression.Left))
  878. {
  879. EmitRawBranchTrue(expression.Right, label);
  880. break;
  881. }
  882. if (IsNull(expression.Right))
  883. {
  884. EmitRawBranchTrue(expression.Left, label);
  885. break;
  886. }
  887. Visit(expression.Left); PopType();
  888. Visit(expression.Right); PopType();
  889. _il.Emit(OpCodes.Ceq);
  890. _il.Emit(OpCodes.Brfalse, label);
  891. break;
  892. }
  893. case BinaryOperatorType.GreaterThan:
  894. {
  895. LoadCmpOperands(expression);
  896. _il.Emit(OpCodes.Bgt, label);
  897. break;
  898. }
  899. case BinaryOperatorType.GreaterThanOrEqual:
  900. {
  901. LoadCmpOperands(expression);
  902. _il.Emit(OpCodes.Bge, label);
  903. break;
  904. }
  905. case BinaryOperatorType.LessThan:
  906. {
  907. LoadCmpOperands(expression);
  908. _il.Emit(OpCodes.Blt, label);
  909. break;
  910. }
  911. case BinaryOperatorType.LessThanOrEqual:
  912. {
  913. LoadCmpOperands(expression);
  914. _il.Emit(OpCodes.Ble, label);
  915. break;
  916. }
  917. default:
  918. {
  919. DefaultBranchTrue(expression, label);
  920. break;
  921. }
  922. }
  923. }
  924. void EmitRawBranchTrue(Expression expression, Label label)
  925. {
  926. expression.Accept(this); PopType();
  927. _il.Emit(OpCodes.Brtrue, label);
  928. }
  929. void EmitBranchTrue(Expression expression, Label label)
  930. {
  931. switch (expression.NodeType)
  932. {
  933. case NodeType.BinaryExpression:
  934. {
  935. EmitBranchTrue((BinaryExpression)expression, label);
  936. break;
  937. }
  938. case NodeType.UnaryExpression:
  939. {
  940. EmitBranchTrue((UnaryExpression)expression, label);
  941. break;
  942. }
  943. default:
  944. {
  945. DefaultBranchTrue(expression, label);
  946. break;
  947. }
  948. }
  949. }
  950. void DefaultBranchTrue(Expression expression, Label label)
  951. {
  952. expression.Accept(this);
  953. IType type = PopType();
  954. if (TypeSystemServices.DoubleType == type)
  955. {
  956. _il.Emit(OpCodes.Ldc_R8, 0.0);
  957. _il.Emit(OpCodes.Bne_Un, label);
  958. }
  959. else if (TypeSystemServices.SingleType == type)
  960. {
  961. _il.Emit(OpCodes.Ldc_R4, 0.0f);
  962. _il.Emit(OpCodes.Bne_Un, label);
  963. }
  964. else
  965. {
  966. EmitToBoolIfNeeded(expression);
  967. _il.Emit(OpCodes.Brtrue, label);
  968. }
  969. }
  970. void EmitBranchFalse(BinaryExpression expression, Label label)
  971. {
  972. switch (expression.Operator)
  973. {
  974. case BinaryOperatorType.TypeTest:
  975. {
  976. EmitTypeTest(expression);
  977. _il.Emit(OpCodes.Brfalse, label);
  978. break;
  979. }
  980. case BinaryOperatorType.Or:
  981. {
  982. Label end = _il.DefineLabel();
  983. EmitBranchTrue(expression.Left, end);
  984. EmitBranchFalse(expression.Right, label);
  985. _il.MarkLabel(end);
  986. break;
  987. }
  988. case BinaryOperatorType.And:
  989. {
  990. EmitBranchFalse(expression.Left, label);
  991. EmitBranchFalse(expression.Right, label);
  992. break;
  993. }
  994. case BinaryOperatorType.Equality:
  995. {
  996. if (CanOptimizeAwayZeroOrFalseComparison(expression.Left, expression.Right))
  997. {
  998. EmitBranchTrue(expression.Right, label);
  999. }
  1000. else if (CanOptimizeAwayZeroOrFalseComparison(expression.Right, expression.Left))
  1001. {
  1002. EmitBranchTrue(expression.Left, label);
  1003. }
  1004. else
  1005. {
  1006. DefaultBranchFalse(expression, label);
  1007. }
  1008. break;
  1009. }
  1010. case BinaryOperatorType.Inequality:
  1011. {
  1012. if (CanOptimizeAwayZeroOrFalseComparison(expression.Left, expression.Right))
  1013. {
  1014. EmitBranchFalse(expression.Right, label);
  1015. }
  1016. else if (CanOptimizeAwayZeroOrFalseComparison(expression.Right, expression.Left))
  1017. {
  1018. EmitBranchFalse(expression.Left, label);
  1019. }
  1020. else
  1021. {
  1022. DefaultBranchFalse(expression, label);
  1023. }
  1024. break;
  1025. }
  1026. default:
  1027. {
  1028. DefaultBranchFalse(expression, label);
  1029. break;
  1030. }
  1031. }
  1032. }
  1033. private bool IsNull(Expression expression)
  1034. {
  1035. return NodeType.NullLiteralExpression == expression.NodeType;
  1036. }
  1037. private bool CanOptimizeAwayZeroOrFalseComparison(Expression expression, Expression operand)
  1038. {
  1039. return (IsZero(expression) || IsFalse(expression));
  1040. }
  1041. private bool IsFalse(Expression expression)
  1042. {
  1043. return NodeType.BoolLiteralExpression == expression.NodeType
  1044. && (false == ((BoolLiteralExpression)expression).Value);
  1045. }
  1046. private bool IsZero(Expression expression)
  1047. {
  1048. return NodeType.IntegerLiteralExpression == expression.NodeType
  1049. && (0 == ((IntegerLiteralExpression)expression).Value);
  1050. }
  1051. void EmitBranchFalse(Expression expression, Label label)
  1052. {
  1053. switch (expression.NodeType)
  1054. {
  1055. case NodeType.UnaryExpression:
  1056. {
  1057. EmitBranchFalse((UnaryExpression)expression, label);
  1058. break;
  1059. }
  1060. case NodeType.BinaryExpression:
  1061. {
  1062. EmitBranchFalse((BinaryExpression)expression, label);
  1063. break;
  1064. }
  1065. default:
  1066. {
  1067. DefaultBranchFalse(expression, label);
  1068. break;
  1069. }
  1070. }
  1071. }
  1072. void EmitBranchFalse(UnaryExpression expression, Label label)
  1073. {
  1074. switch (expression.Operator)
  1075. {
  1076. case UnaryOperatorType.LogicalNot:
  1077. {
  1078. EmitBranchTrue(expression.Operand, label);
  1079. break;
  1080. }
  1081. default:
  1082. {
  1083. DefaultBranchFalse(expression, label);
  1084. break;
  1085. }
  1086. }
  1087. }
  1088. void DefaultBranchFalse(Expression expression, Label label)
  1089. {
  1090. expression.Accept(this);
  1091. IType type = PopType();
  1092. if (TypeSystemServices.DoubleType == type)
  1093. {
  1094. _il.Emit(OpCodes.Ldc_R8, (double)0.0);
  1095. _il.Emit(OpCodes.Ceq);
  1096. _il.Emit(OpCodes.Brtrue, label);
  1097. }
  1098. else if (TypeSystemServices.SingleType == type)
  1099. {
  1100. _il.Emit(OpCodes.Ldc_R4, (float)0.0);
  1101. _il.Emit(OpCodes.Ceq);
  1102. _il.Emit(OpCodes.Brtrue, label);
  1103. }
  1104. else
  1105. {
  1106. EmitToBoolIfNeeded(expression);
  1107. _il.Emit(OpCodes.Brfalse, label);
  1108. }
  1109. }
  1110. override public void OnBreakStatement(BreakStatement node)
  1111. {
  1112. EmitDebugInfo(node);
  1113. if (InTryInLoop())
  1114. {
  1115. _il.Emit(OpCodes.Leave, _currentLoopInfo.BreakLabel);
  1116. }
  1117. else
  1118. {
  1119. _il.Emit(OpCodes.Br, _currentLoopInfo.BreakLabel);
  1120. }
  1121. }
  1122. override public void OnContinueStatement(ContinueStatement node)
  1123. {
  1124. EmitDebugInfo(node);
  1125. if (InTryInLoop())
  1126. {
  1127. _il.Emit(OpCodes.Leave, _currentLoopInfo.ContinueLabel);
  1128. }
  1129. else
  1130. {
  1131. _il.Emit(OpCodes.Br, _currentLoopInfo.ContinueLabel);
  1132. }
  1133. }
  1134. override public void OnWhileStatement(WhileStatement node)
  1135. {
  1136. Label endLabel = _il.DefineLabel();
  1137. Label bodyLabel = _il.DefineLabel();
  1138. Label thenLabel = _il.DefineLabel();
  1139. Label conditionLabel = _il.DefineLabel();
  1140. LocalBuilder enteredLoop = null;
  1141. if(null != node.OrBlock)
  1142. {
  1143. enteredLoop = _il.DeclareLocal(typeof(bool));
  1144. _il.Emit(OpCodes.Ldc_I4_0);
  1145. _il.Emit(OpCodes.Stloc, enteredLoop);
  1146. }
  1147. _il.Emit(OpCodes.Br, conditionLabel);
  1148. _il.MarkLabel(bodyLabel);
  1149. EnterLoop(endLabel, conditionLabel);
  1150. if(null != node.OrBlock)
  1151. {
  1152. _il.Emit(OpCodes.Ldc_I4_1);
  1153. _il.Emit(OpCodes.Stloc, enteredLoop);
  1154. }
  1155. node.Block.Accept(this);
  1156. LeaveLoop();
  1157. _il.MarkLabel(conditionLabel);
  1158. EmitDebugInfo(node);
  1159. EmitBranchTrue(node.Condition, bodyLabel);
  1160. if(null != node.OrBlock)
  1161. {
  1162. _il.Emit(OpCodes.Ldloc, enteredLoop);
  1163. _il.Emit(OpCodes.Brtrue, thenLabel);
  1164. EnterLoop(endLabel, thenLabel);
  1165. node.OrBlock.Accept(this);
  1166. LeaveLoop();
  1167. _il.MarkLabel(thenLabel);
  1168. }
  1169. if(null != node.ThenBlock)
  1170. {
  1171. node.ThenBlock.Accept(this);
  1172. }
  1173. _il.MarkLabel(endLabel);
  1174. }
  1175. void EmitIntNot()
  1176. {
  1177. _il.Emit(OpCodes.Ldc_I4_0);
  1178. _il.Emit(OpCodes.Ceq);
  1179. }
  1180. void EmitGenericNot()
  1181. {
  1182. // bool codification:
  1183. // value_on_stack ? 0 : 1
  1184. Label wasTrue = _il.DefineLabel();
  1185. Label wasFalse = _il.DefineLabel();
  1186. _il.Emit(OpCodes.Brfalse, wasFalse);
  1187. _il.Emit(OpCodes.Ldc_I4_0);
  1188. _il.Emit(OpCodes.Br, wasTrue);
  1189. _il.MarkLabel(wasFalse);
  1190. _il.Emit(OpCodes.Ldc_I4_1);
  1191. _il.MarkLabel(wasTrue);
  1192. }
  1193. override public void OnUnaryExpression(UnaryExpression node)
  1194. {
  1195. switch (node.Operator)
  1196. {
  1197. case UnaryOperatorType.LogicalNot:
  1198. {
  1199. EmitLogicalNot(node);
  1200. break;
  1201. }
  1202. case UnaryOperatorType.UnaryNegation:
  1203. {
  1204. EmitUnaryNegation(node);
  1205. break;
  1206. }
  1207. case UnaryOperatorType.OnesComplement:
  1208. {
  1209. EmitOnesComplement(node);
  1210. break;
  1211. }
  1212. default:
  1213. {
  1214. NotImplemented(node, "unary operator not supported");
  1215. break;
  1216. }
  1217. }
  1218. }
  1219. private void EmitOnesComplement(UnaryExpression node)
  1220. {
  1221. node.Operand.Accept(this);
  1222. _il.Emit(OpCodes.Not);
  1223. }
  1224. private void EmitLogicalNot(UnaryExpression node)
  1225. {
  1226. Expression operand = node.Operand;
  1227. operand.Accept(this);
  1228. IType typeOnStack = PopType();
  1229. if (IsBoolOrInt(typeOnStack) || EmitToBoolIfNeeded(operand))
  1230. {
  1231. EmitIntNot();
  1232. }
  1233. else
  1234. {
  1235. EmitGenericNot();
  1236. }
  1237. PushBool();
  1238. }
  1239. private void EmitUnaryNegation(UnaryExpression node)
  1240. {
  1241. node.Operand.Accept(this);
  1242. IType type = PopType();
  1243. _il.Emit(OpCodes.Ldc_I4, -1);
  1244. EmitCastIfNeeded(type, TypeSystemServices.IntType);
  1245. _il.Emit(OpCodes.Mul);
  1246. PushType(type);
  1247. }
  1248. bool ShouldLeaveValueOnStack(Expression node)
  1249. {
  1250. return node.ParentNode.NodeType != NodeType.ExpressionStatement;
  1251. }
  1252. void OnReferenceComparison(BinaryExpression node)
  1253. {
  1254. node.Left.Accept(this); PopType();
  1255. node.Right.Accept(this); PopType();
  1256. _il.Emit(OpCodes.Ceq);
  1257. if (BinaryOperatorType.ReferenceInequality == node.Operator)
  1258. {
  1259. EmitIntNot();
  1260. }
  1261. PushBool();
  1262. }
  1263. void OnAssignmentToSlice(BinaryExpression node)
  1264. {
  1265. SlicingExpression slice = (SlicingExpression)node.Left;
  1266. Visit(slice.Target);
  1267. IArrayType arrayType = (IArrayType)PopType();
  1268. IType elementType = arrayType.GetElementType();
  1269. OpCode opcode = GetStoreEntityOpCode(elementType);
  1270. Slice index = slice.Indices[0];
  1271. EmitNormalizedArrayIndex(slice, index.Begin);
  1272. bool stobj = IsStobj(opcode);
  1273. if (stobj)
  1274. {
  1275. _il.Emit(OpCodes.Ldelema, GetSystemType(elementType));
  1276. }
  1277. Visit(node.Right);
  1278. EmitCastIfNeeded(elementType, PopType());
  1279. bool leaveValueOnStack = ShouldLeaveValueOnStack(node);
  1280. LocalBuilder temp = null;
  1281. if (leaveValueOnStack)
  1282. {
  1283. _il.Emit(OpCodes.Dup);
  1284. temp = StoreTempLocal(elementType);
  1285. }
  1286. if (stobj)
  1287. {
  1288. _il.Emit(opcode, GetSystemType(elementType));
  1289. }
  1290. else
  1291. {
  1292. _il.Emit(opcode);
  1293. }
  1294. if (leaveValueOnStack)
  1295. {
  1296. LoadLocal(temp, elementType);
  1297. }
  1298. else
  1299. {
  1300. PushVoid();
  1301. }
  1302. }
  1303. private void LoadLocal(LocalBuilder local, IType localType)
  1304. {
  1305. _il.Emit(OpCodes.Ldloc, local);
  1306. PushType(localType);
  1307. }
  1308. private LocalBuilder StoreTempLocal(IType elementType)
  1309. {
  1310. LocalBuilder temp;
  1311. temp = _il.DeclareLocal(GetSystemType(elementType));
  1312. _il.Emit(OpCodes.Stloc, temp);
  1313. return temp;
  1314. }
  1315. void OnAssignment(BinaryExpression node)
  1316. {
  1317. if (NodeType.SlicingExpression == node.Left.NodeType)
  1318. {
  1319. OnAssignmentToSlice(node);
  1320. return;
  1321. }
  1322. // when the parent is not a statement we need to leave
  1323. // the value on the stack
  1324. bool leaveValueOnStack = ShouldLeaveValueOnStack(node);
  1325. IEntity tag = TypeSystemServices.GetEntity(node.Left);
  1326. switch (tag.EntityType)
  1327. {
  1328. case EntityType.Local:
  1329. {
  1330. SetLocal(node, (InternalLocal)tag, leaveValueOnStack);
  1331. break;
  1332. }
  1333. case EntityType.Parameter:
  1334. {
  1335. InternalParameter param = (InternalParameter)tag;
  1336. if (param.Parameter.IsByRef)
  1337. {
  1338. SetByRefParam(param, node.Right, leaveValueOnStack);
  1339. break;
  1340. }
  1341. Visit(node.Right);
  1342. EmitCastIfNeeded(param.Type, PopType());
  1343. if (leaveValueOnStack)
  1344. {
  1345. _il.Emit(OpCodes.Dup);
  1346. PushType(param.Type);
  1347. }
  1348. _il.Emit(OpCodes.Starg, param.Index);
  1349. break;
  1350. }
  1351. case EntityType.Field:
  1352. {
  1353. IField field = (IField)tag;
  1354. SetField(node, field, node.Left, node.Right, leaveValueOnStack);
  1355. break;
  1356. }
  1357. case EntityType.Property:
  1358. {
  1359. SetProperty(node, (IProperty)tag, node.Left, node.Right, leaveValueOnStack);
  1360. break;
  1361. }
  1362. default:
  1363. {
  1364. NotImplemented(node, tag.ToString());
  1365. break;
  1366. }
  1367. }
  1368. if (!leaveValueOnStack)
  1369. {
  1370. PushVoid();
  1371. }
  1372. }
  1373. private void SetByRefParam(InternalParameter param, Expression right, bool leaveValueOnStack)
  1374. {
  1375. LocalBuilder temp = null;
  1376. IType tempType = null;
  1377. if (leaveValueOnStack)
  1378. {
  1379. Visit(right);
  1380. tempType = PopType();
  1381. temp = StoreTempLocal(tempType);
  1382. }
  1383. LoadParam(param);
  1384. if (temp != null)
  1385. {
  1386. LoadLocal(temp, tempType);
  1387. }
  1388. else
  1389. {
  1390. Visit(right);
  1391. }
  1392. EmitCastIfNeeded(param.Type, PopType());
  1393. OpCode storecode = GetStoreRefParamCode(param.Type);
  1394. if (IsStobj(storecode)) //passing struct/decimal byref
  1395. {
  1396. _il.Emit(storecode, GetSystemType(param.Type));
  1397. }
  1398. else
  1399. {
  1400. _il.Emit(storecode);
  1401. }
  1402. if (null != temp)
  1403. {
  1404. LoadLocal(temp, tempType);
  1405. }
  1406. }
  1407. void EmitTypeTest(BinaryExpression node)
  1408. {
  1409. Visit(node.Left); PopType();
  1410. Type type = null;
  1411. if (NodeType.TypeofExpression == node.Right.NodeType)
  1412. {
  1413. type = GetSystemType(((TypeofExpression)node.Right).Type);
  1414. }
  1415. else
  1416. {
  1417. type = GetSystemType(node.Right);
  1418. }
  1419. _il.Emit(OpCodes.Isinst, type);
  1420. }
  1421. void OnTypeTest(BinaryExpression node)
  1422. {
  1423. EmitTypeTest(node);
  1424. Label isTrue = _il.DefineLabel();
  1425. Label isFalse = _il.DefineLabel();
  1426. _il.Emit(OpCodes.Brtrue, isTrue);
  1427. _il.Emit(OpCodes.Ldc_I4_0);
  1428. _il.Emit(OpCodes.Br, isFalse);
  1429. _il.MarkLabel(isTrue);
  1430. _il.Emit(OpCodes.Ldc_I4_1);
  1431. _il.MarkLabel(isFalse);
  1432. PushBool();
  1433. }
  1434. void LoadCmpOperands(BinaryExpression node)
  1435. {
  1436. IType lhs = node.Left.ExpressionType;
  1437. IType rhs = node.Right.ExpressionType;
  1438. IType type = TypeSystemServices.GetPromotedNumberType(lhs, rhs);
  1439. Visit(node.Left);
  1440. EmitCastIfNeeded(type, PopType());
  1441. Visit(node.Right);
  1442. EmitCastIfNeeded(type, PopType());
  1443. }
  1444. void OnEquality(BinaryExpression node)
  1445. {
  1446. LoadCmpOperands(node);
  1447. _il.Emit(OpCodes.Ceq);
  1448. PushBool();
  1449. }
  1450. void OnInequality(BinaryExpression node)
  1451. {
  1452. LoadCmpOperands(node);
  1453. _il.Emit(OpCodes.Ceq);
  1454. EmitIntNot();
  1455. PushBool();
  1456. }
  1457. void OnGreaterThan(BinaryExpression node)
  1458. {
  1459. LoadCmpOperands(node);
  1460. _il.Emit(OpCodes.Cgt);
  1461. PushBool();
  1462. }
  1463. void OnGreaterThanOrEqual(BinaryExpression node)
  1464. {
  1465. OnLessThan(node);
  1466. EmitIntNot();
  1467. }
  1468. void OnLessThan(BinaryExpression node)
  1469. {
  1470. LoadCmpOperands(node);
  1471. _il.Emit(OpCodes.Clt);
  1472. PushBool();
  1473. }
  1474. void OnLessThanOrEqual(BinaryExpression node)
  1475. {
  1476. OnGreaterThan(node);
  1477. EmitIntNot();
  1478. }
  1479. void OnExponentiation(BinaryExpression node)
  1480. {
  1481. Visit(node.Left);
  1482. EmitCastIfNeeded(TypeSystemServices.DoubleType, PopType());
  1483. Visit(node.Right);
  1484. EmitCastIfNeeded(TypeSystemServices.DoubleType, PopType());
  1485. _il.EmitCall(OpCodes.Call, Math_Pow, null);
  1486. PushType(TypeSystemServices.DoubleType);
  1487. }
  1488. void OnArithmeticOperator(BinaryExpression node)
  1489. {
  1490. IType type = node.ExpressionType;
  1491. node.Left.Accept(this); EmitCastIfNeeded(type, PopType());
  1492. node.Right.Accept(this); EmitCastIfNeeded(type, PopType());
  1493. _il.Emit(GetArithmeticOpCode(type, node.Operator));
  1494. PushType(type);
  1495. }
  1496. bool EmitToBoolIfNeeded(Expression expression)
  1497. {
  1498. IType type = GetExpressionType(expression);
  1499. if (TypeSystemServices.ObjectType == type ||
  1500. TypeSystemServices.DuckType == type)
  1501. {
  1502. _il.EmitCall(OpCodes.Call, RuntimeServices_ToBool_Object, null);
  1503. return true;
  1504. }
  1505. if (TypeSystemServices.DecimalType == type)
  1506. {
  1507. _il.EmitCall(OpCodes.Call, RuntimeServices_ToBool_Decimal, null);
  1508. return true;
  1509. }
  1510. if (TypeSystemServices.SingleType == type)
  1511. {
  1512. _il.EmitCall(OpCodes.Call, RuntimeServices_ToBool_Single, null);
  1513. return true;
  1514. }
  1515. if (TypeSystemServices.DoubleType == type)
  1516. {
  1517. _il.EmitCall(OpCodes.Call, RuntimeServices_ToBool_Double, null);
  1518. return true;
  1519. }
  1520. return false;
  1521. }
  1522. void EmitAnd(BinaryExpression node)
  1523. {
  1524. EmitLogicalOperator(node, OpCodes.Brtrue, OpCodes.Brfalse);
  1525. }
  1526. void EmitOr(BinaryExpression node)
  1527. {
  1528. EmitLogicalOperator(node, OpCodes.Brfalse, OpCodes.Brtrue);
  1529. }
  1530. void EmitLogicalOperator(BinaryExpression node, OpCode brForValueType, OpCode brForRefType)
  1531. {
  1532. IType type = GetExpressionType(node);
  1533. Visit(node.Left);
  1534. IType lhsType = PopType();
  1535. if (null != lhsType && lhsType.IsValueType && !type.IsValueType)
  1536. {
  1537. // if boxing, first evaluate the value
  1538. // as it is and then box it...
  1539. Label evalRhs = _il.DefineLabel();
  1540. Label end = _il.DefineLabel();
  1541. _il.Emit(OpCodes.Dup);
  1542. EmitToBoolIfNeeded(node.Left); // may need to convert decimal to bool
  1543. _il.Emit(brForValueType, evalRhs);
  1544. EmitCastIfNeeded(type, lhsType);
  1545. _il.Emit(OpCodes.Br, end);
  1546. _il.MarkLabel(evalRhs);
  1547. _il.Emit(OpCodes.Pop);
  1548. Visit(node.Right);
  1549. EmitCastIfNeeded(type, PopType());
  1550. _il.MarkLabel(end);
  1551. }
  1552. else
  1553. {
  1554. Label end = _il.DefineLabel();
  1555. EmitCastIfNeeded(type, lhsType);
  1556. _il.Emit(OpCodes.Dup);
  1557. EmitToBoolIfNeeded(node.Left);
  1558. _il.Emit(brForRefType, end);
  1559. _il.Emit(OpCodes.Pop);
  1560. Visit(node.Right);
  1561. EmitCastIfNeeded(type, PopType());
  1562. _il.MarkLabel(end);
  1563. }
  1564. PushType(type);
  1565. }
  1566. IType GetExpectedTypeForBitwiseRightOperand(BinaryExpression node)
  1567. {
  1568. switch (node.Operator)
  1569. {
  1570. // BOO-705
  1571. case BinaryOperatorType.ShiftLeft:
  1572. case BinaryOperatorType.ShiftRight:
  1573. return TypeSystemServices.IntType;
  1574. }
  1575. return GetExpressionType(node);
  1576. }
  1577. void EmitBitwiseOperator(BinaryExpression node)
  1578. {
  1579. IType type = node.ExpressionType;
  1580. Visit(node.Left);
  1581. EmitCastIfNeeded(type, PopType());
  1582. Visit(node.Right);
  1583. EmitCastIfNeeded(
  1584. GetExpectedTypeForBitwiseRightOperand(node),
  1585. PopType());
  1586. switch (node.Operator)
  1587. {
  1588. case BinaryOperatorType.BitwiseOr:
  1589. {
  1590. _il.Emit(OpCodes.Or);
  1591. break;
  1592. }
  1593. case BinaryOperatorType.BitwiseAnd:
  1594. {
  1595. _il.Emit(OpCodes.And);
  1596. break;
  1597. }
  1598. case BinaryOperatorType.ExclusiveOr:
  1599. {
  1600. _il.Emit(OpCodes.Xor);
  1601. break;
  1602. }
  1603. case BinaryOperatorType.ShiftLeft:
  1604. {
  1605. _il.Emit(OpCodes.Shl);
  1606. break;
  1607. }
  1608. case BinaryOperatorType.ShiftRight:
  1609. {
  1610. _il.Emit(OpCodes.Shr);
  1611. break;
  1612. }
  1613. }
  1614. PushType(type);
  1615. }
  1616. override public void OnBinaryExpression(BinaryExpression node)
  1617. {
  1618. switch (node.Operator)
  1619. {
  1620. case BinaryOperatorType.ShiftLeft:
  1621. case BinaryOperatorType.ShiftRight:
  1622. case BinaryOperatorType.ExclusiveOr:
  1623. case BinaryOperatorType.BitwiseAnd:
  1624. case BinaryOperatorType.BitwiseOr:
  1625. {
  1626. EmitBitwiseOperator(node);
  1627. break;
  1628. }
  1629. case BinaryOperatorType.Or:
  1630. {
  1631. EmitOr(node);
  1632. break;
  1633. }
  1634. case BinaryOperatorType.And:
  1635. {
  1636. EmitAnd(node);
  1637. break;
  1638. }
  1639. case BinaryOperatorType.Addition:
  1640. case BinaryOperatorType.Subtraction:
  1641. case BinaryOperatorType.Multiply:
  1642. case BinaryOperatorType.Division:
  1643. case BinaryOperatorType.Modulus:
  1644. {
  1645. OnArithmeticOperator(node);
  1646. break;
  1647. }
  1648. case BinaryOperatorType.Exponentiation:
  1649. {
  1650. OnExponentiation(node);
  1651. break;
  1652. }
  1653. case BinaryOperatorType.Assign:
  1654. {
  1655. OnAssignment(node);
  1656. break;
  1657. }
  1658. case BinaryOperatorType.Equality:
  1659. {
  1660. OnEquality(node);
  1661. break;
  1662. }
  1663. case BinaryOperatorType.Inequality:
  1664. {
  1665. OnInequality(node);
  1666. break;
  1667. }
  1668. case BinaryOperatorType.GreaterThan:
  1669. {
  1670. OnGreaterThan(node);
  1671. break;
  1672. }
  1673. case BinaryOperatorType.LessThan:
  1674. {
  1675. OnLessThan(node);
  1676. break;
  1677. }
  1678. case BinaryOperatorType.GreaterThanOrEqual:
  1679. {
  1680. OnGreaterThanOrEqual(node);
  1681. break;
  1682. }
  1683. case BinaryOperatorType.LessThanOrEqual:
  1684. {
  1685. OnLessThanOrEqual(node);
  1686. break;
  1687. }
  1688. case BinaryOperatorType.ReferenceInequality:
  1689. {
  1690. OnReferenceComparison(node);
  1691. break;
  1692. }
  1693. case BinaryOperatorType.ReferenceEquality:
  1694. {
  1695. OnReferenceComparison(node);
  1696. break;
  1697. }
  1698. case BinaryOperatorType.TypeTest:
  1699. {
  1700. OnTypeTest(node);
  1701. break;
  1702. }
  1703. default:
  1704. {
  1705. OperatorNotImplemented(node);
  1706. break;
  1707. }
  1708. }
  1709. }
  1710. void OperatorNotImplemented(BinaryExpression node)
  1711. {
  1712. NotImplemented(node, node.Operator.ToString());
  1713. }
  1714. override public void OnTypeofExpression(TypeofExpression node)
  1715. {
  1716. EmitGetTypeFromHandle(GetSystemType(node.Type));
  1717. }
  1718. override public void OnCastExpression(CastExpression node)
  1719. {
  1720. IType type = GetType(node.Type);
  1721. Visit(node.Target);
  1722. EmitCastIfNeeded(type, PopType());
  1723. PushType(type);
  1724. }
  1725. override public void OnTryCastExpression(TryCastExpression node)
  1726. {
  1727. Type type = GetSystemType(node.Type);
  1728. node.Target.Accept(this); PopType();
  1729. _il.Emit(OpCodes.Isinst, type);
  1730. PushType(node.ExpressionType);
  1731. }
  1732. void InvokeMethod(IMethod method, MethodInvocationExpression node)
  1733. {
  1734. MethodInfo mi = GetMethodInfo(method);
  1735. if (!InvokeOptimizedMethod(method, mi, node))
  1736. {
  1737. InvokeRegularMethod(method, mi, node);
  1738. }
  1739. }
  1740. bool InvokeOptimizedMethod(IMethod method, MethodInfo mi, MethodInvocationExpression node)
  1741. {
  1742. if (Builtins_ArrayTypedConstructor == mi)
  1743. {
  1744. // optimize constructs such as:
  1745. // array(int, 2)
  1746. IType type = TypeSystemServices.GetReferencedType(node.Arguments[0]);
  1747. if (null != type)
  1748. {
  1749. Visit(node.Arguments[1]);
  1750. EmitCastIfNeeded(TypeSystemServices.IntType, PopType());
  1751. _il.Emit(OpCodes.Newarr, GetSystemType(type));
  1752. PushType(TypeSystemServices.GetArrayType(type, 1));
  1753. return true;
  1754. }
  1755. }
  1756. else if (Builtins_ArrayTypedCollectionConstructor == mi)
  1757. {
  1758. // optimize constructs such as:

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