<commit_before>//! Defines `SimpleJITBackend`.

use cranelift_codegen::binemit::{Addend, CodeOffset, NullTrapSink, Reloc, RelocSink};
use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::{self, ir, settings};
use cranelift_module::{
    Backend, DataContext, DataDescription, Init, Linkage, ModuleNamespace, ModuleResult,
};
use cranelift_native;
use libc;
use memory::Memory;
use std::collections::HashMap;
use std::ffi::CString;
use std::ptr;
use target_lexicon::PointerWidth;
#[cfg(windows)]
use winapi;

/// A builder for `SimpleJITBackend`.
pub struct SimpleJITBuilder {
    isa: Box<TargetIsa>,
    symbols: HashMap<String, *const u8>,
}

impl SimpleJITBuilder {
    /// Create a new `SimpleJITBuilder`.
    pub fn new() -> Self {
        let (flag_builder, isa_builder) = cranelift_native::builders().unwrap_or_else(|_| {
            panic!("host machine is not a supported target");
        });
        let isa = isa_builder.finish(settings::Flags::new(flag_builder));
        Self::with_isa(isa)
    }

    /// Create a new `SimpleJITBuilder` with an arbitrary target. This is mainly
    /// useful for testing.
    ///
    /// SimpleJIT requires a `TargetIsa` configured for non-PIC.
    ///
    /// To create a `SimpleJITBuilder` for native use, use the `new` constructor
    /// instead.
    pub fn with_isa(isa: Box<TargetIsa>) -> Self {
        debug_assert!(!isa.flags().is_pic(), "SimpleJIT requires non-PIC code");
        let symbols = HashMap::new();
        Self { isa, symbols }
    }

    /// Define a symbol in the internal symbol table.
    ///
    /// The JIT will use the symbol table to resolve names that are declared,
    /// but not defined, in the module being compiled.  A common example is
    /// external functions.  With this method, functions and data can be exposed
    /// to the code being compiled which are defined by the host.
    ///
    /// If a symbol is defined more than once, the most recent definition will
    /// be retained.
    ///
    /// If the JIT fails to find a symbol in its internal table, it will fall
    /// back to a platform-specific search (this typically involves searching
    /// the current process for public symbols, followed by searching the
    /// platform's C runtime).
    pub fn symbol<K>(&mut self, name: K, ptr: *const u8) -> &Self
    where
        K: Into<String>,
    {
        self.symbols.insert(name.into(), ptr);
        self
    }

    /// Define multiple symbols in the internal symbol table.
    ///
    /// Using this is equivalent to calling `symbol` on each element.
    pub fn symbols<It, K>(&mut self, symbols: It) -> &Self
    where
        It: IntoIterator<Item = (K, *const u8)>,
        K: Into<String>,
    {
        for (name, ptr) in symbols {
            self.symbols.insert(name.into(), ptr);
        }
        self
    }
}

/// A `SimpleJITBackend` implements `Backend` and emits code and data into memory where it can be
/// directly called and accessed.
///
/// See the `SimpleJITBuilder` for a convenient way to construct `SimpleJITBackend` instances.
pub struct SimpleJITBackend {
    isa: Box<TargetIsa>,
    symbols: HashMap<String, *const u8>,
    code_memory: Memory,
    readonly_memory: Memory,
    writable_memory: Memory,
}

/// A record of a relocation to perform.
struct RelocRecord {
    offset: CodeOffset,
    reloc: Reloc,
    name: ir::ExternalName,
    addend: Addend,
}

pub struct SimpleJITCompiledFunction {
    code: *mut u8,
    size: usize,
    relocs: Vec<RelocRecord>,
}

pub struct SimpleJITCompiledData {
    storage: *mut u8,
    size: usize,
    relocs: Vec<RelocRecord>,
}

impl SimpleJITBackend {
    fn lookup_symbol(&self, name: &str) -> *const u8 {
        match self.symbols.get(name) {
            Some(&ptr) => ptr,
            None => lookup_with_dlsym(name),
        }
    }
}

impl<'simple_jit_backend> Backend for SimpleJITBackend {
    type Builder = SimpleJITBuilder;

    /// SimpleJIT compiled function and data objects may have outstanding
    /// relocations that need to be performed before the memory can be used.
    /// These relocations are performed within `finalize_function` and
    /// `finalize_data`.
    type CompiledFunction = SimpleJITCompiledFunction;
    type CompiledData = SimpleJITCompiledData;

    /// SimpleJIT emits code and data into memory, and provides raw pointers
    /// to them.
    type FinalizedFunction = *const u8;
    type FinalizedData = (*mut u8, usize);

    /// SimpleJIT emits code and data into memory as it processes them, so it
    /// doesn't need to provide anything after the `Module` is complete.
    type Product = ();

    /// Create a new `SimpleJITBackend`.
    fn new(builder: SimpleJITBuilder) -> Self {
        Self {
            isa: builder.isa,
            symbols: builder.symbols,
            code_memory: Memory::new(),
            readonly_memory: Memory::new(),
            writable_memory: Memory::new(),
        }
    }

    fn isa(&self) -> &TargetIsa {
        &*self.isa
    }

    fn declare_function(&mut self, _name: &str, _linkage: Linkage) {
        // Nothing to do.
    }

    fn declare_data(&mut self, _name: &str, _linkage: Linkage, _writable: bool) {
        // Nothing to do.
    }

    fn define_function(
        &mut self,
        _name: &str,
        ctx: &cranelift_codegen::Context,
        _namespace: &ModuleNamespace<Self>,
        code_size: u32,
    ) -> ModuleResult<Self::CompiledFunction> {
        let size = code_size as usize;
        let ptr = self
            .code_memory
            .allocate(size)
            .expect("TODO: handle OOM etc.");
        let mut reloc_sink = SimpleJITRelocSink::new();
        // Ignore traps for now. For now, frontends should just avoid generating code
        // that traps.
        let mut trap_sink = NullTrapSink {};
        unsafe { ctx.emit_to_memory(&*self.isa, ptr, &mut reloc_sink, &mut trap_sink) };

        Ok(Self::CompiledFunction {
            code: ptr,
            size,
            relocs: reloc_sink.relocs,
        })
    }

    fn define_data(
        &mut self,
        _name: &str,
        writable: bool,
        data: &DataContext,
        _namespace: &ModuleNamespace<Self>,
    ) -> ModuleResult<Self::CompiledData> {
        let &DataDescription {
            ref init,
            ref function_decls,
            ref data_decls,
            ref function_relocs,
            ref data_relocs,
        } = data.description();

        let size = init.size();
        let storage = if writable {
            self.writable_memory
                .allocate(size)
                .expect("TODO: handle OOM etc.")
        } else {
            self.readonly_memory
                .allocate(size)
                .expect("TODO: handle OOM etc.")
        };

        match *init {
            Init::Uninitialized => {
                panic!("data is not initialized yet");
            }
            Init::Zeros { .. } => {
                unsafe { ptr::write_bytes(storage, 0, size) };
            }
            Init::Bytes { ref contents } => {
                let src = contents.as_ptr();
                unsafe { ptr::copy_nonoverlapping(src, storage, size) };
            }
        }

        let reloc = match self.isa.triple().pointer_width().unwrap() {
            PointerWidth::U16 => panic!(),
            PointerWidth::U32 => Reloc::Abs4,
            PointerWidth::U64 => Reloc::Abs8,
        };
        let mut relocs = Vec::new();
        for &(offset, id) in function_relocs {
            relocs.push(RelocRecord {
                reloc,
                offset,
                name: function_decls[id].clone(),
                addend: 0,
            });
        }
        for &(offset, id, addend) in data_relocs {
            relocs.push(RelocRecord {
                reloc,
                offset,
                name: data_decls[id].clone(),
                addend,
            });
        }

        Ok(Self::CompiledData {
            storage,
            size,
            relocs,
        })
    }

    fn write_data_funcaddr(
        &mut self,
        _data: &mut Self::CompiledData,
        _offset: usize,
        _what: ir::FuncRef,
    ) {
        unimplemented!();
    }

    fn write_data_dataaddr(
        &mut self,
        _data: &mut Self::CompiledData,
        _offset: usize,
        _what: ir::GlobalValue,
        _usize: Addend,
    ) {
        unimplemented!();
    }

    fn finalize_function(
        &mut self,
        func: &Self::CompiledFunction,
        namespace: &ModuleNamespace<Self>,
    ) -> Self::FinalizedFunction {
        use std::ptr::write_unaligned;

        for &RelocRecord {
            reloc,
            offset,
            ref name,
            addend,
        } in &func.relocs
        {
            let ptr = func.code;
            debug_assert!((offset as usize) < func.size);
            let at = unsafe { ptr.offset(offset as isize) };
            let base = if namespace.is_function(name) {
                let (def, name_str, _signature) = namespace.get_function_definition(&name);
                match def {
                    Some(compiled) => compiled.code,
                    None => self.lookup_symbol(name_str),
                }
            } else {
                let (def, name_str, _writable) = namespace.get_data_definition(&name);
                match def {
                    Some(compiled) => compiled.storage,
                    None => self.lookup_symbol(name_str),
                }
            };
            // TODO: Handle overflow.
            let what = unsafe { base.offset(addend as isize) };
            match reloc {
                Reloc::Abs4 => {
                    // TODO: Handle overflow.
                    #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
                    unsafe {
                        write_unaligned(at as *mut u32, what as u32)
                    };
                }
                Reloc::Abs8 => {
                    #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
                    unsafe {
                        write_unaligned(at as *mut u64, what as u64)
                    };
                }
                Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => {
                    // TODO: Handle overflow.
                    let pcrel = ((what as isize) - (at as isize)) as i32;
                    #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
                    unsafe {
                        write_unaligned(at as *mut i32, pcrel)
                    };
                }
                Reloc::X86GOTPCRel4 | Reloc::X86CallPLTRel4 => panic!("unexpected PIC relocation"),
                _ => unimplemented!(),
            }
        }
        func.code
    }

    fn get_finalized_function(&self, func: &Self::CompiledFunction) -> Self::FinalizedFunction {
        func.code
    }

    fn finalize_data(
        &mut self,
        data: &Self::CompiledData,
        namespace: &ModuleNamespace<Self>,
    ) -> Self::FinalizedData {
        use std::ptr::write_unaligned;

        for record in &data.relocs {
            match *record {
                RelocRecord {
                    reloc,
                    offset,
                    ref name,
                    addend,
                } => {
                    let ptr = data.storage;
                    debug_assert!((offset as usize) < data.size);
                    let at = unsafe { ptr.offset(offset as isize) };
                    let base = if namespace.is_function(name) {
                        let (def, name_str, _signature) = namespace.get_function_definition(&name);
                        match def {
                            Some(compiled) => compiled.code,
                            None => self.lookup_symbol(name_str),
                        }
                    } else {
                        let (def, name_str, _writable) = namespace.get_data_definition(&name);
                        match def {
                            Some(compiled) => compiled.storage,
                            None => self.lookup_symbol(name_str),
                        }
                    };
                    // TODO: Handle overflow.
                    let what = unsafe { base.offset(addend as isize) };
                    match reloc {
                        Reloc::Abs4 => {
                            // TODO: Handle overflow.
                            #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
                            unsafe {
                                write_unaligned(at as *mut u32, what as u32)
                            };
                        }
                        Reloc::Abs8 => {
                            #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
                            unsafe {
                                write_unaligned(at as *mut u64, what as u64)
                            };
                        }
                        Reloc::X86PCRel4
                        | Reloc::X86CallPCRel4
                        | Reloc::X86GOTPCRel4
                        | Reloc::X86CallPLTRel4 => panic!("unexpected text relocation in data"),
                        _ => unimplemented!(),
                    }
                }
            }
        }
        (data.storage, data.size)
    }

    fn get_finalized_data(&self, data: &Self::CompiledData) -> Self::FinalizedData {
        (data.storage, data.size)
    }

    fn publish(&mut self) {
        // Now that we're done patching, prepare the memory for execution!
        self.readonly_memory.set_readonly();
        self.code_memory.set_executable();
    }

    /// SimpleJIT emits code and data into memory as it processes them, so it
    /// doesn't need to provide anything after the `Module` is complete.
    fn finish(self) -> () {}
}

