示例#1
0
文件: Ptc.cs 项目: ntrancer/Ryujinx
        private static TranslatedFunction FastTranslate(byte[] code, UnwindInfo unwindInfo, bool highCq)
        {
            CompiledFunction cFunc = new CompiledFunction(code, unwindInfo);

            IntPtr codePtr = JitCache.Map(cFunc);

            GuestFunction gFunc = Marshal.GetDelegateForFunctionPointer <GuestFunction>(codePtr);

            TranslatedFunction tFunc = new TranslatedFunction(gFunc, highCq);

            return(tFunc);
        }
示例#2
0
 internal JSManagedFunction(
     VirtualMachine vm,
     VariableScope outerScope,
     CompiledFunction compiledFunction,
     JSObject inherited)
     : base(vm, inherited)
 {
     Contract.Requires(compiledFunction != null);
     Contract.Requires(inherited != null);
     OuterScope       = outerScope;
     CompiledFunction = compiledFunction;
 }
        public override void AddDeclarationToBlock(BlockContext context)
        {
            var fdef  = this;
            var block = context.Block;

            if (context.MakeCType(fdef.Specifiers, fdef.Declarator, null, block) is CFunctionType ftype)
            {
                var name = fdef.Declarator.DeclaredIdentifier;
                var f    = new CompiledFunction(name, ftype, fdef.Body);
                block.Functions.Add(f);
            }
        }
示例#4
0
        public static IInvoker GetFunctionInvoker(
            string language, string functionName, string moduleName, string functionHandler,
            int timeout = 180000)
        {
            FunctionCompiler.PublishTestFunction(language, functionName);
            var publishPath = Environment.GetEnvironmentVariable("PUBLISH_PATH");

            var function = new CompiledFunction(moduleName, functionHandler, publishPath, functionName);
            var invoker  = new CompiledFunctionInvoker(function, timeout, publishPath);

            return(invoker);
        }
示例#5
0
        private static TranslatedFunction FastTranslate(ReadOnlySpan <byte> code, ulong guestSize, UnwindInfo unwindInfo, bool highCq)
        {
            CompiledFunction cFunc = new CompiledFunction(code.ToArray(), unwindInfo);

            IntPtr codePtr = JitCache.Map(cFunc);

            GuestFunction gFunc = Marshal.GetDelegateForFunctionPointer <GuestFunction>(codePtr);

            TranslatedFunction tFunc = new TranslatedFunction(gFunc, guestSize, highCq);

            return(tFunc);
        }
示例#6
0
    public Interpreter( CompiledFunction[] bytecode )
    {
        function = new Dictionary<string,CompiledFunction>();

        foreach( CompiledFunction cf in bytecode ) {
            string name = cf.Name;
            if (function.ContainsKey(name)) {
                Console.WriteLine("Duplicate declaration of function {0}", name);
                continue;
            }
            function[name] = cf;
        }
    }
示例#7
0
        public static T Compile <T>(
            ControlFlowGraph cfg,
            OperandType[]    argTypes,
            OperandType retType,
            CompilerOptions options,
            PtcInfo ptcInfo = null)
        {
            CompiledFunction func = Compile(cfg, argTypes, retType, options, ptcInfo);

            IntPtr codePtr = JitCache.Map(func);

            return(Marshal.GetDelegateForFunctionPointer <T>(codePtr));
        }
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureServices(services =>
            {
                var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(IInvoker));
                if (descriptor != null)
                {
                    services.Remove(descriptor);
                }
                services.AddTransient <IInvoker>(provider => {
                    Func <string, string> config = s => Environment.GetEnvironmentVariable(s);

                    var function  = new CompiledFunction(config("MOD_NAME"), config("FUNC_HANDLER"), config("ASSEMBLY_NAME"));
                    var timeoutMs = int.Parse(config("FUNC_TIMEOUT")) * 1000;
                    return(new CompiledFunctionInvoker(function, timeoutMs));
                });
            });
        }
