1
Fork 0

Rollup merge of #93261 - bjorn3:cg_ssa_refactor6, r=cjgillot

Some unwinding related cg_ssa cleanups

These should make it a bit easier for alternative codegen backends to implement unwinding.
This commit is contained in:
Matthias Krüger 2022-01-28 15:20:24 +01:00 committed by GitHub
commit ada77e94ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 75 deletions

View file

@ -1256,7 +1256,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
aggregate_value aggregate_value
} }
fn landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>, _num_clauses: usize) -> RValue<'gcc> { fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
// TODO(antoyo)
}
fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> {
let field1 = self.context.new_field(None, self.u8_type, "landing_pad_field_1"); let field1 = self.context.new_field(None, self.u8_type, "landing_pad_field_1");
let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1"); let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1");
let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]); let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
@ -1267,11 +1271,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
// rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort. // rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort.
} }
fn set_cleanup(&mut self, _landing_pad: RValue<'gcc>) { fn resume(&mut self, _exn: RValue<'gcc>) {
// TODO(antoyo)
}
fn resume(&mut self, _exn: RValue<'gcc>) -> RValue<'gcc> {
unimplemented!(); unimplemented!();
} }
@ -1279,7 +1279,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
unimplemented!(); unimplemented!();
} }
fn cleanup_ret(&mut self, _funclet: &Funclet, _unwind: Option<Block<'gcc>>) -> RValue<'gcc> { fn cleanup_ret(&mut self, _funclet: &Funclet, _unwind: Option<Block<'gcc>>) {
unimplemented!(); unimplemented!();
} }
@ -1287,18 +1287,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
unimplemented!(); unimplemented!();
} }
fn catch_switch(&mut self, _parent: Option<RValue<'gcc>>, _unwind: Option<Block<'gcc>>, _num_handlers: usize) -> RValue<'gcc> { fn catch_switch(
&mut self,
_parent: Option<RValue<'gcc>>,
_unwind: Option<Block<'gcc>>,
_handlers: &[Block<'gcc>],
) -> RValue<'gcc> {
unimplemented!(); unimplemented!();
} }
fn add_handler(&mut self, _catch_switch: RValue<'gcc>, _handler: Block<'gcc>) {
unimplemented!();
}
fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
// TODO(antoyo)
}
// Atomic Operations // Atomic Operations
fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> { fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> {
let expected = self.current_func().new_local(None, cmp.get_type(), "expected"); let expected = self.current_func().new_local(None, cmp.get_type(), "expected");

View file

@ -956,29 +956,24 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
unsafe { llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint, UNNAMED) } unsafe { llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint, UNNAMED) }
} }
fn landing_pad( fn set_personality_fn(&mut self, personality: &'ll Value) {
&mut self,
ty: &'ll Type,
pers_fn: &'ll Value,
num_clauses: usize,
) -> &'ll Value {
// Use LLVMSetPersonalityFn to set the personality. It supports arbitrary Consts while,
// LLVMBuildLandingPad requires the argument to be a Function (as of LLVM 12). The
// personality lives on the parent function anyway.
self.set_personality_fn(pers_fn);
unsafe { unsafe {
llvm::LLVMBuildLandingPad(self.llbuilder, ty, None, num_clauses as c_uint, UNNAMED) llvm::LLVMSetPersonalityFn(self.llfn(), personality);
} }
} }
fn set_cleanup(&mut self, landing_pad: &'ll Value) { fn cleanup_landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value) -> &'ll Value {
let landing_pad = self.landing_pad(ty, pers_fn, 1 /* FIXME should this be 0? */);
unsafe { unsafe {
llvm::LLVMSetCleanup(landing_pad, llvm::True); llvm::LLVMSetCleanup(landing_pad, llvm::True);
} }
landing_pad
} }
fn resume(&mut self, exn: &'ll Value) -> &'ll Value { fn resume(&mut self, exn: &'ll Value) {
unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) } unsafe {
llvm::LLVMBuildResume(self.llbuilder, exn);
}
} }
fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> { fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> {
@ -995,14 +990,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
Funclet::new(ret.expect("LLVM does not have support for cleanuppad")) Funclet::new(ret.expect("LLVM does not have support for cleanuppad"))
} }
fn cleanup_ret( fn cleanup_ret(&mut self, funclet: &Funclet<'ll>, unwind: Option<&'ll BasicBlock>) {
&mut self, unsafe {
funclet: &Funclet<'ll>, llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind)
unwind: Option<&'ll BasicBlock>, .expect("LLVM does not have support for cleanupret");
) -> &'ll Value { }
let ret =
unsafe { llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) };
ret.expect("LLVM does not have support for cleanupret")
} }
fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> { fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> {
@ -1023,7 +1015,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
&mut self, &mut self,
parent: Option<&'ll Value>, parent: Option<&'ll Value>,
unwind: Option<&'ll BasicBlock>, unwind: Option<&'ll BasicBlock>,
num_handlers: usize, handlers: &[&'ll BasicBlock],
) -> &'ll Value { ) -> &'ll Value {
let name = cstr!("catchswitch"); let name = cstr!("catchswitch");
let ret = unsafe { let ret = unsafe {
@ -1031,23 +1023,17 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
self.llbuilder, self.llbuilder,
parent, parent,
unwind, unwind,
num_handlers as c_uint, handlers.len() as c_uint,
name.as_ptr(), name.as_ptr(),
) )
}; };
ret.expect("LLVM does not have support for catchswitch") let ret = ret.expect("LLVM does not have support for catchswitch");
} for handler in handlers {
fn add_handler(&mut self, catch_switch: &'ll Value, handler: &'ll BasicBlock) {
unsafe { unsafe {
llvm::LLVMRustAddHandler(catch_switch, handler); llvm::LLVMRustAddHandler(ret, handler);
} }
} }
ret
fn set_personality_fn(&mut self, personality: &'ll Value) {
unsafe {
llvm::LLVMSetPersonalityFn(self.llfn(), personality);
}
} }
// Atomic Operations // Atomic Operations
@ -1478,4 +1464,19 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
None None
} }
} }
pub(crate) fn landing_pad(
&mut self,
ty: &'ll Type,
pers_fn: &'ll Value,
num_clauses: usize,
) -> &'ll Value {
// Use LLVMSetPersonalityFn to set the personality. It supports arbitrary Consts while,
// LLVMBuildLandingPad requires the argument to be a Function (as of LLVM 12). The
// personality lives on the parent function anyway.
self.set_personality_fn(pers_fn);
unsafe {
llvm::LLVMBuildLandingPad(self.llbuilder, ty, None, num_clauses as c_uint, UNNAMED)
}
}
} }

