コード例 #1
0
ファイル: NodeWalker.cs プロジェクト: buunguyen/bike
 public object Walk(FormalParameter node)
 {
     if (Enter(node))
     {
         node.Identifier.Accept(this);
     }
     Exit(node);
     return null;
 }
コード例 #2
0
 public object Walk(FormalParameter node)
 {
     if (Enter(node))
     {
         node.Identifier.Accept(this);
     }
     Exit(node);
     return(null);
 }
コード例 #3
0
ファイル: AstComparer.cs プロジェクト: raimilcruz/bengala
        public override bool VisitFormalParameter(FormalParameter formalParameter)
        {
            var other = _other as FormalParameter;

            if (other == null)
            {
                return(false);
            }

            return(other.Name == formalParameter.Name && other.TypeIdentifier == formalParameter.TypeIdentifier);
        }
コード例 #4
0
        private bool ParseParameters(Lexer lexer, Environment environment)
        {
            var successfullyParsed = true;

            do
            {
                var token = lexer.GetNextToken();

                if (token.Is(TokenType.RightParenthesis))
                {
                    return(true);
                }

                var parameter = new FormalParameter();

                if (token.Is(TokenType.ByVal) || token.Is(TokenType.ByRef))
                {
                    parameter.ParameterType = token.Is(TokenType.ByVal)
                        ? ParameterType.ByVal : ParameterType.ByRef;

                    token = lexer.GetNextToken();
                    ValidateToken(token, TokenType.Identifier);
                }
                else
                {
                    parameter.ParameterType = ParameterType.ByVal;

                    ValidateToken(token, TokenType.Identifier);
                }

                parameter.Identifier = token.Lexeme;

                // SEM: Validar que no haya parametros con nombres duplicados.
                if (environment.FormalParameters.Exists(parameter.Identifier))
                {
                    LogDuplicateIdentifierFound(parameter.Identifier, token);
                    successfullyParsed = false;
                }

                ValidateToken(lexer.GetNextToken(), TokenType.IdTypeSeparator);

                token = lexer.GetNextToken();
                ValidateToken(token, TokenType.IntegerDataType, TokenType.BooleanDataType);

                parameter.DataType = token.Type == TokenType.IntegerDataType
                    ? DataType.Integer : DataType.Boolean;

                environment.FormalParameters.AddParameter(parameter);
            } while (lexer.GetNextToken().Is(TokenType.ListSeparator));

            return(successfullyParsed);
        }
        // Actual Parameters
        // Always returns null. Uses the given FormalParameter.
        public Void VisitValueParameter(ValueParameter ast, FormalParameter arg)
        {
            TypeDenoter expressionType = ast.Expression.Visit(this, null);

            if (arg is ConstFormalParameter param)
            {
                CheckAndReportError(expressionType.Equals(param.Type), "wrong type for const actual parameter", ast.Expression);
            }
            else
            {
                ReportError("const actual parameter not expected here", ast);
            }
            return(null);
        }
コード例 #6
0
        public FunctionDeclaration(string name, Type returnType, FormalParameter[] formalParameters, Scope scope)
            : base(name, scope)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException("The name is blank!", "name");

            if (returnType == null)
                ThrowHelper.ThrowArgumentNullException(() => returnType);

            if (formalParameters == null)
                ThrowHelper.ThrowArgumentNullException(() => formalParameters);

            Name = name;
            ReturnType = returnType;
            FormalParameters = formalParameters;
        }
        public Void VisitVarParameter(VarParameter ast, FormalParameter arg)
        {
            Declaration actualType = ast.Identifier.Visit(this, null);

            if (!ast.Identifier.IsVariable)
            {
                ReportError("parameter is not a variable", ast.Identifier);
            }
            else if (arg is VarFormalParameter parameter)
            {
                CheckAndReportError(actualType.Equals(parameter.Type), "wrong type for var parameter", ast.Identifier);
            }
            else
            {
                ReportError("var parameter not expected here", ast.Identifier);
            }
            return(null);
        }
コード例 #8
0
        private List <FormalParameter> ParseFormalParameterList()
        {
            var list = new List <FormalParameter>();

            Match(TokenType.LeftParen);
            while (Next().Is(TokenType.Multiply) ||
                   Next().Is(TokenType.Identifier))
            {
                var parameter = new FormalParameter()
                {
                    Token = Next()
                };
                if (Next().Is(TokenType.Multiply))
                {
                    Match(TokenType.Multiply);
                    parameter.IsParams = true;
                }
                parameter.Identifier = ParseIdentifier();
                if (list.Any(param => param.Identifier.Equals(parameter.Identifier)))
                {
                    throw Error("Duplicated parameter name", Next());
                }

                list.Add(parameter);
                if (Next().Is(TokenType.Comma))
                {
                    Match(TokenType.Comma);
                    continue;
                }
                if (Next().Is(TokenType.RightParen))
                {
                    break;
                }
                throw Error("Unexpected token", Next());
            }

            if (list.Any(p => p.IsParams && list.IndexOf(p) != list.Count - 1))
            {
                throw Error("Var-arg parameter must be the last parameter", Next());
            }

            Match(TokenType.RightParen);
            return(list);
        }