#[cfg(not(windows))]
fn lookup_with_dlsym(name: &str) -> *const u8 {
    let c_str = CString::new(name).unwrap();
    let c_str_ptr = c_str.as_ptr();
    let sym = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c_str_ptr) };
    if sym.is_null() {
        panic!("can't resolve symbol {}", name);
    }
    sym as *const u8
}

#[cfg(windows)]
fn lookup_with_dlsym(name: &str) -> *const u8 {
    const MSVCRT_DLL: &[u8] = b"msvcrt.dll\0";

    let c_str = CString::new(name).unwrap();
    let c_str_ptr = c_str.as_ptr();

    unsafe {
        let handles = [
            // try to find the searched symbol in the currently running executable
            ptr::null_mut(),
            // try to find the searched symbol in local c runtime
            winapi::um::libloaderapi::GetModuleHandleA(MSVCRT_DLL.as_ptr() as *const i8),
        ];

        for handle in &handles {
            let addr = winapi::um::libloaderapi::GetProcAddress(*handle, c_str_ptr);
            if addr.is_null() {
                continue;
            }
            return addr as *const u8;
        }

        let msg = if handles[1].is_null() {
            "(msvcrt not loaded)"
        } else {
            ""
        };
        panic!("cannot resolve address of symbol {} {}", name, msg);
    }
}

struct SimpleJITRelocSink {
    pub relocs: Vec<RelocRecord>,
}

impl SimpleJITRelocSink {
    pub fn new() -> Self {
        Self { relocs: Vec::new() }
    }
}

impl RelocSink for SimpleJITRelocSink {
    fn reloc_ebb(&mut self, _offset: CodeOffset, _reloc: Reloc, _ebb_offset: CodeOffset) {
        unimplemented!();
    }

    fn reloc_external(
        &mut self,
        offset: CodeOffset,
        reloc: Reloc,
        name: &ir::ExternalName,
        addend: Addend,
    ) {
        self.relocs.push(RelocRecord {
            offset,
            reloc,
            name: name.clone(),
            addend,
        });
    }

    fn reloc_jt(&mut self, _offset: CodeOffset, _reloc: Reloc, _jt: ir::JumpTable) {
        unimplemented!();
    }
}
<commit_msg>Minor code simplification; avoid an unneeded `match`.<commit_after>//! Defines `SimpleJITBackend`.

use cranelift_codegen::binemit::{Addend, CodeOffset, NullTrapSink, Reloc, RelocSink};
use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::{self, ir, settings};
use cranelift_module::{
    Backend, DataContext, DataDescription, Init, Linkage, ModuleNamespace, ModuleResult,
};
use cranelift_native;
use libc;
use memory::Memory;
use std::collections::HashMap;
use std::ffi::CString;
use std::ptr;
use target_lexicon::PointerWidth;
#[cfg(windows)]
use winapi;

/// A builder for `SimpleJITBackend`.
pub struct SimpleJITBuilder {
    isa: Box<TargetIsa>,
    symbols: HashMap<String, *const u8>,
}

impl SimpleJITBuilder {
    /// Create a new `SimpleJITBuilder`.
    pub fn new() -> Self {
        let (flag_builder, isa_builder) = cranelift_native::builders().unwrap_or_else(|_| {
            panic!("host machine is not a supported target");
        });
        let isa = isa_builder.finish(settings::Flags::new(flag_builder));
        Self::with_isa(isa)
    }

    /// Create a new `SimpleJITBuilder` with an arbitrary target. This is mainly
    /// useful for testing.
    ///
    /// SimpleJIT requires a `TargetIsa` configured for non-PIC.
    ///
    /// To create a `SimpleJITBuilder` for native use, use the `new` constructor
    /// instead.
    pub fn with_isa(isa: Box<TargetIsa>) -> Self {
        debug_assert!(!isa.flags().is_pic(), "SimpleJIT requires non-PIC code");
        let symbols = HashMap::new();
        Self { isa, symbols }
    }

    /// Define a symbol in the internal symbol table.
    ///
    /// The JIT will use the symbol table to resolve names that are declared,
    /// but not defined, in the module being compiled.  A common example is
    /// external functions.  With this method, functions and data can be exposed
    /// to the code being compiled which are defined by the host.
    ///
    /// If a symbol is defined more than once, the most recent definition will
    /// be retained.
    ///
    /// If the JIT fails to find a symbol in its internal table, it will fall
    /// back to a platform-specific search (this typically involves searching
    /// the current process for public symbols, followed by searching the
    /// platform's C runtime).
    pub fn symbol<K>(&mut self, name: K, ptr: *const u8) -> &Self
    where
        K: Into<String>,
    {
        self.symbols.insert(name.into(), ptr);
        self
    }

    /// Define multiple symbols in the internal symbol table.
    ///
    /// Using this is equivalent to calling `symbol` on each element.
    pub fn symbols<It, K>(&mut self, symbols: It) -> &Self
    where
        It: IntoIterator<Item = (K, *const u8)>,
        K: Into<String>,
    {
        for (name, ptr) in symbols {
            self.symbols.insert(name.into(), ptr);
        }
        self
    }
}

/// A `SimpleJITBackend` implements `Backend` and emits code and data into memory where it can be
/// directly called and accessed.
///
/// See the `SimpleJITBuilder` for a convenient way to construct `SimpleJITBackend` instances.
pub struct SimpleJITBackend {
    isa: Box<TargetIsa>,
    symbols: HashMap<String, *const u8>,
    code_memory: Memory,
    readonly_memory: Memory,
    writable_memory: Memory,
}

/// A record of a relocation to perform.
struct RelocRecord {
    offset: CodeOffset,
    reloc: Reloc,
    name: ir::ExternalName,
    addend: Addend,
}

pub struct SimpleJITCompiledFunction {
    code: *mut u8,
    size: usize,
    relocs: Vec<RelocRecord>,
}

pub struct SimpleJITCompiledData {
    storage: *mut u8,
    size: usize,
    relocs: Vec<RelocRecord>,
}

impl SimpleJITBackend {
    fn lookup_symbol(&self, name: &str) -> *const u8 {
        match self.symbols.get(name) {
            Some(&ptr) => ptr,
            None => lookup_with_dlsym(name),
        }
    }
}

