<commit_before>use alloc::arc::Arc;

use arch::context::{CONTEXT_STACK_SIZE, CONTEXT_STACK_ADDR, context_switch, context_userspace, Context, ContextMemory};
use arch::elf::Elf;
use arch::memory;
use arch::regs::Regs;

use collections::string::{String, ToString};
use collections::vec::Vec;

use common::slice::GetSlice;

use core::cell::UnsafeCell;
use core::ops::DerefMut;
use core::{mem, ptr};

use fs::Url;

use system::error::{Error, Result, ENOEXEC};

fn execute_inner(url: Url) -> Result<(*mut Context, usize)> {
    let mut vec: Vec<u8> = Vec::new();

    {
        let mut resource = try!(url.open());
        'reading: loop {
            let mut bytes = [0; 4096];
            match resource.read(&mut bytes) {
                Ok(0) => break 'reading,
                Ok(count) => vec.push_all(bytes.get_slice(.. count)),
                Err(err) => return Err(err)
            }
        }
    }

    match Elf::from(&vec) {
        Ok(executable) => {
            let entry = unsafe { executable.entry() };
            let mut memory = Vec::new();
            unsafe {
                for segment in executable.load_segment().iter() {
                    let virtual_address = segment.vaddr as usize;
                    let virtual_size = segment.mem_len as usize;

                    let offset = virtual_address % 4096;

                    let physical_address = memory::alloc(virtual_size + offset);

                    if physical_address > 0 {
                        // Copy progbits
                        ::memcpy((physical_address + offset) as *mut u8,
                                 (executable.data.as_ptr() as usize + segment.off as usize) as *const u8,
                                 segment.file_len as usize);
                        // Zero bss
                        if segment.mem_len > segment.file_len {
                            ::memset((physical_address + offset + segment.file_len as usize) as *mut u8,
                                    0,
                                    segment.mem_len as usize - segment.file_len as usize);
                        }

                        memory.push(ContextMemory {
                            physical_address: physical_address,
                            virtual_address: virtual_address - offset,
                            virtual_size: virtual_size + offset,
                            writeable: segment.flags & 2 == 2,
                            allocated: true,
                        });
                    }
                }
            }

            if entry > 0 && ! memory.is_empty() {
                let mut contexts = ::env().contexts.lock();
                let mut context = try!(contexts.current_mut());

                //debugln!("{}: {}: execute {}", context.pid, context.name, url.string);

                context.name = url.string;
                context.cwd = Arc::new(UnsafeCell::new(unsafe { (*context.cwd.get()).clone() }));

                unsafe { context.unmap() };
                context.memory = Arc::new(UnsafeCell::new(memory));
                unsafe { context.map() };

                Ok((context.deref_mut(), entry))
            } else {
                Err(Error::new(ENOEXEC))
            }
        },
        Err(msg) => {
            debugln!("execute: failed to exec '{}': {}", url.string, msg);
            Err(Error::new(ENOEXEC))
        }
    }
}

pub fn execute_outer(context_ptr: *mut Context, entry: usize, mut args: Vec<String>) -> ! {
    Context::spawn("kexec".to_string(), box move || {
        let context = unsafe { &mut *context_ptr };

        let mut context_args: Vec<usize> = Vec::new();
        context_args.push(0); // ENVP
        context_args.push(0); // ARGV NULL
        let mut argc = 0;
        while let Some(mut arg) = args.pop() {
            if ! arg.ends_with('\0') {
                arg.push('\0');
            }

            let physical_address = arg.as_ptr() as usize;
            let virtual_address = context.next_mem();
            let virtual_size = arg.len();

            mem::forget(arg);

            unsafe {
                (*context.memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: virtual_size,
                    writeable: false,
                    allocated: true,
                });
            }

            context_args.push(virtual_address as usize);
            argc += 1;
        }
        context_args.push(argc);

        //TODO: No default heap, fix brk
        {
            let virtual_address = context.next_mem();
            let virtual_size = 4096;
            let physical_address = unsafe { memory::alloc(virtual_size) };
            if physical_address > 0 {
                unsafe {
                    (*context.memory.get()).push(ContextMemory {
                        physical_address: physical_address,
                        virtual_address: virtual_address,
                        virtual_size: virtual_size,
                        writeable: true,
                        allocated: true
                    });
                }
            }
        }

        context.regs = Regs::default();
        context.regs.sp = context.kernel_stack + CONTEXT_STACK_SIZE - 128;

        context.stack = Some(ContextMemory {
            physical_address: unsafe { memory::alloc(CONTEXT_STACK_SIZE) },
            virtual_address: CONTEXT_STACK_ADDR,
            virtual_size: CONTEXT_STACK_SIZE,
            writeable: true,
            allocated: true,
        });

        let user_sp = if let Some(ref stack) = context.stack {
            let mut sp = stack.physical_address + stack.virtual_size - 128;
            for arg in context_args.iter() {
                sp -= mem::size_of::<usize>();
                unsafe { ptr::write(sp as *mut usize, *arg) };
            }
            sp - stack.physical_address + stack.virtual_address
        } else {
            0
        };

        unsafe {
            context.push(0x20 | 3);
            context.push(user_sp);
            context.push(1 << 9);
            context.push(0x18 | 3);
            context.push(entry);
            context.push(context_userspace as usize);
        }

        if let Some(vfork) = context.vfork.take() {
            unsafe { (*vfork).blocked = false; }
        }
    });

    loop {
        unsafe { context_switch() };
    }
}

/// Execute an executable
pub fn execute(args: Vec<String>) -> Result<usize> {
    let contexts = ::env().contexts.lock();
    let current = try!(contexts.current());

    if let Ok((context_ptr, entry)) = execute_inner(Url::from_string(current.canonicalize(args.get(0).map_or("", |p| &p)))) {
        execute_outer(context_ptr, entry, args);
    }else{
        let (context_ptr, entry) = try!(execute_inner(Url::from_string("file:/bin/".to_string() + args.get(0).map_or("", |p| &p))));
        execute_outer(context_ptr, entry, args);
    }
}
<commit_msg>Add hashbang uspport<commit_after>use alloc::arc::Arc;

use arch::context::{CONTEXT_STACK_SIZE, CONTEXT_STACK_ADDR, context_switch, context_userspace, Context, ContextMemory};
use arch::elf::Elf;
use arch::memory;
use arch::regs::Regs;

use collections::string::{String, ToString};
use collections::vec::Vec;

use common::slice::GetSlice;

use core::cell::UnsafeCell;
use core::ops::DerefMut;
use core::{mem, ptr, str};

use fs::Url;

use system::error::{Error, Result, ENOEXEC};

pub fn execute_thread(context_ptr: *mut Context, entry: usize, mut args: Vec<String>) -> ! {
    Context::spawn("kexec".to_string(), box move || {
        let context = unsafe { &mut *context_ptr };

        let mut context_args: Vec<usize> = Vec::new();
        context_args.push(0); // ENVP
        context_args.push(0); // ARGV NULL
        let mut argc = 0;
        while let Some(mut arg) = args.pop() {
            if ! arg.ends_with('\0') {
                arg.push('\0');
            }

            let physical_address = arg.as_ptr() as usize;
            let virtual_address = context.next_mem();
            let virtual_size = arg.len();

            mem::forget(arg);

            unsafe {
                (*context.memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: virtual_size,
                    writeable: false,
                    allocated: true,
                });
            }

            context_args.push(virtual_address as usize);
            argc += 1;
        }
        context_args.push(argc);

        //TODO: No default heap, fix brk
        {
            let virtual_address = context.next_mem();
            let virtual_size = 4096;
            let physical_address = unsafe { memory::alloc(virtual_size) };
            if physical_address > 0 {
                unsafe {
                    (*context.memory.get()).push(ContextMemory {
                        physical_address: physical_address,
                        virtual_address: virtual_address,
                        virtual_size: virtual_size,
                        writeable: true,
                        allocated: true
                    });
                }
            }
        }

        context.regs = Regs::default();
        context.regs.sp = context.kernel_stack + CONTEXT_STACK_SIZE - 128;

        context.stack = Some(ContextMemory {
            physical_address: unsafe { memory::alloc(CONTEXT_STACK_SIZE) },
            virtual_address: CONTEXT_STACK_ADDR,
            virtual_size: CONTEXT_STACK_SIZE,
            writeable: true,
            allocated: true,
        });

        let user_sp = if let Some(ref stack) = context.stack {
            let mut sp = stack.physical_address + stack.virtual_size - 128;
            for arg in context_args.iter() {
                sp -= mem::size_of::<usize>();
                unsafe { ptr::write(sp as *mut usize, *arg) };
            }
            sp - stack.physical_address + stack.virtual_address
        } else {
            0
        };

        unsafe {
            context.push(0x20 | 3);
            context.push(user_sp);
            context.push(1 << 9);
            context.push(0x18 | 3);
            context.push(entry);
            context.push(context_userspace as usize);
        }

        if let Some(vfork) = context.vfork.take() {
            unsafe { (*vfork).blocked = false; }
        }
    });

    loop {
        unsafe { context_switch() };
    }
}

