Ejemplo n.º 1
0
 public void TestLazyIRCompilation( )
 {
     using (Library.InitializeLLVM( ))
     {
         Library.RegisterNative( );
         using (LLVMContextRef context = LLVMContextCreate( ))
         {
             string nativeTriple = LLVMGetDefaultTargetTriple();
             Assert.IsFalse(string.IsNullOrWhiteSpace(nativeTriple));
             Assert.IsTrue(LLVMGetTargetFromTriple(nativeTriple, out LLVMTargetRef targetHandle, out string errorMessag).Succeeded);
             LLVMTargetMachineRef machine = LLVMCreateTargetMachine(
                 targetHandle,
                 nativeTriple,
                 string.Empty,
                 string.Empty,
                 LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault,
                 LLVMRelocMode.LLVMRelocDefault,
                 LLVMCodeModel.LLVMCodeModelJITDefault);
             using ( machine )
             {
                 LLVMOrcJITStackRef orcJit = LLVMOrcCreateInstance(machine);
                 using ( orcJit )
                 {
                     // try several different modules with the same function name replacing the previous
                     AddAndExecuteTestModule(orcJit, context, machine, 42);
                     AddAndExecuteTestModule(orcJit, context, machine, 12345678);
                     AddAndExecuteTestModule(orcJit, context, machine, 87654321);
                 }
             }
         }
     }
 }
Ejemplo n.º 2
0
        public static void EmitToFile(this LLVMTargetMachineRef self, Module module, string filename)
        {
            if (module is null)
            {
                throw new ArgumentNullException(nameof(module));
            }

            try
            {
                var filenameMarshaled = Marshal.StringToCoTaskMemAnsi(filename);
                if (LLVM.TargetMachineEmitToFile(
                        self, module.GetModuleRef(), filenameMarshaled, LLVMCodeGenFileType.LLVMObjectFile, out string error))
                {
                    throw new Exception(error);
                }
            }
            catch (System.AccessViolationException e)
            {
                Console.WriteLine("===================================");
                module.Dump();
                Console.WriteLine("===================================");
                throw new Exception($"Failed to emit module '{module}' to file '{filename}': {e.Message}");
            }
            catch (Exception e)
            {
                throw new Exception($"Failed to emit module '{module}' to file '{filename}': {e.Message}");
            }
        }
Ejemplo n.º 3
0
 /// <summary cref="DisposeBase.Dispose(bool)"/>
 protected override void Dispose(bool disposing)
 {
     if (LLVMTargetMachine.Pointer != IntPtr.Zero)
     {
         DisposeTargetMachine(LLVMTargetMachine);
         LLVMTargetMachine = default(LLVMTargetMachineRef);
     }
 }
Ejemplo n.º 4
0
        private void makeObjectFile()
        {
            LLVM.InitializeX86TargetMC();
            LLVM.InitializeX86Target();
            LLVM.InitializeX86TargetInfo();
            LLVM.InitializeX86AsmParser();
            LLVM.InitializeX86AsmPrinter();

            LLVMTargetRef target = LLVM.GetFirstTarget();

            if (target.Pointer == IntPtr.Zero)
            {
                return;
            }

            string triple = getTargetTriple();

            LLVMTargetMachineRef targetMachine = LLVM.CreateTargetMachine(target, triple, "generic", "",
                                                                          LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault, LLVMRelocMode.LLVMRelocDefault,
                                                                          LLVMCodeModel.LLVMCodeModelDefault);

#if EMIT_TO_FILE
            string message;
            unsafe
            {
                fixed(char *fileName = options.OutPath)
                {
                    LLVM.TargetMachineEmitToFile(targetMachine, module, new IntPtr(fileName),
                                                 LLVMCodeGenFileType.LLVMObjectFile, out message);
                    LLVM.DisposeTargetMachine(targetMachine);
                }
            }
            if (!String.IsNullOrEmpty(message))
            {
                log.globalError("Failed to emit object file. LLVM Error: {0}", message);
            }
#else
            LLVM.TargetMachineEmitToMemoryBuffer(targetMachine, module, LLVMCodeGenFileType.LLVMObjectFile,
                                                 out var _, out var memoryBuffer);

            size_t bufferSize  = LLVM.GetBufferSize(memoryBuffer);
            IntPtr bufferStart = LLVM.GetBufferStart(memoryBuffer);

            unsafe {
                Stream   s    = new UnmanagedMemoryStream((byte *)bufferStart.ToPointer(), bufferSize);
                FileInfo file = new FileInfo(options.OutPath);
                if (file.Exists)
                {
                    file.Delete();
                }

                using (FileStream fs = file.Open(FileMode.Create, FileAccess.Write))
                    using (DisposableBuffer unused = new DisposableBuffer(memoryBuffer)) {
                        s.CopyTo(fs);
                    }
            }
#endif
        }