コード例 #9
0
 public virtual void Exit(FormalParameter node)
 {
 }
コード例 #10
0
 public virtual bool Enter(FormalParameter node)
 {
     return true;
 }
コード例 #11
0
 public virtual void Exit(FormalParameter node)
 {
 }
コード例 #12
0
 public virtual bool Enter(FormalParameter node)
 {
     return(true);
 }
コード例 #13
0
ファイル: Parser.cs プロジェクト: buunguyen/bike
        private List<FormalParameter> ParseFormalParameterList()
        {
            var list = new List<FormalParameter>();
            Match(TokenType.LeftParen);
            while (Next().Is(TokenType.Multiply) ||
                   Next().Is(TokenType.Identifier))
            {
                var parameter = new FormalParameter() {Token = Next()};
                if (Next().Is(TokenType.Multiply))
                {
                    Match(TokenType.Multiply);
                    parameter.IsParams = true;
                }
                parameter.Identifier = ParseIdentifier();
                if (list.Any(param => param.Identifier.Equals(parameter.Identifier)))
                    throw Error("Duplicated parameter name", Next());

                list.Add(parameter);
                if (Next().Is(TokenType.Comma))
                {
                    Match(TokenType.Comma);
                    continue;
                }
                if (Next().Is(TokenType.RightParen))
                    break;
                throw Error("Unexpected token", Next());
            }

            if (list.Any(p => p.IsParams && list.IndexOf(p) != list.Count - 1))
                throw Error("Var-arg parameter must be the last parameter", Next());

            Match(TokenType.RightParen);
            return list;
        }
コード例 #14
0
        public static Subprogram BuildIR(this MethodInfo method,
                                         IList <SpecialRegister> srpool,
                                         IDictionary <MethodInfo, Subprogram> spmap,
                                         bool anonymousKernel = false)
        {
            if (!method.IsStatic)
            {
                throw new ArgumentException("Only static methods are supported", "method");
            }

            bool kernel = anonymousKernel || Attribute.GetCustomAttribute(method, typeof(KernelAttribute)) != null;
            bool result = method.ReturnType != typeof(void);

            if (kernel && result)
            {
                throw new ArgumentException("Kernels can not have return parameter", "method");
            }

            List <FormalParameter> formalParameters = new List <FormalParameter>(method.GetParameters().Select(pi =>
            {
                PassingStyles ps   = pi.ParameterType.IsByRef ? pi.IsOut ? PassingStyles.OUT : PassingStyles.REF : PassingStyles.VAL;
                Type pt            = pi.ParameterType.IsByRef ? pi.ParameterType.GetElementType() : pi.ParameterType;
                FormalParameter fp = pt.IsArray ? new FormalParameter(pt.GetElementType(), anonymousKernel ? StateSpaces.GLOBAL :
                                                                      (Attribute.GetCustomAttribute(pi, typeof(StateSpaceAttribute)) as StateSpaceAttribute).StateSpace, ps) :
                                     new Argument(pt, ps);
                fp.Name = pi.Name;
                return(fp);
            }));

            if (result)
            {
                FormalParameter returnParameter = method.ReturnType.IsArray ? new FormalParameter(method.ReturnType.GetElementType(),
                                                                                                  (Attribute.GetCustomAttribute(method.ReturnParameter, typeof(StateSpaceAttribute)) as StateSpaceAttribute).StateSpace,
                                                                                                  PassingStyles.OUT) :
                                                  new Argument(method.ReturnType, PassingStyles.OUT);
                returnParameter.Name = method.Name;
                formalParameters.Add(returnParameter);
            }

            IList <FormalParameter> formalParametersRO = formalParameters.AsReadOnly();

            IList <VirtualRegister> localVariablesRO = new List <VirtualRegister>(method.GetMethodBody().LocalVariables.Select(lvi =>
                                                                                                                               new VirtualRegister(InstructionSelector.UpconvertMapping[lvi.LocalType.IsArray ? typeof(int) : lvi.LocalType]))).AsReadOnly();

            Subprogram subprogram = kernel ? new Kernel(formalParametersRO) : new Subprogram(formalParametersRO);

            subprogram.Name = method.Name;

            spmap.Add(method, subprogram);

            Func <Type, StateSpaces, InstructionSelector.DynamicRegister> regalloc =
                IRBuildOptions.WasteRegisters ?
                (Func <Type, StateSpaces, InstructionSelector.DynamicRegister>)RegisterAllocator.Waste :
                new RegisterAllocator().Allocate;

            subprogram.CFGRoot = BuildIRCFG(BuildCILCFG(method.GetInstructions().First()),
                                            new Stack <Tuple <Tuple <GenericOperand, bool>, InstructionSelector> >(),
                                            new Dictionary <CILBB, List <CILBBImplementation> >(),
                                            formalParametersRO, localVariablesRO, result, srpool, spmap, regalloc).AsBasicBlock;

            if (regalloc.Target != null && !(regalloc.Target as RegisterAllocator).FinishTest())
            {
                throw new Exception("There is a bug in instruction selecting phase: we have live registers");
            }

            return(subprogram);
        }
