<commit_before>/*!
`ed25519`, a signature scheme specified in
[Ed25519](http://ed25519.cr.yp.to/). This function is conjectured to meet the
standard notion of unforgeability for a public-key signature scheme under
chosen-message attacks.
*/
extern crate extra;
use std::libc::{c_ulonglong, c_int};
use std::vec::{from_elem};

#[link(name = "sodium")]
extern {
    fn crypto_sign_ed25519_keypair(pk: *mut u8,
                                   sk: *mut u8) -> c_int;
    fn crypto_sign_ed25519_seed_keypair(pk: *mut u8,
                                        sk: *mut u8,
                                        seed: *u8) -> c_int;
    fn crypto_sign_ed25519(sm: *mut u8,
                           smlen: *mut c_ulonglong,
                           m: *u8,
                           mlen: c_ulonglong,
                           sk: *u8) -> c_int;
    fn crypto_sign_ed25519_open(m: *mut u8,
                                mlen: *mut c_ulonglong,
                                sm: *u8,
                                smlen: c_ulonglong,
                                pk: *u8) -> c_int;
}

pub static SEEDBYTES: uint = 32;
pub static SECRETKEYBYTES: uint = 64;
pub static PUBLICKEYBYTES: uint = 32;
pub static SIGNATUREBYTES: uint = 64;

/**
 * `Seed` that can be used for keypair generation
 *
 * The `Seed` is used by `keypair_from_seed()` to generate
 * a secret and public signature key.
 *
 * When a `Seed` goes out of scope its contents
 * will be zeroed out
 */
pub struct Seed([u8, ..SEEDBYTES]);
impl Drop for Seed {
    fn drop(&mut self) {
        let &Seed(ref mut s) = self;
        for e in s.mut_iter() { *e = 0 }
    }
}

/**
 * `SecretKey` for signatures
 *
 * When a `SecretKey` goes out of scope its contents
 * will be zeroed out
 */
pub struct SecretKey([u8, ..SECRETKEYBYTES]);
impl Drop for SecretKey {
    fn drop(&mut self) {
        let &SecretKey(ref mut sk) = self;
        for e in sk.mut_iter() { *e = 0 }
    }
}
/**
 * `PublicKey` for signatures
 */
pub struct PublicKey([u8, ..PUBLICKEYBYTES]);

/**
 * `gen_keypair()` randomly generates a secret key and a corresponding public
 * key.
 *
 * THREAD SAFETY: `gen_keypair()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_keypair() -> (PublicKey, SecretKey) {
    unsafe {
        let mut pk = [0u8, ..PUBLICKEYBYTES];
        let mut sk = [0u8, ..SECRETKEYBYTES];
        crypto_sign_ed25519_keypair(pk.as_mut_ptr(), sk.as_mut_ptr());
        (PublicKey(pk), SecretKey(sk))
    }
}

/**
 * `keypair_from_seed()` computes a secret key and a corresponding public key
 * from a `Seed`.
 */
pub fn keypair_from_seed(&Seed(seed): &Seed) -> (PublicKey, SecretKey) {
    unsafe {
        let mut pk = [0u8, ..PUBLICKEYBYTES];
        let mut sk = [0u8, ..SECRETKEYBYTES];
        crypto_sign_ed25519_seed_keypair(pk.as_mut_ptr(),
                                         sk.as_mut_ptr(),
                                         seed.as_ptr());
        (PublicKey(pk), SecretKey(sk))
    }
}

/**
 * `sign()` signs a message `m` using the signer's secret key `sk`.
 * `sign()` returns the resulting signed message `sm`.
 */
pub fn sign(m: &[u8],
            &SecretKey(sk): &SecretKey) -> ~[u8] {
    unsafe {
        let mut sm = from_elem(m.len() + SIGNATUREBYTES, 0u8);
        let mut smlen = 0;
        crypto_sign_ed25519(sm.as_mut_ptr(),
                            &mut smlen,
                            m.as_ptr(),
                            m.len() as c_ulonglong,
                            sk.as_ptr());
        sm.truncate(smlen as uint);
        sm
    }
}

/**
 * `verify()` verifies the signature in `sm` using the signer's public key `pk`.
 * `verify()` returns the message `Some(m)`.
 * If the signature fails verification, `verify()` returns `None`.
 */
pub fn verify(sm: &[u8],
              &PublicKey(pk): &PublicKey) -> Option<~[u8]> {
    unsafe {
        let mut m = from_elem(sm.len(), 0u8);
        let mut mlen = 0;
        if crypto_sign_ed25519_open(m.as_mut_ptr(),
                                    &mut mlen,
                                    sm.as_ptr(),
                                    sm.len() as c_ulonglong,
                                    pk.as_ptr()) == 0 {
            m.truncate(mlen as uint);
            Some(m)
        } else {
            None
        }
    }
}

#[test]
fn test_sign_verify() {
    use randombytes::randombytes;
    for i in range(0, 256) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i as uint);
        let sm = sign(m, &sk);
        let m2 = verify(sm, &pk);
        assert!(Some(m) == m2);
    }
}

#[test]
fn test_sign_verify_tamper() {
    use randombytes::randombytes;
    for i in range(0, 32) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i as uint);
        let mut sm = sign(m, &sk);
        for j in range(0, sm.len()) {
            sm[j] ^= 0x20;
            assert!(None == verify(sm, &pk));
            sm[j] ^= 0x20;
        }
    }
}

#[test]
fn test_sign_verify_seed() {
    use randombytes::{randombytes, randombytes_into};
    for i in range(0, 256) {
        let mut seedbuf = [0, ..32];
        randombytes_into(seedbuf);
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = randombytes(i as uint);
        let sm = sign(m, &sk);
        let m2 = verify(sm, &pk);
        assert!(Some(m) == m2);
    }
}

#[test]
fn test_sign_verify_tamper_seed() {
    use randombytes::{randombytes, randombytes_into};
    for i in range(0, 32) {
        let mut seedbuf = [0, ..32];
        randombytes_into(seedbuf);
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = randombytes(i as uint);
        let mut sm = sign(m, &sk);
        for j in range(0, sm.len()) {
            sm[j] ^= 0x20;
            assert!(None == verify(sm, &pk));
            sm[j] ^= 0x20;
        }
    }
}

#[test]
fn test_vectors() {
    // test vectors from the Python implementation
    // form the [Ed25519 Homepage](http://ed25519.cr.yp.to/software.html)
    use self::serialize::hex::{FromHex, ToHex};
    use std::io::buffered::BufferedReader;
    use std::io::File;
    use std::path::Path;

    let p = &Path::new("testvectors/ed25519.input");
    let mut r = BufferedReader::new(File::open(p).unwrap());
    loop {
        let line = match r.read_line() {
            None => break,
            Some(line) => line
        };
        let mut x = line.split(':');
        let x0 = x.next().unwrap();
        let x1 = x.next().unwrap();
        let x2 = x.next().unwrap();
        let x3 = x.next().unwrap();
        let seed_bytes = x0.slice(0, 64).from_hex().unwrap();
        assert!(seed_bytes.len() == SEEDBYTES);
        let mut seedbuf = [0u8, ..SEEDBYTES];
        for (s, b) in seedbuf.mut_iter().zip(seed_bytes.iter()) {
            *s = *b
        }
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = x2.from_hex().unwrap();
        let sm = sign(m, &sk);
        verify(sm, &pk).unwrap();
        let PublicKey(pkbuf) = pk;
        assert!(x1 == pkbuf.to_hex());
        assert!(x3 == sm.to_hex());
    }
}
<commit_msg>Changed import of extern crate extra to extern crate serialize<commit_after>/*!
`ed25519`, a signature scheme specified in
[Ed25519](http://ed25519.cr.yp.to/). This function is conjectured to meet the
standard notion of unforgeability for a public-key signature scheme under
chosen-message attacks.
*/
extern crate serialize;
use std::libc::{c_ulonglong, c_int};
use std::vec::{from_elem};

#[link(name = "sodium")]
extern {
    fn crypto_sign_ed25519_keypair(pk: *mut u8,
                                   sk: *mut u8) -> c_int;
    fn crypto_sign_ed25519_seed_keypair(pk: *mut u8,
                                        sk: *mut u8,
                                        seed: *u8) -> c_int;
    fn crypto_sign_ed25519(sm: *mut u8,
                           smlen: *mut c_ulonglong,
                           m: *u8,
                           mlen: c_ulonglong,
                           sk: *u8) -> c_int;
    fn crypto_sign_ed25519_open(m: *mut u8,
                                mlen: *mut c_ulonglong,
                                sm: *u8,
                                smlen: c_ulonglong,
                                pk: *u8) -> c_int;
}

pub static SEEDBYTES: uint = 32;
pub static SECRETKEYBYTES: uint = 64;
pub static PUBLICKEYBYTES: uint = 32;
pub static SIGNATUREBYTES: uint = 64;

/**
 * `Seed` that can be used for keypair generation
 *
 * The `Seed` is used by `keypair_from_seed()` to generate
 * a secret and public signature key.
 *
 * When a `Seed` goes out of scope its contents
 * will be zeroed out
 */
pub struct Seed([u8, ..SEEDBYTES]);
impl Drop for Seed {
    fn drop(&mut self) {
        let &Seed(ref mut s) = self;
        for e in s.mut_iter() { *e = 0 }
    }
}

/**
 * `SecretKey` for signatures
 *
 * When a `SecretKey` goes out of scope its contents
 * will be zeroed out
 */
pub struct SecretKey([u8, ..SECRETKEYBYTES]);
impl Drop for SecretKey {
    fn drop(&mut self) {
        let &SecretKey(ref mut sk) = self;
        for e in sk.mut_iter() { *e = 0 }
    }
}
/**
 * `PublicKey` for signatures
 */
pub struct PublicKey([u8, ..PUBLICKEYBYTES]);

/**
 * `gen_keypair()` randomly generates a secret key and a corresponding public
 * key.
 *
 * THREAD SAFETY: `gen_keypair()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_keypair() -> (PublicKey, SecretKey) {
    unsafe {
        let mut pk = [0u8, ..PUBLICKEYBYTES];
        let mut sk = [0u8, ..SECRETKEYBYTES];
        crypto_sign_ed25519_keypair(pk.as_mut_ptr(), sk.as_mut_ptr());
        (PublicKey(pk), SecretKey(sk))
    }
}

/**
 * `keypair_from_seed()` computes a secret key and a corresponding public key
 * from a `Seed`.
 */
