Skip to content

Commit f4ea709

Browse files
authored
Merge pull request rust-lang#135 from rust-lang/feature/byval-params
Add support for on_stack parameters
2 parents 1a9ae8d + dcc0853 commit f4ea709

File tree

6 files changed

+61
-28
lines changed

6 files changed

+61
-28
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/abi.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use gccjit::{ToRValue, Type};
1+
use gccjit::{ToLValue, ToRValue, Type};
22
use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods};
3+
use rustc_data_structures::stable_set::FxHashSet;
34
use rustc_middle::bug;
45
use rustc_middle::ty::Ty;
56
use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg, RegKind};
@@ -15,9 +16,21 @@ impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
1516
}
1617

1718
fn get_param(&mut self, index: usize) -> Self::Value {
18-
self.cx.current_func.borrow().expect("current func")
19-
.get_param(index as i32)
20-
.to_rvalue()
19+
let func = self.current_func();
20+
let param = func.get_param(index as i32);
21+
let on_stack =
22+
if let Some(on_stack_param_indices) = self.on_stack_function_params.borrow().get(&func) {
23+
on_stack_param_indices.contains(&index)
24+
}
25+
else {
26+
false
27+
};
28+
if on_stack {
29+
param.to_lvalue().get_address(None)
30+
}
31+
else {
32+
param.to_rvalue()
33+
}
2134
}
2235
}
2336

@@ -87,12 +100,13 @@ impl GccType for Reg {
87100

88101
pub trait FnAbiGccExt<'gcc, 'tcx> {
89102
// TODO(antoyo): return a function pointer type instead?
90-
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool);
103+
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>);
91104
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
92105
}
93106

94107
impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
95-
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool) {
108+
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>) {
109+
let mut on_stack_param_indices = FxHashSet::default();
96110
let args_capacity: usize = self.args.iter().map(|arg|
97111
if arg.pad.is_some() {
98112
1
@@ -144,17 +158,22 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
144158
unimplemented!();
145159
}
146160
PassMode::Cast(cast) => cast.gcc_type(cx),
147-
PassMode::Indirect { extra_attrs: None, .. } => cx.type_ptr_to(arg.memory_ty(cx)),
161+
PassMode::Indirect { extra_attrs: None, on_stack: true, .. } => {
162+
on_stack_param_indices.insert(argument_tys.len());
163+
arg.memory_ty(cx)
164+
},
165+
PassMode::Indirect { extra_attrs: None, on_stack: false, .. } => cx.type_ptr_to(arg.memory_ty(cx)),
148166
};
149167
argument_tys.push(arg_ty);
150168
}
151169

152-
(return_ty, argument_tys, self.c_variadic)
170+
(return_ty, argument_tys, self.c_variadic, on_stack_param_indices)
153171
}
154172

155173
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
156-
let (return_type, params, variadic) = self.gcc_type(cx);
174+
let (return_type, params, variadic, on_stack_param_indices) = self.gcc_type(cx);
157175
let pointer_type = cx.context.new_function_pointer_type(None, return_type, &params, variadic);
176+
cx.on_stack_params.borrow_mut().insert(pointer_type.dyncast_function_ptr_type().expect("function ptr type"), on_stack_param_indices);
158177
pointer_type
159178
}
160179
}

src/builder.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use rustc_codegen_ssa::traits::{
3030
OverflowOp,
3131
StaticBuilderMethods,
3232
};
33+
use rustc_data_structures::stable_set::FxHashSet;
3334
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
3435
use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
3536
use rustc_span::Span;
@@ -207,6 +208,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
207208
param_types.push(param);
208209
}
209210

