Ejemplo n.º 1
0
 public AstActionBlock(ISourcePosition position, AstBlock parent, AstAction action)
     : base(position,parent)
 {
     if (action == null)
         throw new ArgumentNullException("action");
     Action = action;
 }
        /// <summary>
        /// Optimize expressions
        /// </summary>
        public static void Convert(AstBlock ast)
        {
            var variableExpressions = ast.GetExpressions().Where(x => x.Operand is AstVariable).ToList();
            var allVariables = variableExpressions.Select(x => (AstVariable)x.Operand).Distinct().ToList();
            var allStructVariables = allVariables.Where(x => x.Type.IsStruct()).ToList();

            var index = 0;
            foreach (var iterator in allStructVariables)
            {
                var variable = iterator;
                if (variable.IsThis || variable.IsParameter)
                    continue;
                if (variableExpressions.Any(x => (x.Operand == variable) && (x.Code == AstCode.Stloc)))
                    continue;

                // Get struct type
                var structType = variable.Type.Resolve();
                var defaultCtorDef = StructCallConverter.GetDefaultValueCtor(structType);
                var defaultCtor = variable.Type.CreateReference(defaultCtorDef);

                // Variable is not initialized
                var newObjExpr = new AstExpression(ast.SourceLocation, AstCode.Newobj, defaultCtor).SetType(variable.Type);
                var initExpr = new AstExpression(ast.SourceLocation, AstCode.Stloc, variable, newObjExpr).SetType(variable.Type);
                ast.Body.Insert(index++, initExpr);
            }           
        }
Ejemplo n.º 3
0
            public void ShouldBeAppliedIfFunctionDoesNotEndWithReturn()
            {
                var block     = new AstBlock(null);
                var lambdaAst = new AstParameterlessLambda(block, null);

                block.Expressions.Add(
                    new AstFunctionCall("println", new List <AstExpression>
                {
                    new AstBinaryMathOperation(BinaryMath.Plus,
                                               new AstIntegerConstant(5, null),
                                               new AstIntegerConstant(5, null),
                                               null)
                }, null));
                block.Expressions.Add(
                    new AstFunctionCall("println", new List <AstExpression>
                {
                    new AstStringConstant("hello world", null)
                }, null)
                    );

                var env = new ScriptEnvironment(new OperationCodeFactory(), new ValueFactory());

                Compiler.Compile(env,
                                 new AstRoot(new Position(0, 0))
                {
                    Expressions = { lambdaAst }
                });
                Assert.Equal(typeof(Return),
                             env.Functions[GetGlobalName(Compiler.GetAnonymousFunctionName(1))].Code.Last().Op.GetType());
            }
Ejemplo n.º 4
0
        /// <summary>
        /// Create the body of the valueOf(string) method.
        /// </summary>
        private AstBlock CreateValueOfBody(XSyntheticMethodDefinition method, XTypeSystem typeSystem)
        {
            var fields = XType.Fields.Where(x => x.IsStatic && !(x is XSyntheticFieldDefinition)).ToList();
            var ast    = AstBlock.Create <AstExpression>();

            // Find name
            foreach (var field in fields)
            {
                var notEqualLabel = new AstLabel(AstNode.NoSource, "not_equal_to" + field.Name);
                var equalsExpr    = new AstExpression(AstNode.NoSource, AstCode.Call, FrameworkReferences.StringEquals(typeSystem),
                                                      new AstExpression(AstNode.NoSource, AstCode.Ldstr, field.Name),
                                                      new AstExpression(AstNode.NoSource, AstCode.Ldloc, method.AstParameters[0]));

                // If !equals(name, field.name) goto notEqualLabel
                ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Brfalse, notEqualLabel, equalsExpr));
                // Return field object
                ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Ret, null,
                                               new AstExpression(AstNode.NoSource, AstCode.Ldsfld, field)));
                // notEqualLabel:
                ast.Body.Add(notEqualLabel);
            }

            // Return null
            ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Ret, null,
                                           new AstExpression(AstNode.NoSource, AstCode.Ldnull, null)));
            return(ast);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Create the body of the unbox(object) method.
        /// </summary>
        private AstBlock CreateUnboxBody(XSyntheticMethodDefinition method, bool isWide, AssemblyCompiler compiler)
        {
            // Prepare
            var loc = AstNode.NoSource;
            Func <AstExpression> ldValue = () => new AstExpression(loc, AstCode.Ldloc, method.AstParameters[0]);
            var afterMyEnum = new AstLabel(loc, "_afterMyEnum");

            // value instanceof MyEnumType?
            var ifNotInstanceOfMyEnum = new AstExpression(loc, AstCode.Brfalse, afterMyEnum, new AstExpression(loc, AstCode.SimpleInstanceOf, XType, ldValue()));
            var returnMyEnum          = new AstExpression(loc, AstCode.Ret, null, new AstExpression(loc, AstCode.SimpleCastclass, XType, ldValue()));

            // boxToMyEnum(UnboxInteger(value))
            var boxingType         = compiler.GetDot42InternalType("Boxing").Resolve();
            var unboxNumericMethod = boxingType.Methods.First(x => x.Name == (isWide ? "UnboxLong" : "UnboxInteger"));
            var unboxToNumeric     = new AstExpression(loc, AstCode.Call, unboxNumericMethod, ldValue());
            var numericToMyEnum    = new AstExpression(loc, isWide ? AstCode.Long_to_enum : AstCode.Int_to_enum, XType, unboxToNumeric).SetType(XType);
            var returnX            = new AstExpression(loc, AstCode.Ret, null, numericToMyEnum);

            var ast = new AstBlock(loc, new AstNode[] {
                ifNotInstanceOfMyEnum,
                returnMyEnum,
                afterMyEnum,
                returnX
            });

            return(ast);
        }
Ejemplo n.º 6
0
        private static void FixBlock(AstBlock block)
        {
            if (block == null) return;

            bool wasLastExpressionCallToMonitorEnter = false;

            foreach (AstNode node in block.GetChildren())
            {
                var expr = node as AstExpression;
                if (expr != null)
                {
                    if(expr.Code != AstCode.Nop)
                        wasLastExpressionCallToMonitorEnter = IsCallToMonitorEnter(expr);
                    continue;
                }

                var tryCatch = node as AstTryCatchBlock;
                if (wasLastExpressionCallToMonitorEnter && tryCatch != null)
                {
                    // a lock statement.
                    FixTryCatchFinally(tryCatch);
                }

                wasLastExpressionCallToMonitorEnter = false;
            }
        }
