提交 de5f8244 编写于 作者: E Eduard Burtescu

trans: Use llvm::Attributes directly in ArgTy.

上级 c7172a99
......@@ -185,7 +185,7 @@ pub enum DLLStorageClassTypes {
}
}
#[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_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 @@ pub fn new<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
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 @@ pub fn new<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}
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 @@ pub fn new<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
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 @@ pub fn new<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
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 @@ pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
}
}
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;
}
// skip padding
if arg.pad.is_some() { i += 1; }
if let Some(attr) = arg.attr {
attrs.arg(i).set(attr);
if !arg.is_ignore() {
if arg.pad.is_some() { i += 1; }
*attrs.arg(i) = arg.attrs;
i += 1;
}
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 @@
// 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 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 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 @@ fn x86_64_ty<F>(ccx: &CrateContext,
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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册