public ProjectedClass(string mdns, string mdname, string clrns, string clrname, ClrAssembly clrAsm, ClrAssembly contractAsm, bool winMDValueType, bool clrValueType) { this.WinMDClass = new ClassName(mdns, mdname, winMDValueType); this.ClrClass = new ClassName(clrns, clrname, clrValueType); this.ClrAssembly = clrAsm; this.ContractAssembly = contractAsm; }
public AssemblyArtifact(IDistributionSegment Segment, NodeFilePath ArtifactPath) : base(Segment, ArtifactPath) { Descriptor = from a in ClrAssembly.Get(ArtifactPath) from d in a.Describe() select d; }
public static InputContext Create(string assemblyFile) { var assembly = ClrAssembly.LoadFile(assemblyFile); var document = XmlDocument.LoadFile(Path.ChangeExtension(assemblyFile, ".xml")); return(new InputContext(assembly, document)); }
private static Task OptimizeAssemblyAsync( ClrAssembly assembly, bool printIr, bool parallelOptimization) { var typeSystem = assembly.Resolver.TypeEnvironment; var pipeline = new Optimization[] { // * Expand LINQ queries. new ExpandLinq(typeSystem.Boolean, typeSystem.Int32), // * Inline direct method calls and devirtualize calls. Inlining.Instance, CopyPropagation.Instance, CallDevirtualization.Instance, DeadValueElimination.Instance, // * Box to alloca, aggregates to scalars, scalars to registers. // Also throw in GVN. BoxToAlloca.Instance, CopyPropagation.Instance, PartialScalarReplacement.Instance, GlobalValueNumbering.Instance, CopyPropagation.Instance, DeadValueElimination.Instance, AllocaToRegister.Instance, // * Optimize control flow. InstructionSimplification.Instance, new ConstantPropagation(), MemoryAccessElimination.Instance, DeadValueElimination.Instance, new JumpThreading(true), SwitchSimplification.Instance, DuplicateReturns.Instance, TailRecursionElimination.Instance, BlockFusion.Instance }; // Create an on-demand optimizer, which will optimize methods // lazily. Optimizer optimizer; if (parallelOptimization) { optimizer = new ParallelOnDemandOptimizer( pipeline, method => GetInitialMethodBody(method, typeSystem)); } else { optimizer = new OnDemandOptimizer( pipeline, method => GetInitialMethodBody(method, typeSystem)); } return(optimizer.RunAllAsync( GetAllMethods(assembly).Select( method => UpdateMethodBodyAsync(method, optimizer, typeSystem, printIr)))); }
public Compiler(ClrAssembly assembly, Dependencies dependencies, ILog Log, OptionSet options) { this.Assembly = assembly; this.Log = Log; this.Dependencies = dependencies; this.CompilerOptions = options; }
private static DataTable GetClusterCharacteristics(string strModel, string strClusterUniqueID, double dThreshold) { //if we don't know the path to the system data mining sprocs assembly, get it if (_cachedSystemDataMiningSprocsPath.Length == 0) { Microsoft.AnalysisServices.Server svr = new Microsoft.AnalysisServices.Server(); svr.Connect(Context.CurrentServerID); ClrAssembly ass = (ClrAssembly)svr.Assemblies.GetByName("System"); if (ass == null) { throw new Exception("System (data mining sprocs) assembly not found"); } foreach (ClrAssemblyFile file in ass.Files) { if (file.Type == ClrAssemblyFileType.Main) { lock (_cachedSystemDataMiningSprocsPath) _cachedSystemDataMiningSprocsPath = file.Name; break; } } svr.Disconnect(); } //get the DataMining sprocs assembly and call the GetClusterCharacteristics function System.Reflection.Assembly asAss = System.Reflection.Assembly.LoadFile(_cachedSystemDataMiningSprocsPath); Type t = asAss.GetType("Microsoft.AnalysisServices.System.DataMining.Clustering"); object oClustering = t.GetConstructor(new Type[] { }).Invoke(new object[] { }); return((DataTable)t.InvokeMember("GetClusterCharacteristics", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod, null, oClustering, new object[] { strModel, strClusterUniqueID, dThreshold })); }
private static Task <AssemblyContentDescription> CreateContentDescriptionAsync( IMethod method, IEnumerable <ITypeMember> memberRoots, IEnumerable <IType> typeRoots, ClrAssembly assembly) { // TODO: deduplicate this logic (it also appears in IL2LLVM and ILOpt) var typeSystem = assembly.Resolver.TypeEnvironment; var pipeline = new Optimization[] { new ConstantPropagation(), MemoryAccessElimination.Instance, DeadValueElimination.Instance, new JumpThreading(true), SwitchSimplification.Instance, DuplicateReturns.Instance, TailRecursionElimination.Instance, BlockFusion.Instance }; var optimizer = new OnDemandOptimizer( pipeline, m => GetInitialMethodBody(m, typeSystem)); return(AssemblyContentDescription.CreateTransitiveAsync( new SimpleName("kernel").Qualify(), assembly.Attributes, null, new ITypeMember[] { method }.Concat(memberRoots), typeRoots, optimizer)); }
private static IEnumerable <ClrMethodDefinition> GetAllMethods( Mono.Cecil.TypeDefinition typeDefinition, ClrAssembly parentAssembly) { return(typeDefinition.Methods .Select(parentAssembly.Resolve) .Cast <ClrMethodDefinition>() .Concat( typeDefinition.NestedTypes.SelectMany( type => GetAllMethods(type, parentAssembly)))); }
private static void OptimizeAssembly( Mono.Cecil.AssemblyDefinition cecilAsm, ClrAssembly flameAsm, Func <ClrMethodDefinition, MethodBody> optimizeBody) { foreach (var module in cecilAsm.Modules) { foreach (var type in module.Types) { OptimizeType(type, flameAsm, optimizeBody); } } }
private static ClrAssembly ResolveCorlib() { var env = new MutableTypeEnvironment(null); var asm = new ClrAssembly( Mono.Cecil.ModuleDefinition .ReadModule(typeof(object).Module.FullyQualifiedName) .Assembly, NullAssemblyResolver.Instance, env); env.InnerEnvironment = new CorlibTypeEnvironment(asm); return(asm); }
static AssemblyRef CreateAssembly(ModuleDef module, ClrAssembly clrAsm) { var mscorlib = module == null ? null : module.CorLibTypes.AssemblyRef; var asm = new AssemblyRefUser(GetName(clrAsm), contractAsmVersion, new PublicKeyToken(GetPublicKeyToken(clrAsm)), UTF8String.Empty); if (mscorlib != null && mscorlib.Name == mscorlibName && mscorlib.Version != invalidWinMDVersion) { asm.Version = mscorlib.Version; } var mod = module as ModuleDefMD; if (mod != null) { Version ver = null; foreach (var asmRef in mod.GetAssemblyRefs()) { if (asmRef.IsContentTypeWindowsRuntime) { continue; } if (asmRef.Name != asm.Name) { continue; } if (asmRef.Culture != asm.Culture) { continue; } if (!PublicKeyBase.TokenEquals(asmRef.PublicKeyOrToken, asm.PublicKeyOrToken)) { continue; } if (asmRef.Version == invalidWinMDVersion) { continue; } if (ver == null || asmRef.Version > ver) { ver = asmRef.Version; } } if (ver != null) { asm.Version = ver; } } return(asm); }
private static void OptimizeType( Mono.Cecil.TypeDefinition typeDefinition, ClrAssembly parentAssembly, Func <ClrMethodDefinition, MethodBody> optimizeBody) { foreach (var method in typeDefinition.Methods) { OptimizeMethod(method, parentAssembly, optimizeBody); } foreach (var type in typeDefinition.NestedTypes) { OptimizeType(type, parentAssembly, optimizeBody); } }
private CudaModule( ClrAssembly sourceAssembly, ModuleBuilder intermediateModule, LLVMTargetMachineRef targetMachine, CUmodule compiledModule, string entryPointName, CudaContext context) { this.SourceAssembly = sourceAssembly; this.IntermediateModule = intermediateModule; this.TargetMachine = targetMachine; this.TargetData = LLVM.CreateTargetDataLayout(TargetMachine); this.CompiledModule = compiledModule; this.EntryPointName = entryPointName; this.Context = context; }
private static Task <CudaModule> CompileAsync( MethodReference method, IEnumerable <MethodReference> methodRoots, IEnumerable <TypeReference> typeRoots, int threadIdParamIndex, CudaContext context) { var module = method.Module; var flameModule = ClrAssembly.Wrap(module.Assembly); return(CompileAsync( flameModule.Resolve(method), methodRoots.Select(flameModule.Resolve).ToArray(), typeRoots.Select(flameModule.Resolve).ToArray(), threadIdParamIndex, flameModule, context)); }
private static void OptimizeMethod( Mono.Cecil.MethodDefinition methodDefinition, ClrAssembly parentAssembly, Func <ClrMethodDefinition, MethodBody> optimizeBody) { if (methodDefinition.HasBody) { var flameMethod = (ClrMethodDefinition)parentAssembly.Resolve(methodDefinition); var irBody = flameMethod.Body; var errors = irBody.Validate(); if (errors.Count > 0) { var sourceIr = FormatIr(irBody); log.Log( new LogEntry( Severity.Warning, "invalid IR", Quotation.QuoteEvenInBold( "the Flame IR produced by the CIL analyzer for ", flameMethod.FullName.ToString(), " is erroneous; skipping it."), CreateRemark( "errors in IR:", new BulletedList(errors.Select(x => new Text(x)).ToArray())), CreateRemark( "generated Flame IR:", new Paragraph(new WrapBox(sourceIr, 0, -sourceIr.Length))))); return; } var optBody = optimizeBody(flameMethod); var emitter = new ClrMethodBodyEmitter( methodDefinition, optBody, parentAssembly.Resolver.TypeEnvironment); var newCilBody = emitter.Compile(); methodDefinition.Body = newCilBody; } }
static UTF8String GetName(ClrAssembly clrAsm) { switch (clrAsm) { case ClrAssembly.Mscorlib: return(clrAsmName_Mscorlib); case ClrAssembly.SystemNumericsVectors: return(clrAsmName_SystemNumericsVectors); case ClrAssembly.SystemObjectModel: return(clrAsmName_SystemObjectModel); case ClrAssembly.SystemRuntime: return(clrAsmName_SystemRuntime); case ClrAssembly.SystemRuntimeInteropServicesWindowsRuntime: return(clrAsmName_SystemRuntimeInteropServicesWindowsRuntime); case ClrAssembly.SystemRuntimeWindowsRuntime: return(clrAsmName_SystemRuntimeWindowsRuntime); case ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml: return(clrAsmName_SystemRuntimeWindowsRuntimeUIXaml); default: throw new InvalidOperationException(); } }
static byte[] GetPublicKeyToken(ClrAssembly clrAsm) { switch (clrAsm) { case ClrAssembly.Mscorlib: return(neutralPublicKey); case ClrAssembly.SystemNumericsVectors: return(contractPublicKeyToken); case ClrAssembly.SystemObjectModel: return(contractPublicKeyToken); case ClrAssembly.SystemRuntime: return(contractPublicKeyToken); case ClrAssembly.SystemRuntimeInteropServicesWindowsRuntime: return(contractPublicKeyToken); case ClrAssembly.SystemRuntimeWindowsRuntime: return(neutralPublicKey); case ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml: return(neutralPublicKey); default: throw new InvalidOperationException(); } }
/// <summary> /// Called by the loader via <see cref="ClrAssembly"/>. /// </summary> internal ClrModule(ClrAssembly/*!*/ assembly) : base(assembly) { }
public static int Main(string[] args) { // Acquire a log. var rawLog = TerminalLog.Acquire(); var log = new TransformLog( rawLog, new Func <LogEntry, LogEntry>[] { MakeDiagnostic }); // Parse command-line options. var parser = new GnuOptionSetParser( Options.All, Options.Input); var recLog = new RecordingLog(log); var parsedOptions = parser.Parse(args, recLog); if (recLog.Contains(Severity.Error)) { // Stop the program if the command-line arguments // are half baked. return(1); } if (parsedOptions.GetValue <bool>(Options.Help)) { // Wrap the help message into a log entry and send it to the log. rawLog.Log( new LogEntry( Severity.Info, new HelpMessage( "fbfc is a compiler that turns Brainfuck code into CIL assemblies.", "fbfc path [options...]", Options.All))); return(0); } var inputPath = parsedOptions.GetValue <string>(Options.Input); if (string.IsNullOrEmpty(inputPath)) { log.Log( new LogEntry( Severity.Error, "nothing to compile", "no input file")); return(1); } var outputPath = parsedOptions.GetValue <string>(Options.Output); if (string.IsNullOrEmpty(outputPath)) { outputPath = Path.GetFileNameWithoutExtension(inputPath) + ".exe"; } // Read the Brainfuck source code from disk. SourceDocument source; try { source = new StringDocument(inputPath, File.ReadAllText(inputPath)); } catch (Exception) { log.Log( new LogEntry( Severity.Error, "invalid source path", Quotation.QuoteEvenInBold( "cannot read Brainfuck source code at ", inputPath, "."))); return(1); } var asmName = Path.GetFileNameWithoutExtension(outputPath); var cecilAsm = Mono.Cecil.AssemblyDefinition.CreateAssembly( new Mono.Cecil.AssemblyNameDefinition(asmName, new Version(1, 0, 0, 0)), asmName, Mono.Cecil.ModuleKind.Console); var flameAsm = ClrAssembly.Wrap(cecilAsm); var typeEnv = flameAsm.Resolver.TypeEnvironment; var compiler = new Compiler( flameAsm, Dependencies.Resolve( typeEnv, new ReadOnlyTypeResolver(typeEnv.Object.Parent.Assembly), log), log, parsedOptions); compiler.Compile(source); cecilAsm.Write(outputPath); return(0); }
public InputContext(ClrAssembly assembly, XmlDocument document) { Assembly = assembly ?? throw new ArgumentNullException(nameof(assembly)); Document = document ?? throw new ArgumentNullException(nameof(document)); }
private DataTable getFunctionList(AssemblyCollection assColl) { Context.TraceEvent(100, 0, "ListFunctions: Starting"); // build the structure for the datatable which is returned DataTable dtFuncs = new DataTable("dtFunctions"); dtFuncs.Columns.Add("Assembly", typeof(String)); dtFuncs.Columns.Add("Class", typeof(String)); dtFuncs.Columns.Add("Method", typeof(String)); dtFuncs.Columns.Add("ReturnType", typeof(String)); dtFuncs.Columns.Add("Parameters", typeof(String)); if (Context.ExecuteForPrepare) { // we can exit after building the table function if this is only // being executed for a prepare. Context.TraceEvent(100, 0, "ListFunctions: Finished (ExecuteForPrepare)"); return(dtFuncs); } foreach (Microsoft.AnalysisServices.Assembly ass in assColl) { Context.CheckCancelled(); if (ass is ClrAssembly) // we can only use reflection against .Net assemblies { Type t = ass.GetType(); ClrAssembly clrAss = (ClrAssembly)ass; Context.TraceEvent(100, 0, "ListFunctions: Processing the " + clrAss.Name + " Assembly"); foreach (ClrAssemblyFile f in clrAss.Files) // an assembly can have multiple files { Context.CheckCancelled(); // We only want to get the "main" asembly file and only files which have data // (Some of the system assemblies appear to be registrations only and do not // have any data. if (f.Data.Count > 0 && f.Type == ClrAssemblyFileType.Main) { // assembly the assembly back into a single byte from the blocks of base64 strings byte[] rawAss = new byte[0]; int iPos = 0; byte[] buff = new byte[0]; foreach (string block in f.Data) { Context.CheckCancelled(); buff = System.Convert.FromBase64String(block); System.Array.Resize(ref rawAss, rawAss.Length + buff.Length); buff.CopyTo(rawAss, iPos); iPos += buff.Length; } // use reflection to extract the public types and methods from the // re-assembled assembly. Context.TraceEvent(100, 0, "ListFunctions: Starting reflection against " + f.Name); System.Reflection.Assembly asAss = System.Reflection.Assembly.Load(rawAss); Type[] assTypes = asAss.GetTypes(); for (int i = 0; i < assTypes.Length; i++) { Type t2 = assTypes[i]; if (t2.IsPublic) { MethodInfo[] methods; methods = t2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); int paramCnt = 0; foreach (MethodInfo meth in methods) { Context.CheckCancelled(); // build the parameter signature as a string ParameterInfo[] Params = meth.GetParameters(); System.Text.StringBuilder paramList = new System.Text.StringBuilder(); paramCnt = Params.Length; string[] paramArray = new string[paramCnt]; // add the first parameter if (paramCnt > 0) { paramList.Append(Params[0].Name); paramList.Append(" as "); paramList.Append(StripNamespace(Params[0].ParameterType.ToString())); } // add subsequent parameters, inserting a comma before each new one. for (int j = 1; j < paramCnt; j++) { paramList.Append(", "); paramList.Append(Params[j].Name); paramList.Append(" as "); paramList.Append(StripNamespace(Params[j].ParameterType.ToString())); } DataRow rowFunc = dtFuncs.NewRow(); Object[] items = new Object[5]; items[0] = ass.Name; items[1] = t2.Name; items[2] = meth.Name; items[3] = StripNamespace(meth.ReturnType.ToString()); items[4] = paramList.ToString(); rowFunc.ItemArray = items; dtFuncs.Rows.Add(rowFunc); rowFunc.AcceptChanges(); } // foreach meth } // if t2.IsPublic } // assTypes.Length Context.TraceEvent(100, 0, "ListFunctions: Finished reflecting against " + f.Name); } // if f.data.count > 0 && f.Type == main } // foreach f } // if ass is clrAssembly } // foreach ass dtFuncs.AcceptChanges(); Context.TraceEvent(100, dtFuncs.Rows.Count, "ListFunctions: Finished (" + dtFuncs.Rows.Count.ToString() + " function signatures)"); return(dtFuncs); }
/// <summary> /// Returns the defining system as determined by convention alignment /// </summary> /// <param name="a">The assembly to evaluate</param> /// <returns></returns> public static SystemIdentifier DefiningSystem(this ClrAssembly a) => a.ReflectedElement.DefiningSystem();
public static int Main(string[] args) { // Acquire a log. var rawLog = TerminalLog.Acquire(); log = new TransformLog( rawLog, new Func <LogEntry, LogEntry>[] { MakeDiagnostic }); // Parse command-line options. var parser = new GnuOptionSetParser( Options.All, Options.Input); var recLog = new RecordingLog(log); var parsedOptions = parser.Parse(args, recLog); if (recLog.Contains(Severity.Error)) { // Stop the program if the command-line arguments // are half baked. return(1); } if (parsedOptions.GetValue <bool>(Options.Help)) { // Wrap the help message into a log entry and send it to the log. TerminalLog.AcquireStandardOutput().Log( new LogEntry( Severity.Info, new HelpMessage( "il2llvm is a command-line tool that compiles CIL assemblies to LLVM modules.", "il2llvm path [options...]", Options.All))); return(0); } var inputPath = parsedOptions.GetValue <string>(Options.Input); if (string.IsNullOrEmpty(inputPath)) { log.Log( new LogEntry( Severity.Error, "nothing to compile", "no input file")); return(1); } var outputPath = parsedOptions.GetValue <string>(Options.Output); if (string.IsNullOrEmpty(outputPath)) { outputPath = Path.GetFileNameWithoutExtension(inputPath) + ".ll"; } var printIr = parsedOptions.GetValue <bool>(Options.PrintIr); // Read the assembly from disk. Mono.Cecil.AssemblyDefinition cecilAsm; try { cecilAsm = Mono.Cecil.AssemblyDefinition.ReadAssembly( inputPath, new Mono.Cecil.ReaderParameters { ReadWrite = false }); } catch (Exception) { log.Log( new LogEntry( Severity.Error, "unreadable assembly", Quotation.QuoteEvenInBold( "cannot read assembly at ", inputPath, "."))); return(1); } if (cecilAsm.EntryPoint == null) { log.Log( new LogEntry( Severity.Error, "unsuitable assembly", "input assembly does not define an entry point.")); return(1); } try { // Wrap the CIL assembly in a Flame assembly. var flameAsm = ClrAssembly.Wrap(cecilAsm); // Compile the assembly to an LLVM module. var module = CompileAsync(flameAsm).Result; // Write the LLVM module to disk. string error; if (LLVM.PrintModuleToFile(module, outputPath, out error)) { log.Log(new LogEntry(Severity.Error, "cannot write module", error)); } LLVM.DisposeModule(module); } finally { // Be sure to dispose the assembly after we've used it. cecilAsm.Dispose(); } return(0); }
private static Task <AssemblyContentDescription> CreateContentDescriptionAsync(ClrAssembly assembly) { var typeSystem = assembly.Resolver.TypeEnvironment; var pipeline = new Optimization[] { new ConstantPropagation(), MemoryAccessElimination.Instance, DeadValueElimination.Instance, new JumpThreading(true), SwitchSimplification.Instance, DuplicateReturns.Instance, TailRecursionElimination.Instance, BlockFusion.Instance }; var optimizer = new OnDemandOptimizer( pipeline, method => GetInitialMethodBody(method, typeSystem)); return(AssemblyContentDescription.CreateTransitiveAsync( assembly.FullName, assembly.Attributes, assembly.Resolve(assembly.Definition.EntryPoint), optimizer)); }
private static async Task <LLVMModuleRef> CompileAsync(ClrAssembly assembly) { var desc = await CreateContentDescriptionAsync(assembly); return(LlvmBackend.Compile(desc, assembly.Resolver.TypeEnvironment).Module); }
public static int Main(string[] args) { // Acquire a log. var rawLog = TerminalLog.Acquire(); log = new TransformLog( rawLog, new Func <LogEntry, LogEntry>[] { MakeDiagnostic }); // Parse command-line options. var parser = new GnuOptionSetParser( Options.All, Options.Input); var recLog = new RecordingLog(log); var parsedOptions = parser.Parse(args, recLog); if (recLog.Contains(Severity.Error)) { // Stop the program if the command-line arguments // are half baked. return(1); } if (parsedOptions.GetValue <bool>(Options.Help)) { // Wrap the help message into a log entry and send it to the log. TerminalLog.AcquireStandardOutput().Log( new LogEntry( Severity.Info, new HelpMessage( "ilopt is a command-line tool that optimizes CIL assemblies.", "ilopt path [options...]", Options.All))); return(0); } var inputPath = parsedOptions.GetValue <string>(Options.Input); if (string.IsNullOrEmpty(inputPath)) { log.Log( new LogEntry( Severity.Error, "nothing to optimize", "no input file")); return(1); } var outputPath = parsedOptions.GetValue <string>(Options.Output); if (string.IsNullOrEmpty(outputPath)) { outputPath = Path.GetFileNameWithoutExtension(inputPath) + ".opt" + Path.GetExtension(inputPath); } var printIr = parsedOptions.GetValue <bool>(Options.PrintIr); // Read the assembly from disk. Mono.Cecil.AssemblyDefinition cecilAsm; try { cecilAsm = Mono.Cecil.AssemblyDefinition.ReadAssembly( inputPath, new Mono.Cecil.ReaderParameters { ReadWrite = false }); } catch (Exception) { log.Log( new LogEntry( Severity.Error, "unreadable assembly", Quotation.QuoteEvenInBold( "cannot read assembly at ", inputPath, "."))); return(1); } try { // Make all non-public types, methods and fields in the assembly // internal if the user requests it. This will work to // our advantage. if (parsedOptions.GetValue <bool>(Options.Internalize)) { MakeInternal(cecilAsm); } // Wrap the CIL assembly in a Flame assembly. var flameAsm = ClrAssembly.Wrap(cecilAsm); // Optimize the assembly. OptimizeAssemblyAsync( flameAsm, printIr, parsedOptions.GetValue <bool>(Options.Parallel)).Wait(); // Write the optimized assembly to disk. cecilAsm.Write(outputPath); } finally { // Be sure to dispose the assembly after we've used it. cecilAsm.Dispose(); } return(0); }
private static IEnumerable <ClrMethodDefinition> GetAllMethods(ClrAssembly assembly) { return(assembly.Definition.Modules .SelectMany(module => module.Types) .SelectMany(type => GetAllMethods(type, assembly))); }
private static async Task <CudaModule> CompileAsync( IMethod method, IEnumerable <ITypeMember> memberRoots, IEnumerable <IType> typeRoots, int threadIdParamIndex, ClrAssembly assembly, CudaContext context) { // Figure out which members we need to compile. var desc = await CreateContentDescriptionAsync(method, memberRoots, typeRoots, assembly); // Compile those members to LLVM IR. Use an Itanium name mangling scheme. var mangler = new ItaniumMangler(assembly.Resolver.TypeEnvironment); var moduleBuilder = LlvmBackend.Compile(desc, assembly.Resolver.TypeEnvironment); var module = moduleBuilder.Module; // Generate type metadata for all type roots. foreach (var type in typeRoots) { moduleBuilder.Metadata.GetMetadata(type, moduleBuilder); } // Get the compiled kernel function. var kernelFuncName = mangler.Mangle(method, true); var kernelFunc = LLVM.GetNamedFunction(module, kernelFuncName); if (threadIdParamIndex >= 0) { // If we have a thread ID parameter, then we need to generate a thunk // kernel function that calls our actual kernel function. This thunk's // responsibility is to determine the thread ID of the kernel. var thunkKernelName = "kernel"; var thunkTargetType = kernelFunc.TypeOf().GetElementType(); var thunkParamTypes = new List <LLVMTypeRef>(thunkTargetType.GetParamTypes()); if (threadIdParamIndex < thunkParamTypes.Count) { thunkParamTypes.RemoveAt(threadIdParamIndex); } var thunkKernel = LLVM.AddFunction( module, thunkKernelName, LLVM.FunctionType( thunkTargetType.GetReturnType(), thunkParamTypes.ToArray(), thunkTargetType.IsFunctionVarArg)); using (var builder = new IRBuilder(moduleBuilder.Context)) { builder.PositionBuilderAtEnd(thunkKernel.AppendBasicBlock("entry")); var args = new List <LLVMValueRef>(thunkKernel.GetParams()); args.Insert(threadIdParamIndex, ComputeUniqueThreadId(builder, module)); var call = builder.CreateCall(kernelFunc, args.ToArray(), ""); if (call.TypeOf().TypeKind == LLVMTypeKind.LLVMVoidTypeKind) { builder.CreateRetVoid(); } else { builder.CreateRet(call); } } kernelFuncName = thunkKernelName; kernelFunc = thunkKernel; } // Mark the compiled kernel as a kernel symbol. LLVM.AddNamedMetadataOperand( module, "nvvm.annotations", LLVM.MDNode(new LLVMValueRef[] { kernelFunc, MDString("kernel"), LLVM.ConstInt(LLVM.Int32TypeInContext(LLVM.GetModuleContext(module)), 1, false) })); // LLVM.DumpModule(module); // Compile that LLVM IR down to PTX. LLVMTargetMachineRef machine; var ptx = CompileToPtx(module, context.GetDeviceComputeCapability(), out machine); // Console.WriteLine(System.Text.Encoding.UTF8.GetString(ptx)); // Load the PTX kernel. return(new CudaModule(assembly, moduleBuilder, machine, context.LoadModulePTX(ptx), kernelFuncName, context)); }