Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions compiler/rustc_codegen_gcc/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{
BackendTypes, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods,
LayoutTypeCodegenMethods, OverflowOp, StaticBuilderMethods,
LayoutTypeCodegenMethods, OverflowOp, ReturnSlot, StaticBuilderMethods,
};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::bug;
Expand Down Expand Up @@ -603,6 +603,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
fn_attrs: Option<&CodegenFnAttrs>,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
func: RValue<'gcc>,
return_slot: ReturnSlot<RValue<'gcc>>,
args: &[RValue<'gcc>],
then: Block<'gcc>,
catch: Block<'gcc>,
Expand All @@ -613,7 +614,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {

let current_block = self.block;
self.block = try_block;
let call = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); // FIXME(antoyo): use funclet here?
// FIXME(antoyo): use funclet here?
let call = self.call(typ, fn_attrs, fn_abi, func, return_slot, args, None, instance);
self.block = current_block;

let return_value =
Expand Down Expand Up @@ -641,13 +643,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
fn_attrs: Option<&CodegenFnAttrs>,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
func: RValue<'gcc>,
return_slot: ReturnSlot<RValue<'gcc>>,
args: &[RValue<'gcc>],
then: Block<'gcc>,
catch: Block<'gcc>,
_funclet: Option<&Funclet>,
instance: Option<Instance<'tcx>>,
) -> RValue<'gcc> {
let call_site = self.call(typ, fn_attrs, fn_abi, func, args, None, instance);
let call_site = self.call(typ, fn_attrs, fn_abi, func, return_slot, args, None, instance);
let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
self.llbb().end_with_conditional(self.location, condition, then, catch);
if let Some(_fn_abi) = fn_abi {
Expand Down Expand Up @@ -1772,19 +1775,30 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
_fn_attrs: Option<&CodegenFnAttrs>,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
func: RValue<'gcc>,
return_slot: ReturnSlot<RValue<'gcc>>,
args: &[RValue<'gcc>],
funclet: Option<&Funclet>,
_instance: Option<Instance<'tcx>>,
) -> RValue<'gcc> {
// FIXME: change this in the `rustc_codegen_gcc` repo after the sync, to use the `libgccjit` indirect return suppport.
let args = match return_slot {
ReturnSlot::Direct => args.to_vec(),
ReturnSlot::Indirect(sret_ptr) => {
let mut args = args.to_vec();
// Prepend the indirect return pointer
args.insert(0, sret_ptr);
args
}
};
// FIXME(antoyo): remove when having a proper API.
let gcc_func = unsafe { std::mem::transmute::<RValue<'gcc>, Function<'gcc>>(func) };
let call = if self.functions.borrow().values().any(|value| *value == gcc_func) {
// FIXME(antoyo): remove when the API supports a different type for functions.
let func: Function<'gcc> = self.cx.rvalue_as_function(func);
self.function_call(func, args, funclet)
self.function_call(func, &args, funclet)
} else {
// If it's a not function that was defined, it's a function pointer.
self.function_ptr_call(typ, fn_abi, func, args, funclet)
self.function_ptr_call(typ, fn_abi, func, &args, funclet)
};
if let Some(_fn_abi) = fn_abi {
// FIXME(bjorn3): Apply function attributes
Expand All @@ -1798,6 +1812,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
_fn_attrs: Option<&CodegenFnAttrs>,
_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
_llfn: Self::Value,
_return_slot: ReturnSlot<Self::Value>,
_args: &[Self::Value],
_funclet: Option<&Self::Funclet>,
_instance: Option<Instance<'tcx>>,
Expand Down
35 changes: 28 additions & 7 deletions compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
use rustc_codegen_ssa::traits::MiscCodegenMethods;
use rustc_codegen_ssa::traits::{
ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods,
IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods,
IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, ReturnSlot,
};
use rustc_codegen_ssa::{MemFlags, RetagInfo};
use rustc_data_structures::fx::FxHashSet;
Expand Down Expand Up @@ -656,7 +656,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
}

// FIXME directly use the llvm intrinsic adjustment functions here
let llret = self.call(fn_ty, None, None, fn_ptr, &call_args, None, None);
let llret =
self.call(fn_ty, None, None, fn_ptr, ReturnSlot::Direct, &call_args, None, None);
if is_cleanup {
self.apply_attrs_to_cleanup_callsite(llret);
}
Expand All @@ -667,7 +668,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
fn abort(&mut self) {
let func = self.context.get_builtin_function("abort");
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
self.call(self.type_void(), None, None, func, &[], None, None);
self.call(self.type_void(), None, None, func, ReturnSlot::Direct, &[], None, None);
}

fn assume(&mut self, value: Self::Value) {
Expand Down Expand Up @@ -1348,7 +1349,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
let param_type = bx.u8_type.make_pointer();
let fn_type =
bx.context.new_function_pointer_type(None, bx.type_void(), &[param_type], false);
bx.call(fn_type, None, None, try_func, &[data], None, None);
bx.call(fn_type, None, None, try_func, ReturnSlot::Direct, &[data], None, None);
// Return 0 unconditionally from the intrinsic call;
// we can never unwind.
OperandValue::Immediate(bx.const_bool(false)).store(bx, dest);
Expand Down Expand Up @@ -1421,21 +1422,41 @@ fn codegen_gnu_try<'gcc, 'tcx>(
let zero = bx.cx.context.new_rvalue_zero(bx.int_type);
let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, None);
bx.call(catch_ty, None, None, catch_func, ReturnSlot::Direct, &[data, ptr], None, None);
bx.ret(bx.const_bool(true));

// NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not
// generate a try/catch.
// FIXME(antoyo): add a check in the libgccjit API to prevent this.
bx.switch_to_block(current_block);
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None);
bx.invoke(
try_func_ty,
None,
None,
try_func,
ReturnSlot::Direct,
&[data],
then,
catch,
None,
None,
);
});

