/// <inheritdoc/>
        public void Dispose( )
        {
            if (EngineHandle != default)
            {
                LLVMDisposeExecutionEngine(EngineHandle);
            }

            OwnedModules.Clear( );
            EngineHandle = default;
        }
        /// <summary>Add a module to the engine</summary>
        /// <param name="module">The module to add to the engine</param>
        /// <remarks>
        /// <note type="warning">
        /// The input <paramref name="module"/> is disconnected from the underlying LLVM
        /// module as the module is considered fully owned by the engine. Thus, upon return
        /// the <see cref="BitcodeModule.IsDisposed"/> property is <see langword="true"/>
        /// </note>
        /// </remarks>
        /// <returns>Handle for the module in the engine</returns>
        public int AddModule(BitcodeModule module)
        {
            int handle = System.Threading.Interlocked.Increment(ref NextHandleValue) - 1;

            lock ( OwnedModules )
            {
                OwnedModules.Add(handle, module.ModuleHandle);
            }

            if (handle == 0)
            {
                CreateEngine(module);
            }

            LLVMAddModule(EngineHandle, module.ModuleHandle);
            module.Detach( );
            return(handle);
        }
        /// <summary>Removes a module from the engine</summary>
        /// <param name="handle"><see cref="AddModule(BitcodeModule)"/> to remove</param>
        /// <remarks>
        /// This effectively transfers ownership of the module back to the caller.
        /// </remarks>
        public void RemoveModule(int handle)
        {
            if (!OwnedModules.TryGetValue(handle, out LLVMModuleRef module))
            {
                throw new ArgumentException("Unknown handle value");
            }

            // Current LLVM-C API is a bit brain dead on this one. The return is hardcoded to 0
            // and the out error message is never used. Furthermore, the return from the C++
            // ExecutionEngine::removeModule() is ultimately ignored.
            if (LLVMRemoveModule(EngineHandle, module, out LLVMModuleRef baseModule, out string errMsg).Failed)
            {
                throw new InternalCodeGeneratorException("Failed to remove module from engine");
            }

            // MCJIT engine doesn't cleanup after a remove
            LLVMExecutionEngineClearGlobalMappingsFromModule(EngineHandle, baseModule);
            LLVMDisposeModule(module);
        }