Ejemplo n.º 1
0
        static void EmitDebugEpilogue(MethodDefinition wrapper, ILProcessor il, DebugVariables vars)
        {
            if (vars != null)
            {
                var disposeMethod = vars.ErrorHelperType.Methods.First(
                    method => method.Name == "Dispose");

                // Store then reload the result from the call
                var resultLocal = new VariableDefinition(wrapper.ReturnType);
                if (resultLocal.VariableType.FullName != Program.TypeVoid.FullName)
                {
                    il.Body.Variables.Add(resultLocal);
                    il.Emit(OpCodes.Stloc, resultLocal);
                }

                // Special case End to turn on error checking.
                if (il.Body.Method.Name == "End")
                {
                    il.Emit(OpCodes.Call, vars.Get_CurrentContext);
                    il.Emit(OpCodes.Ldc_I4_1);
                    il.Emit(OpCodes.Conv_I1);
                    il.Emit(OpCodes.Call, vars.Set_ErrorChecking);
                }

                // We need a NOP to set up the finally handler range correctly.
                var nopInstruction        = Instruction.Create(OpCodes.Nop);
                var loadInstruction       = Instruction.Create(OpCodes.Ldloca, vars.ErrorHelperLocal);
                var disposeInstruction    = Instruction.Create(OpCodes.Call, disposeMethod);
                var endFinallyInstruction = Instruction.Create(OpCodes.Endfinally);
                var endTryInstruction     = Instruction.Create(OpCodes.Leave, nopInstruction);

                il.Append(endTryInstruction);
                il.Append(loadInstruction);
                il.Append(disposeInstruction);
                il.Append(endFinallyInstruction);
                il.Append(nopInstruction);

                var finallyHandler = new ExceptionHandler(ExceptionHandlerType.Finally);
                finallyHandler.TryStart     = vars.BeginTry;
                finallyHandler.TryEnd       = loadInstruction;
                finallyHandler.HandlerStart = loadInstruction;
                finallyHandler.HandlerEnd   = nopInstruction;

                il.Body.ExceptionHandlers.Add(finallyHandler);

                if (resultLocal.VariableType.FullName != Program.TypeVoid.FullName)
                {
                    il.Emit(OpCodes.Ldloc, resultLocal);
                }
            }
        }
Ejemplo n.º 2
0
        public static DebugVariables GetVariables(Jint.Engine engines)
        {
            DebugVariables variables = new DebugVariables();

            if (engines.ExecutionContext.LexicalEnvironment != null)
            {
                var lexicalEnvironment = engines.ExecutionContext.LexicalEnvironment;

                variables.Local  = GetLocalVariables(lexicalEnvironment);
                variables.Global = GetGlobalVariables(lexicalEnvironment);
            }

            return(variables);
        }
Ejemplo n.º 3
0
        private static DebugVariables EmitDebugPrologue(MethodDefinition wrapper, ILProcessor il)
        {
            DebugVariables vars = null;

            if (il.Body.Method.Name != "GetError")
            {
                // Pull out the namespace name, method fullname will look
                // something like "type namespace.class::method(type arg)"
                var module = il.Body.Method.FullName;
                module = module.Substring(module.IndexOf(' ') + 1);
                module = module.Substring(0, module.IndexOf("::", StringComparison.Ordinal));
                module = module.Substring(0, module.LastIndexOf('.'));

                // Only works for Graphics modules due to hardcoded use of
                // OpenTK.Graphics.GraphicsContext
                if (module == "OpenTK.Graphics.OpenGL4" ||
                    module == "OpenTK.Graphics.OpenGL" ||
                    module == "OpenTK.Graphics.ES10" ||
                    module == "OpenTK.Graphics.ES11" ||
                    module == "OpenTK.Graphics.ES20" ||
                    module == "OpenTK.Graphics.ES30")
                {
                    var errorHelperType = wrapper.Module.GetType(module, "ErrorHelper");

                    if (errorHelperType != null)
                    {
                        vars = new DebugVariables();
                        vars.ErrorHelperType = errorHelperType;

                        // GraphicsContext type
                        var graphicsContext = wrapper.Module.Types.First(
                            type => type.FullName == "OpenTK.Graphics.GraphicsContext");

                        // IGraphicsContext type
                        var iGraphicsContext = wrapper.Module.Types.First(
                            type => type.FullName == "OpenTK.Graphics.IGraphicsContext");

                        // Get the constructor that takes a GraphicsContext parameter
                        var ctor = vars.ErrorHelperType.GetConstructors().FirstOrDefault(
                            c => c.Parameters.Count == 1 &&
                            c.Parameters[0].ParameterType.FullName == iGraphicsContext.FullName);

                        if (ctor == null)
                        {
                            throw new InvalidOperationException(
                                      String.Format(
                                          "{0} does needs a constructor taking {1}",
                                          errorHelperType,
                                          graphicsContext));
                        }

                        // GraphicsContext.CurrentContext property getter
                        vars.Get_CurrentContext = graphicsContext.Methods.First(
                            method => method.Name == "get_CurrentContext");

                        vars.Set_ErrorChecking = graphicsContext.Methods.First(
                            method => method.Name == "set_ErrorChecking");

                        vars.ErrorHelperLocal = new VariableDefinition(vars.ErrorHelperType);

                        // using (new ErrorHelper(GraphicsContext.CurrentContext)) { ...
                        il.Body.Variables.Add(vars.ErrorHelperLocal);
                        il.Emit(OpCodes.Ldloca, vars.ErrorHelperLocal);
                        il.Emit(OpCodes.Call, vars.Get_CurrentContext);
                        il.Emit(OpCodes.Call, ctor);

                        vars.BeginTry = Instruction.Create(OpCodes.Nop);
                        il.Append(vars.BeginTry);

                        // Special case Begin to turn off error checking.
                        if (il.Body.Method.Name == "Begin")
                        {
                            il.Emit(OpCodes.Call, vars.Get_CurrentContext);
                            il.Emit(OpCodes.Ldc_I4_0);
                            il.Emit(OpCodes.Conv_I1);
                            il.Emit(OpCodes.Call, vars.Set_ErrorChecking);
                        }
                    }
                }
            }

            return(vars);
        }
