/// <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); }
public void AddLoopUnrollPass() => LLVM.AddLoopUnrollPass(this.Unwrap());
public void Compile() { string triple = "x86_64-pc-linux-gnu"; LLVM.InitializeX86TargetInfo(); LLVM.InitializeX86Target(); LLVM.InitializeX86TargetMC(); LLVM.InitializeX86AsmParser(); LLVM.InitializeX86AsmPrinter(); LLVM.SetTarget(ModuleRef, triple); var fnPassManager = LLVM.CreateFunctionPassManagerForModule(ModuleRef); var modulePassManager = LLVM.CreatePassManager(); LLVM.InitializeFunctionPassManager(fnPassManager); // Optimizations LLVM.AddPromoteMemoryToRegisterPass(fnPassManager); LLVM.AddInstructionCombiningPass(fnPassManager); LLVM.AddJumpThreadingPass(fnPassManager); LLVM.AddEarlyCSEPass(fnPassManager); LLVM.AddConstantPropagationPass(fnPassManager); LLVM.AddCFGSimplificationPass(fnPassManager); LLVM.AddReassociatePass(fnPassManager); LLVM.AddLoopUnrollPass(fnPassManager); LLVM.AddLoopRerollPass(fnPassManager); LLVM.AddLoopDeletionPass(fnPassManager); LLVM.AddLoopRotatePass(fnPassManager); LLVM.AddLoopIdiomPass(fnPassManager); LLVM.AddLoopUnswitchPass(fnPassManager); LLVM.AddDeadStoreEliminationPass(fnPassManager); LLVM.AddBasicAliasAnalysisPass(fnPassManager); LLVM.AddIndVarSimplifyPass(fnPassManager); LLVM.AddSCCPPass(fnPassManager); LLVM.AddLICMPass(fnPassManager); LLVM.AddCorrelatedValuePropagationPass(fnPassManager); LLVM.AddScopedNoAliasAAPass(modulePassManager); LLVM.AddDeadArgEliminationPass(modulePassManager); LLVM.AddTailCallEliminationPass(modulePassManager); LLVM.AddLoopUnswitchPass(modulePassManager); LLVM.AddIPSCCPPass(modulePassManager); LLVM.AddReassociatePass(modulePassManager); LLVM.AddAlwaysInlinerPass(modulePassManager); // O2 LLVM.AddNewGVNPass(fnPassManager); LLVM.AddLowerExpectIntrinsicPass(fnPassManager); LLVM.AddScalarReplAggregatesPassSSA(fnPassManager); LLVM.AddMergedLoadStoreMotionPass(fnPassManager); LLVM.AddSLPVectorizePass(fnPassManager); LLVM.AddConstantMergePass(modulePassManager); LLVM.AddConstantMergePass(modulePassManager); LLVM.AddFunctionInliningPass(modulePassManager); void RecurseTypes(Collection <TypeDefinition> collection, Action <TypeDefinition> callback) { foreach (TypeDefinition typeDef in collection) { callback(typeDef); RecurseTypes(typeDef.NestedTypes, callback); } } // First, declare all types and only define the types in a later pass. // The reason is that we may have cycles of types. var typeList = new List <TypeDefinition>(); foreach (ModuleDefinition moduleDef in assemblyDefinition.Modules) { RecurseTypes(moduleDef.Types, typeDef => { typeList.Add(typeDef); TypeLookup.DeclareType(typeDef); }); } // Now, we have all types, so we can declare the methods. // Again, we may have cycles so the methods are declared and defined in separate passes. // Also define the types now. var methodCompilerLookup = new Dictionary <MethodDefinition, MethodCompiler>(); foreach (var typeDef in typeList) { TypeLookup.DefineType(typeDef); StaticFieldLookup.DeclareFieldsFor(typeDef); foreach (MethodDefinition methodDef in typeDef.Methods) { methodCompilerLookup.Add(methodDef, new MethodCompiler(this, methodDef)); } } // Compile the methods. Action <TypeDefinition> methodCompilationFn = typeDef => { foreach (MethodDefinition methodDef in typeDef.Methods) { var methodCompiler = methodCompilerLookup[methodDef]; methodCompiler.Compile(); if (!LLVM.VerifyFunction(methodCompiler.FunctionValueRef, LLVMVerifierFailureAction.LLVMPrintMessageAction)) { LLVM.RunFunctionPassManager(fnPassManager, methodCompiler.FunctionValueRef); } } }; if (LLVM.StartMultithreaded()) { Parallel.ForEach(typeList, methodCompilationFn); } else { typeList.ForEach(methodCompilationFn); } // Free memory already. MethodLookup.Finish(); methodCompilerLookup.Clear(); Console.WriteLine("-------------------"); if (LLVM.VerifyModule(ModuleRef, LLVMVerifierFailureAction.LLVMPrintMessageAction, out var outMsg)) { Console.WriteLine(outMsg); } LLVM.RunPassManager(modulePassManager, ModuleRef); // Cleanup LLVM.DisposePassManager(modulePassManager); LLVM.DumpModule(ModuleRef); // XXX string errorMsg; LLVMTargetRef targetRef; if (LLVM.GetTargetFromTriple(triple, out targetRef, out errorMsg)) { Console.WriteLine(errorMsg); } LLVMTargetMachineRef machineRef = LLVM.CreateTargetMachine(targetRef, triple, "generic", "", LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault, LLVMRelocMode.LLVMRelocDefault, LLVMCodeModel.LLVMCodeModelDefault); System.IO.File.Delete("test.s"); if (LLVM.TargetMachineEmitToFile(machineRef, ModuleRef, Marshal.StringToHGlobalAnsi("test.s"), LLVMCodeGenFileType.LLVMAssemblyFile, out errorMsg)) { Console.WriteLine(errorMsg); } Console.WriteLine("written"); LLVM.DisposeTargetMachine(machineRef); }