impl<'simple_jit_backend> Backend for SimpleJITBackend {
    type Builder = SimpleJITBuilder;

    /// SimpleJIT compiled function and data objects may have outstanding
    /// relocations that need to be performed before the memory can be used.
    /// These relocations are performed within `finalize_function` and
    /// `finalize_data`.
    type CompiledFunction = SimpleJITCompiledFunction;
    type CompiledData = SimpleJITCompiledData;

    /// SimpleJIT emits code and data into memory, and provides raw pointers
    /// to them.
    type FinalizedFunction = *const u8;
    type FinalizedData = (*mut u8, usize);

    /// SimpleJIT emits code and data into memory as it processes them, so it
    /// doesn't need to provide anything after the `Module` is complete.
    type Product = ();

    /// Create a new `SimpleJITBackend`.
    fn new(builder: SimpleJITBuilder) -> Self {
        Self {
            isa: builder.isa,
            symbols: builder.symbols,
            code_memory: Memory::new(),
            readonly_memory: Memory::new(),
            writable_memory: Memory::new(),
        }
    }

    fn isa(&self) -> &TargetIsa {
        &*self.isa
    }

    fn declare_function(&mut self, _name: &str, _linkage: Linkage) {
        // Nothing to do.
    }

    fn declare_data(&mut self, _name: &str, _linkage: Linkage, _writable: bool) {
        // Nothing to do.
    }

    fn define_function(
        &mut self,
        _name: &str,
        ctx: &cranelift_codegen::Context,
        _namespace: &ModuleNamespace<Self>,
        code_size: u32,
    ) -> ModuleResult<Self::CompiledFunction> {
        let size = code_size as usize;
        let ptr = self
            .code_memory
            .allocate(size)
            .expect("TODO: handle OOM etc.");
        let mut reloc_sink = SimpleJITRelocSink::new();
        // Ignore traps for now. For now, frontends should just avoid generating code
        // that traps.
        let mut trap_sink = NullTrapSink {};
        unsafe { ctx.emit_to_memory(&*self.isa, ptr, &mut reloc_sink, &mut trap_sink) };

        Ok(Self::CompiledFunction {
            code: ptr,
            size,
            relocs: reloc_sink.relocs,
        })
    }

    fn define_data(
        &mut self,
        _name: &str,
        writable: bool,
        data: &DataContext,
        _namespace: &ModuleNamespace<Self>,
    ) -> ModuleResult<Self::CompiledData> {
        let &DataDescription {
            ref init,
            ref function_decls,
            ref data_decls,
            ref function_relocs,
            ref data_relocs,
        } = data.description();

        let size = init.size();
        let storage = if writable {
            self.writable_memory
                .allocate(size)
                .expect("TODO: handle OOM etc.")
        } else {
            self.readonly_memory
                .allocate(size)
                .expect("TODO: handle OOM etc.")
        };

        match *init {
            Init::Uninitialized => {
                panic!("data is not initialized yet");
            }
            Init::Zeros { .. } => {
                unsafe { ptr::write_bytes(storage, 0, size) };
            }
            Init::Bytes { ref contents } => {
                let src = contents.as_ptr();
                unsafe { ptr::copy_nonoverlapping(src, storage, size) };
            }
        }

        let reloc = match self.isa.triple().pointer_width().unwrap() {
            PointerWidth::U16 => panic!(),
            PointerWidth::U32 => Reloc::Abs4,
            PointerWidth::U64 => Reloc::Abs8,
        };
        let mut relocs = Vec::new();
        for &(offset, id) in function_relocs {
            relocs.push(RelocRecord {
                reloc,
                offset,
                name: function_decls[id].clone(),
                addend: 0,
            });
        }
        for &(offset, id, addend) in data_relocs {
            relocs.push(RelocRecord {
                reloc,
                offset,
                name: data_decls[id].clone(),
                addend,
            });
        }

        Ok(Self::CompiledData {
            storage,
            size,
            relocs,
        })
    }

    fn write_data_funcaddr(
        &mut self,
        _data: &mut Self::CompiledData,
        _offset: usize,
        _what: ir::FuncRef,
    ) {
        unimplemented!();
    }

    fn write_data_dataaddr(
        &mut self,
        _data: &mut Self::CompiledData,
        _offset: usize,
        _what: ir::GlobalValue,
        _usize: Addend,
    ) {
        unimplemented!();
    }

    fn finalize_function(
        &mut self,
        func: &Self::CompiledFunction,
        namespace: &ModuleNamespace<Self>,
    ) -> Self::FinalizedFunction {
        use std::ptr::write_unaligned;

        for &RelocRecord {
            reloc,
            offset,
            ref name,
            addend,
        } in &func.relocs
        {
            let ptr = func.code;
            debug_assert!((offset as usize) < func.size);
            let at = unsafe { ptr.offset(offset as isize) };
            let base = if namespace.is_function(name) {
                let (def, name_str, _signature) = namespace.get_function_definition(&name);
                match def {
                    Some(compiled) => compiled.code,
                    None => self.lookup_symbol(name_str),
                }
            } else {
                let (def, name_str, _writable) = namespace.get_data_definition(&name);
                match def {
                    Some(compiled) => compiled.storage,
                    None => self.lookup_symbol(name_str),
                }
            };
            // TODO: Handle overflow.
            let what = unsafe { base.offset(addend as isize) };
            match reloc {
                Reloc::Abs4 => {
                    // TODO: Handle overflow.
                    #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
                    unsafe {
                        write_unaligned(at as *mut u32, what as u32)
                    };
                }
                Reloc::Abs8 => {
                    #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
                    unsafe {
                        write_unaligned(at as *mut u64, what as u64)
                    };
                }
                Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => {
                    // TODO: Handle overflow.
                    let pcrel = ((what as isize) - (at as isize)) as i32;
                    #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
                    unsafe {
                        write_unaligned(at as *mut i32, pcrel)
                    };
                }
                Reloc::X86GOTPCRel4 | Reloc::X86CallPLTRel4 => panic!("unexpected PIC relocation"),
                _ => unimplemented!(),
            }
        }
        func.code
    }

    fn get_finalized_function(&self, func: &Self::CompiledFunction) -> Self::FinalizedFunction {
        func.code
    }

    fn finalize_data(
        &mut self,
        data: &Self::CompiledData,
        namespace: &ModuleNamespace<Self>,
    ) -> Self::FinalizedData {
        use std::ptr::write_unaligned;

        for &RelocRecord {
            reloc,
            offset,
            ref name,
            addend,
        } in &data.relocs
        {
            let ptr = data.storage;
            debug_assert!((offset as usize) < data.size);
            let at = unsafe { ptr.offset(offset as isize) };
            let base = if namespace.is_function(name) {
                let (def, name_str, _signature) = namespace.get_function_definition(&name);
                match def {
                    Some(compiled) => compiled.code,
                    None => self.lookup_symbol(name_str),
                }
            } else {
                let (def, name_str, _writable) = namespace.get_data_definition(&name);
                match def {
                    Some(compiled) => compiled.storage,
                    None => self.lookup_symbol(name_str),
                }
            };
            // TODO: Handle overflow.
            let what = unsafe { base.offset(addend as isize) };
            match reloc {
                Reloc::Abs4 => {
                    // TODO: Handle overflow.
                    #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
                    unsafe {
                        write_unaligned(at as *mut u32, what as u32)
                    };
                }
                Reloc::Abs8 => {
                    #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
                    unsafe {
                        write_unaligned(at as *mut u64, what as u64)
                    };
                }
                Reloc::X86PCRel4
                | Reloc::X86CallPCRel4
                | Reloc::X86GOTPCRel4
                | Reloc::X86CallPLTRel4 => panic!("unexpected text relocation in data"),
                _ => unimplemented!(),
            }
        }
        (data.storage, data.size)
    }

    fn get_finalized_data(&self, data: &Self::CompiledData) -> Self::FinalizedData {
        (data.storage, data.size)
    }

    fn publish(&mut self) {
        // Now that we're done patching, prepare the memory for execution!
        self.readonly_memory.set_readonly();
        self.code_memory.set_executable();
    }

    /// SimpleJIT emits code and data into memory as it processes them, so it
    /// doesn't need to provide anything after the `Module` is complete.
    fn finish(self) -> () {}
}

#[cfg(not(windows))]
fn lookup_with_dlsym(name: &str) -> *const u8 {
    let c_str = CString::new(name).unwrap();
    let c_str_ptr = c_str.as_ptr();
    let sym = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c_str_ptr) };
    if sym.is_null() {
        panic!("can't resolve symbol {}", name);
    }
    sym as *const u8
}

#[cfg(windows)]
fn lookup_with_dlsym(name: &str) -> *const u8 {
    const MSVCRT_DLL: &[u8] = b"msvcrt.dll\0";

    let c_str = CString::new(name).unwrap();
    let c_str_ptr = c_str.as_ptr();

    unsafe {
        let handles = [
            // try to find the searched symbol in the currently running executable
            ptr::null_mut(),
            // try to find the searched symbol in local c runtime
            winapi::um::libloaderapi::GetModuleHandleA(MSVCRT_DLL.as_ptr() as *const i8),
        ];

        for handle in &handles {
            let addr = winapi::um::libloaderapi::GetProcAddress(*handle, c_str_ptr);
            if addr.is_null() {
                continue;
            }
            return addr as *const u8;
        }

        let msg = if handles[1].is_null() {
            "(msvcrt not loaded)"
        } else {
            ""
        };
        panic!("cannot resolve address of symbol {} {}", name, msg);
    }
}

struct SimpleJITRelocSink {
    pub relocs: Vec<RelocRecord>,
}

impl SimpleJITRelocSink {
    pub fn new() -> Self {
        Self { relocs: Vec::new() }
    }
}

impl RelocSink for SimpleJITRelocSink {
    fn reloc_ebb(&mut self, _offset: CodeOffset, _reloc: Reloc, _ebb_offset: CodeOffset) {
        unimplemented!();
    }

    fn reloc_external(
        &mut self,
        offset: CodeOffset,
        reloc: Reloc,
        name: &ir::ExternalName,
        addend: Addend,
    ) {
        self.relocs.push(RelocRecord {
            offset,
            reloc,
            name: name.clone(),
            addend,
        });
    }

    fn reloc_jt(&mut self, _offset: CodeOffset, _reloc: Reloc, _jt: ir::JumpTable) {
        unimplemented!();
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Implementation of the `RawLink` smart-ish pointer.
//!
//! A `RawLink` is a zero-cost abstraction that allows a raw pointer to be used
//! with an `Option`-esque API.
//!
//! TODO: implement all monadic operations over `Option`-esque types (i.e.
//! `map()`, `and_then()`, etc).

use core::ptr;
use core::fmt;
use core::mem;

/// A `RawLink` provides an `Option`-like interface to a raw pointer.
#[allow(raw_pointer_derive)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct RawLink<T>(*mut T);

unsafe impl<T> Send for RawLink<T>
where T: 'static
    , T: Send {}

unsafe impl<T> Sync for RawLink<T>
where T: Send
    , T: Sync {}

impl<T> Default for RawLink<T> {
    fn default() -> Self { Self::none() }
}

impl<T> fmt::Display for RawLink<T>
where T: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.0.is_null() {
            write!(f, "RawLink::none")
        } else {
            unsafe { write!(f, "RawLink::some({})", *self.0) }
        }

    }
}

impl<T> RawLink<T> {

    /// Equivalent of `Option::None` for a `RawLink`
    ///
    /// # Returns
    ///   - A `RawLink<T>` wrapping a null pointer
    #[inline]
    pub const fn none() -> RawLink<T> { RawLink(ptr::null_mut()) }