コード例 #15
0
 public Setter(string propertyName, FormalParameter setParameter, FunctionStatementList functionBody)
 {
     this.propertyName = propertyName;
     this.setParameter = setParameter;
     this.functionBody = functionBody;
 }
コード例 #16
0
        public override Statement EmitStatement(EmitMode mode)
        {
            if (mode == EmitMode.ForStorage)
            {
                SaveObjectID();
                SaveLocator();
            }
            else
            {
                RemoveObjectID();
                RemoveLocator();
            }
            try
            {
                IMetaData result;

                if ((mode != EmitMode.ForRemote) && (DeclarationText != null))
                {
                    SourceStatement statement = new SourceStatement();
                    statement.Source = DeclarationText + InitializationText + AggregationText + FinalizationText;
                    result           = statement;
                }
                else
                {
                    CreateAggregateOperatorStatement statement = new CreateAggregateOperatorStatement();
                    statement.OperatorName = Schema.Object.EnsureRooted(OperatorName);
                    foreach (Operand operand in Operands)
                    {
                        FormalParameter formalParameter = new FormalParameter();
                        formalParameter.Identifier    = operand.Name;
                        formalParameter.TypeSpecifier = operand.DataType.EmitSpecifier(mode);
                        formalParameter.Modifier      = operand.Modifier;
                        statement.FormalParameters.Add(formalParameter);
                    }
                    statement.ReturnType = ReturnDataType.EmitSpecifier(mode);
                                        #if USEVIRTUAL
                    statement.IsVirtual      = IsVirtual;
                    statement.IsAbstract     = IsAbstract;
                    statement.IsOverride     = IsOverride;
                    statement.IsReintroduced = IsReintroduced;
                                        #endif
                    if ((mode == EmitMode.ForRemote) && !IsRemotable)
                    {
                        statement.Initialization.Block = new Block();
                        statement.Aggregation.Block    = new Block();
                        statement.Finalization.Block   = new Block();
                    }
                    else
                    {
                        Initialization.EmitStatement(mode, statement.Initialization);
                        Aggregation.EmitStatement(mode, statement.Aggregation);
                        Finalization.EmitStatement(mode, statement.Finalization);
                    }
                    result = statement;
                }

                result.MetaData = MetaData == null ? null : MetaData.Copy();
                if (SessionObjectName != null)
                {
                    if (result.MetaData == null)
                    {
                        result.MetaData = new MetaData();
                    }
                    result.MetaData.Tags.AddOrUpdate("DAE.GlobalObjectName", OperatorName, true);
                }
                return((Statement)result);
            }
            finally
            {
                if (mode == EmitMode.ForStorage)
                {
                    RemoveObjectID();
                    RemoveLocator();
                }
            }
        }
コード例 #17
0
 public virtual T VisitFormalParameter(FormalParameter formalParameter)
 {
     return(default(T));
 }
