trans: Handle ignored arguments/returns uniformly.

This commit is contained in:
Eduard Burtescu 2016-03-06 12:36:39 +02:00
parent 7454b5c61d
commit 80d939fd22
10 changed files with 65 additions and 55 deletions

View File

@ -9,7 +9,7 @@
// except according to those terms.
use llvm::{self, ValueRef};
use trans::common::{return_type_is_void, type_is_fat_ptr};
use trans::common::{type_is_fat_ptr, Block};
use trans::context::CrateContext;
use trans::cabi_x86;
use trans::cabi_x86_64;
@ -20,7 +20,7 @@ use trans::cabi_powerpc;
use trans::cabi_powerpc64;
use trans::cabi_mips;
use trans::cabi_asmjs;
use trans::machine::{llsize_of_alloc, llsize_of_real};
use trans::machine::{llalign_of_min, llsize_of, llsize_of_real};
use trans::type_::Type;
use trans::type_of;
@ -97,6 +97,8 @@ impl ArgType {
}
pub fn make_indirect(&mut self, ccx: &CrateContext) {
assert_eq!(self.kind, ArgKind::Direct);
// Wipe old attributes, likely not valid through indirection.
self.attrs = llvm::Attributes::default();
@ -113,6 +115,7 @@ impl ArgType {
}
pub fn ignore(&mut self) {
assert_eq!(self.kind, ArgKind::Direct);
self.kind = ArgKind::Ignore;
}
@ -200,39 +203,40 @@ impl FnType {
arg.attrs.set(llvm::Attribute::ZExt);
arg
} else {
ArgType::new(type_of::type_of(ccx, ty),
type_of::sizing_type_of(ccx, ty))
let mut arg = ArgType::new(type_of::type_of(ccx, ty),
type_of::sizing_type_of(ccx, ty));
if llsize_of_real(ccx, arg.ty) == 0 {
arg.ignore();
}
arg
}
};
let mut ret = match sig.output {
ty::FnConverging(ret_ty) if !return_type_is_void(ccx, ret_ty) => {
arg_of(ret_ty)
}
_ => ArgType::new(Type::void(ccx), Type::void(ccx))
let ret_ty = match sig.output {
ty::FnConverging(ret_ty) => ret_ty,
ty::FnDiverging => ccx.tcx().mk_nil()
};
let mut ret = arg_of(ret_ty);
if let ty::FnConverging(ret_ty) = sig.output {
if !type_is_fat_ptr(ccx.tcx(), ret_ty) {
// The `noalias` attribute on the return value is useful to a
// function ptr caller.
if let ty::TyBox(_) = ret_ty.sty {
// `Box` pointer return values never alias because ownership
// is transferred
ret.attrs.set(llvm::Attribute::NoAlias);
}
if !type_is_fat_ptr(ccx.tcx(), ret_ty) {
// The `noalias` attribute on the return value is useful to a
// function ptr caller.
if let ty::TyBox(_) = ret_ty.sty {
// `Box` pointer return values never alias because ownership
// is transferred
ret.attrs.set(llvm::Attribute::NoAlias);
}
// We can also mark the return value as `dereferenceable` in certain cases
match ret_ty.sty {
// These are not really pointers but pairs, (pointer, len)
ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
ty::TyBox(ty) => {
let llty = type_of::sizing_type_of(ccx, ty);
let llsz = llsize_of_real(ccx, llty);
ret.attrs.set_dereferenceable(llsz);
}
_ => {}
// We can also mark the return value as `dereferenceable` in certain cases
match ret_ty.sty {
// These are not really pointers but pairs, (pointer, len)
ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
ty::TyBox(ty) => {
let llty = type_of::sizing_type_of(ccx, ty);
let llsz = llsize_of_real(ccx, llty);
ret.attrs.set_dereferenceable(llsz);
}
_ => {}
}
}
@ -318,8 +322,8 @@ impl FnType {
// Scalars and vectors, always immediate.
return;
}
let size = llsize_of_alloc(ccx, arg.ty);
if size > llsize_of_alloc(ccx, ccx.int_type()) {
let size = llsize_of_real(ccx, arg.ty);
if size > llsize_of_real(ccx, ccx.int_type()) {
arg.make_indirect(ccx);
} else if size > 0 {
// We want to pass small aggregates as immediates, but using
@ -376,7 +380,9 @@ impl FnType {
pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
let mut llargument_tys = Vec::new();
let llreturn_ty = if self.ret.is_indirect() {
let llreturn_ty = if self.ret.is_ignore() {
Type::void(ccx)
} else if self.ret.is_indirect() {
llargument_tys.push(self.ret.original_ty.ptr_to());
Type::void(ccx)
} else {
@ -410,7 +416,9 @@ impl FnType {
pub fn apply_attrs_llfn(&self, llfn: ValueRef) {
let mut i = if self.ret.is_indirect() { 1 } else { 0 };
self.ret.attrs.apply_llfn(i, llfn);
if !self.ret.is_ignore() {
self.ret.attrs.apply_llfn(i, llfn);
}
i += 1;
for arg in &self.args {
if !arg.is_ignore() {
@ -423,7 +431,9 @@ impl FnType {
pub fn apply_attrs_callsite(&self, callsite: ValueRef) {
let mut i = if self.ret.is_indirect() { 1 } else { 0 };
self.ret.attrs.apply_callsite(i, callsite);
if !self.ret.is_ignore() {
self.ret.attrs.apply_callsite(i, callsite);
}
i += 1;
for arg in &self.args {
if !arg.is_ignore() {

View File

@ -229,11 +229,12 @@ fn is_reg_ty(ty: Type) -> bool {
}
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
if fty.ret.ty != Type::void(ccx) {
if !fty.ret.is_ignore() {
classify_ret_ty(ccx, &mut fty.ret);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
classify_arg_ty(ccx, arg);
}
}

View File

@ -179,11 +179,12 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType, flavor: Flavor) {
Flavor::Ios => ios_ty_align as TyAlignFn,
};
if fty.ret.ty != Type::void(ccx) {
if !fty.ret.is_ignore() {
classify_ret_ty(ccx, &mut fty.ret, align_fn);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
classify_arg_ty(ccx, arg, align_fn);
}
}

View File

@ -13,7 +13,6 @@
use llvm::{Struct, Array, Attribute};
use trans::abi::{FnType, ArgType};
use trans::context::CrateContext;
use trans::type_::Type;
// Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128
@ -45,11 +44,12 @@ fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
}
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
if fty.ret.ty != Type::void(ccx) {
if !fty.ret.is_ignore() {
classify_ret_ty(ccx, &mut fty.ret);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
classify_arg_ty(ccx, arg);
}
}

View File

@ -146,14 +146,13 @@ fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
}
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
if fty.ret.ty != Type::void(ccx) {
if !is_reg_ty(fty.ret.ty) {
fty.ret.make_indirect(ccx);
}
if !fty.ret.is_ignore() && !is_reg_ty(fty.ret.ty) {
fty.ret.make_indirect(ccx);
}
let mut offset = if fty.ret.is_indirect() { 4 } else { 0 };
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
classify_arg_ty(ccx, arg, &mut offset);
}
}

View File

@ -141,14 +141,13 @@ fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
}
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
if fty.ret.ty != Type::void(ccx) {
if !is_reg_ty(fty.ret.ty) {
fty.ret.make_indirect(ccx);
}
if !fty.ret.is_ignore() && !is_reg_ty(fty.ret.ty) {
fty.ret.make_indirect(ccx);
}
let mut offset = if fty.ret.is_indirect() { 4 } else { 0 };
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
classify_arg_ty(ccx, arg, &mut offset);
}
}

View File

@ -232,11 +232,12 @@ fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
}
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
if fty.ret.ty != Type::void(ccx) {
if !fty.ret.is_ignore() {
classify_ret_ty(ccx, &mut fty.ret);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
classify_arg_ty(ccx, arg);
}
}

View File

@ -15,7 +15,7 @@ use super::common::*;
use super::machine::*;
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
if fty.ret.ty.kind() == Struct {
if !fty.ret.is_ignore() && fty.ret.ty.kind() == Struct {
// Returning a structure. Most often, this will use
// a hidden first argument. On some platforms, though,
// small structs are returned as integers.
@ -38,13 +38,10 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
if arg.ty.kind() == Struct {
if llsize_of_alloc(ccx, arg.ty) == 0 {
arg.ignore();
} else {
arg.make_indirect(ccx);
arg.attrs.set(Attribute::ByVal);
}
arg.make_indirect(ccx);
arg.attrs.set(Attribute::ByVal);
}
}
}

View File

@ -406,7 +406,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
let mut int_regs = 6; // RDI, RSI, RDX, RCX, R8, R9
let mut sse_regs = 8; // XMM0-7
if fty.ret.ty != Type::void(ccx) {
if !fty.ret.is_ignore() {
x86_64_ty(ccx, &mut fty.ret, |cls| {
if cls.is_ret_bysret() {
// `sret` parameter thus one less register available
@ -419,6 +419,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
x86_64_ty(ccx, arg, |cls| {
let needed_int = cls.iter().filter(|&&c| c == Int).count() as isize;
let needed_sse = cls.iter().filter(|c| c.is_sse()).count() as isize;

View File

@ -29,10 +29,11 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
}
};
if fty.ret.ty != Type::void(ccx) {
if !fty.ret.is_ignore() {
fixup(&mut fty.ret);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
fixup(arg);
}
}