<commit_before>// Copyright 2015 <NAME>.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// LLVM Execution Engine
// LLVM-C header ExecutionEngine.h

use std;
use std::ffi::CString;

use libc::{c_char, c_uint, size_t};

use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::execution_engine::*;
use llvm_sys::target_machine::*;

use ::{LLVMRef, LLVMRefCtor};
use core;
use execution_engine::GenericValue;
use execution_engine::MCJITMemoryManager;

pub struct FrozenModule {
    module: core::Module
}

impl FrozenModule {
    pub fn get(&self) -> &core::Module {
        &self.module
    }
}

pub struct ExecutionEngine {
    ee: LLVMExecutionEngineRef,
    _memory_manager: Option<Box<MCJITMemoryManager>>
}

impl ExecutionEngine {
    pub fn new(mut module: core::Module) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateExecutionEngineForModule(&mut ee, module.to_ref(), &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn new_interpreter(mut module: core::Module) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateInterpreterForModule(&mut ee, module.to_ref(), &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn new_jit_compiler(mut module: core::Module, opt_level: u32) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateJITCompilerForModule(&mut ee, module.to_ref(), opt_level, &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn add_module(&mut self, mut module: core::Module) -> FrozenModule {
        unsafe {
            LLVMAddModule(self.to_ref(), module.to_ref());
            module.unown();
        }
        FrozenModule {module: module}
    }

    pub fn remove_module(&mut self, module: FrozenModule) -> Result<core::Module, String> {
        let mut module_ref = 0 as LLVMModuleRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            if LLVMRemoveModule(self.to_ref(), module.get().to_ref(), &mut module_ref, &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            }
            else {
                Ok(core::Module::from_ref(module_ref))
            }
        }
    }

    pub fn run_static_constructors(&mut self) {
        unsafe {
            LLVMRunStaticConstructors(self.to_ref())
        }
    }

    pub fn run_static_destructors(&mut self) {
        unsafe {
            LLVMRunStaticDestructors(self.to_ref())
        }
    }

    pub fn run_function<T:core::Function>(&mut self, f: &T, args: &mut [LLVMGenericValueRef]) -> GenericValue {
        unsafe {
            GenericValue::from_ref(LLVMRunFunction(self.to_ref(), f.to_ref(), args.len() as c_uint, args.as_mut_ptr()))
        }
    }

    pub fn get_function_address(&self, name: &str) -> u64 {
        let name = CString::new(name).unwrap();
        unsafe {
            LLVMGetFunctionAddress(self.to_ref(), name.as_ptr() as *const c_char)
        }
    }
}

impl LLVMRef<LLVMExecutionEngineRef> for ExecutionEngine {
    fn to_ref(&self) -> LLVMExecutionEngineRef {
        self.ee
    }
}

impl Drop for ExecutionEngine {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeExecutionEngine(self.to_ref())
        }
    }
}

pub struct MCJITBuilder {
    options: LLVMMCJITCompilerOptions,
    memory_manager: Option<Box<MCJITMemoryManager>>
}

impl MCJITBuilder {
    pub fn new() -> MCJITBuilder {
        let options = LLVMMCJITCompilerOptions {
            OptLevel: 0,
            CodeModel: LLVMCodeModel::LLVMCodeModelJITDefault,
            NoFramePointerElim: 0,
            EnableFastISel: 0,
            MCJMM: 0 as LLVMMCJITMemoryManagerRef
        };
        MCJITBuilder {options: options, memory_manager: None}
    }

    pub fn set_opt_level(mut self, opt_level: u32) -> Self {
        self.options.OptLevel = opt_level;
        self
    }

    pub fn set_code_model(mut self, code_model: LLVMCodeModel) -> Self {
        self.options.CodeModel = code_model;
        self
    }

