예제 #1
0
        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));
        }
예제 #2
0
        /// <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);
            }
        }
예제 #3
0
        /// <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);
            }
        }
예제 #4
0
        /// <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));
        }
예제 #5
0
파일: LLVM.cs 프로젝트: RainsSoft/SharpLang
 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;
 }
예제 #6
0
파일: LLVM.cs 프로젝트: RainsSoft/SharpLang
 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;
 }
예제 #7
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);
        }