Ejemplo n.º 7
0
        private static void FixBlock(AstBlock block)
        {
            if (block == null)
            {
                return;
            }

            bool wasLastExpressionCallToMonitorEnter = false;

            foreach (AstNode node in block.GetChildren())
            {
                var expr = node as AstExpression;
                if (expr != null)
                {
                    if (expr.Code != AstCode.Nop)
                    {
                        wasLastExpressionCallToMonitorEnter = IsCallToMonitorEnter(expr);
                    }
                    continue;
                }

                var tryCatch = node as AstTryCatchBlock;
                if (wasLastExpressionCallToMonitorEnter && tryCatch != null)
                {
                    // a lock statement.
                    FixTryCatchFinally(tryCatch);
                }

                wasLastExpressionCallToMonitorEnter = false;
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Is the given field initialized in the given code?
        /// </summary>
        private static bool IsInitialized(AstBlock ast, XFieldDefinition field)
        {
            var storeCode       = field.IsStatic ? AstCode.Stsfld : AstCode.Stfld;
            var initExpressions = ast.GetSelfAndChildrenRecursive <AstExpression>(x => (x.Code == storeCode) && ((XFieldReference)x.Operand).IsSame(field)).ToList();

            return(initExpressions.Any());
        }
        /// <summary>
        /// Optimize expressions
        /// </summary>
        public static void Convert(AstBlock ast)
        {
            var variableExpressions = ast.GetExpressions().Where(x => x.Operand is AstVariable).ToList();
            var allVariables        = variableExpressions.Select(x => (AstVariable)x.Operand).Distinct().ToList();
            var allStructVariables  = allVariables.Where(x => x.Type.IsStruct()).ToList();

            var index = 0;

            foreach (var iterator in allStructVariables)
            {
                var variable = iterator;
                if (variable.IsThis || variable.IsParameter)
                {
                    continue;
                }
                if (variableExpressions.Any(x => (x.Operand == variable) && (x.Code == AstCode.Stloc)))
                {
                    continue;
                }

                // Get struct type
                var structType     = variable.Type.Resolve();
                var defaultCtorDef = StructCallConverter.GetDefaultValueCtor(structType);
                var defaultCtor    = variable.Type.CreateReference(defaultCtorDef);

                // Variable is not initialized
                var newObjExpr = new AstExpression(ast.SourceLocation, AstCode.Newobj, defaultCtor).SetType(variable.Type);
                var initExpr   = new AstExpression(ast.SourceLocation, AstCode.Stloc, variable, newObjExpr).SetType(variable.Type);
                ast.Body.Insert(index++, initExpr);
            }
        }
Ejemplo n.º 10
0
 public AstScopedBlock([NotNull] ISourcePosition p, [NotNull] AstBlock lexicalScope, string uid = null, string prefix = null)
     : base(p,lexicalScope, uid:uid, prefix:prefix)
 {
     if (lexicalScope == null)
         throw new System.ArgumentNullException("lexicalScope");
     _lexicalScope = lexicalScope;
 }
Ejemplo n.º 11
0
 public AstWhileLoop(ISourcePosition position, AstBlock parentBlock, bool isPrecondition = true,
     bool isPositive = true)
     : base(position,parentBlock)
 {
     IsPrecondition = isPrecondition;
     IsPositive = isPositive;
 }
Ejemplo n.º 12
0
        void ApplyLambdaBlock(AstBlock ast, DrawBlock parent, Block result)
        {
            if (ast.UsingBlocks == null)
            {
                var usingBlocks = new List <Block>();

                for (int j = 0, l = result.Members.Count; j < l; j++)
                {
                    var apply = result.Members[j] as Apply;

                    if (apply != null)
                    {
                        usingBlocks.Add(apply.Block);
                    }
                }

                result.SetUsingBlocks(usingBlocks.ToArray());
            }

            Expression obj = null;

            if (!parent.Method.IsStatic)
            {
                obj = new This(parent.Source, _compiler.TypeBuilder.Parameterize(parent.Method.DeclaringType)).Address;
            }

            parent.Members.Add(new Apply(ast.Name.Source, 0, result, obj));
        }
Ejemplo n.º 13
0
 /// <summary>
 /// AST ctor
 /// </summary>
 public MethodSource(XMethodDefinition method, AstBlock ast)
 {
     if (ast == null)
         throw new ArgumentNullException();
     this.method = method;
     this.ast = ast;
 }
Ejemplo n.º 14
0
 public static void Run(DecompilerContext context, AstBlock method)
 {
     var ta = new TypeAnalysis(context);
     ta.CreateDependencyGraph(method);
     ta.IdentifySingleLoadVariables();
     ta.RunInference();
 }
Ejemplo n.º 15
0
		public bool InlineAllInBlock(AstBlock block)
		{
			bool modified = false;
			List<AstNode> body = block.Body;
			if (block is AstTryCatchBlock.CatchBlock && body.Count > 1) {
				AstVariable v = ((AstTryCatchBlock.CatchBlock)block).ExceptionVariable;
				if (v != null && v.IsGenerated) {
					if (numLdloca.GetOrDefault(v) == 0 && numStloc.GetOrDefault(v) == 1 && numLdloc.GetOrDefault(v) == 1) {
						AstVariable v2;
						AstExpression ldException;
						if (body[0].Match(AstCode.Stloc, out v2, out ldException) && ldException.MatchLdloc(v)) {
							body.RemoveAt(0);
							((AstTryCatchBlock.CatchBlock)block).ExceptionVariable = v2;
							modified = true;
						}
					}
				}
			}
			for(int i = 0; i < body.Count - 1;) {
				AstVariable locVar;
				AstExpression expr;
				if (body[i].Match(AstCode.Stloc, out locVar, out expr) && InlineOneIfPossible(block.Body, i, aggressive: false)) {
					modified = true;
					i = Math.Max(0, i - 1); // Go back one step
				} else {
					i++;
				}
			}
			foreach(AstBasicBlock bb in body.OfType<AstBasicBlock>()) {
				modified |= InlineAllInBasicBlock(bb);
			}
			return modified;
		}
Ejemplo n.º 16
0
 public AstLoopBlock(string file, int line, int column, AstBlock parentBlock, 
                     string uid = null,
                     string prefix = null)
     : this (new SourcePosition(file,line,column), parentBlock, uid, prefix)
 {
     
 }
Ejemplo n.º 17
0
        private static void Generate(CodeGenContext context, AstBlock block)
        {
            AstBlockVisitor visitor = new AstBlockVisitor(block);

            var loopTargets = new Dictionary <AstBlock, (SpvInstruction, SpvInstruction)>();

            visitor.BlockEntered += (sender, e) =>
            {
                AstBlock mergeBlock = e.Block.Parent;

                if (e.Block.Type == AstBlockType.If)
                {
                    AstBlock ifTrueBlock = e.Block;
                    AstBlock ifFalseBlock;

                    if (AstHelper.Next(e.Block) is AstBlock nextBlock && nextBlock.Type == AstBlockType.Else)
                    {
                        ifFalseBlock = nextBlock;
                    }
                    else
                    {
                        ifFalseBlock = mergeBlock;
                    }

                    var condition = context.Get(AggregateType.Bool, e.Block.Condition);

                    context.SelectionMerge(context.GetNextLabel(mergeBlock), SelectionControlMask.MaskNone);
                    context.BranchConditional(condition, context.GetNextLabel(ifTrueBlock), context.GetNextLabel(ifFalseBlock));
                }
Ejemplo n.º 18
0
		public void RemoveGotos(AstBlock method)
		{
			// Build the navigation data
			parent[method] = null;
			foreach (var node in method.GetSelfAndChildrenRecursive<AstNode>()) {
				AstNode previousChild = null;
				foreach (var child in node.GetChildren()) {
					if (parent.ContainsKey(child))
						throw new Exception("The following expression is linked from several locations: " + child);
					parent[child] = node;
					if (previousChild != null)
						nextSibling[previousChild] = child;
					previousChild = child;
				}
				if (previousChild != null)
					nextSibling[previousChild] = null;
			}
			
			// Simplify gotos
			bool modified;
			do {
				modified = false;
				foreach (var gotoExpr in method.GetSelfAndChildrenRecursive<AstExpression>(e => e.Code == AstCode.Br || e.Code == AstCode.Leave)) {
					modified |= TrySimplifyGoto(gotoExpr);
				}
			} while(modified);
			
			RemoveRedundantCode(method);
		}
Ejemplo n.º 19
0
        /// <summary>
        /// Add generic instance field initialization code.
        /// </summary>
        private static void AddGenericInstanceFieldInitializationCode(AstBlock ast)
        {
            var initExpr = new AstExpression(ast.SourceLocation, AstCode.StGenericInstanceField, null,
                                             new AstExpression(ast.SourceLocation, AstCode.LdGenericInstanceTypeArgument, null));

            InsertAfter(ast, null, new[] { initExpr });
        }
Ejemplo n.º 20
0
 public AstTryCatchFinally(ISourcePosition p, AstBlock lexicalScope)
     : base(p, lexicalScope)
 {
     TryBlock = new AstScopedBlock(p, this);
     CatchBlock = new AstScopedBlock(p, TryBlock);
     FinallyBlock = new AstScopedBlock(p, TryBlock);
 }
Ejemplo n.º 21
0
 protected AstScopedExpr([NotNull] ISourcePosition position, [NotNull] AstBlock lexicalScope)
     : base(position)
 {
     if (lexicalScope == null)
         throw new System.ArgumentNullException("lexicalScope");
     _lexicalScope = lexicalScope;
 }
Ejemplo n.º 22
0
    public override AstNode ShallowClone()
    {
        var res = new AstBlock(Source, Start, End);

        res.Body.AddRange(Body.AsReadOnlySpan());
        return(res);
    }
Ejemplo n.º 23
0
 protected AstScopedExpr([NotNull] string file, int line, int column, [NotNull] AstBlock lexicalScope)
     : base(file, line, column)
 {
     if (lexicalScope == null)
         throw new System.ArgumentNullException("lexicalScope");
     _lexicalScope = lexicalScope;
 }
Ejemplo n.º 24
0
 internal AstScopedExpr([NotNull] Parser p, [NotNull]  AstBlock lexicalScope)
     : base(p)
 {
     if (lexicalScope == null)
         throw new System.ArgumentNullException("lexicalScope");
     _lexicalScope = lexicalScope;
 }
Ejemplo n.º 25
0
        /// <summary>
        /// Create the body of the values() method.
        /// </summary>
        private AstBlock CreateValuesBody()
        {
            var fields = XType.Fields.Where(x => x.IsStatic && !(x is XSyntheticFieldDefinition)).ToList();

            // Allocate array
            var arrVar = new AstGeneratedVariable("array", "array")
            {
                Type = new XArrayType(XType)
            };
            var createArr = new AstExpression(AstNode.NoSource, AstCode.Stloc, arrVar,
                                              new AstExpression(AstNode.NoSource, AstCode.Newarr, XType,
                                                                new AstExpression(AstNode.NoSource, AstCode.Ldc_I4, fields.Count)));
            var ast = AstBlock.CreateOptimizedForTarget(createArr);

            // Initialize array
            var index = 0;

            foreach (var field in fields)
            {
                ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Stelem_Any, null,
                                               new AstExpression(AstNode.NoSource, AstCode.Ldloc, arrVar),
                                               new AstExpression(AstNode.NoSource, AstCode.Ldc_I4, index),
                                               new AstExpression(AstNode.NoSource, AstCode.Ldsfld, field)));
                index++;
            }

            // Return array
            ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Ret, null,
                                           new AstExpression(AstNode.NoSource, AstCode.Ldloc, arrVar)));
            return(ast);
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Group input into a set of blocks that can be later arbitraliby schufled.
        /// The method adds necessary branches to make control flow between blocks
        /// explicit and thus order independent.
        /// </summary>
        private void SplitToBasicBlocks(AstBlock block)
        {
            var basicBlocks = new List <AstNode>();

            var entryLabel = block.Body.FirstOrDefault() as AstLabel ?? new AstLabel(block.SourceLocation, "Block_" + (nextLabelIndex++));
            var basicBlock = new AstBasicBlock(block.SourceLocation);

            basicBlocks.Add(basicBlock);
            basicBlock.Body.Add(entryLabel);
            block.EntryGoto = new AstExpression(block.SourceLocation, AstCode.Br, entryLabel);

            if (block.Body.Count > 0)
            {
                if (block.Body[0] != entryLabel)
                {
                    basicBlock.Body.Add(block.Body[0]);
                }

                for (var i = 1; i < block.Body.Count; i++)
                {
                    var lastNode = block.Body[i - 1];
                    var currNode = block.Body[i];

                    // Start a new basic block if necessary
                    if (currNode is AstLabel ||
                        currNode is AstTryCatchBlock || // Counts as label
                        lastNode.IsConditionalControlFlow() ||
                        lastNode.IsUnconditionalControlFlow())
                    {
                        // Try to reuse the label
                        var label = currNode as AstLabel ?? new AstLabel(currNode.SourceLocation, "Block_" + (nextLabelIndex++));

                        // Terminate the last block
                        if (!lastNode.IsUnconditionalControlFlow())
                        {
                            // Explicit branch from one block to other
                            basicBlock.Body.Add(new AstExpression(lastNode.SourceLocation, AstCode.Br, label));
                        }

                        // Start the new block
                        basicBlock = new AstBasicBlock(currNode.SourceLocation);
                        basicBlocks.Add(basicBlock);
                        basicBlock.Body.Add(label);

                        // Add the node to the basic block
                        if (currNode != label)
                        {
                            basicBlock.Body.Add(currNode);
                        }
                    }
                    else
                    {
                        basicBlock.Body.Add(currNode);
                    }
                }
            }

            block.Body = basicBlocks;
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Convert the given method into optimized Ast format.
        /// </summary>
        internal protected static AstNode CreateOptimizedAst(AssemblyCompiler compiler, MethodSource source,
            bool generateSetNextInstructionCode, 
            StopAstConversion debugStop = StopAstConversion.None,
            AstOptimizationStep debugStopOptimizing = AstOptimizationStep.None
            )
        {
            // Build AST
            DecompilerContext context;
            AstBlock ast;
            if (source.IsDotNet)
            {
                context = new DecompilerContext(source.Method);
                var astBuilder = new IL2Ast.AstBuilder(source.ILMethod, true, context);
                var children = astBuilder.Build();
                ast = new AstBlock(children.Select(x => x.SourceLocation).FirstOrDefault(), children);
                if ((source.ILMethod.IsConstructor) && (source.Method.DeclaringType.Fields.Any(x => x.FieldType.IsEnum() || x.Name.EndsWith(NameConstants.Atomic.FieldUpdaterPostfix))))
                {
                    // Ensure all fields are initialized
                    AddFieldInitializationCode(compiler, source, ast);
                }
                if (source.Method.NeedsGenericInstanceTypeParameter && (source.Name == ".ctor"))
                {
                    // Add code to save the generic instance type parameter into the generic instance field.
                    AddGenericInstanceFieldInitializationCode(source, ast, compiler.Module.TypeSystem);
                }
            }
            else if (source.IsJava)
            {
                var astBuilder = new Java2Ast.AstBuilder(compiler.Module, source.JavaMethod, source.Method.DeclaringType, true);
                context = new DecompilerContext(source.Method);
                ast = astBuilder.Build();
            }
            else if (source.IsAst)
            {
                context = new DecompilerContext(source.Method);
                ast = source.Ast;
            }
            else
            {
                throw new NotSupportedException("Unknown source");
            }

            if (debugStop == StopAstConversion.AfterILConversion) return ast;

            // Optimize AST
            var astOptimizer = new AstOptimizer(context, ast);
            astOptimizer.Optimize(debugStopOptimizing);

            if (debugStop == StopAstConversion.AfterOptimizing) return ast;

            // Optimize AST towards the target
            TargetConverters.Convert(context, ast, source, compiler, debugStop);

            if(generateSetNextInstructionCode)
                SetNextInstructionGenerator.Convert(ast, source, compiler);

            // Return return
            return ast;
        }
Ejemplo n.º 28
0
 /// <summary>
 /// Create the body of the ctor.
 /// </summary>
 private AstBlock CreateCtorBody()
 {
     return(AstBlock.CreateOptimizedForTarget(
                // Call base ctor
                new AstExpression(AstNode.NoSource, AstCode.CallBaseCtor, 0,
                                  new AstExpression(AstNode.NoSource, AstCode.Ldthis, null)),
                // Return
                new AstExpression(AstNode.NoSource, AstCode.Ret, null)));
 }
Ejemplo n.º 29
0
 /// <summary>
 /// Create the body of the Create(int|long) method.
 /// </summary>
 private AstBlock CreateCreateBody(XSyntheticMethodDefinition method, XMethodReference ctor)
 {
     return(AstBlock.CreateOptimizedForTarget(
                new AstExpression(AstNode.NoSource, AstCode.Ret, null,
                                  new AstExpression(AstNode.NoSource, AstCode.Newobj, ctor,
                                                    new AstExpression(AstNode.NoSource, AstCode.Ldstr, "?"),
                                                    new AstExpression(AstNode.NoSource, AstCode.Ldc_I4, -1),
                                                    new AstExpression(AstNode.NoSource, AstCode.Ldloc, method.AstParameters[0])))));
 }
Ejemplo n.º 30
0
 public AstForLoop(ISourcePosition position, AstBlock parentBlock)
     : this(position, new AstScopedBlock(
         position,
         new AstScopedBlock(
             position, 
             parentBlock, prefix: "init"),
         prefix:"next"))
 {
 }
Ejemplo n.º 31
0
 /// <summary>
 /// AST ctor
 /// </summary>
 public MethodSource(XMethodDefinition method, AstBlock ast)
 {
     if (ast == null)
     {
         throw new ArgumentNullException();
     }
     this.method = method;
     this.ast    = ast;
 }
Ejemplo n.º 32
0
 public VariableDefinition(AstBlock parentBlock, AstNode parent, AstVar astVar, AstVarDef astVarDef, bool canMoveInitialization, int originalIndexInVar)
 {
     ParentBlock           = parentBlock;
     Parent                = parent;
     AstVar                = astVar;
     CanMoveInitialization = canMoveInitialization;
     OriginalIndexInVar    = originalIndexInVar;
     AstVarDef             = astVarDef;
 }
Ejemplo n.º 33
0
        internal sealed override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            string debugString = (IsSingletonDeclaration) ? "SINGLETON" : ((this is ClassDefinition) ? "CLASS" : "MODULE") + " " + QualifiedName.Name;

            ScopeBuilder outerLocals = gen.CurrentScope;

            // definition needs to take place outside the defined lexical scope:
            var definition   = MakeDefinitionExpression(gen);
            var selfVariable = outerLocals.DefineHiddenVariable("#module", typeof(RubyModule));
            var parentScope  = gen.CurrentScopeVariable;

            // inner locals:
            ScopeBuilder scope         = DefineLocals();
            var          scopeVariable = scope.DefineHiddenVariable("#scope", typeof(RubyScope));

            gen.EnterModuleDefinition(
                scope,
                selfVariable,
                scopeVariable,
                IsSingletonDeclaration
                );

            // transform body:
            MSA.Expression transformedBody = Body.TransformRead(gen);

            // outer local:
            MSA.Expression resultVariable = outerLocals.DefineHiddenVariable("#result", transformedBody.Type);

            // begin with new scope
            //   self = DefineModule/Class(... parent scope here ...)
            //   <body>
            // end
            MSA.Expression result = new AstBlock {
                gen.DebugMarker(debugString),
                Ast.Assign(selfVariable, definition),
                scope.CreateScope(
                    scopeVariable,
                    Methods.CreateModuleScope.OpCall(
                        scope.MakeLocalsStorage(),
                        scope.GetVariableNamesExpression(),
                        parentScope,
                        selfVariable
                        ),
                    Ast.Block(
                        Ast.Assign(resultVariable, transformedBody),
                        AstUtils.Empty()
                        )
                    ),
                gen.DebugMarker("END OF " + debugString),
                resultVariable
            };

            gen.LeaveModuleDefinition();

            return(result);
        }
Ejemplo n.º 34
0
 bool BlockIsDisallowed(AstBlock node)
 {
     return(node is AstSwitch ||
            node is AstSwitchBranch ||
            node is AstLambda ||
            node is AstTry ||
            node is AstCatch ||
            node is AstFinally ||
            node is AstClass);
 }
Ejemplo n.º 35
0
 public AstCondition(ISourcePosition p, AstBlock parentBlock, AstExpr condition, bool isNegative = false)
     : base(p)
 {
     IfBlock = new AstScopedBlock(p,parentBlock,prefix: "if");
     ElseBlock = new AstScopedBlock(p,parentBlock,prefix:"else");
     if (condition == null)
         throw new ArgumentNullException("condition");
     Condition = condition;
     IsNegative = isNegative;
 }
Ejemplo n.º 36
0
        /// <summary>
        /// Create the body of the IntValue or LongValue method.
        /// </summary>
        private AstBlock CreateIntOrLongValueBody()
        {
            // Get value__
            var valueField = XType.Fields.First(x => !x.IsStatic && x.Name == NameConstants.Enum.ValueFieldName);

            return(AstBlock.CreateOptimizedForTarget(
                       new AstExpression(AstNode.NoSource, AstCode.Ret, null,
                                         new AstExpression(AstNode.NoSource, AstCode.Ldfld, valueField,
                                                           new AstExpression(AstNode.NoSource, AstCode.Ldthis, null)))));
        }
Ejemplo n.º 37
0
		public static void RemoveRedundantCode(AstBlock method)
		{
			// Remove dead lables and nops
			HashSet<AstLabel> liveLabels = new HashSet<AstLabel>(method.GetSelfAndChildrenRecursive<AstExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets()));
			foreach(AstBlock block in method.GetSelfAndChildrenRecursive<AstBlock>()) {
				block.Body = block.Body.Where(n => !n.Match(AstCode.Nop) && !(n is AstLabel && !liveLabels.Contains((AstLabel)n))).ToList();
			}
				
			// Remove redundant break at the end of case
			// Remove redundant case blocks altogether
			foreach(AstSwitch ilSwitch in method.GetSelfAndChildrenRecursive<AstSwitch>()) {
				foreach(AstBlock ilCase in ilSwitch.CaseBlocks) {
					Debug.Assert(ilCase.EntryGoto == null);
					
					int count = ilCase.Body.Count;
					if (count >= 2) {
						if (ilCase.Body[count - 2].IsUnconditionalControlFlow() &&
						    ilCase.Body[count - 1].Match(AstCode.LoopOrSwitchBreak)) 
						{
							ilCase.Body.RemoveAt(count - 1);
						}
					}
				}
				
				var defaultCase = ilSwitch.CaseBlocks.SingleOrDefault(cb => cb.Values == null);
				// If there is no default block, remove empty case blocks
				if (defaultCase == null || (defaultCase.Body.Count == 1 && defaultCase.Body.Single().Match(AstCode.LoopOrSwitchBreak))) {
					ilSwitch.CaseBlocks.RemoveAll(b => b.Body.Count == 1 && b.Body.Single().Match(AstCode.LoopOrSwitchBreak));
				}
			}
			
			// Remove redundant return at the end of method
			if (method.Body.Count > 0 && method.Body.Last().Match(AstCode.Ret) && ((AstExpression)method.Body.Last()).Arguments.Count == 0) {
				method.Body.RemoveAt(method.Body.Count - 1);
			}
			
			// Remove unreachable return statements
			bool modified = false;
			foreach(AstBlock block in method.GetSelfAndChildrenRecursive<AstBlock>()) {
				for (int i = 0; i < block.Body.Count - 1;) {
					if (block.Body[i].IsUnconditionalControlFlow() && block.Body[i+1].Match(AstCode.Ret)) {
						modified = true;
						block.Body.RemoveAt(i+1);
					} else {
						i++;
					}
				}
			}
			if (modified) {
				// More removals might be possible
				new GotoRemoval().RemoveGotos(method);
			}
		}
