Esempio n. 1
0
 public void AddConstantPropagationPass() => LLVM.AddConstantPropagationPass(this.Unwrap());
Esempio n. 2
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);
        }
Esempio n. 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);
        }
Esempio n. 4
0
        public void TestFact()
        {
            ModuleRef Module = LLVM.ModuleCreateWithName("fac_module");

            TypeRef[] fac_args = { LLVM.Int32Type() };
            ValueRef  fac      = LLVM.AddFunction(Module, "fac", LLVM.FunctionType(LLVM.Int32Type(), fac_args, false));

            LLVM.SetFunctionCallConv(fac, (uint)Swigged.LLVM.CallConv.CCallConv);
            ValueRef n = LLVM.GetParam(fac, 0);

            BasicBlockRef entry   = LLVM.AppendBasicBlock(fac, "entry");
            BasicBlockRef iftrue  = LLVM.AppendBasicBlock(fac, "iftrue");
            BasicBlockRef iffalse = LLVM.AppendBasicBlock(fac, "iffalse");
            BasicBlockRef end     = LLVM.AppendBasicBlock(fac, "end");
            BuilderRef    builder = LLVM.CreateBuilder();

            LLVM.PositionBuilderAtEnd(builder, entry);
            ValueRef If = LLVM.BuildICmp(builder, Swigged.LLVM.IntPredicate.IntEQ, n, LLVM.ConstInt(LLVM.Int32Type(), 0, false), "n == 0");

            LLVM.BuildCondBr(builder, If, iftrue, iffalse);

            LLVM.PositionBuilderAtEnd(builder, iftrue);
            ValueRef res_iftrue = LLVM.ConstInt(LLVM.Int32Type(), 1, false);

            LLVM.BuildBr(builder, end);

            LLVM.PositionBuilderAtEnd(builder, iffalse);
            ValueRef n_minus = LLVM.BuildSub(builder, n, LLVM.ConstInt(LLVM.Int32Type(), 1, false), "n - 1");

            ValueRef[] call_fac_args = { n_minus };
            ValueRef   call_fac      = LLVM.BuildCall(builder, fac, call_fac_args, "fac(n - 1)");
            ValueRef   res_iffalse   = LLVM.BuildMul(builder, n, call_fac, "n * fac(n - 1)");

            LLVM.BuildBr(builder, end);

            LLVM.PositionBuilderAtEnd(builder, end);
            ValueRef res = LLVM.BuildPhi(builder, LLVM.Int32Type(), "result");

            ValueRef[]      phi_vals   = { res_iftrue, res_iffalse };
            BasicBlockRef[] phi_blocks = { iftrue, iffalse };
            LLVM.AddIncoming(res, phi_vals, phi_blocks);
            LLVM.BuildRet(builder, res);

            MyString error = new MyString();

            LLVM.VerifyModule(Module, VerifierFailureAction.PrintMessageAction, error);
            if (error.ToString() != "")
            {
                throw new Exception("Failed");
            }

            ExecutionEngineRef engine;
            ModuleProviderRef  provider = LLVM.CreateModuleProviderForExistingModule(Module);

            LLVM.CreateJITCompilerForModule(out engine, Module, 0, error);

            PassManagerRef pass = LLVM.CreatePassManager();

            // LLVM.AddTargetData(LLVM.GetExecutionEngineTargetData(engine), pass);
            LLVM.AddConstantPropagationPass(pass);
            LLVM.AddInstructionCombiningPass(pass);
            LLVM.AddPromoteMemoryToRegisterPass(pass);
            // LLVMAddDemoteMemoryToRegisterPass(pass); // Demotes every possible value to memory
            LLVM.AddGVNPass(pass);
            LLVM.AddCFGSimplificationPass(pass);
            LLVM.RunPassManager(pass, Module);
            LLVM.DumpModule(Module);

            ulong input = 10;

            for (ulong i = 0; i < input; ++i)
            {
                GenericValueRef exec_args                 = LLVM.CreateGenericValueOfInt(LLVM.Int32Type(), input, false);
                GenericValueRef exec_res                  = LLVM.RunFunction(engine, fac, 1, out exec_args);
                var             result_of_function        = LLVM.GenericValueToInt(exec_res, false);
                var             result_of_csharp_function = Factorial(input);
                if (result_of_csharp_function != result_of_function)
                {
                    throw new Exception("Results not the same.");
                }
            }

            LLVM.DisposePassManager(pass);
            LLVM.DisposeBuilder(builder);
            LLVM.DisposeExecutionEngine(engine);
        }
Esempio n. 5
0
        public bool Compile(CompilerOptions pOptions, out LLVMModuleRef?pModule)
        {
            double totalTime = 0;
            var    sw        = new System.Diagnostics.Stopwatch();

            sw.Start();

            //Read source files
            pModule = null;
            string source = string.IsNullOrEmpty(pOptions.SourceFile) ? pOptions.Source : ReadSourceFile(pOptions.SourceFile);

            if (source == null)
            {
                return(false);
            }

            var lexer  = new SmallerLexer();
            var stream = lexer.StartTokenStream(source, pOptions.SourceFile);
            var parser = new SmallerParser(stream);

            //Create AST
            var tree = parser.Parse();

            if (CompilerErrors.ErrorOccurred)
            {
                return(false);
            }

            totalTime += RecordPerfData(sw, "Parsed in: ");

            //Type inference, type checking, AST transformations
            var compilationModule = ModuleBuilder.Build(tree);

            if (compilationModule == null)
            {
                return(false);
            }

            totalTime += RecordPerfData(sw, "Type checked in: ");

            LLVMModuleRef      module      = LLVM.ModuleCreateWithName(tree.Name);
            LLVMPassManagerRef passManager = LLVM.CreateFunctionPassManagerForModule(module);

            if (pOptions.Optimizations)
            {
                LLVM.AddConstantPropagationPass(passManager);

                //Promote allocas to registers
                LLVM.AddPromoteMemoryToRegisterPass(passManager);

                //Do simple peephole optimizations
                LLVM.AddInstructionCombiningPass(passManager);

                //Re-associate expressions
                LLVM.AddReassociatePass(passManager);

                //Eliminate common subexpressions
                LLVM.AddGVNPass(passManager);

                //Simplify control flow graph
                LLVM.AddCFGSimplificationPass(passManager);
            }
            LLVM.InitializeFunctionPassManager(passManager);

            //Emitting LLVM bytecode
            using (var c = new EmittingContext(module, passManager, pOptions.Debug))
            {
                compilationModule.Emit(c);

                if (LLVM.VerifyModule(module, LLVMVerifierFailureAction.LLVMPrintMessageAction, out string message).Value != 0)
                {
                    LLVM.DumpModule(module);
                    LLVM.DisposePassManager(passManager);
                    pModule = null;
                    return(false);
                }
            }

            pModule = module;
            LLVM.DisposePassManager(passManager);

            totalTime += RecordPerfData(sw, "Emitted bytecode in: ");

            Console.WriteLine("Total time: " + totalTime + "s");

            return(true);
        }