/// Execute an executable
pub fn execute(mut args: Vec<String>) -> Result<usize> {
    let contexts = ::env().contexts.lock();
    let current = try!(contexts.current());

    let mut vec: Vec<u8> = Vec::new();

    let mut url = Url::from_string(current.canonicalize(args.get(0).map_or("", |p| &p)));
    {
        let mut resource = if let Ok(resource) = url.open() {
            resource
        } else {
            url = Url::from_string("file:/bin/".to_string() + args.get(0).map_or("", |p| &p));
            try!(url.open())
        };

        'reading: loop {
            let mut bytes = [0; 4096];
            match resource.read(&mut bytes) {
                Ok(0) => break 'reading,
                Ok(count) => vec.push_all(bytes.get_slice(.. count)),
                Err(err) => return Err(err)
            }
        }
    }

    if vec.starts_with(b"#!") {
        if let Some(mut arg) = args.get_mut(0) {
            *arg = url.string;
        }
        if let Some(line) = unsafe { str::from_utf8_unchecked(&vec[2..]) }.lines().next() {
            let mut i = 0;
            for arg in line.trim().split(' ') {
                if ! arg.is_empty() {
                    args.insert(i, arg.to_string());
                    i += 1;
                }
            }
            if i == 0 {
                args.insert(i, "/bin/sh".to_string());
            }
            execute(args)
        } else {
            Err(Error::new(ENOEXEC))
        }
    } else {
        match Elf::from(&vec) {
            Ok(executable) => {
                let entry = unsafe { executable.entry() };
                let mut memory = Vec::new();
                unsafe {
                    for segment in executable.load_segment().iter() {
                        let virtual_address = segment.vaddr as usize;
                        let virtual_size = segment.mem_len as usize;

                        let offset = virtual_address % 4096;

                        let physical_address = memory::alloc(virtual_size + offset);

                        if physical_address > 0 {
                            // Copy progbits
                            ::memcpy((physical_address + offset) as *mut u8,
                                     (executable.data.as_ptr() as usize + segment.off as usize) as *const u8,
                                     segment.file_len as usize);
                            // Zero bss
                            if segment.mem_len > segment.file_len {
                                ::memset((physical_address + offset + segment.file_len as usize) as *mut u8,
                                        0,
                                        segment.mem_len as usize - segment.file_len as usize);
                            }

                            memory.push(ContextMemory {
                                physical_address: physical_address,
                                virtual_address: virtual_address - offset,
                                virtual_size: virtual_size + offset,
                                writeable: segment.flags & 2 == 2,
                                allocated: true,
                            });
                        }
                    }
                }

                if entry > 0 && ! memory.is_empty() {
                    let mut contexts = ::env().contexts.lock();
                    let mut context = try!(contexts.current_mut());

                    //debugln!("{}: {}: execute {}", context.pid, context.name, url.string);

                    context.name = url.string;
                    context.cwd = Arc::new(UnsafeCell::new(unsafe { (*context.cwd.get()).clone() }));

                    unsafe { context.unmap() };
                    context.memory = Arc::new(UnsafeCell::new(memory));
                    unsafe { context.map() };

                    execute_thread(context.deref_mut(), entry, args);
                } else {
                    Err(Error::new(ENOEXEC))
                }
            },
            Err(msg) => {
                debugln!("execute: failed to exec '{}': {}", url.string, msg);
                Err(Error::new(ENOEXEC))
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>feat(geektime_algo): add 39 back tracking bag_exec<commit_after>use std::collections::HashMap;

fn solve_bag(items: Vec<(i32, i32)>, capacity: i32) -> HashMap<i32, Vec<i32>> {
    let pick_idx       = 0;
    let current_weight = 0;
    let mut picks      = vec![-1; items.len()];
    let mut max_values = vec![-1; items.len()];
    let mut result     = HashMap::new();

    bag(pick_idx,
        current_weight,
        &items,
        capacity,
        &mut picks,
        &mut max_values,
        &mut result,);

    result
}

fn bag(pick_idx:       i32,
       current_weight: i32,
       items:          &Vec<(i32, i32)>,
       capacity:       i32,
       picks:          &mut Vec<i32>,
       max_values:     &mut Vec<i32>,
       result:         &mut HashMap<i32, Vec<i32>>) {
   if current_weight == capacity || pick_idx == items.len() as i32 {
       if get_value(items, &picks) > get_value(items, max_values) {
           for i in 0..picks.len() {
            max_values[i] = picks[i];
           }
           result.insert(get_value(items, max_values), picks.to_vec());
       }
       return;
   }

   // 选
   let item_weight = items[pick_idx as usize].0;
   if current_weight + item_weight <= capacity {
       picks[pick_idx as usize] = 1;
       bag(pick_idx + 1,
           current_weight + item_weight,
           items,
           capacity,
           picks,
           max_values,
           result);
   }

   // 不选
   picks[pick_idx as usize] = 0;
   bag(pick_idx + 1,
       current_weight,
       items,
       capacity,
       picks,
       max_values,
       result);

}

fn get_value(items: &Vec<(i32, i32)>, picks: &Vec<i32>) -> i32 {
    let mut result = 0;
    for i in 0..picks.len() {
        if picks[i] == 1 { result += items[i].1; }
    }
    result
}

fn main() {
    // [(weight, value)...]
    let items = vec![(3, 5), (2, 2), (1, 4), (1, 2), (4, 10)];
    let m = solve_bag(items, 10);
    println!("{:?}", m); // {13: [1, 1, 1, 1, 0], 21: [1, 1, 1, 0, 1]}
}
<|endoftext|>


<commit_before><commit_msg>[No-auto] lib/entry/ref: Fix Clippy warnings<commit_after><|endoftext|>


<commit_before><commit_msg>Add problem #6<commit_after>use std;

fn sum_of_square(n: u64) -> u64 {
    ret n * (n + 1u64) * (2u64 * n + 1u64) / 6u64;
}

fn sum_of_seq(n: u64) -> u64 {
    ret n * (n + 1u64) / 2u64;
}

fn square_of_sum(n: u64) -> u64 {
    let s = sum_of_seq(n);
    ret s * s;
}

fn main() {
    let sq_of_sum = square_of_sum(100u64);
    let sum_of_sq = sum_of_square(100u64);
    std::io::println(#fmt("%u - %u = %u", sq_of_sum, sum_of_sq, sq_of_sum - sum_of_sq));
}
<|endoftext|>


<commit_before><commit_msg>add dumb Mounter<commit_after>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use logger;
use env;

pub struct Mounter {
}

impl Mounter {

    pub fn new() -> Mounter {
        //
        //TODO
        //
        Mounter{}
    }

    pub fn mount(&self, l: &logger::Logger, e: &env::Env) {
        //
        //TODO
        //
    }
}
<|endoftext|>


<commit_before><commit_msg>Add more examples of define_dummy_packet/network_bytes<commit_after><|endoftext|>


<commit_before>use std::path::PathBuf;

use git2::{Index, Repository};
use toml::Value;

use libimagerror::into::IntoError;
use libimagerror::trace::{MapErrTrace, trace_error};
use libimagstore::hook::error::CustomData;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::result::HookResult;
use libimagutil::debug_result::*;

use vcs::git::action::StoreAction;
use vcs::git::result::Result;
use vcs::git::error::{MapErrInto, GitHookErrorKind as GHEK};

/// Runtime object for git hook implementations.
///
/// Contains some utility functionality to hold the repository and the configuration for the hooks.
pub struct Runtime {
    repository: Option<Repository>,
    config: Option<Value>,
}

impl Runtime {

    /// Build a `Runtime` object, pass the store path to build the `Repository` instance the
    /// `Runtime` has to contain.
    ///
    /// If the building of the `Repository` fails, this function `trace_error()`s the error and
    /// returns a `Runtime` object that does _not_ contain a `Repository`.
    pub fn new(storepath: &PathBuf) -> Runtime {
        Runtime {
            repository: Repository::open(storepath).map_err_trace().ok(),
            config: None,
        }
    }

    /// Set the configuration for the `Runtime`. Always returns `Ok(())`.
    pub fn set_config(&mut self, cfg: &Value) -> Result<()> {
        self.config = Some(cfg.clone());
        Ok(())
    }

    /// Check whether the `Runtime` has a `Repository`
    pub fn has_repository(&self) -> bool {
        self.repository.is_some()
    }

    /// Check whether the `Runtime` has a configuration
    pub fn has_config(&self) -> bool {
        self.config.is_some()
    }

    /// Get the the config value by reference or get an `Err()` which can be returned to the callee
    /// of the Hook.
    ///
    /// The `action` Argument is required in case of `Err()` so the error message can be build
    /// correctly.
    pub fn config_value_or_err(&self, action: &StoreAction) -> HookResult<&Value> {
        self.config
            .as_ref()
            .ok_or(GHEK::NoConfigError.into_error())
            .map_err_into(GHEK::ConfigError)
            .map_err(Box::new)
            .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e))
            .map_err(|mut e| e.with_custom_data(CustomData::default().aborting(false)))
            .map_dbg_err(|_| {
                format!("[GIT {} HOOK]: Couldn't get Value object from config", action.uppercase())
            })
    }

    /// Get the `Repository` object from the `Runtime` or an `Err()` that can be returned to the
    /// callee of the Hook.
    ///
    /// The `action` Argument is required in case of `Err()` so the error message can be build
    /// correctly.
    pub fn repository(&self, action: &StoreAction) -> HookResult<&Repository> {
        use vcs::git::error::MapIntoHookError;

        debug!("[GIT {} HOOK]: Getting repository", action.uppercase());
        self.repository
            .as_ref()
            .ok_or(GHEK::MkRepo.into_error())
            .map_err_into(GHEK::RepositoryError)
            .map_into_hook_error()
            .map_dbg_err(|_| format!("[GIT {} HOOK]: Couldn't fetch Repository", action.uppercase()))
            .map_dbg(|_| format!("[GIT {} HOOK]: Repository object fetched", action.uppercase()))
    }

    /// Ensure that the branch that is put in the configuration file is checked out, if any.
    pub fn ensure_cfg_branch_is_checked_out(&self, action: &StoreAction) -> HookResult<()> {
        use vcs::git::config::ensure_branch;
        use vcs::git::config::do_checkout_ensure_branch;

        if !do_checkout_ensure_branch(self.config.as_ref()) {
            return Ok(())
        }

        debug!("[GIT {} HOOK]: Ensuring branch checkout", action.uppercase());
        let head = try!(self
                        .repository(action)
                        .and_then(|r| {
                            debug!("[GIT {} HOOK]: Repository fetched, getting head", action.uppercase());
                            r.head()
                                .map_dbg_err_str("Couldn't fetch HEAD")
                                .map_dbg_err(|e| format!("\tbecause = {:?}", e))
                                .map_err_into(GHEK::HeadFetchError)
                                .map_err(|e| e.into())
                        }));
        debug!("[GIT {} HOOK]: HEAD fetched", action.uppercase());

        // TODO: Fail if not on branch? hmmh... I'm not sure
        if !head.is_branch() {
            debug!("[GIT {} HOOK]: HEAD is not a branch", action.uppercase());
            return Err(GHEK::NotOnBranch.into_error().into());
        }
        debug!("[GIT {} HOOK]: HEAD is a branch", action.uppercase());

        // Check out appropriate branch ... or fail
        match ensure_branch(self.config.as_ref()) {
            Ok(Some(s)) => {
                debug!("[GIT {} HOOK]: We have to ensure branch: {}", action.uppercase(), s);
                match head.name().map(|name| {
                    debug!("[GIT {} HOOK]: {} == {}", action.uppercase(), name, s);
                    name == s
                }) {
                    Some(b) => {
                        if b {
                            debug!("[GIT {} HOOK]: Branch already checked out.", action.uppercase());
                            Ok(())
                        } else {
                            debug!("[GIT {} HOOK]: Branch not checked out.", action.uppercase());
                            unimplemented!()
                        }
                    },

                    None => Err(GHEK::RepositoryBranchNameFetchingError.into_error())
                        .map_err_into(GHEK::RepositoryBranchError)
                        .map_err_into(GHEK::RepositoryError),
                }
            },
            Ok(None) => {
                debug!("[GIT {} HOOK]: No branch to checkout", action.uppercase());
                Ok(())
            },

            Err(e) => Err(e).map_err_into(GHEK::RepositoryError),
        }
        .map_err(Box::new)
        .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e))
        .map_dbg_str("[GIT CREATE HOOK]: Branch checked out")
    }

    /// Check whether the WD is "dirty" - whether there is a diff to the repository
    /// This function returns false if there is no `Repository` object in the `Runtime`
    pub fn repo_is_dirty(&self, index: &Index) -> bool {
        match self.repository.as_ref() {
            Some(repo) => {
                repo.diff_index_to_workdir(Some(index), None)
                    .map_dbg_str("Fetched diff: Index <-> WD")
                    .map_dbg_err_str("Failed to fetch diff: Index <-> WD")
                    .map(|diff| diff.deltas().count() != 0)
                    .unwrap_or(false)
            },

            None => {
                debug!("No repository: Cannot fetch diff: Index <-> WD");
                false
            }
        }

    }

}