Ejemplo n.º 38
0
 /// <summary>
 /// Insert all expressions after the given marker.
 /// </summary>
 private static void InsertAfter(AstBlock ast, AstExpression marker, IEnumerable <AstExpression> expressions)
 {
     if (marker != null)
     {
         var block = ast.GetSelfAndChildrenRecursive <AstBlock>(b => b.Body.Contains(marker)).First();
         var index = block.Body.IndexOf(marker);
         block.Body.InsertRange(index + 1, expressions);
     }
     else
     {
         ast.Body.InsertRange(0, expressions);
     }
 }
Ejemplo n.º 39
0
        /// <summary>
        /// Create the body of the values() method.
        /// </summary>
        private AstBlock CreateValuesBody(XFieldDefinition enumInfoField, XTypeSystem typeSystem)
        {
            var internalEnumInfoType = Compiler.GetDot42InternalType("EnumInfo");
            var valuesMethod         = new XMethodReference.Simple("Values", true, typeSystem.Object, internalEnumInfoType);

            var ast = AstBlock.CreateOptimizedForTarget(
                new AstExpression(AstNode.NoSource, AstCode.Ret, null,
                                  new AstExpression(AstNode.NoSource, AstCode.SimpleCastclass, new XArrayType(XType),
                                                    new AstExpression(AstNode.NoSource, AstCode.Call, valuesMethod,
                                                                      new AstExpression(AstNode.NoSource, AstCode.Ldsfld, enumInfoField)))));

            return(ast);
        }