Ejemplo n.º 4
0
        // Create body for method
        private static void ProcessMethod(MethodDefinition wrapper, MethodDefinition native, int slot,
                                          FieldDefinition entry_points)
        {
            var body         = wrapper.Body;
            var il           = body.GetILProcessor();
            var instructions = body.Instructions;

            instructions.Clear();

            // Declare pinned variables for every reference and array parameter
            // and push each parameter on the stack

            DebugVariables vars = null;

            if (Options.EnableDebugCalls)
            {
                vars = EmitDebugPrologue(wrapper, il);
            }

            // Patch convenience wrappers
            List <GeneratedVariableIdentifier> generatedVariables = new List <GeneratedVariableIdentifier>();

            if (wrapper.Parameters.Count == native.Parameters.Count)
            {
                generatedVariables = EmitParameters(wrapper, native, body, il);
            }
            else
            {
                int difference = native.Parameters.Count - wrapper.Parameters.Count;
                generatedVariables = EmitConvenienceWrapper(wrapper, native, difference, body, il);
            }

            if (slot == -1 || Options.UseDLLImport)
            {
                // issue DllImport call
                EmitCall(il, native);
            }
            else
            {
                // push the entry point address on the stack
                EmitEntryPoint(entry_points, il, slot);

                // issue calli
                EmitCalli(il, native);
            }

            if (wrapper.ReturnType.Name != "Void")
            {
                EmitReturnTypeWrapper(wrapper, native, body, il);
            }

            EmitParameterEpilogues(wrapper, native, body, il, generatedVariables);

            if (Options.EnableDebugCalls)
            {
                EmitDebugEpilogue(wrapper, il, vars);
            }

            // return
            il.Emit(OpCodes.Ret);

            if (body.Variables.Count > 0)
            {
                // Required for verifiable executables
                // (otherwise peverify complains bitterly)
                body.InitLocals = true;
            }
            body.OptimizeMacros();
        }