pub fn keypair_from_seed(&Seed(seed): &Seed) -> (PublicKey, SecretKey) {
    unsafe {
        let mut pk = [0u8, ..PUBLICKEYBYTES];
        let mut sk = [0u8, ..SECRETKEYBYTES];
        crypto_sign_ed25519_seed_keypair(pk.as_mut_ptr(),
                                         sk.as_mut_ptr(),
                                         seed.as_ptr());
        (PublicKey(pk), SecretKey(sk))
    }
}

/**
 * `sign()` signs a message `m` using the signer's secret key `sk`.
 * `sign()` returns the resulting signed message `sm`.
 */
pub fn sign(m: &[u8],
            &SecretKey(sk): &SecretKey) -> ~[u8] {
    unsafe {
        let mut sm = from_elem(m.len() + SIGNATUREBYTES, 0u8);
        let mut smlen = 0;
        crypto_sign_ed25519(sm.as_mut_ptr(),
                            &mut smlen,
                            m.as_ptr(),
                            m.len() as c_ulonglong,
                            sk.as_ptr());
        sm.truncate(smlen as uint);
        sm
    }
}

/**
 * `verify()` verifies the signature in `sm` using the signer's public key `pk`.
 * `verify()` returns the message `Some(m)`.
 * If the signature fails verification, `verify()` returns `None`.
 */
pub fn verify(sm: &[u8],
              &PublicKey(pk): &PublicKey) -> Option<~[u8]> {
    unsafe {
        let mut m = from_elem(sm.len(), 0u8);
        let mut mlen = 0;
        if crypto_sign_ed25519_open(m.as_mut_ptr(),
                                    &mut mlen,
                                    sm.as_ptr(),
                                    sm.len() as c_ulonglong,
                                    pk.as_ptr()) == 0 {
            m.truncate(mlen as uint);
            Some(m)
        } else {
            None
        }
    }
}

#[test]
fn test_sign_verify() {
    use randombytes::randombytes;
    for i in range(0, 256) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i as uint);
        let sm = sign(m, &sk);
        let m2 = verify(sm, &pk);
        assert!(Some(m) == m2);
    }
}

#[test]
fn test_sign_verify_tamper() {
    use randombytes::randombytes;
    for i in range(0, 32) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i as uint);
        let mut sm = sign(m, &sk);
        for j in range(0, sm.len()) {
            sm[j] ^= 0x20;
            assert!(None == verify(sm, &pk));
            sm[j] ^= 0x20;
        }
    }
}

#[test]
fn test_sign_verify_seed() {
    use randombytes::{randombytes, randombytes_into};
    for i in range(0, 256) {
        let mut seedbuf = [0, ..32];
        randombytes_into(seedbuf);
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = randombytes(i as uint);
        let sm = sign(m, &sk);
        let m2 = verify(sm, &pk);
        assert!(Some(m) == m2);
    }
}

#[test]
fn test_sign_verify_tamper_seed() {
    use randombytes::{randombytes, randombytes_into};
    for i in range(0, 32) {
        let mut seedbuf = [0, ..32];
        randombytes_into(seedbuf);
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = randombytes(i as uint);
        let mut sm = sign(m, &sk);
        for j in range(0, sm.len()) {
            sm[j] ^= 0x20;
            assert!(None == verify(sm, &pk));
            sm[j] ^= 0x20;
        }
    }
}

#[test]
fn test_vectors() {
    // test vectors from the Python implementation
    // form the [Ed25519 Homepage](http://ed25519.cr.yp.to/software.html)
    use self::serialize::hex::{FromHex, ToHex};
    use std::io::buffered::BufferedReader;
    use std::io::File;
    use std::path::Path;

    let p = &Path::new("testvectors/ed25519.input");
    let mut r = BufferedReader::new(File::open(p).unwrap());
    loop {
        let line = match r.read_line() {
            None => break,
            Some(line) => line
        };
        let mut x = line.split(':');
        let x0 = x.next().unwrap();
        let x1 = x.next().unwrap();
        let x2 = x.next().unwrap();
        let x3 = x.next().unwrap();
        let seed_bytes = x0.slice(0, 64).from_hex().unwrap();
        assert!(seed_bytes.len() == SEEDBYTES);
        let mut seedbuf = [0u8, ..SEEDBYTES];
        for (s, b) in seedbuf.mut_iter().zip(seed_bytes.iter()) {
            *s = *b
        }
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = x2.from_hex().unwrap();
        let sm = sign(m, &sk);
        verify(sm, &pk).unwrap();
        let PublicKey(pkbuf) = pk;
        assert!(x1 == pkbuf.to_hex());
        assert!(x3 == sm.to_hex());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Defines the traits to be implemented by SSA data structures.
//!
//! These traits extend upon the ones provided in `cfg_traits.1
//!
//! # Design
//!
//!  * `SSA` - Analogous to `CFG` this trait provides __accessors__ to
//!  the data: Methods to enumerate operations, discovered connected operations,
//!  determine which operation a basic block is in. etc.
//!
//!  * `SSAMod` - This trait provides methods to __manipulate__ operation nodes.
//!
//!  * `SSAExtras` - TODO
//!
//! The associated type `SSA::ValueRef` is used by the methods to refer to
//! nodes.
//!  `ValueRefs` are invalidated by removal or replacement of the target node.
//!  You can revalidate a ValueRef by calling `SSA::refresh` on it.
//!  Currently `SSAStorage` automatically uses `refresh` on arguments of its
//!  `*_use`, `get_node_data` and `replace` methods.

use std::hash::Hash;
use std::fmt::{self, Debug};

use middle::ir;
use super::cfg_traits::{CFG, CFGMod};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ValueType {
    Integer {
        width: ir::WidthSpec,
    },
}

impl<'a> From<&'a str> for ValueType {
    fn from(v: &'a str) -> ValueType {
        let t = v.to_owned().chars().nth(0).unwrap();

        let w = match t {
            'i' => v[1..].parse::<u16>().unwrap(),
            _ => unimplemented!(),
        };

        ValueType::Integer { width: w }
    }
}

impl From<String> for ValueType {
    fn from(v: String) -> ValueType {
        From::from(&*v)
    }
}

impl From<u16> for ValueType {
    fn from(v: u16) -> ValueType {
        ValueType::Integer { width: v as ir::WidthSpec }
    }
}

impl From<usize> for ValueType {
    fn from(v: usize) -> ValueType {
        ValueType::Integer { width: v as ir::WidthSpec }
    }
}

pub struct BBInfo;
//// Data associated with a basic block. Use is optional.
//#[derive(Clone, Debug)]
//pub struct BBInfo {
    //pub addr: u64,
//}

/// Value node without operands
#[derive(Clone, Debug)]
pub enum NodeType {
    /// An operation node with the specified opcode.
    Op(ir::MOpcode),
    /// A phi node.
    Phi,
    /// A node with unknown value.
    Undefined,
    Comment(String),
}

// Implement display helper for NodeData to make it a little nicer to read prefix notation.
impl fmt::Display for NodeType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match *self {
            NodeType::Op(op) => format!("{}", op),
            NodeType::Phi => "Phi".to_owned(),
            NodeType::Comment(ref s) => s.clone(),
            // Don't care about these
            _ => String::new(),
        };
        write!(f, "{}", s)
    }
}

/// Value node without operands with `ValueType`
#[derive(Clone, Debug)]
pub struct NodeData {
    pub vt: ValueType,
    pub nt: NodeType,
}

/// Trait for the SSA Form implementation.
// This trait ensures that any other ssa form will be compatible with our
// implementations provided
// the SSA form implements the following traits.
pub trait SSA: CFG {
	type ValueRef: Eq + Hash + Clone + Copy + Debug; // We could drop the Copy trait later and insert .clone()

    ///////////////////////////////////////////////////////////////////////////
    //// Node accessors and helpers
    ///////////////////////////////////////////////////////////////////////////

    fn get_address(&self, &Self::ValueRef) -> ir::MAddress;
    /// Get all the NodeIndex of all operations/expressions in the BasicBlock with index 'i'.
    fn exprs_in(&self, i: &Self::ActionRef) -> Vec<Self::ValueRef>;

    /// Check if the node at the given index is a expression or not.
    fn is_expr(&self, i: &Self::ValueRef) -> bool;

    /// Check if the node at the given index is a phi node or not.
    fn is_phi(&self, i: &Self::ValueRef) -> bool;

    /// Get all phis in the BasicBlock with index 'i'.
    fn get_phis(&self, i: &Self::ActionRef) -> Vec<Self::ValueRef>;

    /// Get all the uses of the node with index 'i'.
    fn get_uses(&self, i: &Self::ValueRef) -> Vec<Self::ValueRef>;

    /// Get the NodeIndex of the BasicBlock to which node with index 'i' belongs to.
    fn get_block(&self, i: &Self::ValueRef) -> Self::ActionRef;

    /// Get the operands for the operation with NodeIndex 'i'.
    fn get_operands(&self, i: &Self::ValueRef) -> Vec<Self::ValueRef>;

    /// Get the operands for the operation with NodeIndex 'i' as tuples.
    fn get_sparse_operands(&self, i: &Self::ValueRef) -> Vec<(u8, Self::ValueRef)>;

    /// Get the lhs() of the Operation with NodeIndex 'i'.
    fn lhs(&self, i: &Self::ValueRef) -> Self::ValueRef {
        self.get_operands(i)[0]
    }

    /// Get the rhs() of the Operation with NodeIndex 'i'.
    fn rhs(&self, i: &Self::ValueRef) -> Self::ValueRef {
        self.get_operands(i)[1]
    }

    /// Get the actual NodeData.
    fn get_node_data(&self, i: &Self::ValueRef) -> Result<NodeData, Box<Debug>>;

    /// Get comment information, as a pack of get_node_data on a Comment data.
    fn get_comment(&self, i: &Self::ValueRef) -> Option<String>;

    /// Get OpCode information, as a pack of get_node_data on a Comment data.
    fn get_opcode(&self, i: &Self::ValueRef) -> Option<ir::MOpcode>;

    /// Returns true if the expression acts as a `Selector` for control flow.
    fn is_selector(&self, i: &Self::ValueRef) -> bool;

    /// Returns the selector for the Block.
    fn selector_of(&self, i: &Self::ActionRef) -> Option<Self::ValueRef>;

    /// Get the Block for which i acts as a selector.
    fn selects_for(&self, i: &Self::ValueRef) -> Self::ActionRef;

    /// Get Jump target of a call or an unconditional jump.
    fn get_target(&self, i: &Self::ValueRef) -> Self::ActionRef;

    /// Get branches of a selector (false_branch, true_branch).
    fn get_branches(&self, i: &Self::ValueRef) -> (Self::ActionRef, Self::ActionRef);

    /// Helper method that gets only the true branch.
    fn get_true_branch(&self, i: &Self::ValueRef) -> Self::ActionRef {
        self.get_branches(i).1
    }

