Пример #1
0
 public MethodLookup(LLVMModuleRef moduleRef, TypeLookup typeLookup)
 {
     this.moduleRef  = moduleRef;
     this.typeLookup = typeLookup;
     createSystemObjectCtor();
     createCctorCaller();
 }
Пример #2
0
        public void Compile()
        {
            if (offsetToBasicBlock.Count > 0)
            {
                throw new InvalidOperationException("This method is already compiled.");
            }

            LLVMBuilderRef builder = LLVM.CreateBuilder();

            // Add the entry point as the first basic block.
            {
                var it = MethodDef.Body.Instructions.GetEnumerator();
                it.MoveNext();
                AddBasicBlockAt(it.Current);
            }

            // Generate the entry point code for arguments.
            LLVM.PositionBuilderAtEnd(builder, offsetToBasicBlock[0].LLVMBlock);
            uint paramCount = LLVM.CountParams(FunctionValueRef);

            ArgumentValues = new EmulatedStateValue[paramCount];
            int offset = MethodDef.HasThis ? 1 : 0;

            for (uint i = 0; i < paramCount; ++i)
            {
                LLVMValueRef param    = LLVM.GetParam(FunctionValueRef, i);
                var          valueRef = LLVM.BuildAlloca(builder, LLVM.TypeOf(param), "arg" + i);

                TypeInfo typeInfo;
                if (MethodDef.HasThis && i == 0)
                {
                    typeInfo = TypeInfo.Reference;
                }
                else
                {
                    typeInfo = MethodDef.Parameters[(int)i - offset].ParameterType.GetTypeInfo();
                }

                ArgumentValues[i] = new EmulatedStateValue(valueRef, typeInfo);
                LLVM.BuildStore(builder, param, valueRef);
            }

            // Generate the entry point code for locals.
            {
                var locals = MethodDef.Body.Variables;
                LocalValues = new EmulatedStateValue[locals.Count];
                for (int i = 0; i < locals.Count; ++i)
                {
                    var cilType  = locals[i].VariableType;
                    var valueRef = LLVM.BuildAlloca(builder, TypeLookup.GetLLVMTypeRef(cilType), "local" + i);
                    LocalValues[i] = new EmulatedStateValue(valueRef, cilType.GetTypeInfo());
                }
            }

            // Now, find the basic blocks.
            {
                int currentBlockIndex = 0;
                foreach (Instruction insn in MethodDef.Body.Instructions)
                {
                    if (HasBasicBlock(insn.Offset))
                    {
                        // This is a fallthrough?
                        if (currentBlockIndex != insn.Offset)
                        {
                            // Can't be fallthrough if previous instruction was an unconditional branch.
                            if (!insn.Previous.IsUnconditionalBranchInstruction())
                            {
                                AddOutgoingEdge(currentBlockIndex, insn.Offset);
                            }
                        }

                        currentBlockIndex = insn.Offset;
                    }

                    if (insn.IsBranchInstruction())
                    {
                        AddBasicBlockAt((Instruction)insn.Operand);
                        AddOutgoingEdge(currentBlockIndex, ((Instruction)insn.Operand).Offset);
                        AddBasicBlockAt(insn.Next);
                        // Can't be fallthrough if current instruction was an unconditional branch.
                        if (!insn.IsUnconditionalBranchInstruction())
                        {
                            AddOutgoingEdge(currentBlockIndex, insn.Next.Offset);
                        }
                    }
                }
            }

            compileBasicBlock(builder, 0);

            LLVM.DisposeBuilder(builder);
        }
Пример #3
0
 public StaticFieldLookup(LLVMModuleRef moduleRef, TypeLookup typeLookup)
 {
     this.moduleRef  = moduleRef;
     this.typeLookup = typeLookup;
 }
Пример #4
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);
        }