<commit_before>use std::rc::Rc;
use ast::typed::{Signedness, Size, Type, TypeVar};
use super::rollback_map::Map;

#[derive(Debug, Clone)]
enum VarTarget {
    Type(Type),
    UnsizedInt(Signedness),
    Int,
}

pub struct UnifyTable {
    var_target: Map<TypeVar, VarTarget>,
    next_var: u32,
}

impl UnifyTable {
    pub fn new() -> UnifyTable {
        UnifyTable {
            var_target: Map::new(),
            next_var: 0,
        }
    }

    pub fn fresh_var(&mut self) -> TypeVar {
        let var = TypeVar(self.next_var);
        self.next_var += 1;
        var
    }

    pub fn fresh_int_var(&mut self, sign: Option<Signedness>) -> TypeVar {
        let var = TypeVar(self.next_var);
        match sign {
            Some(sign) => self.var_target.insert(var, VarTarget::UnsizedInt(sign)),
            None => self.var_target.insert(var, VarTarget::Int),
        }
        self.var_target.commit();
        self.next_var += 1;
        var
    }

    pub fn unify(&mut self, a: &Type, b: &Type) -> Result<Type, ()> {
        match self.unify_raw(a, b) {
            Ok(()) => {
                self.commit();
                Ok(a.clone())
            }
            Err(()) => {
                self.rollback();
                Err(())
            }
        }
    }

    fn unify_raw(&mut self, a: &Type, b: &Type) -> Result<(), ()> {
        let a = self.shallow_normalize(a);
        let b = self.shallow_normalize(b);
        match (a, b) {
            (Type::Concrete(a, ref ap), Type::Concrete(b, ref bp)) => if a == b {
                assert_eq!(ap.len(), bp.len());
                for (a, b) in ap.iter().zip(bp.iter()) {
                    self.unify_raw(a, b)?;
                }
                Ok(())
            } else {
                Err(())
            },
            (Type::Function(ref ap, ref a), Type::Function(ref bp, ref b)) => {
                if ap.len() == bp.len() {
                    for (a, b) in ap.iter().zip(bp.iter()) {
                        self.unify_raw(a, b)?;
                    }
                    self.unify_raw(a, b)
                } else {
                    Err(())
                }
            }
            (Type::Int(sign1, size1), Type::Int(sign2, size2)) => {
                if sign1 == sign2 && size1 == size2 {
                    Ok(())
                } else {
                    Err(())
                }
            }
            // TODO: accout for mutability
            (Type::Pointer(_, ref a), Type::Pointer(_, ref b)) => self.unify_raw(a, b),
            (Type::Var(a), ty) | (ty, Type::Var(a)) => self.unify_var_type(a, ty),
            (Type::Bool, Type::Bool) |
            (Type::Unit, Type::Unit) |
            (Type::Error, _) | (_, Type::Error) => Ok(()),
            (_, _) => Err(()),
        }
    }

    fn unify_var_var(&mut self, a: TypeVar, b: TypeVar) -> Result<(), ()> {
        let at = self.var_target.get(&a).cloned();
        let bt = self.var_target.get(&b).cloned();
        match (at, bt) {
            (Some(VarTarget::Type(_)), _) | (_, Some(VarTarget::Type(_))) => {
                panic!("cannot unify non-normalized var")
            }
            (None, _) | (Some(VarTarget::Int), Some(_)) => {
                self.var_target.insert(a, VarTarget::Type(Type::Var(b)));
                Ok(())
            }
            (_, None) | (Some(_), Some(VarTarget::Int)) => {
                self.var_target.insert(b, VarTarget::Type(Type::Var(a)));
                Ok(())
            }
            (Some(VarTarget::UnsizedInt(s1)), Some(VarTarget::UnsizedInt(s2))) => if s1 == s2 {
                self.var_target.insert(a, VarTarget::Type(Type::Var(b)));
                Ok(())
            } else {
                Err(())
            },
        }
    }

    fn unify_var_type(&mut self, v: TypeVar, b: Type) -> Result<(), ()> {
        match b {
            Type::Var(b) if b == v => return Ok(()),
            _ => {}
        }
        if self.occurs(v, &b) {
            return Err(());
        }
        let vt = self.var_target.get(&v).cloned();
        match (vt, b) {
            (_, Type::Error) => {
                self.var_target.insert(v, VarTarget::Type(Type::Error));
                Ok(())
            }
            (Some(VarTarget::Type(_)), _) => panic!("cannot unify non-normalized var"),
            (_, Type::Var(b)) => self.unify_var_var(v, b),
            (None, ty) | (Some(VarTarget::Int), ty @ Type::Int(_, _)) => {
                self.var_target.insert(v, VarTarget::Type(ty));
                Ok(())
            }
            (Some(VarTarget::UnsizedInt(sign)), Type::Int(sign2, size)) => if sign == sign2 {
                self.var_target
                    .insert(v, VarTarget::Type(Type::Int(sign2, size)));
                Ok(())
            } else {
                Err(())
            },
            _ => Err(()),
        }
    }

    fn occurs(&mut self, var: TypeVar, typ: &Type) -> bool {
        let typ = self.shallow_normalize(typ);
        match typ {
            Type::Bool | Type::Error | Type::Int(_, _) | Type::Unit => false,
            Type::Concrete(_, ref params) => {
                for param in params.iter() {
                    if self.occurs(var, param) {
                        return true;
                    }
                }
                false
            }
            Type::Function(ref params, ref out) => {
                for param in params.iter() {
                    if self.occurs(var, param) {
                        return true;
                    }
                }
                self.occurs(var, out)
            }
            Type::Pointer(_, ref to) => self.occurs(var, to),
            Type::Var(v) => var == v,
        }
    }

    fn get_var_type(&self, var: TypeVar) -> Type {
        match self.var_target.get(&var) {
            Some(&VarTarget::Type(ref ty)) => self.shallow_normalize(ty),
            Some(&VarTarget::Int) | Some(&VarTarget::UnsizedInt(_)) | None => Type::Var(var),
        }
    }

    pub fn shallow_normalize(&self, a: &Type) -> Type {
        match a {
            &Type::Var(var) => self.get_var_type(var),
            ty => ty.clone(),
        }
    }

    pub fn normalize(&mut self, a: &Type) -> Result<Type, ()> {
        match self.shallow_normalize(a) {
            Type::Bool => Ok(Type::Bool),
            Type::Unit => Ok(Type::Unit),
            Type::Concrete(sym, ref params) => {
                let mut normalized = Vec::new();
                for param in &**params {
                    normalized.push(self.normalize(param)?);
                }
                Ok(Type::Concrete(sym, normalized.into()))
            }
            Type::Error => Ok(Type::Error),
            Type::Function(ref params, ref out) => {
                let out = self.normalize(out)?;
                let mut normalized = Vec::new();
                for param in &**params {
                    normalized.push(self.normalize(param)?);
                }
                Ok(Type::Function(normalized.into(), Rc::new(out)))
            }
            ty @ Type::Int(_, _) => Ok(ty),
            Type::Pointer(mutability, ref ty) => {
                let ty = self.normalize(ty)?;
                Ok(Type::Pointer(mutability, Rc::new(ty)))
            }
            Type::Var(var) => {
                match self.var_target.get(&var) {
                    Some(&VarTarget::Type(_)) => panic!("var not normalized"),
                    Some(&VarTarget::Int) => {
                        return Ok(Type::Int(Signedness::Signed, Size::Bit32));
                    }
                    Some(&VarTarget::UnsizedInt(sign)) => {
                        return Ok(Type::Int(sign, Size::Bit32));
                    }
                    None => {
                        // there is no sensible default
                        // fall though because of borrowck
                    }
                }
                // unify this var with an error to prevent further
                // error reports about same variable
                self.var_target.insert(var, VarTarget::Type(Type::Error));
                Err(())
            }
        }
    }

    pub fn describe_var(&self, var: TypeVar) -> &'static str {
        match self.var_target.get(&var) {
            Some(&VarTarget::Int) => "{int}",
            Some(&VarTarget::UnsizedInt(Signedness::Signed)) => "{signed}",
            Some(&VarTarget::UnsizedInt(Signedness::Unsigned)) => "{unsigned}",
            _ => "_",
        }
    }

    fn commit(&mut self) {
        self.var_target.commit();
    }

    fn rollback(&mut self) {
        self.var_target.rollback();
    }
}
<commit_msg>coerce `*mut _` to `*_`<commit_after>use std::rc::Rc;
use ast::typed::{Mutability, Signedness, Size, Type, TypeVar};
use super::rollback_map::Map;

#[derive(Debug, Clone)]
enum VarTarget {
    Type(Type),
    UnsizedInt(Signedness),
    Int,
}

pub struct UnifyTable {
    var_target: Map<TypeVar, VarTarget>,
    next_var: u32,
}

impl UnifyTable {
    pub fn new() -> UnifyTable {
        UnifyTable {
            var_target: Map::new(),
            next_var: 0,
        }
    }

    pub fn fresh_var(&mut self) -> TypeVar {
        let var = TypeVar(self.next_var);
        self.next_var += 1;
        var
    }

    pub fn fresh_int_var(&mut self, sign: Option<Signedness>) -> TypeVar {
        let var = TypeVar(self.next_var);
        match sign {
            Some(sign) => self.var_target.insert(var, VarTarget::UnsizedInt(sign)),
            None => self.var_target.insert(var, VarTarget::Int),
        }
        self.var_target.commit();
        self.next_var += 1;
        var
    }

    pub fn unify(&mut self, a: &Type, b: &Type) -> Result<Type, ()> {
        match self.unify_raw(a, b, true) {
            Ok(()) => {
                self.commit();
                Ok(a.clone())
            }
            Err(()) => {
                self.rollback();
                Err(())
            }
        }
    }

