コード例 #1
0
        /// <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);
        }
コード例 #2
0
ファイル: PassManager.cs プロジェクト: bamfbamf/LLVMSharp
 public void AddLoopRotatePass() => LLVM.AddLoopRotatePass(this.Unwrap());
コード例 #3
0
        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);
        }