Ejemplo n.º 40
0
 /// <summary>
 ///     Creates a new macro context in the specified macro session.
 /// </summary>
 /// <param name = "session">The macro expansion session.</param>
 /// <param name = "invocation">The node that is being expanded.</param>
 /// <param name = "isJustEffect">Whether the nodes return value will be discarded by the surrounding program.</param>
 internal MacroContext(MacroSession session, AstGetSet invocation, bool isJustEffect)
 {
     if (session == null)
         throw new ArgumentNullException("session");
     if (invocation == null)
         throw new ArgumentNullException("invocation");
     _isJustEffect = isJustEffect;
     _invocation = invocation;
     _session = session;
     _block = new AstScopedBlock(invocation.Position, session.CurrentBlock);
     _isPartialApplication = _invocation.Arguments.Any(AstPartiallyApplicable.IsPlaceholder);
     _sentinelBlock = session.Target.CurrentBlock;
 }
Ejemplo n.º 41
0
        /// <summary>
        /// Create the body of the ctor.
        /// </summary>
        private AstBlock CreateCtorBody()
        {
            // here we could also preserve the original underlying type.
            bool isWide     = Type.GetEnumUnderlyingType().Resolve().IsWide();
            var  underlying = isWide ? Compiler.Module.TypeSystem.Long : Compiler.Module.TypeSystem.Int;

            return(AstBlock.CreateOptimizedForTarget(
                       // Call base ctor
                       new AstExpression(AstNode.NoSource, AstCode.CallBaseCtor, 0,
                                         new AstExpression(AstNode.NoSource, AstCode.Ldthis, null),
                                         new AstExpression(AstNode.NoSource, AstCode.TypeOf, underlying)),
                       // Return
                       new AstExpression(AstNode.NoSource, AstCode.Ret, null)));
        }
