From 3bd7efadae490bcf3434719dc97e649f93645901 Mon Sep 17 00:00:00 2001 From: Irina Popa Date: Thu, 28 Dec 2017 19:07:02 +0200 Subject: [PATCH] rustc_target: move in type definitions from rustc_trans::abi. --- src/Cargo.lock | 3 +- src/librustc_target/Cargo.toml | 4 +- src/librustc_target/abi/call.rs | 214 ++++++++++++++++++++++++++++++ src/librustc_target/abi/mod.rs | 2 + src/librustc_target/lib.rs | 3 +- src/librustc_trans/Cargo.toml | 1 - src/librustc_trans/abi.rs | 223 +++----------------------------- src/librustc_trans/intrinsic.rs | 2 +- src/librustc_trans/lib.rs | 2 - src/librustc_trans/mir/block.rs | 2 +- 10 files changed, 243 insertions(+), 213 deletions(-) create mode 100644 src/librustc_target/abi/call.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index cc21e394e1d..878212d4ee4 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2115,8 +2115,8 @@ dependencies = [ name = "rustc_target" version = "0.0.0" dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "syntax 0.0.0", ] @@ -2138,7 +2138,6 @@ dependencies = [ name = "rustc_trans" version = "0.0.0" dependencies = [ - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/librustc_target/Cargo.toml b/src/librustc_target/Cargo.toml index 54c13258ef2..4064cb17f01 100644 --- a/src/librustc_target/Cargo.toml +++ b/src/librustc_target/Cargo.toml @@ -9,10 +9,10 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] +bitflags = "1.0" +log = "0.4" syntax = { path = "../libsyntax" } serialize = { path = "../libserialize" } -log = "0.4" -rand = "0.4" [features] jemalloc = [] diff --git a/src/librustc_target/abi/call.rs b/src/librustc_target/abi/call.rs new file mode 100644 index 00000000000..bea705b9ece --- /dev/null +++ b/src/librustc_target/abi/call.rs @@ -0,0 +1,214 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use abi::{Align, HasDataLayout, Size}; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum PassMode { + /// Ignore the argument (useful for empty struct). + Ignore, + /// Pass the argument directly. + Direct(ArgAttributes), + /// Pass a pair's elements directly in two arguments. + Pair(ArgAttributes, ArgAttributes), + /// Pass the argument after casting it, to either + /// a single uniform or a pair of registers. + Cast(CastTarget), + /// Pass the argument indirectly via a hidden pointer. + Indirect(ArgAttributes), +} + +// Hack to disable non_upper_case_globals only for the bitflags! and not for the rest +// of this module +pub use self::attr_impl::ArgAttribute; + +#[allow(non_upper_case_globals)] +#[allow(unused)] +mod attr_impl { + // The subset of llvm::Attribute needed for arguments, packed into a bitfield. + bitflags! { + #[derive(Default)] + pub struct ArgAttribute: u16 { + const ByVal = 1 << 0; + const NoAlias = 1 << 1; + const NoCapture = 1 << 2; + const NonNull = 1 << 3; + const ReadOnly = 1 << 4; + const SExt = 1 << 5; + const StructRet = 1 << 6; + const ZExt = 1 << 7; + const InReg = 1 << 8; + } + } +} + +/// A compact representation of LLVM attributes (at least those relevant for this module) +/// that can be manipulated without interacting with LLVM's Attribute machinery. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct ArgAttributes { + pub regular: ArgAttribute, + pub pointee_size: Size, + pub pointee_align: Option +} + +impl ArgAttributes { + pub fn new() -> Self { + ArgAttributes { + regular: ArgAttribute::default(), + pointee_size: Size::from_bytes(0), + pointee_align: None, + } + } + + pub fn set(&mut self, attr: ArgAttribute) -> &mut Self { + self.regular = self.regular | attr; + self + } + + pub fn contains(&self, attr: ArgAttribute) -> bool { + self.regular.contains(attr) + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum RegKind { + Integer, + Float, + Vector +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct Reg { + pub kind: RegKind, + pub size: Size, +} + +macro_rules! reg_ctor { + ($name:ident, $kind:ident, $bits:expr) => { + pub fn $name() -> Reg { + Reg { + kind: RegKind::$kind, + size: Size::from_bits($bits) + } + } + } +} + +impl Reg { + reg_ctor!(i8, Integer, 8); + reg_ctor!(i16, Integer, 16); + reg_ctor!(i32, Integer, 32); + reg_ctor!(i64, Integer, 64); + + reg_ctor!(f32, Float, 32); + reg_ctor!(f64, Float, 64); +} + +impl Reg { + pub fn align(&self, cx: C) -> Align { + let dl = cx.data_layout(); + match self.kind { + RegKind::Integer => { + match self.size.bits() { + 1 => dl.i1_align, + 2...8 => dl.i8_align, + 9...16 => dl.i16_align, + 17...32 => dl.i32_align, + 33...64 => dl.i64_align, + 65...128 => dl.i128_align, + _ => panic!("unsupported integer: {:?}", self) + } + } + RegKind::Float => { + match self.size.bits() { + 32 => dl.f32_align, + 64 => dl.f64_align, + _ => panic!("unsupported float: {:?}", self) + } + } + RegKind::Vector => dl.vector_align(self.size) + } + } +} + +/// An argument passed entirely registers with the +/// same kind (e.g. HFA / HVA on PPC64 and AArch64). +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct Uniform { + pub unit: Reg, + + /// The total size of the argument, which can be: + /// * equal to `unit.size` (one scalar/vector) + /// * a multiple of `unit.size` (an array of scalar/vectors) + /// * if `unit.kind` is `Integer`, the last element + /// can be shorter, i.e. `{ i64, i64, i32 }` for + /// 64-bit integers with a total size of 20 bytes + pub total: Size, +} + +impl From for Uniform { + fn from(unit: Reg) -> Uniform { + Uniform { + unit, + total: unit.size + } + } +} + +impl Uniform { + pub fn align(&self, cx: C) -> Align { + self.unit.align(cx) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct CastTarget { + pub prefix: [Option; 8], + pub prefix_chunk: Size, + pub rest: Uniform, +} + +impl From for CastTarget { + fn from(unit: Reg) -> CastTarget { + CastTarget::from(Uniform::from(unit)) + } +} + +impl From for CastTarget { + fn from(uniform: Uniform) -> CastTarget { + CastTarget { + prefix: [None; 8], + prefix_chunk: Size::from_bytes(0), + rest: uniform + } + } +} + +impl CastTarget { + pub fn pair(a: Reg, b: Reg) -> CastTarget { + CastTarget { + prefix: [Some(a.kind), None, None, None, None, None, None, None], + prefix_chunk: a.size, + rest: Uniform::from(b) + } + } + + pub fn size(&self, cx: C) -> Size { + (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64) + .abi_align(self.rest.align(cx)) + self.rest.total + } + + pub fn align(&self, cx: C) -> Align { + self.prefix.iter() + .filter_map(|x| x.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.align(cx))) + .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)), + |acc, align| acc.max(align)) + } +} \ No newline at end of file diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index e2f9737d878..8cdc34db2df 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -16,6 +16,8 @@ use spec::Target; use std::cmp; use std::ops::{Add, Sub, Mul, AddAssign, RangeInclusive}; +pub mod call; + /// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout) /// for a target, which contains everything needed to compute layouts. pub struct TargetDataLayout { diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index a98685f9274..c2418a3b2a7 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -31,8 +31,9 @@ #![feature(inclusive_range)] #![feature(slice_patterns)] +#[macro_use] +extern crate bitflags; extern crate syntax; -extern crate rand; extern crate serialize; #[macro_use] extern crate log; diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 26d1d2e2c86..32432d6cc83 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -10,7 +10,6 @@ crate-type = ["dylib"] test = false [dependencies] -bitflags = "1.0" cc = "1.0.1" flate2 = "1.0" jobserver = "0.1.5" diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 19ae1fa0478..f19fc074416 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -37,53 +37,14 @@ use type_::Type; use type_of::{LayoutLlvmExt, PointerKind}; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Align, Size, TyLayout}; -use rustc::ty::layout::{HasDataLayout, LayoutOf}; +use rustc::ty::layout::{self, LayoutOf, Size, TyLayout}; use libc::c_uint; use std::cmp; pub use syntax::abi::Abi; pub use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum PassMode { - /// Ignore the argument (useful for empty struct). - Ignore, - /// Pass the argument directly. - Direct(ArgAttributes), - /// Pass a pair's elements directly in two arguments. - Pair(ArgAttributes, ArgAttributes), - /// Pass the argument after casting it, to either - /// a single uniform or a pair of registers. - Cast(CastTarget), - /// Pass the argument indirectly via a hidden pointer. - Indirect(ArgAttributes), -} - -// Hack to disable non_upper_case_globals only for the bitflags! and not for the rest -// of this module -pub use self::attr_impl::ArgAttribute; - -#[allow(non_upper_case_globals)] -#[allow(unused)] -mod attr_impl { - // The subset of llvm::Attribute needed for arguments, packed into a bitfield. - bitflags! { - #[derive(Default)] - pub struct ArgAttribute: u16 { - const ByVal = 1 << 0; - const NoAlias = 1 << 1; - const NoCapture = 1 << 2; - const NonNull = 1 << 3; - const ReadOnly = 1 << 4; - const SExt = 1 << 5; - const StructRet = 1 << 6; - const ZExt = 1 << 7; - const InReg = 1 << 8; - } - } -} +pub use rustc_target::abi::call::*; macro_rules! for_each_kind { ($flags: ident, $f: ident, $($kind: ident),+) => ({ @@ -91,41 +52,24 @@ macro_rules! for_each_kind { }) } -impl ArgAttribute { +trait ArgAttributeExt { + fn for_each_kind(&self, f: F) where F: FnMut(llvm::Attribute); +} + +impl ArgAttributeExt for ArgAttribute { fn for_each_kind(&self, mut f: F) where F: FnMut(llvm::Attribute) { for_each_kind!(self, f, ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg) } } -/// A compact representation of LLVM attributes (at least those relevant for this module) -/// that can be manipulated without interacting with LLVM's Attribute machinery. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct ArgAttributes { - regular: ArgAttribute, - pointee_size: Size, - pointee_align: Option +pub trait ArgAttributesExt { + fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef); + fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef); } -impl ArgAttributes { - fn new() -> Self { - ArgAttributes { - regular: ArgAttribute::default(), - pointee_size: Size::from_bytes(0), - pointee_align: None, - } - } - - pub fn set(&mut self, attr: ArgAttribute) -> &mut Self { - self.regular = self.regular | attr; - self - } - - pub fn contains(&self, attr: ArgAttribute) -> bool { - self.regular.contains(attr) - } - - pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { +impl ArgAttributesExt for ArgAttributes { + fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -150,7 +94,7 @@ impl ArgAttributes { } } - pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) { + fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -175,67 +119,13 @@ impl ArgAttributes { } } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum RegKind { - Integer, - Float, - Vector + +pub trait LlvmType { + fn llvm_type(&self, cx: &CodegenCx) -> Type; } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct Reg { - pub kind: RegKind, - pub size: Size, -} - -macro_rules! reg_ctor { - ($name:ident, $kind:ident, $bits:expr) => { - pub fn $name() -> Reg { - Reg { - kind: RegKind::$kind, - size: Size::from_bits($bits) - } - } - } -} - -impl Reg { - reg_ctor!(i8, Integer, 8); - reg_ctor!(i16, Integer, 16); - reg_ctor!(i32, Integer, 32); - reg_ctor!(i64, Integer, 64); - - reg_ctor!(f32, Float, 32); - reg_ctor!(f64, Float, 64); -} - -impl Reg { - pub fn align(&self, cx: &CodegenCx) -> Align { - let dl = cx.data_layout(); - match self.kind { - RegKind::Integer => { - match self.size.bits() { - 1 => dl.i1_align, - 2...8 => dl.i8_align, - 9...16 => dl.i16_align, - 17...32 => dl.i32_align, - 33...64 => dl.i64_align, - 65...128 => dl.i128_align, - _ => bug!("unsupported integer: {:?}", self) - } - } - RegKind::Float => { - match self.size.bits() { - 32 => dl.f32_align, - 64 => dl.f64_align, - _ => bug!("unsupported float: {:?}", self) - } - } - RegKind::Vector => dl.vector_align(self.size) - } - } - - pub fn llvm_type(&self, cx: &CodegenCx) -> Type { +impl LlvmType for Reg { + fn llvm_type(&self, cx: &CodegenCx) -> Type { match self.kind { RegKind::Integer => Type::ix(cx, self.size.bits()), RegKind::Float => { @@ -252,36 +142,6 @@ impl Reg { } } -/// An argument passed entirely registers with the -/// same kind (e.g. HFA / HVA on PPC64 and AArch64). -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct Uniform { - pub unit: Reg, - - /// The total size of the argument, which can be: - /// * equal to `unit.size` (one scalar/vector) - /// * a multiple of `unit.size` (an array of scalar/vectors) - /// * if `unit.kind` is `Integer`, the last element - /// can be shorter, i.e. `{ i64, i64, i32 }` for - /// 64-bit integers with a total size of 20 bytes - pub total: Size, -} - -impl From for Uniform { - fn from(unit: Reg) -> Uniform { - Uniform { - unit, - total: unit.size - } - } -} - -impl Uniform { - pub fn align(&self, cx: &CodegenCx) -> Align { - self.unit.align(cx) - } -} - pub trait LayoutExt<'tcx> { fn is_aggregate(&self) -> bool; fn homogeneous_aggregate<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option; @@ -381,51 +241,8 @@ impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct CastTarget { - pub prefix: [Option; 8], - pub prefix_chunk: Size, - pub rest: Uniform, -} - -impl From for CastTarget { - fn from(unit: Reg) -> CastTarget { - CastTarget::from(Uniform::from(unit)) - } -} - -impl From for CastTarget { - fn from(uniform: Uniform) -> CastTarget { - CastTarget { - prefix: [None; 8], - prefix_chunk: Size::from_bytes(0), - rest: uniform - } - } -} - -impl CastTarget { - pub fn pair(a: Reg, b: Reg) -> CastTarget { - CastTarget { - prefix: [Some(a.kind), None, None, None, None, None, None, None], - prefix_chunk: a.size, - rest: Uniform::from(b) - } - } - - pub fn size(&self, cx: &CodegenCx) -> Size { - (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64) - .abi_align(self.rest.align(cx)) + self.rest.total - } - - pub fn align(&self, cx: &CodegenCx) -> Align { - self.prefix.iter() - .filter_map(|x| x.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.align(cx))) - .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)), - |acc, align| acc.max(align)) - } - - pub fn llvm_type(&self, cx: &CodegenCx) -> Type { +impl LlvmType for CastTarget { + fn llvm_type(&self, cx: &CodegenCx) -> Type { let rest_ll_unit = self.rest.unit.llvm_type(cx); let rest_count = self.rest.total.bytes() / self.rest.unit.size.bytes(); let rem_bytes = self.rest.total.bytes() % self.rest.unit.size.bytes(); diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index ecdc2d20d21..7594085488f 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -13,7 +13,7 @@ use intrinsics::{self, Intrinsic}; use llvm; use llvm::{ValueRef}; -use abi::{Abi, FnType, PassMode}; +use abi::{Abi, FnType, LlvmType, PassMode}; use mir::place::PlaceRef; use mir::operand::{OperandRef, OperandValue}; use base::*; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 8fcc849b060..2fa43e4440b 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -33,8 +33,6 @@ use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; -#[macro_use] -extern crate bitflags; extern crate flate2; extern crate libc; #[macro_use] extern crate rustc; diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 93bc89f0914..973bd3d5baa 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -13,7 +13,7 @@ use rustc::middle::lang_items; use rustc::ty::{self, TypeFoldable}; use rustc::ty::layout::{self, LayoutOf}; use rustc::mir; -use abi::{Abi, FnType, ArgType, PassMode}; +use abi::{Abi, FnType, ArgType, LlvmType, PassMode}; use base; use callee; use builder::Builder;