211+
let mut on_stack_param_indices = FxHashSet::default();
212+
if let Some(indices) = self.on_stack_params.borrow().get(&gcc_func) {
213+
on_stack_param_indices = indices.clone();
214+
}
215+
210216
if all_args_match {
211217
return Cow::Borrowed(args);
212218
}
@@ -215,10 +221,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
215221
.into_iter()
216222
.zip(args.iter())
217223
.enumerate()
218-
.map(|(_i, (expected_ty, &actual_val))| {
224+
.map(|(index, (expected_ty, &actual_val))| {
219225
let actual_ty = actual_val.get_type();
220226
if expected_ty != actual_ty {
221-
self.bitcast(actual_val, expected_ty)
227+
if on_stack_param_indices.contains(&index) {
228+
actual_val.dereference(None).to_rvalue()
229+
}
230+
else {
231+
self.bitcast(actual_val, expected_ty)
232+
}
222233
}
223234
else {
224235
actual_val
@@ -946,14 +957,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
946957
}
947958

948959
/* Miscellaneous instructions */
949-
fn memcpy(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) {
950-
if flags.contains(MemFlags::NONTEMPORAL) {
951-
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
952-
let val = self.load(src.get_type(), src, src_align);
953-
let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
954-
self.store_with_flags(val, ptr, dst_align, flags);
955-
return;
956-
}
960+
fn memcpy(&mut self, dst: RValue<'gcc>, _dst_align: Align, src: RValue<'gcc>, _src_align: Align, size: RValue<'gcc>, flags: MemFlags) {
961+
assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported");
957962
let size = self.intcast(size, self.type_size_t(), false);
958963
let _is_volatile = flags.contains(MemFlags::VOLATILE);
959964
let dst = self.pointercast(dst, self.type_i8p());

src/context.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::cell::{Cell, RefCell};
22

3-
use gccjit::{Block, CType, Context, Function, FunctionType, LValue, RValue, Struct, Type};
3+
use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, RValue, Struct, Type};
44
use rustc_codegen_ssa::base::wants_msvc_seh;
55
use rustc_codegen_ssa::traits::{
66
BackendTypes,
@@ -81,6 +81,12 @@ pub struct CodegenCx<'gcc, 'tcx> {
8181
/// Cache generated vtables
8282
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
8383

84+
// TODO(antoyo): improve the SSA API to not require those.
85+
// Mapping from function pointer type to indexes of on stack parameters.
86+
pub on_stack_params: RefCell<FxHashMap<FunctionPtrType<'gcc>, FxHashSet<usize>>>,
87+
// Mapping from function to indexes of on stack parameters.
88+
pub on_stack_function_params: RefCell<FxHashMap<Function<'gcc>, FxHashSet<usize>>>,
89+
8490
/// Cache of emitted const globals (value -> global)
8591
pub const_globals: RefCell<FxHashMap<RValue<'gcc>, RValue<'gcc>>>,
8692
/// Map from the address of a global variable (rvalue) to the global variable itself (lvalue).
@@ -208,6 +214,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
208214
linkage: Cell::new(FunctionType::Internal),
209215
instances: Default::default(),
210216
function_instances: Default::default(),
217+
on_stack_params: Default::default(),
218+
on_stack_function_params: Default::default(),
211219
vtables: Default::default(),
212220
const_globals: Default::default(),
213221
global_lvalues: Default::default(),

src/declare.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
8080
}
8181

8282
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> RValue<'gcc> {
83-
let (return_type, params, variadic) = fn_abi.gcc_type(self);
83+
let (return_type, params, variadic, on_stack_param_indices) = fn_abi.gcc_type(self);
8484
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &params, variadic);
85+
self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
8586
// FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
8687
unsafe { std::mem::transmute(func) }
8788
}

src/intrinsic/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -464,17 +464,17 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
464464
val.to_rvalue()
465465
};
466466
match self.mode {
467-
PassMode::Ignore => {}
467+
PassMode::Ignore => {},
468468
PassMode::Pair(..) => {
469469
OperandValue::Pair(next(), next()).store(bx, dst);
470-
}
470+
},
471471
PassMode::Indirect { extra_attrs: Some(_), .. } => {
472472
OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
473-
}
473+
},
474474
PassMode::Direct(_) | PassMode::Indirect { extra_attrs: None, .. } | PassMode::Cast(_) => {
475475
let next_arg = next();
476-
self.store(bx, next_arg.to_rvalue(), dst);
477-
}
476+
self.store(bx, next_arg, dst);
477+
},
478478
}
479479
}
480480
}

0 commit comments

Comments
 (0)