private JitCompiler(CpuConfig config, Type t_kernel, TypeBuilder t_xformed) { _config = config; _t_kernel = t_kernel; _m_kernel = _t_kernel.GetMethod("RunKernel", BF.All); ValidateInputParameters(); // todo. think how to support multiple methods: *Dims, *Idxes, synchronization points // todo. I'd even say that we should embed constants instead of Dims and cache such bodies between calls // todo. if some dimension is equal to 1, then strip off corresponding loop var lam = _m_kernel.Decompile(); _hir = lam.Body; _params = lam.Sig.Syms; _locals = lam.Body.LocalsRecursive(); _xhir = new Block(); _tids.Add("x", new Local("tid_x", typeof(int))); _tids.Add("y", new Local("tid_y", typeof(int))); _tids.Add("z", new Local("tid_z", typeof(int))); _xhir.Locals.AddElements(_tids.Values); InferLocalAllocationHints(); ReplicatePrivatelyAllocatedLocals(); LiftLocallyAllocatedLocals(); HoistGloballyAllocatedLocals(); _callsToSyncThreads = _hir.Family().OfType<Eval>().Where(eval => { var m1 = eval.InvokedMethod(); var syncapi_syncThreads = typeof(ISyncApi).GetMethod("SyncThreads"); return m1.Api() == syncapi_syncThreads; }).ToReadOnly(); TransformBlock(_hir, _xhir, false); // todo. currently we don't support debuggable IL // the latter implies correct PDB-mappings and working watch for replicated vars _config.EmitDebuggableIL.AssertFalse(); _t_xformed = t_xformed; _t_xformed.AddInterfaceImplementation(typeof(IBlockRunner)); _m_xformed = _t_xformed.DefineMethod("RunBlock", MA.Public, typeof(void), typeof(int3).MkArray()); _m_xformed.DefineParameter(1, ParmA.None, "blockIdx"); CompileTransformedHir(); }
Expression Decompile(MethodInfo method, Expression instance, IList<Expression> arguments) { var expression = method.Decompile(); var expressions = new Dictionary<Expression, Expression>(); var argIndex = 0; for (var index = 0; index < expression.Parameters.Count; index++) { var parameter = expression.Parameters[index]; if (index == 0 && method.IsStatic == false) { expressions.Add(parameter, instance); } else { expressions.Add(parameter, arguments[argIndex++]); } } return Visit(new ReplaceExpressionVisitor(expressions).Visit(expression.Body)); }
private static Function EmitFunction(Context context, Module module, MethodInfo method) { var funcType = new FunctionType(ConvertType(context, method.ReturnType), AnalyzeArguments(context, method.GetParameters())); var intrinsic = method.GetCustomAttribute<Gpu.BuiltinAttribute>(); if (intrinsic != null) { var name = intrinsic.Intrinsic; var preExisting = module.GetFunction(name); if (preExisting != null) return preExisting; return module.CreateFunction(name, funcType); } var function = module.CreateFunction(method.Name, funcType); var block = new Block("entry", context, function); var writer = new InstructionBuilder(context, block); var opcodes = method.Decompile().ToList(); FindBranchTargets(opcodes, context, function); var body = method.GetMethodBody(); var efo = new EmitFuncObj(context, module, function, writer, null, new Stack<Value>(), body == null ? null : new Value[body.LocalVariables.Count], new Value[method.GetParameters().Length]); foreach (var opcode in opcodes) { if (EmitFunctions.ContainsKey(opcode.Opcode) == false) throw new Exception("Unsupported CIL instruction " + opcode.Opcode); var func = EmitFunctions[opcode.Opcode]; efo.Argument = opcode.Parameter; func(efo); } return function; }