<commit_msg>Variable hasnt to be mutable<commit_after>use std::path::PathBuf;

use git2::{Index, Repository};
use toml::Value;

use libimagerror::into::IntoError;
use libimagerror::trace::{MapErrTrace, trace_error};
use libimagstore::hook::error::CustomData;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::result::HookResult;
use libimagutil::debug_result::*;

use vcs::git::action::StoreAction;
use vcs::git::result::Result;
use vcs::git::error::{MapErrInto, GitHookErrorKind as GHEK};

/// Runtime object for git hook implementations.
///
/// Contains some utility functionality to hold the repository and the configuration for the hooks.
pub struct Runtime {
    repository: Option<Repository>,
    config: Option<Value>,
}

impl Runtime {

    /// Build a `Runtime` object, pass the store path to build the `Repository` instance the
    /// `Runtime` has to contain.
    ///
    /// If the building of the `Repository` fails, this function `trace_error()`s the error and
    /// returns a `Runtime` object that does _not_ contain a `Repository`.
    pub fn new(storepath: &PathBuf) -> Runtime {
        Runtime {
            repository: Repository::open(storepath).map_err_trace().ok(),
            config: None,
        }
    }

    /// Set the configuration for the `Runtime`. Always returns `Ok(())`.
    pub fn set_config(&mut self, cfg: &Value) -> Result<()> {
        self.config = Some(cfg.clone());
        Ok(())
    }

    /// Check whether the `Runtime` has a `Repository`
    pub fn has_repository(&self) -> bool {
        self.repository.is_some()
    }

    /// Check whether the `Runtime` has a configuration
    pub fn has_config(&self) -> bool {
        self.config.is_some()
    }

    /// Get the the config value by reference or get an `Err()` which can be returned to the callee
    /// of the Hook.
    ///
    /// The `action` Argument is required in case of `Err()` so the error message can be build
    /// correctly.
    pub fn config_value_or_err(&self, action: &StoreAction) -> HookResult<&Value> {
        self.config
            .as_ref()
            .ok_or(GHEK::NoConfigError.into_error())
            .map_err_into(GHEK::ConfigError)
            .map_err(Box::new)
            .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e))
            .map_err(|e| e.with_custom_data(CustomData::default().aborting(false)))
            .map_dbg_err(|_| {
                format!("[GIT {} HOOK]: Couldn't get Value object from config", action.uppercase())
            })
    }

    /// Get the `Repository` object from the `Runtime` or an `Err()` that can be returned to the
    /// callee of the Hook.
    ///
    /// The `action` Argument is required in case of `Err()` so the error message can be build
    /// correctly.
    pub fn repository(&self, action: &StoreAction) -> HookResult<&Repository> {
        use vcs::git::error::MapIntoHookError;

        debug!("[GIT {} HOOK]: Getting repository", action.uppercase());
        self.repository
            .as_ref()
            .ok_or(GHEK::MkRepo.into_error())
            .map_err_into(GHEK::RepositoryError)
            .map_into_hook_error()
            .map_dbg_err(|_| format!("[GIT {} HOOK]: Couldn't fetch Repository", action.uppercase()))
            .map_dbg(|_| format!("[GIT {} HOOK]: Repository object fetched", action.uppercase()))
    }

    /// Ensure that the branch that is put in the configuration file is checked out, if any.
    pub fn ensure_cfg_branch_is_checked_out(&self, action: &StoreAction) -> HookResult<()> {
        use vcs::git::config::ensure_branch;
        use vcs::git::config::do_checkout_ensure_branch;

        if !do_checkout_ensure_branch(self.config.as_ref()) {
            return Ok(())
        }

        debug!("[GIT {} HOOK]: Ensuring branch checkout", action.uppercase());
        let head = try!(self
                        .repository(action)
                        .and_then(|r| {
                            debug!("[GIT {} HOOK]: Repository fetched, getting head", action.uppercase());
                            r.head()
                                .map_dbg_err_str("Couldn't fetch HEAD")
                                .map_dbg_err(|e| format!("\tbecause = {:?}", e))
                                .map_err_into(GHEK::HeadFetchError)
                                .map_err(|e| e.into())
                        }));
        debug!("[GIT {} HOOK]: HEAD fetched", action.uppercase());

        // TODO: Fail if not on branch? hmmh... I'm not sure
        if !head.is_branch() {
            debug!("[GIT {} HOOK]: HEAD is not a branch", action.uppercase());
            return Err(GHEK::NotOnBranch.into_error().into());
        }
        debug!("[GIT {} HOOK]: HEAD is a branch", action.uppercase());

        // Check out appropriate branch ... or fail
        match ensure_branch(self.config.as_ref()) {
            Ok(Some(s)) => {
                debug!("[GIT {} HOOK]: We have to ensure branch: {}", action.uppercase(), s);
                match head.name().map(|name| {
                    debug!("[GIT {} HOOK]: {} == {}", action.uppercase(), name, s);
                    name == s
                }) {
                    Some(b) => {
                        if b {
                            debug!("[GIT {} HOOK]: Branch already checked out.", action.uppercase());
                            Ok(())
                        } else {
                            debug!("[GIT {} HOOK]: Branch not checked out.", action.uppercase());
                            unimplemented!()
                        }
                    },

                    None => Err(GHEK::RepositoryBranchNameFetchingError.into_error())
                        .map_err_into(GHEK::RepositoryBranchError)
                        .map_err_into(GHEK::RepositoryError),
                }
            },
            Ok(None) => {
                debug!("[GIT {} HOOK]: No branch to checkout", action.uppercase());
                Ok(())
            },

            Err(e) => Err(e).map_err_into(GHEK::RepositoryError),
        }
        .map_err(Box::new)
        .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e))
        .map_dbg_str("[GIT CREATE HOOK]: Branch checked out")
    }

    /// Check whether the WD is "dirty" - whether there is a diff to the repository
    /// This function returns false if there is no `Repository` object in the `Runtime`
    pub fn repo_is_dirty(&self, index: &Index) -> bool {
        match self.repository.as_ref() {
            Some(repo) => {
                repo.diff_index_to_workdir(Some(index), None)
                    .map_dbg_str("Fetched diff: Index <-> WD")
                    .map_dbg_err_str("Failed to fetch diff: Index <-> WD")
                    .map(|diff| diff.deltas().count() != 0)
                    .unwrap_or(false)
            },

            None => {
                debug!("No repository: Cannot fetch diff: Index <-> WD");
                false
            }
        }

    }

}

<|endoftext|>


<commit_before><commit_msg>Rollup merge of #73362 - erikdesjardins:bounds, r=nikomatsakis<commit_after>// no-system-llvm
// compile-flags: -O
// ignore-debug: the debug assertions get in the way
#![crate_type = "lib"]

// Make sure no bounds checks are emitted in the loop when upfront slicing
// ensures that the slices are big enough.
// In particular, bounds checks were not always optimized out if the upfront
// check was for a greater len than the loop requires.
// (i.e. `already_sliced_no_bounds_check` was not always optimized even when
// `already_sliced_no_bounds_check_exact` was)
// CHECK-LABEL: @already_sliced_no_bounds_check
#[no_mangle]
pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
    // CHECK: slice_index_len_fail
    // CHECK-NOT: panic_bounds_check
    let _ = (&a[..2048], &b[..2048], &mut c[..2048]);
    for i in 0..1024 {
        c[i] = a[i] ^ b[i];
    }
}

// CHECK-LABEL: @already_sliced_no_bounds_check_exact
#[no_mangle]
pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) {
    // CHECK: slice_index_len_fail
    // CHECK-NOT: panic_bounds_check
    let _ = (&a[..1024], &b[..1024], &mut c[..1024]);
    for i in 0..1024 {
        c[i] = a[i] ^ b[i];
    }
}

// Make sure we're checking for the right thing: there can be a panic if the slice is too small.
// CHECK-LABEL: @already_sliced_bounds_check
#[no_mangle]
pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
    // CHECK: slice_index_len_fail
    // CHECK: panic_bounds_check
    let _ = (&a[..1023], &b[..2048], &mut c[..2048]);
    for i in 0..1024 {
        c[i] = a[i] ^ b[i];
    }
}
<|endoftext|>


<commit_before><commit_msg>Rollup merge of #44464 - Dushistov:master, r=alexcrichton<commit_after>// Copyright 2017 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.

pub fn example(ref s: str) {}
//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied
//~| `str` does not have a constant size known at compile-time
//~| the trait `std::marker::Sized` is not implemented for `str`

fn main() {}
<|endoftext|>


<commit_before><commit_msg>I am lazy, and start new<commit_after>fn main() {}
<|endoftext|>


<commit_before><commit_msg>Add a compile-fail test for attempts to extend non-objects.<commit_after>//error-pattern:x does not have object type
use std;

