public MethodLookup(LLVMModuleRef moduleRef, TypeLookup typeLookup) { this.moduleRef = moduleRef; this.typeLookup = typeLookup; createSystemObjectCtor(); createCctorCaller(); }
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); }
public StaticFieldLookup(LLVMModuleRef moduleRef, TypeLookup typeLookup) { this.moduleRef = moduleRef; this.typeLookup = typeLookup; }
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); }