コード例 #18
0
        public InstructionSelector(IList <Instruction> cilbbcode,
                                   Stack <Tuple <Tuple <GenericOperand, bool>, InstructionSelector> > stack,
                                   IList <FormalParameter> parameters,
                                   IList <VirtualRegister> variables,
                                   bool result,
                                   IList <SpecialRegister> srpool,
                                   IDictionary <MethodInfo, Subprogram> spmap,
                                   Func <Type, StateSpaces, DynamicRegister> regalloc)
        {
            this.stack    = stack;
            this.regalloc = regalloc;

            bool skipnext = false;

            foreach (Instruction cilinstr in cilbbcode)
            {
                if (skipnext)
                {
                    skipnext = false;
                    continue;
                }

                if (Trailer != null)
                {
                    throw new ArgumentException("No instruction is permitted after trailing control flow one", "cilbbcode");
                }

                GenericOperand  left     = null;
                GenericOperand  right    = null;
                GenericOperand  extra    = null;
                VirtualRegister regleft  = null;
                VirtualRegister regright = null;
                VirtualRegister target   = null;
                FormalParameter arg      = null;
                VirtualRegister loc      = null;

                CILOpCodes cilopcode = (CILOpCodes)cilinstr.OpCode.Value;

                bool isArithmetic = cilopcode >= CILOpCodes.Add && cilopcode <= CILOpCodes.Xor;
                bool isCompare    = cilopcode >= CILOpCodes.Ceq && cilopcode <= CILOpCodes.Clt_Un;
                bool isCompBranch = cilopcode >= CILOpCodes.Beq_S && cilopcode <= CILOpCodes.Blt_Un_S ||
                                    cilopcode >= CILOpCodes.Beq && cilopcode <= CILOpCodes.Blt_Un;

                if (isArithmetic || isCompare || isCompBranch)
                {
                    right = RetrieveOperand();
                    left  = RetrieveOperand();
                    if (cilopcode == CILOpCodes.Mul &&
                        cilinstr.Next != null &&
                        (CILOpCodes)cilinstr.Next.OpCode.Value == CILOpCodes.Add)
                    {
                        extra = RetrieveOperand();
                    }
                    Type targetType = ArithmeticMapping[left.DataType][right.DataType];

                    right = ConvertOperand(right, targetType);
                    left  = ConvertOperand(left, targetType);
                    if (extra != null)
                    {
                        extra = ConvertOperand(extra, targetType);
                    }

                    ReleaseOperand(right);
                    ReleaseOperand(left);
                    if (extra != null)
                    {
                        ReleaseOperand(extra);
                    }

                    target = AllocateRegister(isArithmetic ? targetType : typeof(int));

                    if (!isCompBranch)
                    {
                        PushByVal(target);
                    }
                }

                switch (cilopcode)
                {
                // Method arguments loading
                case CILOpCodes.Ldarg_0:
                case CILOpCodes.Ldarg_1:
                case CILOpCodes.Ldarg_2:
                case CILOpCodes.Ldarg_3:
                case CILOpCodes.Ldarg_S:
                case CILOpCodes.Ldarg:
                    arg = parameters[(cilinstr.Operand == null) ? (cilopcode - CILOpCodes.Ldarg_0) :
                                     (cilinstr.Operand as ParameterInfo).Position];
                    if (arg.PassingStyle == PassingStyles.VAL)
                    {
                        target = AllocateRegister(arg.StateSpace != StateSpaces.REG ? arg.UnderlyingType : arg.DataType, arg.StateSpace);
                        code.Add(new UnaryOperation(IROpCodes.MOV, target, arg));
                        PushByVal(target);
                    }
                    else
                    {
                        PushByRef(arg);
                    }
                    break;

                case CILOpCodes.Ldarga_S:
                case CILOpCodes.Ldarga:
                    arg = parameters[(cilinstr.Operand as ParameterInfo).Position];
                    PushByRef(arg);
                    break;

                // Local variables loading
                case CILOpCodes.Ldloc_0:
                case CILOpCodes.Ldloc_1:
                case CILOpCodes.Ldloc_2:
                case CILOpCodes.Ldloc_3:
                case CILOpCodes.Ldloc_S:
                case CILOpCodes.Ldloc:
                    loc = variables[(cilinstr.Operand == null) ? (cilopcode - CILOpCodes.Ldloc_0) :
                                    (cilinstr.Operand as LocalVariableInfo).LocalIndex];
                    target = AllocateRegister(loc.UnderlyingType, loc.StateSpace);
                    code.Add(new UnaryOperation(IROpCodes.MOV, target, loc));
                    PushByVal(target);
                    break;

                case CILOpCodes.Ldloca_S:
                case CILOpCodes.Ldloca:
                    loc = variables[(cilinstr.Operand as LocalVariableInfo).LocalIndex];
                    PushByRef(loc);
                    break;

                // Method arguments storing
                case CILOpCodes.Starg_S:
                case CILOpCodes.Starg:
                    arg   = parameters[(cilinstr.Operand as ParameterInfo).Position];
                    right = RetrieveOperand();
                    if (arg.DataType != right.DataType)
                    {
                        code.Add(new UnaryOperation(IROpCodes.CVT, arg, right));
                    }
                    else
                    {
                        code.Add(new UnaryOperation(IROpCodes.MOV, arg, right));
                    }
                    ReleaseOperand(right);
                    break;

                // Local variables storing
                case CILOpCodes.Stloc_0:
                case CILOpCodes.Stloc_1:
                case CILOpCodes.Stloc_2:
                case CILOpCodes.Stloc_3:
                case CILOpCodes.Stloc_S:
                case CILOpCodes.Stloc:
                    loc = variables[(cilinstr.Operand == null) ? (cilopcode - CILOpCodes.Stloc_0) :
                                    (cilinstr.Operand as LocalVariableInfo).LocalIndex];
                    right = RetrieveOperand();
                    if (loc.DataType != right.DataType)
                    {
                        code.Add(new UnaryOperation(IROpCodes.CVT, loc, right));
                    }
                    else
                    {
                        code.Add(new UnaryOperation(IROpCodes.MOV, loc, right));
                    }
                    ReleaseOperand(right);
                    break;

                // Constants storing
                case CILOpCodes.Ldnull:
                    PushByRef(new ImmediateValue((int)0));
                    break;

                case CILOpCodes.Ldc_I4_M1:
                case CILOpCodes.Ldc_I4_0:
                case CILOpCodes.Ldc_I4_1:
                case CILOpCodes.Ldc_I4_2:
                case CILOpCodes.Ldc_I4_3:
                case CILOpCodes.Ldc_I4_4:
                case CILOpCodes.Ldc_I4_5:
                case CILOpCodes.Ldc_I4_6:
                case CILOpCodes.Ldc_I4_7:
                case CILOpCodes.Ldc_I4_8:
                case CILOpCodes.Ldc_I4_S:
                case CILOpCodes.Ldc_I4:
                case CILOpCodes.Ldc_I8:
                case CILOpCodes.Ldc_R4:
                case CILOpCodes.Ldc_R8:
                    PushByRef(new ImmediateValue((cilinstr.Operand == null) ?
                                                 (int)(cilopcode - CILOpCodes.Ldc_I4_0) : (ValueType)Convert.ChangeType(cilinstr.Operand,
                                                                                                                        UpconvertMapping[cilinstr.Operand.GetType()])));
                    break;

                // Array elements loading
                case CILOpCodes.Ldelem_I1:
                case CILOpCodes.Ldelem_U1:
                case CILOpCodes.Ldelem_I2:
                case CILOpCodes.Ldelem_U2:
                case CILOpCodes.Ldelem_I4:
                case CILOpCodes.Ldelem_U4:
                case CILOpCodes.Ldelem_I8:
                case CILOpCodes.Ldelem_R4:
                case CILOpCodes.Ldelem_R8:
                case CILOpCodes.Ldelem:
                    regright = MapToRegister(RetrieveOperand());                     // index
                    regleft  = RetrieveOperand() as VirtualRegister;                 // array
                    VirtualRegister address = CalculateAddress(regleft, regright);
                    target = AllocateRegister(UpconvertMapping[regleft.UnderlyingType]);
                    code.Add(new LDInstruction(target, address));
                    ReleaseOperand(address);
                    PushByVal(target);
                    break;

                case CILOpCodes.Ldelema:
                    regright = MapToRegister(RetrieveOperand());                     // index
                    regleft  = RetrieveOperand() as VirtualRegister;                 // array
                    PushByVal(CalculateAddress(regleft, regright));
                    break;

                // Array elements storing
                case CILOpCodes.Stelem_I1:
                case CILOpCodes.Stelem_I2:
                case CILOpCodes.Stelem_I4:
                case CILOpCodes.Stelem_I8:
                case CILOpCodes.Stelem_R4:
                case CILOpCodes.Stelem_R8:
                case CILOpCodes.Stelem:
                    GenericOperand val = RetrieveOperand();                     // value
                    regright = MapToRegister(RetrieveOperand());                // index
                    regleft  = RetrieveOperand() as VirtualRegister;            // array
                    IEnumerable <Type> compatible = regleft.UnderlyingType.CompatibleTypes().Where(type => type.SizeOf() >= sizeof(int));
                    target = !compatible.Contains(val.DataType) ?
                             ConvertOperand(val, compatible.First()) as VirtualRegister : MapToRegister(val);
                    address = CalculateAddress(regleft, regright);
                    code.Add(new STInstruction(address, target));
                    ReleaseOperand(address);
                    ReleaseOperand(target);
                    break;

                // Indirect loads
                case CILOpCodes.Ldobj:
                case CILOpCodes.Ldind_I1:
                case CILOpCodes.Ldind_U1:
                case CILOpCodes.Ldind_I2:
                case CILOpCodes.Ldind_U2:
                case CILOpCodes.Ldind_I4:
                case CILOpCodes.Ldind_U4:
                case CILOpCodes.Ldind_I8:
                case CILOpCodes.Ldind_R4:
                case CILOpCodes.Ldind_R8:
                    // pointer (induced by ldelema) / variable (induced by ldloca) / parameter (induced by ldarga or pass-by-ref ldarg)
                    regright = RetrieveOperand() as VirtualRegister;
                    if (regright.StateSpace == StateSpaces.REG)
                    {
                        target = AllocateRegister(regright.DataType);
                        code.Add(new UnaryOperation(IROpCodes.MOV, target, regright));
                    }
                    else
                    {
                        target = AllocateRegister(UpconvertMapping[regright.UnderlyingType]);
                        code.Add(new LDInstruction(target, regright));
                    }
                    ReleaseOperand(regright);
                    PushByVal(target);
                    break;

                case CILOpCodes.Ldind_Ref:
                    regright = RetrieveOperand() as VirtualRegister;                     // pointer (induced by pass-by-ref ldarg)
                    target   = AllocateRegister(regright.UnderlyingType, regright.StateSpace);
                    code.Add(new UnaryOperation(IROpCodes.MOV, target, regright));
                    ReleaseOperand(regright);
                    PushByVal(target);
                    break;

                // Indirect stores
                case CILOpCodes.Stobj:
                case CILOpCodes.Stind_I1:
                case CILOpCodes.Stind_I2:
                case CILOpCodes.Stind_I4:
                case CILOpCodes.Stind_I8:
                case CILOpCodes.Stind_R4:
                case CILOpCodes.Stind_R8:
                    right = RetrieveOperand();                     // value
                    // pointer (induced by ldelema) / variable (induced by ldloca) / parameter (induced by ldarga or pass-by-ref ldarg)
                    regleft = RetrieveOperand() as VirtualRegister;
                    if (regleft.StateSpace == StateSpaces.REG)
                    {
                        if (regleft.DataType != right.DataType)
                        {
                            code.Add(new UnaryOperation(IROpCodes.CVT, regleft, right));
                        }
                        else
                        {
                            code.Add(new UnaryOperation(IROpCodes.MOV, regleft, right));
                        }
                        ReleaseOperand(right);
                    }
                    else
                    {
                        compatible = regleft.UnderlyingType.CompatibleTypes().Where(type => type.SizeOf() >= sizeof(int));
                        regright   = !compatible.Contains(right.DataType) ?
                                     ConvertOperand(right, compatible.First()) as VirtualRegister : MapToRegister(right);
                        code.Add(new STInstruction(regleft, regright));
                        ReleaseOperand(regright);
                    }
                    ReleaseOperand(regleft);
                    break;

                case CILOpCodes.Stind_Ref:
                    regright = RetrieveOperand() as VirtualRegister;                    // source pointer (induced by ldarg or pass-by-ref ldarg)
                    regleft  = RetrieveOperand() as VirtualRegister;                    // target pointer (induced by pass-by-ref ldarg)
                    code.Add(new UnaryOperation(IROpCodes.MOV, regleft, regright));
                    ReleaseOperand(regleft);
                    ReleaseOperand(regright);
                    break;

                // Comparison branches
                case CILOpCodes.Beq:
                case CILOpCodes.Beq_S:
                    code.Add(new BinaryOperation(IROpCodes.EQ, target, left, right));
                    goto case CILOpCodes.Brtrue;

                case CILOpCodes.Bne_Un:
                case CILOpCodes.Bne_Un_S:
                    code.Add(new BinaryOperation(IROpCodes.NE, target, left, right));
                    goto case CILOpCodes.Brtrue;

                case CILOpCodes.Bge_S:
                case CILOpCodes.Bge_Un_S:
                case CILOpCodes.Bge:
                case CILOpCodes.Bge_Un:
                    code.Add(new BinaryOperation(IROpCodes.GE, target, left, right));
                    goto case CILOpCodes.Brtrue;

                case CILOpCodes.Bgt_S:
                case CILOpCodes.Bgt_Un_S:
                case CILOpCodes.Bgt:
                case CILOpCodes.Bgt_Un:
                    code.Add(new BinaryOperation(IROpCodes.GT, target, left, right));
                    goto case CILOpCodes.Brtrue;

                case CILOpCodes.Ble_S:
                case CILOpCodes.Ble_Un_S:
                case CILOpCodes.Ble:
                case CILOpCodes.Ble_Un:
                    code.Add(new BinaryOperation(IROpCodes.LE, target, left, right));
                    goto case CILOpCodes.Brtrue;

                case CILOpCodes.Blt_S:
                case CILOpCodes.Blt_Un_S:
                case CILOpCodes.Blt:
                case CILOpCodes.Blt_Un:
                    code.Add(new BinaryOperation(IROpCodes.LT, target, left, right));
                    goto case CILOpCodes.Brtrue;

                // Basic branches (the last instructions in basic block)
                case CILOpCodes.Br_S:
                case CILOpCodes.Br:
                    Trailer = new JMPInstruction();
                    break;

                case CILOpCodes.Brfalse_S:
                case CILOpCodes.Brfalse:
                    regleft = MapToRegister(ConvertOperand(RetrieveOperand(), typeof(int)));
                    Trailer = new JFInstruction(regleft);
                    ReleaseOperand(regleft);
                    break;

                case CILOpCodes.Brtrue_S:
                case CILOpCodes.Brtrue:
                    regleft = isCompBranch ? target : MapToRegister(ConvertOperand(RetrieveOperand(), typeof(int)));
                    Trailer = new JTInstruction(regleft);
                    ReleaseOperand(regleft);
                    break;

                // Call stuff.
                case CILOpCodes.Call:
                    MethodInfo   method   = cilinstr.Operand as MethodInfo;
                    PropertyInfo property = method.DeclaringType.GetProperty(method.Name.Replace("get_", ""));
                    if (property != null)
                    {
                        // Handle predefined value access.
                        PredefinedValueAttribute pva = Attribute.GetCustomAttribute(property,
                                                                                    typeof(PredefinedValueAttribute)) as PredefinedValueAttribute;
                        if (pva != null)
                        {
                            PushByVal(MapToRegister(srpool.Single(sr => sr.Value == pva.Value)));
                        }
                        else
                        {
                            throw new NotSupportedException(method.DeclaringType.FullName + "." + property.Name);
                        }
                    }
                    else
                    {
                        // Handle intrinsic function call.
                        IntrinsicFunctionAttribute ifa = Attribute.GetCustomAttribute(method,
                                                                                      typeof(IntrinsicFunctionAttribute)) as IntrinsicFunctionAttribute;
                        if (ifa != null)
                        {
                            switch (ifa.OpCode)
                            {
                            case IROpCodes.SYNC:
                                code.Add(new SYNCInstruction());
                                break;

                            case IROpCodes.ABS:
                            case IROpCodes.SQRT:
                            case IROpCodes.RSQRT:
                            case IROpCodes.SIN:
                            case IROpCodes.COS:
                            case IROpCodes.LG2:
                            case IROpCodes.EX2:
                                right = ConvertOperand(RetrieveOperand(), UpconvertMapping[method.ReturnType]);
                                ReleaseOperand(right);
                                target = AllocateRegister(right.DataType);
                                code.Add(new UnaryOperation(ifa.OpCode, target, right));
                                PushByVal(target);
                                break;

                            case IROpCodes.MIN:
                            case IROpCodes.MAX:
                                right = ConvertOperand(RetrieveOperand(), UpconvertMapping[method.ReturnType]);
                                left  = ConvertOperand(RetrieveOperand(), right.DataType);
                                ReleaseOperand(right);
                                ReleaseOperand(left);
                                target = AllocateRegister(right.DataType);
                                code.Add(new BinaryOperation(ifa.OpCode, target, left, right));
                                PushByVal(target);
                                break;

                            default:
                                throw new NotSupportedException(ifa.OpCode.ToString());
                            }
                        }
                        else
                        {
                            // Handle subprogram call.
                            Subprogram sp;
                            spmap.TryGetValue(method, out sp);
                            if (sp == null)
                            {
                                sp = method.BuildIR(srpool, spmap);
                            }

                            List <GenericOperand> actualParameters = new List <GenericOperand>();
                            List <Tuple <VirtualRegister, VirtualRegister> > wrappedRefElements =
                                new List <Tuple <VirtualRegister, VirtualRegister> >();

                            if (method.ReturnType != typeof(void))
                            {
                                arg    = sp.FormalParameters.Last();
                                target = AllocateRegister(arg.StateSpace != StateSpaces.REG ?
                                                          arg.UnderlyingType : arg.DataType, arg.StateSpace);
                                PushByVal(target);
                            }

                            foreach (FormalParameter fp in sp.FormalParameters.Reverse())
                            {
                                GenericOperand ap = RetrieveOperand();
                                if (fp.StateSpace == StateSpaces.REG)
                                {
                                    VirtualRegister regap = ap as VirtualRegister;
                                    if (regap != null && regap.StateSpace != StateSpaces.REG)
                                    {
                                        // Passing array element by reference.

                                        // Create wrapping register.
                                        regright = AllocateRegister(fp.DataType);
                                        // Load array element value to wrapping register.
                                        if (fp.PassingStyle == PassingStyles.REF)
                                        {
                                            code.Add(new LDInstruction(regright, regap));
                                        }
                                        // Remember address-to-register mapping.
                                        wrappedRefElements.Add(new Tuple <VirtualRegister, VirtualRegister>(regap, regright));

                                        // Replace original actual parameter with wrapping register.
                                        ap = regright;
                                    }
                                    else if (fp.PassingStyle == PassingStyles.VAL)
                                    {
                                        // Perform implicit parameter conversion.
                                        ap = ConvertOperand(ap, fp.DataType);
                                    }
                                }
                                actualParameters.Insert(0, ap);
                            }

                            code.Add(new CALLInstruction(sp, actualParameters));

                            // Update values of wrapped array elements.
                            code.AddRange(wrappedRefElements.Select(we => new STInstruction(we.Item1, we.Item2)));

                            foreach (VirtualRegister ap in actualParameters)
                            {
                                ReleaseOperand(ap);
                            }
                            foreach (Tuple <VirtualRegister, VirtualRegister> we in wrappedRefElements)
                            {
                                ReleaseOperand(we.Item1);
                            }

                            if (method.ReturnType != typeof(void))
                            {
                                PushByVal(target);
                                (target as DynamicRegister).Live = true;
                            }
                        }
                    }
                    break;

                // Arithmetic operations
                case CILOpCodes.Add:
                    code.Add(new BinaryOperation(IROpCodes.ADD, target, left, right));
                    break;

                case CILOpCodes.Sub:
                    code.Add(new BinaryOperation(IROpCodes.SUB, target, left, right));
                    break;

                case CILOpCodes.Mul:
                    if (extra != null)
                    {
                        code.Add(new MADOperation(target, left, right, extra));
                        skipnext = true;
                    }
                    else
                    {
                        code.Add(new BinaryOperation(IROpCodes.MUL, target, left, right));
                    }
                    break;

                case CILOpCodes.Div:
                case CILOpCodes.Div_Un:
                    code.Add(new BinaryOperation(IROpCodes.DIV, target, left, right));
                    break;

                case CILOpCodes.Rem:
                case CILOpCodes.Rem_Un:
                    code.Add(new BinaryOperation(IROpCodes.REM, target, left, right));
                    break;

                case CILOpCodes.And:
                    code.Add(new BinaryOperation(IROpCodes.AND, target, left, right));
                    break;

                case CILOpCodes.Or:
                    code.Add(new BinaryOperation(IROpCodes.OR, target, left, right));
                    break;

                case CILOpCodes.Xor:
                    code.Add(new BinaryOperation(IROpCodes.XOR, target, left, right));
                    break;

                case CILOpCodes.Neg:
                    right = RetrieveOperand();
                    right = ConvertOperand(right, NegMapping[right.DataType]);
                    ReleaseOperand(right);
                    target = AllocateRegister(right.DataType);
                    code.Add(new UnaryOperation(IROpCodes.NEG, target, right));
                    PushByVal(target);
                    break;

                case CILOpCodes.Not:
                    right = RetrieveOperand();
                    right = ConvertOperand(right, NotMapping[right.DataType]);
                    ReleaseOperand(right);
                    target = AllocateRegister(right.DataType);
                    code.Add(new UnaryOperation(IROpCodes.NOT, target, right));
                    PushByVal(target);
                    break;

                // Convert operations
                case CILOpCodes.Conv_I1:
                case CILOpCodes.Conv_Ovf_I1:
                case CILOpCodes.Conv_Ovf_I1_Un:
                    PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(sbyte))));
                    break;

                case CILOpCodes.Conv_I2:
                case CILOpCodes.Conv_Ovf_I2:
                case CILOpCodes.Conv_Ovf_I2_Un:
                    PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(short))));
                    break;

                case CILOpCodes.Conv_I:
                case CILOpCodes.Conv_Ovf_I:
                case CILOpCodes.Conv_Ovf_I_Un:
                case CILOpCodes.Conv_U:
                case CILOpCodes.Conv_Ovf_U:
                case CILOpCodes.Conv_Ovf_U_Un:
                case CILOpCodes.Conv_I4:
                case CILOpCodes.Conv_Ovf_I4:
                case CILOpCodes.Conv_Ovf_I4_Un:
                    PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(int))));
                    break;

                case CILOpCodes.Conv_I8:
                case CILOpCodes.Conv_Ovf_I8:
                case CILOpCodes.Conv_Ovf_I8_Un:
                    PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(long))));
                    break;

                case CILOpCodes.Conv_U1:
                case CILOpCodes.Conv_Ovf_U1:
                case CILOpCodes.Conv_Ovf_U1_Un:
                    PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(byte))));
                    break;

                case CILOpCodes.Conv_U2:
                case CILOpCodes.Conv_Ovf_U2:
                case CILOpCodes.Conv_Ovf_U2_Un:
                    PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(ushort))));
                    break;

                case CILOpCodes.Conv_U4:
                case CILOpCodes.Conv_Ovf_U4:
                case CILOpCodes.Conv_Ovf_U4_Un:
                    PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(uint))));
                    break;

                case CILOpCodes.Conv_U8:
                case CILOpCodes.Conv_Ovf_U8:
                case CILOpCodes.Conv_Ovf_U8_Un:
                    PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(ulong))));
                    break;

                case CILOpCodes.Conv_R4:
                case CILOpCodes.Conv_R_Un:
                    PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(float))));
                    break;

                case CILOpCodes.Conv_R8:
                    PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(double))));
                    break;

                // Compare operations
                case CILOpCodes.Ceq:
                    code.Add(new BinaryOperation(IROpCodes.EQ, target, left, right));
                    break;

                case CILOpCodes.Cgt:
                case CILOpCodes.Cgt_Un:
                    code.Add(new BinaryOperation(IROpCodes.GT, target, left, right));
                    break;

                case CILOpCodes.Clt:
                case CILOpCodes.Clt_Un:
                    code.Add(new BinaryOperation(IROpCodes.LT, target, left, right));
                    break;

                // Stack manipulation
                case CILOpCodes.Pop:
                    ReleaseOperand(RetrieveOperand());
                    break;

                case CILOpCodes.Dup:
                    bool byref = stack.Peek().Item1.Item2;
                    right = RetrieveOperand();
                    if (byref)
                    {
                        PushByRef(right);
                        PushByRef(right);
                    }
                    else
                    {
                        regright = right as VirtualRegister;
                        PushByVal(regright);
                        target = AllocateRegister(regright.UnderlyingType, regright.StateSpace);
                        code.Add(new UnaryOperation(IROpCodes.MOV, target, regright));
                        PushByVal(target);
                    }
                    break;

                case CILOpCodes.Ret:
                    if (result)
                    {
                        arg   = parameters.Last();
                        right = RetrieveOperand();
                        if (arg.DataType != right.DataType)
                        {
                            code.Add(new UnaryOperation(IROpCodes.CVT, arg, right));
                        }
                        else
                        {
                            code.Add(new UnaryOperation(IROpCodes.MOV, arg, right));
                        }
                        ReleaseOperand(right);
                    }
                    Trailer = new RETInstruction();
                    break;

                case CILOpCodes.Nop:
                    break;

                default:
                    throw new NotSupportedException(cilinstr.OpCode.Name);
                }

                if (isCompare)
                {
                    code.Add(new UnaryOperation(IROpCodes.NEG, target, target));
                }
            }
            if (Trailer == null)
            {
                Trailer = new JMPInstruction();
            }
        }