示例#9
0
        public static IntPtr Map(CompiledFunction func)
        {
            byte[] code = func.Code;

            lock (_lock)
            {
                int funcOffset = Allocate(code.Length);

                IntPtr funcPtr = _basePointer + funcOffset;

                Marshal.Copy(code, 0, funcPtr, code.Length);

                ReprotectRange(funcOffset, code.Length);

                Add(new JitCacheEntry(funcOffset, code.Length, func.UnwindInfo));

                return(funcPtr);
            }
        }
示例#10
0
        private List <Path> GenerateConstriants(CompiledFunction function)
        {
            var cutSet  = new HashSet <IBlock>();
            var visited = new HashSet <IBlock>();

            foreach (var block in function.EntryBlock.Traverse())
            {
                visited.Add(block);

                var successors = block.GetSuccessors();

                if (visited.Overlaps(successors))
                {
                    cutSet.Add(block); // Cut points are at the ends of blocks.
                }
            }

            return(GeneratePaths(function.EntryBlock, cutSet));
        }
示例#11
0
        private static CompiledFunction Compile(Function function, bool isEvalMode)
        {
            Contract.Requires(function != null);
            Contract.Ensures(Contract.Result <CompiledFunction>() != null);
            // Пока используем простую реализацию на основе рекурсии (потом заменим на обход на основе стека)
            if (function.NestedFunctions.Count == 0)
            {
                return(FunctionCompiler.Compile(
                           function, CompiledFunction.EmptyNestedFunctions, isEvalMode));
            }
            var nestedFunctions = new CompiledFunction[function.NestedFunctions.Count];

            for (var i = 0; i < nestedFunctions.Length; i++)
            {
                nestedFunctions[i] = Compile(function.NestedFunctions[i], false);
                // Для того чтобы раньше освободить ссылку на функцию
                function.NestedFunctions[i] = null;
            }
            return(FunctionCompiler.Compile(
                       function, nestedFunctions, isEvalMode));
        }
示例#12
0
        public static IntPtr Map(CompiledFunction func)
        {
            byte[] code = func.Code;

            lock (_lock)
            {
                Debug.Assert(_initialized);

                int funcOffset = Allocate(code.Length);

                IntPtr funcPtr = _jitRegion.Pointer + funcOffset;

                Marshal.Copy(code, 0, funcPtr, code.Length);

                ReprotectRange(funcOffset, code.Length);

                Add(new JitCacheEntry(funcOffset, code.Length, func.UnwindInfo));

                return funcPtr;
            }
        }
示例#13
0
 // A method for testing the other methods in the CompiledFunction class.
 public static bool UnitTest(bool verbose)
 {
     try {
         CompiledFunction cf = new CompiledFunction("test");
         cf.AddArgument("a");
         cf.AddArgument("b");
         cf.AddVariable("x");
         cf.AddVariable("y");
         cf.AddInstruction(OpCode.Load,1);
         int k = cf.AddInstruction(OpCode.Jump, 0);
         cf.AddInstruction(OpCode.Call, "getval", 0);
         int t = cf.getCodeOffset();
         cf.PatchInstruction(k, t);
         cf.AddInstruction(OpCode.Add);
     } catch( Exception e ) {
         Console.WriteLine("CompiledFunction: unit test failed; exception thrown:\n\t{0}",
             e.Message);
         return false;
     }
     Console.WriteLine("CompiledFunction: unit test succeeded");
     return true;
 }
示例#14
0
        public static IntPtr Map(CompiledFunction func)
        {
            byte[] code = func.Code;

            lock (_lock)
            {
                Debug.Assert(_initialized);

                int funcOffset = Allocate(code.Length);

                IntPtr funcPtr = _jitRegion.Pointer + funcOffset;

                ReprotectAsWritable(funcOffset, code.Length);

                Marshal.Copy(code, 0, funcPtr, code.Length);

                ReprotectAsExecutable(funcOffset, code.Length);

                Add(funcOffset, code.Length, func.UnwindInfo);

                return(funcPtr);
            }
        }