Ejemplo n.º 42
0
        /// <summary>
        /// Perform one pass of a given optimization on this block.
        /// This block must consist of only basicblocks.
        /// </summary>
        public static bool RunOptimization(this AstBlock block, Func <List <AstNode>, AstBasicBlock, int, bool> optimization)
        {
            bool           modified = false;
            List <AstNode> body     = block.Body;

            for (int i = body.Count - 1; i >= 0; i--)
            {
                if (i < body.Count && optimization(body, (AstBasicBlock)body[i], i))
                {
                    modified = true;
                }
            }
            return(modified);
        }
Ejemplo n.º 43
0
        /// <summary>
        /// Convert the given method into optimized Ast format.
        /// </summary>
        protected static AstNode CreateOptimizedAst(AssemblyCompiler compiler, MethodSource source)
        {
            // Build AST
            DecompilerContext context;
            AstBlock          ast;

            if (source.IsDotNet)
            {
                context = new DecompilerContext(source.Method);
                var astBuilder = new IL2Ast.AstBuilder(source.ILMethod, true, context);
                var children   = astBuilder.Build();
                ast = new AstBlock(children.Select(x => x.SourceLocation).FirstOrDefault(), children);
                if ((source.ILMethod.IsConstructor) && (source.Method.DeclaringType.Fields.Any(x => x.FieldType.IsEnum())))
                {
                    // Ensure all fields are initialized
                    AddFieldInitializationCode(source, ast);
                }
                if (source.Method.NeedsGenericInstanceTypeParameter && (source.Name == ".ctor"))
                {
                    // Add code to safe the generic instance type parameter into the generic instance field.
                    AddGenericInstanceFieldInitializationCode(ast);
                }
            }
            else if (source.IsJava)
            {
                var astBuilder = new Java2Ast.AstBuilder(compiler.Module, source.JavaMethod, source.Method.DeclaringType, true);
                context = new DecompilerContext(source.Method);
                ast     = astBuilder.Build();
            }
            else if (source.IsAst)
            {
                context = new DecompilerContext(source.Method);
                ast     = source.Ast;
            }
            else
            {
                throw new NotSupportedException("Unknown source");
            }

            // Optimize AST
            var astOptimizer = new AstOptimizer(context, ast);

            astOptimizer.Optimize();

            // Optimize AST towards the target
            TargetConverters.Convert(context, ast, source, compiler);

            // Return return
            return(ast);
        }
Ejemplo n.º 44
0
		public SimpleControlFlow(DecompilerContext context, AstBlock method)
		{
			this.context = context;
			this.typeSystem = context.CurrentModule.TypeSystem;
			
			foreach(AstLabel target in method.GetSelfAndChildrenRecursive<AstExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets())) {
				labelGlobalRefCount[target] = labelGlobalRefCount.GetOrDefault(target) + 1;
			}
			foreach(AstBasicBlock bb in method.GetSelfAndChildrenRecursive<AstBasicBlock>()) {
				foreach(AstLabel label in bb.GetChildren().OfType<AstLabel>()) {
					labelToBasicBlock[label] = bb;
				}
			}
		}
Ejemplo n.º 45
0
        /// <summary>
        /// Convert the given method into optimized Ast format.
        /// </summary>
        protected static AstNode CreateOptimizedAst(AssemblyCompiler compiler, MethodSource source)
        {
            // Build AST
            DecompilerContext context;
            AstBlock ast;
            if (source.IsDotNet)
            {
                context = new DecompilerContext(source.Method);
                var astBuilder = new IL2Ast.AstBuilder(source.ILMethod, true, context);
                var children = astBuilder.Build();
                ast = new AstBlock(children.Select(x => x.SourceLocation).FirstOrDefault(), children);
                if ((source.ILMethod.IsConstructor) && (source.Method.DeclaringType.Fields.Any(x => x.FieldType.IsEnum())))
                {
                    // Ensure all fields are initialized
                    AddFieldInitializationCode(source, ast);
                }
                if (source.Method.NeedsGenericInstanceTypeParameter && (source.Name == ".ctor"))
                {
                    // Add code to safe the generic instance type parameter into the generic instance field.
                    AddGenericInstanceFieldInitializationCode(ast);
                }
            }
            else if (source.IsJava)
            {
                var astBuilder = new Java2Ast.AstBuilder(compiler.Module, source.JavaMethod, source.Method.DeclaringType, true);
                context = new DecompilerContext(source.Method);
                ast = astBuilder.Build();
            }
            else if (source.IsAst)
            {
                context = new DecompilerContext(source.Method);
                ast = source.Ast;
            }
            else
            {
                throw new NotSupportedException("Unknown source");
            }

            // Optimize AST
            var astOptimizer = new AstOptimizer(context, ast);
            astOptimizer.Optimize();

            // Optimize AST towards the target
            TargetConverters.Convert(context, ast, source, compiler);

            // Return return
            return ast;
        }
Ejemplo n.º 46
0
        /// <summary>
        /// Reduces the branch codes to just br and brtrue.
        /// Moves ILRanges to the branch argument
        /// </summary>
        void ReduceBranchInstructionSet(AstBlock block)
        {
            for (int i = 0; i < block.Body.Count; i++)
            {
                AstExpression expr = block.Body[i] as AstExpression;
                if (expr != null && expr.Prefixes == null)
                {
                    AstCode op;
                    switch (expr.Code)
                    {
                    case AstCode.Switch:
                    case AstCode.LookupSwitch:
                    case AstCode.Brtrue:
                    case AstCode.Brfalse:
                        expr.Arguments.Single().ILRanges.AddRange(expr.ILRanges);
                        expr.ILRanges.Clear();
                        continue;

                    case AstCode.__Beq: op = AstCode.Ceq; break;

                    case AstCode.__Bne_Un: op = AstCode.Cne; break;

                    case AstCode.__Bgt: op = AstCode.Cgt; break;

                    case AstCode.__Bgt_Un: op = AstCode.Cgt_Un; break;

                    case AstCode.__Ble: op = AstCode.Cle; break;

                    case AstCode.__Ble_Un: op = AstCode.Cle_Un; break;

                    case AstCode.__Blt: op = AstCode.Clt; break;

                    case AstCode.__Blt_Un: op = AstCode.Clt_Un; break;

                    case AstCode.__Bge: op = AstCode.Cge; break;

                    case AstCode.__Bge_Un: op = AstCode.Cge_Un; break;

                    default:
                        continue;
                    }
                    var newExpr = new AstExpression(expr.SourceLocation, op, null, expr.Arguments);
                    block.Body[i] = new AstExpression(expr.SourceLocation, AstCode.Brtrue, expr.Operand, newExpr);
                    newExpr.ILRanges.AddRange(expr.ILRanges);
                }
            }
        }