    /// Equivalent of `Option::Some` for a `RawLink`
    ///
    /// # Returns
    ///   - A `RawLink<T>` wrapping a pointer to the specified value
    #[inline]
    pub const fn some(thing: &mut T) -> RawLink<T> { RawLink(thing) }

    pub const fn from_raw(ptr: *mut T) -> RawLink<T> { RawLink(ptr) }

    /// Resolve the `RawLink` to an `Option`
    ///
    /// # Returns
    ///   - `Some<&'a T>` if the `RawLink` is not a null pointer
    ///   - `None` if the `RawLink` is a null pointer
    ///
    /// # Unsafe due to
    ///   - Returning a reference with an arbitrary lifetime
    ///   - Dereferencing a raw pointer
    #[inline]
    pub unsafe fn resolve<'a>(&self) -> Option<&'a T> {
        self.0.as_ref()
    }

    /// Resolve the `RawLink` to an `Option` on a mutable pointer
    ///
    /// # Returns
    ///   - `Some<&'a mut T>` if the `RawLink` is not a null pointer
    ///   - `None` if the `RawLink` is a null pointer
    ///
    /// # Unsafe due to
    ///   - Returning a reference with an arbitrary lifetime
    ///   - Dereferencing a raw pointer
    #[inline]
    pub unsafe fn resolve_mut<'a>(&self) -> Option<&'a mut T> {
        self.0.as_mut()
    }

    #[inline]
    pub fn is_some(&self) -> bool { !self.is_none() }

    #[inline]
    pub fn is_none(&self) -> bool { self.0.is_null() }

    /// Returns the `RawLink` and replaces it with `RawLink::none()`.
    #[inline]
    pub fn take(&mut self) -> Self { mem::replace(self, Self::none()) }

    pub unsafe fn map<U, F: FnOnce(T) -> U>(self, f: F) -> RawLink<U> {
        unimplemented!()
    }
}
<commit_msg>Now with FreeList::remove() function<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Implementation of the `RawLink` smart-ish pointer.
//!
//! A `RawLink` is a zero-cost abstraction that allows a raw pointer to be used
//! with an `Option`-esque API.
//!
//! TODO: implement all monadic operations over `Option`-esque types (i.e.
//! `map()`, `and_then()`, etc).

use core::ptr;
use core::fmt;
use core::mem;

/// A `RawLink` provides an `Option`-like interface to a raw pointer.
#[allow(raw_pointer_derive)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct RawLink<T>(*mut T);

unsafe impl<T> Send for RawLink<T>
where T: 'static
    , T: Send {}

unsafe impl<T> Sync for RawLink<T>
where T: Send
    , T: Sync {}

impl<T> Default for RawLink<T> {
    fn default() -> Self { Self::none() }
}

impl<T> fmt::Display for RawLink<T>
where T: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.0.is_null() {
            write!(f, "RawLink::none")
        } else {
            unsafe { write!(f, "RawLink::some({})", *self.0) }
        }

    }
}

impl<T> RawLink<T> {

    /// Equivalent of `Option::None` for a `RawLink`
    ///
    /// # Returns
    ///   - A `RawLink<T>` wrapping a null pointer
    #[inline]
    pub const fn none() -> RawLink<T> { RawLink(ptr::null_mut()) }

    /// Equivalent of `Option::Some` for a `RawLink`
    ///
    /// # Returns
    ///   - A `RawLink<T>` wrapping a pointer to the specified value
    #[inline]
    pub const fn some(thing: &mut T) -> RawLink<T> { RawLink(thing) }

    pub const fn from_raw(ptr: *mut T) -> RawLink<T> { RawLink(ptr) }

    /// Resolve the `RawLink` to an `Option`
    ///
    /// # Returns
    ///   - `Some<&'a T>` if the `RawLink` is not a null pointer
    ///   - `None` if the `RawLink` is a null pointer
    ///
    /// # Unsafe due to
    ///   - Returning a reference with an arbitrary lifetime
    ///   - Dereferencing a raw pointer
    #[inline]
    pub unsafe fn resolve<'a>(&self) -> Option<&'a T> {
        self.0.as_ref()
    }

    /// Resolve the `RawLink` to an `Option` on a mutable pointer
    ///
    /// # Returns
    ///   - `Some<&'a mut T>` if the `RawLink` is not a null pointer
    ///   - `None` if the `RawLink` is a null pointer
    ///
    /// # Unsafe due to
    ///   - Returning a reference with an arbitrary lifetime
    ///   - Dereferencing a raw pointer
    #[inline]
    pub unsafe fn resolve_mut<'a>(&self) -> Option<&'a mut T> {
        self.0.as_mut()
    }

    /// Please don't do this.
    #[inline]
    pub unsafe fn as_raw(&self) -> *mut T { self.0 }

    #[inline]
    pub fn is_some(&self) -> bool { !self.is_none() }

    #[inline]
    pub fn is_none(&self) -> bool { self.0.is_null() }

    /// Returns the `RawLink` and replaces it with `RawLink::none()`.
    #[inline]
    pub fn take(&mut self) -> Self { mem::replace(self, Self::none()) }

    pub unsafe fn map<U, F: FnOnce(T) -> U>(self, f: F) -> RawLink<U> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>use cranelift_module::*;
use crate::prelude::*;
use crate::rustc::mir::interpret::{
    read_target_uint, AllocId, AllocType, Allocation, ConstValue, EvalResult, GlobalId, Scalar,
};
use crate::rustc::ty::Const;
use crate::rustc_mir::interpret::{EvalContext, Machine, Memory, MemoryKind, OpTy, PlaceTy, Pointer};
use std::borrow::Cow;

#[derive(Default)]
pub struct ConstantCx {
    todo: HashSet<TodoItem>,
    done: HashSet<DataId>,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
enum TodoItem {
    Alloc(AllocId),
    Static(DefId),
}

impl ConstantCx {
    pub fn finalize<'a, 'tcx: 'a, B: Backend>(
        mut self,
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
        module: &mut Module<B>,
    ) {
        //println!("todo {:?}", self.todo);
        define_all_allocs(tcx, module, &mut self);
        //println!("done {:?}", self.done);
        self.done.clear();
    }
}

pub fn codegen_static<'a, 'tcx: 'a>(ccx: &mut ConstantCx, def_id: DefId) {
    ccx.todo.insert(TodoItem::Static(def_id));
}

pub fn codegen_static_ref<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    static_: &Static<'tcx>,
) -> CPlace<'tcx> {
    let data_id = data_id_for_static(fx.tcx, fx.module, static_.def_id);
    cplace_for_dataid(fx, static_.ty, data_id)
}

pub fn trans_promoted<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    promoted: Promoted,
) -> CPlace<'tcx> {
    let const_ = fx
        .tcx
        .const_eval(ParamEnv::reveal_all().and(GlobalId {
            instance: fx.instance,
            promoted: Some(promoted),
        }))
        .unwrap();

    let const_ = force_eval_const(fx, const_);
    trans_const_place(fx, const_)
}

pub fn trans_constant<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    constant: &Constant<'tcx>,
) -> CValue<'tcx> {
    let const_ = fx.monomorphize(&constant.literal);
    let const_ = force_eval_const(fx, const_);
    trans_const_value(fx, const_)
}

pub fn force_eval_const<'a, 'tcx: 'a>(
    fx: &FunctionCx<'a, 'tcx, impl Backend>,
    const_: &'tcx Const<'tcx>,
) -> &'tcx Const<'tcx> {
    match const_.val {
        ConstValue::Unevaluated(def_id, ref substs) => {
            let param_env = ParamEnv::reveal_all();
            let instance = Instance::resolve(fx.tcx, param_env, def_id, substs).unwrap();
            let cid = GlobalId {
                instance,
                promoted: None,
            };
            fx.tcx.const_eval(param_env.and(cid)).unwrap()
        }
        _ => const_,
    }
}

fn trans_const_value<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    const_: &'tcx Const<'tcx>,
) -> CValue<'tcx> {
    let ty = fx.monomorphize(&const_.ty);
    let layout = fx.layout_of(ty);
    match ty.sty {
        ty::Bool => {
            let bits = const_.val.try_to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as u64 as i64)
        }
        ty::Uint(_) => {
            let bits = const_.val.try_to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as u64 as i64)
        }
        ty::Int(_) => {
            let bits = const_.val.try_to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as i128 as i64)
        }
        ty::FnDef(def_id, substs) => {
            let func_ref = fx.get_function_ref(
                Instance::resolve(fx.tcx, ParamEnv::reveal_all(), def_id, substs).unwrap(),
            );
            let func_addr = fx.bcx.ins().func_addr(fx.module.pointer_type(), func_ref);
            CValue::ByVal(func_addr, layout)
        }
        _ => trans_const_place(fx, const_).to_cvalue(fx),
    }
}

fn trans_const_place<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    const_: &'tcx Const<'tcx>,
) -> CPlace<'tcx> {
    // Adapted from https://github.com/rust-lang/rust/pull/53671/files#diff-e0b58bb6712edaa8595ad7237542c958L551
    let result = || -> EvalResult<'tcx, &'tcx Allocation> {
        let mut ecx = EvalContext::new(
            fx.tcx.at(DUMMY_SP),
            ty::ParamEnv::reveal_all(),
            TransPlaceInterpreter,
        );
        let op = ecx.const_to_op(const_)?;
        let ptr = ecx.allocate(op.layout, MemoryKind::Stack)?;
        ecx.copy_op(op, ptr.into())?;
        let alloc = ecx.memory.get(ptr.to_ptr()?.alloc_id)?;
        Ok(fx.tcx.intern_const_alloc(alloc.clone()))
    };
    let alloc = result().expect("unable to convert ConstValue to Allocation");

    //println!("const value: {:?} allocation: {:?}", value, alloc);
    let alloc_id = fx.tcx.alloc_map.lock().allocate(alloc);
    fx.constants.todo.insert(TodoItem::Alloc(alloc_id));
    let data_id = data_id_for_alloc_id(fx.module, alloc_id);
    cplace_for_dataid(fx, const_.ty, data_id)
}