View file

@ -525,9 +525,8 @@ fn codegen_msvc_try<'ll>(
normal.ret(bx.const_i32(0)); normal.ret(bx.const_i32(0));
let cs = catchswitch.catch_switch(None, None, 2); let cs =
catchswitch.add_handler(cs, catchpad_rust.llbb()); catchswitch.catch_switch(None, None, &[catchpad_rust.llbb(), catchpad_foreign.llbb()]);
catchswitch.add_handler(cs, catchpad_foreign.llbb());
// We can't use the TypeDescriptor defined in libpanic_unwind because it // We can't use the TypeDescriptor defined in libpanic_unwind because it
// might be in another DLL and the SEH encoding only supports specifying // might be in another DLL and the SEH encoding only supports specifying

View file

@ -1346,8 +1346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let mut cp_bx = self.new_block(&format!("cp_funclet{:?}", bb)); let mut cp_bx = self.new_block(&format!("cp_funclet{:?}", bb));
ret_llbb = cs_bx.llbb(); ret_llbb = cs_bx.llbb();
let cs = cs_bx.catch_switch(None, None, 1); let cs = cs_bx.catch_switch(None, None, &[cp_bx.llbb()]);
cs_bx.add_handler(cs, cp_bx.llbb());
// The "null" here is actually a RTTI type descriptor for the // The "null" here is actually a RTTI type descriptor for the
// C++ personality function, but `catch (...)` has no type so // C++ personality function, but `catch (...)` has no type so
@ -1374,8 +1373,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let llpersonality = self.cx.eh_personality(); let llpersonality = self.cx.eh_personality();
let llretty = self.landing_pad_type(); let llretty = self.landing_pad_type();
let lp = bx.landing_pad(llretty, llpersonality, 1); let lp = bx.cleanup_landing_pad(llretty, llpersonality);
bx.set_cleanup(lp);
let slot = self.get_personality_slot(&mut bx); let slot = self.get_personality_slot(&mut bx);
slot.storage_live(&mut bx); slot.storage_live(&mut bx);

View file

@ -421,29 +421,22 @@ pub trait BuilderMethods<'a, 'tcx>:
fn extract_value(&mut self, agg_val: Self::Value, idx: u64) -> Self::Value; fn extract_value(&mut self, agg_val: Self::Value, idx: u64) -> Self::Value;
fn insert_value(&mut self, agg_val: Self::Value, elt: Self::Value, idx: u64) -> Self::Value; fn insert_value(&mut self, agg_val: Self::Value, elt: Self::Value, idx: u64) -> Self::Value;
fn landing_pad( fn set_personality_fn(&mut self, personality: Self::Value);
&mut self,
ty: Self::Type, // These are used by everyone except msvc
pers_fn: Self::Value, fn cleanup_landing_pad(&mut self, ty: Self::Type, pers_fn: Self::Value) -> Self::Value;
num_clauses: usize, fn resume(&mut self, exn: Self::Value);
) -> Self::Value;
fn set_cleanup(&mut self, landing_pad: Self::Value); // These are used only by msvc
fn resume(&mut self, exn: Self::Value) -> Self::Value;
fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet; fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
fn cleanup_ret( fn cleanup_ret(&mut self, funclet: &Self::Funclet, unwind: Option<Self::BasicBlock>);
&mut self,
funclet: &Self::Funclet,
unwind: Option<Self::BasicBlock>,
) -> Self::Value;
fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet; fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet;
fn catch_switch( fn catch_switch(
&mut self, &mut self,
parent: Option<Self::Value>, parent: Option<Self::Value>,
unwind: Option<Self::BasicBlock>, unwind: Option<Self::BasicBlock>,
num_handlers: usize, handlers: &[Self::BasicBlock],
) -> Self::Value; ) -> Self::Value;
fn add_handler(&mut self, catch_switch: Self::Value, handler: Self::BasicBlock);
fn set_personality_fn(&mut self, personality: Self::Value);
fn atomic_cmpxchg( fn atomic_cmpxchg(
&mut self, &mut self,