    fn unify_raw(&mut self, a: &Type, b: &Type, allow_coerce: bool) -> Result<(), ()> {
        let a = self.shallow_normalize(a);
        let b = self.shallow_normalize(b);
        match (a, b) {
            (Type::Concrete(a, ref ap), Type::Concrete(b, ref bp)) => if a == b {
                assert_eq!(ap.len(), bp.len());
                for (a, b) in ap.iter().zip(bp.iter()) {
                    self.unify_raw(a, b, false)?;
                }
                Ok(())
            } else {
                Err(())
            },
            (Type::Function(ref ap, ref a), Type::Function(ref bp, ref b)) => {
                if ap.len() == bp.len() {
                    for (a, b) in ap.iter().zip(bp.iter()) {
                        // flip `a` and `b` when unifying because fns are
                        // contravariant on their arguments - so we can only
                        // coerce types backwards.
                        self.unify_raw(b, a, true)?;
                    }
                    self.unify_raw(a, b, true)
                } else {
                    Err(())
                }
            }
            (Type::Int(sign1, size1), Type::Int(sign2, size2)) => {
                if sign1 == sign2 && size1 == size2 {
                    Ok(())
                } else {
                    Err(())
                }
            }
            (Type::Pointer(m1, ref a), Type::Pointer(m2, ref b)) if m1 == m2 => {
                self.unify_raw(a, b, false)
            }
            (Type::Pointer(Mutability::Mut, ref a), Type::Pointer(Mutability::Const, ref b))
            if allow_coerce => {
                self.unify_raw(a, b, false)
            }
            (Type::Var(a), ty) | (ty, Type::Var(a)) => self.unify_var_type(a, ty),
            (Type::Bool, Type::Bool) |
            (Type::Unit, Type::Unit) |
            (Type::Error, _) | (_, Type::Error) => Ok(()),
            (_, _) => Err(()),
        }
    }

    fn unify_var_var(&mut self, a: TypeVar, b: TypeVar) -> Result<(), ()> {
        let at = self.var_target.get(&a).cloned();
        let bt = self.var_target.get(&b).cloned();
        match (at, bt) {
            (Some(VarTarget::Type(_)), _) | (_, Some(VarTarget::Type(_))) => {
                panic!("cannot unify non-normalized var")
            }
            (None, _) | (Some(VarTarget::Int), Some(_)) => {
                self.var_target.insert(a, VarTarget::Type(Type::Var(b)));
                Ok(())
            }
            (_, None) | (Some(_), Some(VarTarget::Int)) => {
                self.var_target.insert(b, VarTarget::Type(Type::Var(a)));
                Ok(())
            }
            (Some(VarTarget::UnsizedInt(s1)), Some(VarTarget::UnsizedInt(s2))) => if s1 == s2 {
                self.var_target.insert(a, VarTarget::Type(Type::Var(b)));
                Ok(())
            } else {
                Err(())
            },
        }
    }

    fn unify_var_type(&mut self, v: TypeVar, b: Type) -> Result<(), ()> {
        match b {
            Type::Var(b) if b == v => return Ok(()),
            _ => {}
        }
        if self.occurs(v, &b) {
            return Err(());
        }
        let vt = self.var_target.get(&v).cloned();
        match (vt, b) {
            (_, Type::Error) => {
                self.var_target.insert(v, VarTarget::Type(Type::Error));
                Ok(())
            }
            (Some(VarTarget::Type(_)), _) => panic!("cannot unify non-normalized var"),
            (_, Type::Var(b)) => self.unify_var_var(v, b),
            (None, ty) | (Some(VarTarget::Int), ty @ Type::Int(_, _)) => {
                self.var_target.insert(v, VarTarget::Type(ty));
                Ok(())
            }
            (Some(VarTarget::UnsizedInt(sign)), Type::Int(sign2, size)) => if sign == sign2 {
                self.var_target
                    .insert(v, VarTarget::Type(Type::Int(sign2, size)));
                Ok(())
            } else {
                Err(())
            },
            _ => Err(()),
        }
    }

    fn occurs(&mut self, var: TypeVar, typ: &Type) -> bool {
        let typ = self.shallow_normalize(typ);
        match typ {
            Type::Bool | Type::Error | Type::Int(_, _) | Type::Unit => false,
            Type::Concrete(_, ref params) => {
                for param in params.iter() {
                    if self.occurs(var, param) {
                        return true;
                    }
                }
                false
            }
            Type::Function(ref params, ref out) => {
                for param in params.iter() {
                    if self.occurs(var, param) {
                        return true;
                    }
                }
                self.occurs(var, out)
            }
            Type::Pointer(_, ref to) => self.occurs(var, to),
            Type::Var(v) => var == v,
        }
    }

    fn get_var_type(&self, var: TypeVar) -> Type {
        match self.var_target.get(&var) {
            Some(&VarTarget::Type(ref ty)) => self.shallow_normalize(ty),
            Some(&VarTarget::Int) | Some(&VarTarget::UnsizedInt(_)) | None => Type::Var(var),
        }
    }

    pub fn shallow_normalize(&self, a: &Type) -> Type {
        match a {
            &Type::Var(var) => self.get_var_type(var),
            ty => ty.clone(),
        }
    }

    pub fn normalize(&mut self, a: &Type) -> Result<Type, ()> {
        match self.shallow_normalize(a) {
            Type::Bool => Ok(Type::Bool),
            Type::Unit => Ok(Type::Unit),
            Type::Concrete(sym, ref params) => {
                let mut normalized = Vec::new();
                for param in &**params {
                    normalized.push(self.normalize(param)?);
                }
                Ok(Type::Concrete(sym, normalized.into()))
            }
            Type::Error => Ok(Type::Error),
            Type::Function(ref params, ref out) => {
                let out = self.normalize(out)?;
                let mut normalized = Vec::new();
                for param in &**params {
                    normalized.push(self.normalize(param)?);
                }
                Ok(Type::Function(normalized.into(), Rc::new(out)))
            }
            ty @ Type::Int(_, _) => Ok(ty),
            Type::Pointer(mutability, ref ty) => {
                let ty = self.normalize(ty)?;
                Ok(Type::Pointer(mutability, Rc::new(ty)))
            }
            Type::Var(var) => {
                match self.var_target.get(&var) {
                    Some(&VarTarget::Type(_)) => panic!("var not normalized"),
                    Some(&VarTarget::Int) => {
                        return Ok(Type::Int(Signedness::Signed, Size::Bit32));
                    }
                    Some(&VarTarget::UnsizedInt(sign)) => {
                        return Ok(Type::Int(sign, Size::Bit32));
                    }
                    None => {
                        // there is no sensible default
                        // fall though because of borrowck
                    }
                }
                // unify this var with an error to prevent further
                // error reports about same variable
                self.var_target.insert(var, VarTarget::Type(Type::Error));
                Err(())
            }
        }
    }

    pub fn describe_var(&self, var: TypeVar) -> &'static str {
        match self.var_target.get(&var) {
            Some(&VarTarget::Int) => "{int}",
            Some(&VarTarget::UnsizedInt(Signedness::Signed)) => "{signed}",
            Some(&VarTarget::UnsizedInt(Signedness::Unsigned)) => "{unsigned}",
            _ => "_",
        }
    }

    fn commit(&mut self) {
        self.var_target.commit();
    }

    fn rollback(&mut self) {
        self.var_target.rollback();
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::io;
use std::rc::{Rc, Weak};
use std::net::{Ipv4Addr, SocketAddr};
use std::time::Instant;
use log::LogLevel;
use mio::{Event, PollOpt, Ready, Token};
use mio::net::UdpSocket;

use super::binary;
use super::client::Client;
use super::connection::{self, Connection, ConnectionId};
use super::datagram_buffer::DatagramBuffer;
use super::ipv4_packet::{IPv4Packet, MAX_PACKET_LENGTH};
use super::packetizer::Packetizer;
use super::selector::Selector;

const TAG: &'static str = "UDPConnection";

pub const IDLE_TIMEOUT_SECONDS: u64 = 2 * 60;

pub struct UDPConnection {
    id: ConnectionId,
    client: Weak<RefCell<Client>>,
    socket: UdpSocket,
    token: Token,
    client_to_network: DatagramBuffer,
    network_to_client: Packetizer,
    closed: bool,
    idle_since: Instant,
}

impl UDPConnection {
    pub fn new(selector: &mut Selector, id: ConnectionId, client: Weak<RefCell<Client>>, reference_packet: &IPv4Packet) -> io::Result<Rc<RefCell<Self>>> {
        let socket = UDPConnection::create_socket(&id)?;
        let raw: &[u8] = reference_packet.raw();
        let ipv4_header = reference_packet.ipv4_header().clone();
        let transport_header = reference_packet.transport_header().as_ref().unwrap().clone();
        let rc = Rc::new(RefCell::new(Self {
            id: id,
            client: client,
            socket: socket,
            token: Token(0), // default value, will be set afterwards
            client_to_network: DatagramBuffer::new(4 * MAX_PACKET_LENGTH),
            network_to_client: Packetizer::new(raw, ipv4_header, transport_header),
            closed: false,
            idle_since: Instant::now(),
        }));

        {
            let rc_clone = rc.clone();
            let handler = move |selector: &mut Selector, ready| {
                let mut self_ref = rc_clone.borrow_mut();
                self_ref.on_ready(selector, ready);
            };
            let mut self_ref = rc.borrow_mut();
            let token = selector.register(&self_ref.socket, handler, Ready::readable(), PollOpt::level())?;
            self_ref.token = token;
        }
        Ok(rc)
    }

    fn create_socket(id: &ConnectionId) -> io::Result<UdpSocket> {
        let autobind_addr = SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 0);
        let udp_socket = UdpSocket::bind(&autobind_addr)?;
        let rewritten_destination = connection::rewritten_destination(id.destination_ip(), id.destination_port()).into();
        udp_socket.connect(rewritten_destination)?;
        Ok(udp_socket)
    }

    fn close(&mut self, selector: &mut Selector) {
        self.closed = true;
        self.disconnect(selector);

        // route is embedded in router which is embedded in client: the client necessarily exists
        let client_rc = self.client.upgrade().expect("expected client not found");
        let mut client = client_rc.borrow_mut();
        client.router().remove(&self.id);
    }

    fn process_send(&mut self, selector: &mut Selector) {
        if let Err(err) = self.write() {
            error!(target: TAG, "{} Cannot write: {}", self.id, err);
            self.close(selector);
        }
    }

    fn process_receive(&mut self, selector: &mut Selector) {
        if let Err(err) = self.read(selector) {
            error!(target: TAG, "{} Cannot read: {}", self.id, err);
            self.close(selector);
        }
    }

    fn read(&mut self, selector: &mut Selector) -> io::Result<()> {
        let ipv4_packet = self.network_to_client.packetize(&mut self.socket)?;
        let client_rc = self.client.upgrade().expect("expected client not found");
        match client_rc.borrow_mut().send_to_client(selector, &ipv4_packet) {
            Ok(_) => {
                debug!(target: TAG, "{} Packet ({} bytes) sent to client", self.id, ipv4_packet.length());
                if log_enabled!(target: TAG, LogLevel::Trace) {
                    binary::to_string(ipv4_packet.raw());
                }
            },
            Err(_) => warn!(target: TAG, "{} Cannot send to client, drop packet", self.id),
        }
        Ok(())
    }

    fn write(&mut self) -> io::Result<()> {
        self.client_to_network.write_to(&mut self.socket)?;
        Ok(())
    }

    fn update_interests(&mut self, selector: &mut Selector) {
        let mut ready = Ready::empty();
        if self.may_read() {
            ready = Ready::readable();
        }
        if self.may_write() {
            ready = ready | Ready::writable();
        }
        selector.reregister(&self.socket, self.token, ready, PollOpt::level()).expect("Cannot register on poll");
    }

    fn may_read(&self) -> bool {
        // TODO
        true
    }

    fn may_write(&self) -> bool {
        !self.client_to_network.is_empty()
    }

    fn on_ready(&mut self, selector: &mut Selector, event: Event) {
        assert!(!self.closed);
        self.touch();
        let ready = event.readiness();
        if ready.is_writable() {
            self.process_send(selector);
        }
        if !self.closed && ready.is_readable() {
            self.process_receive(selector);
        }
        if !self.closed {
            self.update_interests(selector);
        }
    }

    fn touch(&mut self) {
        self.idle_since = Instant::now();
    }
}