    pub fn no_frame_pointer_elim(mut self) -> Self {
        self.options.NoFramePointerElim = 1;
        self<commit_msg>[execution_engine] use proper options initializing function in MCJITBuilder<commit_after>// Copyright 2015 <NAME>.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// LLVM Execution Engine
// LLVM-C header ExecutionEngine.h

use std;
use std::ffi::CString;

use libc::{c_char, c_uint, size_t};

use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::execution_engine::*;
use llvm_sys::target_machine::*;

use ::{LLVMRef, LLVMRefCtor};
use core;
use execution_engine::GenericValue;
use execution_engine::MCJITMemoryManager;

pub struct FrozenModule {
    module: core::Module
}

impl FrozenModule {
    pub fn get(&self) -> &core::Module {
        &self.module
    }
}

pub struct ExecutionEngine {
    ee: LLVMExecutionEngineRef,
    _memory_manager: Option<Box<MCJITMemoryManager>>
}

impl ExecutionEngine {
    pub fn new(mut module: core::Module) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateExecutionEngineForModule(&mut ee, module.to_ref(), &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn new_interpreter(mut module: core::Module) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateInterpreterForModule(&mut ee, module.to_ref(), &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn new_jit_compiler(mut module: core::Module, opt_level: u32) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateJITCompilerForModule(&mut ee, module.to_ref(), opt_level, &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn add_module(&mut self, mut module: core::Module) -> FrozenModule {
        unsafe {
            LLVMAddModule(self.to_ref(), module.to_ref());
            module.unown();
        }
        FrozenModule {module: module}
    }

    pub fn remove_module(&mut self, module: FrozenModule) -> Result<core::Module, String> {
        let mut module_ref = 0 as LLVMModuleRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            if LLVMRemoveModule(self.to_ref(), module.get().to_ref(), &mut module_ref, &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            }
            else {
                Ok(core::Module::from_ref(module_ref))
            }
        }
    }

    pub fn run_static_constructors(&mut self) {
        unsafe {
            LLVMRunStaticConstructors(self.to_ref())
        }
    }

    pub fn run_static_destructors(&mut self) {
        unsafe {
            LLVMRunStaticDestructors(self.to_ref())
        }
    }

    pub fn run_function<T:core::Function>(&mut self, f: &T, args: &mut [LLVMGenericValueRef]) -> GenericValue {
        unsafe {
            GenericValue::from_ref(LLVMRunFunction(self.to_ref(), f.to_ref(), args.len() as c_uint, args.as_mut_ptr()))
        }
    }

    pub fn get_function_address(&self, name: &str) -> u64 {
        let name = CString::new(name).unwrap();
        unsafe {
            LLVMGetFunctionAddress(self.to_ref(), name.as_ptr() as *const c_char)
        }
    }
}

impl LLVMRef<LLVMExecutionEngineRef> for ExecutionEngine {
    fn to_ref(&self) -> LLVMExecutionEngineRef {
        self.ee
    }
}

impl Drop for ExecutionEngine {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeExecutionEngine(self.to_ref())
        }
    }
}

pub struct MCJITBuilder {
    options: LLVMMCJITCompilerOptions,
    memory_manager: Option<Box<MCJITMemoryManager>>
}

impl MCJITBuilder {
    pub fn new() -> MCJITBuilder {
        let mut options;
        unsafe {
            options = std::mem::uninitialized();
            LLVMInitializeMCJITCompilerOptions(&mut options, std::mem::size_of::<LLVMMCJITCompilerOptions>() as size_t);
        }

        MCJITBuilder {options: options, memory_manager: None}
    }

    pub fn set_opt_level(mut self, opt_level: u32) -> Self {
        self.options.OptLevel = opt_level;
        self
    }

    pub fn set_code_model(mut self, code_model: LLVMCodeModel) -> Self {
        self.options.CodeModel = code_model;
        self
    }

    pub fn no_frame_pointer_elim(mut self) -> Self {
        self.options.NoFramePointerElim = 1;
        self
{'fraction_non_alphanumeric': 0.11459468522089027, 'fraction_numerical': 0.005532735350825719, 'mean_word_length': 2.380561065457637, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5701918', 'n_tokens_mistral': 3772, 'n_tokens_neox': 3692, 'n_words': 812}