fn main() {
    auto x = 3;

    auto anon_obj = obj {
        fn foo() -> int {
            ret 3;
        }
        with x
    };
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use dbus;
use dbus::Message;
use dbus::MessageItem;
use dbus::arg::IterAppend;
use dbus::tree::Access;
use dbus::tree::EmitsChangedSignal;
use dbus::tree::Factory;
use dbus::tree::MTFn;
use dbus::tree::MethodErr;
use dbus::tree::MethodInfo;
use dbus::tree::MethodResult;
use dbus::tree::PropInfo;

use uuid::Uuid;

use engine::RenameAction;

use super::types::{DbusContext, DbusErrorEnum, OPContext, TData};

use super::util::STRATIS_BASE_PATH;
use super::util::STRATIS_BASE_SERVICE;
use super::util::code_to_message_items;
use super::util::engine_to_dbus_err;
use super::util::get_next_arg;
use super::util::get_parent;
use super::util::get_uuid;
use super::util::ok_message_items;
use super::util::ref_ok_or;

pub fn create_dbus_filesystem<'a>(dbus_context: &DbusContext,
                                  parent: dbus::Path<'static>,
                                  uuid: Uuid)
                                  -> dbus::Path<'a> {
    let f = Factory::new_fn();

    let rename_method = f.method("SetName", (), rename_filesystem)
        .in_arg(("name", "s"))
        .out_arg(("action", "b"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let name_property = f.property::<&str, _>("Name", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::False)
        .on_get(get_filesystem_name);

    let pool_property = f.property::<&dbus::Path, _>("Pool", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::Const)
        .on_get(get_parent);

    let uuid_property = f.property::<&str, _>("Uuid", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::Const)
        .on_get(get_uuid);

    let object_name = format!("{}/{}",
                              STRATIS_BASE_PATH,
                              dbus_context.get_next_id().to_string());

    let interface_name = format!("{}.{}", STRATIS_BASE_SERVICE, "filesystem");

    let object_path = f.object_path(object_name, Some(OPContext::new(parent, uuid)))
        .introspectable()
        .add(f.interface(interface_name, ())
                 .add_m(rename_method)
                 .add_p(name_property)
                 .add_p(pool_property)
                 .add_p(uuid_property));

    let path = object_path.get_name().to_owned();
    dbus_context.actions.borrow_mut().push_add(object_path);
    path
}

fn rename_filesystem(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    let message: &Message = m.msg;
    let mut iter = message.iter_init();

    let new_name: &str = try!(get_next_arg(&mut iter, 0));

    let dbus_context = m.tree.get_data();
    let object_path = m.path.get_name();
    let return_message = message.method_return();
    let default_return = MessageItem::Bool(false);

    let filesystem_path = m.tree
        .get(&object_path)
        .expect("implicit argument must be in tree");
    let filesystem_data = get_data!(filesystem_path; default_return; return_message);

    let pool_path = get_parent!(m; filesystem_data; default_return; return_message);
    let pool_uuid = &get_data!(pool_path; default_return; return_message).uuid;

    let mut engine = dbus_context.engine.borrow_mut();
    let pool = get_pool!(engine; pool_uuid; default_return; return_message);

    let msg = match pool.rename_filesystem(&filesystem_data.uuid, &new_name) {
        Ok(RenameAction::NoSource) => {
            let error_message = format!("pool {} doesn't know about filesystem {}",
                                        pool_uuid,
                                        filesystem_data.uuid);
            let (rc, rs) = code_to_message_items(DbusErrorEnum::INTERNAL_ERROR, error_message);
            return_message.append3(default_return, rc, rs)
        }
        Ok(RenameAction::Identity) => {
            let (rc, rs) = ok_message_items();
            return_message.append3(default_return, rc, rs)
        }
        Ok(RenameAction::Renamed) => {
            let (rc, rs) = ok_message_items();
            return_message.append3(MessageItem::Bool(true), rc, rs)
        }
        Err(err) => {
            let (rc, rs) = engine_to_dbus_err(&err);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append3(default_return, rc, rs)
        }
    };

    Ok(vec![msg])
}

fn get_filesystem_name(i: &mut IterAppend,
                       p: &PropInfo<MTFn<TData>, TData>)
                       -> Result<(), MethodErr> {
    let dbus_context = p.tree.get_data();
    let object_path = p.path.get_name();

    let filesystem_path = p.tree
        .get(&object_path)
        .expect("tree must contain implicit argument");
    let filesystem_data = try!(ref_ok_or(filesystem_path.get_data(),
                                         MethodErr::failed(&format!("no data for object path {}",
                                                                    &object_path))));

    let pool_path = try!(p.tree
                             .get(&filesystem_data.parent)
                             .ok_or(MethodErr::failed(&format!("no path for parent object path {}",
                                                               &filesystem_data.parent))));
    let pool_uuid = try!(ref_ok_or(pool_path.get_data(),
                                   MethodErr::failed(&format!("no data for object path {}",
                                                              &object_path))))
            .uuid;

    let mut engine = dbus_context.engine.borrow_mut();
    let pool = try!(engine
                        .get_pool(&pool_uuid)
                        .ok_or(MethodErr::failed(&format!("no pool corresponding to uuid {}",
                                                          &pool_uuid))));

    let filesystem_uuid = &filesystem_data.uuid;
    i.append(try!(pool.get_filesystem(filesystem_uuid)
                      .map(|x| MessageItem::Str(x.name().to_owned()))
                      .ok_or(MethodErr::failed(&format!("no name for filesystem with uuid {}",
                                                        &filesystem_uuid)))));
    Ok(())
}
<commit_msg>publish the devnode on dbus as a property of filesystem<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use dbus;
use dbus::Message;
use dbus::MessageItem;
use dbus::arg::IterAppend;
use dbus::tree::Access;
use dbus::tree::EmitsChangedSignal;
use dbus::tree::Factory;
use dbus::tree::MTFn;
use dbus::tree::MethodErr;
use dbus::tree::MethodInfo;
use dbus::tree::MethodResult;
use dbus::tree::PropInfo;

use uuid::Uuid;

use engine::RenameAction;

use super::types::{DbusContext, DbusErrorEnum, OPContext, TData};

use super::util::STRATIS_BASE_PATH;
use super::util::STRATIS_BASE_SERVICE;
use super::util::code_to_message_items;
use super::util::engine_to_dbus_err;
use super::util::get_next_arg;
use super::util::get_parent;
use super::util::get_uuid;
use super::util::ok_message_items;
use super::util::ref_ok_or;

pub fn create_dbus_filesystem<'a>(dbus_context: &DbusContext,
                                  parent: dbus::Path<'static>,
                                  uuid: Uuid)
                                  -> dbus::Path<'a> {
    let f = Factory::new_fn();

    let rename_method = f.method("SetName", (), rename_filesystem)
        .in_arg(("name", "s"))
        .out_arg(("action", "b"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let devnode_property = f.property::<&str, _>("Devnode", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::Const)
        .on_get(get_filesystem_devnode);

    let name_property = f.property::<&str, _>("Name", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::False)
        .on_get(get_filesystem_name);

    let pool_property = f.property::<&dbus::Path, _>("Pool", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::Const)
        .on_get(get_parent);

    let uuid_property = f.property::<&str, _>("Uuid", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::Const)
        .on_get(get_uuid);

    let object_name = format!("{}/{}",
                              STRATIS_BASE_PATH,
                              dbus_context.get_next_id().to_string());

    let interface_name = format!("{}.{}", STRATIS_BASE_SERVICE, "filesystem");

    let object_path = f.object_path(object_name, Some(OPContext::new(parent, uuid)))
        .introspectable()
        .add(f.interface(interface_name, ())
                 .add_m(rename_method)
                 .add_p(devnode_property)
                 .add_p(name_property)
                 .add_p(pool_property)
                 .add_p(uuid_property));

    let path = object_path.get_name().to_owned();
    dbus_context.actions.borrow_mut().push_add(object_path);
    path
}

fn rename_filesystem(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    let message: &Message = m.msg;
    let mut iter = message.iter_init();

    let new_name: &str = try!(get_next_arg(&mut iter, 0));

    let dbus_context = m.tree.get_data();
    let object_path = m.path.get_name();
    let return_message = message.method_return();
    let default_return = MessageItem::Bool(false);

    let filesystem_path = m.tree
        .get(&object_path)
        .expect("implicit argument must be in tree");
    let filesystem_data = get_data!(filesystem_path; default_return; return_message);

    let pool_path = get_parent!(m; filesystem_data; default_return; return_message);
    let pool_uuid = &get_data!(pool_path; default_return; return_message).uuid;

    let mut engine = dbus_context.engine.borrow_mut();
    let pool = get_pool!(engine; pool_uuid; default_return; return_message);

    let msg = match pool.rename_filesystem(&filesystem_data.uuid, &new_name) {
        Ok(RenameAction::NoSource) => {
            let error_message = format!("pool {} doesn't know about filesystem {}",
                                        pool_uuid,
                                        filesystem_data.uuid);
            let (rc, rs) = code_to_message_items(DbusErrorEnum::INTERNAL_ERROR, error_message);
            return_message.append3(default_return, rc, rs)
        }
        Ok(RenameAction::Identity) => {
            let (rc, rs) = ok_message_items();
            return_message.append3(default_return, rc, rs)
        }
        Ok(RenameAction::Renamed) => {
            let (rc, rs) = ok_message_items();
            return_message.append3(MessageItem::Bool(true), rc, rs)
        }
        Err(err) => {
            let (rc, rs) = engine_to_dbus_err(&err);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append3(default_return, rc, rs)
        }
    };

    Ok(vec![msg])
}

/// Get the devnode for an object path.
fn get_filesystem_devnode(i: &mut IterAppend,
                          p: &PropInfo<MTFn<TData>, TData>)
                          -> Result<(), MethodErr> {
    let dbus_context = p.tree.get_data();
    let object_path = p.path.get_name();

    let filesystem_path = p.tree
        .get(&object_path)
        .expect("tree must contain implicit argument");
    let filesystem_data = try!(ref_ok_or(filesystem_path.get_data(),
                                         MethodErr::failed(&format!("no data for object path {}",
                                                                    &object_path))));
    let pool_path = try!(p.tree
                             .get(&filesystem_data.parent)
                             .ok_or(MethodErr::failed(&format!("no path for parent object path {}",
                                                               &filesystem_data.parent))));
    let pool_uuid = try!(ref_ok_or(pool_path.get_data(),
                                   MethodErr::failed(&format!("no data for object path {}",
                                                              &object_path))))
            .uuid;
    let mut engine = dbus_context.engine.borrow_mut();
    let pool = try!(engine
                        .get_pool(&pool_uuid)
                        .ok_or(MethodErr::failed(&format!("no pool corresponding to uuid {}",
                                                          &pool_uuid))));
    let filesystem_uuid = &filesystem_data.uuid;
    let filesystem = try!(pool.get_filesystem(filesystem_uuid)
        .ok_or(MethodErr::failed(&format!("no name for filesystem with uuid {}",
                                          &filesystem_uuid))));
    let devnode = try!(filesystem
        .devnode()
        .map_err(|_| {
                     MethodErr::failed(&format!("no devnode for filesystem with uuid {}",
                                                &filesystem_uuid))
                 }));
    i.append(MessageItem::Str(format!("{}", devnode.display())));
    Ok(())
}

fn get_filesystem_name(i: &mut IterAppend,
                       p: &PropInfo<MTFn<TData>, TData>)
                       -> Result<(), MethodErr> {
    let dbus_context = p.tree.get_data();
    let object_path = p.path.get_name();

    let filesystem_path = p.tree
        .get(&object_path)
        .expect("tree must contain implicit argument");
    let filesystem_data = try!(ref_ok_or(filesystem_path.get_data(),
                                         MethodErr::failed(&format!("no data for object path {}",
                                                                    &object_path))));

    let pool_path = try!(p.tree
                             .get(&filesystem_data.parent)
                             .ok_or(MethodErr::failed(&format!("no path for parent object path {}",
                                                               &filesystem_data.parent))));
    let pool_uuid = try!(ref_ok_or(pool_path.get_data(),
                                   MethodErr::failed(&format!("no data for object path {}",
                                                              &object_path))))
            .uuid;

    let mut engine = dbus_context.engine.borrow_mut();
    let pool = try!(engine
                        .get_pool(&pool_uuid)
                        .ok_or(MethodErr::failed(&format!("no pool corresponding to uuid {}",
                                                          &pool_uuid))));

    let filesystem_uuid = &filesystem_data.uuid;
    i.append(try!(pool.get_filesystem(filesystem_uuid)
                      .map(|x| MessageItem::Str(x.name().to_owned()))
                      .ok_or(MethodErr::failed(&format!("no name for filesystem with uuid {}",
                                                        &filesystem_uuid)))));
    Ok(())
}
<|endoftext|>


<commit_before>use super::{
    FnEvalContext,
    CachedMir,
    TerminatorTarget,
    ConstantId,
    GlobalEvalContext
};
use error::EvalResult;
use rustc::mir::repr as mir;
use rustc::ty::subst::{self, Subst};
use rustc::hir::def_id::DefId;
use rustc::mir::visit::{Visitor, LvalueContext};
use syntax::codemap::Span;
use std::rc::Rc;

pub enum Event {
    Constant,
    Assignment,
    Terminator,
    Done,
}

pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{
    fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>,
    mir: CachedMir<'mir, 'tcx>,
    process: fn (&mut Stepper<'fncx, 'a, 'b, 'mir, 'tcx>) -> EvalResult<()>,
}

impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx> {
    pub(super) fn new(fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>) -> Self {
        Stepper {
            mir: fncx.mir(),
            fncx: fncx,
            process: Self::dummy,
        }
    }

    fn dummy(&mut self) -> EvalResult<()> { Ok(()) }

    fn statement(&mut self) -> EvalResult<()> {
        let block_data = self.mir.basic_block_data(self.fncx.frame().next_block);
        let stmt = &block_data.statements[self.fncx.frame().stmt];
        let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
        let result = self.fncx.eval_assignment(lvalue, rvalue);
        self.fncx.maybe_report(stmt.span, result)?;
        self.fncx.frame_mut().stmt += 1;
        Ok(())
    }

    fn terminator(&mut self) -> EvalResult<()> {
        // after a terminator we go to a new block
        self.fncx.frame_mut().stmt = 0;
        let term = {
            let block_data = self.mir.basic_block_data(self.fncx.frame().next_block);
            let terminator = block_data.terminator();
            let result = self.fncx.eval_terminator(terminator);
            self.fncx.maybe_report(terminator.span, result)?
        };
        match term {
            TerminatorTarget::Block => {},
            TerminatorTarget::Return => {
                assert!(self.fncx.frame().constants.is_empty());
                self.fncx.pop_stack_frame();
                if !self.fncx.stack.is_empty() {
                    self.mir = self.fncx.mir();
                }
            },
            TerminatorTarget::Call => {
                self.mir = self.fncx.mir();
            },
        }
        Ok(())
    }

    fn constant(&mut self) -> EvalResult<()> {
        let (cid, span, return_ptr, mir) = self.fncx.frame_mut().constants.pop().expect("state machine broken");
        let def_id = cid.def_id();
        let substs = cid.substs();
        self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr));
        self.mir = self.fncx.mir();
        Ok(())
    }

    pub fn step(&mut self) -> EvalResult<Event> {
        (self.process)(self)?;

        if self.fncx.stack.is_empty() {
            // fuse the iterator
            self.process = Self::dummy;
            return Ok(Event::Done);
        }

        if !self.fncx.frame().constants.is_empty() {
            self.process = Self::constant;
            return Ok(Event::Constant);
        }

        let block = self.fncx.frame().next_block;
        let stmt = self.fncx.frame().stmt;
        let basic_block = self.mir.basic_block_data(block);

        if let Some(ref stmt) = basic_block.statements.get(stmt) {
            assert!(self.fncx.frame().constants.is_empty());
            ConstantExtractor {
                span: stmt.span,
                mir: &self.mir,
                gecx: self.fncx.gecx,
                frame: self.fncx.stack.last_mut().expect("stack empty"),
            }.visit_statement(block, stmt);
            if self.fncx.frame().constants.is_empty() {
                self.process = Self::statement;
                return Ok(Event::Assignment);
            } else {
                self.process = Self::constant;
                return Ok(Event::Constant);
            }
        }

        let terminator = basic_block.terminator();
        assert!(self.fncx.frame().constants.is_empty());
        ConstantExtractor {
            span: terminator.span,
            mir: &self.mir,
            gecx: self.fncx.gecx,
            frame: self.fncx.stack.last_mut().expect("stack empty"),
        }.visit_terminator(block, terminator);
        if self.fncx.frame().constants.is_empty() {
            self.process = Self::terminator;
            Ok(Event::Terminator)
        } else {
            self.process = Self::constant;
            Ok(Event::Constant)
        }
    }

    /// returns the statement that will be processed next
    pub fn stmt(&self) -> &mir::Statement {
        &self.fncx.basic_block().statements[self.fncx.frame().stmt]
    }

    /// returns the terminator of the current block
    pub fn term(&self) -> &mir::Terminator {
        self.fncx.basic_block().terminator()
    }

    pub fn block(&self) -> mir::BasicBlock {
        self.fncx.frame().next_block
    }
}