    /// Helper method that gets only the false branch.
    fn get_false_branch(&self, i: &Self::ValueRef) -> Self::ActionRef {
        self.get_branches(i).0
    }

    /// Gets the data dependencies of a value node in any order.
    /// (See get_operands for ordered return value)
    fn args_of(&self, node: Self::ValueRef) -> Vec<Self::ValueRef>;

    /// Gets uses dependents of a value node.
    /// (Equivalent as `SSAMod::get_uses`)
    fn uses_of(&self, node: Self::ValueRef) -> Vec<Self::ValueRef>;

    /// Get the NodeIndex of the BasicBlock to which node with index 'i' belongs to.
    /// (Alias for get_block)
    fn block_of(&self, i: &Self::ValueRef) -> Self::ActionRef {
        self.get_block(i)
    }

    /// Get a node that has all register values at the beginning of the specified basic block as args
    fn registers_at(&self, i: &Self::ActionRef) -> Self::ValueRef;

    fn invalid_value(&self) -> Self::ValueRef;

    fn to_value(&self, Self::ActionRef) -> Self::ValueRef;
    fn to_action(&self, Self::ValueRef) -> Self::ActionRef;

    fn node_count(&self) -> usize;
    fn edge_count(&self) -> usize;
    fn nodes(&self) -> Vec<Self::ValueRef>;
}

/// Trait for modifying SSA data
pub trait SSAMod: SSA + CFGMod {

    /// Add a new operation node.
    fn add_op(&mut self,
              opc: ir::MOpcode,
              vt: ValueType,
              addr: Option<u64>)
              -> Self::ValueRef;

    /// Add a new constant node.
    fn add_const(&mut self, value: u64) -> Self::ValueRef;

    /// Add a new phi node.
    fn add_phi(&mut self, vt: ValueType) -> Self::ValueRef;

    /// Add a new undefined node
    fn add_undefined(&mut self, vt: ValueType) -> Self::ValueRef;

    /// Add a new comment node
    fn add_comment(&mut self,
                   vt: ValueType,
                   msg: String)
                   -> Self::ValueRef;

    /// Associate a node with index n with a block
    fn add_to_block(&mut self, node: Self::ValueRef, block: Self::ActionRef, ir::MAddress);

    /// Mark the node as selector for the control edges away from the specified basic block
    fn mark_selector(&mut self, node: Self::ValueRef, block: Self::ActionRef);

    /// Add a data source to a phi node.
    fn phi_use(&mut self, phi: Self::ValueRef, node: Self::ValueRef);

    /// Remove a data source from a phi node.
    fn phi_unuse(&mut self, phi: Self::ValueRef, node: Self::ValueRef);

    /// Set the index-th argument of the node.
    fn op_use(&mut self, node: Self::ValueRef, index: u8, argument: Self::ValueRef);

    /// Disconnect n1 from n2 (deletes the edge if one exists.
    fn disconnect(&mut self, &Self::ValueRef, &Self::ValueRef);

    /// Replace one node by another within one basic block.
    fn replace(&mut self, node: Self::ValueRef, replacement: Self::ValueRef);

    /// Remove a node without replacement
    fn remove(&mut self, node: Self::ValueRef);

    /// Remove control flow edge. This is a part of SSAMod as this potentially modifies the ssa.
    fn remove_edge(&mut self, i: &Self::CFEdgeRef);

    fn map_registers(&mut self, regs: Vec<String>);

    fn set_addr(&mut self, &Self::ValueRef, ir::MAddress);
}

/// Extras. TODO
///
/// Design requirement - For a method to be a part of `SSAExtras`, it __has__ to have a default
/// implementation that would work out of the box. Since these methods are only extras and do not
/// add any major functionality, but rather just convinence or display glitter, the user must not
/// be burdened with implementing this. All methods must return `Option<T>` to ensure this.

#[derive(Clone, Debug, Default)]
pub struct RegInfo {
    pub name: String,
    pub type_info: Option<String>,
    pub alias_info: Option<String>,
}

pub trait SSAExtra: SSA {
    fn mark(&mut self, _: &Self::ValueRef) { }
    fn clear_mark(&mut self, &Self::ValueRef) { }
    fn set_color(&mut self, _: &Self::ValueRef, _: u8) { }
    fn set_comment(&mut self, _: &Self::ValueRef, _: String) { }
    fn set_register(&mut self, _: &Self::ValueRef, _: RegInfo) {  }
    fn add_flag(&mut self, _: &Self::ValueRef, _: String) { }
    fn is_marked(&self, _: &Self::ValueRef) -> bool {
        false
    }

    fn color(&self, _: &Self::ValueRef) -> Option<u8> {
        None
    }

    fn comments(&self, _: &Self::ValueRef) -> Option<String> {
        None
    }

    fn addr(&self, _: &Self::ValueRef) -> Option<String> {
        None
    }

    fn register(&self, _: &Self::ValueRef) -> Option<RegInfo> {
        None
    }

    fn flags(&self, _: &Self::ValueRef) -> Option<String> {
        None
    }
}

pub trait SSAWalk<I: Iterator<Item=<Self as SSA>::ValueRef>>: SSA {
    fn bfs_walk(&self) -> I;
    fn inorder_walk(&self) -> I;
    fn dfs_walk(&self) -> I;
}
<commit_msg>Change regfile APIs<commit_after>// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Defines the traits to be implemented by SSA data structures.
//!
//! These traits extend upon the ones provided in `cfg_traits.1
//!
//! # Design
//!
//!  * `SSA` - Analogous to `CFG` this trait provides __accessors__ to
//!  the data: Methods to enumerate operations, discovered connected operations,
//!  determine which operation a basic block is in. etc.
//!
//!  * `SSAMod` - This trait provides methods to __manipulate__ operation nodes.
//!
//!  * `SSAExtras` - TODO
//!
//! The associated type `SSA::ValueRef` is used by the methods to refer to
//! nodes.
//!  `ValueRefs` are invalidated by removal or replacement of the target node.
//!  You can revalidate a ValueRef by calling `SSA::refresh` on it.
//!  Currently `SSAStorage` automatically uses `refresh` on arguments of its
//!  `*_use`, `get_node_data` and `replace` methods.

use std::hash::Hash;
use std::fmt::{self, Debug};

use middle::ir;
use super::cfg_traits::{CFG, CFGMod};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ValueType {
    Integer {
        width: ir::WidthSpec,
    },
}

impl<'a> From<&'a str> for ValueType {
    fn from(v: &'a str) -> ValueType {
        let t = v.to_owned().chars().nth(0).unwrap();

        let w = match t {
            'i' => v[1..].parse::<u16>().unwrap(),
            _ => unimplemented!(),
        };

        ValueType::Integer { width: w }
    }
}

impl From<String> for ValueType {
    fn from(v: String) -> ValueType {
        From::from(&*v)
    }
}

impl From<u16> for ValueType {
    fn from(v: u16) -> ValueType {
        ValueType::Integer { width: v as ir::WidthSpec }
    }
}

impl From<usize> for ValueType {
    fn from(v: usize) -> ValueType {
        ValueType::Integer { width: v as ir::WidthSpec }
    }
}

pub struct BBInfo;
//// Data associated with a basic block. Use is optional.
//#[derive(Clone, Debug)]
//pub struct BBInfo {
    //pub addr: u64,
//}

/// Value node without operands
#[derive(Clone, Debug)]
pub enum NodeType {
    /// An operation node with the specified opcode.
    Op(ir::MOpcode),
    /// A phi node.
    Phi,
    /// A node with unknown value.
    Undefined,
    Comment(String),
}

// Implement display helper for NodeData to make it a little nicer to read prefix notation.
impl fmt::Display for NodeType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match *self {
            NodeType::Op(op) => format!("{}", op),
            NodeType::Phi => "Phi".to_owned(),
            NodeType::Comment(ref s) => s.clone(),
            // Don't care about these
            _ => String::new(),
        };
        write!(f, "{}", s)
    }
}

/// Value node without operands with `ValueType`
#[derive(Clone, Debug)]
pub struct NodeData {
    pub vt: ValueType,
    pub nt: NodeType,
}

/// Trait for the SSA Form implementation.
// This trait ensures that any other ssa form will be compatible with our
// implementations provided
// the SSA form implements the following traits.
pub trait SSA: CFG {
	type ValueRef: Eq + Hash + Clone + Copy + Debug; // We could drop the Copy trait later and insert .clone()

    ///////////////////////////////////////////////////////////////////////////
    //// Node accessors and helpers
    ///////////////////////////////////////////////////////////////////////////

    fn get_address(&self, &Self::ValueRef) -> ir::MAddress;
    /// Get all the NodeIndex of all operations/expressions in the BasicBlock with index 'i'.
    fn exprs_in(&self, i: &Self::ActionRef) -> Vec<Self::ValueRef>;

    /// Check if the node at the given index is a expression or not.
    fn is_expr(&self, i: &Self::ValueRef) -> bool;

    /// Check if the node at the given index is a phi node or not.
    fn is_phi(&self, i: &Self::ValueRef) -> bool;

    /// Get all phis in the BasicBlock with index 'i'.
    fn get_phis(&self, i: &Self::ActionRef) -> Vec<Self::ValueRef>;

    /// Get all the uses of the node with index 'i'.
    fn get_uses(&self, i: &Self::ValueRef) -> Vec<Self::ValueRef>;

    /// Get the NodeIndex of the BasicBlock to which node with index 'i' belongs to.
    fn get_block(&self, i: &Self::ValueRef) -> Self::ActionRef;

    /// Get the operands for the operation with NodeIndex 'i'.
    fn get_operands(&self, i: &Self::ValueRef) -> Vec<Self::ValueRef>;

    /// Get the operands for the operation with NodeIndex 'i' as tuples.
    fn get_sparse_operands(&self, i: &Self::ValueRef) -> Vec<(u8, Self::ValueRef)>;

    /// Get the lhs() of the Operation with NodeIndex 'i'.
    fn lhs(&self, i: &Self::ValueRef) -> Self::ValueRef {
        self.get_operands(i)[0]
    }

    /// Get the rhs() of the Operation with NodeIndex 'i'.
    fn rhs(&self, i: &Self::ValueRef) -> Self::ValueRef {
        self.get_operands(i)[1]
    }

    /// Get the actual NodeData.
    fn get_node_data(&self, i: &Self::ValueRef) -> Result<NodeData, Box<Debug>>;

    /// Get comment information, as a pack of get_node_data on a Comment data.
    fn get_comment(&self, i: &Self::ValueRef) -> Option<String>;

    /// Get OpCode information, as a pack of get_node_data on a Comment data.
    fn get_opcode(&self, i: &Self::ValueRef) -> Option<ir::MOpcode>;