Ejemplo n.º 47
0
        public static bool RunOptimization(this AstBlock block, Func <List <AstNode>, AstExpression, int, bool> optimization)
        {
            bool modified = false;

            foreach (AstBasicBlock bb in block.Body)
            {
                for (int i = bb.Body.Count - 1; i >= 0; i--)
                {
                    AstExpression expr = bb.Body.ElementAtOrDefault(i) as AstExpression;
                    if (expr != null && optimization(bb.Body, expr, i))
                    {
                        modified = true;
                    }
                }
            }
            return(modified);
        }
Ejemplo n.º 48
0
        public SimpleControlFlow(DecompilerContext context, AstBlock method)
        {
            this.context    = context;
            this.typeSystem = context.CurrentModule.TypeSystem;

            foreach (AstLabel target in method.GetSelfAndChildrenRecursive <AstExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets()))
            {
                labelGlobalRefCount[target] = labelGlobalRefCount.GetOrDefault(target) + 1;
            }
            foreach (AstBasicBlock bb in method.GetSelfAndChildrenRecursive <AstBasicBlock>())
            {
                foreach (AstLabel label in bb.GetChildren().OfType <AstLabel>())
                {
                    labelToBasicBlock[label] = bb;
                }
            }
        }
Ejemplo n.º 49
0
        internal static MSA.Expression /*!*/ MakeCallWithBlockRetryable(AstGenerator /*!*/ gen, MSA.Expression /*!*/ invoke,
                                                                        MSA.Expression blockArgVariable, MSA.Expression transformedBlock, bool isBlockDefinition)
        {
            Assert.NotNull(invoke);
            Debug.Assert((blockArgVariable == null) == (transformedBlock == null));

            // see Ruby Language.doc/Control Flow Implementation/Method Call With a Block
            MSA.Expression          resultVariable = gen.CurrentScope.DefineHiddenVariable("#method-result", typeof(object));
            MSA.ParameterExpression evalUnwinder;

            MSA.LabelTarget retryLabel = Ast.Label("retry");

            var result = new AstBlock {
                Ast.Assign(blockArgVariable, Ast.Convert(transformedBlock, blockArgVariable.Type)),

                Ast.Label(retryLabel),

                (isBlockDefinition) ? Methods.InitializeBlock.OpCall(blockArgVariable) : null,

                AstUtils.Try(
                    Ast.Assign(resultVariable, invoke)
                    ).Catch(evalUnwinder = Ast.Parameter(typeof(EvalUnwinder), "#u"),
                            Ast.Assign(
                                resultVariable,
                                Ast.Field(evalUnwinder, EvalUnwinder.ReturnValueField)
                                )
                            ),

                Ast.IfThen(Ast.TypeEqual(resultVariable, typeof(BlockReturnResult)),
                           Ast.IfThenElse(Methods.IsRetrySingleton.OpCall(resultVariable),
                                          // retry:
                                          AstUtils.IfThenElse(Ast.Equal(gen.MakeMethodBlockParameterRead(), blockArgVariable),
                                                              RetryStatement.TransformRetry(gen),
                                                              Ast.Goto(retryLabel)
                                                              ),
                                          // return:
                                          gen.Return(ReturnStatement.Propagate(gen, resultVariable))
                                          )
                           ),

                resultVariable
            };

            return(result);
        }
Ejemplo n.º 50
0
        /// <summary>
        /// Perform all dot42 related Ast conversions.
        /// </summary>
        public static void Convert(DecompilerContext context, AstBlock ast, MethodSource currentMethod, AssemblyCompiler compiler)
        {
            if (ast.IsOptimizedForTarget)
            {
                return;
            }
#if DEBUG
            //Debugger.Launch();
            if ((currentMethod.Method != null) && (currentMethod.Method.Name.Equals("runTest", StringComparison.OrdinalIgnoreCase)))
            {
                //Debugger.Launch();
            }
#endif

            IntPtrConverter.Convert(ast, compiler);
            TypeOfConverter.Convert(ast, compiler);
            BranchOptimizer.Convert(ast);
            CompoundAssignmentConverter.Convert(ast);
            ByReferenceParamConverter.Convert(context, ast, compiler);
            CompareUnorderedConverter.Convert(ast);
            EnumConverter.Convert(ast, compiler);
            EnumOptimizer.Convert(ast, compiler);

            // Keep this order
            NullableConverter.Convert(ast, compiler);
            PrimitiveAddressOfConverter.Convert(ast, currentMethod, compiler);
            StructCallConverter.Convert(ast, compiler);
            // end

            InitializeStructVariablesConverter.Convert(ast);
            DelegateConverter.Convert(ast);
            LdcWideConverter.Convert(ast);
            LdLocWithConversionConverter.Convert(ast);
            ConvertAfterLoadConversionConverter.Convert(ast);
            ConvertBeforeStoreConversionConverter.Convert(ast);
            CleanupConverter.Convert(ast);

            GenericsConverter.Convert(ast);

            // Expand cast expressions
            CastConverter.Convert(ast, currentMethod, compiler);

            // Expand generic instance information
            GenericInstanceConverter.Convert(ast, currentMethod, compiler);
        }
Ejemplo n.º 51
0
        /// <summary>
        /// Perform all dot42 related Ast conversions.
        /// </summary>
        public static void Convert(DecompilerContext context, AstBlock ast, MethodSource currentMethod, AssemblyCompiler compiler)
        {
            if (ast.IsOptimizedForTarget)
                return;            
#if DEBUG
            //Debugger.Launch();
            if ((currentMethod.Method != null) && (currentMethod.Method.Name.Equals("runTest", StringComparison.OrdinalIgnoreCase)))
            {
                //Debugger.Launch();
            }
#endif

            IntPtrConverter.Convert(ast, compiler);
            TypeOfConverter.Convert(ast, compiler);
            BranchOptimizer.Convert(ast);
            CompoundAssignmentConverter.Convert(ast);
            ByReferenceParamConverter.Convert(context, ast, compiler);
            CompareUnorderedConverter.Convert(ast);
            EnumConverter.Convert(ast, compiler);
            EnumOptimizer.Convert(ast, compiler);

            // Keep this order
            NullableConverter.Convert(ast, compiler);
            PrimitiveAddressOfConverter.Convert(ast, currentMethod, compiler);
            StructCallConverter.Convert(ast, compiler);
            // end

            InitializeStructVariablesConverter.Convert(ast);
            DelegateConverter.Convert(ast);
            LdcWideConverter.Convert(ast);
            LdLocWithConversionConverter.Convert(ast);
            ConvertAfterLoadConversionConverter.Convert(ast);
            ConvertBeforeStoreConversionConverter.Convert(ast);
            CleanupConverter.Convert(ast);

            GenericsConverter.Convert(ast);

            // Expand cast expressions
            CastConverter.Convert(ast, currentMethod, compiler);

            // Expand generic instance information
            GenericInstanceConverter.Convert(ast, currentMethod, compiler);

        }