struct ConstantExtractor<'a, 'b: 'mir, 'mir: 'a, 'tcx: 'b> {
    span: Span,
    mir: &'a CachedMir<'mir, 'tcx>,
    frame: &'a mut Frame<'mir, 'tcx>,
    gecx: &'a mut GlobalEvalContext<'b, 'tcx>,
}

impl<'a, 'b, 'mir, 'tcx> ConstantExtractor<'a, 'b, 'mir, 'tcx> {
    fn static_item(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span) {
        let cid = ConstantId::Static {
            def_id: def_id,
            substs: substs,
        };
        if self.gecx.statics.contains_key(&cid) {
            return;
        }
        let mir = self.gecx.load_mir(def_id);
        let ptr = self.gecx.alloc_ret_ptr(mir.return_ty, substs).expect("there's no such thing as an unreachable static");
        self.gecx.statics.insert(cid.clone(), ptr);
        self.frame.constants.push((cid, span, ptr, mir));
    }
}

impl<'a, 'b, 'mir, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'mir, 'tcx> {
    fn visit_constant(&mut self, constant: &mir::Constant<'tcx>) {
        self.super_constant(constant);
        match constant.literal {
            // already computed by rustc
            mir::Literal::Value { .. } => {}
            mir::Literal::Item { def_id, substs } => {
                let item_ty = self.gecx.tcx.lookup_item_type(def_id).subst(self.gecx.tcx, substs);
                if item_ty.ty.is_fn() {
                    // unimplemented
                } else {
                    self.static_item(def_id, substs, constant.span);
                }
            },
            mir::Literal::Promoted { index } => {
                let cid = ConstantId::Promoted {
                    def_id: self.frame.def_id,
                    substs: self.frame.substs,
                    index: index,
                };
                if self.gecx.statics.contains_key(&cid) {
                    return;
                }
                let mir = self.mir.promoted[index].clone();
                let return_ty = mir.return_ty;
                let return_ptr = self.gecx.alloc_ret_ptr(return_ty, cid.substs()).expect("there's no such thing as an unreachable static");
                let mir = CachedMir::Owned(Rc::new(mir));
                self.gecx.statics.insert(cid.clone(), return_ptr);
                self.frame.constants.push((cid, constant.span, return_ptr, mir));
            }
        }
    }

    fn visit_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>, context: LvalueContext) {
        self.super_lvalue(lvalue, context);
        if let mir::Lvalue::Static(def_id) = *lvalue {
            let substs = self.gecx.tcx.mk_substs(subst::Substs::empty());
            let span = self.span;
            self.static_item(def_id, substs, span);
        }
    }
}
<commit_msg>don't cache the MIR in the Stepper<commit_after>use super::{
    FnEvalContext,
    CachedMir,
    TerminatorTarget,
    ConstantId,
    GlobalEvalContext
};
use error::EvalResult;
use rustc::mir::repr as mir;
use rustc::ty::subst::{self, Subst};
use rustc::hir::def_id::DefId;
use rustc::mir::visit::{Visitor, LvalueContext};
use syntax::codemap::Span;
use std::rc::Rc;

pub enum Event {
    Constant,
    Assignment,
    Terminator,
    Done,
}

pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{
    fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>,
    process: fn (&mut Stepper<'fncx, 'a, 'b, 'mir, 'tcx>) -> EvalResult<()>,
}

impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx> {
    pub(super) fn new(fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>) -> Self {
        Stepper {
            fncx: fncx,
            process: Self::dummy,
        }
    }

    fn dummy(&mut self) -> EvalResult<()> { Ok(()) }

    fn statement(&mut self) -> EvalResult<()> {
        let mir = self.fncx.mir();
        let block_data = mir.basic_block_data(self.fncx.frame().next_block);
        let stmt = &block_data.statements[self.fncx.frame().stmt];
        let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
        let result = self.fncx.eval_assignment(lvalue, rvalue);
        self.fncx.maybe_report(stmt.span, result)?;
        self.fncx.frame_mut().stmt += 1;
        Ok(())
    }

    fn terminator(&mut self) -> EvalResult<()> {
        // after a terminator we go to a new block
        self.fncx.frame_mut().stmt = 0;
        let term = {
            let mir = self.fncx.mir();
            let block_data = mir.basic_block_data(self.fncx.frame().next_block);
            let terminator = block_data.terminator();
            let result = self.fncx.eval_terminator(terminator);
            self.fncx.maybe_report(terminator.span, result)?
        };
        match term {
            TerminatorTarget::Block => {},
            TerminatorTarget::Return => {
                assert!(self.fncx.frame().constants.is_empty());
                self.fncx.pop_stack_frame();
            },
            TerminatorTarget::Call => {},
        }
        Ok(())
    }

    fn constant(&mut self) -> EvalResult<()> {
        let (cid, span, return_ptr, mir) = self.fncx.frame_mut().constants.pop().expect("state machine broken");
        let def_id = cid.def_id();
        let substs = cid.substs();
        self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr));
        Ok(())
    }

    pub fn step(&mut self) -> EvalResult<Event> {
        (self.process)(self)?;

        if self.fncx.stack.is_empty() {
            // fuse the iterator
            self.process = Self::dummy;
            return Ok(Event::Done);
        }

        if !self.fncx.frame().constants.is_empty() {
            self.process = Self::constant;
            return Ok(Event::Constant);
        }

        let block = self.fncx.frame().next_block;
        let stmt = self.fncx.frame().stmt;
        let mir = self.fncx.mir();
        let basic_block = mir.basic_block_data(block);

        if let Some(ref stmt) = basic_block.statements.get(stmt) {
            assert!(self.fncx.frame().constants.is_empty());
            ConstantExtractor {
                span: stmt.span,
                gecx: self.fncx.gecx,
                frame: self.fncx.stack.last_mut().expect("stack empty"),
            }.visit_statement(block, stmt);
            if self.fncx.frame().constants.is_empty() {
                self.process = Self::statement;
                return Ok(Event::Assignment);
            } else {
                self.process = Self::constant;
                return Ok(Event::Constant);
            }
        }

        let terminator = basic_block.terminator();
        assert!(self.fncx.frame().constants.is_empty());
        ConstantExtractor {
            span: terminator.span,
            gecx: self.fncx.gecx,
            frame: self.fncx.stack.last_mut().expect("stack empty"),
        }.visit_terminator(block, terminator);
        if self.fncx.frame().constants.is_empty() {
            self.process = Self::terminator;
            Ok(Event::Terminator)
        } else {
            self.process = Self::constant;
            Ok(Event::Constant)
        }
    }

    /// returns the statement that will be processed next
    pub fn stmt(&self) -> &mir::Statement {
        &self.fncx.basic_block().statements[self.fncx.frame().stmt]
    }

    /// returns the terminator of the current block
    pub fn term(&self) -> &mir::Terminator {
        self.fncx.basic_block().terminator()
    }

    pub fn block(&self) -> mir::BasicBlock {
        self.fncx.frame().next_block
    }
}