fn data_id_for_alloc_id<B: Backend>(module: &mut Module<B>, alloc_id: AllocId) -> DataId {
    module
        .declare_data(&alloc_id.0.to_string(), Linkage::Local, false)
        .unwrap()
}

fn data_id_for_static<'a, 'tcx: 'a, B: Backend>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    module: &mut Module<B>,
    def_id: DefId,
) -> DataId {
    let symbol_name = tcx.symbol_name(Instance::mono(tcx, def_id)).as_str();
    let is_mutable =
        if let crate::rustc::hir::Mutability::MutMutable = tcx.is_static(def_id).unwrap() {
            true
        } else {
            !tcx.type_of(def_id)
                .is_freeze(tcx, ParamEnv::reveal_all(), DUMMY_SP)
        };
    module
        .declare_data(&*symbol_name, Linkage::Export, is_mutable)
        .unwrap()
}

fn cplace_for_dataid<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    ty: Ty<'tcx>,
    data_id: DataId,
) -> CPlace<'tcx> {
    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
    let global_ptr = fx
        .bcx
        .ins()
        .global_value(fx.module.pointer_type(), local_data_id);
    let layout = fx.layout_of(fx.monomorphize(&ty));
    assert!(!layout.is_unsized(), "unsized statics aren't supported");
    CPlace::Addr(global_ptr, None, layout)
}

fn define_all_allocs<'a, 'tcx: 'a, B: Backend + 'a>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    module: &mut Module<B>,
    cx: &mut ConstantCx,
) {
    let memory = Memory::<TransPlaceInterpreter>::new(tcx.at(DUMMY_SP));

    while let Some(todo_item) = pop_set(&mut cx.todo) {
        let (data_id, alloc) = match todo_item {
            TodoItem::Alloc(alloc_id) => {
                //println!("alloc_id {}", alloc_id);
                let data_id = data_id_for_alloc_id(module, alloc_id);
                let alloc = memory.get(alloc_id).unwrap();
                (data_id, alloc)
            }
            TodoItem::Static(def_id) => {
                //println!("static {:?}", def_id);
                let instance = ty::Instance::mono(tcx, def_id);
                let cid = GlobalId {
                    instance,
                    promoted: None,
                };
                let const_ = tcx.const_eval(ParamEnv::reveal_all().and(cid)).unwrap();

                let alloc = match const_.val {
                    ConstValue::ByRef(_alloc_id, alloc, n) if n.bytes() == 0 => alloc,
                    _ => bug!("static const eval returned {:#?}", const_),
                };

                let data_id = data_id_for_static(tcx, module, def_id);
                (data_id, alloc)
            }
        };

        //("data_id {}", data_id);
        if cx.done.contains(&data_id) {
            continue;
        }

        let mut data_ctx = DataContext::new();

        data_ctx.define(alloc.bytes.to_vec().into_boxed_slice());

        for &(offset, (_tag, reloc)) in alloc.relocations.iter() {
            let reloc_offset = {
                let endianness = tcx.data_layout.endian;
                let offset = offset.bytes() as usize;
                let ptr_size = tcx.data_layout.pointer_size;
                let bytes = &alloc.bytes[offset..offset + ptr_size.bytes() as usize];
                read_target_uint(endianness, bytes).unwrap()
            };

            let data_id = match tcx.alloc_map.lock().get(reloc).unwrap() {
                AllocType::Function(instance) => {
                    let (func_name, sig) = crate::abi::get_function_name_and_sig(tcx, instance);
                    let func_id = module
                        .declare_function(&func_name, Linkage::Import, &sig)
                        .unwrap();
                    let local_func_id = module.declare_func_in_data(func_id, &mut data_ctx);
                    data_ctx.write_function_addr(reloc_offset as u32, local_func_id);
                    continue;
                }
                AllocType::Memory(_) => {
                    cx.todo.insert(TodoItem::Alloc(reloc));
                    data_id_for_alloc_id(module, reloc)
                }
                AllocType::Static(def_id) => {
                    cx.todo.insert(TodoItem::Static(def_id));
                    data_id_for_static(tcx, module, def_id)
                }
            };

            let global_value = module.declare_data_in_data(data_id, &mut data_ctx);
            data_ctx.write_data_addr(reloc_offset as u32, global_value, 0);
        }

        module.define_data(data_id, &data_ctx).unwrap();
        cx.done.insert(data_id);
    }

    assert!(cx.todo.is_empty(), "{:?}", cx.todo);
}

fn pop_set<T: Copy + Eq + ::std::hash::Hash>(set: &mut HashSet<T>) -> Option<T> {
    if let Some(elem) = set.iter().next().map(|elem| *elem) {
        set.remove(&elem);
        Some(elem)
    } else {
        None
    }
}

struct TransPlaceInterpreter;

impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for TransPlaceInterpreter {
    type MemoryKinds = !;
    type PointerTag = ();
    type AllocExtra = ();
    type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation<()>)>;
    const STATIC_KIND: Option<!> = None;
    const ENABLE_PTR_TRACKING_HOOKS: bool = false;

    fn enforce_validity(_: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool {
        false
    }

    fn before_terminator(_: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> {
        panic!();
    }

    fn find_fn(
        _: &mut EvalContext<'a, 'mir, 'tcx, Self>,
        _: Instance<'tcx>,
        _: &[OpTy<'tcx>],
        _: Option<PlaceTy<'tcx>>,
        _: Option<BasicBlock>,
    ) -> EvalResult<'tcx, Option<&'mir Mir<'tcx>>> {
        panic!();
    }

    fn call_intrinsic(
        _: &mut EvalContext<'a, 'mir, 'tcx, Self>,
        _: Instance<'tcx>,
        _: &[OpTy<'tcx>],
        _: PlaceTy<'tcx>,
    ) -> EvalResult<'tcx> {
        panic!();
    }

    fn find_foreign_static(
        _: crate::rustc::ty::query::TyCtxtAt<'a, 'tcx, 'tcx>,
        _: DefId,
    ) -> EvalResult<'tcx, Cow<'tcx, Allocation>> {
        panic!();
    }

    fn static_with_default_tag(alloc: &Allocation) -> Cow<Allocation<()>> {
        Cow::Borrowed(alloc)
    }

    fn ptr_op(
        _: &EvalContext<'a, 'mir, 'tcx, Self>,
        _: mir::BinOp,
        _: Scalar,
        _: TyLayout<'tcx>,
        _: Scalar,
        _: TyLayout<'tcx>,
    ) -> EvalResult<'tcx, (Scalar, bool)> {
        panic!();
    }

    fn box_alloc(_: &mut EvalContext<'a, 'mir, 'tcx, Self>, _: PlaceTy<'tcx>) -> EvalResult<'tcx> {
        panic!();
    }

    fn tag_reference(_: &mut EvalContext<'a, 'mir, 'tcx, Self>, _: Pointer<()>, _: Ty<'tcx>, _: Size, _: Option<BorrowKind>) -> EvalResult<'tcx> {
        panic!();
    }

    fn tag_dereference(_: &EvalContext<'a, 'mir, 'tcx, Self>, _: Pointer<()>, _: Ty<'tcx>) -> EvalResult<'tcx> {
        panic!();
    }
}
<commit_msg>Rustup to rustc 1.31.0-nightly (d586d5d2f 2018-10-29)<commit_after>use cranelift_module::*;
use crate::prelude::*;
use crate::rustc::mir::interpret::{
    read_target_uint, AllocId, AllocType, Allocation, ConstValue, EvalResult, GlobalId, Scalar,
};
use crate::rustc::ty::Const;
use crate::rustc_mir::interpret::{EvalContext, Machine, Memory, MemoryKind, MemPlace, OpTy, PlaceTy, Pointer};
use std::borrow::Cow;

#[derive(Default)]
pub struct ConstantCx {
    todo: HashSet<TodoItem>,
    done: HashSet<DataId>,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
enum TodoItem {
    Alloc(AllocId),
    Static(DefId),
}

impl ConstantCx {
    pub fn finalize<'a, 'tcx: 'a, B: Backend>(
        mut self,
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
        module: &mut Module<B>,
    ) {
        //println!("todo {:?}", self.todo);
        define_all_allocs(tcx, module, &mut self);
        //println!("done {:?}", self.done);
        self.done.clear();
    }
}

pub fn codegen_static<'a, 'tcx: 'a>(ccx: &mut ConstantCx, def_id: DefId) {
    ccx.todo.insert(TodoItem::Static(def_id));
}

pub fn codegen_static_ref<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    static_: &Static<'tcx>,
) -> CPlace<'tcx> {
    let data_id = data_id_for_static(fx.tcx, fx.module, static_.def_id);
    cplace_for_dataid(fx, static_.ty, data_id)
}

pub fn trans_promoted<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    promoted: Promoted,
) -> CPlace<'tcx> {
    let const_ = fx
        .tcx
        .const_eval(ParamEnv::reveal_all().and(GlobalId {
            instance: fx.instance,
            promoted: Some(promoted),
        }))
        .unwrap();

    let const_ = force_eval_const(fx, const_);
    trans_const_place(fx, const_)
}

pub fn trans_constant<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    constant: &Constant<'tcx>,
) -> CValue<'tcx> {
    let const_ = fx.monomorphize(&constant.literal);
    let const_ = force_eval_const(fx, const_);
    trans_const_value(fx, const_)
}

pub fn force_eval_const<'a, 'tcx: 'a>(
    fx: &FunctionCx<'a, 'tcx, impl Backend>,
    const_: &'tcx Const<'tcx>,
) -> &'tcx Const<'tcx> {
    match const_.val {
        ConstValue::Unevaluated(def_id, ref substs) => {
            let param_env = ParamEnv::reveal_all();
            let instance = Instance::resolve(fx.tcx, param_env, def_id, substs).unwrap();
            let cid = GlobalId {
                instance,
                promoted: None,
            };
            fx.tcx.const_eval(param_env.and(cid)).unwrap()
        }
        _ => const_,
    }
}