    /// Returns true if the expression acts as a `Selector` for control flow.
    fn is_selector(&self, i: &Self::ValueRef) -> bool;

    /// Returns the selector for the Block.
    fn selector_of(&self, i: &Self::ActionRef) -> Option<Self::ValueRef>;

    /// Get the Block for which i acts as a selector.
    fn selects_for(&self, i: &Self::ValueRef) -> Self::ActionRef;

    /// Get Jump target of a call or an unconditional jump.
    fn get_target(&self, i: &Self::ValueRef) -> Self::ActionRef;

    /// Get branches of a selector (false_branch, true_branch).
    fn get_branches(&self, i: &Self::ValueRef) -> (Self::ActionRef, Self::ActionRef);

    /// Helper method that gets only the true branch.
    fn get_true_branch(&self, i: &Self::ValueRef) -> Self::ActionRef {
        self.get_branches(i).1
    }

    /// Helper method that gets only the false branch.
    fn get_false_branch(&self, i: &Self::ValueRef) -> Self::ActionRef {
        self.get_branches(i).0
    }

    /// Gets the data dependencies of a value node in any order.
    /// (See get_operands for ordered return value)
    fn args_of(&self, node: Self::ValueRef) -> Vec<Self::ValueRef>;

    /// Gets uses dependents of a value node.
    /// (Equivalent as `SSAMod::get_uses`)
    fn uses_of(&self, node: Self::ValueRef) -> Vec<Self::ValueRef>;

    /// Get the NodeIndex of the BasicBlock to which node with index 'i' belongs to.
    /// (Alias for get_block)
    fn block_of(&self, i: &Self::ValueRef) -> Self::ActionRef {
        self.get_block(i)
    }

    /// Get a node that has all register values at the beginning of the specified basic block as args
    fn registers_at(&self, i: &Self::ActionRef) -> Self::ValueRef;

    fn invalid_value(&self) -> Self::ValueRef;

    fn to_value(&self, Self::ActionRef) -> Self::ValueRef;
    fn to_action(&self, Self::ValueRef) -> Self::ActionRef;

    fn node_count(&self) -> usize;
    fn edge_count(&self) -> usize;
    fn nodes(&self) -> Vec<Self::ValueRef>;
}

/// Trait for modifying SSA data
pub trait SSAMod: SSA + CFGMod {

    /// Add a new operation node.
    fn add_op(&mut self,
              opc: ir::MOpcode,
              vt: ValueType,
              addr: Option<u64>)
              -> Self::ValueRef;

    /// Add a new constant node.
    fn add_const(&mut self, value: u64) -> Self::ValueRef;

    /// Add a new phi node.
    fn add_phi(&mut self, vt: ValueType) -> Self::ValueRef;

    /// Add a new undefined node
    fn add_undefined(&mut self, vt: ValueType) -> Self::ValueRef;

    /// Add a new comment node
    fn add_comment(&mut self,
                   vt: ValueType,
                   msg: String)
                   -> Self::ValueRef;

    /// Associate a node with index n with a block
    fn add_to_block(&mut self, node: Self::ValueRef, block: Self::ActionRef, ir::MAddress);

    /// Mark the node as selector for the control edges away from the specified basic block
    fn mark_selector(&mut self, node: Self::ValueRef, block: Self::ActionRef);

    /// Add a data source to a phi node.
    fn phi_use(&mut self, phi: Self::ValueRef, node: Self::ValueRef);

    /// Remove a data source from a phi node.
    fn phi_unuse(&mut self, phi: Self::ValueRef, node: Self::ValueRef);

    /// Set the index-th argument of the node.
    fn op_use(&mut self, node: Self::ValueRef, index: u8, argument: Self::ValueRef);

    /// Disconnect n1 from n2 (deletes the edge if one exists.
    fn disconnect(&mut self, &Self::ValueRef, &Self::ValueRef);

    /// Replace one node by another within one basic block.
    fn replace(&mut self, node: Self::ValueRef, replacement: Self::ValueRef);

    /// Remove a node without replacement
    fn remove(&mut self, node: Self::ValueRef);

    /// Remove control flow edge. This is a part of SSAMod as this potentially modifies the ssa.
    fn remove_edge(&mut self, i: &Self::CFEdgeRef);

    fn map_registers(&mut self, regs: Vec<String>);

    fn set_addr(&mut self, &Self::ValueRef, ir::MAddress);
}

/// Extras. TODO
///
/// Design requirement - For a method to be a part of `SSAExtras`, it __has__ to have a default
/// implementation that would work out of the box. Since these methods are only extras and do not
/// add any major functionality, but rather just convinence or display glitter, the user must not
/// be burdened with implementing this. All methods must return `Option<T>` to ensure this.

#[derive(Clone, Debug, Default)]
pub struct RegInfo {
    pub name: String,
    pub type_info: Option<String>,
    pub alias_info: Option<String>,
    pub width: Option<usize>,
}

pub trait SSAExtra: SSA {
    fn mark(&mut self, _: &Self::ValueRef) { }
    fn clear_mark(&mut self, &Self::ValueRef) { }
    fn set_color(&mut self, _: &Self::ValueRef, _: u8) { }
    fn set_comment(&mut self, _: &Self::ValueRef, _: String) { }
    fn set_register(&mut self, _: &Self::ValueRef, _: RegInfo) {  }
    fn add_flag(&mut self, _: &Self::ValueRef, _: String) { }
    fn is_marked(&self, _: &Self::ValueRef) -> bool {
        false
    }

    fn color(&self, _: &Self::ValueRef) -> Option<u8> {
        None
    }

    fn comments(&self, _: &Self::ValueRef) -> Option<String> {
        None
    }

    fn addr(&self, _: &Self::ValueRef) -> Option<String> {
        None
    }

    fn register(&self, _: &Self::ValueRef) -> Option<RegInfo> {
        None
    }

    fn flags(&self, _: &Self::ValueRef) -> Option<String> {
        None
    }
}

pub trait SSAWalk<I: Iterator<Item=<Self as SSA>::ValueRef>>: SSA {
    fn bfs_walk(&self) -> I;
    fn inorder_walk(&self) -> I;
    fn dfs_walk(&self) -> I;
}
<|endoftext|>


<commit_before>// spell-checker:ignore (URL) appspot

use crate::numeric::*;

pub(crate) trait Basis {
    const BASIS: &'static [u64];
}

impl Basis for Montgomery<u64> {
    // Small set of bases for the Miller-Rabin prime test, valid for all 64b integers;
    //  discovered by Jim Sinclair on 2011-04-20, see miller-rabin.appspot.com
    #[allow(clippy::unreadable_literal)]
    const BASIS: &'static [u64] = &[2, 325, 9375, 28178, 450775, 9780504, 1795265022];
}

impl Basis for Montgomery<u32> {
    // Small set of bases for the Miller-Rabin prime test, valid for all 32b integers;
    //  discovered by Steve Worley on 2013-05-27, see miller-rabin.appspot.com
    #[allow(clippy::unreadable_literal)]
    const BASIS: &'static [u64] = &[
        4230279247111683200,
        14694767155120705706,
        16641139526367750375,
    ];
}

#[derive(Eq, PartialEq)]
pub(crate) enum Result {
    Prime,
    Pseudoprime,
    Composite(u64),
}

impl Result {
    pub(crate) fn is_prime(&self) -> bool {
        *self == Result::Prime
    }
}

// Deterministic Miller-Rabin primality-checking algorithm, adapted to extract
// (some) dividers; it will fail to factor strong pseudoprimes.
#[allow(clippy::many_single_char_names)]
pub(crate) fn test<A: Arithmetic + Basis>(m: A) -> Result {
    use self::Result::*;

    let n = m.modulus();
    debug_assert!(n > 1);
    debug_assert!(n % 2 != 0);

    // n-1 = r 2ⁱ
    let i = (n - 1).trailing_zeros();
    let r = (n - 1) >> i;

    let one = m.one();
    let minus_one = m.minus_one();

    for _a in A::BASIS.iter() {
        let _a = _a % n;
        if _a == 0 {
            continue;
        }

        let a = m.from_u64(_a);

        // x = a^r mod n
        let mut x = m.pow(a, r);

        {
            // y = ((x²)²...)² i times = x ^ (2ⁱ) = a ^ (r 2ⁱ) = x ^ (n - 1)
            let mut y = x;
            for _ in 0..i {
                y = m.mul(y, y)
            }
            if y != one {
                return Pseudoprime;
            };
        }

        if x == one || x == minus_one {
            continue;
        }

        loop {
            let y = m.mul(x, x);
            if y == one {
                return Composite(gcd(m.to_u64(x) - 1, m.modulus()));
            }
            if y == minus_one {
                // This basis element is not a witness of `n` being composite.
                // Keep looking.
                break;
            }
            x = y;
        }
    }

    Prime
}