struct ConstantExtractor<'a, 'b: 'mir, 'mir: 'a, 'tcx: 'b> {
    span: Span,
    frame: &'a mut Frame<'mir, 'tcx>,
    gecx: &'a mut GlobalEvalContext<'b, 'tcx>,
}

impl<'a, 'b, 'mir, 'tcx> ConstantExtractor<'a, 'b, 'mir, 'tcx> {
    fn static_item(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span) {
        let cid = ConstantId::Static {
            def_id: def_id,
            substs: substs,
        };
        if self.gecx.statics.contains_key(&cid) {
            return;
        }
        let mir = self.gecx.load_mir(def_id);
        let ptr = self.gecx.alloc_ret_ptr(mir.return_ty, substs).expect("there's no such thing as an unreachable static");
        self.gecx.statics.insert(cid.clone(), ptr);
        self.frame.constants.push((cid, span, ptr, mir));
    }
}

impl<'a, 'b, 'mir, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'mir, 'tcx> {
    fn visit_constant(&mut self, constant: &mir::Constant<'tcx>) {
        self.super_constant(constant);
        match constant.literal {
            // already computed by rustc
            mir::Literal::Value { .. } => {}
            mir::Literal::Item { def_id, substs } => {
                let item_ty = self.gecx.tcx.lookup_item_type(def_id).subst(self.gecx.tcx, substs);
                if item_ty.ty.is_fn() {
                    // unimplemented
                } else {
                    self.static_item(def_id, substs, constant.span);
                }
            },
            mir::Literal::Promoted { index } => {
                let cid = ConstantId::Promoted {
                    def_id: self.frame.def_id,
                    substs: self.frame.substs,
                    index: index,
                };
                if self.gecx.statics.contains_key(&cid) {
                    return;
                }
                let mir = self.frame.mir.promoted[index].clone();
                let return_ty = mir.return_ty;
                let return_ptr = self.gecx.alloc_ret_ptr(return_ty, cid.substs()).expect("there's no such thing as an unreachable static");
                let mir = CachedMir::Owned(Rc::new(mir));
                self.gecx.statics.insert(cid.clone(), return_ptr);
                self.frame.constants.push((cid, constant.span, return_ptr, mir));
            }
        }
    }

    fn visit_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>, context: LvalueContext) {
        self.super_lvalue(lvalue, context);
        if let mir::Lvalue::Static(def_id) = *lvalue {
            let substs = self.gecx.tcx.mk_substs(subst::Substs::empty());
            let span = self.span;
            self.static_item(def_id, substs, span);
        }
    }
}
<|endoftext|>


<commit_before>use super::{
    CachedMir,
    ConstantId,
    GlobalEvalContext,
    ConstantKind,
};
use error::EvalResult;
use rustc::mir::repr as mir;
use rustc::ty::{subst, self};
use rustc::hir::def_id::DefId;
use rustc::mir::visit::{Visitor, LvalueContext};
use syntax::codemap::Span;
use std::rc::Rc;
use memory::Pointer;

pub struct Stepper<'fncx, 'a: 'fncx, 'tcx: 'a>{
    gecx: &'fncx mut GlobalEvalContext<'a, 'tcx>,

    // a cache of the constants to be computed before the next statement/terminator
    // this is an optimization, so we don't have to allocate a new vector for every statement
    constants: Vec<(ConstantId<'tcx>, Span, Pointer, CachedMir<'a, 'tcx>)>,
}

impl<'fncx, 'a, 'tcx> Stepper<'fncx, 'a, 'tcx> {
    pub(super) fn new(gecx: &'fncx mut GlobalEvalContext<'a, 'tcx>) -> Self {
        Stepper {
            gecx: gecx,
            constants: Vec::new(),
        }
    }

    fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<()> {
        trace!("{:?}", stmt);
        let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
        self.gecx.eval_assignment(lvalue, rvalue)?;
        self.gecx.frame_mut().stmt += 1;
        Ok(())
    }

    fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<()> {
        // after a terminator we go to a new block
        self.gecx.frame_mut().stmt = 0;
        trace!("{:?}", terminator.kind);
        self.gecx.eval_terminator(terminator)?;
        if !self.gecx.stack.is_empty() {
            trace!("// {:?}", self.gecx.frame().next_block);
        }
        Ok(())
    }

    // returns true as long as there are more things to do
    pub fn step(&mut self) -> EvalResult<bool> {
        if self.gecx.stack.is_empty() {
            return Ok(false);
        }

        let block = self.gecx.frame().next_block;
        let stmt = self.gecx.frame().stmt;
        let mir = self.gecx.mir();
        let basic_block = mir.basic_block_data(block);

        if let Some(ref stmt) = basic_block.statements.get(stmt) {
            assert!(self.constants.is_empty());
            ConstantExtractor {
                span: stmt.span,
                substs: self.gecx.substs(),
                def_id: self.gecx.frame().def_id,
                gecx: self.gecx,
                constants: &mut self.constants,
                mir: &mir,
            }.visit_statement(block, stmt);
            if self.constants.is_empty() {
                self.statement(stmt)?;
            } else {
                self.extract_constants()?;
            }
            return Ok(true);
        }

        let terminator = basic_block.terminator();
        assert!(self.constants.is_empty());
        ConstantExtractor {
            span: terminator.span,
            substs: self.gecx.substs(),
            def_id: self.gecx.frame().def_id,
            gecx: self.gecx,
            constants: &mut self.constants,
            mir: &mir,
        }.visit_terminator(block, terminator);
        if self.constants.is_empty() {
            self.terminator(terminator)?;
        } else {
            self.extract_constants()?;
        }
        Ok(true)
    }

    fn extract_constants(&mut self) -> EvalResult<()> {
        assert!(!self.constants.is_empty());
        for (cid, span, return_ptr, mir) in self.constants.drain(..) {
            trace!("queuing a constant");
            self.gecx.push_stack_frame(cid.def_id, span, mir, cid.substs, Some(return_ptr));
        }
        // self.step() can't be "done", so it can't return false
        assert!(self.step()?);
        Ok(())
    }
}

struct ConstantExtractor<'a, 'b: 'mir, 'mir: 'a, 'tcx: 'b> {
    span: Span,
    // FIXME: directly push the new stackframes instead of doing this intermediate caching
    constants: &'a mut Vec<(ConstantId<'tcx>, Span, Pointer, CachedMir<'mir, 'tcx>)>,
    gecx: &'a mut GlobalEvalContext<'b, 'tcx>,
    mir: &'a mir::Mir<'tcx>,
    def_id: DefId,
    substs: &'tcx subst::Substs<'tcx>,
}

impl<'a, 'b, 'mir, 'tcx> ConstantExtractor<'a, 'b, 'mir, 'tcx> {
    fn global_item(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span) {
        let cid = ConstantId {
            def_id: def_id,
            substs: substs,
            kind: ConstantKind::Global,
        };
        if self.gecx.statics.contains_key(&cid) {
            return;
        }
        let mir = self.gecx.load_mir(def_id);
        let ptr = self.gecx.alloc_ret_ptr(mir.return_ty, substs).expect("there's no such thing as an unreachable static");
        self.gecx.statics.insert(cid.clone(), ptr);
        self.constants.push((cid, span, ptr, mir));
    }
}

impl<'a, 'b, 'mir, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'mir, 'tcx> {
    fn visit_constant(&mut self, constant: &mir::Constant<'tcx>) {
        self.super_constant(constant);
        match constant.literal {
            // already computed by rustc
            mir::Literal::Value { .. } => {}
            mir::Literal::Item { def_id, substs } => {
                if let ty::TyFnDef(..) = constant.ty.sty {
                    // No need to do anything here, even if function pointers are implemented,
                    // because the type is the actual function, not the signature of the function.
                    // Thus we can simply create a zero sized allocation in `evaluate_operand`
                } else {
                    self.global_item(def_id, substs, constant.span);
                }
            },
            mir::Literal::Promoted { index } => {
                let cid = ConstantId {
                    def_id: self.def_id,
                    substs: self.substs,
                    kind: ConstantKind::Promoted(index),
                };
                if self.gecx.statics.contains_key(&cid) {
                    return;
                }
                let mir = self.mir.promoted[index].clone();
                let return_ty = mir.return_ty;
                let return_ptr = self.gecx.alloc_ret_ptr(return_ty, cid.substs).expect("there's no such thing as an unreachable static");
                let mir = CachedMir::Owned(Rc::new(mir));
                self.gecx.statics.insert(cid.clone(), return_ptr);
                self.constants.push((cid, constant.span, return_ptr, mir));
            }
        }
    }

    fn visit_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>, context: LvalueContext) {
        self.super_lvalue(lvalue, context);
        if let mir::Lvalue::Static(def_id) = *lvalue {
            let substs = self.gecx.tcx.mk_substs(subst::Substs::empty());
            let span = self.span;
            self.global_item(def_id, substs, span);
        }
    }
}
<commit_msg>get rid of the constants cache in the stepper<commit_after>use super::{
    CachedMir,
    ConstantId,
    GlobalEvalContext,
    ConstantKind,
};
use error::EvalResult;
use rustc::mir::repr as mir;
use rustc::ty::{subst, self};
use rustc::hir::def_id::DefId;
use rustc::mir::visit::{Visitor, LvalueContext};
use syntax::codemap::Span;
use std::rc::Rc;

pub struct Stepper<'fncx, 'a: 'fncx, 'tcx: 'a>{
    gecx: &'fncx mut GlobalEvalContext<'a, 'tcx>,
}

impl<'fncx, 'a, 'tcx> Stepper<'fncx, 'a, 'tcx> {
    pub(super) fn new(gecx: &'fncx mut GlobalEvalContext<'a, 'tcx>) -> Self {
        Stepper {
            gecx: gecx,
        }
    }

    fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<()> {
        trace!("{:?}", stmt);
        let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
        self.gecx.eval_assignment(lvalue, rvalue)?;
        self.gecx.frame_mut().stmt += 1;
        Ok(())
    }

    fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<()> {
        // after a terminator we go to a new block
        self.gecx.frame_mut().stmt = 0;
        trace!("{:?}", terminator.kind);
        self.gecx.eval_terminator(terminator)?;
        if !self.gecx.stack.is_empty() {
            trace!("// {:?}", self.gecx.frame().next_block);
        }
        Ok(())
    }