Ejemplo n.º 5
0
        static void EmitDebugEpilogue(MethodDefinition wrapper, ILProcessor il, DebugVariables vars)
        {
            if (vars != null)
            {
                var disposeMethod = vars.ErrorHelperType.Methods.First(
                    method => method.Name == "Dispose");

                // Store then reload the result from the call
                var resultLocal = new VariableDefinition(wrapper.ReturnType);
                if (resultLocal.VariableType.FullName != Program.TypeVoid.FullName)
                {
                    il.Body.Variables.Add(resultLocal);
                    il.Emit(OpCodes.Stloc, resultLocal);
                }

                // Special case End to turn on error checking.
                if (il.Body.Method.Name == "End")
                {
                    il.Emit(OpCodes.Call, vars.Get_CurrentContext);
                    il.Emit(OpCodes.Ldc_I4_1);
                    il.Emit(OpCodes.Conv_I1);
                    il.Emit(OpCodes.Call, vars.Set_ErrorChecking);
                }

                // We need a NOP to set up the finally handler range correctly.
                var nopInstruction = Instruction.Create(OpCodes.Nop);
                var loadInstruction = Instruction.Create(OpCodes.Ldloca, vars.ErrorHelperLocal);
                var disposeInstruction = Instruction.Create(OpCodes.Call, disposeMethod);
                var endFinallyInstruction = Instruction.Create(OpCodes.Endfinally);
                var endTryInstruction = Instruction.Create(OpCodes.Leave, nopInstruction);

                il.Append(endTryInstruction);
                il.Append(loadInstruction);
                il.Append(disposeInstruction);
                il.Append(endFinallyInstruction);
                il.Append(nopInstruction);

                var finallyHandler = new ExceptionHandler(ExceptionHandlerType.Finally);
                finallyHandler.TryStart = vars.BeginTry;
                finallyHandler.TryEnd = loadInstruction;
                finallyHandler.HandlerStart = loadInstruction;
                finallyHandler.HandlerEnd = nopInstruction;

                il.Body.ExceptionHandlers.Add(finallyHandler);

                if (resultLocal.VariableType.FullName != Program.TypeVoid.FullName)
                {
                    il.Emit(OpCodes.Ldloc, resultLocal);
                }
            }
        }
Ejemplo n.º 6
0
        static DebugVariables EmitDebugPrologue(MethodDefinition wrapper, ILProcessor il)
        {

            DebugVariables vars = null;
            if (il.Body.Method.Name != "GetError")
            {
                // Pull out the namespace name, method fullname will look 
                // something like "type namespace.class::method(type arg)"
                var module = il.Body.Method.FullName;
                module = module.Substring(module.IndexOf(' ') + 1);
                module = module.Substring(0, module.IndexOf("::"));
                module = module.Substring(0, module.LastIndexOf('.'));

                // Only works for Graphics modules due to hardcoded use of
                // OpenTK.Graphics.GraphicsContext
                if (module == "OpenTK.Graphics.OpenGL4" ||
                    module == "OpenTK.Graphics.OpenGL" ||
                    module == "OpenTK.Graphics.ES10" ||
                    module == "OpenTK.Graphics.ES11" ||
                    module == "OpenTK.Graphics.ES20" ||
                    module == "OpenTK.Graphics.ES30")
                {
                    var errorHelperType = wrapper.Module.GetType(module, "ErrorHelper");

                    if (errorHelperType != null)
                    {
                        vars = new DebugVariables();
                        vars.ErrorHelperType = errorHelperType;

                        // GraphicsContext type
                        var graphicsContext = wrapper.Module.Types.First(
                            type => type.FullName == "OpenTK.Graphics.GraphicsContext");

                        // IGraphicsContext type
                        var iGraphicsContext = wrapper.Module.Types.First(
                            type => type.FullName == "OpenTK.Graphics.IGraphicsContext");

                        // Get the constructor that takes a GraphicsContext parameter
                        var ctor = vars.ErrorHelperType.GetConstructors().FirstOrDefault(
                            c => c.Parameters.Count == 1 &&
                            c.Parameters[0].ParameterType.FullName == iGraphicsContext.FullName);

                        if (ctor == null)
                        {
                            throw new InvalidOperationException(
                                String.Format(
                                    "{0} does needs a constructor taking {1}",
                                    errorHelperType,
                                    graphicsContext));
                        }

                        // GraphicsContext.CurrentContext property getter
                        vars.Get_CurrentContext = graphicsContext.Methods.First(
                            method => method.Name == "get_CurrentContext");

                        vars.Set_ErrorChecking = graphicsContext.Methods.First(
                            method => method.Name == "set_ErrorChecking");

                        vars.ErrorHelperLocal = new VariableDefinition(vars.ErrorHelperType);

                        // using (new ErrorHelper(GraphicsContext.CurrentContext)) { ...
                        il.Body.Variables.Add(vars.ErrorHelperLocal);
                        il.Emit(OpCodes.Ldloca, vars.ErrorHelperLocal);
                        il.Emit(OpCodes.Call, vars.Get_CurrentContext);
                        il.Emit(OpCodes.Call, ctor);

                        vars.BeginTry = Instruction.Create(OpCodes.Nop);
                        il.Append(vars.BeginTry);

                        // Special case Begin to turn off error checking.
                        if (il.Body.Method.Name == "Begin")
                        {
                            il.Emit(OpCodes.Call, vars.Get_CurrentContext);
                            il.Emit(OpCodes.Ldc_I4_0);
                            il.Emit(OpCodes.Conv_I1);
                            il.Emit(OpCodes.Call, vars.Set_ErrorChecking);
                        }
                    }
                }
            }

            return vars;
        }