// Used by build.rs' tests and debug assertions
#[allow(dead_code)]
pub(crate) fn is_prime(n: u64) -> bool {
    if n < 2 {
        false
    } else if n % 2 == 0 {
        n == 2
    } else {
        test::<Montgomery<u64>>(Montgomery::new(n)).is_prime()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::numeric::{Arithmetic, Montgomery};
    use quickcheck::quickcheck;
    use std::iter;
    const LARGEST_U64_PRIME: u64 = 0xFFFFFFFFFFFFFFC5;

    fn primes() -> impl Iterator<Item = u64> {
        iter::once(2).chain(odd_primes())
    }

    fn odd_primes() -> impl Iterator<Item = u64> {
        use crate::table::{NEXT_PRIME, P_INVS_U64};
        P_INVS_U64
            .iter()
            .map(|(p, _, _)| *p)
            .chain(iter::once(NEXT_PRIME))
    }

    #[test]
    fn largest_prime() {
        assert!(is_prime(LARGEST_U64_PRIME));
    }

    #[test]
    fn largest_composites() {
        for i in LARGEST_U64_PRIME + 1..=u64::MAX {
            assert!(!is_prime(i), "2⁶⁴ - {} reported prime", u64::MAX - i + 1);
        }
    }

    #[test]
    fn two() {
        assert!(is_prime(2));
    }

    // TODO: Deduplicate with macro in numeric.rs
    macro_rules! parametrized_check {
        ( $f:ident ) => {
            paste::item! {
                #[test]
                fn [< $f _ u32 >]() {
                    $f::<Montgomery<u32>>()
                }
                #[test]
                fn [< $f _ u64 >]() {
                    $f::<Montgomery<u64>>()
                }
            }
        };
    }

    fn first_primes<A: Arithmetic + Basis>() {
        for p in odd_primes() {
            assert!(test(A::new(p)).is_prime(), "{} reported composite", p);
        }
    }
    parametrized_check!(first_primes);

    #[test]
    fn one() {
        assert!(!is_prime(1));
    }
    #[test]
    fn zero() {
        assert!(!is_prime(0));
    }

    fn first_composites<A: Arithmetic + Basis>() {
        for (p, q) in primes().zip(odd_primes()) {
            for i in p + 1..q {
                assert!(!is_prime(i), "{} reported prime", i);
            }
        }
    }
    parametrized_check!(first_composites);

    #[test]
    fn issue_1556() {
        // 10 425 511 = 2441 × 4271
        assert!(!is_prime(10_425_511));
    }

    fn small_semiprimes<A: Arithmetic + Basis>() {
        for p in odd_primes() {
            for q in odd_primes().take_while(|q| *q <= p) {
                let n = p * q;
                let m = A::new(n);
                assert!(!test(m).is_prime(), "{} = {} × {} reported prime", n, p, q);
            }
        }
    }
    parametrized_check!(small_semiprimes);

    quickcheck! {
        fn composites(i: u64, j: u64) -> bool {
            i < 2 || j < 2 || !is_prime(i*j)
        }
    }
}
<commit_msg>factor::miller_rabin: Remove duplicated work<commit_after>// spell-checker:ignore (URL) appspot

use crate::numeric::*;

pub(crate) trait Basis {
    const BASIS: &'static [u64];
}

impl Basis for Montgomery<u64> {
    // Small set of bases for the Miller-Rabin prime test, valid for all 64b integers;
    //  discovered by Jim Sinclair on 2011-04-20, see miller-rabin.appspot.com
    #[allow(clippy::unreadable_literal)]
    const BASIS: &'static [u64] = &[2, 325, 9375, 28178, 450775, 9780504, 1795265022];
}

impl Basis for Montgomery<u32> {
    // Small set of bases for the Miller-Rabin prime test, valid for all 32b integers;
    //  discovered by Steve Worley on 2013-05-27, see miller-rabin.appspot.com
    #[allow(clippy::unreadable_literal)]
    const BASIS: &'static [u64] = &[
        4230279247111683200,
        14694767155120705706,
        16641139526367750375,
    ];
}

#[derive(Eq, PartialEq)]
pub(crate) enum Result {
    Prime,
    Pseudoprime,
    Composite(u64),
}

impl Result {
    pub(crate) fn is_prime(&self) -> bool {
        *self == Result::Prime
    }
}

// Deterministic Miller-Rabin primality-checking algorithm, adapted to extract
// (some) dividers; it will fail to factor strong pseudoprimes.
#[allow(clippy::many_single_char_names)]
pub(crate) fn test<A: Arithmetic + Basis>(m: A) -> Result {
    use self::Result::*;

    let n = m.modulus();
    debug_assert!(n > 1);
    debug_assert!(n % 2 != 0);

    // n-1 = r 2ⁱ
    let i = (n - 1).trailing_zeros();
    let r = (n - 1) >> i;

    let one = m.one();
    let minus_one = m.minus_one();

    'witness: for _a in A::BASIS.iter() {
        let _a = _a % n;
        if _a == 0 {
            continue;
        }

        let a = m.from_u64(_a);

        // x = a^r mod n
        let mut x = m.pow(a, r);

        if x == one || x == minus_one {
            continue;
        }

        for _ in 1..i {
            let y = m.mul(x, x);
            if y == one {
                return Composite(gcd(m.to_u64(x) - 1, m.modulus()));
            }
            if y == minus_one {
                // This basis element is not a witness of `n` being composite.
                // Keep looking.
                continue 'witness;
            }
            x = y;
        }

        return Pseudoprime;
    }

    Prime
}

// Used by build.rs' tests and debug assertions
#[allow(dead_code)]
pub(crate) fn is_prime(n: u64) -> bool {
    if n < 2 {
        false
    } else if n % 2 == 0 {
        n == 2
    } else {
        test::<Montgomery<u64>>(Montgomery::new(n)).is_prime()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::numeric::{Arithmetic, Montgomery};
    use quickcheck::quickcheck;
    use std::iter;
    const LARGEST_U64_PRIME: u64 = 0xFFFFFFFFFFFFFFC5;

    fn primes() -> impl Iterator<Item = u64> {
        iter::once(2).chain(odd_primes())
    }

    fn odd_primes() -> impl Iterator<Item = u64> {
        use crate::table::{NEXT_PRIME, P_INVS_U64};
        P_INVS_U64
            .iter()
            .map(|(p, _, _)| *p)
            .chain(iter::once(NEXT_PRIME))
    }

    #[test]
    fn largest_prime() {
        assert!(is_prime(LARGEST_U64_PRIME));
    }

    #[test]
    fn largest_composites() {
        for i in LARGEST_U64_PRIME + 1..=u64::MAX {
            assert!(!is_prime(i), "2⁶⁴ - {} reported prime", u64::MAX - i + 1);
        }
    }

    #[test]
    fn two() {
        assert!(is_prime(2));
    }

    // TODO: Deduplicate with macro in numeric.rs
    macro_rules! parametrized_check {
        ( $f:ident ) => {
            paste::item! {
                #[test]
                fn [< $f _ u32 >]() {
                    $f::<Montgomery<u32>>()
                }
                #[test]
                fn [< $f _ u64 >]() {
                    $f::<Montgomery<u64>>()
                }
            }
        };
    }

    fn first_primes<A: Arithmetic + Basis>() {
        for p in odd_primes() {
            assert!(test(A::new(p)).is_prime(), "{} reported composite", p);
        }
    }
    parametrized_check!(first_primes);

    #[test]
    fn one() {
        assert!(!is_prime(1));
    }
    #[test]
    fn zero() {
        assert!(!is_prime(0));
    }

    fn first_composites<A: Arithmetic + Basis>() {
        for (p, q) in primes().zip(odd_primes()) {
            for i in p + 1..q {
                assert!(!is_prime(i), "{} reported prime", i);
            }
        }
    }
    parametrized_check!(first_composites);

    #[test]
    fn issue_1556() {
        // 10 425 511 = 2441 × 4271
        assert!(!is_prime(10_425_511));
    }

    fn small_semiprimes<A: Arithmetic + Basis>() {
        for p in odd_primes() {
            for q in odd_primes().take_while(|q| *q <= p) {
                let n = p * q;
                let m = A::new(n);
                assert!(!test(m).is_prime(), "{} = {} × {} reported prime", n, p, q);
            }
        }
    }
    parametrized_check!(small_semiprimes);

    quickcheck! {
        fn composites(i: u64, j: u64) -> bool {
            i < 2 || j < 2 || !is_prime(i*j)
        }
    }
}
<|endoftext|>


<commit_before>use crate::utils::span_lint;

use rustc_data_structures::fx::FxHashSet;
use rustc_lint::{LateLintPass, LateContext};
use rustc_session::{impl_lint_pass, declare_tool_lint};
use rustc_hir::*;
use rustc_span::Symbol;

declare_clippy_lint! {
    /// **What it does:** Lints for specific trait methods defined in clippy.toml
    ///
    /// **Why is this bad?** Some methods are undesirable in certain contexts,
    /// and it would be beneficial to lint for them as needed.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// // example code where clippy issues a warning
    /// foo.bad_method(); // Foo is disallowed
    /// ```
    /// Use instead:
    /// ```rust
    /// // example code which does not raise clippy warning
    /// GoodStruct.bad_method(); // not disallowed
    /// ```
    pub DISALLOWED_METHOD,
    nursery,
    "used disallowed method call"
}

#[derive(Clone, Debug)]
pub struct DisallowedMethod {
    disallowed: FxHashSet<Vec<Symbol>>,
}

impl DisallowedMethod {
    pub fn new(disallowed: FxHashSet<String>) -> Self {
        Self {
            disallowed: disallowed.iter()
                .map(|s| {
                    s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>()
                })
                .collect(),
        }
    }
}

impl_lint_pass!(DisallowedMethod => [DISALLOWED_METHOD]);

impl <'tcx> LateLintPass<'tcx> for DisallowedMethod {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if let ExprKind::MethodCall(path, _, _args, _) = &expr.kind {
            let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();

            let method_call = cx.get_def_path(def_id);
            if self.disallowed.contains(&method_call) {
                span_lint(
                    cx,
                    DISALLOWED_METHOD,
                    expr.span,
                    &format!(
                        "Use of a disallowed method `{}`",
                        method_call
                            .iter()
                            .map(|s| s.to_ident_string())
                            .collect::<Vec<_>>()
                            .join("::"),
                    )
                );
            }
        }
    }
}
<commit_msg>update unused variable<commit_after>use crate::utils::span_lint;

use rustc_data_structures::fx::FxHashSet;
use rustc_lint::{LateLintPass, LateContext};
use rustc_session::{impl_lint_pass, declare_tool_lint};
use rustc_hir::*;
use rustc_span::Symbol;

declare_clippy_lint! {
    /// **What it does:** Lints for specific trait methods defined in clippy.toml
    ///
    /// **Why is this bad?** Some methods are undesirable in certain contexts,
    /// and it would be beneficial to lint for them as needed.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// // example code where clippy issues a warning
    /// foo.bad_method(); // Foo is disallowed
    /// ```
    /// Use instead:
    /// ```rust
    /// // example code which does not raise clippy warning
    /// GoodStruct.bad_method(); // not disallowed
    /// ```
    pub DISALLOWED_METHOD,
    nursery,
    "used disallowed method call"
}

#[derive(Clone, Debug)]
pub struct DisallowedMethod {
    disallowed: FxHashSet<Vec<Symbol>>,
}

impl DisallowedMethod {
    pub fn new(disallowed: FxHashSet<String>) -> Self {
        Self {
            disallowed: disallowed.iter()
                .map(|s| {
                    s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>()
                })
                .collect(),
        }
    }
}

impl_lint_pass!(DisallowedMethod => [DISALLOWED_METHOD]);

impl <'tcx> LateLintPass<'tcx> for DisallowedMethod {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if let ExprKind::MethodCall(_path, _, _args, _) = &expr.kind {
            let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();