let func = unsafe { std::mem::transmute::<Function<'gcc>, RValue<'gcc>>(func) };

// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None, None);
let ret = bx.call(
llty,
None,
None,
func,
ReturnSlot::Direct,
&[try_func, data, catch_func],
None,
None,
);
OperandValue::Immediate(ret).store(bx, dest);
}

Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,9 +562,20 @@ pub(crate) fn inline_asm_call<'ll>(
assert!(catch_funclet.is_none());
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None)
} else if let Some((catch, funclet)) = catch_funclet {
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None)
bx.invoke(
fty,
None,
None,
v,
ReturnSlot::Direct,
inputs,
dest.unwrap(),
catch,
funclet,
None,
)
} else {
bx.call(fty, None, None, v, inputs, None, None)
bx.call(fty, None, None, v, ReturnSlot::Direct, inputs, None, None)
};

// Store mark in a metadata node so we can map LLVM errors
Expand Down
44 changes: 37 additions & 7 deletions compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,15 +451,25 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn_attrs: Option<&CodegenFnAttrs>,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
llfn: &'ll Value,
return_slot: ReturnSlot<&'ll Value>,
args: &[&'ll Value],
then: &'ll BasicBlock,
catch: &'ll BasicBlock,
funclet: Option<&Funclet<'ll>>,
instance: Option<Instance<'tcx>>,
) -> &'ll Value {
// If this function returns indirectly (`PassMode::Indirect`),
// the `return_slot` should be the first argument.
let args = match return_slot {
ReturnSlot::Direct => args.to_vec(),
ReturnSlot::Indirect(sret_ptr) => {
let mut args = args.to_vec();
args.insert(0, sret_ptr);
args
}
};
debug!("invoke {:?} with args ({:?})", llfn, args);

let args = self.check_call("invoke", llty, llfn, args);
let args = self.check_call("invoke", llty, llfn, &args);
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
if let Some(funclet_bundle) = funclet_bundle {
Expand Down Expand Up @@ -1452,13 +1462,23 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
caller_attrs: Option<&CodegenFnAttrs>,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
llfn: &'ll Value,
return_slot: ReturnSlot<&'ll Value>,
args: &[&'ll Value],
funclet: Option<&Funclet<'ll>>,
callee_instance: Option<Instance<'tcx>>,
) -> &'ll Value {
// If this function returns indirectly (`PassMode::Indirect`),
// the `return_slot` should be the first argument.
let args = match return_slot {
ReturnSlot::Direct => args.to_vec(),
ReturnSlot::Indirect(sret_ptr) => {
let mut args = args.to_vec();
args.insert(0, sret_ptr);
args
}
};
debug!("call {:?} with args ({:?})", llfn, args);

let args = self.check_call("call", llty, llfn, args);
let args = self.check_call("call", llty, llfn, &args);
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
if let Some(funclet_bundle) = funclet_bundle {
Expand Down Expand Up @@ -1519,12 +1539,21 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
caller_attrs: Option<&CodegenFnAttrs>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
llfn: Self::Value,
return_slot: ReturnSlot<Self::Value>,
args: &[Self::Value],
funclet: Option<&Self::Funclet>,
callee_instance: Option<Instance<'tcx>>,
) {
let call =
self.call(llty, caller_attrs, Some(fn_abi), llfn, args, funclet, callee_instance);
let call = self.call(
llty,
caller_attrs,
Some(fn_abi),
llfn,
return_slot,
args,
funclet,
callee_instance,
);
llvm::LLVMSetTailCallKind(call, llvm::TailCallKind::MustTail);

match &fn_abi.ret.mode {
Expand Down Expand Up @@ -1819,7 +1848,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
args: &[&'ll Value],
) -> &'ll Value {
let (ty, f) = self.cx.get_intrinsic(base_name.into(), type_params);
self.call(ty, None, None, f, args, None, None)
// No LLVM intrinsic returns its data indirectly (via `sret`).
self.call(ty, None, None, f, ReturnSlot::Direct, args, None, None)
}

fn call_lifetime_intrinsic(&mut self, intrinsic: &'static str, ptr: &'ll Value, size: Size) {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/builder/autodiff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::mir::IntrinsicResult;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceValue;
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods};
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, ReturnSlot};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir::attrs::RustcAutodiff;
use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt, TypingEnv};
Expand Down Expand Up @@ -377,7 +377,7 @@ pub(crate) fn generate_enzyme_call<'ll, 'tcx>(
crate::typetree::add_tt(&bx, fn_to_diff, fnc_tree);
}