Ejemplo n.º 5
0
        private LLVMTargetDataRef TargetDataFromTriple(string triple)
        {
            LLVMTargetRef        target        = LLVMTargetRef.GetTargetFromTriple(triple);
            LLVMTargetMachineRef targetMachine = target.CreateTargetMachine(triple, "", "",
                                                                            LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault, LLVMRelocMode.LLVMRelocDefault,
                                                                            LLVMCodeModel.LLVMCodeModelDefault);

            return(targetMachine.CreateTargetDataLayout());
        }
Ejemplo n.º 6
0
    // Create a new module with the given name.
    // The passed target triple can be used for cross compilation.
    // If it is null, the current platform will be used.
    public Module(string name, string targetTriple, bool useOptimizations)
    {
        // Create the module and the builder.
        this.Mod     = LLVM.ModuleCreateWithName(name);
        this.Builder = LLVM.CreateBuilder();

        // Get the default target triple if necessary:
        if (targetTriple == null)
        {
            targetTriple = Marshal.PtrToStringAnsi(LLVM.GetDefaultTargetTriple());
        }

        // Select the target based on the triple.
        if (LLVM.GetTargetFromTriple(targetTriple, out var target, out var error))
        {
            throw new ArgumentException($"Failed to obtain target from triple '{ targetTriple }': { error }");
        }

        LLVM.SetTarget(this.Mod, targetTriple);

        // Create a target machine.
        this._targetMachine = LLVM.CreateTargetMachine(target, targetTriple, "generic", "",
                                                       LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault, LLVMRelocMode.LLVMRelocPIC, LLVMCodeModel.LLVMCodeModelDefault);

        // Create a data layout from the machine and assign it to the module.
        var dataLayout = LLVM.CreateTargetDataLayout(this._targetMachine);

        LLVM.SetModuleDataLayout(this.Mod, dataLayout);

        // Create the function pass manager for optimized runs.
        if (useOptimizations)
        {
            var funcPassManager = LLVM.CreateFunctionPassManagerForModule(this.Mod);

            // Add some nice optimization passes.
            LLVM.AddBasicAliasAnalysisPass(funcPassManager);
            LLVM.AddPromoteMemoryToRegisterPass(funcPassManager);
            LLVM.AddInstructionCombiningPass(funcPassManager);
            LLVM.AddReassociatePass(funcPassManager);
            LLVM.AddGVNPass(funcPassManager);
            LLVM.AddCFGSimplificationPass(funcPassManager);

            // TODO: Add more!

            // Initialize the manager and its passes and store it.
            LLVM.InitializeFunctionPassManager(funcPassManager);
            this._funcPassManager = funcPassManager;
        }
        else
        {
            this._funcPassManager = null;
        }
    }