            let method_call = cx.get_def_path(def_id);
            if self.disallowed.contains(&method_call) {
                span_lint(
                    cx,
                    DISALLOWED_METHOD,
                    expr.span,
                    &format!(
                        "Use of a disallowed method `{}`",
                        method_call
                            .iter()
                            .map(|s| s.to_ident_string())
                            .collect::<Vec<_>>()
                            .join("::"),
                    )
                );
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate memchr;
use self::memchr::memrchr;
use path_parsing::{SEP, last_non_sep_i};

pub fn basename<'a>(pth: &'a str, ext: &str) -> &'a str {
  let name_end = (last_non_sep_i(pth) + 1) as usize;
  // Known edge case, all '/'.
  if !pth.is_empty() && name_end == 0 {
    return &pth[..1];
  }
  let name_start = memrchr(SEP, &pth.as_bytes()[..name_end]).unwrap_or(0);
  let mut name = &pth[name_start..name_end];
  if ext == ".*" {
    if let Some(dot_i) = memrchr('.' as u8, name.as_bytes()) {
      name = &name[..dot_i];
    }
  } else if name.ends_with(ext) {
    name = &name[..name.len() - ext.len()];
  };
  name
}

#[test]
fn edge_case_all_seps() {
  assert_eq!("/", basename("///", ".*"));
}
<commit_msg>Fix off-by-one in basename<commit_after>extern crate memchr;
use self::memchr::memrchr;
use path_parsing::{SEP, last_non_sep_i};

pub fn basename<'a>(pth: &'a str, ext: &str) -> &'a str {
  let name_end = (last_non_sep_i(pth) + 1) as usize;
  // Known edge case, all '/'.
  if !pth.is_empty() && name_end == 0 {
    return &pth[..1];
  }
  let name_start = match memrchr(SEP, &pth.as_bytes()[..name_end]) {
    Some(i) => i + 1,
    _ => 0
  };
  let mut name = &pth[name_start..name_end];
  if ext == ".*" {
    if let Some(dot_i) = memrchr('.' as u8, name.as_bytes()) {
      name = &name[..dot_i];
    }
  } else if name.ends_with(ext) {
    name = &name[..name.len() - ext.len()];
  };
  name
}

#[test]
fn edge_case_all_seps() {
  assert_eq!("/", basename("///", ".*"));
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;

use std::env;
use std::io::{stdout, Write};

use coreutils::extra::OptionalExt;

fn main() {
    let mut stdout = stdout();

    let mut newline = true;
    for arg in env::args().skip(1) {
        if arg == "-n" {
            newline = false;
        } else {
            write!(stdout, "{} ", arg).try();
        }
    }
    if newline {
        write!(stdout, "\n").try();
    }
}
<commit_msg>Only check for -n flag as first argument. Fix extra white space at the end of the last argument.<commit_after>#![deny(warnings)]

extern crate coreutils;

use std::env;
use std::io::{stdout, Write};

use coreutils::extra::OptionalExt;

fn main() {
    let mut stdout = stdout();

    let mut args = env::args();
    let mut newline = true;

    if let Some(arg) = args.nth(1) {
        if arg == "-n" {
            newline = false;
            if let Some(arg) = args.nth(0) {write!(stdout, "{}", arg).try();}
        } else {
            write!(stdout, "{}", arg).try();
        }
    }
    for arg in args {
        write!(stdout, " {}", arg).try();
    }
    if newline {
        write!(stdout, "\n").try();
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use std::convert::TryInto;

use crate::action;
use crate::message;
use crate::session;

pub struct Response<R: action::Response> {
    pub session_id: String,
    pub request_id: Option<u64>,
    pub response_id: Option<u64>,
    pub data: R,
}

pub struct Status {
    pub session_id: String,
    pub request_id: u64,
    pub result: session::Result<()>,
}

impl<R: action::Response> Response<R> {

    pub fn send(self) -> Result<(), prost::EncodeError> {
        let message = self.try_into()?;
        message::send(message);

        Ok(())
    }
}

impl<R: action::Response> TryInto<rrg_proto::GrrMessage> for Response<R> {

    type Error = prost::EncodeError;

    fn try_into(self) -> Result<rrg_proto::GrrMessage, prost::EncodeError> {
        let mut data = Vec::new();
        prost::Message::encode(&self.data.into_proto(), &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: self.response_id,
            request_id: self.request_id,
            r#type: Some(rrg_proto::grr_message::Type::Message.into()),
            args_rdf_name: R::RDF_NAME.map(String::from),
            args: Some(data),
            ..Default::default()
        })
    }
}

impl TryInto<rrg_proto::GrrMessage> for Status {

    type Error = prost::EncodeError;

    fn try_into(self) -> Result<rrg_proto::GrrMessage, prost::EncodeError> {
        let status = match self.result {
            Ok(()) => rrg_proto::GrrStatus {
                status: Some(rrg_proto::grr_status::ReturnedStatus::Ok.into()),
                ..Default::default()
            },
            Err(error) => rrg_proto::GrrStatus {
                status: Some(rrg_proto::grr_status::ReturnedStatus::GenericError.into()),
                error_message: Some(error.to_string()),
                ..Default::default()
            },
        };

        let mut data = Vec::new();
        prost::Message::encode(&status, &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: Some(self.request_id),
            r#type: Some(rrg_proto::grr_message::Type::Status.into()),
            args_rdf_name: Some(String::from("GrrStatus")),
            args: Some(data),
            ..Default::default()
        })
    }
}
<commit_msg>Use a local import to avoid long lines.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use std::convert::TryInto;

use crate::action;
use crate::message;
use crate::session;

pub struct Response<R: action::Response> {
    pub session_id: String,
    pub request_id: Option<u64>,
    pub response_id: Option<u64>,
    pub data: R,
}

pub struct Status {
    pub session_id: String,
    pub request_id: u64,
    pub result: session::Result<()>,
}

impl<R: action::Response> Response<R> {

    pub fn send(self) -> Result<(), prost::EncodeError> {
        let message = self.try_into()?;
        message::send(message);

        Ok(())
    }
}

impl<R: action::Response> TryInto<rrg_proto::GrrMessage> for Response<R> {

    type Error = prost::EncodeError;

    fn try_into(self) -> Result<rrg_proto::GrrMessage, prost::EncodeError> {
        let mut data = Vec::new();
        prost::Message::encode(&self.data.into_proto(), &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: self.response_id,
            request_id: self.request_id,
            r#type: Some(rrg_proto::grr_message::Type::Message.into()),
            args_rdf_name: R::RDF_NAME.map(String::from),
            args: Some(data),
            ..Default::default()
        })
    }
}

impl TryInto<rrg_proto::GrrMessage> for Status {

    type Error = prost::EncodeError;

    fn try_into(self) -> Result<rrg_proto::GrrMessage, prost::EncodeError> {
        use rrg_proto::grr_status::ReturnedStatus;

        let status = match self.result {
            Ok(()) => rrg_proto::GrrStatus {
                status: Some(ReturnedStatus::Ok.into()),
                ..Default::default()
            },
            Err(error) => rrg_proto::GrrStatus {
                status: Some(ReturnedStatus::GenericError.into()),
                error_message: Some(error.to_string()),
                ..Default::default()
            },
        };

        let mut data = Vec::new();
        prost::Message::encode(&status, &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: Some(self.request_id),
            r#type: Some(rrg_proto::grr_message::Type::Status.into()),
            args_rdf_name: Some(String::from("GrrStatus")),
            args: Some(data),
            ..Default::default()
        })
    }
}
<|endoftext|>


<commit_before>use std::env;

use cargo::ops;
use cargo::util::{CliResult, Config};

#[derive(Deserialize)]
pub struct Options {
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_bin: bool,
    flag_lib: bool,
    arg_path: Option<String>,
    flag_name: Option<String>,
    flag_vcs: Option<ops::VersionControl>,
    flag_frozen: bool,
    flag_locked: bool,
}

pub const USAGE: &'static str = "
Create a new cargo package in current directory

Usage:
    cargo init [options] [<path>]
    cargo init -h | --help

Options:
    -h, --help          Print this message
    --vcs VCS           Initialize a new repository for the given version
                        control system (git or hg) or do not initialize any version
                        control at all (none) overriding a global configuration.
    --bin               Use a binary (application) template
    --lib               Use a library template [default]
    --name NAME         Set the resulting package name
    -v, --verbose ...   Use verbose output (-vv very verbose/build.rs output)
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date
";

pub fn execute(options: Options, config: &Config) -> CliResult {
    debug!("executing; cmd=cargo-init; args={:?}", env::args().collect::<Vec<_>>());
    config.configure(options.flag_verbose,
                     options.flag_quiet,
                     &options.flag_color,
                     options.flag_frozen,
                     options.flag_locked)?;

    let Options { flag_bin, flag_lib, arg_path, flag_name, flag_vcs, .. } = options;

    let tmp = &arg_path.unwrap_or(format!("."));
    let opts = ops::NewOptions::new(flag_vcs,
                                     flag_bin,
                                     flag_lib,
                                     tmp,
                                     flag_name.as_ref().map(|s| s.as_ref()));

    let opts_lib = opts.lib;
    ops::init(opts, config)?;

    config.shell().status("Created", format!("{} project",
                                             if opts_lib { "library" }
                                             else {"binary (application)"}))?;

    Ok(())
}

<commit_msg>[bin/init] Update USAGE<commit_after>use std::env;

use cargo::ops;
use cargo::util::{CliResult, Config};

#[derive(Deserialize)]
pub struct Options {
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_bin: bool,
    flag_lib: bool,
    arg_path: Option<String>,
    flag_name: Option<String>,
    flag_vcs: Option<ops::VersionControl>,
    flag_frozen: bool,
    flag_locked: bool,
}

pub const USAGE: &'static str = "
Create a new cargo package in an existing directory

Usage:
    cargo init [options] [<path>]
    cargo init -h | --help

Options:
    -h, --help          Print this message
    --vcs VCS           Initialize a new repository for the given version
                        control system (git, hg, pijul, or fossil) or do not
                        initialize any version control at all (none), overriding
                        a global configuration.
    --bin               Use a binary (application) template
    --lib               Use a library template [default]
    --name NAME         Set the resulting package name
    -v, --verbose ...   Use verbose output (-vv very verbose/build.rs output)
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date
";

pub fn execute(options: Options, config: &Config) -> CliResult {
    debug!("executing; cmd=cargo-init; args={:?}", env::args().collect::<Vec<_>>());
    config.configure(options.flag_verbose,
                     options.flag_quiet,
                     &options.flag_color,
                     options.flag_frozen,
                     options.flag_locked)?;

    let Options { flag_bin, flag_lib, arg_path, flag_name, flag_vcs, .. } = options;

    let path = &arg_path.unwrap_or(format!("."));
    let opts = ops::NewOptions::new(flag_vcs,
                                     flag_bin,
                                     flag_lib,
                                     path,
                                     flag_name.as_ref().map(|s| s.as_ref()));

    let opts_lib = opts.lib;
    ops::init(opts, config)?;

    config.shell().status("Created", format!("{} project",
                                             if opts_lib { "library" }
                                             else {"binary (application)"}))?;

    Ok(())
}