impl Connection for UDPConnection {
    fn id(&self) -> &ConnectionId {
        &self.id
    }

    fn send_to_network(&mut self, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        match self.client_to_network.read_from(ipv4_packet.payload()) {
            Ok(_) => {
                self.update_interests(selector);
            },
            Err(err) => warn!(target: TAG, "{} Cannot send to network, drop packet: {}", self.id, err),
        }
    }

    fn disconnect(&mut self, selector: &mut Selector) {
        info!(target: TAG, "{} Close", self.id);
        selector.deregister(&self.socket, self.token).unwrap();
        // socket will be closed by RAII
    }

    fn is_expired(&self) -> bool {
        self.idle_since.elapsed().as_secs() > IDLE_TIMEOUT_SECONDS
    }
}
<commit_msg>Improve UDPConnection.update_interests()<commit_after>use std::cell::RefCell;
use std::io;
use std::rc::{Rc, Weak};
use std::net::{Ipv4Addr, SocketAddr};
use std::time::Instant;
use log::LogLevel;
use mio::{Event, PollOpt, Ready, Token};
use mio::net::UdpSocket;

use super::binary;
use super::client::Client;
use super::connection::{self, Connection, ConnectionId};
use super::datagram_buffer::DatagramBuffer;
use super::ipv4_packet::{IPv4Packet, MAX_PACKET_LENGTH};
use super::packetizer::Packetizer;
use super::selector::Selector;

const TAG: &'static str = "UDPConnection";

pub const IDLE_TIMEOUT_SECONDS: u64 = 2 * 60;

pub struct UDPConnection {
    id: ConnectionId,
    client: Weak<RefCell<Client>>,
    socket: UdpSocket,
    token: Token,
    client_to_network: DatagramBuffer,
    network_to_client: Packetizer,
    closed: bool,
    idle_since: Instant,
}

impl UDPConnection {
    pub fn new(selector: &mut Selector, id: ConnectionId, client: Weak<RefCell<Client>>, reference_packet: &IPv4Packet) -> io::Result<Rc<RefCell<Self>>> {
        let socket = UDPConnection::create_socket(&id)?;
        let raw: &[u8] = reference_packet.raw();
        let ipv4_header = reference_packet.ipv4_header().clone();
        let transport_header = reference_packet.transport_header().as_ref().unwrap().clone();
        let rc = Rc::new(RefCell::new(Self {
            id: id,
            client: client,
            socket: socket,
            token: Token(0), // default value, will be set afterwards
            client_to_network: DatagramBuffer::new(4 * MAX_PACKET_LENGTH),
            network_to_client: Packetizer::new(raw, ipv4_header, transport_header),
            closed: false,
            idle_since: Instant::now(),
        }));

        {
            let rc_clone = rc.clone();
            let handler = move |selector: &mut Selector, ready| {
                let mut self_ref = rc_clone.borrow_mut();
                self_ref.on_ready(selector, ready);
            };
            let mut self_ref = rc.borrow_mut();
            let token = selector.register(&self_ref.socket, handler, Ready::readable(), PollOpt::level())?;
            self_ref.token = token;
        }
        Ok(rc)
    }

    fn create_socket(id: &ConnectionId) -> io::Result<UdpSocket> {
        let autobind_addr = SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 0);
        let udp_socket = UdpSocket::bind(&autobind_addr)?;
        let rewritten_destination = connection::rewritten_destination(id.destination_ip(), id.destination_port()).into();
        udp_socket.connect(rewritten_destination)?;
        Ok(udp_socket)
    }

    fn close(&mut self, selector: &mut Selector) {
        self.closed = true;
        self.disconnect(selector);

        // route is embedded in router which is embedded in client: the client necessarily exists
        let client_rc = self.client.upgrade().expect("expected client not found");
        let mut client = client_rc.borrow_mut();
        client.router().remove(&self.id);
    }

    fn process_send(&mut self, selector: &mut Selector) {
        if let Err(err) = self.write() {
            error!(target: TAG, "{} Cannot write: {}", self.id, err);
            self.close(selector);
        }
    }

    fn process_receive(&mut self, selector: &mut Selector) {
        if let Err(err) = self.read(selector) {
            error!(target: TAG, "{} Cannot read: {}", self.id, err);
            self.close(selector);
        }
    }

    fn read(&mut self, selector: &mut Selector) -> io::Result<()> {
        let ipv4_packet = self.network_to_client.packetize(&mut self.socket)?;
        let client_rc = self.client.upgrade().expect("expected client not found");
        match client_rc.borrow_mut().send_to_client(selector, &ipv4_packet) {
            Ok(_) => {
                debug!(target: TAG, "{} Packet ({} bytes) sent to client", self.id, ipv4_packet.length());
                if log_enabled!(target: TAG, LogLevel::Trace) {
                    binary::to_string(ipv4_packet.raw());
                }
            },
            Err(_) => warn!(target: TAG, "{} Cannot send to client, drop packet", self.id),
        }
        Ok(())
    }

    fn write(&mut self) -> io::Result<()> {
        self.client_to_network.write_to(&mut self.socket)?;
        Ok(())
    }

    fn update_interests(&mut self, selector: &mut Selector) {
        let ready = if self.client_to_network.is_empty() {
            Ready::readable()
        } else {
            Ready::readable() | Ready::writable()
        };
        selector.reregister(&self.socket, self.token, ready, PollOpt::level()).expect("Cannot register on poll");
    }

    fn on_ready(&mut self, selector: &mut Selector, event: Event) {
        assert!(!self.closed);
        self.touch();
        let ready = event.readiness();
        if ready.is_writable() {
            self.process_send(selector);
        }
        if !self.closed && ready.is_readable() {
            self.process_receive(selector);
        }
        if !self.closed {
            self.update_interests(selector);
        }
    }

    fn touch(&mut self) {
        self.idle_since = Instant::now();
    }
}

impl Connection for UDPConnection {
    fn id(&self) -> &ConnectionId {
        &self.id
    }

    fn send_to_network(&mut self, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        match self.client_to_network.read_from(ipv4_packet.payload()) {
            Ok(_) => {
                self.update_interests(selector);
            },
            Err(err) => warn!(target: TAG, "{} Cannot send to network, drop packet: {}", self.id, err),
        }
    }

    fn disconnect(&mut self, selector: &mut Selector) {
        info!(target: TAG, "{} Close", self.id);
        selector.deregister(&self.socket, self.token).unwrap();
        // socket will be closed by RAII
    }

    fn is_expired(&self) -> bool {
        self.idle_since.elapsed().as_secs() > IDLE_TIMEOUT_SECONDS
    }
}
<|endoftext|>


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

use target::{Target, TargetResult};

pub fn target() -> TargetResult {
    let mut base = super::fuchsia_base::opts();
    base.max_atomic_width = Some(128);

    Ok(Target {
        llvm_target: "aarch64-unknown-fuchsia".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "64".to_string(),
        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
        arch: "aarch64".to_string(),
        target_os: "fuchsia".to_string(),
        target_env: "".to_string(),
        target_vendor: "unknown".to_string(),
        options: base,
    })
}
<commit_msg>Auto merge of #37619 - TimNN:aarch64-fuchsia-abi-blacklist, r=alexcrichton<commit_after>// Copyright 2016 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.

use target::{Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    let mut base = super::fuchsia_base::opts();
    base.max_atomic_width = Some(128);

    Ok(Target {
        llvm_target: "aarch64-unknown-fuchsia".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "64".to_string(),
        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
        arch: "aarch64".to_string(),
        target_os: "fuchsia".to_string(),
        target_env: "".to_string(),
        target_vendor: "unknown".to_string(),
        options: TargetOptions {
            abi_blacklist: super::arm_base::abi_blacklist(),
            .. base
        },
    })
}
<|endoftext|>


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

use driver::session::Session;

use middle::save::generated_code;

use std::cell::Cell;

use syntax::ast;
use syntax::codemap::*;
use syntax::parse::lexer;
use syntax::parse::lexer::{Reader,StringReader};
use syntax::parse::token;
use syntax::parse::token::{keywords, Token};

pub struct SpanUtils<'a> {
    pub sess: &'a Session,
    pub err_count: Cell<int>,
}