Ejemplo n.º 7
0
        // Create body for method
        static void ProcessMethod(MethodDefinition wrapper, MethodDefinition native, int slot,
                                  FieldDefinition entry_points, IEnumerable <string> options)
        {
            var body         = wrapper.Body;
            var il           = body.GetILProcessor();
            var instructions = body.Instructions;

            instructions.Clear();

            // Declare pinned variables for every reference and array parameter
            // and push each parameter on the stack

            DebugVariables vars = null;

            if (options.Contains("-debug"))
            {
                vars = EmitDebugPrologue(wrapper, il);
            }

            // Patch convenience wrappers
            if (wrapper.Parameters.Count == native.Parameters.Count)
            {
                EmitParameters(wrapper, body, il);
            }
            else
            {
                int difference = native.Parameters.Count - wrapper.Parameters.Count;
                EmitConvenienceWrapper(wrapper, native, difference, body, il);
            }

            if (slot != -1)
            {
                // push the entry point address on the stack
                EmitEntryPoint(entry_points, il, slot);

                // issue calli
                EmitCalli(il, native);
            }
            else
            {
                // issue DllImport call
                EmitCall(il, native);
            }

            if (wrapper.ReturnType.Name != "Void")
            {
                EmitReturnTypeWrapper(wrapper, native, body, il);
            }
            if (wrapper.Parameters.Any(p => p.ParameterType.Name == "StringBuilder"))
            {
                EmitStringBuilderEpilogue(wrapper, native, body, il);
            }
            if (wrapper.Parameters.Any(p => p.ParameterType.Name == "String" && p.ParameterType.IsArray))
            {
                EmitStringArrayEpilogue(wrapper, body, il);
            }
            if (wrapper.Parameters.Any(p => p.ParameterType.Name == "String" && !p.ParameterType.IsArray))
            {
                EmitStringEpilogue(wrapper, body, il);
            }

            if (options.Contains("-debug"))
            {
                EmitDebugEpilogue(wrapper, il, vars);
            }

            // return
            il.Emit(OpCodes.Ret);

            if (body.Variables.Count > 0)
            {
                // Required for verifiable executables
                // (otherwise peverify complains bitterly)
                body.InitLocals = true;
            }
            body.OptimizeMacros();
        }
