예제 #1
0
 /// <summary>
 /// Wraps 'type' in a ByReferenceType if it is a value type. If a constrained prefix is specified,
 /// returns the constrained type wrapped in a ByReferenceType.
 /// </summary>
 XTypeReference MakeRefIfValueType(XTypeReference type, AstExpressionPrefix constrainedPrefix)
 {
     if (constrainedPrefix != null)
         return new XByReferenceType((XTypeReference)constrainedPrefix.Operand);
     if (type.IsValueType)
         return new XByReferenceType(type);
     else
         return type;
 }
예제 #2
0
        private List <AstNode> ConvertToAst(IEnumerable <ByteCode> body)
        {
            var ast = new List <AstNode>();

            // Convert stack-based IL code to ILAst tree
            foreach (var byteCode in body)
            {
                var ilRange = new InstructionRange(byteCode.Offset, byteCode.EndOffset);

                if (byteCode.StackBefore == null)
                {
                    // Unreachable code
                    continue;
                }

                var expr = new AstExpression(byteCode.SequencePoint, byteCode.Code, byteCode.Operand);
                expr.ILRanges.Add(ilRange);
                if (byteCode.Prefixes != null && byteCode.Prefixes.Length > 0)
                {
                    var prefixes = new AstExpressionPrefix[byteCode.Prefixes.Length];
                    for (var i = 0; i < prefixes.Length; i++)
                    {
                        var operand = byteCode.Prefixes[i].Operand;
                        if (operand is FieldReference)
                        {
                            operand = XBuilder.AsFieldReference(module, (FieldReference)operand);
                        }
                        else if (operand is MethodReference)
                        {
                            operand = XBuilder.AsMethodReference(module, (MethodReference)operand);
                        }
                        else if (operand is TypeReference)
                        {
                            operand = XBuilder.AsTypeReference(module, (TypeReference)operand);
                        }
                        prefixes[i] = new AstExpressionPrefix((AstCode)byteCode.Prefixes[i].OpCode.Code, operand);
                    }
                    expr.Prefixes = prefixes;
                }

                // Label for this instruction
                if (byteCode.Label != null)
                {
                    ast.Add(byteCode.Label);
                }

                // Reference arguments using temporary variables
                var popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
                for (var i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++)
                {
                    var slot = byteCode.StackBefore[i];
                    expr.Arguments.Add(new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, slot.LoadFrom));
                }

                // Store the result to temporary variable(s) if needed
                if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0)
                {
                    ast.Add(expr);
                }
                else if (byteCode.StoreTo.Count == 1)
                {
                    ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, byteCode.StoreTo[0], expr));
                }
                else
                {
                    var tmpVar = new AstGeneratedVariable("expr_" + byteCode.Offset.ToString("X2"), byteCode.StoreTo.Select(x => x.OriginalName).FirstOrDefault());
                    ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, tmpVar, expr));
                    foreach (var storeTo in byteCode.StoreTo.AsEnumerable().Reverse())
                    {
                        ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, storeTo, new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, tmpVar)));
                    }
                }
            }

            return(ast);
        }