public static Module Translate(Context context, params MethodInfo[] methods) { var module = new Module("Module", context); if (Environment.Is64BitOperatingSystem) { PInvoke.LLVMSetTarget(module, "nvptx64-nvidia-cuda"); PInvoke.LLVMSetDataLayout(module, "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"); } else { PInvoke.LLVMSetTarget(module, "nvptx-nvidia-cuda"); PInvoke.LLVMSetDataLayout(module, "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"); } foreach (var method in methods) Translate(context, module, method); return module; }
public Module(string name) : base(LLVM.ModuleCreateWithName(name)) { _ctx = null; }
public static StructType Get(Context ctx, string name, Type[] types, bool packed = false) { StructType ty = StructType.Get(ctx, name); ty.SetBody(types, packed); return ty; }
public static StructType Get(Context ctx, string name) { StructType ty = new StructType(LLVM.StructCreateNamed(ctx, name)); return ty; }
private static void FindBranchTargets(IList<OpCodeInstruction> opCodes, Context context, Function function) { for (var i = 0; i < opCodes.Count; i++) { var op = opCodes[i]; var opcode = op.Opcode; switch (opcode.FlowControl) { case FlowControl.Branch: case FlowControl.Cond_Branch: break; default: continue; } var target = Convert.ToInt32(op.Parameter); target += (int)opCodes[i + 1].InstructionStart; var insert = 0; while (opCodes[insert].InstructionStart != target) insert++; var contBlock = opcode.FlowControl == FlowControl.Cond_Branch ? new Block("", context, function) : null; Block block; if (opCodes[insert].Opcode == OpCodes.Nop && opCodes[insert].Parameter != null) block = (Block)opCodes[insert].Parameter; else { opCodes.Insert(insert, new OpCodeInstruction(target, OpCodes.Nop, block = new Block("", context, function))); if (insert < i) i++; } opCodes[i] = new OpCodeInstruction(op.InstructionStart, op.Opcode, contBlock == null ? (object)block : Tuple.Create(contBlock, block)); } }
public static void Translate(Context context, Module module, MethodInfo method) { var function = EmitFunction(context, module, method); var metadataArgs = new[] { function, PInvoke.LLVMMDStringInContext(context, method.Name), IntegerType.GetInt32(context).Constant(1, true) }; var metadata = PInvoke.LLVMMDNodeInContext(context, metadataArgs); PInvoke.LLVMAddNamedMetadataOperand(module, "nvvm.annotations", metadata); }
public EmitFuncObj(Context context, Module module, Function function, InstructionBuilder instructionBuilder, object argument, Stack<Value> stack, Value[] locals, Value[] parameters) { Context = context; Module = module; Function = function; Builder = instructionBuilder; Argument = argument; Stack = stack; Locals = locals; Parameters = parameters; }
private static Type ConvertType(Context context, System.Type type) { if (type == typeof(void)) return Type.GetVoid(context); if (type == typeof(bool)) return IntegerType.Get(context, 1); if (type == typeof(byte)) return IntegerType.Get(context, 8); if (type == typeof(short)) return IntegerType.Get(context, 16); if (type == typeof(int)) return IntegerType.GetInt32(context); if (type == typeof(long)) return IntegerType.Get(context, 64); if (type == typeof(float)) return FloatType.Get(context, 32); if (type == typeof(double)) return FloatType.Get(context, 64); if (type.IsArray) return PointerType.Get(ConvertType(context, type.GetElementType()), 1); throw new Exception("Type cannot be translated to CUDA: " + type.FullName); }
private static Type[] AnalyzeArguments(Context context, IEnumerable<ParameterInfo> parameters) { return parameters.Select(p => ConvertType(context, p.ParameterType)).ToArray(); }
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; }