<|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate env_logger;
extern crate getopts;
#[macro_use]
extern crate log;
extern crate log_settings;
extern crate miri;
extern crate rustc;
extern crate rustc_metadata;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_codegen_utils;
extern crate rustc_interface;
extern crate syntax;

use std::str::FromStr;
use std::env;

use rustc_interface::interface;
use rustc::hir::def_id::LOCAL_CRATE;

struct MiriCompilerCalls {
    miri_config: miri::MiriConfig,
}

impl rustc_driver::Callbacks for MiriCompilerCalls {
    fn after_parsing(&mut self, compiler: &interface::Compiler) -> bool {
        let attr = (
            syntax::symbol::Symbol::intern("miri"),
            syntax::feature_gate::AttributeType::Whitelisted,
        );
        compiler.session().plugin_attributes.borrow_mut().push(attr);

        // Continue execution
        true
    }

    fn after_analysis(&mut self, compiler: &interface::Compiler) -> bool {
        init_late_loggers();
        compiler.session().abort_if_errors();

        compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| {
            let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect("no main function found!");
            let mut config = self.miri_config.clone();

            // Add filename to `miri` arguments.
            config.args.insert(0, compiler.input().filestem().to_string());

            miri::eval_main(tcx, entry_def_id, config);
        });

        compiler.session().abort_if_errors();

        // Don't continue execution
        false
    }
}

fn init_early_loggers() {
    // Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to
    // initialize them both, and we always initialize `miri`'s first.
    let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE");
    env_logger::init_from_env(env);
    // We only initialize `rustc` if the env var is set (so the user asked for it).
    // If it is not set, we avoid initializing now so that we can initialize
    // later with our custom settings, and *not* log anything for what happens before
    // `miri` gets started.
    if env::var("RUSTC_LOG").is_ok() {
        rustc_driver::init_rustc_env_logger();
    }
}

fn init_late_loggers() {
    // We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG`
    // env var if it is not set, control it based on `MIRI_LOG`.
    if let Ok(var) = env::var("MIRI_LOG") {
        if env::var("RUSTC_LOG").is_err() {
            // We try to be a bit clever here: if `MIRI_LOG` is just a single level
            // used for everything, we only apply it to the parts of rustc that are
            // CTFE-related. Otherwise, we use it verbatim for `RUSTC_LOG`.
            // This way, if you set `MIRI_LOG=trace`, you get only the right parts of
            // rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_mir::interpret=debug`.
            if log::Level::from_str(&var).is_ok() {
                env::set_var("RUSTC_LOG",
                    &format!("rustc::mir::interpret={0},rustc_mir::interpret={0}", var));
            } else {
                env::set_var("RUSTC_LOG", &var);
            }
            rustc_driver::init_rustc_env_logger();
        }
    }

    // If `MIRI_BACKTRACE` is set and `RUST_CTFE_BACKTRACE` is not, set `RUST_CTFE_BACKTRACE`.
    // Do this late, so we really only apply this to miri's errors.
    if let Ok(var) = env::var("MIRI_BACKTRACE") {
        if env::var("RUST_CTFE_BACKTRACE") == Err(env::VarError::NotPresent) {
            env::set_var("RUST_CTFE_BACKTRACE", &var);
        }
    }
}

/// Returns the "default sysroot" that Miri will use if no `--sysroot` flag is set.
/// Should be a compile-time constant.
fn compile_time_sysroot() -> String {
    // Taken from PR <https://github.com/Manishearth/rust-clippy/pull/911>.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => {
            option_env!("RUST_SYSROOT")
                .expect(
                    "could not find sysroot. Either set `MIRI_SYSROOT` at run-time, or at \
                     build-time specify `RUST_SYSROOT` env var or use rustup or multirust",
                )
                .to_owned()
        }
    }
}

fn main() {
    init_early_loggers();

    // Parse our arguments and split them across `rustc` and `miri`.
    let mut validate = true;
    let mut seed: Option<u64> = None;
    let mut rustc_args = vec![];
    let mut miri_args = vec![];
    let mut after_dashdash = false;
    for arg in std::env::args() {
        if rustc_args.is_empty() {
            // Very first arg: for `rustc`.
            rustc_args.push(arg);
        }
        else if after_dashdash {
            // Everything that comes after are `miri` args.
            miri_args.push(arg);
        } else {
            match arg.as_str() {
                "-Zmiri-disable-validation" => {
                    validate = false;
                },
                "--" => {
                    after_dashdash = true;
                }
                arg if arg.starts_with("-Zmiri-seed=") => {
                    if seed.is_some() {
                        panic!("Cannot specify -Zmiri-seed multiple times!");
                    }
                    let seed_raw = hex::decode(arg.trim_start_matches("-Zmiri-seed=")).unwrap();
                    if seed_raw.len() > 8 {
                        panic!(format!("-Zmiri-seed must be at most 8 bytes, was {}", seed_raw.len()));
                    }

                    let mut bytes = [0; 8];
                    bytes[..seed_raw.len()].copy_from_slice(&seed_raw);
                    seed = Some(u64::from_be_bytes(bytes));

                },
                _ => {
                    rustc_args.push(arg);
                }
            }
        }
    }

    // Determine sysroot.
    let sysroot_flag = "--sysroot".to_string();
    if !rustc_args.contains(&sysroot_flag) {
        // We need to *always* set a --sysroot, as the "default" rustc uses is
        // somewhere in the directory miri was built in.
        // If no --sysroot is given, fall back to env vars that are read at *compile-time*.
        rustc_args.push(sysroot_flag);
        rustc_args.push(compile_time_sysroot());
    }

    // Finally, add the default flags all the way in the beginning, but after the binary name.
    rustc_args.splice(1..1, miri::miri_default_args().iter().map(ToString::to_string));

    debug!("rustc arguments: {:?}", rustc_args);
    debug!("miri arguments: {:?}", miri_args);
    let miri_config = miri::MiriConfig { validate, args: miri_args, seed };
    let result = rustc_driver::report_ices_to_stderr_if_any(move || {
        rustc_driver::run_compiler(&rustc_args, &mut MiriCompilerCalls { miri_config }, None, None)
    }).and_then(|result| result);
    std::process::exit(result.is_err() as i32);
}
<commit_msg>fix running a Miri that was built in bootstrap<commit_after>#![feature(rustc_private)]

extern crate env_logger;
extern crate getopts;
#[macro_use]
extern crate log;
extern crate log_settings;
extern crate miri;
extern crate rustc;
extern crate rustc_metadata;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_codegen_utils;
extern crate rustc_interface;
extern crate syntax;

use std::str::FromStr;
use std::env;

use rustc_interface::interface;
use rustc::hir::def_id::LOCAL_CRATE;

struct MiriCompilerCalls {
    miri_config: miri::MiriConfig,
}

impl rustc_driver::Callbacks for MiriCompilerCalls {
    fn after_parsing(&mut self, compiler: &interface::Compiler) -> bool {
        let attr = (
            syntax::symbol::Symbol::intern("miri"),
            syntax::feature_gate::AttributeType::Whitelisted,
        );
        compiler.session().plugin_attributes.borrow_mut().push(attr);

        // Continue execution
        true
    }

    fn after_analysis(&mut self, compiler: &interface::Compiler) -> bool {
        init_late_loggers();
        compiler.session().abort_if_errors();

        compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| {
            let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect("no main function found!");
            let mut config = self.miri_config.clone();

            // Add filename to `miri` arguments.
            config.args.insert(0, compiler.input().filestem().to_string());

            miri::eval_main(tcx, entry_def_id, config);
        });

        compiler.session().abort_if_errors();

        // Don't continue execution
        false
    }
}

fn init_early_loggers() {
    // Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to
    // initialize them both, and we always initialize `miri`'s first.
    let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE");
    env_logger::init_from_env(env);
    // We only initialize `rustc` if the env var is set (so the user asked for it).
    // If it is not set, we avoid initializing now so that we can initialize
    // later with our custom settings, and *not* log anything for what happens before
    // `miri` gets started.
    if env::var("RUSTC_LOG").is_ok() {
        rustc_driver::init_rustc_env_logger();
    }
}

fn init_late_loggers() {
    // We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG`
    // env var if it is not set, control it based on `MIRI_LOG`.
    if let Ok(var) = env::var("MIRI_LOG") {
        if env::var("RUSTC_LOG").is_err() {
            // We try to be a bit clever here: if `MIRI_LOG` is just a single level
            // used for everything, we only apply it to the parts of rustc that are
            // CTFE-related. Otherwise, we use it verbatim for `RUSTC_LOG`.
            // This way, if you set `MIRI_LOG=trace`, you get only the right parts of
            // rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_mir::interpret=debug`.
            if log::Level::from_str(&var).is_ok() {
                env::set_var("RUSTC_LOG",
                    &format!("rustc::mir::interpret={0},rustc_mir::interpret={0}", var));
            } else {
                env::set_var("RUSTC_LOG", &var);
            }
            rustc_driver::init_rustc_env_logger();
        }
    }

    // If `MIRI_BACKTRACE` is set and `RUST_CTFE_BACKTRACE` is not, set `RUST_CTFE_BACKTRACE`.
    // Do this late, so we really only apply this to miri's errors.
    if let Ok(var) = env::var("MIRI_BACKTRACE") {
        if env::var("RUST_CTFE_BACKTRACE") == Err(env::VarError::NotPresent) {
            env::set_var("RUST_CTFE_BACKTRACE", &var);
        }
    }
}

/// Returns the "default sysroot" that Miri will use if no `--sysroot` flag is set.
/// Should be a compile-time constant.
fn compile_time_sysroot() -> Option<String> {
    if option_env!("RUSTC_STAGE").is_some() {
        // This is being built as part of rustc, and gets shipped with rustup.
        // We can rely on the sysroot computation in librustc.
        return None;
    }
    // For builds outside rustc, we need to ensure that we got a sysroot
    // that gets used as a default.  The sysroot computation in librustc would
    // end up somewhere in the build dir.
    // Taken from PR <https://github.com/Manishearth/rust-clippy/pull/911>.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    Some(match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => {
            option_env!("RUST_SYSROOT")
                .expect("To build Miri without rustup, set the `RUST_SYSROOT` env var at build time")
                .to_owned()
        }
    })
}

