Merge pull request #326 from GuillaumeGomez/non-null
Add support for NonNull function attribute
This commit is contained in:
commit
c80fb4aaf0
78
src/abi.rs
78
src/abi.rs
@ -1,4 +1,4 @@
|
||||
use gccjit::{ToLValue, ToRValue, Type};
|
||||
use gccjit::{FnAttribute, ToLValue, ToRValue, Type};
|
||||
use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::bug;
|
||||
@ -96,14 +96,22 @@ impl GccType for Reg {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FnAbiGcc<'gcc> {
|
||||
pub return_type: Type<'gcc>,
|
||||
pub arguments_type: Vec<Type<'gcc>>,
|
||||
pub is_c_variadic: bool,
|
||||
pub on_stack_param_indices: FxHashSet<usize>,
|
||||
pub fn_attributes: Vec<FnAttribute<'gcc>>,
|
||||
}
|
||||
|
||||
pub trait FnAbiGccExt<'gcc, 'tcx> {
|
||||
// TODO(antoyo): return a function pointer type instead?
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>);
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc>;
|
||||
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>) {
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc> {
|
||||
let mut on_stack_param_indices = FxHashSet::default();
|
||||
|
||||
// This capacity calculation is approximate.
|
||||
@ -111,7 +119,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
self.args.len() + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 }
|
||||
);
|
||||
|
||||
let return_ty =
|
||||
let return_type =
|
||||
match self.ret.mode {
|
||||
PassMode::Ignore => cx.type_void(),
|
||||
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx),
|
||||
@ -121,19 +129,23 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
cx.type_void()
|
||||
}
|
||||
};
|
||||
let mut non_null_args = Vec::new();
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
let apply_attrs = |ty: Type<'gcc>, attrs: &ArgAttributes| {
|
||||
if cx.sess().opts.optimize != config::OptLevel::No
|
||||
&& attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias)
|
||||
{
|
||||
ty.make_restrict()
|
||||
} else {
|
||||
ty
|
||||
let mut apply_attrs = |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| {
|
||||
if cx.sess().opts.optimize == config::OptLevel::No {
|
||||
return ty;
|
||||
}
|
||||
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) {
|
||||
ty = ty.make_restrict()
|
||||
}
|
||||
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) {
|
||||
non_null_args.push(arg_index as i32 + 1);
|
||||
}
|
||||
ty
|
||||
};
|
||||
#[cfg(not(feature = "master"))]
|
||||
let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes| {
|
||||
let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| {
|
||||
ty
|
||||
};
|
||||
|
||||
@ -141,8 +153,9 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
let arg_ty = match arg.mode {
|
||||
PassMode::Ignore => continue,
|
||||
PassMode::Pair(a, b) => {
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a));
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b));
|
||||
let arg_pos = argument_tys.len();
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a, arg_pos));
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b, arg_pos + 1));
|
||||
continue;
|
||||
}
|
||||
PassMode::Cast { ref cast, pad_i32 } => {
|
||||
@ -151,31 +164,54 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
argument_tys.push(Reg::i32().gcc_type(cx));
|
||||
}
|
||||
let ty = cast.gcc_type(cx);
|
||||
apply_attrs(ty, &cast.attrs)
|
||||
apply_attrs(ty, &cast.attrs, argument_tys.len())
|
||||
}
|
||||
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => {
|
||||
// This is a "byval" argument, so we don't apply the `restrict` attribute on it.
|
||||
on_stack_param_indices.insert(argument_tys.len());
|
||||
arg.memory_ty(cx)
|
||||
},
|
||||
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs),
|
||||
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()),
|
||||
PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
|
||||
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs)
|
||||
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len())
|
||||
}
|
||||
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
|
||||
assert!(!on_stack);
|
||||
apply_attrs(apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs), &meta_attrs)
|
||||
let ty = apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len());
|
||||
apply_attrs(ty, &meta_attrs, argument_tys.len())
|
||||
}
|
||||
};
|
||||
argument_tys.push(arg_ty);
|
||||
}
|
||||
|
||||
(return_ty, argument_tys, self.c_variadic, on_stack_param_indices)
|
||||
#[cfg(feature = "master")]
|
||||
let fn_attrs = if non_null_args.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
vec![FnAttribute::NonNull(non_null_args)]
|
||||
};
|
||||
#[cfg(not(feature = "master"))]
|
||||
let fn_attrs = Vec::new();
|
||||
|
||||
FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type: argument_tys,
|
||||
is_c_variadic: self.c_variadic,
|
||||
on_stack_param_indices,
|
||||
fn_attributes: fn_attrs,
|
||||
}
|
||||
}
|
||||
|
||||
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
|
||||
let (return_type, params, variadic, on_stack_param_indices) = self.gcc_type(cx);
|
||||
let pointer_type = cx.context.new_function_pointer_type(None, return_type, ¶ms, variadic);
|
||||
// FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
|
||||
let FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type,
|
||||
is_c_variadic,
|
||||
on_stack_param_indices,
|
||||
..
|
||||
} = self.gcc_type(cx);
|
||||
let pointer_type = cx.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic);
|
||||
cx.on_stack_params.borrow_mut().insert(pointer_type.dyncast_function_ptr_type().expect("function ptr type"), on_stack_param_indices);
|
||||
pointer_type
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use rustc_middle::ty::Ty;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
|
||||
use crate::abi::FnAbiGccExt;
|
||||
use crate::abi::{FnAbiGcc, FnAbiGccExt};
|
||||
use crate::context::CodegenCx;
|
||||
use crate::intrinsic::llvm;
|
||||
|
||||
@ -80,9 +80,18 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> {
|
||||
let (return_type, params, variadic, on_stack_param_indices) = fn_abi.gcc_type(self);
|
||||
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, ¶ms, variadic);
|
||||
let FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type,
|
||||
is_c_variadic,
|
||||
on_stack_param_indices,
|
||||
fn_attributes,
|
||||
} = fn_abi.gcc_type(self);
|
||||
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &arguments_type, is_c_variadic);
|
||||
self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
|
||||
for fn_attr in fn_attributes {
|
||||
func.add_attribute(fn_attr);
|
||||
}
|
||||
func
|
||||
}
|
||||
|
||||
|
@ -1197,7 +1197,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut
|
||||
#[cfg(feature="master")]
|
||||
fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig: ty::PolyFnSig<'tcx>, codegen: &mut dyn FnMut(Builder<'a, 'gcc, 'tcx>)) -> (Type<'gcc>, Function<'gcc>) {
|
||||
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
|
||||
let (typ, _, _, _) = fn_abi.gcc_type(cx);
|
||||
let return_type = fn_abi.gcc_type(cx).return_type;
|
||||
// FIXME(eddyb) find a nicer way to do this.
|
||||
cx.linkage.set(FunctionType::Internal);
|
||||
let func = cx.declare_fn(name, fn_abi);
|
||||
@ -1207,5 +1207,5 @@ fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig
|
||||
let block = Builder::append_block(cx, func_val, "entry-block");
|
||||
let bx = Builder::build(cx, block);
|
||||
codegen(bx);
|
||||
(typ, func)
|
||||
(return_type, func)
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||
|
||||
use crate::abi::{FnAbiGccExt, GccType};
|
||||
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
|
||||
use crate::context::CodegenCx;
|
||||
use crate::type_::struct_fields;
|
||||
|
||||
@ -372,7 +372,13 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
|
||||
let (return_type, param_types, variadic, _) = fn_abi.gcc_type(self);
|
||||
self.context.new_function_pointer_type(None, return_type, ¶m_types, variadic)
|
||||
// FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
|
||||
let FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type,
|
||||
is_c_variadic,
|
||||
..
|
||||
} = fn_abi.gcc_type(self);
|
||||
self.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user