trans: Use llvm::Attributes directly in ArgTy.
This commit is contained in:
parent
c7172a9935
commit
de5f8244f2
|
@ -185,7 +185,7 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
pub struct Attributes {
|
||||
regular: Attribute,
|
||||
dereferenceable_bytes: u64
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub use self::ArgKind::*;
|
||||
|
||||
use llvm;
|
||||
use trans::common::{return_type_is_void, type_is_fat_ptr};
|
||||
use trans::context::CrateContext;
|
||||
|
@ -43,7 +41,7 @@ pub const FAT_PTR_ADDR: usize = 0;
|
|||
pub const FAT_PTR_EXTRA: usize = 1;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum ArgKind {
|
||||
enum ArgKind {
|
||||
/// Pass the argument directly using the normal converted
|
||||
/// LLVM type or by coercing to another specified type
|
||||
Direct,
|
||||
|
@ -59,7 +57,7 @@ pub enum ArgKind {
|
|||
/// This is borrowed from clang's ABIInfo.h
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct ArgType {
|
||||
pub kind: ArgKind,
|
||||
kind: ArgKind,
|
||||
/// Original LLVM type
|
||||
pub original_ty: Type,
|
||||
/// Sizing LLVM type (pointers are opaque).
|
||||
|
@ -81,28 +79,48 @@ pub struct ArgType {
|
|||
pub cast: Option<Type>,
|
||||
/// Dummy argument, which is emitted before the real argument
|
||||
pub pad: Option<Type>,
|
||||
/// LLVM attribute of argument
|
||||
pub attr: Option<llvm::Attribute>
|
||||
/// LLVM attributes of argument
|
||||
pub attrs: llvm::Attributes
|
||||
}
|
||||
|
||||
impl ArgType {
|
||||
fn new(original_ty: Type, ty: Type) -> ArgType {
|
||||
ArgType {
|
||||
kind: Direct,
|
||||
kind: ArgKind::Direct,
|
||||
original_ty: original_ty,
|
||||
ty: ty,
|
||||
cast: None,
|
||||
pad: None,
|
||||
attr: None
|
||||
attrs: llvm::Attributes::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_indirect(&mut self, ccx: &CrateContext) {
|
||||
// Wipe old attributes, likely not valid through indirection.
|
||||
self.attrs = llvm::Attributes::default();
|
||||
|
||||
let llarg_sz = llsize_of_real(ccx, self.ty);
|
||||
|
||||
// For non-immediate arguments the callee gets its own copy of
|
||||
// the value on the stack, so there are no aliases. It's also
|
||||
// program-invisible so can't possibly capture
|
||||
self.attrs.set(llvm::Attribute::NoAlias)
|
||||
.set(llvm::Attribute::NoCapture)
|
||||
.set_dereferenceable(llarg_sz);
|
||||
|
||||
self.kind = ArgKind::Indirect;
|
||||
}
|
||||
|
||||
pub fn ignore(&mut self) {
|
||||
self.kind = ArgKind::Ignore;
|
||||
}
|
||||
|
||||
pub fn is_indirect(&self) -> bool {
|
||||
self.kind == Indirect
|
||||
self.kind == ArgKind::Indirect
|
||||
}
|
||||
|
||||
pub fn is_ignore(&self) -> bool {
|
||||
self.kind == Ignore
|
||||
self.kind == ArgKind::Ignore
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,7 +196,7 @@ impl FnType {
|
|||
if ty.is_bool() {
|
||||
let llty = Type::i1(ccx);
|
||||
let mut arg = ArgType::new(llty, llty);
|
||||
arg.attr = Some(llvm::Attribute::ZExt);
|
||||
arg.attrs.set(llvm::Attribute::ZExt);
|
||||
arg
|
||||
} else {
|
||||
ArgType::new(type_of::type_of(ccx, ty),
|
||||
|
@ -221,7 +239,7 @@ impl FnType {
|
|||
}
|
||||
let size = llsize_of_alloc(ccx, arg.ty);
|
||||
if size > llsize_of_alloc(ccx, ccx.int_type()) {
|
||||
arg.kind = Indirect;
|
||||
arg.make_indirect(ccx);
|
||||
} else if size > 0 {
|
||||
// We want to pass small aggregates as immediates, but using
|
||||
// a LLVM aggregate type for this leads to bad optimizations,
|
||||
|
@ -238,6 +256,9 @@ impl FnType {
|
|||
for arg in &mut fty.args {
|
||||
fixup(arg);
|
||||
}
|
||||
if fty.ret.is_indirect() {
|
||||
fty.ret.attrs.set(llvm::Attribute::StructRet);
|
||||
}
|
||||
return fty;
|
||||
}
|
||||
|
||||
|
@ -264,6 +285,10 @@ impl FnType {
|
|||
a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
|
||||
}
|
||||
|
||||
if fty.ret.is_indirect() {
|
||||
fty.ret.attrs.set(llvm::Attribute::StructRet);
|
||||
}
|
||||
|
||||
fty
|
||||
}
|
||||
|
||||
|
@ -302,43 +327,18 @@ impl FnType {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn llvm_attrs(&self, ccx: &CrateContext) -> llvm::AttrBuilder {
|
||||
pub fn llvm_attrs(&self) -> 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).set(llvm::Attribute::StructRet)
|
||||
.set(llvm::Attribute::NoAlias)
|
||||
.set(llvm::Attribute::NoCapture)
|
||||
.set_dereferenceable(llret_sz);
|
||||
};
|
||||
|
||||
// Add attributes that depend on the concrete foreign ABI
|
||||
if let Some(attr) = self.ret.attr {
|
||||
attrs.arg(i).set(attr);
|
||||
}
|
||||
|
||||
*attrs.arg(i) = self.ret.attrs;
|
||||
i += 1;
|
||||
for arg in &self.args {
|
||||
if arg.is_ignore() {
|
||||
continue;
|
||||
if !arg.is_ignore() {
|
||||
if arg.pad.is_some() { i += 1; }
|
||||
*attrs.arg(i) = arg.attrs;
|
||||
i += 1;
|
||||
}
|
||||
// skip padding
|
||||
if arg.pad.is_some() { i += 1; }
|
||||
|
||||
if let Some(attr) = arg.attr {
|
||||
attrs.arg(i).set(attr);
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
attrs
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
|
||||
use trans::abi::{FnType, ArgType, Indirect};
|
||||
use trans::abi::{FnType, ArgType};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
|
||||
|
@ -185,7 +185,7 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
|||
ret.cast = Some(llty);
|
||||
return;
|
||||
}
|
||||
ret.kind = Indirect;
|
||||
ret.make_indirect(ccx);
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
|
||||
|
@ -214,7 +214,7 @@ fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
|
|||
arg.cast = Some(llty);
|
||||
return;
|
||||
}
|
||||
arg.kind = Indirect;
|
||||
arg.make_indirect(ccx);
|
||||
}
|
||||
|
||||
fn is_reg_ty(ty: Type) -> bool {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
|
||||
use trans::abi::{FnType, ArgType, Indirect};
|
||||
use trans::abi::{FnType, ArgType};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
|
||||
|
@ -145,7 +145,7 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType, align_fn: TyAlignFn) {
|
|||
ret.cast = Some(llty);
|
||||
return;
|
||||
}
|
||||
ret.kind = Indirect;
|
||||
ret.make_indirect(ccx);
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, align_fn: TyAlignFn) {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use llvm::{Struct, Array, Attribute};
|
||||
use trans::abi::{FnType, ArgType, Indirect};
|
||||
use trans::abi::{FnType, ArgType};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
|
||||
|
@ -20,36 +20,36 @@ 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(ret: &mut ArgType) {
|
||||
fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
||||
match ret.ty.kind() {
|
||||
Struct => {
|
||||
let field_types = ret.ty.field_types();
|
||||
if field_types.len() == 1 {
|
||||
ret.cast = Some(field_types[0]);
|
||||
} else {
|
||||
ret.kind = Indirect;
|
||||
ret.make_indirect(ccx);
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
ret.kind = Indirect;
|
||||
ret.make_indirect(ccx);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(arg: &mut ArgType) {
|
||||
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
|
||||
if arg.ty.is_aggregate() {
|
||||
arg.kind = Indirect;
|
||||
arg.attr = Some(Attribute::ByVal);
|
||||
arg.make_indirect(ccx);
|
||||
arg.attrs.set(Attribute::ByVal);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
if fty.ret.ty != Type::void(ccx) {
|
||||
classify_ret_ty(&mut fty.ret);
|
||||
classify_ret_ty(ccx, &mut fty.ret);
|
||||
}
|
||||
|
||||
for arg in &mut fty.args {
|
||||
classify_arg_ty(arg);
|
||||
classify_arg_ty(ccx, arg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use libc::c_uint;
|
|||
use std::cmp;
|
||||
use llvm;
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
|
||||
use trans::abi::{ArgType, FnType, Indirect};
|
||||
use trans::abi::{ArgType, FnType};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
|
||||
|
@ -148,7 +148,7 @@ 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.kind = Indirect;
|
||||
fty.ret.make_indirect(ccx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use libc::c_uint;
|
||||
use llvm;
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array};
|
||||
use trans::abi::{FnType, ArgType, Indirect};
|
||||
use trans::abi::{FnType, ArgType};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
|
||||
|
@ -143,7 +143,7 @@ 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.kind = Indirect;
|
||||
fty.ret.make_indirect(ccx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
// need to be fixed when PowerPC vector support is added.
|
||||
|
||||
use llvm::{Integer, Pointer, Float, Double, Struct, Array};
|
||||
use trans::abi::{FnType, ArgType, Indirect};
|
||||
use trans::abi::{FnType, ArgType};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
|
||||
|
@ -158,7 +158,7 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
|||
|
||||
// The PowerPC64 big endian ABI doesn't return aggregates in registers
|
||||
if ccx.sess().target.target.target_endian == "big" {
|
||||
ret.kind = Indirect;
|
||||
ret.make_indirect(ccx);
|
||||
}
|
||||
|
||||
if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ret.ty) {
|
||||
|
@ -182,7 +182,7 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
|
|||
return;
|
||||
}
|
||||
|
||||
ret.kind = Indirect;
|
||||
ret.make_indirect(ccx);
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use llvm::*;
|
||||
use trans::abi::{FnType, Indirect, Ignore};
|
||||
use trans::abi::FnType;
|
||||
use trans::type_::Type;
|
||||
use super::common::*;
|
||||
use super::machine::*;
|
||||
|
@ -30,20 +30,20 @@ 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.make_indirect(ccx)
|
||||
}
|
||||
} else {
|
||||
fty.ret.kind = Indirect;
|
||||
fty.ret.make_indirect(ccx);
|
||||
}
|
||||
}
|
||||
|
||||
for arg in &mut fty.args {
|
||||
if arg.ty.kind() == Struct {
|
||||
if llsize_of_alloc(ccx, arg.ty) == 0 {
|
||||
arg.kind = Ignore;
|
||||
arg.ignore();
|
||||
} else {
|
||||
arg.kind = Indirect;
|
||||
arg.attr = Some(Attribute::ByVal);
|
||||
arg.make_indirect(ccx);
|
||||
arg.attrs.set(Attribute::ByVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use self::RegClass::*;
|
|||
|
||||
use llvm::{Integer, Pointer, Float, Double};
|
||||
use llvm::{Struct, Array, Attribute, Vector};
|
||||
use trans::abi::{ArgType, FnType, Indirect};
|
||||
use trans::abi::{ArgType, FnType};
|
||||
use trans::context::CrateContext;
|
||||
use trans::type_::Type;
|
||||
|
||||
|
@ -393,8 +393,10 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
|||
if !arg.ty.is_reg_ty() {
|
||||
let cls = classify_ty(arg.ty);
|
||||
if is_mem_cls(&cls) {
|
||||
arg.kind = Indirect;
|
||||
arg.attr = ind_attr;
|
||||
arg.make_indirect(ccx);
|
||||
if let Some(attr) = ind_attr {
|
||||
arg.attrs.set(attr);
|
||||
}
|
||||
} else {
|
||||
arg.cast = Some(llreg_ty(ccx, &cls));
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use llvm::*;
|
||||
use super::common::*;
|
||||
use super::machine::*;
|
||||
use trans::abi::{ArgType, FnType, Indirect};
|
||||
use trans::abi::{ArgType, FnType};
|
||||
use trans::type_::Type;
|
||||
|
||||
// Win64 ABI: http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
|
||||
|
@ -24,7 +24,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
|||
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.make_indirect(ccx)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -113,7 +113,7 @@ pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
|
|||
attributes::from_fn_type(ccx, fn_type)
|
||||
} else {
|
||||
attributes::unwind(llfn, false);
|
||||
fty.llvm_attrs(ccx)
|
||||
fty.llvm_attrs()
|
||||
};
|
||||
|
||||
attrs.apply_llfn(llfn);
|
||||
|
|
|
@ -253,7 +253,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
llfn,
|
||||
&llargs_foreign[..],
|
||||
fn_type.cconv,
|
||||
Some(fn_type.llvm_attrs(ccx)),
|
||||
Some(fn_type.llvm_attrs()),
|
||||
call_debug_loc);
|
||||
|
||||
// If the function we just called does not use an outpointer,
|
||||
|
|
Loading…
Reference in New Issue