fn trans_const_value<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    const_: &'tcx Const<'tcx>,
) -> CValue<'tcx> {
    let ty = fx.monomorphize(&const_.ty);
    let layout = fx.layout_of(ty);
    match ty.sty {
        ty::Bool => {
            let bits = const_.val.try_to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as u64 as i64)
        }
        ty::Uint(_) => {
            let bits = const_.val.try_to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as u64 as i64)
        }
        ty::Int(_) => {
            let bits = const_.val.try_to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as i128 as i64)
        }
        ty::FnDef(def_id, substs) => {
            let func_ref = fx.get_function_ref(
                Instance::resolve(fx.tcx, ParamEnv::reveal_all(), def_id, substs).unwrap(),
            );
            let func_addr = fx.bcx.ins().func_addr(fx.module.pointer_type(), func_ref);
            CValue::ByVal(func_addr, layout)
        }
        _ => trans_const_place(fx, const_).to_cvalue(fx),
    }
}

fn trans_const_place<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    const_: &'tcx Const<'tcx>,
) -> CPlace<'tcx> {
    // Adapted from https://github.com/rust-lang/rust/pull/53671/files#diff-e0b58bb6712edaa8595ad7237542c958L551
    let result = || -> EvalResult<'tcx, &'tcx Allocation> {
        let mut ecx = EvalContext::new(
            fx.tcx.at(DUMMY_SP),
            ty::ParamEnv::reveal_all(),
            TransPlaceInterpreter,
        );
        let op = ecx.const_to_op(const_)?;
        let ptr = ecx.allocate(op.layout, MemoryKind::Stack)?;
        ecx.copy_op(op, ptr.into())?;
        let alloc = ecx.memory().get(ptr.to_ptr()?.alloc_id)?;
        Ok(fx.tcx.intern_const_alloc(alloc.clone()))
    };
    let alloc = result().expect("unable to convert ConstValue to Allocation");

    //println!("const value: {:?} allocation: {:?}", value, alloc);
    let alloc_id = fx.tcx.alloc_map.lock().allocate(alloc);
    fx.constants.todo.insert(TodoItem::Alloc(alloc_id));
    let data_id = data_id_for_alloc_id(fx.module, alloc_id);
    cplace_for_dataid(fx, const_.ty, data_id)
}

fn data_id_for_alloc_id<B: Backend>(module: &mut Module<B>, alloc_id: AllocId) -> DataId {
    module
        .declare_data(&alloc_id.0.to_string(), Linkage::Local, false)
        .unwrap()
}

fn data_id_for_static<'a, 'tcx: 'a, B: Backend>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    module: &mut Module<B>,
    def_id: DefId,
) -> DataId {
    let symbol_name = tcx.symbol_name(Instance::mono(tcx, def_id)).as_str();
    let is_mutable =
        if let crate::rustc::hir::Mutability::MutMutable = tcx.is_static(def_id).unwrap() {
            true
        } else {
            !tcx.type_of(def_id)
                .is_freeze(tcx, ParamEnv::reveal_all(), DUMMY_SP)
        };
    module
        .declare_data(&*symbol_name, Linkage::Export, is_mutable)
        .unwrap()
}

fn cplace_for_dataid<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    ty: Ty<'tcx>,
    data_id: DataId,
) -> CPlace<'tcx> {
    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
    let global_ptr = fx
        .bcx
        .ins()
        .global_value(fx.module.pointer_type(), local_data_id);
    let layout = fx.layout_of(fx.monomorphize(&ty));
    assert!(!layout.is_unsized(), "unsized statics aren't supported");
    CPlace::Addr(global_ptr, None, layout)
}

fn define_all_allocs<'a, 'tcx: 'a, B: Backend + 'a>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    module: &mut Module<B>,
    cx: &mut ConstantCx,
) {
    let memory = Memory::<TransPlaceInterpreter>::new(tcx.at(DUMMY_SP));

    while let Some(todo_item) = pop_set(&mut cx.todo) {
        let (data_id, alloc) = match todo_item {
            TodoItem::Alloc(alloc_id) => {
                //println!("alloc_id {}", alloc_id);
                let data_id = data_id_for_alloc_id(module, alloc_id);
                let alloc = memory.get(alloc_id).unwrap();
                (data_id, alloc)
            }
            TodoItem::Static(def_id) => {
                //println!("static {:?}", def_id);
                let instance = ty::Instance::mono(tcx, def_id);
                let cid = GlobalId {
                    instance,
                    promoted: None,
                };
                let const_ = tcx.const_eval(ParamEnv::reveal_all().and(cid)).unwrap();

                let alloc = match const_.val {
                    ConstValue::ByRef(_alloc_id, alloc, n) if n.bytes() == 0 => alloc,
                    _ => bug!("static const eval returned {:#?}", const_),
                };

                let data_id = data_id_for_static(tcx, module, def_id);
                (data_id, alloc)
            }
        };

        //("data_id {}", data_id);
        if cx.done.contains(&data_id) {
            continue;
        }

        let mut data_ctx = DataContext::new();

        data_ctx.define(alloc.bytes.to_vec().into_boxed_slice());

        for &(offset, (_tag, reloc)) in alloc.relocations.iter() {
            let reloc_offset = {
                let endianness = tcx.data_layout.endian;
                let offset = offset.bytes() as usize;
                let ptr_size = tcx.data_layout.pointer_size;
                let bytes = &alloc.bytes[offset..offset + ptr_size.bytes() as usize];
                read_target_uint(endianness, bytes).unwrap()
            };

            let data_id = match tcx.alloc_map.lock().get(reloc).unwrap() {
                AllocType::Function(instance) => {
                    let (func_name, sig) = crate::abi::get_function_name_and_sig(tcx, instance);
                    let func_id = module
                        .declare_function(&func_name, Linkage::Import, &sig)
                        .unwrap();
                    let local_func_id = module.declare_func_in_data(func_id, &mut data_ctx);
                    data_ctx.write_function_addr(reloc_offset as u32, local_func_id);
                    continue;
                }
                AllocType::Memory(_) => {
                    cx.todo.insert(TodoItem::Alloc(reloc));
                    data_id_for_alloc_id(module, reloc)
                }
                AllocType::Static(def_id) => {
                    cx.todo.insert(TodoItem::Static(def_id));
                    data_id_for_static(tcx, module, def_id)
                }
            };

            let global_value = module.declare_data_in_data(data_id, &mut data_ctx);
            data_ctx.write_data_addr(reloc_offset as u32, global_value, 0);
        }

        module.define_data(data_id, &data_ctx).unwrap();
        cx.done.insert(data_id);
    }

    assert!(cx.todo.is_empty(), "{:?}", cx.todo);
}

fn pop_set<T: Copy + Eq + ::std::hash::Hash>(set: &mut HashSet<T>) -> Option<T> {
    if let Some(elem) = set.iter().next().map(|elem| *elem) {
        set.remove(&elem);
        Some(elem)
    } else {
        None
    }
}

struct TransPlaceInterpreter;

impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for TransPlaceInterpreter {
    type MemoryKinds = !;
    type PointerTag = ();
    type AllocExtra = ();
    type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation<()>)>;
    const STATIC_KIND: Option<!> = None;
    const ENABLE_PTR_TRACKING_HOOKS: bool = false;

    fn enforce_validity(_: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool {
        false
    }

    fn before_terminator(_: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> {
        panic!();
    }

    fn find_fn(
        _: &mut EvalContext<'a, 'mir, 'tcx, Self>,
        _: Instance<'tcx>,
        _: &[OpTy<'tcx>],
        _: Option<PlaceTy<'tcx>>,
        _: Option<BasicBlock>,
    ) -> EvalResult<'tcx, Option<&'mir Mir<'tcx>>> {
        panic!();
    }

    fn call_intrinsic(
        _: &mut EvalContext<'a, 'mir, 'tcx, Self>,
        _: Instance<'tcx>,
        _: &[OpTy<'tcx>],
        _: PlaceTy<'tcx>,
    ) -> EvalResult<'tcx> {
        panic!();
    }

    fn find_foreign_static(
        _: crate::rustc::ty::query::TyCtxtAt<'a, 'tcx, 'tcx>,
        _: DefId,
    ) -> EvalResult<'tcx, Cow<'tcx, Allocation>> {
        panic!();
    }

    fn ptr_op(
        _: &EvalContext<'a, 'mir, 'tcx, Self>,
        _: mir::BinOp,
        _: Scalar,
        _: TyLayout<'tcx>,
        _: Scalar,
        _: TyLayout<'tcx>,
    ) -> EvalResult<'tcx, (Scalar, bool)> {
        panic!();
    }

    fn box_alloc(_: &mut EvalContext<'a, 'mir, 'tcx, Self>, _: PlaceTy<'tcx>) -> EvalResult<'tcx> {
        panic!();
    }

    fn tag_reference(_: &mut EvalContext<'a, 'mir, 'tcx, Self>, _: MemPlace, _: Ty<'tcx>, _: Size, _: Option<crate::rustc::hir::Mutability>) -> EvalResult<'tcx, MemPlace> {
        panic!()
    }

    fn tag_dereference(_: &EvalContext<'a, 'mir, 'tcx, Self>, _: MemPlace, _: Ty<'tcx>, _: Size, _: Option<crate::rustc::hir::Mutability>) -> EvalResult<'tcx, MemPlace> {
        panic!();
    }

    fn adjust_static_allocation(alloc: &Allocation) -> Cow<'_, Allocation> {
        Cow::Borrowed(alloc)
    }

    fn tag_new_allocation(_: &mut EvalContext<'a, 'mir, 'tcx, Self>, ptr: Pointer, _: MemoryKind<!>) -> EvalResult<'tcx, Pointer> {
        Ok(ptr)
    }
}
<|endoftext|>


<commit_before>use log::Logger;
use log::LogRecord;
use std::io::{LineBufferedWriter, File, Writer};

pub struct FileLogger {
    file:   LineBufferedWriter<File>
}

