Esempio n. 1
0
 protected AstNodeExprLocal GetLocal(int index)
 {
     if (!Locals.ContainsKey(index))
     {
         Locals[index] = AstLocal.Create(GetVTypeType(), "LocalVFPR" + index);
     }
     return(Ast.Local(Locals[index]));
 }
Esempio n. 2
0
        protected virtual void _Generate(AstNodeExprNewArray NewArray)
        {
            var TempArrayLocal = AstLocal.Create(NewArray.Type, "$TempArray");

            Generate(new AstNodeExprImm(NewArray.Length));
            Emit(OpCodes.Newarr, NewArray.ElementType);
            Emit(OpCodes.Stloc, _GetLocalBuilderFromAstLocal(TempArrayLocal));
            for (int n = 0; n < NewArray.Length; n++)
            {
                Generate(new AstNodeStmAssign(new AstNodeExprArrayAccess(new AstNodeExprLocal(TempArrayLocal), n), NewArray.Values[n]));
            }
            Generate(new AstNodeExprLocal(TempArrayLocal));
        }
Esempio n. 3
0
 private AstNodeExprLValue BranchFlag()
 {
     if (DynarecConfig.BranchFlagAsLocal)
     {
         if (_branchFlagLocal == null)
         {
             _branchFlagLocal = AstLocal.Create <bool>("BranchFlag");
         }
         return(_ast.Local(_branchFlagLocal));
     }
     else
     {
         return(_ast.BranchFlag());
     }
 }
        public void TestSimpleLocal()
        {
            var testLocal = AstLocal.Create <int>("TestLocal");
            var func      = _generatorIl.GenerateDelegate <Func <int> >("Test", new AstNodeStmContainer(
                                                                            new AstNodeStmAssign(
                                                                                new AstNodeExprLocal(testLocal),
                                                                                new AstNodeExprImm(123)
                                                                                ),
                                                                            new AstNodeStmReturn(
                                                                                new AstNodeExprLocal(testLocal)
                                                                                )
                                                                            ));

            Assert.Equal(123, func());
        }
Esempio n. 5
0
        protected virtual void _Generate(AstNodeExprTerop Terop)
        {
            if (Terop.True.Type != Terop.False.Type)
            {
                throw (new InvalidOperationException(String.Format("AstNodeExprTerop '?:' types must match {0} != {1}", Terop.True.Type, Terop.False.Type)));
            }
            var TernaryType         = Terop.True.Type;
            var TernaryTempAstLocal = AstLocal.Create(TernaryType);

            Generate(new AstNodeStmIfElse(
                         Terop.Cond,
                         new AstNodeStmAssign(new AstNodeExprLocal(TernaryTempAstLocal), Terop.True),
                         new AstNodeStmAssign(new AstNodeExprLocal(TernaryTempAstLocal), Terop.False)
                         ));

            Generate(new AstNodeExprLocal(TernaryTempAstLocal));
        }
        protected virtual void _Generate(AstNodeExprTerop terop)
        {
            if (terop.True.Type != terop.False.Type)
            {
                throw new InvalidOperationException(
                          $"AstNodeExprTerop '?:' types must match {terop.True.Type} != {terop.False.Type}");
            }
            var ternaryType         = terop.True.Type;
            var ternaryTempAstLocal = AstLocal.Create(ternaryType);

            Generate(new AstNodeStmIfElse(
                         terop.Cond,
                         new AstNodeStmAssign(new AstNodeExprLocal(ternaryTempAstLocal), terop.True),
                         new AstNodeStmAssign(new AstNodeExprLocal(ternaryTempAstLocal), terop.False)
                         ));

            Generate(new AstNodeExprLocal(ternaryTempAstLocal));
        }
Esempio n. 7
0
        public void TestAstSwitch()
        {
            var Local = AstLocal.Create <int>("Local");
            var Ast   = ast.Statements(
                ast.Switch(
                    ast.Local(Local),
                    ast.Default(ast.Return("Nor One, nor Three")),
                    ast.Case(1, ast.Return("One")),
                    ast.Case(3, ast.Return("Three"))
                    ),
                ast.Return("Invalid!")
                );

            var Actual   = GeneratorCSharp.GenerateString <GeneratorCSharp>(Ast);
            var Expected = @"
				{
					switch (Local) {
						case 1:
							return ""One"";
						break;
						case 3:
							return ""Three"";
						break;
						default:
							return ""Nor One, nor Three"";
						break;
					}
					return ""Invalid!"";
				}
			"            ;

            Actual   = new Regex(@"\s+").Replace(Actual, " ").Trim();
            Expected = new Regex(@"\s+").Replace(Expected, " ").Trim();

            Assert.AreEqual(Expected, Actual);
        }
