Skip to content

Commit 096f14d

Browse files
Add support for NonNull function attribute
1 parent 4dce75f commit 096f14d

File tree

4 files changed

+43
-22
lines changed

4 files changed

+43
-22
lines changed

Diff for: 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;
@@ -98,12 +98,12 @@ impl GccType for Reg {
9898

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

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

109109
// This capacity calculation is approximate.
@@ -121,28 +121,33 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
121121
cx.type_void()
122122
}
123123
};
124+
let mut non_null_args = Vec::new();
124125

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

140144
for arg in self.args.iter() {
141145
let arg_ty = match arg.mode {
142146
PassMode::Ignore => continue,
143147
PassMode::Pair(a, b) => {
144-
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a));
145-
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b));
148+
let arg_pos = argument_tys.len();
149+
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a, arg_pos));
150+
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b, arg_pos + 1));
146151
continue;
147152
}
148153
PassMode::Cast { ref cast, pad_i32 } => {
@@ -151,30 +156,41 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
151156
argument_tys.push(Reg::i32().gcc_type(cx));
152157
}
153158
let ty = cast.gcc_type(cx);
154-
apply_attrs(ty, &cast.attrs)
159+
apply_attrs(ty, &cast.attrs, argument_tys.len())
155160
}
156161
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => {
157162
// This is a "byval" argument, so we don't apply the `restrict` attribute on it.
158163
on_stack_param_indices.insert(argument_tys.len());
159164
arg.memory_ty(cx)
160165
},
161-
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs),
166+
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()),
162167
PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
163-
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs)
168+
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len())
164169
}
165170
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
166171
assert!(!on_stack);
167-
apply_attrs(apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs), &meta_attrs)
172+
let ty = apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len());
173+
apply_attrs(ty, &meta_attrs, argument_tys.len())
168174
}
169175
};
170176
argument_tys.push(arg_ty);
171177
}
172178

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

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

Diff for: 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

Diff for: 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);

Diff for: src/type_of.rs

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

374374
fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
375-
let (return_type, param_types, variadic, _) = fn_abi.gcc_type(self);
375+
// // FIXME: Should we do something with `fn_attrs`?
376+
let (return_type, param_types, variadic, _, _fn_attrs) = fn_abi.gcc_type(self);
376377
self.context.new_function_pointer_type(None, return_type, &param_types, variadic)
377378
}
378379
}

0 commit comments

Comments
 (0)