Skip to content

Commit 8db7f6f

Browse files
Add support for NonNull function attribute
1 parent 03bcfff commit 8db7f6f

File tree

4 files changed

+43
-22
lines changed

4 files changed

+43
-22
lines changed

src/abi.rs

+35-19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use gccjit::{ToLValue, ToRValue, Type};
1+
use gccjit::{FnAttribute, ToLValue, ToRValue, Type};
22
use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods};
33
use rustc_data_structures::fx::FxHashSet;
44
use rustc_middle::bug;
@@ -97,12 +97,12 @@ impl GccType for Reg {
9797

9898
pub trait FnAbiGccExt<'gcc, 'tcx> {
9999
// TODO(antoyo): return a function pointer type instead?
100-
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>);
100+
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>, Vec<FnAttribute<'gcc>>);
101101
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
102102
}
103103

104104
impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
105-
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>) {
105+
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>, Vec<FnAttribute<'gcc>>) {
106106
let mut on_stack_param_indices = FxHashSet::default();
107107

108108
// This capacity calculation is approximate.
@@ -120,28 +120,33 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
120120
cx.type_void()
121121
}
122122
};
123+
let mut non_null_args = Vec::new();
123124

124125
#[cfg(feature = "master")]
125-
let apply_attrs = |ty: Type<'gcc>, attrs: &ArgAttributes| {
126-
if cx.sess().opts.optimize != config::OptLevel::No
127-
&& attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias)
128-
{
129-
ty.make_restrict()
130-
} else {
131-
ty
126+
let mut apply_attrs = |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| {
127+
if cx.sess().opts.optimize == config::OptLevel::No {
128+
return ty;
132129
}
130+
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) {
131+
ty = ty.make_restrict()
132+
}
133+
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) {
134+
non_null_args.push(arg_index as i32 + 1);
135+
}
136+
ty
133137
};
134138
#[cfg(not(feature = "master"))]
135-
let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes| {
139+
let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| {
136140
ty
137141
};
138142

139143
for arg in self.args.iter() {
140144
let arg_ty = match arg.mode {
141145
PassMode::Ignore => continue,
142146
PassMode::Pair(a, b) => {
143-
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0, true), &a));
144-
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1, true), &b));
147+
let arg_pos = argument_tys.len();
148+
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0, true), &a, arg_pos));
149+
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1, true), &b, arg_pos + 1));
145150
continue;
146151
}
147152
PassMode::Cast(ref cast, pad_i32) => {
@@ -150,30 +155,41 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
150155
argument_tys.push(Reg::i32().gcc_type(cx));
151156
}
152157
let ty = cast.gcc_type(cx);
153-
apply_attrs(ty, &cast.attrs)
158+
apply_attrs(ty, &cast.attrs, argument_tys.len())
154159
}
155160
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: true } => {
156161
// This is a "byval" argument, so we don't apply the `restrict` attribute on it.
157162
on_stack_param_indices.insert(argument_tys.len());
158163
arg.memory_ty(cx)
159164
},
160-
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs),
165+
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()),
161166
PassMode::Indirect { attrs, extra_attrs: None, on_stack: false } => {
162-
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs)
167+
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len())
163168
}
164169
PassMode::Indirect { attrs, extra_attrs: Some(extra_attrs), on_stack } => {
165170
assert!(!on_stack);
166-
apply_attrs(apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs), &extra_attrs)
171+
let ty = apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len());
172+
apply_attrs(ty, &extra_attrs, argument_tys.len())
167173
}
168174
};
169175
argument_tys.push(arg_ty);
170176
}
171177

172-
(return_ty, argument_tys, self.c_variadic, on_stack_param_indices)
178+
#[cfg(feature = "master")]
179+
let fn_attrs = if non_null_args.is_empty() {
180+
Vec::new()
181+
} else {
182+
vec![FnAttribute::NonNull(non_null_args)]
183+
};
184+
#[cfg(not(feature = "master"))]
185+
let fn_attrs = Vec::new();
186+
187+
(return_ty, argument_tys, self.c_variadic, on_stack_param_indices, fn_attrs)
173188
}
174189

175190
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
176-
let (return_type, params, variadic, on_stack_param_indices) = self.gcc_type(cx);
191+
// FIXME: Should we do something with `fn_attrs`?
192+
let (return_type, params, variadic, on_stack_param_indices, _fn_attrs) = self.gcc_type(cx);
177193
let pointer_type = cx.context.new_function_pointer_type(None, return_type, &params, variadic);
178194
cx.on_stack_params.borrow_mut().insert(pointer_type.dyncast_function_ptr_type().expect("function ptr type"), on_stack_param_indices);
179195
pointer_type

src/declare.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
8080
}
8181

8282
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> {
83-
let (return_type, params, variadic, on_stack_param_indices) = fn_abi.gcc_type(self);
83+
let (return_type, params, variadic, on_stack_param_indices, fn_attrs) = fn_abi.gcc_type(self);
8484
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &params, variadic);
8585
self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
86+
// We need to handle `nonnull` here where we still have access to function args.
87+
for fn_attr in fn_attrs {
88+
func.add_attribute(fn_attr);
89+
}
8690
func
8791
}
8892

src/intrinsic/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut
11971197
#[cfg(feature="master")]
11981198
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>) {
11991199
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
1200-
let (typ, _, _, _) = fn_abi.gcc_type(cx);
1200+
let (typ, _, _, _, _) = fn_abi.gcc_type(cx);
12011201
// FIXME(eddyb) find a nicer way to do this.
12021202
cx.linkage.set(FunctionType::Internal);
12031203
let func = cx.declare_fn(name, fn_abi);

src/type_of.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,8 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
384384
}
385385

386386
fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
387-
let (return_type, param_types, variadic, _) = fn_abi.gcc_type(self);
387+
// // FIXME: Should we do something with `fn_attrs`?
388+
let (return_type, param_types, variadic, _, _fn_attrs) = fn_abi.gcc_type(self);
388389
self.context.new_function_pointer_type(None, return_type, &param_types, variadic)
389390
}
390391
}

0 commit comments

Comments
 (0)