Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Prev Previous commit
Next Next commit
rustc_trans: generalize cabi_* to any context type.
  • Loading branch information
irinagpopa committed Apr 26, 2018
commit fb15d447009f7b32cf435e0ad63bbbed5961e243
6 changes: 3 additions & 3 deletions src/librustc_target/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,18 +784,18 @@ pub trait LayoutOf {
fn layout_of(self, ty: Self::Ty) -> Self::TyLayout;
}

pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized {
pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
fn for_variant(this: TyLayout<'a, Self>, cx: C, variant_index: usize) -> TyLayout<'a, Self>;
fn field(this: TyLayout<'a, Self>, cx: C, i: usize) -> C::TyLayout;
}

impl<'a, Ty> TyLayout<'a, Ty> {
pub fn for_variant<C>(self, cx: C, variant_index: usize) -> Self
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf {
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
Ty::for_variant(self, cx, variant_index)
}
pub fn field<C>(self, cx: C, i: usize) -> C::TyLayout
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf {
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
Ty::field(self, cx, i)
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,16 @@ pub struct Target {
pub options: TargetOptions,
}

pub trait HasTargetSpec: Copy {
fn target_spec(&self) -> &Target;
}

impl<'a> HasTargetSpec for &'a Target {
fn target_spec(&self) -> &Target {
self
}
}

/// Optional aspects of a target specification.
///
/// This has an implementation of `Default`, see each field for what the default is. In general,
Expand Down
64 changes: 43 additions & 21 deletions src/librustc_trans/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ use mir::operand::OperandValue;
use type_::Type;
use type_of::{LayoutLlvmExt, PointerKind};

use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, TyLayoutMethods};
use rustc_target::spec::HasTargetSpec;
use rustc::ty::{self, Ty};
use rustc::ty::layout::{self, LayoutOf, Size, TyLayout};
use rustc::ty::layout;

use libc::c_uint;
use std::cmp;
Expand Down Expand Up @@ -142,12 +144,13 @@ impl LlvmType for Reg {
}
}

pub trait LayoutExt<'tcx> {
pub trait LayoutExt<'a, Ty>: Sized {
fn is_aggregate(&self) -> bool;
fn homogeneous_aggregate<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<Reg>;
fn homogeneous_aggregate<C>(&self, cx: C) -> Option<Reg>
where Ty: TyLayoutMethods<'a, C> + Copy, C: LayoutOf<Ty = Ty, TyLayout = Self> + Copy;
}

impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
impl<'a, Ty> LayoutExt<'a, Ty> for TyLayout<'a, Ty> {
fn is_aggregate(&self) -> bool {
match self.abi {
layout::Abi::Uninhabited |
Expand All @@ -158,7 +161,9 @@ impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
}
}

fn homogeneous_aggregate<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<Reg> {
fn homogeneous_aggregate<C>(&self, cx: C) -> Option<Reg>
where Ty: TyLayoutMethods<'a, C> + Copy, C: LayoutOf<Ty = Ty, TyLayout = Self> + Copy
{
match self.abi {
layout::Abi::Uninhabited => None,

Expand Down Expand Up @@ -280,17 +285,17 @@ impl LlvmType for CastTarget {
/// Information about how to pass an argument to,
/// or return a value from, a function, under some ABI.
#[derive(Debug)]
pub struct ArgType<'tcx> {
pub layout: TyLayout<'tcx>,
pub struct ArgType<'tcx, Ty = ty::Ty<'tcx>> {
pub layout: TyLayout<'tcx, Ty>,

/// Dummy argument, which is emitted before the real argument.
pub pad: Option<Reg>,

pub mode: PassMode,
}

impl<'a, 'tcx> ArgType<'tcx> {
fn new(layout: TyLayout<'tcx>) -> ArgType<'tcx> {
impl<'a, 'tcx, Ty> ArgType<'tcx, Ty> {
fn new(layout: TyLayout<'tcx, Ty>) -> Self {
ArgType {
layout,
pad: None,
Expand Down Expand Up @@ -364,7 +369,9 @@ impl<'a, 'tcx> ArgType<'tcx> {
pub fn is_ignore(&self) -> bool {
self.mode == PassMode::Ignore
}
}

impl<'a, 'tcx> ArgType<'tcx> {
/// Get the LLVM type for a place of the original Rust type of
/// this argument/return, i.e. the result of `type_of::type_of`.
pub fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
Expand Down Expand Up @@ -451,12 +458,12 @@ impl<'a, 'tcx> ArgType<'tcx> {
/// I will do my best to describe this structure, but these
/// comments are reverse-engineered and may be inaccurate. -NDM
#[derive(Debug)]
pub struct FnType<'tcx> {
pub struct FnType<'tcx, Ty = ty::Ty<'tcx>> {
/// The LLVM types of each argument.
pub args: Vec<ArgType<'tcx>>,
pub args: Vec<ArgType<'tcx, Ty>>,

/// LLVM return type.
pub ret: ArgType<'tcx>,
pub ret: ArgType<'tcx, Ty>,

pub variadic: bool,

Expand All @@ -474,15 +481,15 @@ impl<'a, 'tcx> FnType<'tcx> {

pub fn new(cx: &CodegenCx<'a, 'tcx>,
sig: ty::FnSig<'tcx>,
extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
extra_args: &[Ty<'tcx>]) -> Self {
let mut fn_ty = FnType::unadjusted(cx, sig, extra_args);
fn_ty.adjust_for_abi(cx, sig.abi);
fn_ty
}

pub fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
sig: ty::FnSig<'tcx>,
extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
extra_args: &[Ty<'tcx>]) -> Self {
let mut fn_ty = FnType::unadjusted(cx, sig, extra_args);
// Don't pass the vtable, it's not an argument of the virtual fn.
{
Expand All @@ -507,7 +514,7 @@ impl<'a, 'tcx> FnType<'tcx> {

pub fn unadjusted(cx: &CodegenCx<'a, 'tcx>,
sig: ty::FnSig<'tcx>,
extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
extra_args: &[Ty<'tcx>]) -> Self {
debug!("FnType::unadjusted({:?}, {:?})", sig, extra_args);

use self::Abi::*;
Expand Down Expand Up @@ -569,7 +576,7 @@ impl<'a, 'tcx> FnType<'tcx> {
// Handle safe Rust thin and fat pointers.
let adjust_for_rust_scalar = |attrs: &mut ArgAttributes,
scalar: &layout::Scalar,
layout: TyLayout<'tcx>,
layout: TyLayout<'tcx, Ty<'tcx>>,
offset: Size,
is_return: bool| {
// Booleans are always an i1 that needs to be zero-extended.
Expand Down Expand Up @@ -742,7 +749,18 @@ impl<'a, 'tcx> FnType<'tcx> {
return;
}

match &cx.sess().target.target.arch[..] {
if let Err(msg) = self.adjust_for_cabi(cx, abi) {
cx.sess().fatal(&msg);
}
}
}

impl<'a, Ty> FnType<'a, Ty> {
fn adjust_for_cabi<C>(&mut self, cx: C, abi: Abi) -> Result<(), String>
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
{
match &cx.target_spec().arch[..] {
"x86" => {
let flavor = if abi == Abi::Fastcall {
cabi_x86::Flavor::Fastcall
Expand All @@ -753,7 +771,7 @@ impl<'a, 'tcx> FnType<'tcx> {
},
"x86_64" => if abi == Abi::SysV64 {
cabi_x86_64::compute_abi_info(cx, self);
} else if abi == Abi::Win64 || cx.sess().target.target.options.is_like_windows {
} else if abi == Abi::Win64 || cx.target_spec().options.is_like_windows {
cabi_x86_win64::compute_abi_info(self);
} else {
cabi_x86_64::compute_abi_info(cx, self);
Expand All @@ -767,10 +785,10 @@ impl<'a, 'tcx> FnType<'tcx> {
"s390x" => cabi_s390x::compute_abi_info(cx, self),
"asmjs" => cabi_asmjs::compute_abi_info(cx, self),
"wasm32" => {
if cx.sess().opts.target_triple.triple().contains("emscripten") {
if cx.target_spec().llvm_target.contains("emscripten") {
cabi_asmjs::compute_abi_info(cx, self)
} else {
cabi_wasm32::compute_abi_info(cx, self)
cabi_wasm32::compute_abi_info(self)
}
}
"msp430" => cabi_msp430::compute_abi_info(self),
Expand All @@ -779,14 +797,18 @@ impl<'a, 'tcx> FnType<'tcx> {
"nvptx" => cabi_nvptx::compute_abi_info(self),
"nvptx64" => cabi_nvptx64::compute_abi_info(self),
"hexagon" => cabi_hexagon::compute_abi_info(self),
a => cx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
a => return Err(format!("unrecognized arch \"{}\" in target specification", a))
}

if let PassMode::Indirect(ref mut attrs) = self.ret.mode {
attrs.set(ArgAttribute::StructRet);
}

Ok(())
}
}

impl<'a, 'tcx> FnType<'tcx> {
pub fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
let mut llargument_tys = Vec::new();

Expand Down
24 changes: 18 additions & 6 deletions src/librustc_trans/cabi_aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
// except according to those terms.

use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
use context::CodegenCx;
use rustc_target::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};

fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
-> Option<Uniform> {
fn is_homogeneous_aggregate<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
-> Option<Uniform>
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
let size = arg.layout.size;

Expand All @@ -38,7 +41,10 @@ fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgTyp
})
}

fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(32);
return;
Expand Down Expand Up @@ -69,7 +75,10 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
ret.make_indirect();
}

fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
if !arg.layout.is_aggregate() {
arg.extend_integer_width_to(32);
return;
Expand Down Expand Up @@ -100,7 +109,10 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
arg.make_indirect();
}

pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
if !fty.ret.is_ignore() {
classify_ret_ty(cx, &mut fty.ret);
}
Expand Down
27 changes: 20 additions & 7 deletions src/librustc_trans/cabi_arm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@
// except according to those terms.

use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
use context::CodegenCx;
use rustc_target::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
use rustc_target::spec::HasTargetSpec;
use llvm::CallConv;

fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
-> Option<Uniform> {
fn is_homogeneous_aggregate<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
-> Option<Uniform>
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
let size = arg.layout.size;

Expand All @@ -39,7 +43,10 @@ fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgTyp
})
}

fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>, vfp: bool) {
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>, vfp: bool)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(32);
return;
Expand Down Expand Up @@ -71,7 +78,10 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>,
ret.make_indirect();
}

fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>, vfp: bool) {
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>, vfp: bool)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
if !arg.layout.is_aggregate() {
arg.extend_integer_width_to(32);
return;
Expand All @@ -92,10 +102,13 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>,
});
}

pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
{
// If this is a target with a hard-float ABI, and the function is not explicitly
// `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
let vfp = cx.sess().target.target.llvm_target.ends_with("hf")
let vfp = cx.target_spec().llvm_target.ends_with("hf")
&& fty.cconv != CallConv::ArmAapcsCallConv
&& !fty.variadic;

Expand Down
14 changes: 10 additions & 4 deletions src/librustc_trans/cabi_asmjs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
// except according to those terms.

use abi::{FnType, ArgType, LayoutExt, Uniform};
use context::CodegenCx;
use rustc_target::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};

// Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128

// See the https://github.com/kripken/emscripten-fastcomp-clang repository.
// The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions.

fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
if ret.layout.is_aggregate() {
if let Some(unit) = ret.layout.homogeneous_aggregate(cx) {
let size = ret.layout.size;
Expand All @@ -33,13 +36,16 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
}
}

fn classify_arg_ty(arg: &mut ArgType) {
fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
if arg.layout.is_aggregate() {
arg.make_indirect_byval();
}
}

pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
if !fty.ret.is_ignore() {
classify_ret_ty(cx, &mut fty.ret);
}
Expand Down
Loading