Ejemplo n.º 52
0
        private MSA.Expression /*!*/ TransformWrite(AstGenerator /*!*/ gen, MSA.Expression /*!*/ transformedRight, bool isSimpleRhs)
        {
            var writes = new AstBlock();

            MSA.Expression rightList = gen.CurrentScope.DefineHiddenVariable("#rhs", typeof(IList));
            MSA.Expression result;

            if (isSimpleRhs)
            {
                // 1.9 returns the RHS, not an unsplatted array, if there is just a single RHS:
                result = gen.CurrentScope.DefineHiddenVariable("#pr", transformedRight.Type);
                writes.Add(Ast.Assign(result, transformedRight));

                transformedRight = AstUtils.LightDynamic(ImplicitSplatAction.Make(gen.Context), typeof(IList), result);
            }
            else
            {
                result = rightList;
            }

            writes.Add(Ast.Assign(rightList, transformedRight));

            for (int i = 0; i < _unsplattedValueIndex; i++)
            {
                writes.Add(_leftValues[i].TransformWrite(gen, Methods.GetArrayItem.OpCall(rightList, AstUtils.Constant(i))));
            }

            if (HasUnsplattedValue)
            {
                MSA.Expression explicitCount = AstUtils.Constant(_leftValues.Length - 1);

                // remaining RHS values:
                MSA.Expression array = Methods.GetArrayRange.OpCall(rightList, AstUtils.Constant(_unsplattedValueIndex), explicitCount);
                writes.Add(_leftValues[_unsplattedValueIndex].TransformWrite(gen, array));

                for (int i = _unsplattedValueIndex + 1; i < _leftValues.Length; i++)
                {
                    writes.Add(_leftValues[i].TransformWrite(gen, Methods.GetTrailingArrayItem.OpCall(rightList, AstUtils.Constant(_leftValues.Length - i), explicitCount)));
                }
            }

            writes.Add(result);
            return(writes);
        }
Ejemplo n.º 53
0
 /// <summary>
 /// Add initialization code to the given constructor for non-initialized struct fields.
 /// </summary>
 private static void AddFieldInitializationCode(MethodSource ctor, AstBlock ast)
 {
     List<XFieldDefinition> fieldsToInitialize;
     var declaringType = ctor.Method.DeclaringType;
     var fieldsThatMayNeedInitialization = declaringType.Fields.Where(x => x.IsReachable && x.FieldType.IsEnum());
     var index = 0;
     if (ctor.Method.IsStatic)
     {
         fieldsToInitialize = fieldsThatMayNeedInitialization.Where(x => x.IsStatic && !IsInitialized(ast, x)).ToList();
         foreach (var field in fieldsToInitialize)
         {
             var defaultExpr = new AstExpression(ast.SourceLocation, AstCode.DefaultValue, field.FieldType);
             var initExpr = new AstExpression(ast.SourceLocation, AstCode.Stsfld, field, defaultExpr);
             ast.Body.Insert(index++, initExpr);
         }
     }
     else
     {
         // If there is a this ctor being called, we do not have to initialize here.
         var thisCalls = ast.GetSelfAndChildrenRecursive<AstExpression>(x => (x.Code == AstCode.Call) && ((XMethodReference) x.Operand).DeclaringType.IsSame(declaringType));
         if (thisCalls.Any(x => ((XMethodReference) x.Operand).Name == ".ctor"))
             return;
         fieldsToInitialize = fieldsThatMayNeedInitialization.Where(x => !x.IsStatic && !IsInitialized(ast, x)).ToList();
         if (fieldsToInitialize.Any())
         {
             var baseCall = FindFirstBaseCtorCall(ast, declaringType);
             var initExpressions = new List<AstExpression>();
             foreach (var field in fieldsToInitialize)
             {
                 var thisExpr = new AstExpression(ast.SourceLocation, AstCode.Ldthis, null);
                 var defaultExpr = new AstExpression(ast.SourceLocation, AstCode.DefaultValue, field.FieldType);
                 initExpressions.Add(new AstExpression(ast.SourceLocation, AstCode.Stfld, field, thisExpr, defaultExpr));
             }
             InsertAfter(ast, baseCall, initExpressions);
         }
     }
 }
Ejemplo n.º 54
0
        /// <summary>
        /// Convert the given method to a list of Ast nodes.
        /// </summary>
        public AstBlock Build()
        {
            if ((codeAttr == null) || (codeAttr.Code.Length == 0))
                return new AstBlock((ISourceLocation)null);

            var body = StackAnalysis();
            var offset2ByteCode = new Dictionary<int, ByteCode>();
            foreach (var bc in body)
            {
                offset2ByteCode[bc.Offset] = bc;
            }
            var blockStarts = SplitInBlocks(body, validExceptionHandlers);
            var list = ConvertToAst(body, new HashSet<ExceptionHandler>(validExceptionHandlers), blockStarts, 0, offset2ByteCode);
            var ast = new AstBlock(list.Select(x => x.SourceLocation).FirstOrDefault(), list);

            if (methodDef.IsSynchronized)
            {
                // Wrap in synchronization block
                var sl = ast.SourceLocation;
                var tryCatch = new AstTryCatchBlock(sl);
                // try-lock(this)
                var lockExpr = methodDef.IsStatic ?
                    new AstExpression(sl, AstCode.TypeOf, declaringType) :
                    new AstExpression(sl, AstCode.Ldthis, null);
                ast.Body.Insert(0, new AstExpression(sl, AstCode.Call, MonitorMethodReference("Enter"), new AstExpression(lockExpr)));
                tryCatch.TryBlock = ast;
                // finally-unlock(this)
                tryCatch.FinallyBlock = new AstBlock(sl, 
                    new AstExpression(sl, AstCode.Call, MonitorMethodReference("Exit"), new AstExpression(lockExpr)),
                    new AstExpression(sl, AstCode.Endfinally, null));
                // Wrap try/catch in block
                ast = new AstBlock(sl, tryCatch);
            }

            return ast;
        }
Ejemplo n.º 55
0
        internal MSA.Expression/*!*/ TransformStatements(MSA.Expression prologue, Statements/*!*/ statements, MSA.Expression epilogue, 
            ResultOperation resultOperation) {

            Assert.NotNull(statements);

            int count = statements.Count + (prologue != null ? 1 : 0) + (epilogue != null ? 1 : 0);

            if (count == 0) {

                if (resultOperation.IsIgnore) {
                    return AstUtils.Empty();
                } else if (resultOperation.Variable != null) {
                    return Ast.Assign(resultOperation.Variable, AstUtils.Constant(null, resultOperation.Variable.Type));
                } else {
                    return Ast.Return(CurrentFrame.ReturnLabel, AstUtils.Constant(null));
                }

            } else if (count == 1) {
                if (prologue != null) {
                    return prologue;
                }

                if (epilogue != null) {
                    return epilogue;
                }

                if (resultOperation.IsIgnore) {
                    return statements.First.Transform(this);
                } else {
                    return statements.First.TransformResult(this, resultOperation);
                }

            } else {
                var result = new AstBlock();

                if (prologue != null) {
                    result.Add(prologue);
                }

                // transform all but the last statement if it is an expression stmt:
                foreach (var statement in statements.AllButLast) {
                    result.Add(statement.Transform(this));
                }

                if (statements.Count > 0) {
                    if (resultOperation.IsIgnore) {
                        result.Add(statements.Last.Transform(this));
                    } else {
                        result.Add(statements.Last.TransformResult(this, resultOperation));
                    }
                }

                if (epilogue != null) {
                    result.Add(epilogue);
                }

                result.Add(AstUtils.Empty());
                return result;
            }
        }
Ejemplo n.º 56
0
        internal sealed override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
            string debugString = (IsSingletonDeclaration) ? "SINGLETON" : ((this is ClassDefinition) ? "CLASS" : "MODULE") + " " + QualifiedName.Name;

            ScopeBuilder outerLocals = gen.CurrentScope;
                
            // definition needs to take place outside the defined lexical scope:
            var definition = MakeDefinitionExpression(gen);
            var selfVariable = outerLocals.DefineHiddenVariable("#module", typeof(RubyModule));
            var parentScope = gen.CurrentScopeVariable;

            // inner locals:
            ScopeBuilder scope = DefineLocals();
            var scopeVariable = scope.DefineHiddenVariable("#scope", typeof(RubyScope));
            
            gen.EnterModuleDefinition(
                scope,
                selfVariable, 
                scopeVariable, 
                IsSingletonDeclaration
            );

            // transform body:
            MSA.Expression transformedBody = Body.TransformRead(gen);

            // outer local:
            MSA.Expression resultVariable = outerLocals.DefineHiddenVariable("#result", transformedBody.Type);
            
            // begin with new scope
            //   self = DefineModule/Class(... parent scope here ...)
            //   <body>
            // end
            MSA.Expression result = new AstBlock {
                gen.DebugMarker(debugString),
                Ast.Assign(selfVariable, definition),
                scope.CreateScope(
                    scopeVariable,
                    Methods.CreateModuleScope.OpCall(
                        scope.MakeLocalsStorage(),
                        scope.GetVariableNamesExpression(), 
                        parentScope, 
                        selfVariable
                    ),
                    Ast.Block(
                        Ast.Assign(resultVariable, transformedBody),
                        AstUtils.Empty()
                    )
                ),
                gen.DebugMarker("END OF " + debugString),
                resultVariable
            };

            gen.LeaveModuleDefinition();

            return result;
        }