    // returns true as long as there are more things to do
    pub fn step(&mut self) -> EvalResult<bool> {
        if self.gecx.stack.is_empty() {
            return Ok(false);
        }

        let block = self.gecx.frame().next_block;
        let stmt = self.gecx.frame().stmt;
        let mir = self.gecx.mir();
        let basic_block = mir.basic_block_data(block);

        if let Some(ref stmt) = basic_block.statements.get(stmt) {
            let current_stack = self.gecx.stack.len();
            ConstantExtractor {
                span: stmt.span,
                substs: self.gecx.substs(),
                def_id: self.gecx.frame().def_id,
                gecx: self.gecx,
                mir: &mir,
            }.visit_statement(block, stmt);
            if current_stack == self.gecx.stack.len() {
                self.statement(stmt)?;
            } else {
                // ConstantExtractor added some new frames for statics/constants/promoteds
                // self.step() can't be "done", so it can't return false
                assert!(self.step()?);
            }
            return Ok(true);
        }

        let terminator = basic_block.terminator();
        let current_stack = self.gecx.stack.len();
        ConstantExtractor {
            span: terminator.span,
            substs: self.gecx.substs(),
            def_id: self.gecx.frame().def_id,
            gecx: self.gecx,
            mir: &mir,
        }.visit_terminator(block, terminator);
        if current_stack == self.gecx.stack.len() {
            self.terminator(terminator)?;
        } else {
            // ConstantExtractor added some new frames for statics/constants/promoteds
            // self.step() can't be "done", so it can't return false
            assert!(self.step()?);
        }
        Ok(true)
    }
}

// WARNING: make sure that any methods implemented on this type don't ever access gecx.stack
// this includes any method that might access the stack
// basically don't call anything other than `load_mir`, `alloc_ret_ptr`, `push_stack_frame`
// The reason for this is, that `push_stack_frame` modifies the stack out of obvious reasons
struct ConstantExtractor<'a, 'b: 'a, 'tcx: 'b> {
    span: Span,
    gecx: &'a mut GlobalEvalContext<'b, 'tcx>,
    mir: &'a mir::Mir<'tcx>,
    def_id: DefId,
    substs: &'tcx subst::Substs<'tcx>,
}

impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> {
    fn global_item(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span) {
        let cid = ConstantId {
            def_id: def_id,
            substs: substs,
            kind: ConstantKind::Global,
        };
        if self.gecx.statics.contains_key(&cid) {
            return;
        }
        let mir = self.gecx.load_mir(def_id);
        let ptr = self.gecx.alloc_ret_ptr(mir.return_ty, substs).expect("there's no such thing as an unreachable static");
        self.gecx.statics.insert(cid.clone(), ptr);
        self.gecx.push_stack_frame(def_id, span, mir, substs, Some(ptr));
    }
}

impl<'a, 'b, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx> {
    fn visit_constant(&mut self, constant: &mir::Constant<'tcx>) {
        self.super_constant(constant);
        match constant.literal {
            // already computed by rustc
            mir::Literal::Value { .. } => {}
            mir::Literal::Item { def_id, substs } => {
                if let ty::TyFnDef(..) = constant.ty.sty {
                    // No need to do anything here, even if function pointers are implemented,
                    // because the type is the actual function, not the signature of the function.
                    // Thus we can simply create a zero sized allocation in `evaluate_operand`
                } else {
                    self.global_item(def_id, substs, constant.span);
                }
            },
            mir::Literal::Promoted { index } => {
                let cid = ConstantId {
                    def_id: self.def_id,
                    substs: self.substs,
                    kind: ConstantKind::Promoted(index),
                };
                if self.gecx.statics.contains_key(&cid) {
                    return;
                }
                let mir = self.mir.promoted[index].clone();
                let return_ty = mir.return_ty;
                let return_ptr = self.gecx.alloc_ret_ptr(return_ty, cid.substs).expect("there's no such thing as an unreachable static");
                let mir = CachedMir::Owned(Rc::new(mir));
                self.gecx.statics.insert(cid.clone(), return_ptr);
                self.gecx.push_stack_frame(self.def_id, constant.span, mir, self.substs, Some(return_ptr));
            }
        }
    }

    fn visit_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>, context: LvalueContext) {
        self.super_lvalue(lvalue, context);
        if let mir::Lvalue::Static(def_id) = *lvalue {
            let substs = self.gecx.tcx.mk_substs(subst::Substs::empty());
            let span = self.span;
            self.global_item(def_id, substs, span);
        }
    }
}
<|endoftext|>


<commit_before>// The two functions returning `result` should by type compatibile
// even though they use different int types. This will probably
// not be true after #2187

#[no_core];

enum result<T, U> {
    ok(T),
    err(U)
}

type error = int;

fn get_fd() -> result<int, error> {
    getsockopt_i64()
}

fn getsockopt_i64() -> result<i64, error> {
    fail
}

fn main() { }<commit_msg>test: Fix run-pass/enum-mach-type-compat on x86<commit_after>// The two functions returning `result` should by type compatibile
// even though they use different int types. This will probably
// not be true after #2187

#[no_core];

enum result<T, U> {
    ok(T),
    err(U)
}

type error = int;

#[cfg(target_arch = "x86_64")]
fn get_fd() -> result<int, error> {
    getsockopt_i64()
}

#[cfg(target_arch = "x86_64")]
fn getsockopt_i64() -> result<i64, error> {
    fail
}

#[cfg(target_arch = "x86")]
fn get_fd() -> result<int, error> {
    getsockopt_i32()
}

#[cfg(target_arch = "x86")]
fn getsockopt_i32() -> result<i32, error> {
    fail
}

fn main() { }<|endoftext|>


<commit_before><commit_msg>add test for using target features in doctests<commit_after>// Copyright 2017 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.

// only-x86_64
// compile-flags:--test
// should-fail
// no-system-llvm

// #49723: rustdoc didn't add target features when extracting or running doctests

#![feature(doc_cfg)]

/// Foo
///
/// # Examples
///
/// ```
/// #![feature(cfg_target_feature)]
///
/// #[cfg(target_feature = "sse")]
/// assert!(false);
/// ```
#[doc(cfg(target_feature = "sse"))]
pub unsafe fn foo() {}
<|endoftext|>


<commit_before>// Copyright 2014 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.

//! Unwind library interface

#[allow(non_camel_case_types)];
#[allow(dead_code)]; // these are just bindings

use libc;

#[cfg(not(target_arch = "arm"))]
#[repr(C)]
pub enum _Unwind_Action
{
    _UA_SEARCH_PHASE = 1,
    _UA_CLEANUP_PHASE = 2,
    _UA_HANDLER_FRAME = 4,
    _UA_FORCE_UNWIND = 8,
    _UA_END_OF_STACK = 16,
}

#[cfg(target_arch = "arm")]
#[repr(C)]
pub enum _Unwind_State
{
  _US_VIRTUAL_UNWIND_FRAME = 0,
  _US_UNWIND_FRAME_STARTING = 1,
  _US_UNWIND_FRAME_RESUME = 2,
  _US_ACTION_MASK = 3,
  _US_FORCE_UNWIND = 8,
  _US_END_OF_STACK = 16
}

#[repr(C)]
pub enum _Unwind_Reason_Code {
    _URC_NO_REASON = 0,
    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
    _URC_FATAL_PHASE2_ERROR = 2,
    _URC_FATAL_PHASE1_ERROR = 3,
    _URC_NORMAL_STOP = 4,
    _URC_END_OF_STACK = 5,
    _URC_HANDLER_FOUND = 6,
    _URC_INSTALL_CONTEXT = 7,
    _URC_CONTINUE_UNWIND = 8,
    _URC_FAILURE = 9, // used only by ARM EABI
}

pub type _Unwind_Exception_Class = u64;

pub type _Unwind_Word = libc::uintptr_t;

#[cfg(target_arch = "x86")]
pub static unwinder_private_data_size: int = 5;

#[cfg(target_arch = "x86_64")]
pub static unwinder_private_data_size: int = 2;

#[cfg(target_arch = "arm")]
pub static unwinder_private_data_size: int = 20;

#[cfg(target_arch = "mips")]
pub static unwinder_private_data_size: int = 2;

pub struct _Unwind_Exception {
    exception_class: _Unwind_Exception_Class,
    exception_cleanup: _Unwind_Exception_Cleanup_Fn,
    private: [_Unwind_Word, ..unwinder_private_data_size],
}

pub enum _Unwind_Context {}

pub type _Unwind_Exception_Cleanup_Fn =
        extern "C" fn(unwind_code: _Unwind_Reason_Code,
                      exception: *_Unwind_Exception);

pub type _Unwind_Trace_Fn =
        extern "C" fn(ctx: *_Unwind_Context,
                      arg: *libc::c_void) -> _Unwind_Reason_Code;

#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "win32")]
#[link(name = "gcc_s")]
extern {}

#[cfg(target_os = "android")]
#[link(name = "gcc")]
extern {}

extern "C" {
    pub fn _Unwind_RaiseException(exception: *_Unwind_Exception)
                -> _Unwind_Reason_Code;
    pub fn _Unwind_DeleteException(exception: *_Unwind_Exception);
    pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
                             trace_argument: *libc::c_void)
                -> _Unwind_Reason_Code;
    #[cfg(stage0, not(target_os = "android"))]
    pub fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t;
    #[cfg(stage0, not(target_os = "android"))]
    pub fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void;

    #[cfg(not(stage0),
          not(target_os = "android"),
          not(target_os = "linux", target_arch = "arm"))]
    pub fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t;
    #[cfg(not(stage0),
          not(target_os = "android"),
          not(target_os = "linux", target_arch = "arm"))]
    pub fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void;
}

// On android, the function _Unwind_GetIP is a macro, and this is the expansion
// of the macro. This is all copy/pasted directly from the header file with the
// definition of _Unwind_GetIP.
#[cfg(target_os = "android")]
#[cfg(target_os = "linux", target_os = "arm")]
pub unsafe fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t {
    #[repr(C)]
    enum _Unwind_VRS_Result {
        _UVRSR_OK = 0,
        _UVRSR_NOT_IMPLEMENTED = 1,
        _UVRSR_FAILED = 2,
    }
    #[repr(C)]
    enum _Unwind_VRS_RegClass {
        _UVRSC_CORE = 0,
        _UVRSC_VFP = 1,
        _UVRSC_FPA = 2,
        _UVRSC_WMMXD = 3,
        _UVRSC_WMMXC = 4,
    }
    #[repr(C)]
    enum _Unwind_VRS_DataRepresentation {
        _UVRSD_UINT32 = 0,
        _UVRSD_VFPX = 1,
        _UVRSD_FPAX = 2,
        _UVRSD_UINT64 = 3,
        _UVRSD_FLOAT = 4,
        _UVRSD_DOUBLE = 5,
    }

    type _Unwind_Word = libc::c_uint;
    extern {
        fn _Unwind_VRS_Get(ctx: *_Unwind_Context,
                           klass: _Unwind_VRS_RegClass,
                           word: _Unwind_Word,
                           repr: _Unwind_VRS_DataRepresentation,
                           data: *mut libc::c_void) -> _Unwind_VRS_Result;
    }

    let mut val: _Unwind_Word = 0;
    let ptr = &mut val as *mut _Unwind_Word;
    let _ = _Unwind_VRS_Get(ctx, _UVRSC_CORE, 15, _UVRSD_UINT32,
                            ptr as *mut libc::c_void);
    (val & !1) as libc::uintptr_t
}

