PageRenderTime 232ms CodeModel.GetById 20ms RepoModel.GetById 4ms app.codeStats 1ms

/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
  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:
  1759. // array(int, (1, 2, 3))
  1760. // array(byte, [1, 2, 3, 4])
  1761. IType type = TypeSystemServices.GetReferencedType(node.Arguments[0]);
  1762. if (null != type)
  1763. {
  1764. ListLiteralExpression items = node.Arguments[1] as ListLiteralExpression;
  1765. if (null != items)
  1766. {
  1767. EmitArray(type, items.Items);
  1768. PushType(TypeSystemServices.GetArrayType(type, 1));
  1769. return true;
  1770. }
  1771. }
  1772. }
  1773. return false;
  1774. }
  1775. void InvokeRegularMethod(IMethod method, MethodInfo mi, MethodInvocationExpression node)
  1776. {
  1777. // Do not emit call if conditional attributes (if any) do not match defined symbols
  1778. if (!CheckConditionalAttributes(method, mi))
  1779. {
  1780. EmitNop();
  1781. PushType(method.ReturnType); // keep a valid state
  1782. return;
  1783. }
  1784. IType targetType = null;
  1785. Expression target = null;
  1786. if (!mi.IsStatic)
  1787. {
  1788. target = GetTargetObject(node);
  1789. targetType = target.ExpressionType;
  1790. PushTargetObject(node, mi);
  1791. }
  1792. PushArguments(method, node.Arguments);
  1793. // Emit a constrained call if target is a generic parameter
  1794. if (targetType != null && targetType is IGenericParameter)
  1795. {
  1796. _il.Emit(OpCodes.Constrained, GetSystemType(targetType));
  1797. }
  1798. _il.EmitCall(GetCallOpCode(target, method), mi, null);
  1799. PushType(method.ReturnType);
  1800. }
  1801. //returns true if no conditional attribute match the defined symbols
  1802. //else return false (which means the method won't get emitted)
  1803. private bool CheckConditionalAttributes(IMethod method, MethodInfo mi)
  1804. {
  1805. if (method.ReturnType != TypeSystemServices.VoidType
  1806. || null != (method as GenericMappedMethod)) return true;
  1807. object[] attrs;
  1808. if (null != (method as InternalMethod) || (null != (method as GenericConstructedMethod) &&
  1809. null == (((GenericConstructedMethod)method).GenericDefinition as ExternalMethod)))
  1810. {
  1811. //internal methods
  1812. InternalMethod im = (method as InternalMethod) ?? ((method as GenericConstructedMethod).GenericDefinition as InternalMethod);
  1813. attrs = MetadataUtil.GetCustomAttributes(im.Method, TypeSystemServices.ConditionalAttribute);
  1814. if (0 == attrs.Length) return true;
  1815. foreach (Boo.Lang.Compiler.Ast.Attribute attr in attrs)
  1816. {
  1817. if (1 != attr.Arguments.Count || null == (attr.Arguments[0] as StringLiteralExpression)) continue;
  1818. string conditionString = (attr.Arguments[0] as StringLiteralExpression).Value;
  1819. if (!Parameters.Defines.ContainsKey(conditionString)) {
  1820. _context.TraceInfo("call to method '{0}' not emitted because the symbol '{1}' is not defined.", method.ToString(), conditionString);
  1821. return false;
  1822. }
  1823. }
  1824. } else {
  1825. //external methods
  1826. attrs = mi.GetCustomAttributes(typeof(System.Diagnostics.ConditionalAttribute), false);
  1827. if (0 == attrs.Length) return true;
  1828. foreach (System.Diagnostics.ConditionalAttribute attr in attrs)
  1829. {
  1830. if (!Parameters.Defines.ContainsKey(attr.ConditionString)) {
  1831. _context.TraceInfo("call to method '{0}' not emitted because the symbol '{1}' is not defined.", method.ToString(), attr.ConditionString);
  1832. return false;
  1833. }
  1834. }
  1835. }
  1836. return true;
  1837. }
  1838. private void PushTargetObject(MethodInvocationExpression node, MethodInfo mi)
  1839. {
  1840. Expression target = GetTargetObject(node);
  1841. IType targetType = target.ExpressionType;
  1842. // If target is a generic parameter, its address must be loaded
  1843. // to allow a constrained method call
  1844. if (targetType is IGenericParameter)
  1845. {
  1846. LoadAddress(target);
  1847. }
  1848. else if (targetType.IsValueType)
  1849. {
  1850. if (mi.DeclaringType.IsValueType)
  1851. {
  1852. LoadAddress(target);
  1853. }
  1854. else
  1855. {
  1856. Visit(node.Target);
  1857. EmitBox(PopType());
  1858. }
  1859. }
  1860. else
  1861. {
  1862. // pushes target reference
  1863. Visit(node.Target);
  1864. PopType();
  1865. }
  1866. }
  1867. private static Expression GetTargetObject(MethodInvocationExpression node)
  1868. {
  1869. Expression target = node.Target;
  1870. // Skip over generic reference expressions
  1871. GenericReferenceExpression genericRef = target as GenericReferenceExpression;
  1872. if (genericRef != null)
  1873. {
  1874. target = genericRef.Target;
  1875. }
  1876. MemberReferenceExpression memberRef = target as MemberReferenceExpression;
  1877. if (memberRef != null)
  1878. {
  1879. return memberRef.Target;
  1880. }
  1881. return null;
  1882. }
  1883. private OpCode GetCallOpCode(Expression target, IMethod method)
  1884. {
  1885. if (method.IsStatic) return OpCodes.Call;
  1886. if (NodeType.SuperLiteralExpression == target.NodeType) return OpCodes.Call;
  1887. if (IsValueTypeMethodCall(target, method)) return OpCodes.Call;
  1888. return OpCodes.Callvirt;
  1889. }
  1890. private bool IsValueTypeMethodCall(Expression target, IMethod method)
  1891. {
  1892. IType type = target.ExpressionType;
  1893. return type.IsValueType && method.DeclaringType == type;
  1894. }
  1895. void InvokeSuperMethod(IMethod methodInfo, MethodInvocationExpression node)
  1896. {
  1897. IMethod super = ((InternalMethod)methodInfo).Overriden;
  1898. MethodInfo superMI = GetMethodInfo(super);
  1899. if (methodInfo.DeclaringType.IsValueType)
  1900. {
  1901. _il.Emit(OpCodes.Ldarga_S, 0);
  1902. }
  1903. else
  1904. {
  1905. _il.Emit(OpCodes.Ldarg_0); // this
  1906. }
  1907. PushArguments(super, node.Arguments);
  1908. _il.EmitCall(OpCodes.Call, superMI, null);
  1909. PushType(super.ReturnType);
  1910. }
  1911. void EmitGetTypeFromHandle(Type type)
  1912. {
  1913. _il.Emit(OpCodes.Ldtoken, type);
  1914. _il.EmitCall(OpCodes.Call, Type_GetTypeFromHandle, null);
  1915. PushType(TypeSystemServices.TypeType);
  1916. }
  1917. void OnEval(MethodInvocationExpression node)
  1918. {
  1919. int allButLast = node.Arguments.Count-1;
  1920. for (int i=0; i<allButLast; ++i)
  1921. {
  1922. Visit(node.Arguments[i]);
  1923. DiscardValueOnStack();
  1924. }
  1925. Visit(node.Arguments[-1]);
  1926. }
  1927. void OnAddressOf(MethodInvocationExpression node)
  1928. {
  1929. MemberReferenceExpression methodRef = (MemberReferenceExpression)node.Arguments[0];
  1930. MethodInfo method = GetMethodInfo((IMethod)GetEntity(methodRef));
  1931. if (method.IsVirtual)
  1932. {
  1933. _il.Emit(OpCodes.Dup);
  1934. _il.Emit(OpCodes.Ldvirtftn, method);
  1935. }
  1936. else
  1937. {
  1938. _il.Emit(OpCodes.Ldftn, method);
  1939. }
  1940. PushType(TypeSystemServices.IntPtrType);
  1941. }
  1942. void OnBuiltinFunction(BuiltinFunction function, MethodInvocationExpression node)
  1943. {
  1944. switch (function.FunctionType)
  1945. {
  1946. case BuiltinFunctionType.Switch:
  1947. {
  1948. OnSwitch(node);
  1949. break;
  1950. }
  1951. case BuiltinFunctionType.AddressOf:
  1952. {
  1953. OnAddressOf(node);
  1954. break;
  1955. }
  1956. case BuiltinFunctionType.Eval:
  1957. {
  1958. OnEval(node);
  1959. break;
  1960. }
  1961. case BuiltinFunctionType.InitValueType:
  1962. {
  1963. OnInitValueType(node);
  1964. break;
  1965. }
  1966. default:
  1967. {
  1968. NotImplemented(node, "BuiltinFunction: " + function.FunctionType);
  1969. break;
  1970. }
  1971. }
  1972. }
  1973. private void OnInitValueType(MethodInvocationExpression node)
  1974. {
  1975. Debug.Assert(1 == node.Arguments.Count);
  1976. Expression argument = node.Arguments[0];
  1977. LoadAddressForInitObj(argument);
  1978. System.Type type = GetSystemType(GetExpressionType(argument));
  1979. Debug.Assert(type.IsValueType);
  1980. _il.Emit(OpCodes.Initobj, type);
  1981. PushVoid();
  1982. }
  1983. private void LoadAddressForInitObj(Expression argument)
  1984. {
  1985. IEntity entity = argument.Entity;
  1986. switch (entity.EntityType)
  1987. {
  1988. case EntityType.Local:
  1989. {
  1990. InternalLocal local = (InternalLocal)entity;
  1991. LocalBuilder builder = local.LocalBuilder;
  1992. _il.Emit(OpCodes.Ldloca, builder);
  1993. break;
  1994. }
  1995. case EntityType.Field:
  1996. {
  1997. EmitLoadFieldAddress(argument, (IField)entity);
  1998. break;
  1999. }
  2000. default:
  2001. NotImplemented(argument, "__initobj__");
  2002. break;
  2003. }
  2004. }
  2005. override public void OnMethodInvocationExpression(MethodInvocationExpression node)
  2006. {
  2007. IEntity tag = TypeSystemServices.GetEntity(node.Target);
  2008. switch (tag.EntityType)
  2009. {
  2010. case EntityType.BuiltinFunction:
  2011. {
  2012. OnBuiltinFunction((BuiltinFunction)tag, node);
  2013. break;
  2014. }
  2015. case EntityType.Method:
  2016. {
  2017. IMethod methodInfo = (IMethod)tag;
  2018. if (node.Target.NodeType == NodeType.SuperLiteralExpression)
  2019. {
  2020. InvokeSuperMethod(methodInfo, node);
  2021. }
  2022. else
  2023. {
  2024. InvokeMethod(methodInfo, node);
  2025. }
  2026. break;
  2027. }
  2028. case EntityType.Constructor:
  2029. {
  2030. IConstructor constructorInfo = (IConstructor)tag;
  2031. ConstructorInfo ci = GetConstructorInfo(constructorInfo);
  2032. if (NodeType.SuperLiteralExpression == node.Target.NodeType || node.Target.NodeType == NodeType.SelfLiteralExpression)
  2033. {
  2034. // super constructor call
  2035. _il.Emit(OpCodes.Ldarg_0);
  2036. PushArguments(constructorInfo, node.Arguments);
  2037. _il.Emit(OpCodes.Call, ci);
  2038. PushVoid();
  2039. }
  2040. else
  2041. {
  2042. PushArguments(constructorInfo, node.Arguments);
  2043. _il.Emit(OpCodes.Newobj, ci);
  2044. // constructor invocation resulting type is
  2045. PushType(constructorInfo.DeclaringType);
  2046. }
  2047. break;
  2048. }
  2049. default:
  2050. {
  2051. NotImplemented(node, tag.ToString());
  2052. break;
  2053. }
  2054. }
  2055. }
  2056. override public void OnTimeSpanLiteralExpression(TimeSpanLiteralExpression node)
  2057. {
  2058. _il.Emit(OpCodes.Ldc_I8, node.Value.Ticks);
  2059. _il.Emit(OpCodes.Newobj, TimeSpan_LongConstructor);
  2060. PushType(TypeSystemServices.TimeSpanType);
  2061. }
  2062. override public void OnIntegerLiteralExpression(IntegerLiteralExpression node)
  2063. {
  2064. if (node.IsLong)
  2065. {
  2066. _il.Emit(OpCodes.Ldc_I8, node.Value);
  2067. PushType(TypeSystemServices.LongType);
  2068. }
  2069. else
  2070. {
  2071. switch (node.Value)
  2072. {
  2073. case -1L: _il.Emit(OpCodes.Ldc_I4_M1); break;
  2074. case 0L: _il.Emit(OpCodes.Ldc_I4_0); break;
  2075. case 1L: _il.Emit(OpCodes.Ldc_I4_1); break;
  2076. case 2L: _il.Emit(OpCodes.Ldc_I4_2); break;
  2077. case 3L: _il.Emit(OpCodes.Ldc_I4_3); break;
  2078. case 4L: _il.Emit(OpCodes.Ldc_I4_4); break;
  2079. case 5L: _il.Emit(OpCodes.Ldc_I4_5); break;
  2080. case 6L: _il.Emit(OpCodes.Ldc_I4_6); break;
  2081. case 7L: _il.Emit(OpCodes.Ldc_I4_7); break;
  2082. case 8L: _il.Emit(OpCodes.Ldc_I4_8); break;
  2083. default:
  2084. {
  2085. _il.Emit(OpCodes.Ldc_I4, (int)node.Value);
  2086. break;
  2087. }
  2088. }
  2089. PushType(TypeSystemServices.IntType);
  2090. }
  2091. }
  2092. override public void OnDoubleLiteralExpression(DoubleLiteralExpression node)
  2093. {
  2094. if (node.IsSingle)
  2095. {
  2096. _il.Emit(OpCodes.Ldc_R4, (float)node.Value);
  2097. PushType(TypeSystemServices.SingleType);
  2098. }
  2099. else
  2100. {
  2101. _il.Emit(OpCodes.Ldc_R8, node.Value);
  2102. PushType(TypeSystemServices.DoubleType);
  2103. }
  2104. }
  2105. override public void OnBoolLiteralExpression(BoolLiteralExpression node)
  2106. {
  2107. if (node.Value)
  2108. {
  2109. _il.Emit(OpCodes.Ldc_I4_1);
  2110. }
  2111. else
  2112. {
  2113. _il.Emit(OpCodes.Ldc_I4_0);
  2114. }
  2115. PushBool();
  2116. }
  2117. override public void OnHashLiteralExpression(HashLiteralExpression node)
  2118. {
  2119. _il.Emit(OpCodes.Newobj, Hash_Constructor);
  2120. IType objType = TypeSystemServices.ObjectType;
  2121. foreach (ExpressionPair pair in node.Items)
  2122. {
  2123. _il.Emit(OpCodes.Dup);
  2124. Visit(pair.First);
  2125. EmitCastIfNeeded(objType, PopType());
  2126. Visit(pair.Second);
  2127. EmitCastIfNeeded(objType, PopType());
  2128. _il.EmitCall(OpCodes.Callvirt, Hash_Add, null);
  2129. }
  2130. PushType(TypeSystemServices.HashType);
  2131. }
  2132. override public void OnGeneratorExpression(GeneratorExpression node)
  2133. {
  2134. NotImplemented(node, node.ToString());
  2135. }
  2136. override public void OnListLiteralExpression(ListLiteralExpression node)
  2137. {
  2138. if (node.Items.Count > 0)
  2139. {
  2140. EmitObjectArray(node.Items);
  2141. _il.Emit(OpCodes.Ldc_I4_1);
  2142. _il.Emit(OpCodes.Newobj, List_ArrayBoolConstructor);
  2143. }
  2144. else
  2145. {
  2146. _il.Emit(OpCodes.Newobj, List_EmptyConstructor);
  2147. }
  2148. PushType(TypeSystemServices.ListType);
  2149. }
  2150. override public void OnArrayLiteralExpression(ArrayLiteralExpression node)
  2151. {
  2152. IArrayType type = (IArrayType)node.ExpressionType;
  2153. EmitArray(type.GetElementType(), node.Items);
  2154. PushType(type);
  2155. }
  2156. override public void OnRELiteralExpression(RELiteralExpression node)
  2157. {
  2158. _il.Emit(OpCodes.Ldstr, RuntimeServices.Mid(node.Value, 1, -1));
  2159. _il.Emit(OpCodes.Newobj, Regex_Constructor);
  2160. PushType(node.ExpressionType);
  2161. }
  2162. override public void OnStringLiteralExpression(StringLiteralExpression node)
  2163. {
  2164. if (0 != node.Value.Length)
  2165. {
  2166. _il.Emit(OpCodes.Ldstr, node.Value);
  2167. }
  2168. else /* force use of CLR-friendly string.Empty */
  2169. {
  2170. _il.Emit(OpCodes.Ldsfld, typeof(string).GetField("Empty"));
  2171. }
  2172. PushType(TypeSystemServices.StringType);
  2173. }
  2174. override public void OnCharLiteralExpression(CharLiteralExpression node)
  2175. {
  2176. _il.Emit(OpCodes.Ldc_I4, node.Value[0]);
  2177. PushType(TypeSystemServices.CharType);
  2178. }
  2179. override public void OnSlicingExpression(SlicingExpression node)
  2180. {
  2181. if (AstUtil.IsLhsOfAssignment(node))
  2182. {
  2183. return;
  2184. }
  2185. Visit(node.Target);
  2186. IArrayType type = (IArrayType)PopType();
  2187. EmitNormalizedArrayIndex(node, node.Indices[0].Begin);
  2188. IType elementType = type.GetElementType();
  2189. OpCode opcode = GetLoadEntityOpCode(elementType);
  2190. if (OpCodes.Ldelema.Value == opcode.Value)
  2191. {
  2192. Type systemType = GetSystemType(elementType);
  2193. _il.Emit(opcode, systemType);
  2194. _il.Emit(OpCodes.Ldobj, systemType);
  2195. }
  2196. else if (OpCodes.Ldelem.Value == opcode.Value)
  2197. {
  2198. _il.Emit(opcode, GetSystemType(elementType));
  2199. }
  2200. else
  2201. {
  2202. _il.Emit(opcode);
  2203. }
  2204. PushType(elementType);
  2205. }
  2206. void EmitNormalizedArrayIndex(SlicingExpression sourceNode, Expression index)
  2207. {
  2208. bool isNegative = false;
  2209. if (CanBeNegative(index, ref isNegative)
  2210. && !_rawArrayIndexing
  2211. && !AstAnnotations.IsRawIndexing(sourceNode))
  2212. {
  2213. if (isNegative)
  2214. {
  2215. _il.Emit(OpCodes.Dup);
  2216. _il.Emit(OpCodes.Ldlen);
  2217. EmitLoadInt(index);
  2218. _il.Emit(OpCodes.Add);
  2219. }
  2220. else
  2221. {
  2222. _il.Emit(OpCodes.Dup);
  2223. EmitLoadInt(index);
  2224. _il.EmitCall(OpCodes.Call, RuntimeServices_NormalizeArrayIndex, null);
  2225. }
  2226. }
  2227. else
  2228. {
  2229. EmitLoadInt(index);
  2230. }
  2231. }
  2232. bool CanBeNegative(Expression expression, ref bool isNegative)
  2233. {
  2234. IntegerLiteralExpression integer = expression as IntegerLiteralExpression;
  2235. if (null != integer)
  2236. {
  2237. if (integer.Value >= 0)
  2238. {
  2239. return false;
  2240. }
  2241. isNegative = true;
  2242. }
  2243. return true;
  2244. }
  2245. void EmitLoadInt(Expression expression)
  2246. {
  2247. Visit(expression);
  2248. EmitCastIfNeeded(TypeSystemServices.IntType, PopType());
  2249. }
  2250. override public void OnExpressionInterpolationExpression(ExpressionInterpolationExpression node)
  2251. {
  2252. Type stringBuilderType = typeof(StringBuilder);
  2253. ConstructorInfo constructor = stringBuilderType.GetConstructor(new Type[0]);
  2254. ConstructorInfo constructorString = stringBuilderType.GetConstructor(new Type[] { typeof(string) });
  2255. MethodInfo appendObject = stringBuilderType.GetMethod("Append", new Type[] { typeof(object) });
  2256. MethodInfo appendString = stringBuilderType.GetMethod("Append", new Type[] { typeof(string) });
  2257. Expression arg0 = node.Expressions[0];
  2258. IType argType = arg0.ExpressionType;
  2259. /* if arg0 is a string, let's call StringBuilder constructor
  2260. * directly with the string */
  2261. if ( ( typeof(StringLiteralExpression) == arg0.GetType()
  2262. && ((StringLiteralExpression) arg0).Value.Length > 0 )
  2263. || ( typeof(StringLiteralExpression) != arg0.GetType()
  2264. && TypeSystemServices.StringType == argType ) )
  2265. {
  2266. Visit(arg0);
  2267. PopType();
  2268. _il.Emit(OpCodes.Newobj, constructorString);
  2269. }
  2270. else
  2271. {
  2272. _il.Emit(OpCodes.Newobj, constructor);
  2273. arg0 = null; /* arg0 is not a string so we want it to be appended below */
  2274. }
  2275. foreach (Expression arg in node.Expressions)
  2276. {
  2277. /* we do not need to append literal string.Empty
  2278. * or arg0 if it has been handled by ctor */
  2279. if ( ( typeof(StringLiteralExpression) == arg.GetType()
  2280. && ((StringLiteralExpression) arg).Value.Length == 0 )
  2281. || arg == arg0 )
  2282. {
  2283. continue;
  2284. }
  2285. Visit(arg);
  2286. argType = PopType();
  2287. if (TypeSystemServices.StringType == argType)
  2288. {
  2289. _il.EmitCall(OpCodes.Call, appendString, null);
  2290. }
  2291. else
  2292. {
  2293. EmitCastIfNeeded(TypeSystemServices.ObjectType, argType);
  2294. _il.EmitCall(OpCodes.Call, appendObject, null);
  2295. }
  2296. }
  2297. _il.EmitCall(OpCodes.Call, stringBuilderType.GetMethod("ToString", new Type[0]), null);
  2298. PushType(TypeSystemServices.StringType);
  2299. }
  2300. void LoadMemberTarget(Expression self, IMember member)
  2301. {
  2302. if (member.DeclaringType.IsValueType)
  2303. {
  2304. LoadAddress(self);
  2305. }
  2306. else
  2307. {
  2308. Visit(self);
  2309. PopType();
  2310. }
  2311. }
  2312. void EmitLoadFieldAddress(Expression expression, IField field)
  2313. {
  2314. if (field.IsStatic)
  2315. {
  2316. _il.Emit(OpCodes.Ldsflda, GetFieldInfo(field));
  2317. }
  2318. else
  2319. {
  2320. LoadMemberTarget(((MemberReferenceExpression)expression).Target, field);
  2321. _il.Emit(OpCodes.Ldflda, GetFieldInfo(field));
  2322. }
  2323. }
  2324. void EmitLoadField(Expression self, IField fieldInfo)
  2325. {
  2326. if (fieldInfo.IsStatic)
  2327. {
  2328. if (fieldInfo.IsLiteral)
  2329. {
  2330. EmitLoadLiteralField(self, fieldInfo);
  2331. }
  2332. else
  2333. {
  2334. _il.Emit(OpCodes.Ldsfld, GetFieldInfo(fieldInfo));
  2335. }
  2336. }
  2337. else
  2338. {
  2339. LoadMemberTarget(self, fieldInfo);
  2340. _il.Emit(OpCodes.Ldfld, GetFieldInfo(fieldInfo));
  2341. }
  2342. PushType(fieldInfo.Type);
  2343. }
  2344. object GetStaticValue(IField field)
  2345. {
  2346. InternalField internalField = field as InternalField;
  2347. if (null != internalField)
  2348. {
  2349. return GetInternalFieldStaticValue(internalField);
  2350. }
  2351. return field.StaticValue;
  2352. }
  2353. object GetInternalFieldStaticValue(InternalField field)
  2354. {
  2355. return GetValue(field.Type, (Expression)field.StaticValue);
  2356. }
  2357. void EmitLoadLiteralField(Node node, IField fieldInfo)
  2358. {
  2359. object value = GetStaticValue(fieldInfo);
  2360. if (null == value)
  2361. {
  2362. _il.Emit(OpCodes.Ldnull);
  2363. }
  2364. else
  2365. {
  2366. TypeCode type = Type.GetTypeCode(value.GetType());
  2367. switch (type)
  2368. {
  2369. case TypeCode.Byte:
  2370. {
  2371. _il.Emit(OpCodes.Ldc_I4, (int)(byte)value);
  2372. _il.Emit(OpCodes.Conv_U1);
  2373. break;
  2374. }
  2375. case TypeCode.SByte:
  2376. {
  2377. _il.Emit(OpCodes.Ldc_I4, (int)(sbyte)value);
  2378. _il.Emit(OpCodes.Conv_I1);
  2379. break;
  2380. }
  2381. case TypeCode.Char:
  2382. {
  2383. _il.Emit(OpCodes.Ldc_I4, (int)(char)value);
  2384. break;
  2385. }
  2386. case TypeCode.Int16:
  2387. {
  2388. _il.Emit(OpCodes.Ldc_I4, (int)(short)value);
  2389. break;
  2390. }
  2391. case TypeCode.UInt16:
  2392. {
  2393. _il.Emit(OpCodes.Ldc_I4, (int)(ushort)value);
  2394. break;
  2395. }
  2396. case TypeCode.Int32:
  2397. {
  2398. _il.Emit(OpCodes.Ldc_I4, (int)value);
  2399. break;
  2400. }
  2401. case TypeCode.UInt32:
  2402. {
  2403. uint uValue = (uint)value;
  2404. _il.Emit(OpCodes.Ldc_I4, unchecked((int)uValue));
  2405. _il.Emit(OpCodes.Conv_U4);
  2406. break;
  2407. }
  2408. case TypeCode.Int64:
  2409. {
  2410. _il.Emit(OpCodes.Ldc_I8, (long)value);
  2411. break;
  2412. }
  2413. case TypeCode.UInt64:
  2414. {
  2415. ulong uValue = (ulong)value;
  2416. _il.Emit(OpCodes.Ldc_I8, unchecked((long)uValue));
  2417. _il.Emit(OpCodes.Conv_U8);
  2418. break;
  2419. }
  2420. case TypeCode.Single:
  2421. {
  2422. _il.Emit(OpCodes.Ldc_R4, (float)value);
  2423. break;
  2424. }
  2425. case TypeCode.Double:
  2426. {
  2427. _il.Emit(OpCodes.Ldc_R8, (double)value);
  2428. break;
  2429. }
  2430. case TypeCode.String:
  2431. {
  2432. _il.Emit(OpCodes.Ldstr, (string)value);
  2433. break;
  2434. }
  2435. default:
  2436. {
  2437. NotImplemented(node, "Literal: " + type.ToString());
  2438. break;
  2439. }
  2440. }
  2441. }
  2442. }
  2443. override public void OnGenericReferenceExpression(GenericReferenceExpression node)
  2444. {
  2445. IEntity tag = TypeSystem.TypeSystemServices.GetEntity(node);
  2446. switch (tag.EntityType)
  2447. {
  2448. case EntityType.Type:
  2449. {
  2450. EmitGetTypeFromHandle(GetSystemType(node));
  2451. break;
  2452. }
  2453. case EntityType.Method:
  2454. {
  2455. node.Target.Accept(this);
  2456. break;
  2457. }
  2458. default:
  2459. {
  2460. NotImplemented(node, tag.ToString());
  2461. break;
  2462. }
  2463. }
  2464. }
  2465. override public void OnMemberReferenceExpression(MemberReferenceExpression node)
  2466. {
  2467. IEntity tag = TypeSystem.TypeSystemServices.GetEntity(node);
  2468. switch (tag.EntityType)
  2469. {
  2470. case EntityType.Ambiguous:
  2471. case EntityType.Method:
  2472. {
  2473. node.Target.Accept(this);
  2474. break;
  2475. }
  2476. case EntityType.Field:
  2477. {
  2478. EmitLoadField(node.Target, (IField)tag);
  2479. break;
  2480. }
  2481. case EntityType.Type:
  2482. {
  2483. EmitGetTypeFromHandle(GetSystemType(node));
  2484. break;
  2485. }
  2486. default:
  2487. {
  2488. NotImplemented(node, tag.ToString());
  2489. break;
  2490. }
  2491. }
  2492. }
  2493. void LoadAddress(Expression expression)
  2494. {
  2495. if (NodeType.SelfLiteralExpression == expression.NodeType)
  2496. {
  2497. if (expression.ExpressionType.IsValueType)
  2498. {
  2499. _il.Emit(OpCodes.Ldarg_0);
  2500. return;
  2501. }
  2502. }
  2503. IEntity tag = expression.Entity;
  2504. if (null != tag)
  2505. {
  2506. switch (tag.EntityType)
  2507. {
  2508. case EntityType.Local:
  2509. {
  2510. _il.Emit(OpCodes.Ldloca, ((InternalLocal)tag).LocalBuilder);
  2511. return;
  2512. }
  2513. case EntityType.Parameter:
  2514. {
  2515. InternalParameter param = (InternalParameter)tag;
  2516. if (param.Parameter.IsByRef)
  2517. {
  2518. LoadParam(param);
  2519. }
  2520. else
  2521. {
  2522. _il.Emit(OpCodes.Ldarga, param.Index);
  2523. }
  2524. return;
  2525. }
  2526. case EntityType.Field:
  2527. {
  2528. IField field = (IField)tag;
  2529. if (!field.IsLiteral)
  2530. {
  2531. EmitLoadFieldAddress(expression, field);
  2532. return;
  2533. }
  2534. break;
  2535. }
  2536. }
  2537. }
  2538. if (IsValueTypeArraySlicing(expression))
  2539. {
  2540. SlicingExpression slicing = (SlicingExpression)expression;
  2541. Visit(slicing.Target);
  2542. IArrayType arrayType = (IArrayType)PopType();
  2543. EmitNormalizedArrayIndex(slicing, slicing.Indices[0].Begin);
  2544. _il.Emit(OpCodes.Ldelema, GetSystemType(arrayType.GetElementType()));
  2545. }
  2546. else
  2547. {
  2548. // declare local to hold value type
  2549. Visit(expression);
  2550. LocalBuilder temp = _il.DeclareLocal(GetSystemType(PopType()));
  2551. _il.Emit(OpCodes.Stloc, temp);
  2552. _il.Emit(OpCodes.Ldloca, temp);
  2553. }
  2554. }
  2555. bool IsValueTypeArraySlicing(Expression expression)
  2556. {
  2557. SlicingExpression slicing = expression as SlicingExpression;
  2558. if (null != slicing)
  2559. {
  2560. IArrayType type = (IArrayType)slicing.Target.ExpressionType;
  2561. return type.GetElementType().IsValueType;
  2562. }
  2563. return false;
  2564. }
  2565. override public void OnSelfLiteralExpression(SelfLiteralExpression node)
  2566. {
  2567. _il.Emit(OpCodes.Ldarg_0);
  2568. if (node.ExpressionType.IsValueType)
  2569. {
  2570. _il.Emit(OpCodes.Ldobj, GetSystemType(node.ExpressionType));
  2571. }
  2572. PushType(node.ExpressionType);
  2573. }
  2574. override public void OnSuperLiteralExpression(SuperLiteralExpression node)
  2575. {
  2576. _il.Emit(OpCodes.Ldarg_0);
  2577. if (node.ExpressionType.IsValueType)
  2578. {
  2579. _il.Emit(OpCodes.Ldobj, GetSystemType(node.ExpressionType));
  2580. }
  2581. PushType(node.ExpressionType);
  2582. }
  2583. override public void OnNullLiteralExpression(NullLiteralExpression node)
  2584. {
  2585. _il.Emit(OpCodes.Ldnull);
  2586. PushType(null);
  2587. }
  2588. override public void OnReferenceExpression(ReferenceExpression node)
  2589. {
  2590. IEntity info = TypeSystem.TypeSystemServices.GetEntity(node);
  2591. switch (info.EntityType)
  2592. {
  2593. case EntityType.Local:
  2594. {
  2595. InternalLocal local = (InternalLocal)info;
  2596. LocalBuilder builder = local.LocalBuilder;
  2597. _il.Emit(OpCodes.Ldloc, builder);
  2598. PushType(local.Type);
  2599. break;
  2600. }
  2601. case EntityType.Parameter:
  2602. {
  2603. InternalParameter param = (InternalParameter)info;
  2604. LoadParam(param);
  2605. if (param.Parameter.IsByRef)
  2606. {
  2607. OpCode code = GetLoadRefParamCode(param.Type);
  2608. if (code.Value == OpCodes.Ldobj.Value)
  2609. {
  2610. _il.Emit(code, GetSystemType(param.Type));
  2611. }
  2612. else {
  2613. _il.Emit(code);
  2614. }
  2615. }
  2616. PushType(param.Type);
  2617. break;
  2618. }
  2619. case EntityType.Array:
  2620. case EntityType.Type:
  2621. {
  2622. EmitGetTypeFromHandle(GetSystemType(node));
  2623. break;
  2624. }
  2625. default:
  2626. {
  2627. NotImplemented(node, info.ToString());
  2628. break;
  2629. }
  2630. }
  2631. }
  2632. void LoadParam(InternalParameter param)
  2633. {
  2634. int index = param.Index;
  2635. switch (index)
  2636. {
  2637. case 0:
  2638. {
  2639. _il.Emit(OpCodes.Ldarg_0);
  2640. break;
  2641. }
  2642. case 1:
  2643. {
  2644. _il.Emit(OpCodes.Ldarg_1);
  2645. break;
  2646. }
  2647. case 2:
  2648. {
  2649. _il.Emit(OpCodes.Ldarg_2);
  2650. break;
  2651. }
  2652. case 3:
  2653. {
  2654. _il.Emit(OpCodes.Ldarg_3);
  2655. break;
  2656. }
  2657. default:
  2658. {
  2659. if (index < 256)
  2660. {
  2661. _il.Emit(OpCodes.Ldarg_S, index);
  2662. }
  2663. else
  2664. {
  2665. _il.Emit(OpCodes.Ldarg, index);
  2666. }
  2667. break;
  2668. }
  2669. }
  2670. }
  2671. void SetLocal(BinaryExpression node, InternalLocal tag, bool leaveValueOnStack)
  2672. {
  2673. node.Right.Accept(this); // leaves type on stack
  2674. IType typeOnStack = null;
  2675. if (leaveValueOnStack)
  2676. {
  2677. typeOnStack = PeekTypeOnStack();
  2678. _il.Emit(OpCodes.Dup);
  2679. }
  2680. else
  2681. {
  2682. typeOnStack = PopType();
  2683. }
  2684. EmitAssignment(tag, typeOnStack);
  2685. }
  2686. void EmitAssignment(InternalLocal tag, IType typeOnStack)
  2687. {
  2688. // todo: assignment result must be type on the left in the
  2689. // case of casting
  2690. LocalBuilder local = tag.LocalBuilder;
  2691. EmitCastIfNeeded(tag.Type, typeOnStack);
  2692. _il.Emit(OpCodes.Stloc, local);
  2693. }
  2694. void SetField(Node sourceNode, IField field, Expression reference, Expression value, bool leaveValueOnStack)
  2695. {
  2696. OpCode opSetField = OpCodes.Stsfld;
  2697. if (!field.IsStatic)
  2698. {
  2699. opSetField = OpCodes.Stfld;
  2700. if (null != reference)
  2701. {
  2702. LoadMemberTarget(
  2703. ((MemberReferenceExpression)reference).Target,
  2704. field);
  2705. }
  2706. }
  2707. value.Accept(this);
  2708. EmitCastIfNeeded(field.Type, PopType());
  2709. LocalBuilder local = null;
  2710. if (leaveValueOnStack)
  2711. {
  2712. _il.Emit(OpCodes.Dup);
  2713. local = _il.DeclareLocal(GetSystemType(field.Type));
  2714. _il.Emit(OpCodes.Stloc, local);
  2715. }
  2716. _il.Emit(opSetField, GetFieldInfo(field));
  2717. if (leaveValueOnStack)
  2718. {
  2719. _il.Emit(OpCodes.Ldloc, local);
  2720. PushType(field.Type);
  2721. }
  2722. }
  2723. void SetProperty(Node sourceNode, IProperty property, Expression reference, Expression value, bool leaveValueOnStack)
  2724. {
  2725. OpCode callOpCode = OpCodes.Call;
  2726. MethodInfo setMethod = GetMethodInfo(property.GetSetMethod());
  2727. if (null != reference)
  2728. {
  2729. if (!setMethod.IsStatic)
  2730. {
  2731. Expression target = ((MemberReferenceExpression)reference).Target;
  2732. if (setMethod.DeclaringType.IsValueType)
  2733. {
  2734. LoadAddress(target);
  2735. }
  2736. else
  2737. {
  2738. callOpCode = GetCallOpCode(target, property.GetSetMethod());
  2739. target.Accept(this);
  2740. PopType();
  2741. }
  2742. }
  2743. }
  2744. value.Accept(this);
  2745. EmitCastIfNeeded(property.Type, PopType());
  2746. LocalBuilder local = null;
  2747. if (leaveValueOnStack)
  2748. {
  2749. _il.Emit(OpCodes.Dup);
  2750. local = _il.DeclareLocal(GetSystemType(property.Type));
  2751. _il.Emit(OpCodes.Stloc, local);
  2752. }
  2753. _il.EmitCall(callOpCode, setMethod, null);
  2754. if (leaveValueOnStack)
  2755. {
  2756. _il.Emit(OpCodes.Ldloc, local);
  2757. PushType(property.Type);
  2758. }
  2759. }
  2760. bool EmitDebugInfo(Node node)
  2761. {
  2762. return EmitDebugInfo(node, node);
  2763. }
  2764. private const int _DBG_SYMBOLS_QUEUE_CAPACITY = 5;
  2765. private System.Collections.Generic.Queue<LexicalInfo> _dbgSymbols = new System.Collections.Generic.Queue<LexicalInfo>(_DBG_SYMBOLS_QUEUE_CAPACITY);
  2766. bool EmitDebugInfo(Node startNode, Node endNode)
  2767. {
  2768. if (!Parameters.Debug) return false;
  2769. LexicalInfo start = startNode.LexicalInfo;
  2770. if (!start.IsValid) return false;
  2771. ISymbolDocumentWriter writer = GetDocumentWriter(start.FullPath);
  2772. if (null == writer) return false;
  2773. // ensure there is no duplicate emitted
  2774. if (_dbgSymbols.Contains(start)) {
  2775. _context.TraceInfo("duplicate symbol emit attempt for '{0}' : '{1}'.", start.ToString(), startNode.ToString());
  2776. return false;
  2777. }
  2778. if (_dbgSymbols.Count >= _DBG_SYMBOLS_QUEUE_CAPACITY) _dbgSymbols.Dequeue();
  2779. _dbgSymbols.Enqueue(start);
  2780. try
  2781. {
  2782. _il.MarkSequencePoint(writer, start.Line, 0, start.Line+1, 0);
  2783. }
  2784. catch (Exception x)
  2785. {
  2786. Error(CompilerErrorFactory.InternalError(startNode, x));
  2787. return false;
  2788. }
  2789. return true;
  2790. }
  2791. private void EmitNop()
  2792. {
  2793. _il.Emit(OpCodes.Nop);
  2794. }
  2795. private ISymbolDocumentWriter GetDocumentWriter(string fname)
  2796. {
  2797. ISymbolDocumentWriter writer = GetCachedDocumentWriter(fname);
  2798. if (null != writer) return writer;
  2799. writer = _moduleBuilder.DefineDocument(
  2800. fname,
  2801. Guid.Empty,
  2802. Guid.Empty,
  2803. SymDocumentType.Text);
  2804. _symbolDocWriters.Add(fname, writer);
  2805. return writer;
  2806. }
  2807. private ISymbolDocumentWriter GetCachedDocumentWriter(string fname)
  2808. {
  2809. return (ISymbolDocumentWriter) _symbolDocWriters[fname];
  2810. }
  2811. bool IsBoolOrInt(IType type)
  2812. {
  2813. return TypeSystemServices.BoolType == type ||
  2814. TypeSystemServices.IntType == type;
  2815. }
  2816. void PushArguments(IMethodBase entity, ExpressionCollection args)
  2817. {
  2818. IParameter[] parameters = entity.GetParameters();
  2819. for (int i=0; i<args.Count; ++i)
  2820. {
  2821. IType parameterType = parameters[i].Type;
  2822. Expression arg = args[i];
  2823. /*
  2824. InternalParameter internalparam = parameters[i] as InternalParameter;
  2825. if ((parameterType.IsByRef) ||
  2826. (internalparam != null &&
  2827. internalparam.Parameter.IsByRef)
  2828. )
  2829. */
  2830. if (parameters[i].IsByRef)
  2831. {
  2832. LoadAddress(arg);
  2833. }
  2834. else
  2835. {
  2836. arg.Accept(this);
  2837. EmitCastIfNeeded(parameterType, PopType());
  2838. }
  2839. }
  2840. }
  2841. void EmitObjectArray(ExpressionCollection items)
  2842. {
  2843. EmitArray(TypeSystemServices.ObjectType, items);
  2844. }
  2845. void EmitArray(IType type, ExpressionCollection items)
  2846. {
  2847. _il.Emit(OpCodes.Ldc_I4, items.Count);
  2848. _il.Emit(OpCodes.Newarr, GetSystemType(type));
  2849. OpCode opcode = GetStoreEntityOpCode(type);
  2850. for (int i=0; i<items.Count; ++i)
  2851. {
  2852. StoreEntity(opcode, i, items[i], type);
  2853. }
  2854. }
  2855. bool IsInteger(IType type)
  2856. {
  2857. return type == TypeSystemServices.IntType ||
  2858. type == TypeSystemServices.LongType ||
  2859. type == TypeSystemServices.ByteType;
  2860. }
  2861. MethodInfo GetToDecimalConversionMethod(IType type)
  2862. {
  2863. MethodInfo method =
  2864. typeof(Decimal).GetMethod("op_Implicit", new Type[] { GetSystemType(type) });
  2865. if (method == null)
  2866. {
  2867. method =
  2868. typeof(Decimal).GetMethod("op_Explicit", new Type[] { GetSystemType(type) });
  2869. if (method == null)
  2870. {
  2871. NotImplemented(string.Format("Numeric promotion for {0} to decimal not implemented!", type));
  2872. }
  2873. }
  2874. return method;
  2875. }
  2876. MethodInfo GetFromDecimalConversionMethod(IType type)
  2877. {
  2878. string toType = "To" + type.Name;
  2879. MethodInfo method =
  2880. typeof(Decimal).GetMethod(toType, new Type[] { typeof(Decimal) });
  2881. if (method == null)
  2882. {
  2883. NotImplemented(string.Format("Numeric promotion for decimal to {0} not implemented!", type));
  2884. }
  2885. return method;
  2886. }
  2887. OpCode GetArithmeticOpCode(IType type, BinaryOperatorType op)
  2888. {
  2889. if (IsInteger(type) && _checked)
  2890. {
  2891. switch (op)
  2892. {
  2893. case BinaryOperatorType.Addition: return OpCodes.Add_Ovf;
  2894. case BinaryOperatorType.Subtraction: return OpCodes.Sub_Ovf;
  2895. case BinaryOperatorType.Multiply: return OpCodes.Mul_Ovf;
  2896. case BinaryOperatorType.Division: return OpCodes.Div;
  2897. case BinaryOperatorType.Modulus: return OpCodes.Rem;
  2898. }
  2899. }
  2900. else
  2901. {
  2902. switch (op)
  2903. {
  2904. case BinaryOperatorType.Addition: return OpCodes.Add;
  2905. case BinaryOperatorType.Subtraction: return OpCodes.Sub;
  2906. case BinaryOperatorType.Multiply: return OpCodes.Mul;
  2907. case BinaryOperatorType.Division: return OpCodes.Div;
  2908. case BinaryOperatorType.Modulus: return OpCodes.Rem;
  2909. }
  2910. }
  2911. throw new ArgumentException("op");
  2912. }
  2913. OpCode GetLoadEntityOpCode(IType type)
  2914. {
  2915. if (!type.IsValueType)
  2916. {
  2917. return type is IGenericParameter
  2918. ? OpCodes.Ldelem
  2919. : OpCodes.Ldelem_Ref;
  2920. }
  2921. if (TypeSystemServices.IntType == type ||
  2922. type.IsEnum)
  2923. {
  2924. return OpCodes.Ldelem_I4;
  2925. }
  2926. if (TypeSystemServices.UIntType == type)
  2927. {
  2928. return OpCodes.Ldelem_U4;
  2929. }
  2930. if (TypeSystemServices.LongType == type)
  2931. {
  2932. return OpCodes.Ldelem_I8;
  2933. }
  2934. if (TypeSystemServices.SByteType == type)
  2935. {
  2936. return OpCodes.Ldelem_I1;
  2937. }
  2938. if (TypeSystemServices.ByteType == type)
  2939. {
  2940. return OpCodes.Ldelem_U1;
  2941. }
  2942. if (TypeSystemServices.ShortType == type ||
  2943. TypeSystemServices.CharType == type)
  2944. {
  2945. return OpCodes.Ldelem_I2;
  2946. }
  2947. if (TypeSystemServices.UShortType == type)
  2948. {
  2949. return OpCodes.Ldelem_U2;
  2950. }
  2951. if (TypeSystemServices.SingleType == type)
  2952. {
  2953. return OpCodes.Ldelem_R4;
  2954. }
  2955. if (TypeSystemServices.DoubleType == type)
  2956. {
  2957. return OpCodes.Ldelem_R8;
  2958. }
  2959. //NotImplemented("LoadEntityOpCode(" + tag + ")");
  2960. return OpCodes.Ldelema;
  2961. }
  2962. OpCode GetStoreEntityOpCode(IType tag)
  2963. {
  2964. if (tag.IsValueType)
  2965. {
  2966. if (TypeSystemServices.IntType == tag ||
  2967. tag.IsEnum)
  2968. {
  2969. return OpCodes.Stelem_I4;
  2970. }
  2971. if (TypeSystemServices.LongType == tag)
  2972. {
  2973. return OpCodes.Stelem_I8;
  2974. }
  2975. if (TypeSystemServices.ByteType == tag)
  2976. {
  2977. return OpCodes.Stelem_I1;
  2978. }
  2979. if (TypeSystemServices.ShortType == tag ||
  2980. TypeSystemServices.CharType == tag)
  2981. {
  2982. return OpCodes.Stelem_I2;
  2983. }
  2984. if (TypeSystemServices.SingleType == tag)
  2985. {
  2986. return OpCodes.Stelem_R4;
  2987. }
  2988. if (TypeSystemServices.DoubleType == tag)
  2989. {
  2990. return OpCodes.Stelem_R8;
  2991. }
  2992. //NotImplemented("GetStoreEntityOpCode(" + tag + ")");
  2993. return OpCodes.Stobj;
  2994. }
  2995. return OpCodes.Stelem_Ref;
  2996. }
  2997. OpCode GetLoadRefParamCode(IType tag)
  2998. {
  2999. if (tag.IsValueType)
  3000. {
  3001. if (TypeSystemServices.IntType == tag ||
  3002. tag.IsEnum)
  3003. {
  3004. return OpCodes.Ldind_I4;
  3005. }
  3006. if (TypeSystemServices.LongType == tag)
  3007. {
  3008. return OpCodes.Ldind_I8;
  3009. }
  3010. if (TypeSystemServices.ByteType == tag)
  3011. {
  3012. return OpCodes.Ldind_I1;
  3013. }
  3014. if (TypeSystemServices.ShortType == tag ||
  3015. TypeSystemServices.CharType == tag)
  3016. {
  3017. return OpCodes.Ldind_I2;
  3018. }
  3019. if (TypeSystemServices.SingleType == tag)
  3020. {
  3021. return OpCodes.Ldind_R4;
  3022. }
  3023. if (TypeSystemServices.DoubleType == tag)
  3024. {
  3025. return OpCodes.Ldind_R8;
  3026. }
  3027. if (TypeSystemServices.UShortType == tag)
  3028. {
  3029. return OpCodes.Ldind_U2;
  3030. }
  3031. if (TypeSystemServices.UIntType == tag)
  3032. {
  3033. return OpCodes.Ldind_U4;
  3034. }
  3035. return OpCodes.Ldobj;
  3036. }
  3037. return OpCodes.Ldind_Ref;
  3038. }
  3039. OpCode GetStoreRefParamCode(IType tag)
  3040. {
  3041. if (tag.IsValueType)
  3042. {
  3043. if (TypeSystemServices.IntType == tag ||
  3044. tag.IsEnum)
  3045. {
  3046. return OpCodes.Stind_I4;
  3047. }
  3048. if (TypeSystemServices.LongType == tag)
  3049. {
  3050. return OpCodes.Stind_I8;
  3051. }
  3052. if (TypeSystemServices.ByteType == tag)
  3053. {
  3054. return OpCodes.Stind_I1;
  3055. }
  3056. if (TypeSystemServices.ShortType == tag ||
  3057. TypeSystemServices.CharType == tag)
  3058. {
  3059. return OpCodes.Stind_I2;
  3060. }
  3061. if (TypeSystemServices.SingleType == tag)
  3062. {
  3063. return OpCodes.Stind_R4;
  3064. }
  3065. if (TypeSystemServices.DoubleType == tag)
  3066. {
  3067. return OpCodes.Stind_R8;
  3068. }
  3069. return OpCodes.Stobj;
  3070. }
  3071. return OpCodes.Stind_Ref;
  3072. }
  3073. bool IsAssignableFrom(IType expectedType, IType actualType)
  3074. {
  3075. return (IsPtr(expectedType) && IsPtr(actualType))
  3076. || expectedType.IsAssignableFrom(actualType);
  3077. }
  3078. bool IsPtr(IType type)
  3079. {
  3080. return (type == TypeSystemServices.IntPtrType)
  3081. || (type == TypeSystemServices.UIntPtrType);
  3082. }
  3083. void EmitCastIfNeeded(IType expectedType, IType actualType)
  3084. {
  3085. if (null == actualType) // see NullLiteralExpression
  3086. {
  3087. return;
  3088. }
  3089. if (!IsAssignableFrom(expectedType, actualType))
  3090. {
  3091. IMethod method = TypeSystemServices.FindImplicitConversionOperator(actualType,expectedType);
  3092. if (method != null)
  3093. {
  3094. EmitBoxIfNeeded(method.GetParameters()[0].Type, actualType);
  3095. _il.EmitCall(OpCodes.Call, GetMethodInfo(method), null);
  3096. return;
  3097. }
  3098. if (expectedType is IGenericParameter)
  3099. {
  3100. // Since expected type is a generic parameter, we don't know whether to emit
  3101. // an unbox opcode or a castclass opcode; so we emit an unbox.any opcode which
  3102. // works as either of those at runtime
  3103. _il.Emit(OpCodes.Unbox_Any, GetSystemType(expectedType));
  3104. }
  3105. else if (expectedType.IsValueType)
  3106. {
  3107. if (actualType.IsValueType)
  3108. {
  3109. // numeric promotion
  3110. if (TypeSystemServices.DecimalType == expectedType)
  3111. {
  3112. _il.EmitCall(OpCodes.Call, GetToDecimalConversionMethod(actualType), null);
  3113. }
  3114. else if (TypeSystemServices.DecimalType == actualType)
  3115. {
  3116. _il.EmitCall(OpCodes.Call, GetFromDecimalConversionMethod(expectedType), null);
  3117. }
  3118. else
  3119. {
  3120. _il.Emit(GetNumericPromotionOpCode(expectedType));
  3121. }
  3122. }
  3123. else
  3124. {
  3125. // To get a value type out of a reference type we emit an unbox opcode
  3126. EmitUnbox(expectedType);
  3127. }
  3128. }
  3129. else
  3130. {
  3131. EmitRuntimeCoercionIfNeeded(expectedType, actualType);
  3132. // In order to cast to a reference type we emit a castclass opcode
  3133. _context.TraceInfo("castclass: expected type='{0}', type on stack='{1}'", expectedType, actualType);
  3134. _il.Emit(OpCodes.Castclass, GetSystemType(expectedType));
  3135. }
  3136. }
  3137. else
  3138. {
  3139. EmitBoxIfNeeded(expectedType, actualType);
  3140. }
  3141. }
  3142. private void EmitRuntimeCoercionIfNeeded(IType expectedType, IType actualType)
  3143. {
  3144. if (TypeSystemServices.IsDuckType(actualType))
  3145. {
  3146. EmitGetTypeFromHandle(GetSystemType(expectedType)); PopType();
  3147. _il.EmitCall(OpCodes.Call, RuntimeServices_Coerce, null);
  3148. }
  3149. }
  3150. private MethodInfo _RuntimeServices_Coerce;
  3151. private MethodInfo RuntimeServices_Coerce
  3152. {
  3153. get
  3154. {
  3155. if (_RuntimeServices_Coerce != null) return _RuntimeServices_Coerce;
  3156. return _RuntimeServices_Coerce = Types.RuntimeServices.GetMethod("Coerce", new Type[] { Types.Object, Types.Type });
  3157. }
  3158. }
  3159. private void EmitBoxIfNeeded(IType expectedType, IType actualType)
  3160. {
  3161. if ((actualType.IsValueType && !expectedType.IsValueType) ||
  3162. (actualType is IGenericParameter && !(expectedType is IGenericParameter)))
  3163. {
  3164. EmitBox(actualType);
  3165. }
  3166. }
  3167. void EmitBox(IType type)
  3168. {
  3169. _il.Emit(OpCodes.Box, GetSystemType(type));
  3170. }
  3171. void EmitUnbox(IType expectedType)
  3172. {
  3173. string unboxMethodName = GetUnboxMethodName(expectedType);
  3174. if (null != unboxMethodName)
  3175. {
  3176. _il.EmitCall(OpCodes.Call, GetRuntimeMethod(unboxMethodName), null);
  3177. }
  3178. else
  3179. {
  3180. Type type = GetSystemType(expectedType);
  3181. _il.Emit(OpCodes.Unbox, type);
  3182. _il.Emit(OpCodes.Ldobj, type);
  3183. }
  3184. }
  3185. MethodInfo GetRuntimeMethod(string methodName)
  3186. {
  3187. return Types.RuntimeServices.GetMethod(methodName);
  3188. }
  3189. string GetUnboxMethodName(IType type)
  3190. {
  3191. if (type == TypeSystemServices.ByteType) return "UnboxByte";
  3192. if (type == TypeSystemServices.SByteType) return "UnboxSByte";
  3193. if (type == TypeSystemServices.ShortType) return "UnboxInt16";
  3194. if (type == TypeSystemServices.UShortType) return "UnboxUInt16";
  3195. if (type == TypeSystemServices.IntType) return "UnboxInt32";
  3196. if (type == TypeSystemServices.UIntType) return "UnboxUInt32";
  3197. if (type == TypeSystemServices.LongType) return "UnboxInt64";
  3198. if (type == TypeSystemServices.ULongType) return "UnboxUInt64";
  3199. if (type == TypeSystemServices.SingleType) return "UnboxSingle";
  3200. if (type == TypeSystemServices.DoubleType) return "UnboxDouble";
  3201. if (type == TypeSystemServices.DecimalType) return "UnboxDecimal";
  3202. if (type == TypeSystemServices.BoolType) return "UnboxBoolean";
  3203. if (type == TypeSystemServices.CharType) return "UnboxChar";
  3204. return null;
  3205. }
  3206. OpCode GetNumericPromotionOpCode(IType type)
  3207. {
  3208. if (type == TypeSystemServices.SByteType)
  3209. {
  3210. return _checked ? OpCodes.Conv_Ovf_I1 : OpCodes.Conv_I1;
  3211. }
  3212. else if (type == TypeSystemServices.ByteType)
  3213. {
  3214. return _checked ? OpCodes.Conv_Ovf_U1 : OpCodes.Conv_U1;
  3215. }
  3216. else if (type == TypeSystemServices.ShortType)
  3217. {
  3218. return _checked ? OpCodes.Conv_Ovf_I2 : OpCodes.Conv_I2;
  3219. }
  3220. else if (type == TypeSystemServices.UShortType ||
  3221. type == TypeSystemServices.CharType)
  3222. {
  3223. return _checked ? OpCodes.Conv_Ovf_U2 : OpCodes.Conv_U2;
  3224. }
  3225. if (type == TypeSystemServices.IntType ||
  3226. type.IsEnum)
  3227. {
  3228. return _checked ? OpCodes.Conv_Ovf_I4 : OpCodes.Conv_I4;
  3229. }
  3230. else if (type == TypeSystemServices.UIntType)
  3231. {
  3232. return _checked ? OpCodes.Conv_Ovf_U4 :OpCodes.Conv_U4;
  3233. }
  3234. else if (type == TypeSystemServices.LongType)
  3235. {
  3236. return _checked ? OpCodes.Conv_Ovf_I8 : OpCodes.Conv_I8;
  3237. }
  3238. else if (type == TypeSystemServices.ULongType)
  3239. {
  3240. return _checked ? OpCodes.Conv_Ovf_U8 :OpCodes.Conv_U8;
  3241. }
  3242. else if (type == TypeSystemServices.SingleType)
  3243. {
  3244. return OpCodes.Conv_R4;
  3245. }
  3246. else if (type == TypeSystemServices.DoubleType)
  3247. {
  3248. return OpCodes.Conv_R8;
  3249. }
  3250. else
  3251. {
  3252. throw new NotImplementedException(string.Format("Numeric promotion for {0} not implemented!", type));
  3253. }
  3254. }
  3255. void StoreEntity(OpCode opcode, int index, Node value, IType elementType)
  3256. {
  3257. _il.Emit(OpCodes.Dup); // array reference
  3258. _il.Emit(OpCodes.Ldc_I4, index); // element index
  3259. bool stobj = IsStobj(opcode); // value type sequence?
  3260. if (stobj)
  3261. {
  3262. Type systemType = GetSystemType(elementType);
  3263. _il.Emit(OpCodes.Ldelema, systemType);
  3264. value.Accept(this);
  3265. EmitCastIfNeeded(elementType, PopType()); // might need to cast to decimal
  3266. _il.Emit(opcode, systemType);
  3267. }
  3268. else
  3269. {
  3270. value.Accept(this);
  3271. EmitCastIfNeeded(elementType, PopType());
  3272. _il.Emit(opcode);
  3273. }
  3274. }
  3275. bool IsStobj(OpCode code)
  3276. {
  3277. return OpCodes.Stobj.Value == code.Value;
  3278. }
  3279. void DefineAssemblyAttributes()
  3280. {
  3281. foreach (Attribute attribute in _assemblyAttributes)
  3282. {
  3283. _asmBuilder.SetCustomAttribute(GetCustomAttributeBuilder(attribute));
  3284. }
  3285. }
  3286. CustomAttributeBuilder CreateDebuggableAttribute()
  3287. {
  3288. return new CustomAttributeBuilder(
  3289. DebuggableAttribute_Constructor,
  3290. new object[] { true, true });
  3291. }
  3292. CustomAttributeBuilder CreateRuntimeCompatibilityAttribute()
  3293. {
  3294. return new CustomAttributeBuilder(
  3295. RuntimeCompatibilityAttribute_Constructor, new object[0],
  3296. RuntimeCompatibilityAttribute_Property, new object[] { true });
  3297. }
  3298. void DefineEntryPoint()
  3299. {
  3300. if (Context.Parameters.GenerateInMemory)
  3301. {
  3302. Context.GeneratedAssembly = _asmBuilder;
  3303. }
  3304. if (CompilerOutputType.Library != Parameters.OutputType)
  3305. {
  3306. Method method = ContextAnnotations.GetEntryPoint(Context);
  3307. if (null != method)
  3308. {
  3309. MethodInfo entryPoint = Context.Parameters.GenerateInMemory
  3310. ? _asmBuilder.GetType(method.DeclaringType.FullName).GetMethod(method.Name, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static)
  3311. : GetMethodBuilder(method);
  3312. _asmBuilder.SetEntryPoint(entryPoint, (PEFileKinds)Parameters.OutputType);
  3313. }
  3314. else
  3315. {
  3316. Errors.Add(CompilerErrorFactory.NoEntryPoint());
  3317. }
  3318. }
  3319. }
  3320. Type[] GetParameterTypes(ParameterDeclarationCollection parameters)
  3321. {
  3322. Type[] types = new Type[parameters.Count];
  3323. for (int i=0; i<types.Length; ++i)
  3324. {
  3325. types[i] = GetSystemType(parameters[i].Type);
  3326. if (parameters[i].IsByRef && !types[i].IsByRef)
  3327. {
  3328. types[i] = types[i].MakeByRefType();
  3329. }
  3330. }
  3331. return types;
  3332. }
  3333. Hashtable _builders = new Hashtable();
  3334. void SetBuilder(Node node, object builder)
  3335. {
  3336. if (null == builder)
  3337. {
  3338. throw new ArgumentNullException("type");
  3339. }
  3340. _builders[node] = builder;
  3341. }
  3342. object GetBuilder(Node node)
  3343. {
  3344. return _builders[node];
  3345. }
  3346. internal TypeBuilder GetTypeBuilder(Node node)
  3347. {
  3348. return (TypeBuilder)_builders[node];
  3349. }
  3350. PropertyBuilder GetPropertyBuilder(Node node)
  3351. {
  3352. return (PropertyBuilder)_builders[node];
  3353. }
  3354. FieldBuilder GetFieldBuilder(Node node)
  3355. {
  3356. return (FieldBuilder)_builders[node];
  3357. }
  3358. MethodBuilder GetMethodBuilder(Method method)
  3359. {
  3360. return (MethodBuilder)_builders[method];
  3361. }
  3362. ConstructorBuilder GetConstructorBuilder(Method method)
  3363. {
  3364. return (ConstructorBuilder)_builders[method];
  3365. }
  3366. LocalBuilder GetLocalBuilder(Node local)
  3367. {
  3368. return GetInternalLocal(local).LocalBuilder;
  3369. }
  3370. PropertyInfo GetPropertyInfo(IEntity tag)
  3371. {
  3372. ExternalProperty external = tag as ExternalProperty;
  3373. if (null != external)
  3374. {
  3375. return external.PropertyInfo;
  3376. }
  3377. return GetPropertyBuilder(((InternalProperty)tag).Property);
  3378. }
  3379. FieldInfo GetFieldInfo(IField tag)
  3380. {
  3381. // If field is mapped from a generic type, get its mapped FieldInfo
  3382. // on the constructed type
  3383. GenericMappedField mapped = tag as GenericMappedField;
  3384. if (mapped != null)
  3385. {
  3386. return GetMappedFieldInfo(mapped.DeclaringType, mapped.Source);
  3387. }
  3388. // If field is external, get its existing FieldInfo
  3389. ExternalField external = tag as ExternalField;
  3390. if (null != external)
  3391. {
  3392. return external.FieldInfo;
  3393. }
  3394. // If field is internal, get its FieldBuilder
  3395. return GetFieldBuilder(((InternalField)tag).Field);
  3396. }
  3397. MethodInfo GetMethodInfo(IMethod entity)
  3398. {
  3399. // If method is mapped from a generic type, get its MethodInfo on the constructed type
  3400. GenericMappedMethod mapped = entity as GenericMappedMethod;
  3401. if (mapped != null)
  3402. {
  3403. return GetMappedMethodInfo(mapped.DeclaringType, mapped.Source);
  3404. }
  3405. // If method is a constructed generic method, get its MethodInfo from its definition
  3406. if (entity is GenericConstructedMethod)
  3407. {
  3408. return GetConstructedMethodInfo(entity.ConstructedInfo);
  3409. }
  3410. // If method is external, get its existing MethodInfo
  3411. ExternalMethod external = entity as ExternalMethod;
  3412. if (null != external)
  3413. {
  3414. return (MethodInfo)external.MethodInfo;
  3415. }
  3416. // If method is internal, get its MethodBuilder
  3417. return GetMethodBuilder(((InternalMethod)entity).Method);
  3418. }
  3419. ConstructorInfo GetConstructorInfo(IConstructor entity)
  3420. {
  3421. // If constructor is external, get its existing ConstructorInfo
  3422. ExternalConstructor external = entity as ExternalConstructor;
  3423. if (null != external)
  3424. {
  3425. return external.ConstructorInfo;
  3426. }
  3427. // If constructor is mapped from a generic type, get its ConstructorInfo on the constructed type
  3428. GenericMappedConstructor mapped = entity as GenericMappedConstructor;
  3429. if (mapped != null)
  3430. {
  3431. return TypeBuilder.GetConstructor(GetSystemType(mapped.DeclaringType), GetConstructorInfo((IConstructor)mapped.Source));
  3432. }
  3433. // If constructor is internal, get its MethodBuilder
  3434. return GetConstructorBuilder(((InternalMethod)entity).Method);
  3435. }
  3436. /// <summary>
  3437. /// Retrieves the MethodInfo for a generic constructed method.
  3438. /// </summary>
  3439. private MethodInfo GetConstructedMethodInfo(IConstructedMethodInfo constructedInfo)
  3440. {
  3441. Type[] arguments = Array.ConvertAll<IType, Type>(
  3442. constructedInfo.GenericArguments,
  3443. GetSystemType);
  3444. return GetMethodInfo(constructedInfo.GenericDefinition).MakeGenericMethod(arguments);
  3445. }
  3446. /// <summary>
  3447. /// Retrieves the FieldInfo for a field as mapped on a generic type.
  3448. /// </summary>
  3449. private FieldInfo GetMappedFieldInfo(IType targetType, IField source)
  3450. {
  3451. FieldInfo fi = GetFieldInfo(source);
  3452. if (!fi.DeclaringType.IsGenericTypeDefinition)
  3453. {
  3454. // HACK: .NET Reflection doesn't allow calling TypeBuilder.GetField(Type, FieldInfo)
  3455. // on types that aren't generic definitions (like open constructed types), so we have
  3456. // to manually find the corresponding FieldInfo on the declaring type's definition
  3457. // before mapping it
  3458. Type definition = fi.DeclaringType.GetGenericTypeDefinition();
  3459. fi = definition.GetField(fi.Name);
  3460. }
  3461. return TypeBuilder.GetField(GetSystemType(targetType), fi);
  3462. }
  3463. /// <summary>
  3464. /// Retrieves the MethodInfo for a method as mapped on a generic type.
  3465. /// </summary>
  3466. private MethodInfo GetMappedMethodInfo(IType targetType, IMethod source)
  3467. {
  3468. MethodInfo mi = GetMethodInfo(source);
  3469. if (!mi.DeclaringType.IsGenericTypeDefinition)
  3470. {
  3471. // HACK: .NET Reflection doesn't allow calling TypeBuilder.GetMethod(Type, MethodInfo)
  3472. // on types that aren't generic definitions (like open constructed types), so we have to
  3473. // manually find the corresponding MethodInfo on the declaring type's definition before
  3474. // mapping it
  3475. Type definition = mi.DeclaringType.GetGenericTypeDefinition();
  3476. mi = Array.Find<MethodInfo>(
  3477. definition.GetMethods(),
  3478. delegate(MethodInfo other) { return other.MetadataToken == mi.MetadataToken; });
  3479. }
  3480. return TypeBuilder.GetMethod(GetSystemType(targetType), mi);
  3481. }
  3482. /// <summary>
  3483. /// Retrieves the ConstructorInfo for a constructor as mapped on a generic type.
  3484. /// </summary>
  3485. private ConstructorInfo GetMappedConstructorInfo(IType targetType, IConstructor source)
  3486. {
  3487. ConstructorInfo ci = GetConstructorInfo(source);
  3488. if (!ci.DeclaringType.IsGenericTypeDefinition)
  3489. {
  3490. // HACK: .NET Reflection doesn't allow calling
  3491. // TypeBuilder.GetConstructor(Type, ConstructorInfo) on types that aren't generic
  3492. // definitions, so we have to manually find the corresponding ConstructorInfo on the
  3493. // declaring type's definition before mapping it
  3494. Type definition = ci.DeclaringType.GetGenericTypeDefinition();
  3495. ci = Array.Find<ConstructorInfo>(
  3496. definition.GetConstructors(),
  3497. delegate(ConstructorInfo other) { return other.MetadataToken == ci.MetadataToken; });
  3498. }
  3499. return TypeBuilder.GetConstructor(GetSystemType(targetType), ci);
  3500. }
  3501. Type GetSystemType(Node node)
  3502. {
  3503. return GetSystemType(GetType(node));
  3504. }
  3505. Type GetSystemType(IType tag)
  3506. {
  3507. Type type = (Type)_typeCache[tag];
  3508. if (type != null)
  3509. {
  3510. return type;
  3511. }
  3512. ExternalType external = tag as ExternalType;
  3513. if (null != external)
  3514. {
  3515. type = external.ActualType;
  3516. }
  3517. else if (tag.IsArray)
  3518. {
  3519. IArrayType arrayType = (IArrayType)tag;
  3520. Type systemType = GetSystemType(arrayType.GetElementType());
  3521. int rank = arrayType.GetArrayRank();
  3522. if (rank == 1)
  3523. {
  3524. type = systemType.MakeArrayType();
  3525. }
  3526. else
  3527. {
  3528. type = systemType.MakeArrayType(rank);
  3529. }
  3530. }
  3531. else if (Null.Default == tag)
  3532. {
  3533. type = Types.Object;
  3534. }
  3535. else if (tag.ConstructedInfo != null)
  3536. {
  3537. // Type is a constructed generic type - create it using its definition's system type
  3538. Type[] arguments = Array.ConvertAll<IType, Type>(tag.ConstructedInfo.GenericArguments, GetSystemType);
  3539. type = GetSystemType(tag.ConstructedInfo.GenericDefinition).MakeGenericType(arguments);
  3540. }
  3541. else if (tag is InternalGenericParameter)
  3542. {
  3543. return (Type)GetBuilder(((InternalGenericParameter)tag).Node);
  3544. }
  3545. else if (tag is AbstractInternalType)
  3546. {
  3547. type = (Type)GetBuilder(((AbstractInternalType)tag).TypeDefinition);
  3548. }
  3549. if (null == type)
  3550. {
  3551. throw new InvalidOperationException(string.Format("Could not find a Type for {0}.", tag));
  3552. }
  3553. _typeCache.Add(tag, type);
  3554. return type;
  3555. }
  3556. TypeAttributes GetNestedTypeAttributes(TypeMember type)
  3557. {
  3558. return GetExtendedTypeAttributes(GetNestedTypeAccessibility(type), type);
  3559. }
  3560. TypeAttributes GetNestedTypeAccessibility(TypeMember type)
  3561. {
  3562. if (type.IsPublic) return TypeAttributes.NestedPublic;
  3563. if (type.IsInternal) return TypeAttributes.NestedAssembly;
  3564. return TypeAttributes.NestedPrivate;
  3565. }
  3566. TypeAttributes GetTypeAttributes(TypeMember type)
  3567. {
  3568. TypeAttributes attributes = type.IsPublic ? TypeAttributes.Public : TypeAttributes.NotPublic;
  3569. return GetExtendedTypeAttributes(attributes, type);
  3570. }
  3571. TypeAttributes GetExtendedTypeAttributes(TypeAttributes attributes, TypeMember type)
  3572. {
  3573. switch (type.NodeType)
  3574. {
  3575. case NodeType.ClassDefinition:
  3576. {
  3577. attributes |= (TypeAttributes.AnsiClass | TypeAttributes.AutoLayout);
  3578. attributes |= TypeAttributes.Class;
  3579. attributes |= TypeAttributes.BeforeFieldInit;
  3580. if (!type.IsTransient)
  3581. {
  3582. attributes |= TypeAttributes.Serializable;
  3583. }
  3584. if (type.IsAbstract)
  3585. {
  3586. attributes |= TypeAttributes.Abstract;
  3587. }
  3588. if (type.IsFinal)
  3589. {
  3590. attributes |= TypeAttributes.Sealed;
  3591. }
  3592. if (((IType)type.Entity).IsValueType)
  3593. {
  3594. attributes |= TypeAttributes.SequentialLayout;
  3595. }
  3596. break;
  3597. }
  3598. case NodeType.EnumDefinition:
  3599. {
  3600. attributes |= TypeAttributes.Sealed;
  3601. attributes |= TypeAttributes.Serializable;
  3602. break;
  3603. }
  3604. case NodeType.InterfaceDefinition:
  3605. {
  3606. attributes |= (TypeAttributes.Interface | TypeAttributes.Abstract);
  3607. break;
  3608. }
  3609. case NodeType.Module:
  3610. {
  3611. attributes |= TypeAttributes.Sealed;
  3612. break;
  3613. }
  3614. }
  3615. return attributes;
  3616. }
  3617. PropertyAttributes GetPropertyAttributes(Property property)
  3618. {
  3619. PropertyAttributes attributes = PropertyAttributes.None;
  3620. if (property.ExplicitInfo != null)
  3621. {
  3622. attributes |= PropertyAttributes.SpecialName | PropertyAttributes.RTSpecialName;
  3623. }
  3624. return attributes;
  3625. }
  3626. MethodAttributes GetMethodAttributesFromTypeMember(TypeMember member)
  3627. {
  3628. MethodAttributes attributes = (MethodAttributes)0;
  3629. if (member.IsPublic)
  3630. {
  3631. attributes = MethodAttributes.Public;
  3632. }
  3633. else if (member.IsProtected)
  3634. {
  3635. attributes = member.IsInternal
  3636. ? MethodAttributes.FamORAssem
  3637. : MethodAttributes.Family;
  3638. }
  3639. else if (member.IsPrivate)
  3640. {
  3641. attributes = MethodAttributes.Private;
  3642. }
  3643. else if (member.IsInternal)
  3644. {
  3645. attributes = MethodAttributes.Assembly;
  3646. }
  3647. if (member.IsStatic)
  3648. {
  3649. attributes |= MethodAttributes.Static;
  3650. if (member.Name.StartsWith("op_"))
  3651. {
  3652. attributes |= MethodAttributes.SpecialName;
  3653. }
  3654. }
  3655. if (member.IsFinal)
  3656. {
  3657. attributes |= MethodAttributes.Final;
  3658. }
  3659. if (member.IsAbstract)
  3660. {
  3661. attributes |= (MethodAttributes.Abstract | MethodAttributes.Virtual);
  3662. }
  3663. if (member.IsVirtual || member.IsOverride)
  3664. {
  3665. attributes |= MethodAttributes.Virtual;
  3666. }
  3667. return attributes;
  3668. }
  3669. MethodAttributes GetPropertyMethodAttributes(TypeMember property)
  3670. {
  3671. MethodAttributes attributes = MethodAttributes.SpecialName | MethodAttributes.HideBySig;
  3672. attributes |= GetMethodAttributesFromTypeMember(property);
  3673. return attributes;
  3674. }
  3675. MethodAttributes GetMethodAttributes(Method method)
  3676. {
  3677. MethodAttributes attributes = MethodAttributes.HideBySig;
  3678. if (method.ExplicitInfo != null)
  3679. {
  3680. attributes |= MethodAttributes.NewSlot;
  3681. }
  3682. if (IsPInvoke(method))
  3683. {
  3684. Debug.Assert(method.IsStatic);
  3685. attributes |= MethodAttributes.PinvokeImpl;
  3686. }
  3687. attributes |= GetMethodAttributesFromTypeMember(method);
  3688. return attributes;
  3689. }
  3690. FieldAttributes GetFieldAttributes(Field field)
  3691. {
  3692. FieldAttributes attributes = 0;
  3693. if (field.IsProtected)
  3694. {
  3695. attributes |= FieldAttributes.Family;
  3696. }
  3697. else if (field.IsPublic)
  3698. {
  3699. attributes |= FieldAttributes.Public;
  3700. }
  3701. else if (field.IsPrivate)
  3702. {
  3703. attributes |= FieldAttributes.Private;
  3704. }
  3705. else if (field.IsInternal)
  3706. {
  3707. attributes |= FieldAttributes.Assembly;
  3708. }
  3709. if (field.IsStatic)
  3710. {
  3711. attributes |= FieldAttributes.Static;
  3712. }
  3713. if (field.IsTransient)
  3714. {
  3715. attributes |= FieldAttributes.NotSerialized;
  3716. }
  3717. if (field.IsFinal)
  3718. {
  3719. IField entity = (IField)field.Entity;
  3720. if (entity.IsLiteral)
  3721. {
  3722. attributes |= FieldAttributes.Literal;
  3723. }
  3724. else
  3725. {
  3726. attributes |= FieldAttributes.InitOnly;
  3727. }
  3728. }
  3729. return attributes;
  3730. }
  3731. ParameterAttributes GetParameterAttributes(ParameterDeclaration param)
  3732. {
  3733. return ParameterAttributes.None;
  3734. }
  3735. void DefineEvent(TypeBuilder typeBuilder, Event node)
  3736. {
  3737. EventBuilder builder = typeBuilder.DefineEvent(node.Name,
  3738. EventAttributes.None,
  3739. GetSystemType(node.Type));
  3740. //MethodAttributes attribs = GetPropertyMethodAttributes(node);
  3741. MethodAttributes baseAttributes = MethodAttributes.SpecialName;
  3742. builder.SetAddOnMethod(DefineMethod(typeBuilder, node.Add, baseAttributes|GetMethodAttributes(node.Add)));
  3743. builder.SetRemoveOnMethod(DefineMethod(typeBuilder, node.Remove, baseAttributes|GetMethodAttributes(node.Remove)));
  3744. if (null != node.Raise)
  3745. {
  3746. builder.SetRaiseMethod(DefineMethod(typeBuilder, node.Raise, baseAttributes|GetMethodAttributes(node.Raise)));
  3747. }
  3748. SetBuilder(node, builder);
  3749. }
  3750. void DefineProperty(TypeBuilder typeBuilder, Property property)
  3751. {
  3752. string name;
  3753. if (property.ExplicitInfo != null)
  3754. {
  3755. name = property.ExplicitInfo.InterfaceType.Name + "." + property.Name;
  3756. }
  3757. else
  3758. {
  3759. name = property.Name;
  3760. }
  3761. PropertyBuilder builder = typeBuilder.DefineProperty(name,
  3762. GetPropertyAttributes(property),
  3763. GetSystemType(property.Type),
  3764. GetParameterTypes(property.Parameters));
  3765. Method getter = property.Getter;
  3766. Method setter = property.Setter;
  3767. MethodAttributes attribs = GetPropertyMethodAttributes(property);
  3768. if (null != getter)
  3769. {
  3770. MethodBuilder getterBuilder =
  3771. DefineMethod(typeBuilder, getter, attribs);
  3772. builder.SetGetMethod(getterBuilder);
  3773. }
  3774. if (null != setter)
  3775. {
  3776. MethodBuilder setterBuilder =
  3777. DefineMethod(typeBuilder, setter, attribs);
  3778. builder.SetSetMethod(setterBuilder);
  3779. }
  3780. bool isDuckTyped = GetEntity(property).IsDuckTyped;
  3781. if (isDuckTyped)
  3782. {
  3783. builder.SetCustomAttribute(CreateDuckTypedCustomAttribute());
  3784. }
  3785. SetBuilder(property, builder);
  3786. }
  3787. void DefineField(TypeBuilder typeBuilder, Field field)
  3788. {
  3789. FieldBuilder builder = typeBuilder.DefineField(field.Name,
  3790. GetSystemType(field),
  3791. GetFieldAttributes(field));
  3792. SetBuilder(field, builder);
  3793. }
  3794. delegate ParameterBuilder ParameterFactory(int index, System.Reflection.ParameterAttributes attributes, string name);
  3795. void DefineParameters(ConstructorBuilder builder, ParameterDeclarationCollection parameters)
  3796. {
  3797. DefineParameters(parameters, new ParameterFactory(builder.DefineParameter));
  3798. }
  3799. void DefineParameters(MethodBuilder builder, ParameterDeclarationCollection parameters)
  3800. {
  3801. DefineParameters(parameters, new ParameterFactory(builder.DefineParameter));
  3802. }
  3803. void DefineParameters(ParameterDeclarationCollection parameters, ParameterFactory defineParameter)
  3804. {
  3805. int last = parameters.Count - 1;
  3806. for (int i=0; i<parameters.Count; ++i)
  3807. {
  3808. ParameterBuilder paramBuilder = defineParameter(i+1, GetParameterAttributes(parameters[i]), parameters[i].Name);
  3809. if (last == i && parameters.VariableNumber)
  3810. {
  3811. SetParamArrayAttribute(paramBuilder);
  3812. }
  3813. SetBuilder(parameters[i], paramBuilder);
  3814. }
  3815. }
  3816. void SetParamArrayAttribute(ParameterBuilder builder)
  3817. {
  3818. builder.SetCustomAttribute(
  3819. new CustomAttributeBuilder(
  3820. ParamArrayAttribute_Constructor,
  3821. new object[0]));
  3822. }
  3823. MethodImplAttributes GetImplementationFlags(Method method)
  3824. {
  3825. MethodImplAttributes flags = MethodImplAttributes.Managed;
  3826. if (method.IsRuntime)
  3827. {
  3828. flags |= MethodImplAttributes.Runtime;
  3829. }
  3830. return flags;
  3831. }
  3832. MethodBuilder DefineMethod(TypeBuilder typeBuilder, Method method, MethodAttributes attributes)
  3833. {
  3834. ParameterDeclarationCollection parameters = method.Parameters;
  3835. MethodAttributes methodAttributes = GetMethodAttributes(method) | attributes;
  3836. string name;
  3837. if (method.ExplicitInfo != null)
  3838. {
  3839. name = method.ExplicitInfo.InterfaceType.Name + "." + method.Name;
  3840. }
  3841. else
  3842. {
  3843. name = method.Name;
  3844. }
  3845. MethodBuilder builder = typeBuilder.DefineMethod(name,
  3846. methodAttributes);
  3847. if (method.GenericParameters.Count != 0)
  3848. {
  3849. DefineGenericParameters(builder, method.GenericParameters.ToArray());
  3850. }
  3851. builder.SetParameters(GetParameterTypes(parameters));
  3852. IType returnType = GetType(method.ReturnType);
  3853. if (IsPInvoke(method) && returnType is TypeSystem.Unknown)
  3854. {
  3855. returnType = TypeSystemServices.VoidType;
  3856. }
  3857. builder.SetReturnType(GetSystemType(returnType));
  3858. builder.SetImplementationFlags(GetImplementationFlags(method));
  3859. DefineParameters(builder, parameters);
  3860. SetBuilder(method, builder);
  3861. IMethod methodEntity = GetEntity(method);
  3862. if (methodEntity.IsDuckTyped)
  3863. {
  3864. builder.SetCustomAttribute(CreateDuckTypedCustomAttribute());
  3865. }
  3866. return builder;
  3867. }
  3868. /// <summary>
  3869. /// Defines the generic parameters of an internal generic type.
  3870. /// </summary>
  3871. void DefineGenericParameters(TypeBuilder builder, GenericParameterDeclaration[] parameters)
  3872. {
  3873. string[] names = Array.ConvertAll<GenericParameterDeclaration, string>(
  3874. parameters,
  3875. delegate(GenericParameterDeclaration gpd) { return gpd.Name; });
  3876. GenericTypeParameterBuilder[] builders = builder.DefineGenericParameters(names);
  3877. DefineGenericParameters(builders, parameters);
  3878. }
  3879. /// <summary>
  3880. /// Defines the generic parameters of an internal generic method.
  3881. /// </summary>
  3882. void DefineGenericParameters(MethodBuilder builder, GenericParameterDeclaration[] parameters)
  3883. {
  3884. string[] names = Array.ConvertAll<GenericParameterDeclaration, string>(
  3885. parameters,
  3886. delegate(GenericParameterDeclaration gpd) { return gpd.Name; });
  3887. GenericTypeParameterBuilder[] builders = builder.DefineGenericParameters(names);
  3888. DefineGenericParameters(builders, parameters);
  3889. }
  3890. void DefineGenericParameters(GenericTypeParameterBuilder[] builders, GenericParameterDeclaration[] declarations)
  3891. {
  3892. // Set builders
  3893. for (int i = 0; i < builders.Length; i++)
  3894. {
  3895. SetBuilder(declarations[i], builders[i]);
  3896. }
  3897. // TODO: Set constraints
  3898. }
  3899. private CustomAttributeBuilder CreateDuckTypedCustomAttribute()
  3900. {
  3901. return new CustomAttributeBuilder(DuckTypedAttribute_Constructor, new object[0]);
  3902. }
  3903. void DefineConstructor(TypeBuilder typeBuilder, Method constructor)
  3904. {
  3905. ConstructorBuilder builder = typeBuilder.DefineConstructor(GetMethodAttributes(constructor),
  3906. CallingConventions.Standard,
  3907. GetParameterTypes(constructor.Parameters));
  3908. builder.SetImplementationFlags(GetImplementationFlags(constructor));
  3909. DefineParameters(builder, constructor.Parameters);
  3910. SetBuilder(constructor, builder);
  3911. }
  3912. bool IsEnumDefinition(TypeMember type)
  3913. {
  3914. return NodeType.EnumDefinition == type.NodeType;
  3915. }
  3916. void DefineType(TypeDefinition typeDefinition)
  3917. {
  3918. TypeBuilder typeBuilder = CreateTypeBuilder(typeDefinition);
  3919. SetBuilder(typeDefinition, typeBuilder);
  3920. if (typeDefinition.GenericParameters.Count > 0)
  3921. {
  3922. DefineGenericParameters(typeBuilder, typeDefinition.GenericParameters.ToArray());
  3923. }
  3924. }
  3925. bool IsValueType(TypeMember type)
  3926. {
  3927. IType entity = type.Entity as IType;
  3928. return null != entity && entity.IsValueType;
  3929. }
  3930. TypeBuilder CreateTypeBuilder(TypeDefinition type)
  3931. {
  3932. Type baseType = null;
  3933. if (IsEnumDefinition(type))
  3934. {
  3935. baseType = typeof(Enum);
  3936. }
  3937. else if (IsValueType(type))
  3938. {
  3939. baseType = Types.ValueType;
  3940. }
  3941. TypeBuilder typeBuilder = null;
  3942. ClassDefinition enclosingType = type.ParentNode as ClassDefinition;
  3943. if (null == enclosingType)
  3944. {
  3945. typeBuilder = _moduleBuilder.DefineType(
  3946. AnnotateGenericTypeName(type, type.QualifiedName),
  3947. GetTypeAttributes(type),
  3948. baseType);
  3949. }
  3950. else
  3951. {
  3952. typeBuilder = GetTypeBuilder(enclosingType).DefineNestedType(
  3953. AnnotateGenericTypeName(type, type.Name),
  3954. GetNestedTypeAttributes(type),
  3955. baseType);
  3956. }
  3957. if (IsEnumDefinition(type))
  3958. {
  3959. // Mono cant construct enum array types unless
  3960. // the fields is already defined
  3961. DefineEnumField(typeBuilder);
  3962. }
  3963. return typeBuilder;
  3964. }
  3965. private string AnnotateGenericTypeName(TypeDefinition typeDef, string name)
  3966. {
  3967. if (typeDef.HasGenericParameters)
  3968. {
  3969. return name + "`" + typeDef.GenericParameters.Count;
  3970. }
  3971. return name;
  3972. }
  3973. void DefineEnumField(TypeBuilder builder)
  3974. {
  3975. Type baseType = typeof(int);
  3976. builder.DefineField("value__", baseType,
  3977. FieldAttributes.Public |
  3978. FieldAttributes.SpecialName |
  3979. FieldAttributes.RTSpecialName);
  3980. }
  3981. void EmitBaseTypesAndAttributes(TypeDefinition typeDefinition, TypeBuilder typeBuilder)
  3982. {
  3983. foreach (TypeReference baseType in typeDefinition.BaseTypes)
  3984. {
  3985. Type type = GetSystemType(baseType);
  3986. // For some reason you can't call IsClass on constructed types created at compile time,
  3987. // so we'll ask the generic definition instead
  3988. if ((type.IsGenericType && type.GetGenericTypeDefinition().IsClass) || (type.IsClass))
  3989. {
  3990. typeBuilder.SetParent(type);
  3991. }
  3992. else
  3993. {
  3994. typeBuilder.AddInterfaceImplementation(type);
  3995. }
  3996. }
  3997. }
  3998. void NotImplemented(string feature)
  3999. {
  4000. throw new NotImplementedException(feature);
  4001. }
  4002. CustomAttributeBuilder GetCustomAttributeBuilder(Attribute node)
  4003. {
  4004. IConstructor constructor = (IConstructor)GetEntity(node);
  4005. ConstructorInfo constructorInfo = GetConstructorInfo(constructor);
  4006. object[] constructorArgs = GetValues(constructor.GetParameters(),
  4007. node.Arguments);
  4008. ExpressionPairCollection namedArgs = node.NamedArguments;
  4009. if (namedArgs.Count > 0)
  4010. {
  4011. PropertyInfo[] namedProperties;
  4012. object[] propertyValues;
  4013. FieldInfo[] namedFields;
  4014. object[] fieldValues;
  4015. GetNamedValues(namedArgs,
  4016. out namedProperties, out propertyValues,
  4017. out namedFields, out fieldValues);
  4018. return new CustomAttributeBuilder(
  4019. constructorInfo, constructorArgs,
  4020. namedProperties, propertyValues,
  4021. namedFields, fieldValues);
  4022. }
  4023. return new CustomAttributeBuilder(constructorInfo, constructorArgs);
  4024. }
  4025. void GetNamedValues(ExpressionPairCollection values,
  4026. out PropertyInfo[] outNamedProperties,
  4027. out object[] outPropertyValues,
  4028. out FieldInfo[] outNamedFields,
  4029. out object[] outFieldValues)
  4030. {
  4031. List namedProperties = new List();
  4032. List propertyValues = new List();
  4033. List namedFields = new List();
  4034. List fieldValues = new List();
  4035. foreach (ExpressionPair pair in values)
  4036. {
  4037. ITypedEntity entity = (ITypedEntity)GetEntity(pair.First);
  4038. object value = GetValue(entity.Type, pair.Second);
  4039. if (EntityType.Property == entity.EntityType)
  4040. {
  4041. namedProperties.Add(GetPropertyInfo(entity));
  4042. propertyValues.Add(value);
  4043. }
  4044. else
  4045. {
  4046. namedFields.Add(GetFieldInfo((IField)entity));
  4047. fieldValues.Add(value);
  4048. }
  4049. }
  4050. outNamedProperties = (PropertyInfo[])namedProperties.ToArray(typeof(PropertyInfo));
  4051. outPropertyValues = propertyValues.ToArray();
  4052. outNamedFields = (FieldInfo[])namedFields.ToArray(typeof(FieldInfo));
  4053. outFieldValues = fieldValues.ToArray();
  4054. }
  4055. object[] GetValues(IParameter[] targetParameters, ExpressionCollection expressions)
  4056. {
  4057. object[] values = new object[expressions.Count];
  4058. for (int i=0; i<values.Length; ++i)
  4059. {
  4060. values[i] = GetValue(targetParameters[i].Type, expressions[i]);
  4061. }
  4062. return values;
  4063. }
  4064. object GetValue(IType expectedType, Expression expression)
  4065. {
  4066. switch (expression.NodeType)
  4067. {
  4068. case NodeType.StringLiteralExpression:
  4069. {
  4070. return ((StringLiteralExpression)expression).Value;
  4071. }
  4072. case NodeType.CharLiteralExpression:
  4073. {
  4074. return ((CharLiteralExpression)expression).Value[0];
  4075. }
  4076. case NodeType.BoolLiteralExpression:
  4077. {
  4078. return ((BoolLiteralExpression)expression).Value;
  4079. }
  4080. case NodeType.IntegerLiteralExpression:
  4081. {
  4082. return ConvertValue(expectedType,
  4083. ((IntegerLiteralExpression)expression).Value);
  4084. }
  4085. case NodeType.DoubleLiteralExpression:
  4086. {
  4087. return ConvertValue(expectedType,
  4088. ((DoubleLiteralExpression)expression).Value);
  4089. }
  4090. case NodeType.TypeofExpression:
  4091. {
  4092. return GetSystemType(((TypeofExpression)expression).Type);
  4093. }
  4094. case NodeType.CastExpression:
  4095. {
  4096. return GetValue(expectedType, ((CastExpression)expression).Target);
  4097. }
  4098. default:
  4099. {
  4100. IEntity tag = GetEntity(expression);
  4101. if (EntityType.Type == tag.EntityType)
  4102. {
  4103. return GetSystemType(expression);
  4104. }
  4105. else if (EntityType.Field == tag.EntityType)
  4106. {
  4107. IField field = (IField)tag;
  4108. if (field.IsLiteral)
  4109. {
  4110. //Scenario:
  4111. //IF:
  4112. //SomeType.StaticReference = "hamsandwich"
  4113. //[RandomAttribute(SomeType.StaticReferenece)]
  4114. //THEN:
  4115. //field.StaticValue != "hamsandwich"
  4116. //field.StaticValue == SomeType.StaticReference
  4117. //SO:
  4118. //If field.StaticValue is an AST Expression, call GetValue() on it
  4119. if (field.StaticValue is Expression)
  4120. {
  4121. return GetValue(expectedType, field.StaticValue as Expression);
  4122. }
  4123. return field.StaticValue;
  4124. }
  4125. }
  4126. break;
  4127. }
  4128. }
  4129. NotImplemented(expression, "Expression value: " + expression);
  4130. return null;
  4131. }
  4132. object ConvertValue(IType expectedType, object value)
  4133. {
  4134. if (expectedType.IsEnum)
  4135. {
  4136. return Convert.ChangeType(value, GetUnderlyingEnumType(expectedType));
  4137. }
  4138. return Convert.ChangeType(value, GetSystemType(expectedType));
  4139. }
  4140. private Type GetUnderlyingEnumType(IType expectedType)
  4141. {
  4142. return expectedType is IInternalEntity
  4143. ? Types.Int
  4144. : Enum.GetUnderlyingType(GetSystemType(expectedType));
  4145. }
  4146. void DefineTypeMembers(TypeDefinition typeDefinition)
  4147. {
  4148. if (IsEnumDefinition(typeDefinition))
  4149. {
  4150. return;
  4151. }
  4152. TypeBuilder typeBuilder = GetTypeBuilder(typeDefinition);
  4153. TypeMemberCollection members = typeDefinition.Members;
  4154. foreach (TypeMember member in members)
  4155. {
  4156. switch (member.NodeType)
  4157. {
  4158. case NodeType.Method:
  4159. {
  4160. DefineMethod(typeBuilder, (Method)member, 0);
  4161. break;
  4162. }
  4163. case NodeType.Constructor:
  4164. {
  4165. DefineConstructor(typeBuilder, (Constructor)member);
  4166. break;
  4167. }
  4168. case NodeType.Field:
  4169. {
  4170. DefineField(typeBuilder, (Field)member);
  4171. break;
  4172. }
  4173. case NodeType.Property:
  4174. {
  4175. DefineProperty(typeBuilder, (Property)member);
  4176. break;
  4177. }
  4178. case NodeType.Event:
  4179. {
  4180. DefineEvent(typeBuilder, (Event)member);
  4181. break;
  4182. }
  4183. }
  4184. }
  4185. }
  4186. string GetAssemblySimpleName(string fname)
  4187. {
  4188. return Path.GetFileNameWithoutExtension(fname);
  4189. }
  4190. string GetTargetDirectory(string fname)
  4191. {
  4192. return Path.GetDirectoryName(Path.GetFullPath(fname));
  4193. }
  4194. string BuildOutputAssemblyName(string fname)
  4195. {
  4196. if (!Path.HasExtension(fname))
  4197. {
  4198. if (CompilerOutputType.Library == Parameters.OutputType)
  4199. {
  4200. fname += ".dll";
  4201. }
  4202. else
  4203. {
  4204. fname += ".exe";
  4205. }
  4206. }
  4207. return Path.GetFullPath(fname);
  4208. }
  4209. void DefineResources()
  4210. {
  4211. foreach (ICompilerResource resource in Parameters.Resources)
  4212. {
  4213. resource.WriteResource(_sreResourceService);
  4214. }
  4215. }
  4216. SREResourceService _sreResourceService;
  4217. class SREResourceService : IResourceService
  4218. {
  4219. AssemblyBuilder _asmBuilder;
  4220. ModuleBuilder _moduleBuilder;
  4221. public SREResourceService (AssemblyBuilder asmBuilder, ModuleBuilder modBuilder)
  4222. {
  4223. this._asmBuilder = asmBuilder;
  4224. this._moduleBuilder = modBuilder;
  4225. }
  4226. public bool EmbedFile(string resourceName, string fname)
  4227. {
  4228. MethodInfo embed_res = typeof (AssemblyBuilder).GetMethod(
  4229. "EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic,
  4230. null, CallingConventions.Any, new Type[] { typeof(string), typeof(string) }, null);
  4231. if (embed_res != null)
  4232. {
  4233. embed_res.Invoke(this._asmBuilder, new object[] { resourceName, fname });
  4234. return true;
  4235. }
  4236. return false;
  4237. }
  4238. public IResourceWriter DefineResource(string resourceName, string resourceDescription)
  4239. {
  4240. return this._moduleBuilder.DefineResource(resourceName, resourceDescription);
  4241. }
  4242. }
  4243. void SetUpAssembly()
  4244. {
  4245. string fname = Parameters.OutputAssembly;
  4246. if (0 == fname.Length)
  4247. {
  4248. fname = CompileUnit.Modules[0].Name;
  4249. }
  4250. string outputFile = BuildOutputAssemblyName(fname);
  4251. AssemblyName asmName = CreateAssemblyName(outputFile);
  4252. _asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, GetAssemblyBuilderAccess(), GetTargetDirectory(outputFile));
  4253. if (Parameters.Debug)
  4254. {
  4255. // ikvm tip: Set DebuggableAttribute to assembly before
  4256. // creating the module, to make sure Visual Studio (Whidbey)
  4257. // picks up the attribute when debugging dynamically generated code.
  4258. _asmBuilder.SetCustomAttribute(CreateDebuggableAttribute());
  4259. }
  4260. _asmBuilder.SetCustomAttribute(CreateRuntimeCompatibilityAttribute());
  4261. _moduleBuilder = _asmBuilder.DefineDynamicModule(asmName.Name, Path.GetFileName(outputFile), Parameters.Debug);
  4262. _sreResourceService = new SREResourceService (_asmBuilder, _moduleBuilder);
  4263. ContextAnnotations.SetAssemblyBuilder(Context, _asmBuilder);
  4264. Context.GeneratedAssemblyFileName = outputFile;
  4265. }
  4266. AssemblyBuilderAccess GetAssemblyBuilderAccess()
  4267. {
  4268. return Parameters.GenerateInMemory ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Save;
  4269. }
  4270. AssemblyName CreateAssemblyName(string outputFile)
  4271. {
  4272. AssemblyName assemblyName = new AssemblyName();
  4273. assemblyName.Name = GetAssemblySimpleName(outputFile);
  4274. assemblyName.Version = GetAssemblyVersion();
  4275. if (Parameters.DelaySign)
  4276. {
  4277. assemblyName.SetPublicKey(GetAssemblyKeyPair(outputFile).PublicKey);
  4278. }
  4279. else
  4280. {
  4281. assemblyName.KeyPair = GetAssemblyKeyPair(outputFile);
  4282. }
  4283. return assemblyName;
  4284. }
  4285. StrongNameKeyPair GetAssemblyKeyPair(string outputFile)
  4286. {
  4287. Attribute attribute = GetAssemblyAttribute("System.Reflection.AssemblyKeyNameAttribute");
  4288. if (Parameters.KeyContainer != null)
  4289. {
  4290. if (attribute != null)
  4291. {
  4292. Warnings.Add(CompilerWarningFactory.HaveBothKeyNameAndAttribute(attribute));
  4293. }
  4294. if (Parameters.KeyContainer != "")
  4295. {
  4296. return new StrongNameKeyPair(Parameters.KeyContainer);
  4297. }
  4298. }
  4299. else if (attribute != null)
  4300. {
  4301. string asmName = ((StringLiteralExpression)attribute.Arguments[0]).Value;
  4302. if (asmName != "") //ignore empty AssemblyKeyName values, like C# does
  4303. {
  4304. return new StrongNameKeyPair(asmName);
  4305. }
  4306. }
  4307. string fname = null;
  4308. string srcFile = null;
  4309. attribute = GetAssemblyAttribute("System.Reflection.AssemblyKeyFileAttribute");
  4310. if (Parameters.KeyFile != null)
  4311. {
  4312. fname = Parameters.KeyFile;
  4313. if (attribute != null)
  4314. {
  4315. Warnings.Add(CompilerWarningFactory.HaveBothKeyFileAndAttribute(attribute));
  4316. }
  4317. }
  4318. else if (attribute != null)
  4319. {
  4320. fname = ((StringLiteralExpression)attribute.Arguments[0]).Value;
  4321. if (attribute.LexicalInfo != null)
  4322. {
  4323. srcFile = attribute.LexicalInfo.FileName;
  4324. }
  4325. }
  4326. if (null != fname && fname.Length > 0)
  4327. {
  4328. if (!Path.IsPathRooted(fname))
  4329. {
  4330. fname = ResolveRelative(outputFile, srcFile, fname);
  4331. }
  4332. using (FileStream stream = File.OpenRead(fname))
  4333. {
  4334. //Parameters.DelaySign is ignored.
  4335. return new StrongNameKeyPair(stream);
  4336. }
  4337. }
  4338. return null;
  4339. }
  4340. string ResolveRelative(string targetFile, string srcFile, string relativeFile)
  4341. {
  4342. //relative to current directory:
  4343. string fname = Path.GetFullPath(relativeFile);
  4344. if (File.Exists(fname))
  4345. {
  4346. return fname;
  4347. }
  4348. //relative to source file:
  4349. if (srcFile != null)
  4350. {
  4351. fname = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(srcFile),
  4352. relativeFile));
  4353. if (File.Exists(fname))
  4354. {
  4355. return fname;
  4356. }
  4357. }
  4358. //relative to output assembly:
  4359. if (targetFile != null)
  4360. {
  4361. fname = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(targetFile),
  4362. relativeFile));
  4363. }
  4364. return fname;
  4365. }
  4366. Version GetAssemblyVersion()
  4367. {
  4368. string version = GetAssemblyAttributeValue("System.Reflection.AssemblyVersionAttribute");
  4369. if (null == version)
  4370. {
  4371. version = "0.0.0.0";
  4372. }
  4373. /* 1.0.* -- BUILD -- based on days since January 1, 2000
  4374. * 1.0.0.* -- REVISION -- based on seconds since midnight, January 1, 2000, divided by 2 *
  4375. */
  4376. string[] sliced = version.Split('.');
  4377. if (sliced.Length > 2)
  4378. {
  4379. DateTime baseTime = new DateTime(2000, 1, 1);
  4380. TimeSpan mark = (DateTime.Now - baseTime);
  4381. if (sliced[2].StartsWith("*"))
  4382. {
  4383. sliced[2] = Math.Round(mark.TotalDays).ToString();
  4384. }
  4385. if (sliced.Length > 3)
  4386. {
  4387. if (sliced[3].StartsWith("*"))
  4388. {
  4389. sliced[3] = Math.Round(mark.TotalSeconds).ToString();
  4390. }
  4391. }
  4392. version = Boo.Lang.Builtins.join(sliced, ".");
  4393. }
  4394. return new Version(version);
  4395. }
  4396. string GetAssemblyAttributeValue(string name)
  4397. {
  4398. Attribute attribute = GetAssemblyAttribute(name);
  4399. if (null != attribute)
  4400. {
  4401. return ((StringLiteralExpression)attribute.Arguments[0]).Value;
  4402. }
  4403. return null;
  4404. }
  4405. Attribute GetAssemblyAttribute(string name)
  4406. {
  4407. Attribute[] attributes = _assemblyAttributes.Get(name);
  4408. if (attributes.Length > 0)
  4409. {
  4410. Debug.Assert(1 == attributes.Length);
  4411. return attributes[0];
  4412. }
  4413. return null;
  4414. }
  4415. protected override IType GetExpressionType(Expression node)
  4416. {
  4417. IType type = base.GetExpressionType(node);
  4418. if (TypeSystemServices.IsUnknown(type)) throw CompilerErrorFactory.InvalidNode(node);
  4419. return type;
  4420. }
  4421. }
  4422. }