public MemoryBuffer EmitToBuffer(NativeModule module, CodeGenFileType fileType) { if (module == null) { throw new ArgumentNullException(nameof(module)); } if (module.TargetTriple != null && Triple != module.TargetTriple) { throw new ArgumentException("Triple specified for the module doesn't match target machine", nameof(module)); } var status = NativeMethods.TargetMachineEmitToMemoryBuffer(TargetMachineHandle , module.ModuleHandle , ( LLVMCodeGenFileType )fileType , out string errTxt , out LLVMMemoryBufferRef bufferHandle ); if (status.Failed) { throw new InternalCodeGeneratorException(errTxt); } return(new MemoryBuffer(bufferHandle)); }
/// <summary>Generate code for the target machine from a module</summary> /// <param name="module"><see cref="NativeModule"/> to generate the code from</param> /// <param name="path">Path to the output file</param> /// <param name="fileType">Type of file to emit</param> public void EmitToFile(NativeModule module, string path, CodeGenFileType fileType) { if (module == null) { throw new ArgumentNullException(nameof(module)); } if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentException("Null or empty paths are not valid", nameof(path)); } if (module.TargetTriple != null && Triple != module.TargetTriple) { throw new ArgumentException("Triple specified for the module doesn't match target machine", nameof(module)); } var status = NativeMethods.TargetMachineEmitToFile(TargetMachineHandle , module.ModuleHandle , path , ( LLVMCodeGenFileType )fileType , out string errTxt ); if (status.Failed) { throw new InternalCodeGeneratorException(errTxt); } }
/// <summary>Generate code for the target machine from a module</summary> /// <param name="module"><see cref="BitcodeModule"/> to generate the code from</param> /// <param name="path">Path to the output file</param> /// <param name="fileType">Type of file to emit</param> public void EmitToFile(BitcodeModule module, string path, CodeGenFileType fileType) { module.ValidateNotNull(nameof(module)); path.ValidateNotNullOrWhiteSpace(nameof(path)); fileType.ValidateDefined(nameof(path)); if (module.TargetTriple != null && Triple != module.TargetTriple) { throw new ArgumentException(Resources.Triple_specified_for_the_module_doesn_t_match_target_machine, nameof(module)); } var status = LLVMTargetMachineEmitToFile(TargetMachineHandle , module.ModuleHandle , path , ( LLVMCodeGenFileType )fileType , out string errTxt ); if (status.Failed) { throw new InternalCodeGeneratorException(errTxt); } }
/// <summary>Emits the module for the target machine to a <see cref="MemoryBuffer"/></summary> /// <param name="module">Module to emit to the buffer</param> /// <param name="fileType">Type of file to generate into the buffer</param> /// <returns><see cref="MemoryBuffer"/> containing the generated code</returns> /// <remarks> /// The <see cref="BitcodeModule.TargetTriple"/> must match the <see cref="Triple"/> for this /// target. /// </remarks> public MemoryBuffer EmitToBuffer(BitcodeModule module, CodeGenFileType fileType) { module.ValidateNotNull(nameof(module)); fileType.ValidateDefined(nameof(fileType)); if (module.TargetTriple != null && Triple != module.TargetTriple) { throw new ArgumentException(Resources.Triple_specified_for_the_module_doesn_t_match_target_machine, nameof(module)); } var status = LLVMTargetMachineEmitToMemoryBuffer(TargetMachineHandle , module.ModuleHandle , ( LLVMCodeGenFileType )fileType , out string errTxt , out LLVMMemoryBufferRef bufferHandle ); if (status.Failed) { throw new InternalCodeGeneratorException(errTxt); } return(new MemoryBuffer(bufferHandle)); }
public unsafe static bool TargetMachineEmitToMemoryBuffer(TargetMachineRef T, ModuleRef M, CodeGenFileType codegen, out string ErrorMessage, out MemoryBufferRef OutMemBuf) { bool ret = LLVMPINVOKE.TargetMachineEmitToMemoryBuffer(T.Value, M.Value, (int)codegen, out ErrorMessage, out OutMemBuf.Value); return ret; }
public unsafe static bool TargetMachineEmitToFile(TargetMachineRef T, ModuleRef M, string Filename, CodeGenFileType codegen, out string ErrorMessage) { bool ret = LLVMPINVOKE.TargetMachineEmitToFile(T.Value, M.Value, Filename, (int)codegen, out ErrorMessage); return ret; }
/// <summary> /// Compiles an IL assembly to LLVM bytecode. /// </summary> /// <param name="moduleName">The module name.</param> public void Compile(string moduleName) { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); // Create LLVM module and its context. LLVM.EnablePrettyStackTrace(); mModule = LLVM.ModuleCreateWithName(moduleName); mContext = LLVM.GetModuleContext(mModule); // Targets. LLVM.InitializeAllTargetInfos(); LLVM.InitializeAllTargets(); LLVM.InitializeAllTargetMCs(); LLVM.InitializeAllAsmParsers(); LLVM.InitializeAllAsmPrinters(); string triplet = (Options.Target == "default") ? LLVM.GetDefaultTargetTriple() : Options.Target; MyString error = new MyString(); LLVM.SetTarget(mModule, triplet); TargetRef target; if (LLVM.GetTargetFromTriple(triplet, out target, error)) { throw new InvalidOperationException(error.ToString()); } // Optimizer. mFunctionPassManager = LLVM.CreateFunctionPassManagerForModule(mModule); mPassManager = LLVM.CreatePassManager(); LLVM.InitializeFunctionPassManager(mFunctionPassManager); #if !DEBUG // O0 if (Options.Optimization >= OptimizationLevel.O0) { // Function passes. LLVM.AddPromoteMemoryToRegisterPass(mFunctionPassManager); LLVM.AddConstantPropagationPass(mFunctionPassManager); LLVM.AddReassociatePass(mFunctionPassManager); LLVM.AddInstructionCombiningPass(mFunctionPassManager); // Module passes. LLVM.AddAlwaysInlinerPass(mPassManager); LLVM.AddStripDeadPrototypesPass(mPassManager); LLVM.AddStripSymbolsPass(mPassManager); } // O1 if (Options.Optimization >= OptimizationLevel.O1) { // Function passes. LLVM.AddLowerExpectIntrinsicPass(mFunctionPassManager); LLVM.AddEarlyCSEPass(mFunctionPassManager); LLVM.AddLoopRotatePass(mFunctionPassManager); LLVM.AddLoopUnswitchPass(mFunctionPassManager); LLVM.AddLoopUnrollPass(mFunctionPassManager); LLVM.AddLoopDeletionPass(mFunctionPassManager); LLVM.AddTailCallEliminationPass(mFunctionPassManager); LLVM.AddGVNPass(mFunctionPassManager); LLVM.AddDeadStoreEliminationPass(mFunctionPassManager); LLVM.AddJumpThreadingPass(mFunctionPassManager); LLVM.AddCFGSimplificationPass(mFunctionPassManager); LLVM.AddMemCpyOptPass(mFunctionPassManager); // Module passes. LLVM.AddDeadArgEliminationPass(mPassManager); LLVM.AddAggressiveDCEPass(mFunctionPassManager); } // O2 if (Options.Optimization >= OptimizationLevel.O2) { // Function passes. LLVM.AddLoopVectorizePass(mFunctionPassManager); LLVM.AddSLPVectorizePass(mFunctionPassManager); // Module passes. LLVM.AddFunctionInliningPass(mPassManager); LLVM.AddConstantMergePass(mPassManager); LLVM.AddArgumentPromotionPass(mPassManager); } #endif // Initialize types and runtime. string dataLayout = LLVM.GetDataLayout(Module); TargetData = LLVM.CreateTargetData(dataLayout); TypeHelper.Init(TargetData, this); RuntimeHelper.ImportFunctions(Module); mBuiltinCompiler.Compile(); compileModules(); LLVM.RunPassManager(mPassManager, Module); // Log time. stopWatch.Stop(); Logger.LogDetail("Compilation time: " + stopWatch.Elapsed); // Debug: print LLVM assembly code. #if DEBUG Console.WriteLine(LLVM.PrintModuleToString(mModule)); #endif // Verify and throw exception on error. Console.ForegroundColor = ConsoleColor.DarkGray; if (LLVM.VerifyModule(mModule, VerifierFailureAction.ReturnStatusAction, error)) { Logger.LogError("Compilation of module failed."); Logger.LogInfo(error.ToString()); LLVM.DisposeTargetData(TargetData); return; } else { Logger.LogDetail("Compilation of module succeeded."); } // Output assembly or object file. if (!Options.OutputLLVMIR && !Options.OutputLLVMBitCode) { TargetMachineRef machine = LLVM.CreateTargetMachine(target, triplet, "generic", "", CodeGenOptLevel.CodeGenLevelDefault, RelocMode.RelocDefault, CodeModel.CodeModelDefault); LLVM.SetModuleDataLayout(mModule, LLVM.CreateTargetDataLayout(machine)); CodeGenFileType type = (Options.OutputAssembly) ? CodeGenFileType.AssemblyFile : CodeGenFileType.ObjectFile; if (LLVM.TargetMachineEmitToFile(machine, mModule, Options.OutputFile, type, error)) { throw new InvalidOperationException(error.ToString()); } } // Output LLVM IR code to a file. else if (Options.OutputLLVMIR) { if (LLVM.PrintModuleToFile(mModule, Options.OutputFile, error)) { Logger.LogError("Writing the LLVM code to a file failed."); Logger.LogInfo(error.ToString()); } } // Output LLVM bitcode. else if (Options.OutputLLVMBitCode) { if (LLVM.WriteBitcodeToFile(mModule, Options.OutputFile) != 0) { Logger.LogError("Writing the LLVM code to a file failed."); Logger.LogInfo(error.ToString()); } } // Cleanup. LLVM.DisposeTargetData(TargetData); }