Ejemplo n.º 8
0
        void ToWorkshop(Func <VarCollection, Rule[]> addRules)
        {
            // Set up the variable collection.
            VarCollection.Setup();

            // Set up initial global and player rules.
            InitialGlobal = new TranslateRule(this, "Initial Global", RuleEvent.OngoingGlobal);
            InitialPlayer = new TranslateRule(this, "Initial Player", RuleEvent.OngoingPlayer);
            WorkshopRules = new List <Rule>();

            // Init called types.
            foreach (var type in Types.CalledTypes.Distinct())
            {
                type.WorkshopInit(this);
            }

            // Assign variables at the rule-set level.
            foreach (var variable in rulesetVariables)
            {
                // Assign the variable an index.
                var assigner = DefaultIndexAssigner.Add(VarCollection, variable, true, null) as IndexReference;

                // Assigner will be non-null if it is an IndexReference.
                if (assigner != null)
                {
                    DebugVariables.Add(variable, assigner);
                    // Initial value.
                    if (variable.InitialValue != null)
                    {
                        var addToInitialRule = GetInitialRule(variable.VariableType == VariableType.Global);

                        addToInitialRule.ActionSet.AddAction(assigner.SetVariable(
                                                                 (Element)variable.InitialValue.Parse(addToInitialRule.ActionSet)
                                                                 ));
                    }
                }
            }

            // Setup single-instance methods.
            foreach (var method in subroutines)
            {
                method.SetupSubroutine();
            }

            // Parse the rules.
            foreach (var rule in rules)
            {
                var  translate = new TranslateRule(this, rule);
                Rule newRule   = translate.GetRule();
                WorkshopRules.Add(newRule);
                rule.ElementCountLens.RuleParsed(newRule);
            }

            // Add built-in rules.
            // Initial player
            if (InitialPlayer.Actions.Count > 0)
            {
                WorkshopRules.Insert(0, InitialPlayer.GetRule());
            }

            // Initial global
            if (InitialGlobal.Actions.Count > 0)
            {
                WorkshopRules.Insert(0, InitialGlobal.GetRule());
            }

            // Additional
            if (addRules != null)
            {
                WorkshopRules.AddRange(addRules.Invoke(VarCollection).Where(rule => rule != null));
            }

            // Order the workshop rules by priority.
            WorkshopRules = WorkshopRules.OrderBy(wr => wr.Priority).ToList();

            // Get the final workshop string.
            WorkshopBuilder result = new WorkshopBuilder(Language);

            LanguageInfo.I18nWarningMessage(result, Language);

            // Get the custom game settings.
            if (Importer.MergedLobbySettings != null)
            {
                Ruleset settings = Ruleset.Parse(Importer.MergedLobbySettings);
                settings.ToWorkshop(result);
                result.AppendLine();
            }

            // Get the variables.
            VarCollection.ToWorkshop(result);
            result.AppendLine();

            // Print class identifiers.
            Types.PrintClassIdentifiers(result);

            // Get the subroutines.
            SubroutineCollection.ToWorkshop(result);

            // Get the rules.
            for (int i = 0; i < WorkshopRules.Count; i++)
            {
                WorkshopRules[i].ToWorkshop(result, OptimizeOutput);
                ElementCount += WorkshopRules[i].ElementCount(OptimizeOutput);
                if (i != WorkshopRules.Count - 1)
                {
                    result.AppendLine();
                }
            }

            WorkshopCode = result.ToString();
        }
        void ToWorkshop(Func <VarCollection, Rule[]> addRules)
        {
            // Set up the variable collection.
            VarCollection.Setup();

            WorkshopConverter = new ToWorkshop(this);

            // Set up initial global and player rules.
            InitialGlobal = new TranslateRule(this, "Initial Global", RuleEvent.OngoingGlobal);
            InitialPlayer = new TranslateRule(this, "Initial Player", RuleEvent.OngoingPlayer);
            WorkshopRules = new List <Rule>();

            WorkshopConverter.InitStatic();

            // Init called types.
            foreach (var workshopInit in _workshopInit)
            {
                workshopInit.WorkshopInit(this);
            }

            // Assign variables at the rule-set level.
            foreach (var variable in rulesetVariables)
            {
                var addToInitialRule = GetInitialRule(variable.VariableType == VariableType.Global);

                // Assign the variable an index.
                IGettable value = variable
                                  .GetDefaultInstance(null)
                                  .GetAssigner(new(addToInitialRule.ActionSet))
                                  .GetValue(new GettableAssignerValueInfo(addToInitialRule.ActionSet)
                {
                    SetInitialValue = SetInitialValue.SetIfExists
                });
                DefaultIndexAssigner.Add(variable, value);

                if (value is IndexReference indexReference)
                {
                    DebugVariables.Add(variable, indexReference);
                }
            }

            // Parse the rules.
            foreach (var rule in rules)
            {
                var  translate = new TranslateRule(this, rule);
                Rule newRule   = GetRule(translate.GetRule());
                WorkshopRules.Add(newRule);
                rule.ElementCountLens.RuleParsed(newRule);
            }

            // Add built-in rules.
            // Initial player
            if (InitialPlayer.Actions.Count > 0)
            {
                WorkshopRules.Insert(0, GetRule(InitialPlayer.GetRule()));
            }

            // Initial global
            if (InitialGlobal.Actions.Count > 0)
            {
                WorkshopRules.Insert(0, GetRule(InitialGlobal.GetRule()));
            }

            // Additional
            if (addRules != null)
            {
                WorkshopRules.AddRange(addRules.Invoke(VarCollection).Where(rule => rule != null));
            }

            // Complete portable functions
            WorkshopConverter.LambdaBuilder.Complete();

            // Order the workshop rules by priority.
            WorkshopRules = WorkshopRules.OrderBy(wr => wr.Priority).ToList();

            // Get the final workshop string.
            WorkshopBuilder result = new WorkshopBuilder(Language);

            LanguageInfo.I18nWarningMessage(result, Language);

            // Get the custom game settings.
            if (Importer.MergedLobbySettings != null)
            {
                Ruleset settings = Ruleset.Parse(Importer.MergedLobbySettings);
                settings.ToWorkshop(result);
                result.AppendLine();
            }

            // Get the variables.
            VarCollection.ToWorkshop(result);
            result.AppendLine();

            // Get the subroutines.
            SubroutineCollection.ToWorkshop(result);

            // Get the rules.
            for (int i = 0; i < WorkshopRules.Count; i++)
            {
                WorkshopRules[i].ToWorkshop(result);
                ElementCount += WorkshopRules[i].ElementCount();
                if (i != WorkshopRules.Count - 1)
                {
                    result.AppendLine();
                }
            }

            WorkshopCode = result.GetResult();
        }