impl FileLogger {
    pub fn new(filename: &String) -> FileLogger {
        FileLogger { file: LineBufferedWriter::new(File::create(&Path::new(filename.clone())).unwrap()) }
    }
}

impl Logger for FileLogger {
    fn log(&mut self, record: &LogRecord) {
        println!("{}:{}: {}",
            record.level, record.module_path, record.args);
        match writeln!(self.file, "{}:{}: {}",
            record.level, record.module_path, record.args) {
            _ => ()
        }
    }
}
<commit_msg>fixed error that made compilation fail<commit_after>use log::Logger;
use log::LogRecord;
use std::io::{LineBufferedWriter, File, Writer};
use std::path::BytesContainer;

pub struct FileLogger {
    file:   LineBufferedWriter<File>
}

impl FileLogger {
    pub fn new(filename: &String) -> FileLogger {
        FileLogger { file: LineBufferedWriter::new(File::create(&Path::new(filename.clone())).unwrap()) }
    }
}

impl Logger for FileLogger {
    fn log(&mut self, record: &LogRecord) {
        println!("{}:{}: {}",
            record.level, record.module_path, record.args);
        self.file.write_line(format!("{}:{}: {}",
                                     record.level,
                                     record.module_path,
                                     record.args)
            .container_as_str().unwrap());
    }
}
<|endoftext|>


<commit_before>// De-duplication macro used in src/app.rs
macro_rules! get_help {
    ($opt:ident) => {
        if let Some(h) = $opt.help {
            format!("{}{}", h,
                if let Some(ref pv) = $opt.possible_vals {
                    let mut pv_s = pv.iter().fold(String::with_capacity(50), |acc, name| {
                        acc + &format!(" {}",name)[..]
                    });
                    pv_s.shrink_to_fit();
                    format!(" [values:{}]", &pv_s[..])
                }else{"".to_owned()})
        } else {
            "    ".to_owned()
        }
    };
}

// De-duplication macro used in src/app.rs
macro_rules! parse_group_reqs {
    ($me:ident, $arg:ident) => {
        for ag in $me.groups.values() {
            let mut found = false;
            for name in ag.args.iter() {
                if name == &$arg.name {
                    $me.required.remove(ag.name);
                    if let Some(ref reqs) = ag.requires {
                        for r in reqs {
                            $me.required.insert(r);
                        }
                    }
                    if let Some(ref bl) = ag.conflicts {
                        for b in bl {
                            $me.blacklist.insert(b);
                        }
                    }
                    found = true;
                    break;
                }
            }
            if found {
                for name in ag.args.iter() {
                    if name == &$arg.name { continue }
                    $me.required.remove(name);
                    $me.blacklist.insert(name);
                }
            }
        }
    };
}

// De-duplication macro used in src/app.rs
macro_rules! validate_reqs {
    ($me:ident, $t:ident, $m:ident, $n:ident) => {
        if let Some(a) = $me.$t.get($n) {
            if let Some(ref bl) = a.blacklist {
                for n in bl.iter() {
                    if $m.args.contains_key(n) {
                        return false
                    } else if $me.groups.contains_key(n) {
                        let grp = $me.groups.get(n).unwrap();
                        for an in grp.args.iter() {
                            if $m.args.contains_key(an) {
                                return false
                            }
                        }
                    }
                }
            }
        }
    };
}

// Thanks to bluss and flan3002 in #rust IRC
//
// Helps with rightward drift when iterating over something and matching each item.
macro_rules! for_match {
    ($it:ident, $($p:pat => $($e:expr);+),*) => {
        for i in $it {
            match i {
            $(
                $p => { $($e)+ }
            )*
            }
        }
    };
}

/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr`
/// This macro returns a `Result<T,String>` which allows you as the developer to decide
/// what you'd like to do on a failed parse. There are two types of errors, parse failures
/// and those where the argument wasn't present (such as a non-required argument).
///
/// You can use it to get a single value, or a `Vec<T>` with the `values_of()`
///
/// **NOTE:** Be cautious, as since this a macro invocation it's not exactly like
/// standard syntax.
///
///
/// # Example single value
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'")
///               .get_matches();
/// let len = value_t!(matches.value_of("length"), u32)
///                 .unwrap_or_else(|e|{
///                     println!("{}",e);
///                     std::process::exit(1)
///                 });
///
/// println!("{} + 2: {}", len, len + 2);
/// # }
/// ```
///
///
/// # Example multiple values
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'")
///               .get_matches();
/// for v in value_t!(matches.values_of("seq"), u32)
///             .unwrap_or_else(|e|{
///                 println!("{}",e);
///                 std::process::exit(1)
///             }) {
///     println!("{} + 2: {}", v, v + 2);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! value_t {
    ($m:ident.value_of($v:expr), $t:ty) => {
        match $m.value_of($v) {
            Some(v) => {
                match v.parse::<$t>() {
                    Ok(val) => Ok(val),
                    Err(_)  => Err(format!("{} isn't a valid {}",v,stringify!($t))),
                }
            },
            None => Err(format!("Argument \"{}\" not found", $v))
        }
    };
    ($m:ident.values_of($v:expr), $t:ty) => {
        match $m.values_of($v) {
            Some(ref v) => {
                let mut tmp = Vec::with_capacity(v.len());
                let mut err = None;
                for pv in v {
                    match pv.parse::<$t>() {
                        Ok(rv) => tmp.push(rv),
                        Err(e) => {
                            err = Some(format!("{} isn't a valid {}\n{}",pv,stringify!($t),e));
                            break
                        }
                    }
                }
                match err {
                    Some(e) => Err(e),
                    None => Ok(tmp)
                }
            },
            None => Err(format!("Argument \"{}\" not found", $v))
        }
    };
}

/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr`
/// This macro returns a `T` or `Vec<T>` or exits with a usage string upon failure. This
/// removes some of the boiler plate to handle failures from value_t! above.
///
/// You can use it to get a single value `T`, or a `Vec<T>` with the `values_of()`
///
/// **NOTE:** This should only be used on required arguments, as it can be confusing to the user
/// why they are getting error messages when it appears they're entering all required argumetns.
///
/// **NOTE:** Be cautious, as since this a macro invocation it's not exactly like
/// standard syntax.
///
///
/// # Example single value
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'")
///               .get_matches();
/// let len = value_t_or_exit!(matches.value_of("length"), u32);
///
/// println!("{} + 2: {}", len, len + 2);
/// # }
/// ```
///
///
/// # Example multiple values
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///                   .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'")
///                   .get_matches();
/// for v in value_t_or_exit!(matches.values_of("seq"), u32) {
///     println!("{} + 2: {}", v, v + 2);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! value_t_or_exit {
    ($m:ident.value_of($v:expr), $t:ty) => {
        match $m.value_of($v) {
            Some(v) => {
                match v.parse::<$t>() {
                    Ok(val) => val,
                    Err(e)  => {
                        println!("{} isn't a valid {}\n{}\n{}\nPlease re-run with --help for \
                            more information",
                            v,
                            stringify!($t),
                            e,
                            $m.usage());
                        ::std::process::exit(1);
                    }
                }
            },
            None => {
                println!("Argument \"{}\" not found or is not valid\n{}\nPlease re-run with \
                    --help for more information",
                    $v,
                    $m.usage());
                ::std::process::exit(1);
            }
        }
    };
    ($m:ident.values_of($v:expr), $t:ty) => {
        match $m.values_of($v) {
            Some(ref v) => {
                let mut tmp = Vec::with_capacity(v.len());
                for pv in v {
                    match pv.parse::<$t>() {
                        Ok(rv) => tmp.push(rv),
                        Err(_)  => {
                            println!("{} isn't a valid {}\n{}\nPlease re-run with --help for more \
                                information",
                                pv,
                                stringify!($t),
                                $m.usage());
                            ::std::process::exit(1);
                        }
                    }
                }
                tmp
            },
            None => {
                println!("Argument \"{}\" not found or is not valid\n{}\nPlease re-run with \
                    --help for more information",
                    $v,
                    $m.usage());
                ::std::process::exit(1);
            }
        }
    };
}

