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); }
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); } }
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); }
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); }
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; } }
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)); }); }); }
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); } }
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)); }
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)); }
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; } }
// 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; }
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); } }
// 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; }
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))); } }
public BlockContext(Block block, MachineInfo machineInfo, Report report, CompiledFunction fdecl, EmitContext parentContext) : base(machineInfo, report, fdecl, parentContext) { Block = block; }
// 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; }
// 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; }
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)); } } }
public static Func <double, double, double> GetFunctionHandle(string formula) { CompiledFunction fn = FunctionCompiler.Compile(2, formula); return((x, y) => fn(x, y)); }