let call = bx.call(enzyme_ty, None, None, ad_fn, &args, None, None);
let call = bx.call(enzyme_ty, None, None, ad_fn, ReturnSlot::Direct, &args, None, None);

let fn_ret_ty = bx.cx.val_ty(call);
if fn_ret_ty == bx.cx.type_void() || fn_ret_ty == bx.cx.type_struct(&[], false) {
Expand Down
32 changes: 25 additions & 7 deletions compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_abi::Align;
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods};
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, ReturnSlot};
use rustc_middle::bug;
use rustc_middle::ty::offload_meta::{MappingFlags, OffloadMetadata, OffloadSize};

Expand Down Expand Up @@ -109,9 +109,18 @@ pub(crate) fn register_offload<'ll>(cx: &CodegenCx<'ll, '_>) {
// }
let bb = Builder::append_block(cx, desc_reg_fn, "entry");
let mut a = Builder::build(cx, bb);
a.call(reg_lib_decl, None, None, register_lib, &[omp_descriptor], None, None);
a.call(init_ty, None, None, init_rtls, &[], None, None);
a.call(atexit, None, None, atexit_fn, &[desc_unreg_fn], None, None);
a.call(
reg_lib_decl,
None,
None,
register_lib,
ReturnSlot::Direct,
&[omp_descriptor],
None,
None,
);
a.call(init_ty, None, None, init_rtls, ReturnSlot::Direct, &[], None, None);
a.call(atexit, None, None, atexit_fn, ReturnSlot::Direct, &[desc_unreg_fn], None, None);
a.ret_void();

// define internal void @.omp_offloading.descriptor_unreg() section ".text.startup" {
Expand All @@ -121,7 +130,16 @@ pub(crate) fn register_offload<'ll>(cx: &CodegenCx<'ll, '_>) {
// }
let bb = Builder::append_block(cx, desc_unreg_fn, "entry");
let mut a = Builder::build(cx, bb);
a.call(reg_lib_decl, None, None, unregister_lib, &[omp_descriptor], None, None);
a.call(
reg_lib_decl,
None,
None,
unregister_lib,
ReturnSlot::Direct,
&[omp_descriptor],
None,
None,
);
a.ret_void();

// @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.omp_offloading.descriptor_reg, ptr null }]
Expand Down Expand Up @@ -740,7 +758,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>(
let num_args = cx.get_const_i32(num_args);
let args =
vec![s_ident_t, i64_max, num_args, geps[0], geps[1], geps[2], o_type, nullptr, nullptr];
builder.call(fn_ty, None, None, fn_to_call, &args, None, None);
builder.call(fn_ty, None, None, fn_to_call, ReturnSlot::Direct, &args, None, None);
}

// Step 2)
Expand Down Expand Up @@ -784,7 +802,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>(
region_id,
a5,
];
builder.call(tgt_target_kernel_ty, None, None, tgt_decl, &args, None, None);
builder.call(tgt_target_kernel_ty, None, None, tgt_decl, ReturnSlot::Direct, &args, None, None);
// %41 = call i32 @__tgt_target_kernel(ptr @1, i64 -1, i32 2097152, i32 256, ptr @.kernel_1.region_id, ptr %kernel_args)

// Step 4)
Expand Down
Loading
Loading