<commit_before>#![feature(box_syntax)]
#[test]
fn it_works() {
}

mod SVM {

    /// Singly-linked cons list.
    ///
    /// This is used internally to represent list primitives in the machine.
    pub enum List<T> {
        Nil,
        Cons(T, Box<List<T>>)
    }

    /// Public implementation for List.
    impl<T> List<T> {

        /// Creates a new empty list
        fn new() -> List<T> {
            List::Nil
        }

        /// Prepends the given item to the list
        fn prepend(self, it: T) -> List<T> {
            List::Cons(it, box self)
        }

        /// Returns the length of the list
        fn length (&self) -> i32 {
            match *self {
                List::Cons(_, ref tail) => 1 + tail.length(),
                List::Nil => 0
            }
        }

    }

    enum Exp {
        Number(i32)
    }

    struct Engine {
        stack: Vec<Exp>
    }
}
<commit_msg>Reorganize namespaces in svm<commit_after>#![feature(box_syntax)]
#[test]
fn it_works() {
}

pub mod svm {
    mod slist {
        use svm::slist::List::{Cons,Nil};
        /// Singly-linked cons list.
        ///
        /// This is used internally to represent list primitives in the machine.
        enum List<T> {
            Nil,
            Cons(T, Box<List<T>>)
        }

        /// Public implementation for List.
        impl<T> List<T> {

            /// Creates a new empty list
            fn new() -> List<T> {
                Nil
            }

            /// Prepends the given item to the list
            fn prepend(self, it: T) -> List<T> {
                Cons(it, box self)
            }

            /// Returns the length of the list
            fn length (&self) -> i32 {
                match *self {
                    Cons(_, ref tail) => 1 + tail.length(),
                    Nil => 0
                }
            }
        }
    }

    enum Exp {
        Number(i32)
    }

    struct Engine {
        stack: Vec<Exp>
    }
}
<|endoftext|>


<commit_before>use rustc::hir::intravisit::FnKind;
use rustc::hir::def_id::DefId;
use rustc::hir;
use rustc::lint::*;
use rustc::ty::{self, Ty};
use syntax::ast;
use syntax::codemap::Span;
use utils::paths;
use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then};
use utils::sugg::DiagnosticBuilderExt;

/// **What it does:** Checks for types with a `fn new() -> Self` method and no
/// implementation of
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html).
///
/// **Why is this bad?** The user might expect to be able to use
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the
/// type can be constructed without arguments.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
///
/// ```rust,ignore
/// struct Foo(Bar);
///
/// impl Foo {
///     fn new() -> Self {
///         Foo(Bar::new())
///     }
/// }
/// ```
///
/// Instead, use:
///
/// ```rust
/// struct Foo(Bar);
///
/// impl Default for Foo {
///     fn default() -> Self {
///         Foo(Bar::new())
///     }
/// }
/// ```
///
/// You can also have `new()` call `Default::default()`.
declare_lint! {
    pub NEW_WITHOUT_DEFAULT,
    Warn,
    "`fn new() -> Self` method without `Default` implementation"
}

/// **What it does:** Checks for types with a `fn new() -> Self` method
/// and no implementation of
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html),
/// where the `Default` can be derived by `#[derive(Default)]`.
///
/// **Why is this bad?** The user might expect to be able to use
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the
/// type can be constructed without arguments.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
///
/// ```rust,ignore
/// struct Foo;
///
/// impl Foo {
///     fn new() -> Self {
///         Foo
///     }
/// }
/// ```
///
/// Just prepend `#[derive(Default)]` before the `struct` definition.
declare_lint! {
    pub NEW_WITHOUT_DEFAULT_DERIVE,
    Warn,
    "`fn new() -> Self` without `#[derive]`able `Default` implementation"
}

#[derive(Copy, Clone)]
pub struct NewWithoutDefault;

impl LintPass for NewWithoutDefault {
    fn get_lints(&self) -> LintArray {
        lint_array!(NEW_WITHOUT_DEFAULT, NEW_WITHOUT_DEFAULT_DERIVE)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        kind: FnKind<'tcx>,
        decl: &'tcx hir::FnDecl,
        _: &'tcx hir::Body,
        span: Span,
        id: ast::NodeId,
    ) {
        if in_external_macro(cx, span) {
            return;
        }

        if let FnKind::Method(name, sig, _, _) = kind {
            if sig.constness == hir::Constness::Const {
                // can't be implemented by default
                return;
            }
            if !cx.generics.expect("method must have generics").ty_params.is_empty() {
               // when the result of `new()` depends on a type parameter we should not require
               // an
               // impl of `Default`
               return;
            }
            if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
                let self_ty = cx.tcx
                    .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)));
                if_chain! {
                                    if same_tys(cx, self_ty, return_ty(cx, id));
                                    if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
                                    if !implements_trait(cx, self_ty, default_trait_id, &[]);
                                    then {
                                        if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
                                            span_lint_and_then(cx,
                                                               NEW_WITHOUT_DEFAULT_DERIVE, span,
                                                               &format!("you should consider deriving a \
                                                                         `Default` implementation for `{}`",
                                                                        self_ty),
                                                               |db| {
                                                db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]");
                                            });
                                        } else {
                                            span_lint_and_then(cx,
                                                               NEW_WITHOUT_DEFAULT, span,
                                                               &format!("you should consider adding a \
                                                                        `Default` implementation for `{}`",
                                                                        self_ty),
                                                               |db| {
                                            db.suggest_prepend_item(cx,
                                                                      span,
                                                                      "try this",
                                                                      &format!(
"impl Default for {} {{
    fn default() -> Self {{
        Self::new()
    }}
}}",
                                                                               self_ty));
                                            });
                                        }
                                    }
                }
            }
        }
    }
}

fn can_derive_default<'t, 'c>(ty: Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option<Span> {
    match ty.sty {
        ty::TyAdt(adt_def, substs) if adt_def.is_struct() => {
            for field in adt_def.all_fields() {
                let f_ty = field.ty(cx.tcx, substs);
                if !implements_trait(cx, f_ty, default_trait_id, &[]) {
                    return None;
                }
            }
            Some(cx.tcx.def_span(adt_def.did))
        },
        _ => None,
    }
}
<commit_msg>Fix excessive indentation in if_chain!<commit_after>use rustc::hir::intravisit::FnKind;
use rustc::hir::def_id::DefId;
use rustc::hir;
use rustc::lint::*;
use rustc::ty::{self, Ty};
use syntax::ast;
use syntax::codemap::Span;
use utils::paths;
use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then};
use utils::sugg::DiagnosticBuilderExt;

/// **What it does:** Checks for types with a `fn new() -> Self` method and no
/// implementation of
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html).
///
/// **Why is this bad?** The user might expect to be able to use
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the
/// type can be constructed without arguments.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
///
/// ```rust,ignore
/// struct Foo(Bar);
///
/// impl Foo {
///     fn new() -> Self {
///         Foo(Bar::new())
///     }
/// }
/// ```
///
/// Instead, use:
///
/// ```rust
/// struct Foo(Bar);
///
/// impl Default for Foo {
///     fn default() -> Self {
///         Foo(Bar::new())
///     }
/// }
/// ```
///
/// You can also have `new()` call `Default::default()`.
declare_lint! {
    pub NEW_WITHOUT_DEFAULT,
    Warn,
    "`fn new() -> Self` method without `Default` implementation"
}

/// **What it does:** Checks for types with a `fn new() -> Self` method
/// and no implementation of
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html),
/// where the `Default` can be derived by `#[derive(Default)]`.
///
/// **Why is this bad?** The user might expect to be able to use
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the
/// type can be constructed without arguments.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
///
/// ```rust,ignore
/// struct Foo;
///
/// impl Foo {
///     fn new() -> Self {
///         Foo
///     }
/// }
/// ```
///
/// Just prepend `#[derive(Default)]` before the `struct` definition.
declare_lint! {
    pub NEW_WITHOUT_DEFAULT_DERIVE,
    Warn,
    "`fn new() -> Self` without `#[derive]`able `Default` implementation"
}

#[derive(Copy, Clone)]
pub struct NewWithoutDefault;

impl LintPass for NewWithoutDefault {
    fn get_lints(&self) -> LintArray {
        lint_array!(NEW_WITHOUT_DEFAULT, NEW_WITHOUT_DEFAULT_DERIVE)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        kind: FnKind<'tcx>,
        decl: &'tcx hir::FnDecl,
        _: &'tcx hir::Body,
        span: Span,
        id: ast::NodeId,
    ) {
        if in_external_macro(cx, span) {
            return;
        }

        if let FnKind::Method(name, sig, _, _) = kind {
            if sig.constness == hir::Constness::Const {
                // can't be implemented by default
                return;
            }
            if !cx.generics.expect("method must have generics").ty_params.is_empty() {
               // when the result of `new()` depends on a type parameter we should not require
               // an
               // impl of `Default`
               return;
            }
            if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
                let self_ty = cx.tcx
                    .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)));
                if_chain! {
                    if same_tys(cx, self_ty, return_ty(cx, id));
                    if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
                    if !implements_trait(cx, self_ty, default_trait_id, &[]);
                    then {
                        if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
                            span_lint_and_then(
                                cx,
                                NEW_WITHOUT_DEFAULT_DERIVE,
                                span,
                                &format!("you should consider deriving a `Default` implementation for `{}`", self_ty),
                                |db| {
                                    db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]");
                                });
                        } else {
                            span_lint_and_then(
                                cx,
                                NEW_WITHOUT_DEFAULT,
                                span,
                                &format!("you should consider adding a `Default` implementation for `{}`", self_ty),
                                |db| {
                                    db.suggest_prepend_item(cx, span, "try this", &create_new_without_default_suggest_msg(self_ty));
                                },
                            );
                        }
                    }
                }
            }
        }
    }
}