Ejemplo n.º 57
0
        private MSA.Expression/*!*/ TransformWrite(AstGenerator/*!*/ gen, MSA.Expression/*!*/ transformedRight, bool isSimpleRhs) {
            var writes = new AstBlock();
            
            MSA.Expression rightList = gen.CurrentScope.DefineHiddenVariable("#rhs", typeof(IList));
            MSA.Expression result;

            if (isSimpleRhs) {
                // 1.9 returns the RHS, not an unsplatted array, if there is just a single RHS:
                result = gen.CurrentScope.DefineHiddenVariable("#pr", transformedRight.Type);
                writes.Add(Ast.Assign(result, transformedRight)); 

                transformedRight = AstUtils.LightDynamic(ImplicitSplatAction.Make(gen.Context), typeof(IList), result);
            } else {
                result = rightList;
            }

            writes.Add(Ast.Assign(rightList, transformedRight));

            for (int i = 0; i < _unsplattedValueIndex; i++) {
                writes.Add(_leftValues[i].TransformWrite(gen, Methods.GetArrayItem.OpCall(rightList, AstUtils.Constant(i))));
            }

            if (HasUnsplattedValue) {
                MSA.Expression explicitCount = AstUtils.Constant(_leftValues.Length - 1);

                // remaining RHS values:
                MSA.Expression array = Methods.GetArrayRange.OpCall(rightList, AstUtils.Constant(_unsplattedValueIndex), explicitCount);
                writes.Add(_leftValues[_unsplattedValueIndex].TransformWrite(gen, array));

                for (int i = _unsplattedValueIndex + 1; i < _leftValues.Length; i++) {
                    writes.Add(_leftValues[i].TransformWrite(gen, Methods.GetTrailingArrayItem.OpCall(rightList, AstUtils.Constant(_leftValues.Length - i), explicitCount)));
                }
            }

            writes.Add(result);
            return writes;
        }
Ejemplo n.º 58
0
        internal static MSA.Expression/*!*/ MakeCallWithBlockRetryable(AstGenerator/*!*/ gen, MSA.Expression/*!*/ invoke,
            MSA.Expression blockArgVariable, MSA.Expression transformedBlock, bool isBlockDefinition) {
            Assert.NotNull(invoke);
            Debug.Assert((blockArgVariable == null) == (transformedBlock == null));

            // see Ruby Language.doc/Control Flow Implementation/Method Call With a Block
            MSA.Expression resultVariable = gen.CurrentScope.DefineHiddenVariable("#method-result", typeof(object));
            MSA.ParameterExpression evalUnwinder;

            MSA.LabelTarget retryLabel = Ast.Label("retry");

            var result = new AstBlock {
                Ast.Assign(blockArgVariable, Ast.Convert(transformedBlock, blockArgVariable.Type)),

                Ast.Label(retryLabel),

                (isBlockDefinition) ? Methods.InitializeBlock.OpCall(blockArgVariable) : null,

                AstUtils.Try(
                    Ast.Assign(resultVariable, invoke)
                ).Catch(evalUnwinder = Ast.Parameter(typeof(EvalUnwinder), "#u"),
                    Ast.Assign(
                        resultVariable, 
                        Ast.Field(evalUnwinder, EvalUnwinder.ReturnValueField)
                    )
                ),

                Ast.IfThen(Ast.TypeEqual(resultVariable, typeof(BlockReturnResult)),
                    Ast.IfThenElse(Methods.IsRetrySingleton.OpCall(resultVariable),
                        // retry:
                        AstUtils.IfThenElse(Ast.Equal(gen.MakeMethodBlockParameterRead(), blockArgVariable),
                            RetryStatement.TransformRetry(gen),
                            Ast.Goto(retryLabel)
                        ),
                        // return:
                        gen.Return(ReturnStatement.Propagate(gen, resultVariable))
                    )
                ),

                resultVariable
            };

            return result;
        }
Ejemplo n.º 59
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/While-Until
        internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
            MSA.Expression resultVariable = gen.CurrentScope.DefineHiddenVariable("#loop-result", typeof(object));
            MSA.Expression redoVariable = gen.CurrentScope.DefineHiddenVariable("#skip-condition", typeof(bool));
            MSA.ParameterExpression unwinder;
            
            bool isInnerLoop = gen.CurrentLoop != null;

            MSA.LabelTarget breakLabel = Ast.Label();
            MSA.LabelTarget continueLabel = Ast.Label();

            gen.EnterLoop(redoVariable, resultVariable, breakLabel, continueLabel);
            MSA.Expression transformedBody = gen.TransformStatements(_statements, ResultOperation.Ignore);
            MSA.Expression transformedCondition = _condition.TransformCondition(gen, true);
            gen.LeaveLoop();

            MSA.Expression conditionPositiveStmt, conditionNegativeStmt;
            if (_isWhileLoop) {
                conditionPositiveStmt = AstUtils.Empty();
                conditionNegativeStmt = Ast.Break(breakLabel);
            } else {
                conditionPositiveStmt = Ast.Break(breakLabel);
                conditionNegativeStmt = AstUtils.Empty();
            }

            // make the loop first:
            MSA.Expression loop = new AstBlock {
                gen.ClearDebugInfo(),
                Ast.Assign(redoVariable, AstUtils.Constant(_isPostTest)),

                AstFactory.Infinite(breakLabel, continueLabel,
                    AstUtils.Try(

                        AstUtils.If(redoVariable, 
                            Ast.Assign(redoVariable, AstUtils.Constant(false))
                        ).ElseIf(transformedCondition,
                            conditionPositiveStmt
                        ).Else(
                            conditionNegativeStmt
                        ),

                        transformedBody,
                        AstUtils.Empty()

                    ).Catch(unwinder = Ast.Parameter(typeof(BlockUnwinder), "#u"), 
                        // redo = u.IsRedo
                        Ast.Assign(redoVariable, Ast.Field(unwinder, BlockUnwinder.IsRedoField)),
                        AstUtils.Empty()

                    ).Filter(unwinder = Ast.Parameter(typeof(EvalUnwinder), "#u"), 
                        Ast.Equal(Ast.Field(unwinder, EvalUnwinder.ReasonField), AstFactory.BlockReturnReasonBreak),

                        // result = unwinder.ReturnValue
                        Ast.Assign(resultVariable, Ast.Field(unwinder, EvalUnwinder.ReturnValueField)),
                        Ast.Break(breakLabel)
                    )
                ),
                gen.ClearDebugInfo(),
                AstUtils.Empty(),
            };

            // wrap it to try finally that updates RFC state:
            if (!isInnerLoop) {
                loop = AstUtils.Try(
                    Methods.EnterLoop.OpCall(gen.CurrentScopeVariable),
                    loop
                ).Finally(
                    Methods.LeaveLoop.OpCall(gen.CurrentScopeVariable)
                );
            }

            return Ast.Block(loop, resultVariable);
        }
Ejemplo n.º 60
0
        private MSA.Expression/*!*/ TransformStatementsToExpression(Statements statements, bool toBoolean, bool positive) {

            if (statements == null || statements.Count == 0) {
                return toBoolean ? AstUtils.Constant(!positive) : AstUtils.Constant(null);
            }

            var last = toBoolean ? statements.Last.TransformCondition(this, positive) : statements.Last.TransformReadStep(this);
            if (statements.Count == 1) {
                return last;
            }

            var result = new AstBlock();
            foreach (var statement in statements.AllButLast) {
                result.Add(statement.Transform(this));
            }
            result.Add(last);

            return result;
        }