impl<'a> SpanUtils<'a> {
    // Standard string for extents/location.
    pub fn extent_str(&self, span: Span) -> String {
        let lo_loc = self.sess.codemap().lookup_char_pos(span.lo);
        let hi_loc = self.sess.codemap().lookup_char_pos(span.hi);
        let lo_pos = self.sess.codemap().lookup_byte_offset(span.lo).pos;
        let hi_pos = self.sess.codemap().lookup_byte_offset(span.hi).pos;

        format!("file_name,{},file_line,{},file_col,{},extent_start,{},\
                 file_line_end,{},file_col_end,{},extent_end,{}",
                lo_loc.file.name, lo_loc.line, lo_loc.col.to_uint(), lo_pos.to_uint(),
                hi_loc.line, hi_loc.col.to_uint(), hi_pos.to_uint())
    }

    // sub_span starts at span.lo, so we need to adjust the positions etc.
    // If sub_span is None, we don't need to adjust.
    pub fn make_sub_span(&self, span: Span, sub_span: Option<Span>) -> Option<Span> {
        let loc = self.sess.codemap().lookup_char_pos(span.lo);
        assert!(!generated_code(span),
                "generated code; we should not be processing this `{}` in {}, line {}",
                 self.snippet(span), loc.file.name, loc.line);

        match sub_span {
            None => None,
            Some(sub) => {
                let FileMapAndBytePos {fm, pos} =
                    self.sess.codemap().lookup_byte_offset(span.lo);
                let base = pos + fm.start_pos;
                Some(Span {
                    lo: base + self.sess.codemap().lookup_byte_offset(sub.lo).pos,
                    hi: base + self.sess.codemap().lookup_byte_offset(sub.hi).pos,
                    expn_id: NO_EXPANSION,
                })
            }
        }
    }

    pub fn snippet(&self, span: Span) -> String {
        match self.sess.codemap().span_to_snippet(span) {
            Some(s) => s,
            None => String::new(),
        }
    }

    pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
        // sadness - we don't have spans for sub-expressions nor access to the tokens
        // so in order to get extents for the function name itself (which dxr expects)
        // we need to re-tokenise the fn definition

        // Note: this is a bit awful - it adds the contents of span to the end of
        // the codemap as a new filemap. This is mostly OK, but means we should
        // not iterate over the codemap. Also, any spans over the new filemap
        // are incompatible with spans over other filemaps.
        let filemap = self.sess.codemap().new_filemap(String::from_str("<anon-dxr>"),
                                                      self.snippet(span));
        let s = self.sess;
        lexer::StringReader::new(s.diagnostic(), filemap)
    }

    // Re-parses a path and returns the span for the last identifier in the path
    pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
        let mut result = None;

        let mut toks = self.retokenise_span(span);
        let mut bracket_count = 0u;
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return self.make_sub_span(span, result)
            }
            if bracket_count == 0 &&
               (ts.tok.is_ident() || ts.tok.is_keyword(keywords::Self)) {
                result = Some(ts.sp);
            }

            bracket_count += match ts.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0
            }
        }
    }

    // Return the span for the first identifier in the path.
    pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut bracket_count = 0u;
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return None;
            }
            if bracket_count == 0 &&
               (ts.tok.is_ident() || ts.tok.is_keyword(keywords::Self)) {
                return self.make_sub_span(span, Some(ts.sp));
            }

            bracket_count += match ts.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0
            }
        }
    }

    // Return the span for the last ident before a `(` or `<` or '::<' and outside any
    // any brackets, or the last span.
    pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut prev = toks.real_token();
        let mut result = None;
        let mut bracket_count = 0u;
        let mut last_span = None;
        while prev.tok != token::Eof {
            last_span = None;
            let mut next = toks.real_token();

            if (next.tok == token::OpenDelim(token::Paren) ||
                next.tok == token::Lt) &&
               bracket_count == 0 &&
               prev.tok.is_ident() {
                result = Some(prev.sp);
            }

            if bracket_count == 0 &&
                next.tok == token::ModSep {
                let old = prev;
                prev = next;
                next = toks.real_token();
                if next.tok == token::Lt &&
                   old.tok.is_ident() {
                    result = Some(old.sp);
                }
            }

            bracket_count += match prev.tok {
                token::OpenDelim(token::Paren) | token::Lt => 1,
                token::CloseDelim(token::Paren) | token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0
            };

            if prev.tok.is_ident() && bracket_count == 0 {
                last_span = Some(prev.sp);
            }
            prev = next;
        }
        if result.is_none() && last_span.is_some() {
            return self.make_sub_span(span, last_span);
        }
        return self.make_sub_span(span, result);
    }

    // Return the span for the last ident before a `<` and outside any
    // brackets, or the last span.
    pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut prev = toks.real_token();
        let mut result = None;
        let mut bracket_count = 0u;
        loop {
            let next = toks.real_token();

            if (next.tok == token::Lt ||
                next.tok == token::Colon) &&
               bracket_count == 0 &&
               prev.tok.is_ident() {
                result = Some(prev.sp);
            }

            bracket_count += match prev.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0
            };

            if next.tok == token::Eof {
                break;
            }
            prev = next;
        }
        if bracket_count != 0 {
            let loc = self.sess.codemap().lookup_char_pos(span.lo);
            self.sess.span_bug(span,
                format!("Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
                        self.snippet(span), loc.file.name, loc.line).as_slice());
        }
        if result.is_none() && prev.tok.is_ident() && bracket_count == 0 {
            return self.make_sub_span(span, Some(prev.sp));
        }
        self.make_sub_span(span, result)
    }

    // Reparse span and return an owned vector of sub spans of the first limit
    // identifier tokens in the given nesting level.
    // example with Foo<Bar<T,V>, Bar<T,V>>
    // Nesting = 0: all idents outside of brackets: ~[Foo]
    // Nesting = 1: idents within one level of brackets: ~[Bar, Bar]
    pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec<Span> {
        let mut result: Vec<Span> = vec!();

        let mut toks = self.retokenise_span(span);
        // We keep track of how many brackets we're nested in
        let mut bracket_count = 0i;
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                if bracket_count != 0 {
                    let loc = self.sess.codemap().lookup_char_pos(span.lo);
                    self.sess.span_bug(span, format!(
                        "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
                         self.snippet(span), loc.file.name, loc.line).as_slice());
                }
                return result
            }
            if (result.len() as int) == limit {
                return result;
            }
            bracket_count += match ts.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shl) => 2,
                token::BinOp(token::Shr) => -2,
                _ => 0
            };
            if ts.tok.is_ident() &&
               bracket_count == nesting {
                result.push(self.make_sub_span(span, Some(ts.sp)).unwrap());
            }
        }
    }

    pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut prev = toks.real_token();
        loop {
            if prev.tok == token::Eof {
                return None;
            }
            let next = toks.real_token();
            if next.tok == tok {
                return self.make_sub_span(span, Some(prev.sp));
            }
            prev = next;
        }
    }

    pub fn sub_span_after_keyword(&self,
                              span: Span,
                              keyword: keywords::Keyword) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return None;
            }
            if ts.tok.is_keyword(keyword) {
                let ts = toks.real_token();
                if ts.tok == token::Eof {
                    return None
                } else {
                    println!("found keyword: {} at {}", ts, ts.sp);
                    return self.make_sub_span(span, Some(ts.sp));
                }
            }
        }
    }

    // Returns a list of the spans of idents in a patch.
    // E.g., For foo::bar<x,t>::baz, we return [foo, bar, baz] (well, their spans)
    pub fn spans_for_path_segments(&self, path: &ast::Path) -> Vec<Span> {
        if generated_code(path.span) {
            return vec!();
        }

        self.spans_with_brackets(path.span, 0, -1)
    }

    // Return an owned vector of the subspans of the param identifier
    // tokens found in span.
    pub fn spans_for_ty_params(&self, span: Span, number: int) -> Vec<Span> {
        if generated_code(span) {
            return vec!();
        }
        // Type params are nested within one level of brackets:
        // i.e. we want ~[A, B] from Foo<A, B<T,U>>
        self.spans_with_brackets(span, 1, number)
    }

    pub fn report_span_err(&self, kind: &str, span: Span) {
        let loc = self.sess.codemap().lookup_char_pos(span.lo);
        info!("({}) Could not find sub_span in `{}` in {}, line {}",
              kind, self.snippet(span), loc.file.name, loc.line);
        self.err_count.set(self.err_count.get()+1);
        if self.err_count.get() > 1000 {
            self.sess.bug("span errors reached 1000, giving up");
        }
    }
}
<commit_msg>rollup merge of #18564 : nick29581/dxr-1a<commit_after>// Copyright 2012-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.

use driver::session::Session;

use middle::save::generated_code;

use std::cell::Cell;

use syntax::ast;
use syntax::codemap::*;
use syntax::parse::lexer;
use syntax::parse::lexer::{Reader,StringReader};
use syntax::parse::token;
use syntax::parse::token::{keywords, Token};

pub struct SpanUtils<'a> {
    pub sess: &'a Session,
    pub err_count: Cell<int>,
}

impl<'a> SpanUtils<'a> {
    // Standard string for extents/location.
    pub fn extent_str(&self, span: Span) -> String {
        let lo_loc = self.sess.codemap().lookup_char_pos(span.lo);
        let hi_loc = self.sess.codemap().lookup_char_pos(span.hi);
        let lo_pos = self.sess.codemap().bytepos_to_file_charpos(span.lo);
        let hi_pos = self.sess.codemap().bytepos_to_file_charpos(span.hi);
        let lo_pos_byte = self.sess.codemap().lookup_byte_offset(span.lo).pos;
        let hi_pos_byte = self.sess.codemap().lookup_byte_offset(span.hi).pos;

        format!("file_name,{},file_line,{},file_col,{},extent_start,{},extent_start_bytes,{},\
                 file_line_end,{},file_col_end,{},extent_end,{},extent_end_bytes,{}",
                lo_loc.file.name,
                lo_loc.line, lo_loc.col.to_uint(), lo_pos.to_uint(), lo_pos_byte.to_uint(),
                hi_loc.line, hi_loc.col.to_uint(), hi_pos.to_uint(), hi_pos_byte.to_uint())
    }