Esempio n. 8
0
        public AstNodeStm MethodCacheInfoCallDynamicPc(AstNodeExpr pc, bool tailCall)
        {
            //if (_DynarecConfig.FunctionCallWithStaticReferences)
            //{
            //	var Call = (AstNodeExpr)ast.CallInstance(GetMethodCacheInfoAtPC(PC), (Action<CpuThreadState>)MethodCacheInfo.Methods.CallDelegate, ast.CpuThreadState);
            //	if (TailCall) Call = ast.TailCall(Call as AstNodeExprCall);
            //	return ast.Statement(Call);
            //}
            //else
            {
                var localCachedPc       = Ast.Local(AstLocal.Create <uint>("CachedPC"));
                var localCachedFunction = Ast.Local(AstLocal.Create <Action <CpuThreadState> >("CachedFunction"));
                var localCalculatePc    = Ast.Local(AstLocal.Create <uint>("CalculatePC"));

                var call    = (AstNodeExpr)Ast.CallDelegate(localCachedFunction, Ast.CpuThreadStateExpr);
                var callStm = (AstNodeStm)Ast.Statement(call);
                if (tailCall)
                {
                    callStm = Ast.Statements(Ast.Statement(Ast.TailCall((AstNodeExprCall)call)), Ast.Return());
                }

                return(Ast.Statements(
                           Ast.Assign(localCalculatePc, pc),
                           Ast.If
                               (Ast.Binary(localCachedPc, "!=", localCalculatePc),
                               Ast.Statements(
                                   Ast.Assign(localCachedPc, localCalculatePc),
                                   Ast.Assign(localCachedFunction,
                                              Ast.CallInstance(Ast.CpuThreadStateExpr,
                                                               (Func <uint, Action <CpuThreadState> >)CpuThreadStateMethods.GetFuncAtPc, pc))
                                   )
                               ),
                           callStm
                           ));
            }
        }