Ejemplo n.º 7
0
        /// <summary>Creates a <see cref="TargetMachine"/> for the target and specified parameters</summary>
        /// <param name="triple">Target triple for this machine (e.g. -mtriple)</param>
        /// <param name="cpu">CPU for this machine (e.g. -mcpu)</param>
        /// <param name="features">Features for this machine (e.g. -mattr...)</param>
        /// <param name="optLevel">Optimization level</param>
        /// <param name="relocationMode">Relocation mode for generated code</param>
        /// <param name="codeModel"><see cref="CodeModel"/> to use for generated code</param>
        /// <returns><see cref="TargetMachine"/> based on the specified parameters</returns>
        public TargetMachine CreateTargetMachine(string triple
                                                 , string cpu                    = null
                                                 , string features               = null
                                                 , CodeGenOpt optLevel           = CodeGenOpt.Default
                                                 , RelocationMode relocationMode = RelocationMode.Default
                                                 , CodeModel codeModel           = CodeModel.Default
                                                 )
        {
            LLVMTargetMachineRef targetMachineHandle = InternalCreateTargetMachine(this, triple, cpu, features, optLevel, relocationMode, codeModel);

            return(new TargetMachine(targetMachineHandle));
        }
Ejemplo n.º 8
0
        public void CompileModule(string file)
        {
            string        error;
            LLVMTargetRef tref;

            LLVM.GetTargetFromTriple(TargetPlatform, out tref, out error);

            LLVMTargetMachineRef machineRef = LLVM.CreateTargetMachine(tref, TargetPlatform, "generic", "",
                                                                       LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault, LLVMRelocMode.LLVMRelocDefault,
                                                                       LLVMCodeModel.LLVMCodeModelDefault);

            LLVM.TargetMachineEmitToFile(machineRef, Module, Marshal.StringToHGlobalAnsi(file),
                                         LLVMCodeGenFileType.LLVMObjectFile, out error);

            LLVM.DisposeTargetMachine(machineRef);
        }
Ejemplo n.º 9
0
 private CudaModule(
     ClrAssembly sourceAssembly,
     ModuleBuilder intermediateModule,
     LLVMTargetMachineRef targetMachine,
     CUmodule compiledModule,
     string entryPointName,
     CudaContext context)
 {
     this.SourceAssembly     = sourceAssembly;
     this.IntermediateModule = intermediateModule;
     this.TargetMachine      = targetMachine;
     this.TargetData         = LLVM.CreateTargetDataLayout(TargetMachine);
     this.CompiledModule     = compiledModule;
     this.EntryPointName     = entryPointName;
     this.Context            = context;
 }
Ejemplo n.º 10
0
        private static byte[] CompileToPtx(
            LLVMModuleRef module,
            Version computeCapability,
            out LLVMTargetMachineRef machine)
        {
            string        triple = "nvptx64-nvidia-cuda";
            LLVMTargetRef target;
            string        error;

            if (LLVM.GetTargetFromTriple(
                    triple,
                    out target,
                    out error))
            {
                throw new Exception(error);
            }
            machine = LLVM.CreateTargetMachine(
                target,
                triple,
                $"sm_{computeCapability.Major}{computeCapability.Minor}",
                "",
                LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault,
                LLVMRelocMode.LLVMRelocDefault,
                LLVMCodeModel.LLVMCodeModelDefault);

            LLVMMemoryBufferRef asmBuf;

            if (LLVM.TargetMachineEmitToMemoryBuffer(machine, module, LLVMCodeGenFileType.LLVMAssemblyFile, out error, out asmBuf))
            {
                throw new Exception(error);
            }

            var asmLength = (int)LLVM.GetBufferSize(asmBuf);
            var asmBytes  = new byte[asmLength];

            Marshal.Copy(LLVM.GetBufferStart(asmBuf), asmBytes, 0, asmLength);

            LLVM.DisposeMemoryBuffer(asmBuf);

            return(asmBytes);
        }
