mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-20 10:55:14 +00:00
trans: Apply ZExt and StructRet attributes uniformly.
This commit is contained in:
parent
ac60318cf5
commit
d492d09f31
@ -10,8 +10,7 @@
|
||||
|
||||
pub use self::ArgKind::*;
|
||||
|
||||
use llvm::{self, AttrHelper, ValueRef};
|
||||
use trans::attributes;
|
||||
use llvm;
|
||||
use trans::common::{return_type_is_void, type_is_fat_ptr};
|
||||
use trans::context::CrateContext;
|
||||
use trans::cabi_x86;
|
||||
@ -23,7 +22,7 @@ use trans::cabi_powerpc;
|
||||
use trans::cabi_powerpc64;
|
||||
use trans::cabi_mips;
|
||||
use trans::cabi_asmjs;
|
||||
use trans::machine::llsize_of_alloc;
|
||||
use trans::machine::{llsize_of_alloc, llsize_of_real};
|
||||
use trans::type_::Type;
|
||||
use trans::type_of;
|
||||
|
||||
@ -191,6 +190,13 @@ impl FnType {
|
||||
cconv: cconv
|
||||
};
|
||||
|
||||
// Add ZExt attributes to i1 arguments and returns.
|
||||
for arg in Some(&mut fty.ret).into_iter().chain(&mut fty.args) {
|
||||
if arg.ty == Type::i1(ccx) {
|
||||
arg.attr = Some(llvm::Attribute::ZExt);
|
||||
}
|
||||
}
|
||||
|
||||
if abi == Rust || abi == RustCall {
|
||||
let fixup = |arg: &mut ArgType| {
|
||||
if !arg.ty.is_aggregate() {
|
||||
@ -246,7 +252,7 @@ impl FnType {
|
||||
fty
|
||||
}
|
||||
|
||||
pub fn to_llvm(&self, ccx: &CrateContext) -> Type {
|
||||
pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
|
||||
let mut llargument_tys = Vec::new();
|
||||
|
||||
let llreturn_ty = if self.ret.is_indirect() {
|
||||
@ -281,19 +287,29 @@ impl FnType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_attributes(&self, llfn: ValueRef) {
|
||||
let mut i = if self.ret.is_indirect() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
pub fn llvm_attrs(&self, ccx: &CrateContext) -> llvm::AttrBuilder {
|
||||
let mut attrs = llvm::AttrBuilder::new();
|
||||
let mut i = if self.ret.is_indirect() { 1 } else { 0 };
|
||||
|
||||
// Add attributes that are always applicable, independent of the concrete foreign ABI
|
||||
if self.ret.is_indirect() {
|
||||
let llret_sz = llsize_of_real(ccx, self.ret.ty);
|
||||
|
||||
// The outptr can be noalias and nocapture because it's entirely
|
||||
// invisible to the program. We also know it's nonnull as well
|
||||
// as how many bytes we can dereference
|
||||
attrs.arg(i, llvm::Attribute::StructRet)
|
||||
.arg(i, llvm::Attribute::NoAlias)
|
||||
.arg(i, llvm::Attribute::NoCapture)
|
||||
.arg(i, llvm::DereferenceableAttribute(llret_sz));
|
||||
};
|
||||
|
||||
// Add attributes that depend on the concrete foreign ABI
|
||||
if let Some(attr) = self.ret.attr {
|
||||
attr.apply_llfn(i, llfn);
|
||||
attrs.arg(i, attr);
|
||||
}
|
||||
|
||||
i += 1;
|
||||
|
||||
for arg in &self.args {
|
||||
if arg.is_ignore() {
|
||||
continue;
|
||||
@ -302,12 +318,12 @@ impl FnType {
|
||||
if arg.pad.is_some() { i += 1; }
|
||||
|
||||
if let Some(attr) = arg.attr {
|
||||
attr.apply_llfn(i, llfn);
|
||||
attrs.arg(i, attr);
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
attributes::unwind(llfn, false);
|
||||
attrs
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute};
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
|
||||
use trans::abi::{FnType, ArgType, Indirect};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
@ -163,9 +163,6 @@ fn is_homogenous_aggregate_ty(ty: Type) -> Option<(Type, u64)> {
|
||||
|
||||
fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
||||
if is_reg_ty(ret.ty) {
|
||||
if ret.ty == Type::i1(ccx) {
|
||||
ret.attr = Some(Attribute::ZExt)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ret.ty) {
|
||||
@ -189,14 +186,10 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
||||
return;
|
||||
}
|
||||
ret.kind = Indirect;
|
||||
ret.attr = Some(Attribute::StructRet);
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
|
||||
if is_reg_ty(arg.ty) {
|
||||
if arg.ty == Type::i1(ccx) {
|
||||
arg.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if let Some((base_ty, members)) = is_homogenous_aggregate_ty(arg.ty) {
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute};
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
|
||||
use trans::abi::{FnType, ArgType, Indirect};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
@ -131,9 +131,6 @@ fn ty_size(ty: Type, align_fn: TyAlignFn) -> usize {
|
||||
|
||||
fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType, align_fn: TyAlignFn) {
|
||||
if is_reg_ty(ret.ty) {
|
||||
if ret.ty == Type::i1(ccx) {
|
||||
ret.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let size = ty_size(ret.ty, align_fn);
|
||||
@ -149,14 +146,10 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType, align_fn: TyAlignFn) {
|
||||
return;
|
||||
}
|
||||
ret.kind = Indirect;
|
||||
ret.attr = Some(Attribute::StructRet);
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, align_fn: TyAlignFn) {
|
||||
if is_reg_ty(arg.ty) {
|
||||
if arg.ty == Type::i1(ccx) {
|
||||
arg.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let align = align_fn(arg.ty);
|
||||
|
@ -20,7 +20,7 @@ use trans::type_::Type;
|
||||
// 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(ccx: &CrateContext, ret: &mut ArgType) {
|
||||
fn classify_ret_ty(ret: &mut ArgType) {
|
||||
match ret.ty.kind() {
|
||||
Struct => {
|
||||
let field_types = ret.ty.field_types();
|
||||
@ -28,38 +28,28 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
||||
ret.cast = Some(field_types[0]);
|
||||
} else {
|
||||
ret.kind = Indirect;
|
||||
ret.attr = Some(Attribute::StructRet);
|
||||
}
|
||||
},
|
||||
Array => {
|
||||
ret.kind = Indirect;
|
||||
ret.attr = Some(Attribute::StructRet);
|
||||
},
|
||||
_ => {
|
||||
if ret.ty == Type::i1(ccx) {
|
||||
ret.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
ret.kind = Indirect;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
|
||||
fn classify_arg_ty(arg: &mut ArgType) {
|
||||
if arg.ty.is_aggregate() {
|
||||
arg.kind = Indirect;
|
||||
arg.attr = Some(Attribute::ByVal);
|
||||
} else {
|
||||
if arg.ty == Type::i1(ccx) {
|
||||
arg.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
if fty.ret.ty != Type::void(ccx) {
|
||||
classify_ret_ty(ccx, &mut fty.ret);
|
||||
classify_ret_ty(&mut fty.ret);
|
||||
}
|
||||
|
||||
for arg in &mut fty.args {
|
||||
classify_arg_ty(ccx, arg);
|
||||
classify_arg_ty(arg);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
use libc::c_uint;
|
||||
use std::cmp;
|
||||
use llvm;
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute};
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
|
||||
use trans::abi::{ArgType, FnType, Indirect};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
@ -86,17 +86,6 @@ fn ty_size(ty: Type) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
||||
if is_reg_ty(ret.ty) {
|
||||
if ret.ty == Type::i1(ccx) {
|
||||
ret.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
} else {
|
||||
ret.kind = Indirect;
|
||||
ret.attr = Some(Attribute::StructRet);
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) {
|
||||
let orig_offset = *offset;
|
||||
let size = ty_size(arg.ty) * 8;
|
||||
@ -106,11 +95,7 @@ fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) {
|
||||
*offset = align_up_to(*offset, align);
|
||||
*offset += align_up_to(size, align * 8) / 8;
|
||||
|
||||
if is_reg_ty(arg.ty) {
|
||||
if arg.ty == Type::i1(ccx) {
|
||||
arg.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
} else {
|
||||
if !is_reg_ty(arg.ty) {
|
||||
arg.cast = Some(struct_ty(ccx, arg.ty));
|
||||
arg.pad = padding_ty(ccx, align, orig_offset);
|
||||
}
|
||||
@ -162,7 +147,9 @@ 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) {
|
||||
classify_ret_ty(ccx, &mut fty.ret);
|
||||
if !is_reg_ty(fty.ret.ty) {
|
||||
fty.ret.kind = Indirect;
|
||||
}
|
||||
}
|
||||
|
||||
let mut offset = if fty.ret.is_indirect() { 4 } else { 0 };
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
use libc::c_uint;
|
||||
use llvm;
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Attribute};
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array};
|
||||
use trans::abi::{FnType, ArgType, Indirect};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
@ -82,17 +82,6 @@ fn ty_size(ty: Type) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
||||
if is_reg_ty(ret.ty) {
|
||||
if ret.ty == Type::i1(ccx) {
|
||||
ret.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
} else {
|
||||
ret.kind = Indirect;
|
||||
ret.attr = Some(Attribute::StructRet);
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) {
|
||||
let orig_offset = *offset;
|
||||
let size = ty_size(arg.ty) * 8;
|
||||
@ -102,11 +91,7 @@ fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) {
|
||||
*offset = align_up_to(*offset, align);
|
||||
*offset += align_up_to(size, align * 8) / 8;
|
||||
|
||||
if is_reg_ty(arg.ty) {
|
||||
if arg.ty == Type::i1(ccx) {
|
||||
arg.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
} else {
|
||||
if !is_reg_ty(arg.ty) {
|
||||
arg.cast = Some(struct_ty(ccx, arg.ty));
|
||||
arg.pad = padding_ty(ccx, align, orig_offset);
|
||||
}
|
||||
@ -157,7 +142,9 @@ 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) {
|
||||
classify_ret_ty(ccx, &mut fty.ret);
|
||||
if !is_reg_ty(fty.ret.ty) {
|
||||
fty.ret.kind = Indirect;
|
||||
}
|
||||
}
|
||||
|
||||
let mut offset = if fty.ret.is_indirect() { 4 } else { 0 };
|
||||
|
@ -15,7 +15,7 @@
|
||||
// Alignment of 128 bit types is not currently handled, this will
|
||||
// need to be fixed when PowerPC vector support is added.
|
||||
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Attribute};
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array};
|
||||
use trans::abi::{FnType, ArgType, Indirect};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
@ -153,16 +153,12 @@ fn is_homogenous_aggregate_ty(ty: Type) -> Option<(Type, u64)> {
|
||||
|
||||
fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
||||
if is_reg_ty(ret.ty) {
|
||||
if ret.ty == Type::i1(ccx) {
|
||||
ret.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// The PowerPC64 big endian ABI doesn't return aggregates in registers
|
||||
if ccx.sess().target.target.target_endian == "big" {
|
||||
ret.kind = Indirect;
|
||||
ret.attr = Some(Attribute::StructRet);
|
||||
}
|
||||
|
||||
if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ret.ty) {
|
||||
@ -187,14 +183,10 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
||||
}
|
||||
|
||||
ret.kind = Indirect;
|
||||
ret.attr = Some(Attribute::StructRet);
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
|
||||
if is_reg_ty(arg.ty) {
|
||||
if arg.ty == Type::i1(ccx) {
|
||||
arg.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -30,17 +30,11 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
2 => fty.ret.cast = Some(Type::i16(ccx)),
|
||||
4 => fty.ret.cast = Some(Type::i32(ccx)),
|
||||
8 => fty.ret.cast = Some(Type::i64(ccx)),
|
||||
_ => {
|
||||
fty.ret.kind = Indirect;
|
||||
fty.ret.attr = Some(Attribute::StructRet);
|
||||
}
|
||||
_ => fty.ret.kind = Indirect
|
||||
}
|
||||
} else {
|
||||
fty.ret.kind = Indirect;
|
||||
fty.ret.attr = Some(Attribute::StructRet);
|
||||
}
|
||||
} else if fty.ret.ty == Type::i1(ccx) {
|
||||
fty.ret.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
|
||||
for arg in &mut fty.args {
|
||||
@ -51,8 +45,6 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
arg.kind = Indirect;
|
||||
arg.attr = Some(Attribute::ByVal);
|
||||
}
|
||||
} else if arg.ty == Type::i1(ccx) {
|
||||
arg.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -387,21 +387,17 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
fn x86_64_ty<F>(ccx: &CrateContext,
|
||||
arg: &mut ArgType,
|
||||
is_mem_cls: F,
|
||||
ind_attr: Attribute)
|
||||
ind_attr: Option<Attribute>)
|
||||
where F: FnOnce(&[RegClass]) -> bool
|
||||
{
|
||||
if !arg.ty.is_reg_ty() {
|
||||
let cls = classify_ty(arg.ty);
|
||||
if is_mem_cls(&cls) {
|
||||
arg.kind = Indirect;
|
||||
arg.attr = Some(ind_attr);
|
||||
arg.attr = ind_attr;
|
||||
} else {
|
||||
arg.cast = Some(llreg_ty(ccx, &cls));
|
||||
}
|
||||
} else {
|
||||
if arg.ty == Type::i1(ccx) {
|
||||
arg.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,7 +413,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}, Attribute::StructRet);
|
||||
}, None);
|
||||
}
|
||||
|
||||
for arg in &mut fty.args {
|
||||
@ -436,7 +432,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
sse_regs -= needed_sse;
|
||||
}
|
||||
in_mem
|
||||
}, Attribute::ByVal);
|
||||
}, Some(Attribute::ByVal));
|
||||
|
||||
// An integer, pointer, double or float parameter
|
||||
// thus the above closure passed to `x86_64_ty` won't
|
||||
|
@ -17,27 +17,22 @@ use trans::type_::Type;
|
||||
// Win64 ABI: http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
|
||||
|
||||
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
let fixup = |a: &mut ArgType, indirect_attr| {
|
||||
let fixup = |a: &mut ArgType| {
|
||||
if a.ty.kind() == Struct {
|
||||
match llsize_of_alloc(ccx, a.ty) {
|
||||
1 => a.cast = Some(Type::i8(ccx)),
|
||||
2 => a.cast = Some(Type::i16(ccx)),
|
||||
4 => a.cast = Some(Type::i32(ccx)),
|
||||
8 => a.cast = Some(Type::i64(ccx)),
|
||||
_ => {
|
||||
a.kind = Indirect;
|
||||
a.attr = indirect_attr;
|
||||
}
|
||||
_ => a.kind = Indirect
|
||||
}
|
||||
} else if a.ty == Type::i1(ccx) {
|
||||
a.attr = Some(Attribute::ZExt);
|
||||
}
|
||||
};
|
||||
|
||||
if fty.ret.ty != Type::void(ccx) {
|
||||
fixup(&mut fty.ret, Some(Attribute::StructRet));
|
||||
fixup(&mut fty.ret);
|
||||
}
|
||||
for arg in &mut fty.args {
|
||||
fixup(arg, None);
|
||||
fixup(arg);
|
||||
}
|
||||
}
|
||||
|
@ -103,17 +103,20 @@ pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
|
||||
debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
|
||||
|
||||
let fty = FnType::new(ccx, f.abi, &sig, &[]);
|
||||
let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.to_llvm(ccx));
|
||||
let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx));
|
||||
|
||||
if sig.output == ty::FnDiverging {
|
||||
llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturn);
|
||||
}
|
||||
|
||||
if f.abi == Abi::Rust || f.abi == Abi::RustCall {
|
||||
attributes::from_fn_type(ccx, fn_type).apply_llfn(llfn);
|
||||
let attrs = if f.abi == Abi::Rust || f.abi == Abi::RustCall {
|
||||
attributes::from_fn_type(ccx, fn_type)
|
||||
} else {
|
||||
fty.add_attributes(llfn);
|
||||
}
|
||||
attributes::unwind(llfn, false);
|
||||
fty.llvm_attrs(ccx)
|
||||
};
|
||||
|
||||
attrs.apply_llfn(llfn);
|
||||
|
||||
llfn
|
||||
}
|
||||
|
@ -247,47 +247,13 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
|
||||
// A function pointer is called without the declaration available, so we have to apply
|
||||
// any attributes with ABI implications directly to the call instruction.
|
||||
let mut attrs = llvm::AttrBuilder::new();
|
||||
|
||||
// Add attributes that are always applicable, independent of the concrete foreign ABI
|
||||
if fn_type.ret.is_indirect() {
|
||||
let llret_sz = machine::llsize_of_real(ccx, fn_type.ret.ty);
|
||||
|
||||
// The outptr can be noalias and nocapture because it's entirely
|
||||
// invisible to the program. We also know it's nonnull as well
|
||||
// as how many bytes we can dereference
|
||||
attrs.arg(1, llvm::Attribute::NoAlias)
|
||||
.arg(1, llvm::Attribute::NoCapture)
|
||||
.arg(1, llvm::DereferenceableAttribute(llret_sz));
|
||||
};
|
||||
|
||||
// Add attributes that depend on the concrete foreign ABI
|
||||
let mut arg_idx = if fn_type.ret.is_indirect() { 1 } else { 0 };
|
||||
match fn_type.ret.attr {
|
||||
Some(attr) => { attrs.arg(arg_idx, attr); },
|
||||
_ => ()
|
||||
}
|
||||
|
||||
arg_idx += 1;
|
||||
for arg_ty in &fn_type.args {
|
||||
if arg_ty.is_ignore() {
|
||||
continue;
|
||||
}
|
||||
// skip padding
|
||||
if arg_ty.pad.is_some() { arg_idx += 1; }
|
||||
|
||||
if let Some(attr) = arg_ty.attr {
|
||||
attrs.arg(arg_idx, attr);
|
||||
}
|
||||
|
||||
arg_idx += 1;
|
||||
}
|
||||
|
||||
let llforeign_retval = CallWithConv(bcx,
|
||||
llfn,
|
||||
&llargs_foreign[..],
|
||||
fn_type.cconv,
|
||||
Some(attrs),
|
||||
Some(fn_type.llvm_attrs(ccx)),
|
||||
call_debug_loc);
|
||||
|
||||
// If the function we just called does not use an outpointer,
|
||||
|
@ -322,7 +322,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
||||
ty::TyFnPtr(f) => {
|
||||
let sig = cx.tcx().erase_late_bound_regions(&f.sig);
|
||||
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
|
||||
FnType::new(cx, f.abi, &sig, &[]).to_llvm(cx).ptr_to()
|
||||
FnType::new(cx, f.abi, &sig, &[]).llvm_type(cx).ptr_to()
|
||||
}
|
||||
ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx),
|
||||
ty::TyTuple(..) => {
|
||||
|
Loading…
Reference in New Issue
Block a user