Skip to content

Commit c80fb4a

Browse files
authored
Merge pull request #326 from GuillaumeGomez/non-null
Add support for NonNull function attribute
2 parents 4dce75f + 0348a5f commit c80fb4a

File tree

4 files changed

+80
-29
lines changed

4 files changed

+80
-29
lines changed

src/abi.rs

+57-21
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;
@@ -96,22 +96,30 @@ impl GccType for Reg {
9696
}
9797
}
9898

99+
pub struct FnAbiGcc<'gcc> {
100+
pub return_type: Type<'gcc>,
101+
pub arguments_type: Vec<Type<'gcc>>,
102+
pub is_c_variadic: bool,
103+
pub on_stack_param_indices: FxHashSet<usize>,
104+
pub fn_attributes: Vec<FnAttribute<'gcc>>,
105+
}
106+
99107
pub trait FnAbiGccExt<'gcc, 'tcx> {
100108
// 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>);
109+
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc>;
102110
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
103111
}
104112

105113
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>) {
114+
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc> {
107115
let mut on_stack_param_indices = FxHashSet::default();
108116

109117
// This capacity calculation is approximate.
110118
let mut argument_tys = Vec::with_capacity(
111119
self.args.len() + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 }
112120
);
113121

114-
let return_ty =
122+
let return_type =
115123
match self.ret.mode {
116124
PassMode::Ignore => cx.type_void(),
117125
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx),
@@ -121,28 +129,33 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
121129
cx.type_void()
122130
}
123131
};
132+
let mut non_null_args = Vec::new();
124133

125134
#[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
135+
let mut apply_attrs = |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| {
136+
if cx.sess().opts.optimize == config::OptLevel::No {
137+
return ty;
138+
}
139+
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) {
140+
ty = ty.make_restrict()
133141
}
142+
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) {
143+
non_null_args.push(arg_index as i32 + 1);
144+
}
145+
ty
134146
};
135147
#[cfg(not(feature = "master"))]
136-
let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes| {
148+
let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| {
137149
ty
138150
};
139151

140152
for arg in self.args.iter() {
141153
let arg_ty = match arg.mode {
142154
PassMode::Ignore => continue,
143155
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));
156+
let arg_pos = argument_tys.len();
157+
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a, arg_pos));
158+
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b, arg_pos + 1));
146159
continue;
147160
}
148161
PassMode::Cast { ref cast, pad_i32 } => {
@@ -151,31 +164,54 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
151164
argument_tys.push(Reg::i32().gcc_type(cx));
152165
}
153166
let ty = cast.gcc_type(cx);
154-
apply_attrs(ty, &cast.attrs)
167+
apply_attrs(ty, &cast.attrs, argument_tys.len())
155168
}
156169
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => {
157170
// This is a "byval" argument, so we don't apply the `restrict` attribute on it.
158171
on_stack_param_indices.insert(argument_tys.len());
159172
arg.memory_ty(cx)
160173
},
161-
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs),
174+
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()),
162175
PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
163-
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs)
176+
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len())
164177
}
165178
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
166179
assert!(!on_stack);
167-
apply_attrs(apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs), &meta_attrs)
180+
let ty = apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len());
181+
apply_attrs(ty, &meta_attrs, argument_tys.len())
168182
}
169183
};
170184
argument_tys.push(arg_ty);
171185
}
172186

173-
(return_ty, argument_tys, self.c_variadic, on_stack_param_indices)
187+
#[cfg(feature = "master")]
188+
let fn_attrs = if non_null_args.is_empty() {
189+
Vec::new()
190+
} else {
191+
vec![FnAttribute::NonNull(non_null_args)]
192+
};
193+
#[cfg(not(feature = "master"))]
194+
let fn_attrs = Vec::new();
195+
196+
FnAbiGcc {
197+
return_type,
198+
arguments_type: argument_tys,
199+
is_c_variadic: self.c_variadic,
200+
on_stack_param_indices,
201+
fn_attributes: fn_attrs,
202+
}
174203
}
175204

176205
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);
178-
let pointer_type = cx.context.new_function_pointer_type(None, return_type, &params, variadic);
206+
// FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
207+
let FnAbiGcc {
208+
return_type,
209+
arguments_type,
210+
is_c_variadic,
211+
on_stack_param_indices,
212+
..
213+
} = self.gcc_type(cx);
214+
let pointer_type = cx.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic);
179215
cx.on_stack_params.borrow_mut().insert(pointer_type.dyncast_function_ptr_type().expect("function ptr type"), on_stack_param_indices);
180216
pointer_type
181217
}

src/declare.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_middle::ty::Ty;
66
use rustc_span::Symbol;
77
use rustc_target::abi::call::FnAbi;
88

9-
use crate::abi::FnAbiGccExt;
9+
use crate::abi::{FnAbiGcc, FnAbiGccExt};
1010
use crate::context::CodegenCx;
1111
use crate::intrinsic::llvm;
1212

@@ -80,9 +80,18 @@ 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);
84-
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &params, variadic);
83+
let FnAbiGcc {
84+
return_type,
85+
arguments_type,
86+
is_c_variadic,
87+
on_stack_param_indices,
88+
fn_attributes,
89+
} = fn_abi.gcc_type(self);
90+
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &arguments_type, is_c_variadic);
8591
self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
92+
for fn_attr in fn_attributes {
93+
func.add_attribute(fn_attr);
94+
}
8695
func
8796
}
8897

src/intrinsic/mod.rs

+2-2
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 return_type = fn_abi.gcc_type(cx).return_type;
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);
@@ -1207,5 +1207,5 @@ fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig
12071207
let block = Builder::append_block(cx, func_val, "entry-block");
12081208
let bx = Builder::build(cx, block);
12091209
codegen(bx);
1210-
(typ, func)
1210+
(return_type, func)
12111211
}

src/type_of.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
99
use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
1010
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
1111

12-
use crate::abi::{FnAbiGccExt, GccType};
12+
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
1313
use crate::context::CodegenCx;
1414
use crate::type_::struct_fields;
1515

@@ -372,7 +372,13 @@ 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);
376-
self.context.new_function_pointer_type(None, return_type, &param_types, variadic)
375+
// FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
376+
let FnAbiGcc {
377+
return_type,
378+
arguments_type,
379+
is_c_variadic,
380+
..
381+
} = fn_abi.gcc_type(self);
382+
self.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic)
377383
}
378384
}

0 commit comments

Comments
 (0)