Ejemplo n.º 11
0
        private static LLVMModuleRef CreateModule(LLVMContextRef context, LLVMTargetMachineRef machine, int magicNumber)
        {
            var module = LLVMModuleCreateWithNameInContext("test", context);
            var layout = LLVMCreateTargetDataLayout(machine);

            LLVMSetModuleDataLayout(module, layout);

            LLVMTypeRef       int32T     = LLVMInt32TypeInContext(context);
            LLVMTypeRef       signature  = LLVMFunctionType(int32T, null, 0, false);
            LLVMValueRef      main       = LLVMAddFunction(module, "main", signature);
            LLVMBasicBlockRef entryBlock = LLVMAppendBasicBlock(main, "entry");

            LLVMBuilderRef builder = LLVMCreateBuilder( );

            LLVMPositionBuilderAtEnd(builder, entryBlock);

            LLVMValueRef constNum = LLVMConstInt(int32T, ( ulong )magicNumber, true);

            LLVMBuildRet(builder, constNum);
            Debug.WriteLine(LLVMPrintModuleToString(module));
            return(module);
        }
Ejemplo n.º 12
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);
        }
Ejemplo n.º 13
0
        private static void AddAndExecuteTestModule(LLVMOrcJITStackRef orcJit, LLVMContextRef context, LLVMTargetMachineRef machine, int expectedResult)
        {
            LLVMModuleRef module = CreateModule(context, machine, expectedResult);
            LLVMErrorRef  err    = LLVMOrcAddEagerlyCompiledIR(orcJit, out ulong jitHandle, module, SymbolResolver, IntPtr.Zero);

            Assert.IsTrue(err.IsInvalid);

            // ORC now owns the module, so it must never be released
            module.SetHandleAsInvalid();
            LLVMOrcGetMangledSymbol(orcJit, out string mangledName, "main");
            err = LibLLVMOrcGetSymbolAddress(orcJit, out ulong funcAddress, mangledName, false);
            Assert.IsTrue(err.IsInvalid);
            Assert.AreNotEqual(0ul, funcAddress);
            var callableMain = Marshal.GetDelegateForFunctionPointer <TestMain>(( IntPtr )funcAddress);

            Assert.AreEqual(expectedResult, callableMain( ));

            LLVMOrcRemoveModule(orcJit, jitHandle);
        }
Ejemplo n.º 14
0
 public static void Dispose(this LLVMTargetMachineRef self)
 {
     LLVM.DisposeTargetMachine(self);
 }
Ejemplo n.º 15
0
 public static extern int GetTargetMachineData(LLVMTargetMachineRef* T);
Ejemplo n.º 16
0
 public static extern System.IntPtr GetTargetMachineCPU(LLVMTargetMachineRef* T);
Ejemplo n.º 17
0
 public static extern void DisposeTargetMachine(LLVMTargetMachineRef* T);
Ejemplo n.º 18
0
 private static extern LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef @TM);
Ejemplo n.º 19
0
 public static extern LLVMTargetRef* GetTargetMachineTarget(LLVMTargetMachineRef* T);
Ejemplo n.º 20
0
 internal TargetMachine(LLVMTargetMachineRef targetMachine) => _targetMachine = targetMachine;
Ejemplo n.º 21
0
 public static extern System.IntPtr GetTargetMachineFeatureString(LLVMTargetMachineRef* T);
Ejemplo n.º 22
0
 internal TargetMachine(Context context, LLVMTargetMachineRef targetMachineHandle)
 {
     TargetMachineHandle = targetMachineHandle;
     Context             = context;
 }
Ejemplo n.º 23
0
 public static extern int TargetMachineEmitToFile(LLVMTargetMachineRef* T, LLVMModuleRef* M, [In][MarshalAs(UnmanagedType.LPStr)] string Filename, LLVMCodeGenFileType codegen, [MarshalAs(UnmanagedType.LPStr)] ref StringBuilder ErrorMessage);
Ejemplo n.º 24
0
        internal TargetMachine(LLVMTargetMachineRef targetMachineHandle)
        {
            targetMachineHandle.ValidateNotDefault(nameof(targetMachineHandle));

            TargetMachineHandle = targetMachineHandle;
        }