/// Convenience macro generated a simple enum with variants to be used as a type when parsing
/// arguments.
///
/// # Example
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::{App, Arg};
/// simple_enum!{Foo => Bar, Baz, Qux}
/// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc
/// // and implements std::str::FromStr to use with the value_t! macros
/// fn main() {
///     let enum_vals = ["Bar", "Baz", "Qux"];
///     let m = App::new("app")
///                 .arg(Arg::from_usage("<foo> 'the foo'")
///                     .possible_values(&enum_vals))
///                 .get_matches();
///     let f = value_t_or_exit!(m.value_of("foo"), Foo);
///
///     // Use f like any other Foo variant...
/// }
/// ```
#[macro_export]
macro_rules! simple_enum {
    ($e:ident => $($v:ident),+) => {
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
}

/// Convenience macro to generate more complete enums with variants to be used as a type when
/// parsing arguments.
///
/// These enums support pub (or not) and use of the #[derive()] traits
///
///
/// # Example
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::{App, Arg};
/// arg_enum!{
///     #[derive(Debug)]
///     pub enum Foo {
///         Bar,
///         Baz,
///         Qux
///     }
/// }
/// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc
/// // and implements std::str::FromStr to use with the value_t! macros
/// fn main() {
///     let m = App::new("app")
///                 .arg_from_usage("<foo> 'the foo'")
///                 .get_matches();
///     let f = value_t_or_exit!(m.value_of("foo"), Foo);
///
///     // Use f like any other Foo variant...
/// }
/// ```
#[macro_export]
macro_rules! arg_enum {
    (enum $e:ident { $($v:ident),+ } ) => {
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (pub enum $e:ident { $($v:ident),+ } ) => {
        pub enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (#[derive($($d:ident),+)] enum $e:ident { $($v:ident),+ } ) => {
        #[derive($($d,)+)]
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (#[derive($($d:ident),+)] pub enum $e:ident { $($v:ident),+ } ) => {
        #[derive($($d,)+)]
        pub enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
}

/// Allows you pull the version for an from your Cargo.toml as MAJOR.MINOR.PATCH_PKGVERSION_PRE
///
/// # Example
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
///     let m = App::new("app")
///                 .version(crate_version!())
///                 .get_matches();
/// # }
/// ```
#[macro_export]
macro_rules! crate_version {
    () => {
        format!("{}.{}.{}{}",
            env!("CARGO_PKG_VERSION_MAJOR"),
            env!("CARGO_PKG_VERSION_MINOR"),
            env!("CARGO_PKG_VERSION_PATCH"),
            option_env!("CARGO_PKG_VERSION_PRE").unwrap_or(""))
    }
}
<commit_msg>docs(macros.rs): fixes doc tests<commit_after>// De-duplication macro used in src/app.rs
macro_rules! get_help {
    ($opt:ident) => {
        if let Some(h) = $opt.help {
            format!("{}{}", h,
                if let Some(ref pv) = $opt.possible_vals {
                    let mut pv_s = pv.iter().fold(String::with_capacity(50), |acc, name| {
                        acc + &format!(" {}",name)[..]
                    });
                    pv_s.shrink_to_fit();
                    format!(" [values:{}]", &pv_s[..])
                }else{"".to_owned()})
        } else {
            "    ".to_owned()
        }
    };
}

// De-duplication macro used in src/app.rs
macro_rules! parse_group_reqs {
    ($me:ident, $arg:ident) => {
        for ag in $me.groups.values() {
            let mut found = false;
            for name in ag.args.iter() {
                if name == &$arg.name {
                    $me.required.remove(ag.name);
                    if let Some(ref reqs) = ag.requires {
                        for r in reqs {
                            $me.required.insert(r);
                        }
                    }
                    if let Some(ref bl) = ag.conflicts {
                        for b in bl {
                            $me.blacklist.insert(b);
                        }
                    }
                    found = true;
                    break;
                }
            }
            if found {
                for name in ag.args.iter() {
                    if name == &$arg.name { continue }
                    $me.required.remove(name);
                    $me.blacklist.insert(name);
                }
            }
        }
    };
}

// De-duplication macro used in src/app.rs
macro_rules! validate_reqs {
    ($me:ident, $t:ident, $m:ident, $n:ident) => {
        if let Some(a) = $me.$t.get($n) {
            if let Some(ref bl) = a.blacklist {
                for n in bl.iter() {
                    if $m.args.contains_key(n) {
                        return false
                    } else if $me.groups.contains_key(n) {
                        let grp = $me.groups.get(n).unwrap();
                        for an in grp.args.iter() {
                            if $m.args.contains_key(an) {
                                return false
                            }
                        }
                    }
                }
            }
        }
    };
}

// Thanks to bluss and flan3002 in #rust IRC
//
// Helps with rightward drift when iterating over something and matching each item.
macro_rules! for_match {
    ($it:ident, $($p:pat => $($e:expr);+),*) => {
        for i in $it {
            match i {
            $(
                $p => { $($e)+ }
            )*
            }
        }
    };
}

/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr`
/// This macro returns a `Result<T,String>` which allows you as the developer to decide
/// what you'd like to do on a failed parse. There are two types of errors, parse failures
/// and those where the argument wasn't present (such as a non-required argument).
///
/// You can use it to get a single value, or a `Vec<T>` with the `values_of()`
///
/// **NOTE:** Be cautious, as since this a macro invocation it's not exactly like
/// standard syntax.
///
///
/// # Example single value
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'")
///               .get_matches();
/// let len = value_t!(matches.value_of("length"), u32)
///                 .unwrap_or_else(|e|{
///                     println!("{}",e);
///                     std::process::exit(1)
///                 });
///
/// println!("{} + 2: {}", len, len + 2);
/// # }
/// ```
///
///
/// # Example multiple values
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'")
///               .get_matches();
/// for v in value_t!(matches.values_of("seq"), u32)
///             .unwrap_or_else(|e|{
///                 println!("{}",e);
///                 std::process::exit(1)
///             }) {
///     println!("{} + 2: {}", v, v + 2);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! value_t {
    ($m:ident.value_of($v:expr), $t:ty) => {
        match $m.value_of($v) {
            Some(v) => {
                match v.parse::<$t>() {
                    Ok(val) => Ok(val),
                    Err(_)  => Err(format!("{} isn't a valid {}",v,stringify!($t))),
                }
            },
            None => Err(format!("Argument \"{}\" not found", $v))
        }
    };
    ($m:ident.values_of($v:expr), $t:ty) => {
        match $m.values_of($v) {
            Some(ref v) => {
                let mut tmp = Vec::with_capacity(v.len());
                let mut err = None;
                for pv in v {
                    match pv.parse::<$t>() {
                        Ok(rv) => tmp.push(rv),
                        Err(e) => {
                            err = Some(format!("{} isn't a valid {}\n{}",pv,stringify!($t),e));
                            break
                        }
                    }
                }
                match err {
                    Some(e) => Err(e),
                    None => Ok(tmp)
                }
            },
            None => Err(format!("Argument \"{}\" not found", $v))
        }
    };
}

/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr`
/// This macro returns a `T` or `Vec<T>` or exits with a usage string upon failure. This
/// removes some of the boiler plate to handle failures from value_t! above.
///
/// You can use it to get a single value `T`, or a `Vec<T>` with the `values_of()`
///
/// **NOTE:** This should only be used on required arguments, as it can be confusing to the user
/// why they are getting error messages when it appears they're entering all required argumetns.
///
/// **NOTE:** Be cautious, as since this a macro invocation it's not exactly like
/// standard syntax.
///
///
/// # Example single value
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'")
///               .get_matches();
/// let len = value_t_or_exit!(matches.value_of("length"), u32);
///
/// println!("{} + 2: {}", len, len + 2);
/// # }
/// ```
///
///
/// # Example multiple values
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///                   .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'")
///                   .get_matches();
/// for v in value_t_or_exit!(matches.values_of("seq"), u32) {
///     println!("{} + 2: {}", v, v + 2);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! value_t_or_exit {
    ($m:ident.value_of($v:expr), $t:ty) => {
        match $m.value_of($v) {
            Some(v) => {
                match v.parse::<$t>() {
                    Ok(val) => val,
                    Err(e)  => {
                        println!("{} isn't a valid {}\n{}\n{}\nPlease re-run with --help for \
                            more information",
                            v,
                            stringify!($t),
                            e,
                            $m.usage());
                        ::std::process::exit(1);
                    }
                }
            },
            None => {
                println!("Argument \"{}\" not found or is not valid\n{}\nPlease re-run with \
                    --help for more information",
                    $v,
                    $m.usage());
                ::std::process::exit(1);
            }
        }
    };
    ($m:ident.values_of($v:expr), $t:ty) => {
        match $m.values_of($v) {
            Some(ref v) => {
                let mut tmp = Vec::with_capacity(v.len());
                for pv in v {
                    match pv.parse::<$t>() {
                        Ok(rv) => tmp.push(rv),
                        Err(_)  => {
                            println!("{} isn't a valid {}\n{}\nPlease re-run with --help for more \
                                information",
                                pv,
                                stringify!($t),
                                $m.usage());
                            ::std::process::exit(1);
                        }
                    }
                }
                tmp
            },
            None => {
                println!("Argument \"{}\" not found or is not valid\n{}\nPlease re-run with \
                    --help for more information",
                    $v,
                    $m.usage());
                ::std::process::exit(1);
            }
        }
    };
}

/// Convenience macro generated a simple enum with variants to be used as a type when parsing
/// arguments.
///
/// # Example
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::{App, Arg};
/// simple_enum!{Foo => Bar, Baz, Qux}
/// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc
/// // and implements std::str::FromStr to use with the value_t! macros
/// fn main() {
///     let enum_vals = ["Bar", "Baz", "Qux"];
///     let m = App::new("app")
///                 .arg(Arg::from_usage("<foo> 'the foo'")
///                     .possible_values(&enum_vals))
///                 .get_matches();
///     let f = value_t_or_exit!(m.value_of("foo"), Foo);
///
///     // Use f like any other Foo variant...
/// }
/// ```
#[macro_export]
macro_rules! simple_enum {
    ($e:ident => $($v:ident),+) => {
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
}

/// Convenience macro to generate more complete enums with variants to be used as a type when
/// parsing arguments.
///
/// These enums support pub (or not) and use of the #[derive()] traits
///
///
/// # Example
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::{App, Arg};
/// arg_enum!{
///     #[derive(Debug)]
///     pub enum Foo {
///         Bar,
///         Baz,
///         Qux
///     }
/// }
/// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc
/// // and implements std::str::FromStr to use with the value_t! macros
/// fn main() {
///     let m = App::new("app")
///                 .arg_from_usage("<foo> 'the foo'")
///                 .get_matches();
///     let f = value_t_or_exit!(m.value_of("foo"), Foo);
///
///     // Use f like any other Foo variant...
/// }
/// ```
#[macro_export]
macro_rules! arg_enum {
    (enum $e:ident { $($v:ident),+ } ) => {
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (pub enum $e:ident { $($v:ident),+ } ) => {
        pub enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (#[derive($($d:ident),+)] enum $e:ident { $($v:ident),+ } ) => {
        #[derive($($d,)+)]
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (#[derive($($d:ident),+)] pub enum $e:ident { $($v:ident),+ } ) => {
        #[derive($($d,)+)]
        pub enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
}

/// Allows you pull the version for an from your Cargo.toml as MAJOR.MINOR.PATCH_PKGVERSION_PRE
///
/// # Example
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
///     let m = App::new("app")
///                 .version(&crate_version!()[..])
///                 .get_matches();
/// # }
/// ```
#[macro_export]
macro_rules! crate_version {
    () => {
        format!("{}.{}.{}{}",
            env!("CARGO_PKG_VERSION_MAJOR"),
            env!("CARGO_PKG_VERSION_MINOR"),
            env!("CARGO_PKG_VERSION_PATCH"),
            option_env!("CARGO_PKG_VERSION_PRE").unwrap_or(""))
    }
}
<|endoftext|>