Esempio n. 9
0
        public void TestAstSwitch()
        {
            var local = AstLocal.Create <int>("Local");
            var ast   = Ast.Statements(
                Ast.Switch(
                    Ast.Local(local),
                    Ast.Default(Ast.Return("Nor One, nor Three")),
                    Ast.Case(1, Ast.Return("One")),
                    Ast.Case(3, Ast.Return("Three"))
                    ),
                Ast.Return("Invalid!")
                );

            var actual   = GeneratorCSharp.GenerateString <GeneratorCSharp>(ast);
            var expected = @"
				{
					switch (Local) {
						case 1:
							return ""One"";
						break;
						case 3:
							return ""Three"";
						break;
						default:
							return ""Nor One, nor Three"";
						break;
					}
					return ""Invalid!"";
				}
			"            ;

            actual   = new Regex(@"\s+").Replace(actual, " ").Trim();
            expected = new Regex(@"\s+").Replace(expected, " ").Trim();

            Assert.Equal(expected, actual);
        }
        protected virtual void _Generate(AstNodeStmSwitch Switch)
        {
            var allCaseValues = Switch.Cases.Select(Case => Case.CaseValue);
            var caseValues    = allCaseValues as IList <object> ?? allCaseValues.ToList();

            if (caseValues.Count != caseValues.Distinct().Count())
            {
                throw new Exception("Repeated case in switch!");
            }

            // Check types and unique values.

            var endCasesLabel = AstLabel.CreateLabel("EndCasesLabel");
            var defaultLabel  = AstLabel.CreateLabel("DefaultLabel");

            if (Switch.Cases.Length > 0)
            {
                var commonType = Switch.Cases.First().CaseValue.GetType();
                if (Switch.Cases.Any(Case => Case.CaseValue.GetType() != commonType))
                {
                    throw new Exception("All cases should have the same type");
                }

                var doneSpecialized = false;

                // Specialized constant-time integer switch (if possible)
                if (AstUtils.IsIntegerType(commonType))
                {
                    var commonMin   = Switch.Cases.Min(Case => AstUtils.CastType <long>(Case.CaseValue));
                    var commonMax   = Switch.Cases.Max(Case => AstUtils.CastType <long>(Case.CaseValue));
                    var casesLength = commonMax - commonMin + 1;

                    // No processing tables greater than 4096 elements.
                    if (casesLength <= 4096)
                    {
                        var labels = new AstLabel[casesLength];
                        for (var n = 0; n < casesLength; n++)
                        {
                            labels[n] = defaultLabel;
                        }

                        foreach (var Case in Switch.Cases)
                        {
                            var realValue = AstUtils.CastType <long>(Case.CaseValue);
                            var offset    = realValue - commonMin;
                            labels[offset] = AstLabel.CreateLabel("Case_" + realValue);
                        }

                        /*
                         * //var SwitchVarLocal = AstLocal.Create(AllCaseValues.First().GetType(), "SwitchVarLocal" + SwitchVarCount++);
                         * //Generate(new AstNodeStmAssign(new AstNodeExprLocal(SwitchVarLocal), Switch.SwitchValue - new AstNodeExprCast(CommonType, CommonMin)));
                         * //Generate(new AstNodeStmIfElse(new AstNodeExprBinop(new AstNodeExprLocal(SwitchVarLocal), "<", 0), new AstNodeStmGotoAlways(DefaultLabel)));
                         * //Generate(new AstNodeStmIfElse(new AstNodeExprBinop(new AstNodeExprLocal(SwitchVarLocal), ">=", CasesLength), new AstNodeStmGotoAlways(DefaultLabel)));
                         * //Generate(new AstNodeExprLocal(SwitchVarLocal));
                         */

                        Generate(Switch.SwitchValue - new AstNodeExprCast(commonType, commonMin));
                        Emit(OpCodes.Switch, labels);
                        Generate(new AstNodeStmGotoAlways(defaultLabel));
                        foreach (var Case in Switch.Cases)
                        {
                            var realValue = AstUtils.CastType <long>(Case.CaseValue);
                            var offset    = realValue - commonMin;
                            Generate(new AstNodeStmLabel(labels[offset]));
                            {
                                Generate(Case.Code);
                            }
                            Generate(new AstNodeStmGotoAlways(endCasesLabel));
                        }

                        doneSpecialized = true;
                    }
                    else
                    {
                        // TODO: find a common shift and masks for all the values to reduce CasesLength.
                        // TODO: On too large test cases, split them recursively in:
                        // if (Var < Half) { switch(Var - LowerPartMin) { ... } } else { switch(Var - Half - UpperPartMin) { ... } }
                    }
                }
                // Specialized switch for strings (checking length, then hash, then contents)
                else if (commonType == typeof(string))
                {
                    // TODO!
                }

                // Generic if/else
                if (!doneSpecialized)
                {
                    var switchVarLocal =
                        AstLocal.Create(caseValues.First().GetType(), "SwitchVarLocal" + _switchVarCount++);
                    Generate(new AstNodeStmAssign(new AstNodeExprLocal(switchVarLocal), Switch.SwitchValue));
                    //Switch.Cases
                    foreach (var Case in Switch.Cases)
                    {
                        var labelSkipThisCase = AstLabel.CreateLabel("LabelCase" + Case.CaseValue);
                        Generate(new AstNodeStmGotoIfFalse(labelSkipThisCase,
                                                           new AstNodeExprBinop(new AstNodeExprLocal(switchVarLocal), "==",
                                                                                new AstNodeExprImm(Case.CaseValue))));
                        Generate(Case.Code);
                        Generate(new AstNodeStmGotoAlways(endCasesLabel));
                        Generate(new AstNodeStmLabel(labelSkipThisCase));
                    }
                }
            }

            Generate(new AstNodeStmLabel(defaultLabel));
            if (Switch.CaseDefault != null)
            {
                Generate(Switch.CaseDefault.Code);
            }

            Generate(new AstNodeStmLabel(endCasesLabel));
        }
        public AstNodeStm Vcmp()
        {
            var vectorSize = _instruction.OneTwo;
            var cond       = _instruction.Imm4;
            var cond2      = (ConditionEnum)cond;
            //bool NormalFlag = (Cond & 8) == 0;
            //bool NotFlag = (Cond & 4) != 0;
            //uint TypeFlag = (Cond & 3);

            var localCcTemp = _ast.Local(AstLocal.Create <bool>());
            var localCcOr   = _ast.Local(AstLocal.Create <bool>());
            var localCcAnd  = _ast.Local(AstLocal.Create <bool>());

            return(_ast.Statements(
                       _ast.Assign(localCcOr, false),
                       _ast.Assign(localCcAnd, true),

                       // TODO: CHECK THIS!
                       _ast.AssignVcc(0, true),
                       _ast.AssignVcc(1, true),
                       _ast.AssignVcc(2, true),
                       _ast.AssignVcc(3, true),
                       _List(vectorSize, index =>
            {
                AstNodeExpr expr;
                //bool UsedForAggregate;

                var left = VecVs[index];
                var right = VecVt[index];
                switch (cond2)
                {
                case ConditionEnum.VcFl:
                    expr = _ast.Immediate(false);
                    break;

                case ConditionEnum.VcEq:
                    expr = _ast.Binary(left, "==", right);
                    break;

                case ConditionEnum.VcLt:
                    expr = _ast.Binary(left, "<", right);
                    break;

                //case ConditionEnum.VC_LE: Expr = ast.Binary(Left, "<=", Right); break;
                case ConditionEnum.VcLe:
                    expr = _ast.CallStatic((Func <float, float, bool>)MathFloat.IsLessOrEqualsThan, left,
                                           right);
                    break;

                case ConditionEnum.VcTr:
                    expr = _ast.Immediate(true);
                    break;

                case ConditionEnum.VcNe:
                    expr = _ast.Binary(left, "!=", right);
                    break;

                //case ConditionEnum.VC_GE: Expr = ast.Binary(Left, ">=", Right); break;
                case ConditionEnum.VcGe:
                    expr = _ast.CallStatic((Func <float, float, bool>)MathFloat.IsGreatOrEqualsThan, left,
                                           right);
                    break;

                case ConditionEnum.VcGt:
                    expr = _ast.Binary(left, ">", right);
                    break;

                case ConditionEnum.VcEz:
                    expr = _ast.Binary(_ast.Binary(left, "==", 0.0f), "||", _ast.Binary(left, "==", -0.0f));
                    break;

                case ConditionEnum.VcEn:
                    expr = _ast.CallStatic((Func <float, bool>)MathFloat.IsNan, left);
                    break;

                case ConditionEnum.VcEi:
                    expr = _ast.CallStatic((Func <float, bool>)MathFloat.IsInfinity, left);
                    break;

                case ConditionEnum.VcEs:
                    expr = _ast.CallStatic((Func <float, bool>)MathFloat.IsNanOrInfinity, left);
                    break;         // Tekken Dark Resurrection

                case ConditionEnum.VcNz:
                    expr = _ast.Binary(left, "!=", 0f);
                    break;

                case ConditionEnum.VcNn:
                    expr = _ast.Unary("!", _ast.CallStatic((Func <float, bool>)MathFloat.IsNan, left));
                    break;

                case ConditionEnum.VcNi:
                    expr = _ast.Unary("!", _ast.CallStatic((Func <float, bool>)MathFloat.IsInfinity, left));
                    break;

                case ConditionEnum.VcNs:
                    expr = _ast.Unary("!",
                                      _ast.CallStatic((Func <float, bool>)MathFloat.IsNanOrInfinity, left));
                    break;

                default: throw (new InvalidOperationException());
                }

                return _ast.Statements(new List <AstNodeStm>
                {
                    _ast.Assign(localCcTemp, expr),
                    _ast.AssignVcc(index, localCcTemp),
                    _ast.Assign(localCcOr, _ast.Binary(localCcOr, "||", localCcTemp)),
                    _ast.Assign(localCcAnd, _ast.Binary(localCcAnd, "&&", localCcTemp))
                });
            }),
                       _ast.AssignVcc(4, localCcOr),
                       _ast.AssignVcc(5, localCcAnd)
                       ));
        }