示例#15
0
    // execute the bytecode of function  fn,
    // using the arguments on the stack and leaving a result on the stack.
    // A result of true indicates that execution completed normally.
    // A result of false indicates that a STOP instruction was executed
    // and interpretation of the whole program should cease.
    bool executeFunction( CompiledFunction fn )
    {
        // allocate slots for local variables on the stack
        int firstLocal = stackHeight - fn.NumArguments;
        for( int i = fn.NumArguments; i < fn.NumLocals; i++ )
            push(new SMValue());

        int pc = 0;

        try {
            int    iopnd;
            float  fopnd;
            string sopnd;
            SMValue val;
            for( ; ; ) {
                Instruction ins = fn.GetInstructionAt(pc++);
                if ((traceFlags & TraceOptions.TraceOps) != TraceOptions.None)
                    Console.WriteLine("* {0}: {1}", pc-1, ins);
                switch(ins.Op) {
                case OpCode.Load:
                    iopnd = ((InstructionInt)ins).IntOperand;
                    if (iopnd >= fn.NumLocals)
                        throw new RunTimeError("invalid immediate operand");
                    val = stack[iopnd+firstLocal];
                    if (val.t == TypeCode.None)
                        throw new RunTimeError("uninitialized variable used");
                    push(val);
                    break;
                case OpCode.Store:
                    iopnd = ((InstructionInt)ins).IntOperand;
                    if (iopnd >= fn.NumLocals)
                        throw new RunTimeError("invalid immediate operand");
                    stack[iopnd+firstLocal] = pop();
                    break;
                case OpCode.LoadIntConst:
                    iopnd = ((InstructionInt)ins).IntOperand;
                    push(new SMValueInt(iopnd));
                    break;
                case OpCode.LoadFltConst:
                    fopnd = ((InstructionFlt)ins).FltOperand;
                    push(new SMValueFloat(fopnd));
                    break;
                case OpCode.LoadStrConst:
                    sopnd = ((InstructionStr)ins).StrOperand;
                    push(new SMValueStr(sopnd));
                    break;
                case OpCode.LoadNull:
                    push(new SMValue());
                    break;
                case OpCode.Jump:
                    pc = ((InstructionInt)ins).IntOperand;
                    break;
                case OpCode.JumpIfFalse:
                    val = pop();
                    if (val.t != TypeCode.IntType)
                        throw new RunTimeError("type mismatch, int value required");
                    if (val.intValue == 0)
                        pc = ((InstructionInt)ins).IntOperand;
                    break;
                case OpCode.Call:
                    sopnd = ((InstructionStrInt)ins).Name;
                    iopnd = ((InstructionStrInt)ins).NumArgs;
                    CompiledFunction callee = null;
                    if (!function.TryGetValue(sopnd, out callee))
                        throw new RunTimeError(
                            String.Format("call to undefined function {0}", sopnd));
                    if (callee.NumArguments != iopnd)
                        throw new RunTimeError(
                            String.Format("call with incorrect number of arguments to function {0}", sopnd));
                    if (!executeFunction(callee))
                        return false;  // failure return
                    break;
                case OpCode.Pop:
                    pop();
                    break;
                case OpCode.Return:
                    val = pop(); // this is the function result
                    // now pop all the local variables (including the arguments)
                    for( int j = fn.NumLocals; j > 0; j-- )
                        pop();
                    push(val);  // put the function result back
                    return true;  // success return
                case OpCode.Add:
                case OpCode.Sub:
                case OpCode.Mul:
                case OpCode.Div:
                case OpCode.CmpEq:
                case OpCode.CmpNe:
                case OpCode.CmpGt:
                case OpCode.CmpGe:
                case OpCode.CmpLt:
                case OpCode.CmpLe:
                    SMValue val2 = pop();  // 2nd operand is above the 1st on the stack!
                    SMValue val1 = pop();
                    if (val1.t == TypeCode.IntType && val2.t == TypeCode.IntType)
                        doIntOp(ins.Op, val1.intValue, val2.intValue);
                    else {
                        float flt1 = (val1.t == TypeCode.FloatType)? val1.fltValue : val1.intValue;
                        float flt2 = (val2.t == TypeCode.FloatType)? val2.fltValue : val2.intValue;
                        doFltOp(ins.Op, flt1, flt2);
                    }
                    break;
                case OpCode.Stop:
                    Console.WriteLine("Program halted (stop instruction)");
                    return false;
                case OpCode.Read:
                    push(readValue());
                    break;
                case OpCode.Write:
                    val = pop();
                    Console.Write(val.ToString());
                    break;
                case OpCode.WriteLine:
                    Console.WriteLine();
                    break;
                default:
                    throw new RunTimeError("unimplemented opcode");
                }
            }
        } catch( ApplicationException e ) {
            Console.WriteLine("Execution aborted due to run-time error:\n\t{0}", e.Message);
        }
        return false;
    }