    // sub_span starts at span.lo, so we need to adjust the positions etc.
    // If sub_span is None, we don't need to adjust.
    pub fn make_sub_span(&self, span: Span, sub_span: Option<Span>) -> Option<Span> {
        let loc = self.sess.codemap().lookup_char_pos(span.lo);
        assert!(!generated_code(span),
                "generated code; we should not be processing this `{}` in {}, line {}",
                 self.snippet(span), loc.file.name, loc.line);

        match sub_span {
            None => None,
            Some(sub) => {
                let FileMapAndBytePos {fm, pos} =
                    self.sess.codemap().lookup_byte_offset(span.lo);
                let base = pos + fm.start_pos;
                Some(Span {
                    lo: base + self.sess.codemap().lookup_byte_offset(sub.lo).pos,
                    hi: base + self.sess.codemap().lookup_byte_offset(sub.hi).pos,
                    expn_id: NO_EXPANSION,
                })
            }
        }
    }

    pub fn snippet(&self, span: Span) -> String {
        match self.sess.codemap().span_to_snippet(span) {
            Some(s) => s,
            None => String::new(),
        }
    }

    pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
        // sadness - we don't have spans for sub-expressions nor access to the tokens
        // so in order to get extents for the function name itself (which dxr expects)
        // we need to re-tokenise the fn definition

        // Note: this is a bit awful - it adds the contents of span to the end of
        // the codemap as a new filemap. This is mostly OK, but means we should
        // not iterate over the codemap. Also, any spans over the new filemap
        // are incompatible with spans over other filemaps.
        let filemap = self.sess.codemap().new_filemap(String::from_str("<anon-dxr>"),
                                                      self.snippet(span));
        let s = self.sess;
        lexer::StringReader::new(s.diagnostic(), filemap)
    }

    // Re-parses a path and returns the span for the last identifier in the path
    pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
        let mut result = None;

        let mut toks = self.retokenise_span(span);
        let mut bracket_count = 0u;
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return self.make_sub_span(span, result)
            }
            if bracket_count == 0 &&
               (ts.tok.is_ident() || ts.tok.is_keyword(keywords::Self)) {
                result = Some(ts.sp);
            }

            bracket_count += match ts.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0
            }
        }
    }

    // Return the span for the first identifier in the path.
    pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut bracket_count = 0u;
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return None;
            }
            if bracket_count == 0 &&
               (ts.tok.is_ident() || ts.tok.is_keyword(keywords::Self)) {
                return self.make_sub_span(span, Some(ts.sp));
            }

            bracket_count += match ts.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0
            }
        }
    }

    // Return the span for the last ident before a `(` or `<` or '::<' and outside any
    // any brackets, or the last span.
    pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut prev = toks.real_token();
        let mut result = None;
        let mut bracket_count = 0u;
        let mut last_span = None;
        while prev.tok != token::Eof {
            last_span = None;
            let mut next = toks.real_token();

            if (next.tok == token::OpenDelim(token::Paren) ||
                next.tok == token::Lt) &&
               bracket_count == 0 &&
               prev.tok.is_ident() {
                result = Some(prev.sp);
            }

            if bracket_count == 0 &&
                next.tok == token::ModSep {
                let old = prev;
                prev = next;
                next = toks.real_token();
                if next.tok == token::Lt &&
                   old.tok.is_ident() {
                    result = Some(old.sp);
                }
            }

            bracket_count += match prev.tok {
                token::OpenDelim(token::Paren) | token::Lt => 1,
                token::CloseDelim(token::Paren) | token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0
            };

            if prev.tok.is_ident() && bracket_count == 0 {
                last_span = Some(prev.sp);
            }
            prev = next;
        }
        if result.is_none() && last_span.is_some() {
            return self.make_sub_span(span, last_span);
        }
        return self.make_sub_span(span, result);
    }

    // Return the span for the last ident before a `<` and outside any
    // brackets, or the last span.
    pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut prev = toks.real_token();
        let mut result = None;
        let mut bracket_count = 0u;
        loop {
            let next = toks.real_token();

            if (next.tok == token::Lt ||
                next.tok == token::Colon) &&
               bracket_count == 0 &&
               prev.tok.is_ident() {
                result = Some(prev.sp);
            }

            bracket_count += match prev.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0
            };

            if next.tok == token::Eof {
                break;
            }
            prev = next;
        }
        if bracket_count != 0 {
            let loc = self.sess.codemap().lookup_char_pos(span.lo);
            self.sess.span_bug(span,
                format!("Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
                        self.snippet(span), loc.file.name, loc.line).as_slice());
        }
        if result.is_none() && prev.tok.is_ident() && bracket_count == 0 {
            return self.make_sub_span(span, Some(prev.sp));
        }
        self.make_sub_span(span, result)
    }

    // Reparse span and return an owned vector of sub spans of the first limit
    // identifier tokens in the given nesting level.
    // example with Foo<Bar<T,V>, Bar<T,V>>
    // Nesting = 0: all idents outside of brackets: ~[Foo]
    // Nesting = 1: idents within one level of brackets: ~[Bar, Bar]
    pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec<Span> {
        let mut result: Vec<Span> = vec!();

        let mut toks = self.retokenise_span(span);
        // We keep track of how many brackets we're nested in
        let mut bracket_count = 0i;
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                if bracket_count != 0 {
                    let loc = self.sess.codemap().lookup_char_pos(span.lo);
                    self.sess.span_bug(span, format!(
                        "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
                         self.snippet(span), loc.file.name, loc.line).as_slice());
                }
                return result
            }
            if (result.len() as int) == limit {
                return result;
            }
            bracket_count += match ts.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shl) => 2,
                token::BinOp(token::Shr) => -2,
                _ => 0
            };
            if ts.tok.is_ident() &&
               bracket_count == nesting {
                result.push(self.make_sub_span(span, Some(ts.sp)).unwrap());
            }
        }
    }

    pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut prev = toks.real_token();
        loop {
            if prev.tok == token::Eof {
                return None;
            }
            let next = toks.real_token();
            if next.tok == tok {
                return self.make_sub_span(span, Some(prev.sp));
            }
            prev = next;
        }
    }

    pub fn sub_span_after_keyword(&self,
                              span: Span,
                              keyword: keywords::Keyword) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return None;
            }
            if ts.tok.is_keyword(keyword) {
                let ts = toks.real_token();
                if ts.tok == token::Eof {
                    return None
                } else {
                    println!("found keyword: {} at {}", ts, ts.sp);
                    return self.make_sub_span(span, Some(ts.sp));
                }
            }
        }
    }

    // Returns a list of the spans of idents in a patch.
    // E.g., For foo::bar<x,t>::baz, we return [foo, bar, baz] (well, their spans)
    pub fn spans_for_path_segments(&self, path: &ast::Path) -> Vec<Span> {
        if generated_code(path.span) {
            return vec!();
        }

        self.spans_with_brackets(path.span, 0, -1)
    }

    // Return an owned vector of the subspans of the param identifier
    // tokens found in span.
    pub fn spans_for_ty_params(&self, span: Span, number: int) -> Vec<Span> {
        if generated_code(span) {
            return vec!();
        }
        // Type params are nested within one level of brackets:
        // i.e. we want ~[A, B] from Foo<A, B<T,U>>
        self.spans_with_brackets(span, 1, number)
    }

    pub fn report_span_err(&self, kind: &str, span: Span) {
        let loc = self.sess.codemap().lookup_char_pos(span.lo);
        info!("({}) Could not find sub_span in `{}` in {}, line {}",
              kind, self.snippet(span), loc.file.name, loc.line);
        self.err_count.set(self.err_count.get()+1);
        if self.err_count.get() > 1000 {
            self.sess.bug("span errors reached 1000, giving up");
        }
    }
}
<|endoftext|>


<commit_before>//! A number of passes which remove various redundancies in the CFG.
//!
//! The `SimplifyCfg` pass gets rid of unnecessary blocks in the CFG, whereas the `SimplifyLocals`
//! gets rid of all the unnecessary local variable declarations.
//!
//! The `SimplifyLocals` pass is kinda expensive and therefore not very suitable to be run often.
//! Most of the passes should not care or be impacted in meaningful ways due to extra locals
//! either, so running the pass once, right before codegen, should suffice.
//!
//! On the other side of the spectrum, the `SimplifyCfg` pass is considerably cheap to run, thus
//! one should run it after every pass which may modify CFG in significant ways. This pass must
//! also be run before any analysis passes because it removes dead blocks, and some of these can be
//! ill-typed.
//!
//! The cause of this typing issue is typeck allowing most blocks whose end is not reachable have
//! an arbitrary return type, rather than having the usual () return type (as a note, typeck's
//! notion of reachability is in fact slightly weaker than MIR CFG reachability - see #31617). A
//! standard example of the situation is:
//!
//! ```rust
//!   fn example() {
//!       let _a: char = { return; };
//!   }
//! ```
//!
//! Here the block (`{ return; }`) has the return type `char`, rather than `()`, but the MIR we
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
//! return.

use crate::transform::{MirPass, MirSource};
use rustc::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc::mir::*;
use rustc::ty::{self, TyCtxt};
use rustc_index::bit_set::BitSet;
use rustc_index::vec::{Idx, IndexVec};
use std::borrow::Cow;

pub struct SimplifyCfg {
    label: String,
}

impl SimplifyCfg {
    pub fn new(label: &str) -> Self {
        SimplifyCfg { label: format!("SimplifyCfg-{}", label) }
    }
}

pub fn simplify_cfg(body: &mut BodyAndCache<'_>) {
    CfgSimplifier::new(body).simplify();
    remove_dead_blocks(body);

    // FIXME: Should probably be moved into some kind of pass manager
    body.basic_blocks_mut().raw.shrink_to_fit();
}

impl<'tcx> MirPass<'tcx> for SimplifyCfg {
    fn name(&self) -> Cow<'_, str> {
        Cow::Borrowed(&self.label)
    }

    fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body);
        simplify_cfg(body);
    }
}

pub struct CfgSimplifier<'a, 'tcx> {
    basic_blocks: &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
    pred_count: IndexVec<BasicBlock, u32>,
}

impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
    pub fn new(body: &'a mut BodyAndCache<'tcx>) -> Self {
        let mut pred_count = IndexVec::from_elem(0u32, body.basic_blocks());

        // we can't use mir.predecessors() here because that counts
        // dead blocks, which we don't want to.
        pred_count[START_BLOCK] = 1;

        for (_, data) in traversal::preorder(body) {
            if let Some(ref term) = data.terminator {
                for &tgt in term.successors() {
                    pred_count[tgt] += 1;
                }
            }
        }

        let basic_blocks = body.basic_blocks_mut();

        CfgSimplifier { basic_blocks, pred_count }
    }

    pub fn simplify(mut self) {
        self.strip_nops();

        let mut start = START_BLOCK;
        let mut new_stmts = vec![];

        loop {
            let mut changed = false;

            self.collapse_goto_chain(&mut start, &mut changed);

            for bb in self.basic_blocks.indices() {
                if self.pred_count[bb] == 0 {
                    continue;
                }

                debug!("simplifying {:?}", bb);

                let mut terminator =
                    self.basic_blocks[bb].terminator.take().expect("invalid terminator state");

                for successor in terminator.successors_mut() {
                    self.collapse_goto_chain(successor, &mut changed);
                }

                let mut inner_changed = true;
                while inner_changed {
                    inner_changed = false;
                    inner_changed |= self.simplify_branch(&mut terminator);
                    inner_changed |= self.merge_successor(&mut new_stmts, &mut terminator);
                    changed |= inner_changed;
                }

                let data = &mut self.basic_blocks[bb];
                data.statements.append(&mut new_stmts);
                data.terminator = Some(terminator);

                changed |= inner_changed;
            }

            if !changed {
                break;
            }
        }

        if start != START_BLOCK {
            debug_assert!(self.pred_count[START_BLOCK] == 0);
            self.basic_blocks.swap(START_BLOCK, start);
            self.pred_count.swap(START_BLOCK, start);

            // pred_count == 1 if the start block has no predecessor _blocks_.
            if self.pred_count[START_BLOCK] > 1 {
                for (bb, data) in self.basic_blocks.iter_enumerated_mut() {
                    if self.pred_count[bb] == 0 {
                        continue;
                    }

                    for target in data.terminator_mut().successors_mut() {
                        if *target == start {
                            *target = START_BLOCK;
                        }
                    }
                }
            }
        }
    }

    // Collapse a goto chain starting from `start`
    fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
        let mut terminator = match self.basic_blocks[*start] {
            BasicBlockData {
                ref statements,
                terminator:
                    ref mut terminator @ Some(Terminator { kind: TerminatorKind::Goto { .. }, .. }),
                ..
            } if statements.is_empty() => terminator.take(),
            // if `terminator` is None, this means we are in a loop. In that
            // case, let all the loop collapse to its entry.
            _ => return,
        };

        let target = match terminator {
            Some(Terminator { kind: TerminatorKind::Goto { ref mut target }, .. }) => {
                self.collapse_goto_chain(target, changed);
                *target
            }
            _ => unreachable!(),
        };
        self.basic_blocks[*start].terminator = terminator;

        debug!("collapsing goto chain from {:?} to {:?}", *start, target);

        *changed |= *start != target;

        if self.pred_count[*start] == 1 {
            // This is the last reference to *start, so the pred-count to
            // to target is moved into the current block.
            self.pred_count[*start] = 0;
        } else {
            self.pred_count[target] += 1;
            self.pred_count[*start] -= 1;
        }

        *start = target;
    }

    // merge a block with 1 `goto` predecessor to its parent
    fn merge_successor(
        &mut self,
        new_stmts: &mut Vec<Statement<'tcx>>,
        terminator: &mut Terminator<'tcx>,
    ) -> bool {
        let target = match terminator.kind {
            TerminatorKind::Goto { target } if self.pred_count[target] == 1 => target,
            _ => return false,
        };

        debug!("merging block {:?} into {:?}", target, terminator);
        *terminator = match self.basic_blocks[target].terminator.take() {
            Some(terminator) => terminator,
            None => {
                // unreachable loop - this should not be possible, as we
                // don't strand blocks, but handle it correctly.
                return false;
            }
        };
        new_stmts.extend(self.basic_blocks[target].statements.drain(..));
        self.pred_count[target] = 0;

        true
    }

    // turn a branch with all successors identical to a goto
    fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
        match terminator.kind {
            TerminatorKind::SwitchInt { .. } => {}
            _ => return false,
        };

        let first_succ = {
            if let Some(&first_succ) = terminator.successors().nth(0) {
                if terminator.successors().all(|s| *s == first_succ) {
                    let count = terminator.successors().count();
                    self.pred_count[first_succ] -= (count - 1) as u32;
                    first_succ
                } else {
                    return false;
                }
            } else {
                return false;
            }
        };

        debug!("simplifying branch {:?}", terminator);
        terminator.kind = TerminatorKind::Goto { target: first_succ };
        true
    }

    fn strip_nops(&mut self) {
        for blk in self.basic_blocks.iter_mut() {
            blk.statements
                .retain(|stmt| if let StatementKind::Nop = stmt.kind { false } else { true })
        }
    }
}

pub fn remove_dead_blocks(body: &mut BodyAndCache<'_>) {
    let mut seen = BitSet::new_empty(body.basic_blocks().len());
    for (bb, _) in traversal::preorder(body) {
        seen.insert(bb.index());
    }

    let basic_blocks = body.basic_blocks_mut();

    let num_blocks = basic_blocks.len();
    let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
    let mut used_blocks = 0;
    for alive_index in seen.iter() {
        replacements[alive_index] = BasicBlock::new(used_blocks);
        if alive_index != used_blocks {
            // Swap the next alive block data with the current available slot. Since
            // alive_index is non-decreasing this is a valid operation.
            basic_blocks.raw.swap(alive_index, used_blocks);
        }
        used_blocks += 1;
    }
    basic_blocks.raw.truncate(used_blocks);

    for block in basic_blocks {
        for target in block.terminator_mut().successors_mut() {
            *target = replacements[target.index()];
        }
    }
}

pub struct SimplifyLocals;

impl<'tcx> MirPass<'tcx> for SimplifyLocals {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
        trace!("running SimplifyLocals on {:?}", source);
        let locals = {
            let read_only_cache = read_only!(body);
            let mut marker = DeclMarker { locals: BitSet::new_empty(body.local_decls.len()), body };
            marker.visit_body(read_only_cache);
            // Return pointer and arguments are always live
            marker.locals.insert(RETURN_PLACE);
            for arg in body.args_iter() {
                marker.locals.insert(arg);
            }

            marker.locals
        };

        let map = make_local_map(&mut body.local_decls, locals);
        // Update references to all vars and tmps now
        LocalUpdater { map, tcx }.visit_body(body);
        body.local_decls.shrink_to_fit();
    }
}

/// Construct the mapping while swapping out unused stuff out from the `vec`.
fn make_local_map<V>(
    vec: &mut IndexVec<Local, V>,
    mask: BitSet<Local>,
) -> IndexVec<Local, Option<Local>> {
    let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, &*vec);
    let mut used = Local::new(0);
    for alive_index in mask.iter() {
        map[alive_index] = Some(used);
        if alive_index != used {
            vec.swap(alive_index, used);
        }
        used.increment_by(1);
    }
    vec.truncate(used.index());
    map
}

struct DeclMarker<'a, 'tcx> {
    pub locals: BitSet<Local>,
    pub body: &'a Body<'tcx>,
}

impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> {
    fn visit_local(&mut self, local: &Local, ctx: PlaceContext, location: Location) {
        // Ignore storage markers altogether, they get removed along with their otherwise unused
        // decls.
        // FIXME: Extend this to all non-uses.
        if ctx.is_storage_marker() {
            return;
        }

        // Ignore stores of constants because `ConstProp` and `CopyProp` can remove uses of many
        // of these locals. However, if the local is still needed, then it will be referenced in
        // another place and we'll mark it as being used there.
        if ctx == PlaceContext::MutatingUse(MutatingUseContext::Store)
            || ctx == PlaceContext::MutatingUse(MutatingUseContext::Projection)
        {
            let block = &self.body.basic_blocks()[location.block];
            if location.statement_index != block.statements.len() {
                let stmt = &block.statements[location.statement_index];

                if let StatementKind::Assign(box (p, Rvalue::Use(Operand::Constant(c)))) =
                    &stmt.kind
                {
                    match c.literal.val {
                        // Keep assignments from unevaluated constants around, since the evaluation
                        // may report errors, even if the use of the constant is dead code.
                        ty::ConstKind::Unevaluated(..) => {}
                        _ => {
                            if !p.is_indirect() {
                                trace!("skipping store of const value {:?} to {:?}", c, p);
                                return;
                            }
                        }
                    }
                }
            }
        }

        self.locals.insert(*local);
    }
}

struct LocalUpdater<'tcx> {
    map: IndexVec<Local, Option<Local>>,
    tcx: TyCtxt<'tcx>,
}

impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
        // Remove unnecessary StorageLive and StorageDead annotations.
        data.statements.retain(|stmt| match &stmt.kind {
            StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => self.map[*l].is_some(),
            StatementKind::Assign(box (place, _)) => self.map[place.local].is_some(),
            _ => true,
        });
        self.super_basic_block_data(block, data);
    }

    fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) {
        *l = self.map[*l].unwrap();
    }

    fn process_projection_elem(&mut self, elem: &PlaceElem<'tcx>) -> Option<PlaceElem<'tcx>> {
        match elem {
            PlaceElem::Index(local) => Some(PlaceElem::Index(self.map[*local].unwrap())),
            _ => None,
        }
    }
}
<commit_msg>Avoid an intermediate Vec in mir simplify<commit_after>//! A number of passes which remove various redundancies in the CFG.
//!
//! The `SimplifyCfg` pass gets rid of unnecessary blocks in the CFG, whereas the `SimplifyLocals`
//! gets rid of all the unnecessary local variable declarations.
//!
//! The `SimplifyLocals` pass is kinda expensive and therefore not very suitable to be run often.
//! Most of the passes should not care or be impacted in meaningful ways due to extra locals
//! either, so running the pass once, right before codegen, should suffice.
//!
//! On the other side of the spectrum, the `SimplifyCfg` pass is considerably cheap to run, thus
//! one should run it after every pass which may modify CFG in significant ways. This pass must
//! also be run before any analysis passes because it removes dead blocks, and some of these can be
//! ill-typed.
//!
//! The cause of this typing issue is typeck allowing most blocks whose end is not reachable have
//! an arbitrary return type, rather than having the usual () return type (as a note, typeck's
//! notion of reachability is in fact slightly weaker than MIR CFG reachability - see #31617). A
//! standard example of the situation is:
//!
//! ```rust
//!   fn example() {
//!       let _a: char = { return; };
//!   }
//! ```
//!
//! Here the block (`{ return; }`) has the return type `char`, rather than `()`, but the MIR we
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
//! return.