fn main() {
    init_early_loggers();

    // Parse our arguments and split them across `rustc` and `miri`.
    let mut validate = true;
    let mut seed: Option<u64> = None;
    let mut rustc_args = vec![];
    let mut miri_args = vec![];
    let mut after_dashdash = false;
    for arg in std::env::args() {
        if rustc_args.is_empty() {
            // Very first arg: for `rustc`.
            rustc_args.push(arg);
        }
        else if after_dashdash {
            // Everything that comes after are `miri` args.
            miri_args.push(arg);
        } else {
            match arg.as_str() {
                "-Zmiri-disable-validation" => {
                    validate = false;
                },
                "--" => {
                    after_dashdash = true;
                }
                arg if arg.starts_with("-Zmiri-seed=") => {
                    if seed.is_some() {
                        panic!("Cannot specify -Zmiri-seed multiple times!");
                    }
                    let seed_raw = hex::decode(arg.trim_start_matches("-Zmiri-seed=")).unwrap();
                    if seed_raw.len() > 8 {
                        panic!(format!("-Zmiri-seed must be at most 8 bytes, was {}", seed_raw.len()));
                    }

                    let mut bytes = [0; 8];
                    bytes[..seed_raw.len()].copy_from_slice(&seed_raw);
                    seed = Some(u64::from_be_bytes(bytes));

                },
                _ => {
                    rustc_args.push(arg);
                }
            }
        }
    }

    // Determine sysroot if needed.  Make sure we always call `compile_time_sysroot`
    // as that also does some sanity-checks of the environment we were built in.
    // FIXME: Ideally we'd turn a bad build env into a compile-time error, but
    // CTFE does not seem powerful enough for that yet.
    if let Some(sysroot) = compile_time_sysroot() {
        let sysroot_flag = "--sysroot".to_string();
        if !rustc_args.contains(&sysroot_flag) {
            // We need to overwrite the default that librustc would compute.
            rustc_args.push(sysroot_flag);
            rustc_args.push(sysroot);
        }
    }

    // Finally, add the default flags all the way in the beginning, but after the binary name.
    rustc_args.splice(1..1, miri::miri_default_args().iter().map(ToString::to_string));

    debug!("rustc arguments: {:?}", rustc_args);
    debug!("miri arguments: {:?}", miri_args);
    let miri_config = miri::MiriConfig { validate, args: miri_args, seed };
    let result = rustc_driver::report_ices_to_stderr_if_any(move || {
        rustc_driver::run_compiler(&rustc_args, &mut MiriCompilerCalls { miri_config }, None, None)
    }).and_then(|result| result);
    std::process::exit(result.is_err() as i32);
}
<|endoftext|>


<commit_before>#![crate_name = "rboy"]
#![license    = "MIT" ]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;
#[phase(plugin)]       extern crate lazy_static;
                       extern crate spinlock;
                       extern crate native;
                       extern crate getopts;
                       extern crate sdl;
                       extern crate rboy;

use rboy::device::Device;
use std::sync::{Arc,RWLock};
use std::comm::{Sender,Receiver,Disconnected,Empty};
use std::task::TaskBuilder;
use std::collections::{Deque, DList};
use native::NativeTaskBuilder;
use spinlock::Spinlock;

static SCALE: uint = 2;
static EXITCODE_INCORRECTOPTIONS: int = 1;
static EXITCODE_CPULOADFAILS: int = 2;

lazy_static! {
	static ref SOUND_BUFFER: Arc<Spinlock<DList<u8>>> = Arc::new(Spinlock::new(DList::new()));
}

fn main() {
	let args = std::os::args();
	let opts = [ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free[0].clone()
	} else {
		println!("{}", getopts::usage(args[0].clone().append(" <filename>").as_slice(), opts));
		std::os::set_exit_status(EXITCODE_INCORRECTOPTIONS);
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE as int, 144*SCALE as int, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdl_tx, cpu_rx) = std::comm::channel();
	let (cpu_tx, sdl_rx) = std::comm::channel();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();

	TaskBuilder::new().native().spawn(proc() cpuloop(&cpu_tx, &cpu_rx, arc2, filename.as_slice(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdl_rx.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&screen, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdl_tx.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdl_tx.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdl_tx.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdl_tx.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<rboy::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(rboy::A),
		sdl::event::XKey => Some(rboy::B),
		sdl::event::UpKey => Some(rboy::Up),
		sdl::event::DownKey => Some(rboy::Down),
		sdl::event::LeftKey => Some(rboy::Left),
		sdl::event::RightKey => Some(rboy::Right),
		sdl::event::SpaceKey => Some(rboy::Select),
		sdl::event::ReturnKey => Some(rboy::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	let data = arc.read();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.fill_rect(
				Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
				sdl::video::RGB(data[y*160*3 + x*3 + 0],
				                data[y*160*3 + x*3 + 1],
				                data[y*160*3 + x*3 + 2])
			);
		}
	}
	screen.flip();
}

enum GBEvent {
	KeyUp(rboy::KeypadKey),
	KeyDown(rboy::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(cpu_tx: &Sender<uint>, cpu_rx: &Receiver<GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => Device::new(filename),
		false => Device::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); std::os::set_exit_status(EXITCODE_CPULOADFAILS); return; },
	};
	c.set_stdout(matches.opt_present("serial"));

	let soundbuffer = SOUND_BUFFER.clone();
	c.set_sound_buffer(soundbuffer);
	open_audio();

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);
	let mut limit_speed = true;

	let waitticks = (4194.304f32 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.check_and_reset_gpu_updated() {
				let mut data = arc.write();
				let gpu_data = c.get_gpu_data();
				for i in range(0, data.len()) { data[i] = gpu_data[i]; }
				if cpu_tx.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		if limit_speed { periodic.recv(); }

		match cpu_rx.try_recv() {
			Ok(event) => match event {
				KeyUp(key) => c.keyup(key),
				KeyDown(key) => c.keydown(key),
				SpeedUp => limit_speed = false,
				SlowDown => limit_speed = true,
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
	close_audio();
}

fn sound_callback(sdlbuf: &mut [u8])
{
	let soundbuffer = SOUND_BUFFER.clone();
	let mut data = soundbuffer.lock();

	for i in range(0, sdlbuf.len())
	{
		sdlbuf[i] = data.pop_front().unwrap_or(0);
	}
}

fn open_audio()
{
	let spec = sdl::audio::DesiredAudioSpec
	{
		freq: 44100,
		format: sdl::audio::S8AudioFormat,
		channels: sdl::audio::Stereo,
		samples: 1024,
		callback: sound_callback,
	};
	match sdl::audio::open(spec)
	{
		Ok(_) => {},
		Err(()) => error!("Could not open audio"),
	}
	sdl::audio::pause(false);
}

fn close_audio()
{
	sdl::audio::close();
}
<commit_msg>timer.periodic now needs a Duration struct<commit_after>#![crate_name = "rboy"]
#![license    = "MIT" ]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;
#[phase(plugin)]       extern crate lazy_static;
                       extern crate spinlock;
                       extern crate native;
                       extern crate getopts;
                       extern crate sdl;
                       extern crate rboy;

use rboy::device::Device;
use std::time::Duration;
use std::sync::{Arc,RWLock};
use std::comm::{Sender,Receiver,Disconnected,Empty};
use std::task::TaskBuilder;
use std::collections::{Deque, DList};
use native::NativeTaskBuilder;
use spinlock::Spinlock;

static SCALE: uint = 2;
static EXITCODE_INCORRECTOPTIONS: int = 1;
static EXITCODE_CPULOADFAILS: int = 2;

lazy_static! {
	static ref SOUND_BUFFER: Arc<Spinlock<DList<u8>>> = Arc::new(Spinlock::new(DList::new()));
}

fn main() {
	let args = std::os::args();
	let opts = [ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free[0].clone()
	} else {
		println!("{}", getopts::usage(args[0].clone().append(" <filename>").as_slice(), opts));
		std::os::set_exit_status(EXITCODE_INCORRECTOPTIONS);
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE as int, 144*SCALE as int, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdl_tx, cpu_rx) = std::comm::channel();
	let (cpu_tx, sdl_rx) = std::comm::channel();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();

	TaskBuilder::new().native().spawn(proc() cpuloop(&cpu_tx, &cpu_rx, arc2, filename.as_slice(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(Duration::milliseconds(8));

	'main : loop {
		periodic.recv();
		match sdl_rx.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&screen, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdl_tx.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdl_tx.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdl_tx.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdl_tx.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<rboy::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(rboy::A),
		sdl::event::XKey => Some(rboy::B),
		sdl::event::UpKey => Some(rboy::Up),
		sdl::event::DownKey => Some(rboy::Down),
		sdl::event::LeftKey => Some(rboy::Left),
		sdl::event::RightKey => Some(rboy::Right),
		sdl::event::SpaceKey => Some(rboy::Select),
		sdl::event::ReturnKey => Some(rboy::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	let data = arc.read();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.fill_rect(
				Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
				sdl::video::RGB(data[y*160*3 + x*3 + 0],
				                data[y*160*3 + x*3 + 1],
				                data[y*160*3 + x*3 + 2])
			);
		}
	}
	screen.flip();
}

enum GBEvent {
	KeyUp(rboy::KeypadKey),
	KeyDown(rboy::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(cpu_tx: &Sender<uint>, cpu_rx: &Receiver<GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => Device::new(filename),
		false => Device::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); std::os::set_exit_status(EXITCODE_CPULOADFAILS); return; },
	};
	c.set_stdout(matches.opt_present("serial"));

	let soundbuffer = SOUND_BUFFER.clone();
	c.set_sound_buffer(soundbuffer);
	open_audio();

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(Duration::milliseconds(8));
	let mut limit_speed = true;

	let waitticks = (4194.304f32 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.check_and_reset_gpu_updated() {
				let mut data = arc.write();
				let gpu_data = c.get_gpu_data();
				for i in range(0, data.len()) { data[i] = gpu_data[i]; }
				if cpu_tx.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		if limit_speed { periodic.recv(); }

		match cpu_rx.try_recv() {
			Ok(event) => match event {
				KeyUp(key) => c.keyup(key),
				KeyDown(key) => c.keydown(key),
				SpeedUp => limit_speed = false,
				SlowDown => limit_speed = true,
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
	close_audio();
}

fn sound_callback(sdlbuf: &mut [u8])
{
	let soundbuffer = SOUND_BUFFER.clone();
	let mut data = soundbuffer.lock();

	for i in range(0, sdlbuf.len())
	{
		sdlbuf[i] = data.pop_front().unwrap_or(0);
	}
}

fn open_audio()
{
	let spec = sdl::audio::DesiredAudioSpec
	{
		freq: 44100,
		format: sdl::audio::S8AudioFormat,
		channels: sdl::audio::Stereo,
		samples: 1024,
		callback: sound_callback,
	};
	match sdl::audio::open(spec)
	{
		Ok(_) => {},
		Err(()) => error!("Could not open audio"),
	}
	sdl::audio::pause(false);
}

fn close_audio()
{
	sdl::audio::close();
}
<|endoftext|>