示例#16
0
        Executable CompileExecutable()
        {
            var exe        = new Executable(options.MachineInfo);
            var exeContext = new ExecutableContext(exe, options.Report);

            // Put something at the zero address so we don't get 0 addresses of globals
            exe.AddGlobal("__zero__", CBasicType.SignedInt);

            //
            // Find Variables, Functions, Types
            //
            var exeInitBody = new Block(VariableScope.Local);
            var tucs        = tus.Select(x => new TranslationUnitContext(x, exeContext));
            var tuInits     = new List <(CompiledFunction, EmitContext)> ();

            foreach (var tuc in tucs)
            {
                var tu = tuc.TranslationUnit;
                AddStatementDeclarations(tuc);
                if (tu.InitStatements.Count > 0)
                {
                    var tuInitBody = new Block(VariableScope.Local);
                    tuInitBody.AddStatements(tu.InitStatements);
                    var tuInit = new CompiledFunction($"__{tu.Name}__cinit", CFunctionType.VoidProcedure, tuInitBody);
                    exeInitBody.AddStatement(new ExpressionStatement(new FuncallExpression(new VariableExpression(tuInit.Name, Location.Null, Location.Null))));
                    tuInits.Add((tuInit, tuc));
                    exe.Functions.Add(tuInit);
                }
            }

            //
            // Generate a function to init globals
            //
            var exeInit = new CompiledFunction($"__cinit", CFunctionType.VoidProcedure, exeInitBody);

            exe.Functions.Add(exeInit);

            //
            // Link everything together
            // This is done before compilation to make sure everything is visible (for recursion)
            //
            var functionsToCompile = new List <(CompiledFunction, EmitContext)> {
                (exeInit, exeContext)
            };

            functionsToCompile.AddRange(tuInits);
            foreach (var tuc in tucs)
            {
                var tu = tuc.TranslationUnit;
                foreach (var g in tu.Variables)
                {
                    var v = exe.AddGlobal(g.Name, g.VariableType);
                    v.InitialValue = g.InitialValue;
                }
                var funcs = tu.Functions.Where(x => x.Body != null).ToList();
                exe.Functions.AddRange(funcs);
                functionsToCompile.AddRange(funcs.Select(x => (x, (EmitContext)tuc)));
            }

            //
            // Compile functions
            //
            foreach (var(f, pc) in functionsToCompile)
            {
                var body = f.Body;
                if (body == null)
                {
                    continue;
                }
                var fc = new FunctionContext(exe, f, pc);
                AddStatementDeclarations(fc);
                body.Emit(fc);
                f.LocalVariables.AddRange(fc.LocalVariables);

                // Make sure it returns
                if (body.Statements.Count == 0 || !body.AlwaysReturns)
                {
                    if (f.FunctionType.ReturnType.IsVoid)
                    {
                        fc.Emit(OpCode.Return);
                    }
                    else
                    {
                        options.Report.Error(161, "'" + f.Name + "' not all code paths return a value");
                    }
                }
            }

            return(exe);
        }

        void AddStatementDeclarations(BlockContext context)
        {
            var block = context.Block;

            foreach (var s in block.Statements)
            {
                AddStatementDeclarations(s, context);
            }
        }

        void AddStatementDeclarations(Statement statement, BlockContext context)
        {
            var block = context.Block;

            if (statement is MultiDeclaratorStatement multi)
            {
                if (multi.InitDeclarators != null)
                {
                    foreach (var idecl in multi.InitDeclarators)
                    {
                        if ((multi.Specifiers.StorageClassSpecifier & StorageClassSpecifier.Typedef) != 0)
                        {
                            var name  = idecl.Declarator.DeclaredIdentifier;
                            var ttype = context.MakeCType(multi.Specifiers, idecl.Declarator, idecl.Initializer, block);
                            block.Typedefs[name] = ttype;
                        }
                        else
                        {
                            CType ctype = context.MakeCType(multi.Specifiers, idecl.Declarator, idecl.Initializer, block);
                            var   name  = idecl.Declarator.DeclaredIdentifier;

                            if (ctype is CFunctionType ftype && !HasStronglyBoundPointer(idecl.Declarator))
                            {
                                var nameContext = (idecl.Declarator.InnerDeclarator is IdentifierDeclarator ndecl && ndecl.Context.Count > 0) ?
                                                  string.Join("::", ndecl.Context) : "";
                                var f = new CompiledFunction(name, nameContext, ftype);
                                block.Functions.Add(f);
                            }
                            else
                            {
                                if ((ctype is CArrayType atype) &&
                                    (atype.Length == null) &&
                                    (idecl.Initializer != null))
                                {
                                    if (idecl.Initializer is StructuredInitializer structInit)
                                    {
                                        var len = 0;
                                        foreach (var i in structInit.Initializers)
                                        {
                                            if (i.Designation == null)
                                            {
                                                len++;
                                            }
                                            else
                                            {
                                                foreach (var de in i.Designation.Designators)
                                                {
                                                    // TODO: Pay attention to designators
                                                    len++;
                                                }
                                            }
                                        }
                                        atype = new CArrayType(atype.ElementType, len);
                                    }
                                    else
                                    {
                                        //Report.Error();
                                    }
                                }
                                //var init = GetInitExpression(idecl.Initializer);
                                block.AddVariable(name, ctype ?? CBasicType.SignedInt);
                            }

                            if (idecl.Initializer != null)
                            {
                                var varExpr  = new VariableExpression(name, Location.Null, Location.Null);
                                var initExpr = GetInitializerExpression(idecl.Initializer);
                                block.InitStatements.Add(new ExpressionStatement(new AssignExpression(varExpr, initExpr)));
                            }
                        }
                    }
                }
        public override void AddDeclarationToBlock(BlockContext context)
        {
            var multi = this;
            var block = context.Block;

            if (multi.InitDeclarators != null)
            {
                foreach (var idecl in multi.InitDeclarators)
                {
                    if ((multi.Specifiers.StorageClassSpecifier & StorageClassSpecifier.Typedef) != 0)
                    {
                        var name  = idecl.Declarator.DeclaredIdentifier;
                        var ttype = context.MakeCType(multi.Specifiers, idecl.Declarator, idecl.Initializer, block);
                        block.Typedefs[name] = ttype;
                    }
                    else
                    {
                        CType ctype = context.MakeCType(multi.Specifiers, idecl.Declarator, idecl.Initializer, block);
                        var   name  = idecl.Declarator.DeclaredIdentifier;

                        if (ctype is CFunctionType ftype && !HasStronglyBoundPointer(idecl.Declarator))
                        {
                            var nameContext = (idecl.Declarator.InnerDeclarator is IdentifierDeclarator ndecl && ndecl.Context.Count > 0) ?
                                              string.Join("::", ndecl.Context) : "";
                            var f = new CompiledFunction(name, nameContext, ftype);
                            block.Functions.Add(f);
                        }
                        else
                        {
                            if ((ctype is CArrayType atype) &&
                                (atype.Length == null) &&
                                (idecl.Initializer != null))
                            {
                                if (idecl.Initializer is StructuredInitializer structInit)
                                {
                                    var len = 0;
                                    foreach (var i in structInit.Initializers)
                                    {
                                        if (i.Designation == null)
                                        {
                                            len++;
                                        }
                                        else
                                        {
                                            foreach (var de in i.Designation.Designators)
                                            {
                                                // TODO: Pay attention to designators
                                                len++;
                                            }
                                        }
                                    }
                                    atype = new CArrayType(atype.ElementType, len);
                                }
                                else
                                {
                                    //Report.Error();
                                }
                            }
                            //var init = GetInitExpression(idecl.Initializer);
                            block.AddVariable(name, ctype ?? CBasicType.SignedInt);
                        }

                        if (idecl.Initializer != null)
                        {
                            var varExpr  = new VariableExpression(name, Location.Null, Location.Null);
                            var initExpr = GetInitializerExpression(idecl.Initializer);
                            block.InitStatements.Add(new ExpressionStatement(new AssignExpression(varExpr, initExpr)));
                        }
                    }
示例#18
0
 public BlockContext(Block block, MachineInfo machineInfo, Report report, CompiledFunction fdecl, EmitContext parentContext)
     : base(machineInfo, report, fdecl, parentContext)
 {
     Block = block;
 }
示例#19
0
文件: parser-v2.cs 项目: bradens/uvc
    // parses one function definition
    void matchFunction()
    {
        match(Token.KwdFunc);
        currFunction = new CompiledFunction(sc.TokenText);

        // Get the function text
        string fnName = sc.TokenText;
        match(Token.Ident);  // the function name

        // check for uniqueness, then add to the function list if unique.
        checkUniqueFunction(fnName);
        FunctionList.Add(fnName);

        currSymbolTable = new SymbolTable();
        match(Token.LPar);
        if (nextToken != Token.RPar) {
            for( ; ; ) {
                string argname = sc.TokenText;
                match(Token.Ident);
                if (!currSymbolTable.AddEntry(argname, currFunction.AddArgument(argname)))
                    SemanticError("duplicate declaration of argument {0}", argname);
                if (nextToken != Token.Comma)
                    break;
                advance();
            }
        }
        match(Token.RPar);
        matchBlock();
        // the function should end with a return statement.  In case ...
        currFunction.AddInstruction(OpCode.Stop);
        program.Add(currFunction);
        currFunction = null;
        currSymbolTable = null;
    }
示例#20
0
    // parses one function definition
    void matchFunction()
    {
        match(Token.KwdFunc);
        currFunction = new CompiledFunction(sc.TokenText);

        // Add next token to list
        string fn = sc.TokenText;

        int args = 0;
        Function func = new Function(fn, 0);

        if (!functionNames.Contains(fn))
            functionNames.Add(fn);
        else
            throw new ParseError("Duplicate function name " + func.name);

        match(Token.Ident);  // the function name
        currSymbolTable = new SymbolTable();
        match(Token.LPar);
        if (nextToken != Token.RPar) {
            for( ; ; ) {
                string argname = sc.TokenText;
                args++;
                match(Token.Ident);
                if (!currSymbolTable.AddEntry(argname, currFunction.AddArgument(argname)))
                    SemanticError("duplicate declaration of argument {0}", argname);
                if (nextToken != Token.Comma)
                    break;
                advance();
            }
        }

        func.args = args;
        functions.Add(func);

        match(Token.RPar);
        matchBlock();
        // the function should end with a return statement.  In case ...
        currFunction.AddInstruction(OpCode.Stop);
        program.Add(currFunction);
        currFunction = null;
        currSymbolTable = null;
    }
示例#21
0
        Executable CompileExecutable()
        {
            var exe        = new Executable(options.MachineInfo);
            var exeContext = new ExecutableContext(exe, options.Report);

            // Put something at the zero address so we don't get 0 addresses of globals
            exe.AddGlobal("__zero__", CBasicType.SignedInt);

            //
            // Find Variables, Functions, Types
            //
            var exeInitBody = new Block(VariableScope.Local);
            var tucs        = tus.Select(x => new TranslationUnitContext(x, exeContext));
            var tuInits     = new List <(CompiledFunction, EmitContext)> ();

            foreach (var tuc in tucs)
            {
                var tu = tuc.TranslationUnit;
                AddStatementDeclarations(tuc);
                if (tu.InitStatements.Count > 0)
                {
                    var tuInitBody = new Block(VariableScope.Local);
                    tuInitBody.AddStatements(tu.InitStatements);
                    var tuInit = new CompiledFunction($"__{tu.Name}__cinit", "", CFunctionType.VoidProcedure, tuInitBody);
                    exeInitBody.AddStatement(new ExpressionStatement(new FuncallExpression(new VariableExpression(tuInit.Name, Location.Null, Location.Null))));
                    tuInits.Add((tuInit, tuc));
                    exe.Functions.Add(tuInit);
                }
            }

            //
            // Generate a function to init globals
            //
            var exeInit = new CompiledFunction($"__cinit", "", CFunctionType.VoidProcedure, exeInitBody);

            exe.Functions.Add(exeInit);

            //
            // Link everything together
            // This is done before compilation to make sure everything is visible (for recursion)
            //
            var functionsToCompile = new List <(CompiledFunction, EmitContext)> {
                (exeInit, exeContext)
            };

            functionsToCompile.AddRange(tuInits);
            foreach (var tuc in tucs)
            {
                var tu = tuc.TranslationUnit;
                foreach (var g in tu.Variables)
                {
                    var v = exe.AddGlobal(g.Name, g.VariableType);
                    v.InitialValue = g.InitialValue;
                }
                var funcs = tu.Functions.Where(x => x.Body != null).ToList();
                exe.Functions.AddRange(funcs);
                functionsToCompile.AddRange(funcs.Select(x => (x, (EmitContext)tuc)));
            }

            //
            // Compile functions
            //
            foreach (var(f, pc) in functionsToCompile)
            {
                var body = f.Body;
                if (body == null)
                {
                    continue;
                }
                var fc = new FunctionContext(exe, f, pc);
                AddStatementDeclarations(fc);
                body.Emit(fc);
                f.LocalVariables.AddRange(fc.LocalVariables);

                // Make sure it returns
                if (body.Statements.Count == 0 || !body.AlwaysReturns)
                {
                    if (f.FunctionType.ReturnType.IsVoid)
                    {
                        fc.Emit(OpCode.Return);
                    }
                    else
                    {
                        options.Report.Error(161, "'" + f.Name + "' not all code paths return a value");
                    }
                }
            }

            return(exe);
        }

        void AddStatementDeclarations(BlockContext context)
        {
            var block = context.Block;

            foreach (var s in block.Statements)
            {
                s.AddDeclarationToBlock(context);
            }
        }

        FunctionDeclarator?GetFunctionDeclarator(Declarator?d)
        {
            if (d == null)
            {
                return(null);
            }
            else if (d is FunctionDeclarator)
            {
                return((FunctionDeclarator)d);
            }
            else
            {
                return(GetFunctionDeclarator(d.InnerDeclarator));
            }
        }
    }
示例#22
0
        public static Func <double, double, double> GetFunctionHandle(string formula)
        {
            CompiledFunction fn = FunctionCompiler.Compile(2, formula);

            return((x, y) => fn(x, y));
        }