use crate::transform::{MirPass, MirSource};
use rustc::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc::mir::*;
use rustc::ty::{self, TyCtxt};
use rustc_index::bit_set::BitSet;
use rustc_index::vec::{Idx, IndexVec};
use std::borrow::Cow;

pub struct SimplifyCfg {
    label: String,
}

impl SimplifyCfg {
    pub fn new(label: &str) -> Self {
        SimplifyCfg { label: format!("SimplifyCfg-{}", label) }
    }
}

pub fn simplify_cfg(body: &mut BodyAndCache<'_>) {
    CfgSimplifier::new(body).simplify();
    remove_dead_blocks(body);

    // FIXME: Should probably be moved into some kind of pass manager
    body.basic_blocks_mut().raw.shrink_to_fit();
}

impl<'tcx> MirPass<'tcx> for SimplifyCfg {
    fn name(&self) -> Cow<'_, str> {
        Cow::Borrowed(&self.label)
    }

    fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body);
        simplify_cfg(body);
    }
}

pub struct CfgSimplifier<'a, 'tcx> {
    basic_blocks: &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
    pred_count: IndexVec<BasicBlock, u32>,
}

impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
    pub fn new(body: &'a mut BodyAndCache<'tcx>) -> Self {
        let mut pred_count = IndexVec::from_elem(0u32, body.basic_blocks());

        // we can't use mir.predecessors() here because that counts
        // dead blocks, which we don't want to.
        pred_count[START_BLOCK] = 1;

        for (_, data) in traversal::preorder(body) {
            if let Some(ref term) = data.terminator {
                for &tgt in term.successors() {
                    pred_count[tgt] += 1;
                }
            }
        }

        let basic_blocks = body.basic_blocks_mut();

        CfgSimplifier { basic_blocks, pred_count }
    }

    pub fn simplify(mut self) {
        self.strip_nops();

        let mut start = START_BLOCK;

        loop {
            let mut changed = false;

            self.collapse_goto_chain(&mut start, &mut changed);

            for bb in self.basic_blocks.indices() {
                if self.pred_count[bb] == 0 {
                    continue;
                }

                debug!("simplifying {:?}", bb);

                let mut terminator =
                    self.basic_blocks[bb].terminator.take().expect("invalid terminator state");

                for successor in terminator.successors_mut() {
                    self.collapse_goto_chain(successor, &mut changed);
                }

                let mut inner_changed = true;
                while inner_changed {
                    inner_changed = false;
                    inner_changed |= self.simplify_branch(&mut terminator);
                    inner_changed |= self.merge_successor(bb, &mut terminator);
                    changed |= inner_changed;
                }

                self.basic_blocks[bb].terminator = Some(terminator);

                changed |= inner_changed;
            }

            if !changed {
                break;
            }
        }

        if start != START_BLOCK {
            debug_assert!(self.pred_count[START_BLOCK] == 0);
            self.basic_blocks.swap(START_BLOCK, start);
            self.pred_count.swap(START_BLOCK, start);

            // pred_count == 1 if the start block has no predecessor _blocks_.
            if self.pred_count[START_BLOCK] > 1 {
                for (bb, data) in self.basic_blocks.iter_enumerated_mut() {
                    if self.pred_count[bb] == 0 {
                        continue;
                    }

                    for target in data.terminator_mut().successors_mut() {
                        if *target == start {
                            *target = START_BLOCK;
                        }
                    }
                }
            }
        }
    }

    // Collapse a goto chain starting from `start`
    fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
        let mut terminator = match self.basic_blocks[*start] {
            BasicBlockData {
                ref statements,
                terminator:
                    ref mut terminator @ Some(Terminator { kind: TerminatorKind::Goto { .. }, .. }),
                ..
            } if statements.is_empty() => terminator.take(),
            // if `terminator` is None, this means we are in a loop. In that
            // case, let all the loop collapse to its entry.
            _ => return,
        };

        let target = match terminator {
            Some(Terminator { kind: TerminatorKind::Goto { ref mut target }, .. }) => {
                self.collapse_goto_chain(target, changed);
                *target
            }
            _ => unreachable!(),
        };
        self.basic_blocks[*start].terminator = terminator;

        debug!("collapsing goto chain from {:?} to {:?}", *start, target);

        *changed |= *start != target;

        if self.pred_count[*start] == 1 {
            // This is the last reference to *start, so the pred-count to
            // to target is moved into the current block.
            self.pred_count[*start] = 0;
        } else {
            self.pred_count[target] += 1;
            self.pred_count[*start] -= 1;
        }

        *start = target;
    }

    // merge a block with 1 `goto` predecessor to its parent
    fn merge_successor(
        &mut self,
        merge_into: BasicBlock,
        terminator: &mut Terminator<'tcx>,
    ) -> bool {
        let target = match terminator.kind {
            TerminatorKind::Goto { target } if self.pred_count[target] == 1 => target,
            _ => return false,
        };

        debug!("merging block {:?} into {:?}", target, terminator);
        *terminator = match self.basic_blocks[target].terminator.take() {
            Some(terminator) => terminator,
            None => {
                // unreachable loop - this should not be possible, as we
                // don't strand blocks, but handle it correctly.
                return false;
            }
        };

        let (from, to) = self.basic_blocks.pick2_mut(target, merge_into);
        to.statements.append(&mut from.statements);
        self.pred_count[target] = 0;

        true
    }

    // turn a branch with all successors identical to a goto
    fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
        match terminator.kind {
            TerminatorKind::SwitchInt { .. } => {}
            _ => return false,
        };

        let first_succ = {
            if let Some(&first_succ) = terminator.successors().nth(0) {
                if terminator.successors().all(|s| *s == first_succ) {
                    let count = terminator.successors().count();
                    self.pred_count[first_succ] -= (count - 1) as u32;
                    first_succ
                } else {
                    return false;
                }
            } else {
                return false;
            }
        };

        debug!("simplifying branch {:?}", terminator);
        terminator.kind = TerminatorKind::Goto { target: first_succ };
        true
    }

    fn strip_nops(&mut self) {
        for blk in self.basic_blocks.iter_mut() {
            blk.statements
                .retain(|stmt| if let StatementKind::Nop = stmt.kind { false } else { true })
        }
    }
}

pub fn remove_dead_blocks(body: &mut BodyAndCache<'_>) {
    let mut seen = BitSet::new_empty(body.basic_blocks().len());
    for (bb, _) in traversal::preorder(body) {
        seen.insert(bb.index());
    }

    let basic_blocks = body.basic_blocks_mut();

    let num_blocks = basic_blocks.len();
    let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
    let mut used_blocks = 0;
    for alive_index in seen.iter() {
        replacements[alive_index] = BasicBlock::new(used_blocks);
        if alive_index != used_blocks {
            // Swap the next alive block data with the current available slot. Since
            // alive_index is non-decreasing this is a valid operation.
            basic_blocks.raw.swap(alive_index, used_blocks);
        }
        used_blocks += 1;
    }
    basic_blocks.raw.truncate(used_blocks);

    for block in basic_blocks {
        for target in block.terminator_mut().successors_mut() {
            *target = replacements[target.index()];
        }
    }
}

pub struct SimplifyLocals;

impl<'tcx> MirPass<'tcx> for SimplifyLocals {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
        trace!("running SimplifyLocals on {:?}", source);
        let locals = {
            let read_only_cache = read_only!(body);
            let mut marker = DeclMarker { locals: BitSet::new_empty(body.local_decls.len()), body };
            marker.visit_body(read_only_cache);
            // Return pointer and arguments are always live
            marker.locals.insert(RETURN_PLACE);
            for arg in body.args_iter() {
                marker.locals.insert(arg);
            }

            marker.locals
        };

        let map = make_local_map(&mut body.local_decls, locals);
        // Update references to all vars and tmps now
        LocalUpdater { map, tcx }.visit_body(body);
        body.local_decls.shrink_to_fit();
    }
}

/// Construct the mapping while swapping out unused stuff out from the `vec`.
fn make_local_map<V>(
    vec: &mut IndexVec<Local, V>,
    mask: BitSet<Local>,
) -> IndexVec<Local, Option<Local>> {
    let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, &*vec);
    let mut used = Local::new(0);
    for alive_index in mask.iter() {
        map[alive_index] = Some(used);
        if alive_index != used {
            vec.swap(alive_index, used);
        }
        used.increment_by(1);
    }
    vec.truncate(used.index());
    map
}

struct DeclMarker<'a, 'tcx> {
    pub locals: BitSet<Local>,
    pub body: &'a Body<'tcx>,
}

impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> {
    fn visit_local(&mut self, local: &Local, ctx: PlaceContext, location: Location) {
        // Ignore storage markers altogether, they get removed along with their otherwise unused
        // decls.
        // FIXME: Extend this to all non-uses.
        if ctx.is_storage_marker() {
            return;
        }

        // Ignore stores of constants because `ConstProp` and `CopyProp` can remove uses of many
        // of these locals. However, if the local is still needed, then it will be referenced in
        // another place and we'll mark it as being used there.
        if ctx == PlaceContext::MutatingUse(MutatingUseContext::Store)
            || ctx == PlaceContext::MutatingUse(MutatingUseContext::Projection)
        {
            let block = &self.body.basic_blocks()[location.block];
            if location.statement_index != block.statements.len() {
                let stmt = &block.statements[location.statement_index];

                if let StatementKind::Assign(box (p, Rvalue::Use(Operand::Constant(c)))) =
                    &stmt.kind
                {
                    match c.literal.val {
                        // Keep assignments from unevaluated constants around, since the evaluation
                        // may report errors, even if the use of the constant is dead code.
                        ty::ConstKind::Unevaluated(..) => {}
                        _ => {
                            if !p.is_indirect() {
                                trace!("skipping store of const value {:?} to {:?}", c, p);
                                return;
                            }
                        }
                    }
                }
            }
        }

        self.locals.insert(*local);
    }
}