fn create_new_without_default_suggest_msg(ty: Ty) -> String {
    #[rustfmt_skip]
    format!(
"impl Default for {} {{
    fn default() -> Self {{
        Self::new()
    }}
}}", ty)
}

fn can_derive_default<'t, 'c>(ty: Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option<Span> {
    match ty.sty {
        ty::TyAdt(adt_def, substs) if adt_def.is_struct() => {
            for field in adt_def.all_fields() {
                let f_ty = field.ty(cx.tcx, substs);
                if !implements_trait(cx, f_ty, default_trait_id, &[]) {
                    return None;
                }
            }
            Some(cx.tcx.def_span(adt_def.did))
        },
        _ => None,
    }
}
<|endoftext|>


<commit_before>use crate::error::Error;
use crate::module::{
    AddrDetails, GlobalSpec, HeapSpec, Module, ModuleInternal, TableElement, TrapManifestRecord,
};
use libc::c_void;
use libloading::{Library, Symbol};
use lucet_module_data::ModuleData;
use std::ffi::CStr;
use std::mem;
use std::path::Path;
use std::slice;
use std::slice::from_raw_parts;
use std::sync::Arc;

/// A Lucet module backed by a dynamically-loaded shared object.
pub struct DlModule {
    lib: Library,

    /// Base address of the dynamically-loaded module
    fbase: *const c_void,

    /// Metadata decoded from inside the module
    module_data: ModuleData<'static>,

    trap_manifest: &'static [TrapManifestRecord],
}

// for the one raw pointer only
unsafe impl Send for DlModule {}
unsafe impl Sync for DlModule {}

impl DlModule {
    /// Create a module, loading code from a shared object on the filesystem.
    pub fn load<P: AsRef<Path>>(so_path: P) -> Result<Arc<Self>, Error> {
        // Load the dynamic library. The undefined symbols corresponding to the lucet_syscall_
        // functions will be provided by the current executable.  We trust our wasm->dylib compiler
        // to make sure these function calls are the way the dylib can touch memory outside of its
        // stack and heap.
        let abs_so_path = so_path.as_ref().canonicalize().map_err(Error::DlError)?;
        let lib = Library::new(abs_so_path.as_os_str()).map_err(Error::DlError)?;

        let module_data_ptr = unsafe {
            lib.get::<*const u8>(b"lucet_module_data").map_err(|e| {
                lucet_incorrect_module!("error loading required symbol `lucet_module_data`: {}", e)
            })?
        };

        let module_data_len = unsafe {
            lib.get::<usize>(b"lucet_module_data_len").map_err(|e| {
                lucet_incorrect_module!(
                    "error loading required symbol `lucet_module_data_len`: {}",
                    e
                )
            })?
        };

        // Deserialize the slice into ModuleData, which will hold refs into the loaded
        // shared object file in `module_data_slice`. Both of these get a 'static lifetime because
        // Rust doesn't have a safe way to describe that their lifetime matches the containing
        // struct (and the dll).
        //
        // The exposed lifetime of ModuleData will be the same as the lifetime of the
        // dynamically loaded library. This makes the interface safe.
        let module_data_slice: &'static [u8] =
            unsafe { slice::from_raw_parts(*module_data_ptr, *module_data_len) };
        let module_data = ModuleData::deserialize(module_data_slice)?;

        let fbase = if let Some(dli) = dladdr(*module_data_ptr as *const c_void) {
            dli.dli_fbase
        } else {
            std::ptr::null()
        };

        let trap_manifest = unsafe {
            if let Ok(len_ptr) = lib.get::<*const u32>(b"lucet_trap_manifest_len") {
                let len = len_ptr.as_ref().ok_or(lucet_incorrect_module!(
                    "`lucet_trap_manifest_len` is defined but null"
                ))?;
                let records = lib
                    .get::<*const TrapManifestRecord>(b"lucet_trap_manifest")
                    .map_err(|e| {
                        lucet_incorrect_module!("error loading symbol `lucet_trap_manifest`: {}", e)
                    })?
                    .as_ref()
                    .ok_or(lucet_incorrect_module!(
                        "`lucet_trap_manifest` is defined but null"
                    ))?;
                from_raw_parts(records, *len as usize)
            } else {
                &[]
            }
        };

        Ok(Arc::new(DlModule {
            lib,
            fbase,
            module_data,
            trap_manifest,
        }))
    }
}

impl Module for DlModule {}

impl ModuleInternal for DlModule {
    fn heap_spec(&self) -> Option<&HeapSpec> {
        self.module_data.heap_spec()
    }

    fn globals(&self) -> &[GlobalSpec] {
        self.module_data.globals_spec()
    }

    fn get_sparse_page_data(&self, page: usize) -> Option<&[u8]> {
        if let Some(ref sparse_data) = self.module_data.sparse_data() {
            *sparse_data.get_page(page)
        } else {
            None
        }
    }

    fn sparse_page_data_len(&self) -> usize {
        self.module_data.sparse_data().map(|d| d.len()).unwrap_or(0)
    }

    fn table_elements(&self) -> Result<&[TableElement], Error> {
        let p_table_segment: Symbol<*const TableElement> = unsafe {
            self.lib.get(b"guest_table_0").map_err(|e| {
                lucet_incorrect_module!("error loading required symbol `guest_table_0`: {}", e)
            })?
        };
        let p_table_segment_len: Symbol<*const usize> = unsafe {
            self.lib.get(b"guest_table_0_len").map_err(|e| {
                lucet_incorrect_module!("error loading required symbol `guest_table_0_len`: {}", e)
            })?
        };
        let len = unsafe { **p_table_segment_len };
        if len > std::u32::MAX as usize {
            lucet_incorrect_module!("table segment too long: {}", len);
        }
        Ok(unsafe { from_raw_parts(*p_table_segment, **p_table_segment_len as usize) })
    }

    fn get_export_func(&self, sym: &[u8]) -> Result<*const extern "C" fn(), Error> {
        let mut guest_sym: Vec<u8> = b"guest_func_".to_vec();
        guest_sym.extend_from_slice(sym);
        match unsafe { self.lib.get::<*const extern "C" fn()>(&guest_sym) } {
            Err(ref e) if is_undefined_symbol(e) => Err(Error::SymbolNotFound(
                String::from_utf8_lossy(sym).into_owned(),
            )),
            Err(e) => Err(Error::DlError(e)),
            Ok(f) => Ok(*f),
        }
    }

    fn get_func_from_idx(
        &self,
        table_id: u32,
        func_id: u32,
    ) -> Result<*const extern "C" fn(), Error> {
        if table_id != 0 {
            return Err(Error::FuncNotFound(table_id, func_id));
        }
        let table = self.table_elements()?;
        let func: extern "C" fn() = table
            .get(func_id as usize)
            .map(|element| unsafe { std::mem::transmute(element.rf) })
            .ok_or(Error::FuncNotFound(table_id, func_id))?;
        Ok(&func as *const extern "C" fn())
    }

    fn get_start_func(&self) -> Result<Option<*const extern "C" fn()>, Error> {
        // `guest_start` is a pointer to the function the module designates as the start function,
        // since we can't have multiple symbols pointing to the same function and guest code might
        // call it in the normal course of execution
        if let Ok(start_func) = unsafe {
            self.lib
                .get::<*const *const extern "C" fn()>(b"guest_start")
        } {
            if start_func.is_null() {
                lucet_incorrect_module!("`guest_start` is defined but null");
            }
            Ok(Some(unsafe { **start_func }))
        } else {
            Ok(None)
        }
    }

    fn trap_manifest(&self) -> &[TrapManifestRecord] {
        self.trap_manifest
    }

    fn addr_details(&self, addr: *const c_void) -> Result<Option<AddrDetails>, Error> {
        if let Some(dli) = dladdr(addr) {
            let file_name = if dli.dli_fname.is_null() {
                None
            } else {
                Some(unsafe { CStr::from_ptr(dli.dli_fname).to_owned().into_string()? })
            };
            let sym_name = if dli.dli_sname.is_null() {
                None
            } else {
                Some(unsafe { CStr::from_ptr(dli.dli_sname).to_owned().into_string()? })
            };
            Ok(Some(AddrDetails {
                in_module_code: dli.dli_fbase as *const c_void == self.fbase,
                file_name,
                sym_name,
            }))
        } else {
            Ok(None)
        }
    }
}

fn is_undefined_symbol(e: &std::io::Error) -> bool {
    // gross, but I'm not sure how else to differentiate this type of error from other
    // IO errors
    format!("{}", e).contains("undefined symbol")
}

// TODO: PR to nix or libloading?
// TODO: possibly not safe to use without grabbing the mutex within libloading::Library?
fn dladdr(addr: *const c_void) -> Option<libc::Dl_info> {
    let mut info = unsafe { mem::uninitialized::<libc::Dl_info>() };
    let res = unsafe { libc::dladdr(addr, &mut info as *mut libc::Dl_info) };
    if res != 0 {
        Some(info)
    } else {
        None
    }
}
<commit_msg>Unfortunately, error strings are not very portable<commit_after>use crate::error::Error;
use crate::module::{
    AddrDetails, GlobalSpec, HeapSpec, Module, ModuleInternal, TableElement, TrapManifestRecord,
};
use libc::c_void;
use libloading::{Library, Symbol};
use lucet_module_data::ModuleData;
use std::ffi::CStr;
use std::mem;
use std::path::Path;
use std::slice;
use std::slice::from_raw_parts;
use std::sync::Arc;

/// A Lucet module backed by a dynamically-loaded shared object.
pub struct DlModule {
    lib: Library,

    /// Base address of the dynamically-loaded module
    fbase: *const c_void,

    /// Metadata decoded from inside the module
    module_data: ModuleData<'static>,

    trap_manifest: &'static [TrapManifestRecord],
}

// for the one raw pointer only
unsafe impl Send for DlModule {}
unsafe impl Sync for DlModule {}

impl DlModule {
    /// Create a module, loading code from a shared object on the filesystem.
    pub fn load<P: AsRef<Path>>(so_path: P) -> Result<Arc<Self>, Error> {
        // Load the dynamic library. The undefined symbols corresponding to the lucet_syscall_
        // functions will be provided by the current executable.  We trust our wasm->dylib compiler
        // to make sure these function calls are the way the dylib can touch memory outside of its
        // stack and heap.
        let abs_so_path = so_path.as_ref().canonicalize().map_err(Error::DlError)?;
        let lib = Library::new(abs_so_path.as_os_str()).map_err(Error::DlError)?;

        let module_data_ptr = unsafe {
            lib.get::<*const u8>(b"lucet_module_data").map_err(|e| {
                lucet_incorrect_module!("error loading required symbol `lucet_module_data`: {}", e)
            })?
        };

        let module_data_len = unsafe {
            lib.get::<usize>(b"lucet_module_data_len").map_err(|e| {
                lucet_incorrect_module!(
                    "error loading required symbol `lucet_module_data_len`: {}",
                    e
                )
            })?
        };

        // Deserialize the slice into ModuleData, which will hold refs into the loaded
        // shared object file in `module_data_slice`. Both of these get a 'static lifetime because
        // Rust doesn't have a safe way to describe that their lifetime matches the containing
        // struct (and the dll).
        //
        // The exposed lifetime of ModuleData will be the same as the lifetime of the
        // dynamically loaded library. This makes the interface safe.
        let module_data_slice: &'static [u8] =
            unsafe { slice::from_raw_parts(*module_data_ptr, *module_data_len) };
        let module_data = ModuleData::deserialize(module_data_slice)?;

        let fbase = if let Some(dli) = dladdr(*module_data_ptr as *const c_void) {
            dli.dli_fbase
        } else {
            std::ptr::null()
        };

        let trap_manifest = unsafe {
            if let Ok(len_ptr) = lib.get::<*const u32>(b"lucet_trap_manifest_len") {
                let len = len_ptr.as_ref().ok_or(lucet_incorrect_module!(
                    "`lucet_trap_manifest_len` is defined but null"
                ))?;
                let records = lib
                    .get::<*const TrapManifestRecord>(b"lucet_trap_manifest")
                    .map_err(|e| {
                        lucet_incorrect_module!("error loading symbol `lucet_trap_manifest`: {}", e)
                    })?
                    .as_ref()
                    .ok_or(lucet_incorrect_module!(
                        "`lucet_trap_manifest` is defined but null"
                    ))?;
                from_raw_parts(records, *len as usize)
            } else {
                &[]
            }
        };

        Ok(Arc::new(DlModule {
            lib,
            fbase,
            module_data,
            trap_manifest,
        }))
    }
}

impl Module for DlModule {}

impl ModuleInternal for DlModule {
    fn heap_spec(&self) -> Option<&HeapSpec> {
        self.module_data.heap_spec()
    }

    fn globals(&self) -> &[GlobalSpec] {
        self.module_data.globals_spec()
    }

    fn get_sparse_page_data(&self, page: usize) -> Option<&[u8]> {
        if let Some(ref sparse_data) = self.module_data.sparse_data() {
            *sparse_data.get_page(page)
        } else {
            None
        }
    }

    fn sparse_page_data_len(&self) -> usize {
        self.module_data.sparse_data().map(|d| d.len()).unwrap_or(0)
    }

    fn table_elements(&self) -> Result<&[TableElement], Error> {
        let p_table_segment: Symbol<*const TableElement> = unsafe {
            self.lib.get(b"guest_table_0").map_err(|e| {
                lucet_incorrect_module!("error loading required symbol `guest_table_0`: {}", e)
            })?
        };
        let p_table_segment_len: Symbol<*const usize> = unsafe {
            self.lib.get(b"guest_table_0_len").map_err(|e| {
                lucet_incorrect_module!("error loading required symbol `guest_table_0_len`: {}", e)
            })?
        };
        let len = unsafe { **p_table_segment_len };
        if len > std::u32::MAX as usize {
            lucet_incorrect_module!("table segment too long: {}", len);
        }
        Ok(unsafe { from_raw_parts(*p_table_segment, **p_table_segment_len as usize) })
    }

    fn get_export_func(&self, sym: &[u8]) -> Result<*const extern "C" fn(), Error> {
        let mut guest_sym: Vec<u8> = b"guest_func_".to_vec();
        guest_sym.extend_from_slice(sym);
        match unsafe { self.lib.get::<*const extern "C" fn()>(&guest_sym) } {
            Err(ref e) if is_undefined_symbol(e) => Err(Error::SymbolNotFound(
                String::from_utf8_lossy(sym).into_owned(),
            )),
            Err(e) => Err(Error::DlError(e)),
            Ok(f) => Ok(*f),
        }
    }

    fn get_func_from_idx(
        &self,
        table_id: u32,
        func_id: u32,
    ) -> Result<*const extern "C" fn(), Error> {
        if table_id != 0 {
            return Err(Error::FuncNotFound(table_id, func_id));
        }
        let table = self.table_elements()?;
        let func: extern "C" fn() = table
            .get(func_id as usize)
            .map(|element| unsafe { std::mem::transmute(element.rf) })
            .ok_or(Error::FuncNotFound(table_id, func_id))?;
        Ok(&func as *const extern "C" fn())
    }

    fn get_start_func(&self) -> Result<Option<*const extern "C" fn()>, Error> {
        // `guest_start` is a pointer to the function the module designates as the start function,
        // since we can't have multiple symbols pointing to the same function and guest code might
        // call it in the normal course of execution
        if let Ok(start_func) = unsafe {
            self.lib
                .get::<*const *const extern "C" fn()>(b"guest_start")
        } {
            if start_func.is_null() {
                lucet_incorrect_module!("`guest_start` is defined but null");
            }
            Ok(Some(unsafe { **start_func }))
        } else {
            Ok(None)
        }
    }

    fn trap_manifest(&self) -> &[TrapManifestRecord] {
        self.trap_manifest
    }

    fn addr_details(&self, addr: *const c_void) -> Result<Option<AddrDetails>, Error> {
        if let Some(dli) = dladdr(addr) {
            let file_name = if dli.dli_fname.is_null() {
                None
            } else {
                Some(unsafe { CStr::from_ptr(dli.dli_fname).to_owned().into_string()? })
            };
            let sym_name = if dli.dli_sname.is_null() {
                None
            } else {
                Some(unsafe { CStr::from_ptr(dli.dli_sname).to_owned().into_string()? })
            };
            Ok(Some(AddrDetails {
                in_module_code: dli.dli_fbase as *const c_void == self.fbase,
                file_name,
                sym_name,
            }))
        } else {
            Ok(None)
        }
    }
}

fn is_undefined_symbol(e: &std::io::Error) -> bool {
    // gross, but I'm not sure how else to differentiate this type of error from other
    // IO errors
    let msg = format!("{}", e);
    msg.contains("undefined symbol") || msg.contains("symbol not found")
}

// TODO: PR to nix or libloading?
// TODO: possibly not safe to use without grabbing the mutex within libloading::Library?
fn dladdr(addr: *const c_void) -> Option<libc::Dl_info> {
    let mut info = unsafe { mem::uninitialized::<libc::Dl_info>() };
    let res = unsafe { libc::dladdr(addr, &mut info as *mut libc::Dl_info) };
    if res != 0 {
        Some(info)
    } else {
        None
    }
}
<|endoftext|>


<commit_before>use core::arch::x86_64 as arch;
use std::env;
use std::f64::consts::PI;
use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Instant;
use std::vec;

/*mod laplace;
mod matmul;

pub use matmul::test_matmul_strassen;*/

#[inline]
fn get_timestamp_rdtscp() -> u64 {
	unsafe {
		let mut _aux = 0;
		let value = arch::__rdtscp(&mut _aux);
		arch::_mm_lfence();
		value
	}
}

pub fn thread_creation() -> Result<(), ()> {
	let n = 1000;

	// cache warmup
	let _ = get_timestamp_rdtscp();

	let mut sum: u64 = 0;
	for _ in 0..n {
		let builder = thread::Builder::new();
		let start = get_timestamp_rdtscp();
		let child = builder.spawn(|| get_timestamp_rdtscp()).unwrap();
		thread::yield_now();
		match child.join() {
			Ok(end) => {
				sum += end - start;
			}
			Err(_) => {
				println!("Unable to join thread!");
			}
		}
	}

	println!("Time to create a thread {} ticks", sum / n);

	Ok(())
}

pub fn bench_sched_one_thread() -> Result<(), ()> {
	let n = 1000000;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp_rdtscp();

	let start = get_timestamp_rdtscp();
	for _ in 0..n {
		thread::yield_now();
	}
	let ticks = get_timestamp_rdtscp() - start;

	println!("Scheduling time {} ticks (1 thread)", ticks / n);

	Ok(())
}

pub fn bench_sched_two_threads() -> Result<(), ()> {
	let n = 1000000;
	let nthreads = 2;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp_rdtscp();

	let start = get_timestamp_rdtscp();
	let threads: Vec<_> = (0..nthreads - 1)
		.map(|_| {
			thread::spawn(move || {
				for _ in 0..n {
					thread::yield_now();
				}
			})
		})
		.collect();

	for _ in 0..n {
		thread::yield_now();
	}

	let ticks = get_timestamp_rdtscp() - start;

	for t in threads {
		t.join().unwrap();
	}

	println!(
		"Scheduling time {} ticks (2 threads)",
		ticks / (nthreads * n)
	);

	Ok(())
}

pub fn pi_sequential(num_steps: u64) -> Result<(), ()> {
	let step = 1.0 / num_steps as f64;
	let mut sum = 0 as f64;

	for i in 0..num_steps {
		let x = (i as f64 + 0.5) * step;
		sum += 4.0 / (1.0 + x * x);
	}

	let mypi = sum * (1.0 / num_steps as f64);
	println!("Pi: {} (sequential)", mypi);

	if (mypi - PI).abs() < 0.00001 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn pi_parallel(nthreads: u64, num_steps: u64) -> Result<(), ()> {
	let step = 1.0 / num_steps as f64;
	let mut sum = 0.0 as f64;

	let threads: Vec<_> = (0..nthreads)
		.map(|tid| {
			thread::spawn(move || {
				let mut partial_sum = 0 as f64;
				let start = (num_steps / nthreads) * tid;
				let end = (num_steps / nthreads) * (tid + 1);

				for i in start..end {
					let x = (i as f64 + 0.5) * step;
					partial_sum += 4.0 / (1.0 + x * x);
				}

				partial_sum
			})
		})
		.collect();

	for t in threads {
		sum += t.join().unwrap();
	}

	let mypi = sum * (1.0 / num_steps as f64);
	println!("Pi: {} (with {} threads)", mypi, nthreads);

	if (mypi - PI).abs() < 0.00001 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn read_file() -> Result<(), std::io::Error> {
	let mut file = File::open("/etc/hostname")?;
	let mut contents = String::new();
	file.read_to_string(&mut contents)?;

	println!("Hostname: {}", contents);

	Ok(())
}

pub fn create_file() -> Result<(), std::io::Error> {
	{
		let mut file = File::create("/tmp/foo.txt")?;
		file.write_all(b"Hello, world!")?;
	}

	let contents = {
		let mut file = File::open("/tmp/foo.txt")?;
		let mut contents = String::new();
		file.read_to_string(&mut contents)?;
		contents
	};

	// delete temporary file
	std::fs::remove_file("/tmp/foo.txt")?;

	if contents == "Hello, world!" {
		Ok(())
	} else {
		let kind = std::io::ErrorKind::Other;
		Err(std::io::Error::from(kind))
	}
}

pub fn print_argv() -> Result<(), ()> {
	let args = env::args();

	// Prints each argument on a separate line
	for (i, argument) in args.enumerate() {
		println!("argument[{}] = {}", i, argument);
	}

	Ok(())
}

pub fn print_env() -> Result<(), ()> {
	let envs = env::vars();

	// We will iterate through the references to the element returned by
	// env::vars();
	for (key, value) in envs {
		println!("{}: {}", key, value);
	}

	Ok(())
}

pub fn hello() -> Result<(), ()> {
	println!("Hello, world!");

	Ok(())
}

pub fn threading() -> Result<(), ()> {
	// Make a vector to hold the children which are spawned.
	let mut children = vec![];

	for i in 0..2 {
		// Spin up another thread
		children.push(thread::spawn(move || {
			println!("this is thread number {}", i);
		}));
	}

	for child in children {
		// Wait for the thread to finish. Returns a result.
		let _ = child.join();
	}

	Ok(())
}

/*pub fn laplace(size_x: usize, size_y: usize) -> Result<(), ()> {
	let matrix = matrix_setup(size_x, size_y);

	let now = Instant::now();
	let (iterations, res) = laplace::compute(matrix, size_x, size_y);
	println!(
		"Time to solve {} s, iterations {}, residuum {}",
		now.elapsed().as_secs_f64(),
		iterations,
		res
	);

	if res < 0.01 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn matrix_setup(size_x: usize, size_y: usize) -> (vec::Vec<vec::Vec<f64>>) {
	let mut matrix = vec![vec![0.0; size_x * size_y]; 2];

	// top row
	for x in 0..size_x {
		matrix[0][x] = 1.0;
		matrix[1][x] = 1.0;
	}

	// bottom row
	for x in 0..size_x {
		matrix[0][(size_y - 1) * size_x + x] = 1.0;
		matrix[1][(size_y - 1) * size_x + x] = 1.0;
	}

	// left row
	for y in 0..size_y {
		matrix[0][y * size_x] = 1.0;
		matrix[1][y * size_x] = 1.0;
	}

	// right row
	for y in 0..size_y {
		matrix[0][y * size_x + size_x - 1] = 1.0;
		matrix[1][y * size_x + size_x - 1] = 1.0;
	}

	matrix
}*/

fn send_http_rquest() -> Result<Vec<u8>, std::io::Error> {
	let mut stream = TcpStream::connect("134.130.122.36:80")?;
	let buf = b"GET /index.html HTTP/1.1\r\nHost: 134.130.122.36\r\nConnection: close\r\n\r\n";
	stream.write_all(buf)?;

	let mut buf = Vec::new();
	stream.read_to_end(&mut buf)?;

	Ok(buf)
}

pub fn test_http_request() -> Result<(), std::io::Error> {
	let buf = send_http_rquest()?;
	let result = str::from_utf8(&buf)
		.unwrap()
		.to_owned()
		.starts_with("HTTP/1.1 301 Moved Permanently");

	match result {
		true => println!("Ckeck http response... ok"),
		_ => println!("Ckeck http response... failed!"),
	};

	Ok(())
}
<commit_msg>use local http server to test the TcpStream<commit_after>use core::arch::x86_64 as arch;
use std::env;
use std::f64::consts::PI;
use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Instant;
use std::vec;

/*mod laplace;
mod matmul;

pub use matmul::test_matmul_strassen;*/

#[inline]
fn get_timestamp_rdtscp() -> u64 {
	unsafe {
		let mut _aux = 0;
		let value = arch::__rdtscp(&mut _aux);
		arch::_mm_lfence();
		value
	}
}

pub fn thread_creation() -> Result<(), ()> {
	let n = 1000;

	// cache warmup
	let _ = get_timestamp_rdtscp();

	let mut sum: u64 = 0;
	for _ in 0..n {
		let builder = thread::Builder::new();
		let start = get_timestamp_rdtscp();
		let child = builder.spawn(|| get_timestamp_rdtscp()).unwrap();
		thread::yield_now();
		match child.join() {
			Ok(end) => {
				sum += end - start;
			}
			Err(_) => {
				println!("Unable to join thread!");
			}
		}
	}

	println!("Time to create a thread {} ticks", sum / n);

	Ok(())
}

pub fn bench_sched_one_thread() -> Result<(), ()> {
	let n = 1000000;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp_rdtscp();

	let start = get_timestamp_rdtscp();
	for _ in 0..n {
		thread::yield_now();
	}
	let ticks = get_timestamp_rdtscp() - start;

	println!("Scheduling time {} ticks (1 thread)", ticks / n);

	Ok(())
}

pub fn bench_sched_two_threads() -> Result<(), ()> {
	let n = 1000000;
	let nthreads = 2;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp_rdtscp();

	let start = get_timestamp_rdtscp();
	let threads: Vec<_> = (0..nthreads - 1)
		.map(|_| {
			thread::spawn(move || {
				for _ in 0..n {
					thread::yield_now();
				}
			})
		})
		.collect();

	for _ in 0..n {
		thread::yield_now();
	}

	let ticks = get_timestamp_rdtscp() - start;

	for t in threads {
		t.join().unwrap();
	}

	println!(
		"Scheduling time {} ticks (2 threads)",
		ticks / (nthreads * n)
	);

	Ok(())
}

pub fn pi_sequential(num_steps: u64) -> Result<(), ()> {
	let step = 1.0 / num_steps as f64;
	let mut sum = 0 as f64;

	for i in 0..num_steps {
		let x = (i as f64 + 0.5) * step;
		sum += 4.0 / (1.0 + x * x);
	}

	let mypi = sum * (1.0 / num_steps as f64);
	println!("Pi: {} (sequential)", mypi);

	if (mypi - PI).abs() < 0.00001 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn pi_parallel(nthreads: u64, num_steps: u64) -> Result<(), ()> {
	let step = 1.0 / num_steps as f64;
	let mut sum = 0.0 as f64;

	let threads: Vec<_> = (0..nthreads)
		.map(|tid| {
			thread::spawn(move || {
				let mut partial_sum = 0 as f64;
				let start = (num_steps / nthreads) * tid;
				let end = (num_steps / nthreads) * (tid + 1);

				for i in start..end {
					let x = (i as f64 + 0.5) * step;
					partial_sum += 4.0 / (1.0 + x * x);
				}

				partial_sum
			})
		})
		.collect();

	for t in threads {
		sum += t.join().unwrap();
	}

	let mypi = sum * (1.0 / num_steps as f64);
	println!("Pi: {} (with {} threads)", mypi, nthreads);

	if (mypi - PI).abs() < 0.00001 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn read_file() -> Result<(), std::io::Error> {
	let mut file = File::open("/etc/hostname")?;
	let mut contents = String::new();
	file.read_to_string(&mut contents)?;

	println!("Hostname: {}", contents);

	Ok(())
}

pub fn create_file() -> Result<(), std::io::Error> {
	{
		let mut file = File::create("/tmp/foo.txt")?;
		file.write_all(b"Hello, world!")?;
	}

	let contents = {
		let mut file = File::open("/tmp/foo.txt")?;
		let mut contents = String::new();
		file.read_to_string(&mut contents)?;
		contents
	};

	// delete temporary file
	std::fs::remove_file("/tmp/foo.txt")?;

	if contents == "Hello, world!" {
		Ok(())
	} else {
		let kind = std::io::ErrorKind::Other;
		Err(std::io::Error::from(kind))
	}
}

pub fn print_argv() -> Result<(), ()> {
	let args = env::args();

	// Prints each argument on a separate line
	for (i, argument) in args.enumerate() {
		println!("argument[{}] = {}", i, argument);
	}

	Ok(())
}

pub fn print_env() -> Result<(), ()> {
	let envs = env::vars();

	// We will iterate through the references to the element returned by
	// env::vars();
	for (key, value) in envs {
		println!("{}: {}", key, value);
	}

	Ok(())
}

pub fn hello() -> Result<(), ()> {
	println!("Hello, world!");

	Ok(())
}

pub fn threading() -> Result<(), ()> {
	// Make a vector to hold the children which are spawned.
	let mut children = vec![];

	for i in 0..2 {
		// Spin up another thread
		children.push(thread::spawn(move || {
			println!("this is thread number {}", i);
		}));
	}

	for child in children {
		// Wait for the thread to finish. Returns a result.
		let _ = child.join();
	}

	Ok(())
}

/*pub fn laplace(size_x: usize, size_y: usize) -> Result<(), ()> {
	let matrix = matrix_setup(size_x, size_y);

	let now = Instant::now();
	let (iterations, res) = laplace::compute(matrix, size_x, size_y);
	println!(
		"Time to solve {} s, iterations {}, residuum {}",
		now.elapsed().as_secs_f64(),
		iterations,
		res
	);

	if res < 0.01 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn matrix_setup(size_x: usize, size_y: usize) -> (vec::Vec<vec::Vec<f64>>) {
	let mut matrix = vec![vec![0.0; size_x * size_y]; 2];

	// top row
	for x in 0..size_x {
		matrix[0][x] = 1.0;
		matrix[1][x] = 1.0;
	}

	// bottom row
	for x in 0..size_x {
		matrix[0][(size_y - 1) * size_x + x] = 1.0;
		matrix[1][(size_y - 1) * size_x + x] = 1.0;
	}

	// left row
	for y in 0..size_y {
		matrix[0][y * size_x] = 1.0;
		matrix[1][y * size_x] = 1.0;
	}

	// right row
	for y in 0..size_y {
		matrix[0][y * size_x + size_x - 1] = 1.0;
		matrix[1][y * size_x + size_x - 1] = 1.0;
	}

	matrix
}*/

fn send_http_rquest() -> Result<Vec<u8>, std::io::Error> {
	let mut stream = TcpStream::connect("10.0.5.1:7878")?;
	let buf = b"GET / HTTP/1.1\r\nHost: 10.0.5.1\r\nUser-Agent: hermit/0.3.16\r\nAccept: */*\r\n\r\n";
	stream.write_all(buf)?;

	let mut buf = Vec::new();
	stream.read_to_end(&mut buf)?;

	Ok(buf)
}

pub fn test_http_request() -> Result<(), std::io::Error> {
	let buf = send_http_rquest()?;
	let result = str::from_utf8(&buf)
		.unwrap()
		.to_owned()
		.starts_with("HTTP/1.1 200 OK");

	match result {
		true => println!("Ckeck http response... ok"),
		_ => println!("Ckeck http response... failed!"),
	};

	Ok(())
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use std::error::Error;

use crate::lsp::{
    Completion, CompletionOptions, CompletionParams, Connection, DidChangeTextDocument,
    DidChangeTextDocumentParams, DidCloseTextDocument, DidCloseTextDocumentParams,
    DidOpenTextDocument, DidOpenTextDocumentParams, InitializeParams, Message, Notification,
    Request, ServerCapabilities, ServerNotification, ServerRequest, ServerRequestId,
    TextDocumentSyncCapability, TextDocumentSyncKind, WorkDoneProgressOptions,
};

use extract_graphql;
use relay_compiler::compiler::Compiler;
use relay_compiler::config::Config;
use relay_compiler::errors::Error as CompilerError;

use crate::error_reporting::{report_build_project_errors, report_syntax_errors};
use crate::lsp::show_info_message;
use crate::state::ServerState;

use common::ConsoleLogger;
use graphql_syntax::GraphQLSource;
use log::info;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::Notify;

/// Initializes an LSP connection, handling the `initize` message and `initialized` notification
/// handshake.
pub fn initialize(
    connection: &Connection,
) -> Result<InitializeParams, Box<dyn Error + Sync + Send>> {
    let mut server_capabilities = ServerCapabilities::default();
    // Enable text document syncing so we can know when files are opened/changed/saved/closed
    server_capabilities.text_document_sync =
        Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::Full));

    server_capabilities.completion_provider = Some(CompletionOptions {
        resolve_provider: Some(true),
        trigger_characters: None,
        work_done_progress_options: WorkDoneProgressOptions {
            work_done_progress: None,
        },
    });

    let server_capabilities = serde_json::to_value(&server_capabilities).unwrap();
    let params = connection.initialize(server_capabilities)?;
    let params: InitializeParams = serde_json::from_value(params).unwrap();
    Ok(params)
}

/// Run the main server loop
pub async fn run(
    connection: Connection,
    _params: InitializeParams,
) -> Result<(), Box<dyn Error + Sync + Send>> {
    show_info_message("Relay Language Server Started!", &connection)?;
    info!("Running language server");

    let receiver = connection.receiver.clone();

    // A `Notify` instance used to signal that the compiler should be initialized.
    let compiler_notify = Arc::new(Notify::new());

    // Thread for the LSP message loop
    let compiler_notifier = compiler_notify.clone();
    tokio::spawn(async move {
        for msg in receiver {
            match msg {
                Message::Request(req) => {
                    // Auto-complete request
                    if req.method == Completion::METHOD {
                        let (request_id, params) = extract_request_params::<Completion>(req);
                        on_completion_request(request_id, params);
                    }
                }
                Message::Notification(notif) => {
                    match &notif.method {
                        method if method == DidOpenTextDocument::METHOD => {
                            let params = extract_notif_params::<DidOpenTextDocument>(notif);
                            on_did_open_text_document(params, &compiler_notifier);
                        }
                        method if method == DidChangeTextDocument::METHOD => {
                            let params = extract_notif_params::<DidChangeTextDocument>(notif);
                            on_did_change_text_document(params);
                        }
                        method if method == DidCloseTextDocument::METHOD => {
                            let params = extract_notif_params::<DidCloseTextDocument>(notif);
                            on_did_close_text_document(params);
                        }
                        _ => {
                            // Notifications we don't care about
                        }
                    }
                }
                Message::Response(_) => {
                    // Ignore responses for now
                }
            }
        }
    });

    info!("Waiting for compiler to initialize...");
    compiler_notify.notified().await;

    let config = load_config();
    let root_dir = config.root_dir.clone();
    let compiler = Compiler::new(config, &ConsoleLogger);
    let mut server_state = ServerState::new(root_dir);
    info!("Compiler initialized");

    compiler
        .watch_with_callback(|result| {
            match result {
                Ok(_) => {
                    info!("Compiled successfully");
                    // Clear all diagnostics
                    server_state.clear_diagnostics(&connection);
                }
                Err(err) => {
                    match err {
                        CompilerError::SyntaxErrors { errors } => {
                            report_syntax_errors(errors, &connection, &mut server_state)
                        }
                        CompilerError::BuildProjectsErrors { errors } => {
                            report_build_project_errors(errors, &connection, &mut server_state)
                        }
                        // Ignore the rest of these errors for now
                        CompilerError::ConfigFileRead { .. } => {}
                        CompilerError::ConfigFileParse { .. } => {}
                        CompilerError::ConfigFileValidation { .. } => {}
                        CompilerError::ReadFileError { .. } => {}
                        CompilerError::WriteFileError { .. } => {}
                        CompilerError::SerializationError { .. } => {}
                        CompilerError::DeserializationError { .. } => {}
                        CompilerError::CanonicalizeRoot { .. } => {}
                        CompilerError::Watchman { .. } => {}
                        CompilerError::EmptyQueryResult => {}
                        CompilerError::FileRead { .. } => {}
                        CompilerError::Syntax { .. } => {}
                    }
                }
            }
        })
        .await
        .unwrap();

    Ok(())
}

/// Returns a set of *non-empty* GraphQL sources if they exist in a file. Returns `None`
/// if extracting fails or there are no GraphQL chunks in the file.
fn extract_graphql_sources(source: &str) -> Option<Vec<GraphQLSource>> {
    match extract_graphql::parse_chunks(source) {
        Ok(chunks) => {
            if chunks.is_empty() {
                None
            } else {
                Some(chunks)
            }
        }
        Err(_) => None,
    }
}

fn on_completion_request(_request_id: ServerRequestId, _params: CompletionParams) {
    // TODO(brandondail)
}

fn on_did_open_text_document(
    params: DidOpenTextDocumentParams,
    compiler_init_notify: &Arc<Notify>,
) {
    info!("Did open text document!");
    let DidOpenTextDocumentParams { text_document } = params;

    // First we check to see if this document has any GraphQL documents.
    let _graphql_sources = match extract_graphql_sources(&text_document.text) {
        Some(sources) => sources,
        // Exit early if there are no sources
        None => return,
    };

    // Notify the mean thread that it can start the compiler now, if it hasn't already
    compiler_init_notify.notify();
}

fn on_did_close_text_document(_params: DidCloseTextDocumentParams) {}

fn on_did_change_text_document(_params: DidChangeTextDocumentParams) {}

fn load_config() -> Config {
    // TODO(brandondail) don't hardcode the test project config here
    let home = std::env::var("HOME").unwrap();
    let config_path = PathBuf::from(format!(
        "{}/fbsource/fbcode/relay/config/config.test.json",
        home
    ));
    let root_dir = PathBuf::from(format!("{}/fbsource", home));
    let mut config = Config::load(root_dir, config_path).unwrap();
    // Don't write artifacts by default
    config.write_artifacts = false;
    config
}

fn extract_notif_params<N>(notif: ServerNotification) -> N::Params
where
    N: Notification,
{
    notif.extract(N::METHOD).unwrap()
}

fn extract_request_params<R>(req: ServerRequest) -> (ServerRequestId, R::Params)
where
    R: Request,
{
    req.extract(R::METHOD).unwrap()
}
<commit_msg>initial document syncing for GraphQL sources<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use std::error::Error;

use crate::lsp::{
    Completion, CompletionOptions, CompletionParams, Connection, DidChangeTextDocument,
    DidChangeTextDocumentParams, DidCloseTextDocument, DidCloseTextDocumentParams,
    DidOpenTextDocument, DidOpenTextDocumentParams, InitializeParams, Message, Notification,
    Position, Request, ServerCapabilities, ServerNotification, ServerRequest, ServerRequestId,
    TextDocumentItem, TextDocumentPositionParams, TextDocumentSyncCapability, TextDocumentSyncKind,
    Url, WorkDoneProgressOptions,
};

use extract_graphql;
use relay_compiler::compiler::Compiler;
use relay_compiler::config::Config;
use relay_compiler::errors::Error as CompilerError;

use crate::error_reporting::{report_build_project_errors, report_syntax_errors};
use crate::lsp::show_info_message;
use crate::state::ServerState;

use common::{ConsoleLogger, FileKey};
use graphql_syntax::{parse, Document, GraphQLSource};
use log::info;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::Notify;

type GraphQLSourceCache = HashMap<Url, Vec<GraphQLSource>>;

/// Initializes an LSP connection, handling the `initize` message and `initialized` notification
/// handshake.
pub fn initialize(
    connection: &Connection,
) -> Result<InitializeParams, Box<dyn Error + Sync + Send>> {
    let mut server_capabilities = ServerCapabilities::default();
    // Enable text document syncing so we can know when files are opened/changed/saved/closed
    server_capabilities.text_document_sync =
        Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::Full));

    server_capabilities.completion_provider = Some(CompletionOptions {
        resolve_provider: Some(true),
        trigger_characters: None,
        work_done_progress_options: WorkDoneProgressOptions {
            work_done_progress: None,
        },
    });

    let server_capabilities = serde_json::to_value(&server_capabilities).unwrap();
    let params = connection.initialize(server_capabilities)?;
    let params: InitializeParams = serde_json::from_value(params).unwrap();
    Ok(params)
}

/// Run the main server loop
pub async fn run(
    connection: Connection,
    _params: InitializeParams,
) -> Result<(), Box<dyn Error + Sync + Send>> {
    show_info_message("Relay Language Server Started!", &connection)?;
    info!("Running language server");

    let receiver = connection.receiver.clone();

    // A `Notify` instance used to signal that the compiler should be initialized.
    let compiler_notify = Arc::new(Notify::new());

    // Thread for the LSP message loop
    let compiler_notifier = compiler_notify.clone();

    tokio::spawn(async move {
        // Cache for the extracted GraphQL sources
        let mut graphql_source_cache = HashMap::new();
        for msg in receiver {
            match msg {
                Message::Request(req) => {
                    // Auto-complete request
                    if req.method == Completion::METHOD {
                        let (request_id, params) = extract_request_params::<Completion>(req);
                        on_completion_request(request_id, params, &graphql_source_cache);
                    }
                }
                Message::Notification(notif) => {
                    match &notif.method {
                        method if method == DidOpenTextDocument::METHOD => {
                            let params = extract_notif_params::<DidOpenTextDocument>(notif);
                            on_did_open_text_document(
                                params,
                                &compiler_notifier,
                                &mut graphql_source_cache,
                            );
                        }
                        method if method == DidChangeTextDocument::METHOD => {
                            let params = extract_notif_params::<DidChangeTextDocument>(notif);
                            on_did_change_text_document(params);
                        }
                        method if method == DidCloseTextDocument::METHOD => {
                            let params = extract_notif_params::<DidCloseTextDocument>(notif);
                            on_did_close_text_document(params);
                        }
                        _ => {
                            // Notifications we don't care about
                        }
                    }
                }
                Message::Response(_) => {
                    // Ignore responses for now
                }
            }
        }
    });

    info!("Waiting for compiler to initialize...");
    compiler_notify.notified().await;

    let config = load_config();
    let root_dir = config.root_dir.clone();
    let compiler = Compiler::new(config, &ConsoleLogger);
    let mut server_state = ServerState::new(root_dir);
    info!("Compiler initialized");

    compiler
        .watch_with_callback(|result| {
            match result {
                Ok(_) => {
                    info!("Compiled successfully");
                    // Clear all diagnostics
                    server_state.clear_diagnostics(&connection);
                }
                Err(err) => {
                    match err {
                        CompilerError::SyntaxErrors { errors } => {
                            report_syntax_errors(errors, &connection, &mut server_state)
                        }
                        CompilerError::BuildProjectsErrors { errors } => {
                            report_build_project_errors(errors, &connection, &mut server_state)
                        }
                        // Ignore the rest of these errors for now
                        CompilerError::ConfigFileRead { .. } => {}
                        CompilerError::ConfigFileParse { .. } => {}
                        CompilerError::ConfigFileValidation { .. } => {}
                        CompilerError::ReadFileError { .. } => {}
                        CompilerError::WriteFileError { .. } => {}
                        CompilerError::SerializationError { .. } => {}
                        CompilerError::DeserializationError { .. } => {}
                        CompilerError::CanonicalizeRoot { .. } => {}
                        CompilerError::Watchman { .. } => {}
                        CompilerError::EmptyQueryResult => {}
                        CompilerError::FileRead { .. } => {}
                        CompilerError::Syntax { .. } => {}
                    }
                }
            }
        })
        .await
        .unwrap();

    Ok(())
}

/// Returns a set of *non-empty* GraphQL sources if they exist in a file. Returns `None`
/// if extracting fails or there are no GraphQL chunks in the file.
fn extract_graphql_sources(source: &str) -> Option<Vec<GraphQLSource>> {
    match extract_graphql::parse_chunks(source) {
        Ok(chunks) => {
            if chunks.is_empty() {
                None
            } else {
                Some(chunks)
            }
        }
        Err(_) => None,
    }
}

fn on_completion_request(
    _request_id: ServerRequestId,
    params: CompletionParams,
    graphql_source_cache: &GraphQLSourceCache,
) {
    let CompletionParams {
        text_document_position,
        ..
    } = params;
    let TextDocumentPositionParams {
        text_document,
        position,
    } = text_document_position;
    let url = text_document.uri;
    let graphql_sources = match graphql_source_cache.get(&url) {
        Some(sources) => sources,
        // If we have no sources for this file, do nothing
        None => return,
    };

    info!(
        "Got completion request for file with sources: {:#?}",
        *graphql_sources
    );

    info!("position: {:?}", position);

    // We have GraphQL documents, now check if the completion request
    // falls within the range of one of these documents.
    let mut target_graphql_source: Option<&GraphQLSource> = None;
    for graphql_source in &*graphql_sources {
        let range = graphql_source.to_range();
        if position >= range.start && position <= range.end {
            target_graphql_source = Some(graphql_source);
            break;
        }
    }

    let graphql_source = match target_graphql_source {
        Some(source) => source,
        // Exit early if this completion request didn't fall within
        // the range of one of our GraphQL documents
        None => return,
    };

    match parse(&graphql_source.text, FileKey::new(&url.to_string())) {
        Ok(definitions) => {
            // Now we need to take the `Position` and map that to an offset relative
            // to this GraphQL document, as the `Span`s in the document are relative.
            info!("Successfully parsed the definitions for a target GraphQL source");
            info!("{:#?}", definitions);
            find_position_in_definitions(position, definitions);
        }
        Err(err) => {
            info!("Failed to parse this target!");
            info!("{:?}", err);
        }
    }
}

fn find_position_in_definitions(_position: Position, _definitions: Document) {
    // TODO(brandondail)
}

fn on_did_open_text_document(
    params: DidOpenTextDocumentParams,
    compiler_init_notify: &Arc<Notify>,
    graphql_source_cache: &mut GraphQLSourceCache,
) {
    info!("Did open text document!");
    let DidOpenTextDocumentParams { text_document } = params;
    let TextDocumentItem { text, uri, .. } = text_document;

    // First we check to see if this document has any GraphQL documents.
    let graphql_sources = match extract_graphql_sources(&text) {
        Some(sources) => sources,
        // Exit early if there are no sources
        None => return,
    };

    // Track the GraphQL sources for this document
    graphql_source_cache.insert(uri, graphql_sources);

    // Notify the mean thread that it can start the compiler now, if it hasn't already
    compiler_init_notify.notify();
}

fn on_did_close_text_document(_params: DidCloseTextDocumentParams) {}

fn on_did_change_text_document(_params: DidChangeTextDocumentParams) {}

fn load_config() -> Config {
    // TODO(brandondail) don't hardcode the test project config here
    let home = std::env::var("HOME").unwrap();
    let config_path = PathBuf::from(format!(
        "{}/fbsource/fbcode/relay/config/config.test.json",
        home
    ));
    let root_dir = PathBuf::from(format!("{}/fbsource", home));
    let mut config = Config::load(root_dir, config_path).unwrap();
    // Don't write artifacts by default
    config.write_artifacts = false;
    config
}

fn extract_notif_params<N>(notif: ServerNotification) -> N::Params
where
    N: Notification,
{
    notif.extract(N::METHOD).unwrap()
}

fn extract_request_params<R>(req: ServerRequest) -> (ServerRequestId, R::Params)
where
    R: Request,
{
    req.extract(R::METHOD).unwrap()
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use clap;
use std::fs;
use std::io::Write;

use common::ui::{UI, Status};
use export_docker;
use export_docker::Result;
use export_k8s::{Manifest, ManifestJson};

use chartfile::ChartFile;
use values::Values;
use deps::Deps;

pub struct Chart<'a> {
    name: String,
    chartfile: ChartFile,
    manifest_template: Option<ManifestJson>,
    values: Values,
    deps: Deps,
    ui: &'a mut UI,
}

impl<'a> Chart<'a> {
    pub fn new_for_cli_matches(ui: &'a mut UI, matches: &clap::ArgMatches) -> Result<Self> {
        let image = if !matches.is_present("NO_DOCKER_IMAGE") {
            export_docker::export_for_cli_matches(ui, &matches)?
        } else {
            None
        };
        let manifest = Manifest::new_from_cli_matches(ui, &matches, image)?;

        let name = matches
            .value_of("CHART")
            .unwrap_or(&manifest.metadata_name)
            .to_string();
        let version = matches.value_of("VERSION");
        let description = matches.value_of("DESCRIPTION");
        let chartfile = ChartFile::new(&name, version, description);
        let deps = Deps::new_for_cli_matches(&matches);

        Ok(Self::new_for_manifest(manifest, name, chartfile, deps, ui))
    }

    fn new_for_manifest(
        manifest: Manifest,
        name: String,
        chartfile: ChartFile,
        deps: Deps,
        ui: &'a mut UI,
    ) -> Self {
        let main = json!({
            "metadata_name": "{{.Values.metadataName}}",
            "service_name": "{{.Values.serviceName}}",
            "image": "{{.Values.imageName}}",
            "count": "{{.Values.instanceCount}}",
            "service_topology": "{{.Values.serviceTopology}}",
            "service_group": manifest.service_group.clone().map(|_| "{{.Values.serviceGroup}}"),
            "config": manifest.config
                .clone()
                .map(|_| "{{.Values.config}}"),
            "ring_secret_name": manifest.ring_secret_name
                .clone()
                .map(|_| "{{.Values.ringSecretName}}"),
            "bind": !manifest.binds.is_empty(),
        });

        let mut values = Values::new();
        values.add_entry("metadataName", &manifest.metadata_name);
        values.add_entry("serviceName", &manifest.service_name);
        values.add_entry("imageName", &manifest.image);
        values.add_entry("instanceCount", &manifest.count.to_string());
        values.add_entry("serviceTopology", &manifest.service_topology.to_string());
        if let Some(ref group) = manifest.service_group {
            values.add_entry("serviceGroup", group);
        }
        if let Some(ref config) = manifest.config {
            values.add_entry("config", config);
        }
        if let Some(ref name) = manifest.ring_secret_name {
            values.add_entry("ringSecretName", name);
        }

        let mut binds = Vec::new();
        let mut i = 0;
        for bind in &manifest.binds {
            let name_var = format!("bindName{}", i);
            let service_var = format!("bindService{}", i);
            let group_var = format!("bindGroup{}", i);
            i = i + 1;

            values.add_entry(&name_var, &bind.name);
            values.add_entry(&service_var, &bind.service_group.service());
            values.add_entry(&group_var, &bind.service_group.group());

            let json = json!({
                "name": format!("{{{{.Values.{}}}}}", name_var),
                "service": format!("{{{{.Values.{}}}}}", service_var),
                "group": format!("{{{{.Values.{}}}}}", group_var),
            });

            binds.push(json);
        }

        let manifest_template = Some(ManifestJson {
            main: main,
            binds: binds,
        });

        Chart {
            name,
            chartfile,
            manifest_template,
            values,
            deps,
            ui,
        }
    }

    pub fn generate(mut self) -> Result<()> {
        self.ui.status(
            Status::Creating,
            format!("directory `{}`", self.name),
        )?;
        fs::create_dir_all(&self.name)?;

        self.generate_chartfile()?;
        self.generate_values()?;
        self.generate_manifest_template()?;
        self.generate_deps()?;

        self.download_deps()
    }

    fn generate_chartfile(&mut self) -> Result<()> {
        let mut write = self.create_file("Chart.yaml")?;
        let out = self.chartfile.into_string()?;

        write.write(out.as_bytes())?;

        Ok(())
    }

    fn generate_manifest_template(&mut self) -> Result<()> {
        let template_path = format!("{}/{}", self.name, "templates");
        self.ui.status(
            Status::Creating,
            format!("directory `{}`", template_path),
        )?;
        fs::create_dir_all(&template_path)?;

        let manifest_path = format!("{}/{}.yaml", template_path, self.name);
        self.ui.status(
            Status::Creating,
            format!("file `{}`", manifest_path),
        )?;
        let mut write = fs::File::create(manifest_path)?;
        let out: String = self.manifest_template
            .take()
            .expect("generate_manifest_template() called more than once")
            .into();

        write.write(out.as_bytes())?;

        Ok(())
    }

    fn generate_values(&mut self) -> Result<()> {
        let mut write = self.create_file("values.yaml")?;
        self.values.generate(&mut write)?;

        Ok(())
    }

    fn generate_deps(&mut self) -> Result<()> {
        let mut write = self.create_file("requirements.yaml")?;
        self.deps.generate(&mut write)?;

        Ok(())
    }

    fn download_deps(&mut self) -> Result<()> {
        self.deps.download(&self.name, self.ui)
    }

    fn create_file(&mut self, name: &str) -> Result<fs::File> {
        let path = format!("{}/{}", self.name, name);
        self.ui.status(Status::Creating, format!("file `{}`", path))?;

        fs::File::create(path).map_err(From::from)
    }
}
<commit_msg>pkg-export-helm: Correct name of manifest template<commit_after>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use clap;
use std::fs;
use std::io::Write;

use common::ui::{UI, Status};
use export_docker;
use export_docker::Result;
use export_k8s::{Manifest, ManifestJson};

use chartfile::ChartFile;
use values::Values;
use deps::Deps;

pub struct Chart<'a> {
    name: String,
    chartfile: ChartFile,
    manifest_template: Option<ManifestJson>,
    values: Values,
    deps: Deps,
    ui: &'a mut UI,
}

impl<'a> Chart<'a> {
    pub fn new_for_cli_matches(ui: &'a mut UI, matches: &clap::ArgMatches) -> Result<Self> {
        let image = if !matches.is_present("NO_DOCKER_IMAGE") {
            export_docker::export_for_cli_matches(ui, &matches)?
        } else {
            None
        };
        let manifest = Manifest::new_from_cli_matches(ui, &matches, image)?;

        let name = matches
            .value_of("CHART")
            .unwrap_or(&manifest.metadata_name)
            .to_string();
        let version = matches.value_of("VERSION");
        let description = matches.value_of("DESCRIPTION");
        let chartfile = ChartFile::new(&name, version, description);
        let deps = Deps::new_for_cli_matches(&matches);

        Ok(Self::new_for_manifest(manifest, name, chartfile, deps, ui))
    }

    fn new_for_manifest(
        manifest: Manifest,
        name: String,
        chartfile: ChartFile,
        deps: Deps,
        ui: &'a mut UI,
    ) -> Self {
        let main = json!({
            "metadata_name": "{{.Values.metadataName}}",
            "service_name": "{{.Values.serviceName}}",
            "image": "{{.Values.imageName}}",
            "count": "{{.Values.instanceCount}}",
            "service_topology": "{{.Values.serviceTopology}}",
            "service_group": manifest.service_group.clone().map(|_| "{{.Values.serviceGroup}}"),
            "config": manifest.config
                .clone()
                .map(|_| "{{.Values.config}}"),
            "ring_secret_name": manifest.ring_secret_name
                .clone()
                .map(|_| "{{.Values.ringSecretName}}"),
            "bind": !manifest.binds.is_empty(),
        });

        let mut values = Values::new();
        values.add_entry("metadataName", &manifest.metadata_name);
        values.add_entry("serviceName", &manifest.service_name);
        values.add_entry("imageName", &manifest.image);
        values.add_entry("instanceCount", &manifest.count.to_string());
        values.add_entry("serviceTopology", &manifest.service_topology.to_string());
        if let Some(ref group) = manifest.service_group {
            values.add_entry("serviceGroup", group);
        }
        if let Some(ref config) = manifest.config {
            values.add_entry("config", config);
        }
        if let Some(ref name) = manifest.ring_secret_name {
            values.add_entry("ringSecretName", name);
        }

        let mut binds = Vec::new();
        let mut i = 0;
        for bind in &manifest.binds {
            let name_var = format!("bindName{}", i);
            let service_var = format!("bindService{}", i);
            let group_var = format!("bindGroup{}", i);
            i = i + 1;

            values.add_entry(&name_var, &bind.name);
            values.add_entry(&service_var, &bind.service_group.service());
            values.add_entry(&group_var, &bind.service_group.group());

            let json = json!({
                "name": format!("{{{{.Values.{}}}}}", name_var),
                "service": format!("{{{{.Values.{}}}}}", service_var),
                "group": format!("{{{{.Values.{}}}}}", group_var),
            });

            binds.push(json);
        }

        let manifest_template = Some(ManifestJson {
            main: main,
            binds: binds,
        });

        Chart {
            name,
            chartfile,
            manifest_template,
            values,
            deps,
            ui,
        }
    }

    pub fn generate(mut self) -> Result<()> {
        self.ui.status(
            Status::Creating,
            format!("directory `{}`", self.name),
        )?;
        fs::create_dir_all(&self.name)?;

        self.generate_chartfile()?;
        self.generate_values()?;
        self.generate_manifest_template()?;
        self.generate_deps()?;

        self.download_deps()
    }

    fn generate_chartfile(&mut self) -> Result<()> {
        let mut write = self.create_file("Chart.yaml")?;
        let out = self.chartfile.into_string()?;

        write.write(out.as_bytes())?;

        Ok(())
    }

    fn generate_manifest_template(&mut self) -> Result<()> {
        let template_path = format!("{}/{}", self.name, "templates");
        self.ui.status(
            Status::Creating,
            format!("directory `{}`", template_path),
        )?;
        fs::create_dir_all(&template_path)?;

        let manifest_path = format!("{}/habitat.yaml", template_path);
        self.ui.status(
            Status::Creating,
            format!("file `{}`", manifest_path),
        )?;
        let mut write = fs::File::create(manifest_path)?;
        let out: String = self.manifest_template
            .take()
            .expect("generate_manifest_template() called more than once")
            .into();

        write.write(out.as_bytes())?;

        Ok(())
    }

    fn generate_values(&mut self) -> Result<()> {
        let mut write = self.create_file("values.yaml")?;
        self.values.generate(&mut write)?;

        Ok(())
    }

    fn generate_deps(&mut self) -> Result<()> {
        let mut write = self.create_file("requirements.yaml")?;
        self.deps.generate(&mut write)?;

        Ok(())
    }

    fn download_deps(&mut self) -> Result<()> {
        self.deps.download(&self.name, self.ui)
    }

    fn create_file(&mut self, name: &str) -> Result<fs::File> {
        let path = format!("{}/{}", self.name, name);
        self.ui.status(Status::Creating, format!("file `{}`", path))?;

        fs::File::create(path).map_err(From::from)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-emscripten
// min-llvm-version 7.0
// error-pattern: panicked

// Test that the simd_f{min,max} intrinsics produce the correct results.

#![feature(repr_simd, platform_intrinsics)]
#![allow(non_camel_case_types)]

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4(pub f32, pub f32, pub f32, pub f32);

extern "platform-intrinsic" {
    fn simd_fmin<T>(x: T, y: T) -> T;
    fn simd_fmax<T>(x: T, y: T) -> T;
}

fn main() {
    let x = f32x4(1.0, 2.0, 3.0, 4.0);
    let y = f32x4(2.0, 1.0, 4.0, 3.0);
    let nan = ::std::f32::NAN;
    let n = f32x4(nan, nan, nan, nan);

    unsafe {
        let min0 = simd_fmin(x, y);
        let min1 = simd_fmin(y, x);
        assert_eq!(min0, min1);
        let e = f32x4(1.0, 1.0, 3.0, 3.0);
        assert_eq!(min0, e);
        let minn = simd_fmin(x, n);
        assert_eq!(minn, x);
        let minn = simd_fmin(y, n);
        assert_eq!(minn, y);

        let max0 = simd_fmax(x, y);
        let max1 = simd_fmax(y, x);
        assert_eq!(max0, max1);
        let e = f32x4(2.0, 2.0, 4.0, 4.0);
        assert_eq!(max0, e);
        let maxn = simd_fmax(x, n);
        assert_eq!(maxn, x);
        let maxn = simd_fmax(y, n);
        assert_eq!(maxn, y);
    }
}
<commit_msg>Auto merge of #52895 - draganmladjenovic:minmax_qnan, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-emscripten
// min-llvm-version 7.0
// error-pattern: panicked

// Test that the simd_f{min,max} intrinsics produce the correct results.

#![feature(repr_simd, platform_intrinsics)]
#![allow(non_camel_case_types)]

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4(pub f32, pub f32, pub f32, pub f32);

extern "platform-intrinsic" {
    fn simd_fmin<T>(x: T, y: T) -> T;
    fn simd_fmax<T>(x: T, y: T) -> T;
}

fn main() {
    let x = f32x4(1.0, 2.0, 3.0, 4.0);
    let y = f32x4(2.0, 1.0, 4.0, 3.0);

    #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
    let nan = ::std::f32::NAN;
    // MIPS hardware treats f32::NAN as SNAN. Clear the signaling bit.
    // See https://github.com/rust-lang/rust/issues/52746.
    #[cfg(any(target_arch = "mips", target_arch = "mips64"))]
    let nan = f32::from_bits(::std::f32::NAN.to_bits() - 1);

    let n = f32x4(nan, nan, nan, nan);

    unsafe {
        let min0 = simd_fmin(x, y);
        let min1 = simd_fmin(y, x);
        assert_eq!(min0, min1);
        let e = f32x4(1.0, 1.0, 3.0, 3.0);
        assert_eq!(min0, e);
        let minn = simd_fmin(x, n);
        assert_eq!(minn, x);
        let minn = simd_fmin(y, n);
        assert_eq!(minn, y);

        let max0 = simd_fmax(x, y);
        let max1 = simd_fmax(y, x);
        assert_eq!(max0, max1);
        let e = f32x4(2.0, 2.0, 4.0, 4.0);
        assert_eq!(max0, e);
        let maxn = simd_fmax(x, n);
        assert_eq!(maxn, x);
        let maxn = simd_fmax(y, n);
        assert_eq!(maxn, y);
    }
}
<|endoftext|>


<commit_before>//! The `check` crate is responsible for ensuring that an AST expression is actually a valid
//! program. This currently consits of three larger parts, typechecking, kindchecking and renaming.
//! If an AST passes the checks in `Typecheck::typecheck_expr` (which runs all of theses checks
//! the expression is expected to compile succesfully (if it does not it should be considered an
//! internal compiler error.

#[macro_use]
extern crate log;
#[cfg(test)]
extern crate env_logger;
extern crate union_find;

extern crate base;
#[cfg(test)]
extern crate parser;

mod instantiate;
pub mod typecheck;
pub mod unify_type;
pub mod unify;
pub mod kindcheck;
mod substitution;
mod rename;

#[cfg(test)]
mod tests {
    use std::cell::RefCell;
    use std::rc::Rc;

    use base::symbol::{Symbols, SymbolModule, Symbol};

    ///Returns a reference to the interner stored in TLD
    pub fn get_local_interner() -> Rc<RefCell<Symbols>> {
        thread_local!(static INTERNER: Rc<RefCell<Symbols>>
                      = Rc::new(RefCell::new(Symbols::new())));
        INTERNER.with(|interner| interner.clone())
    }

    pub fn intern(s: &str) -> Symbol {
        let i = get_local_interner();
        let mut i = i.borrow_mut();
        if s.chars().next().map(|c| c.is_lowercase()).unwrap_or(false) {
            i.symbol(s)
        } else {
            SymbolModule::new("test".into(), &mut i).scoped_symbol(s)
        }
    }
}
<commit_msg>fix(check): Remove dependency on parser<commit_after>//! The `check` crate is responsible for ensuring that an AST expression is actually a valid
//! program. This currently consits of three larger parts, typechecking, kindchecking and renaming.
//! If an AST passes the checks in `Typecheck::typecheck_expr` (which runs all of theses checks
//! the expression is expected to compile succesfully (if it does not it should be considered an
//! internal compiler error.

#[macro_use]
extern crate log;
#[cfg(test)]
extern crate env_logger;
extern crate union_find;

extern crate base;

mod instantiate;
pub mod typecheck;
pub mod unify_type;
pub mod unify;
pub mod kindcheck;
mod substitution;
mod rename;

#[cfg(test)]
mod tests {
    use std::cell::RefCell;
    use std::rc::Rc;

    use base::symbol::{Symbols, SymbolModule, Symbol};

    ///Returns a reference to the interner stored in TLD
    pub fn get_local_interner() -> Rc<RefCell<Symbols>> {
        thread_local!(static INTERNER: Rc<RefCell<Symbols>>
                      = Rc::new(RefCell::new(Symbols::new())));
        INTERNER.with(|interner| interner.clone())
    }

    pub fn intern(s: &str) -> Symbol {
        let i = get_local_interner();
        let mut i = i.borrow_mut();
        if s.chars().next().map(|c| c.is_lowercase()).unwrap_or(false) {
            i.symbol(s)
        } else {
            SymbolModule::new("test".into(), &mut i).scoped_symbol(s)
        }
    }
}
<|endoftext|>