// This function also doesn't exist on android, so make it a no-op
#[cfg(target_os = "android")]
#[cfg(target_os = "linux", target_os = "arm")]
pub unsafe fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void{
    pc
}
<commit_msg>auto merge of #12922 : luqmana/rust/fix-arm, r=alexcrichton<commit_after>// Copyright 2014 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.

//! Unwind library interface

#[allow(non_camel_case_types)];
#[allow(dead_code)]; // these are just bindings

use libc;

#[cfg(not(target_arch = "arm"))]
#[repr(C)]
pub enum _Unwind_Action
{
    _UA_SEARCH_PHASE = 1,
    _UA_CLEANUP_PHASE = 2,
    _UA_HANDLER_FRAME = 4,
    _UA_FORCE_UNWIND = 8,
    _UA_END_OF_STACK = 16,
}

#[cfg(target_arch = "arm")]
#[repr(C)]
pub enum _Unwind_State
{
  _US_VIRTUAL_UNWIND_FRAME = 0,
  _US_UNWIND_FRAME_STARTING = 1,
  _US_UNWIND_FRAME_RESUME = 2,
  _US_ACTION_MASK = 3,
  _US_FORCE_UNWIND = 8,
  _US_END_OF_STACK = 16
}

#[repr(C)]
pub enum _Unwind_Reason_Code {
    _URC_NO_REASON = 0,
    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
    _URC_FATAL_PHASE2_ERROR = 2,
    _URC_FATAL_PHASE1_ERROR = 3,
    _URC_NORMAL_STOP = 4,
    _URC_END_OF_STACK = 5,
    _URC_HANDLER_FOUND = 6,
    _URC_INSTALL_CONTEXT = 7,
    _URC_CONTINUE_UNWIND = 8,
    _URC_FAILURE = 9, // used only by ARM EABI
}

pub type _Unwind_Exception_Class = u64;

pub type _Unwind_Word = libc::uintptr_t;

#[cfg(target_arch = "x86")]
pub static unwinder_private_data_size: int = 5;

#[cfg(target_arch = "x86_64")]
pub static unwinder_private_data_size: int = 2;

#[cfg(target_arch = "arm")]
pub static unwinder_private_data_size: int = 20;

#[cfg(target_arch = "mips")]
pub static unwinder_private_data_size: int = 2;

pub struct _Unwind_Exception {
    exception_class: _Unwind_Exception_Class,
    exception_cleanup: _Unwind_Exception_Cleanup_Fn,
    private: [_Unwind_Word, ..unwinder_private_data_size],
}

pub enum _Unwind_Context {}

pub type _Unwind_Exception_Cleanup_Fn =
        extern "C" fn(unwind_code: _Unwind_Reason_Code,
                      exception: *_Unwind_Exception);

pub type _Unwind_Trace_Fn =
        extern "C" fn(ctx: *_Unwind_Context,
                      arg: *libc::c_void) -> _Unwind_Reason_Code;

#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "win32")]
#[link(name = "gcc_s")]
extern {}

#[cfg(target_os = "android")]
#[link(name = "gcc")]
extern {}

extern "C" {
    pub fn _Unwind_RaiseException(exception: *_Unwind_Exception)
                -> _Unwind_Reason_Code;
    pub fn _Unwind_DeleteException(exception: *_Unwind_Exception);
    pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
                             trace_argument: *libc::c_void)
                -> _Unwind_Reason_Code;
    #[cfg(stage0, not(target_os = "android"))]
    pub fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t;
    #[cfg(stage0, not(target_os = "android"))]
    pub fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void;

    #[cfg(not(stage0),
          not(target_os = "android"),
          not(target_os = "linux", target_arch = "arm"))]
    pub fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t;
    #[cfg(not(stage0),
          not(target_os = "android"),
          not(target_os = "linux", target_arch = "arm"))]
    pub fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void;
}

// On android, the function _Unwind_GetIP is a macro, and this is the expansion
// of the macro. This is all copy/pasted directly from the header file with the
// definition of _Unwind_GetIP.
#[cfg(target_os = "android")]
#[cfg(target_os = "linux", target_arch = "arm")]
pub unsafe fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t {
    #[repr(C)]
    enum _Unwind_VRS_Result {
        _UVRSR_OK = 0,
        _UVRSR_NOT_IMPLEMENTED = 1,
        _UVRSR_FAILED = 2,
    }
    #[repr(C)]
    enum _Unwind_VRS_RegClass {
        _UVRSC_CORE = 0,
        _UVRSC_VFP = 1,
        _UVRSC_FPA = 2,
        _UVRSC_WMMXD = 3,
        _UVRSC_WMMXC = 4,
    }
    #[repr(C)]
    enum _Unwind_VRS_DataRepresentation {
        _UVRSD_UINT32 = 0,
        _UVRSD_VFPX = 1,
        _UVRSD_FPAX = 2,
        _UVRSD_UINT64 = 3,
        _UVRSD_FLOAT = 4,
        _UVRSD_DOUBLE = 5,
    }

    type _Unwind_Word = libc::c_uint;
    extern {
        fn _Unwind_VRS_Get(ctx: *_Unwind_Context,
                           klass: _Unwind_VRS_RegClass,
                           word: _Unwind_Word,
                           repr: _Unwind_VRS_DataRepresentation,
                           data: *mut libc::c_void) -> _Unwind_VRS_Result;
    }

    let mut val: _Unwind_Word = 0;
    let ptr = &mut val as *mut _Unwind_Word;
    let _ = _Unwind_VRS_Get(ctx, _UVRSC_CORE, 15, _UVRSD_UINT32,
                            ptr as *mut libc::c_void);
    (val & !1) as libc::uintptr_t
}

// This function also doesn't exist on android or arm/linux, so make it a no-op
#[cfg(target_os = "android")]
#[cfg(target_os = "linux", target_arch = "arm")]
pub unsafe fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void {
    pc
}
<|endoftext|>


<commit_before><commit_msg>Shut up warnings.<commit_after><|endoftext|>


<commit_before><commit_msg>hash index added; not tested<commit_after>
pub struct HashIndex<K: Eq, V, F: Fn(&K)->u64> {
    bucket: F,
    buffer: Vec<Option<(K,V)>>,
    count:  usize,
    shift:  usize,
    slop:   usize,
}

impl<K: Eq, V, F: Fn(&K)->u64> HashIndex<K, V, F> {
    pub fn new(function: F) -> HashIndex<K, V, F> {
        let slop = 16;
        let mut buffer = Vec::with_capacity(2 + slop);
        for _ in 0..buffer.capacity() { buffer.push(None); }
        HashIndex {
            bucket: function,
            buffer: buffer,
            count: 0,
            shift: 63,
            slop: slop,
        }
    }
    pub fn capacity(&self) -> usize { self.buffer.capacity() }

    pub fn get_ref<'a>(&'a self, query: &K) -> Option<&'a V> {

        let target = (self.bucket)(query) >> self.shift;
        let mut iterator = self.buffer[target as usize ..].iter().map(|x| x.as_ref());
        while let Some(Some(&(ref key, ref val))) = iterator.next() {
            let found = (self.bucket)(key) >> self.shift;
            if found >= target {
                if key == query {
                    return Some(val);
                }
                else {
                    return None;
                }
            }
        }

        return None;
    }

    pub fn get_mut<'a>(&'a mut self, query: &K) -> Option<&'a V> {

        let target = (self.bucket)(query) >> self.shift;
        let mut iterator = self.buffer[target as usize ..].iter_mut().map(|x| x.as_ref());
        while let Some(Some(&(ref key, ref val))) = iterator.next() {
            let found = (self.bucket)(key) >> self.shift;
            if found == target && key == query {
                return Some(val);
            }
            if found > target {
                return None;
            }
        }

        return None;
    }

    pub fn entry_or_insert<G: FnMut()->V>(&mut self, key: K, mut func: G) -> &mut V {

        let target = (self.bucket)(&key) >> self.shift;

        let mut success = false;
        let mut position = target as usize;
        while position < self.buffer.len() {
            if let Some(ref mut kv) = self.buffer[position].as_mut() {
                let found = (self.bucket)(&kv.0) >> self.shift;
                if found == target && key == kv.0 {
                    success = true;
                    break;
                }
                if found > target { break; }
            }
            else { break; }

            position += 1;
        }

        if success { return &mut self.buffer[position].as_mut().unwrap().1; }
        else {
            // position now points at the place where the value should go.
            // we may need to slide everyone from there forward until a None.
            let begin = position;
            while position < self.buffer.len() && self.buffer[position].is_some() {
                position += 1;
            }

            if position < self.buffer.len() {

                for i in 0..(position - begin) {
                    self.buffer.swap(position - i - 1, position - i);
                }

                assert!(self.buffer[begin].is_none());
                self.buffer[begin] = Some((key, func()));
                self.count += 1;
                &mut self.buffer[begin].as_mut().unwrap().1
            }
            else {
                // println!("resizing: load at {}", self.count as f64 / self.buffer.capacity() as f64);

                let old_length = self.buffer.len() - self.slop;
                let mut new_buffer = Vec::with_capacity(2 * old_length + self.slop);
                for _ in 0..new_buffer.capacity() {
                    new_buffer.push(None);
                }
                let old_buffer = ::std::mem::replace(&mut self.buffer, new_buffer);
                self.shift -= 1;

                let mut cursor = 0;
                for oldkeyval in old_buffer.into_iter() {
                    if let Some((oldkey, oldval)) = oldkeyval {
                        let target = (self.bucket)(&oldkey) >> self.shift;
                        cursor = ::std::cmp::max(cursor, target);
                        self.buffer[cursor as usize] = Some((oldkey, oldval));
                        cursor += 1;
                    }
                }

                self.entry_or_insert(key, func)
            }
        }
    }

    pub fn remove_key(&mut self, key: &K) -> Option<V> {

        let target = (self.bucket)(&key) >> self.shift;

        let mut success = false;
        let mut position = target as usize;
        while position < self.buffer.len() {
            if let Some(ref mut kv) = self.buffer[position].as_mut() {
                let found = (self.bucket)(&kv.0) >> self.shift;
                if found == target && key == &kv.0 {
                    success = true;
                    break;
                }
                if found > target { break; }
            }
            else { break; }

            position += 1;
        }

        if success {
            let result = self.buffer[position].take();

            // now propagate the None forward as long as records are past their preferred location
            while position + 1 < self.buffer.len()
               && self.buffer[position].is_some()
               && (self.bucket)(&self.buffer[position].as_ref().unwrap().0) >> self.shift <= position as u64 {
                self.buffer.swap(position, position + 1);
            }

            result.map(|(_,v)| v)
        }
        else {
            None
        }
    }
}
<|endoftext|>