struct LocalUpdater<'tcx> {
    map: IndexVec<Local, Option<Local>>,
    tcx: TyCtxt<'tcx>,
}

impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
        // Remove unnecessary StorageLive and StorageDead annotations.
        data.statements.retain(|stmt| match &stmt.kind {
            StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => self.map[*l].is_some(),
            StatementKind::Assign(box (place, _)) => self.map[place.local].is_some(),
            _ => true,
        });
        self.super_basic_block_data(block, data);
    }

    fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) {
        *l = self.map[*l].unwrap();
    }

    fn process_projection_elem(&mut self, elem: &PlaceElem<'tcx>) -> Option<PlaceElem<'tcx>> {
        match elem {
            PlaceElem::Index(local) => Some(PlaceElem::Index(self.map[*local].unwrap())),
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>// arc1.rs
// Make this code compile by filling in a value for `shared_numbers` where the
// TODO comment is and creating an initial binding for `child_numbers`
// somewhere. Try not to create any copies of the `numbers` Vec!
// Execute `rustlings help arc1` for hints :)

// I AM NOT DONE

use std::sync::Arc;
use std::thread;

fn main() {
    let numbers: Vec<_> = (0..100u32).collect();
    let shared_numbers = // TODO
    let mut joinhandles = Vec::new();

    for offset in 0..8 {
        joinhandles.push(thread::spawn(move || {
            let mut i = offset;
            let mut sum = 0;
            while i < child_numbers.len() {
                sum += child_numbers[i];
                i += 5;
            }
            println!("Sum of offset {} is {}", offset, sum);
        }));
    }
    for handle in joinhandles.into_iter() {
        handle.join().unwrap();
    }
}
<commit_msg>fix(arc1): Fix some words in the comment<commit_after>// arc1.rs
// Make this code compile by filling in a value for `shared_numbers` where the
// TODO comment is and create an initial binding for `child_numbers`
// somewhere. Try not to create any copies of the `numbers` Vec!
// Execute `rustlings hint arc1` for hints :)

// I AM NOT DONE

use std::sync::Arc;
use std::thread;

fn main() {
    let numbers: Vec<_> = (0..100u32).collect();
    let shared_numbers = // TODO
    let mut joinhandles = Vec::new();

    for offset in 0..8 {
        joinhandles.push(thread::spawn(move || {
            let mut i = offset;
            let mut sum = 0;
            while i < child_numbers.len() {
                sum += child_numbers[i];
                i += 5;
            }
            println!("Sum of offset {} is {}", offset, sum);
        }));
    }
    for handle in joinhandles.into_iter() {
        handle.join().unwrap();
    }
}
<|endoftext|>


<commit_before>use std::io::Cursor;
use std::io::{Read, Write};

use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};
use db::row::Row;

// mis info about what's on each page.
const HEADER_SIZE_IN_BYTES : usize = 32;
pub const PAGE_SIZE : usize = 4096;

pub struct Page {
    header: Header,
//    data: [u8; PAGE_SIZE - HEADER_SIZE_IN_BYTES],
    data: Vec<u8>,
    bytes_used: usize, // tracking where we are in the current page

                                      // if we go past the page boundary on a write we fault
}

#[derive(Debug)]
pub enum PageError {
    Full,
    NotFound,
}

pub type PageResult<T> = Result<T, PageError>;

struct Header {
    first_id: u64,
    last_id: u64
}

impl Header {
    fn as_vec(&self) -> Vec<u8> {
        let mut result = Vec::with_capacity(HEADER_SIZE_IN_BYTES);
//        result.resize(HEADER_SIZE_IN_BYTES, 0);
        result.write_u64::<BigEndian>(self.first_id);
        result.write_u64::<BigEndian>(self.last_id);
        result
    }
}

impl Header {
    fn new() -> Header {
        Header{first_id: 0, last_id: 0}
    }
    fn from_bytes(bytes: &[u8]) -> Header {
        let mut cur = Cursor::new(bytes);
        let first_id = cur.read_u64::<BigEndian>().unwrap();
        let last_id = cur.read_u64::<BigEndian>().unwrap();
        Header{first_id: first_id, last_id: last_id}
    }
}

// page deals with bytes, and has zero knowledge of a Row
// storage engine needs to serialize
impl Page {
    pub fn new() -> Page {
        let tmp: [u8; PAGE_SIZE - HEADER_SIZE_IN_BYTES];

        Page{header: Header::new(),
             data: Vec::with_capacity(PAGE_SIZE),
             bytes_used: 0,
             }
    }

    // attempt to write to a page
    // can fail if the page is already full
    // if it fails, the storage engine will have to flush this page
    // then allocate a new page
    pub fn write(&mut self, bytes: &[u8]) -> PageResult<()> {
        if bytes.len() > self.space_available() {
            return Err(PageError::Full)
        }
        // we need the length of the row
        let len = bytes.len() as u16;
        self.data.write_u16::<BigEndian>(len);
        self.data.write(bytes);

        self.bytes_used += 2 + len as usize;

        // TODO: update indexes
        Ok(())
    }

    // internal call, try to write instead since it holds a mutable ref
    fn space_available(&self) -> usize {
        PAGE_SIZE - HEADER_SIZE_IN_BYTES - self.bytes_used
    }

    // returns PAGE_SIZE bytes
    pub fn to_bytes(&self) -> Vec<u8> {
        let mut result = Vec::with_capacity(PAGE_SIZE);
        // get the header
        let header = self.header.as_vec();
        result.extend(header);
        result.extend(&self.data);
        result.resize(PAGE_SIZE, 0);
        result
    }
    pub fn from_bytes(bytes: Vec<u8>) -> PageResult<Page> {
        let p = Page{header: Header::new(),
                     bytes_used: 0,
                     data: bytes};
        Ok(p)
    }

}

#[cfg(test)]
mod tests {
    use super::{Page, HEADER_SIZE_IN_BYTES, PAGE_SIZE};
    #[test]
    fn test_page_insert_ok() {
        let mut p = Page::new();

        assert_eq!(p.space_available(), PAGE_SIZE - HEADER_SIZE_IN_BYTES);
        assert_eq!(p.bytes_used, 0);

        let data: [u8; 16] = [0; 16];
        p.write(&data).expect("Data written");
        // 2 extra bytes from the size
        assert_eq!(p.bytes_used, 18);

        let result = p.to_bytes();
        assert_eq!(result.len(), PAGE_SIZE);
    }

    #[test]
    #[should_panic]
    fn test_page_fault() {
        let mut p = Page::new();
        let data: [u8; 5000] = [0; 5000];
        p.write(&data).expect("Failure is expected");
    }
}

<commit_msg>removed page header<commit_after>use std::io::Cursor;
use std::io::{Read, Write};

use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};
use db::row::Row;

// mis info about what's on each page.
const HEADER_SIZE_IN_BYTES : usize = 32;
pub const PAGE_SIZE : usize = 4096;

pub struct Page {
//    data: [u8; PAGE_SIZE - HEADER_SIZE_IN_BYTES],
    data: Vec<u8>,
    bytes_used: usize, // tracking where we are in the current page

                                      // if we go past the page boundary on a write we fault
}

#[derive(Debug)]
pub enum PageError {
    Full,
    NotFound,
}

pub type PageResult<T> = Result<T, PageError>;

// page deals with bytes, and has zero knowledge of a Row
// storage engine needs to serialize
impl Page {
    pub fn new() -> Page {
        let tmp: [u8; PAGE_SIZE - HEADER_SIZE_IN_BYTES];

        Page{data: Vec::with_capacity(PAGE_SIZE),
             bytes_used: 0,
             }
    }

    // attempt to write to a page
    // can fail if the page is already full
    // if it fails, the storage engine will have to flush this page
    // then allocate a new page
    pub fn write(&mut self, bytes: &[u8]) -> PageResult<()> {
        if bytes.len() > self.space_available() {
            return Err(PageError::Full)
        }
        // we need the length of the row
        let len = bytes.len() as u16;
        self.data.write_u16::<BigEndian>(len);
        self.data.write(bytes);

        self.bytes_used += 2 + len as usize;

        // TODO: update indexes
        Ok(())
    }

    // internal call, try to write instead since it holds a mutable ref
    fn space_available(&self) -> usize {
        PAGE_SIZE - HEADER_SIZE_IN_BYTES - self.bytes_used
    }

    // returns PAGE_SIZE bytes
    pub fn to_bytes(&self) -> Vec<u8> {
        let mut result = Vec::with_capacity(PAGE_SIZE);
        // get the header
        result.extend(&self.data);
        result.resize(PAGE_SIZE, 0);
        result
    }
    pub fn from_bytes(bytes: Vec<u8>) -> PageResult<Page> {
        let p = Page{bytes_used: 0,
                     data: bytes};
        Ok(p)
    }

}

#[cfg(test)]
mod tests {
    use super::{Page, HEADER_SIZE_IN_BYTES, PAGE_SIZE};
    #[test]
    fn test_page_insert_ok() {
        let mut p = Page::new();

        assert_eq!(p.space_available(), PAGE_SIZE - HEADER_SIZE_IN_BYTES);
        assert_eq!(p.bytes_used, 0);

        let data: [u8; 16] = [0; 16];
        p.write(&data).expect("Data written");
        // 2 extra bytes from the size
        assert_eq!(p.bytes_used, 18);

        let result = p.to_bytes();
        assert_eq!(result.len(), PAGE_SIZE);
    }

    #[test]
    #[should_panic]
    fn test_page_fault() {
        let mut p = Page::new();
        let data: [u8; 5000] = [0; 5000];
        p.write(&data).expect("Failure is expected");
    }
}

<|endoftext|>