Skip to content

Commit b7f9e8b

Browse files
committed
Put unwinding support behind the unwinding cargo feature
1 parent a9cd0b7 commit b7f9e8b

File tree

5 files changed

+167
-142
lines changed

5 files changed

+167
-142
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ smallvec = "1.8.1"
4646
unstable-features = ["jit", "inline_asm_sym"]
4747
jit = ["cranelift-jit", "libloading"]
4848
inline_asm_sym = []
49+
unwinding = [] # Not yet included in unstable-features for performance reasons
4950

5051
[package.metadata.rust-analyzer]
5152
rustc_private = true

src/abi/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ pub(crate) fn codegen_call_with_unwind_action(
851851
fx: &mut FunctionCx<'_, '_, '_>,
852852
span: Option<Span>,
853853
func_ref: CallTarget,
854-
unwind: UnwindAction,
854+
mut unwind: UnwindAction,
855855
call_args: &[Value],
856856
target_block: Option<Block>,
857857
) -> SmallVec<[Value; 2]> {
@@ -863,6 +863,11 @@ pub(crate) fn codegen_call_with_unwind_action(
863863
if target_block.is_some() {
864864
assert!(fx.bcx.func.dfg.signatures[sig_ref].returns.is_empty());
865865
}
866+
867+
if cfg!(not(feature = "unwinding")) {
868+
unwind = UnwindAction::Unreachable;
869+
}
870+
866871
match unwind {
867872
UnwindAction::Continue | UnwindAction::Unreachable => {
868873
let call_inst = match func_ref {

src/base.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
300300
}
301301

302302
if bb_data.is_cleanup {
303+
if cfg!(not(feature = "unwinding")) {
304+
continue;
305+
}
306+
303307
fx.bcx.set_cold_block(block);
304308
}
305309

@@ -534,13 +538,15 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
534538
codegen_unwind_terminate(fx, Some(source_info.span), *reason);
535539
}
536540
TerminatorKind::UnwindResume => {
537-
let exception_ptr = fx.bcx.use_var(fx.exception_slot);
538-
fx.lib_call(
539-
"_Unwind_Resume",
540-
vec![AbiParam::new(fx.pointer_type)],
541-
vec![],
542-
&[exception_ptr],
543-
);
541+
if cfg!(feature = "unwinding") {
542+
let exception_ptr = fx.bcx.use_var(fx.exception_slot);
543+
fx.lib_call(
544+
"_Unwind_Resume",
545+
vec![AbiParam::new(fx.pointer_type)],
546+
vec![],
547+
&[exception_ptr],
548+
);
549+
}
544550
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
545551
}
546552
TerminatorKind::Unreachable => {

src/debuginfo/unwind.rs

Lines changed: 144 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -38,68 +38,74 @@ impl UnwindContext {
3838
} else {
3939
gimli::DW_EH_PE_absptr
4040
};
41-
let code_ptr_encoding = if pic_eh_frame {
42-
if module.isa().triple().architecture == target_lexicon::Architecture::X86_64 {
43-
gimli::DwEhPe(
44-
gimli::DW_EH_PE_indirect.0
45-
| gimli::DW_EH_PE_pcrel.0
46-
| gimli::DW_EH_PE_sdata4.0,
47-
)
48-
} else if let target_lexicon::Architecture::Aarch64(_) =
49-
module.isa().triple().architecture
50-
{
51-
gimli::DwEhPe(
52-
gimli::DW_EH_PE_indirect.0
53-
| gimli::DW_EH_PE_pcrel.0
54-
| gimli::DW_EH_PE_sdata8.0,
55-
)
56-
} else {
57-
todo!()
58-
}
59-
} else {
60-
gimli::DwEhPe(gimli::DW_EH_PE_indirect.0 | gimli::DW_EH_PE_absptr.0)
61-
};
6241

6342
cie.fde_address_encoding = ptr_encoding;
64-
cie.lsda_encoding = Some(ptr_encoding);
65-
66-
// FIXME use eh_personality lang item instead
67-
let personality = module
68-
.declare_function(
69-
"rust_eh_personality",
70-
Linkage::Import,
71-
&Signature {
72-
params: vec![
73-
AbiParam::new(types::I32),
74-
AbiParam::new(types::I32),
75-
AbiParam::new(types::I64),
76-
AbiParam::new(module.target_config().pointer_type()),
77-
AbiParam::new(module.target_config().pointer_type()),
78-
],
79-
returns: vec![AbiParam::new(types::I32)],
80-
call_conv: module.target_config().default_call_conv,
81-
},
82-
)
83-
.unwrap();
84-
85-
// Use indirection here to support PIC the case where rust_eh_personality is defined in
86-
// another DSO.
87-
let personality_ref = module
88-
.declare_data("DW.ref.rust_eh_personality", Linkage::Local, false, false)
89-
.unwrap();
90-
91-
let mut personality_ref_data = DataDescription::new();
92-
// Note: Must not use define_zeroinit. The unwinder can't handle this being in the .bss
93-
// section.
94-
let pointer_bytes = usize::from(module.target_config().pointer_bytes());
95-
personality_ref_data.define(vec![0; pointer_bytes].into_boxed_slice());
96-
let personality_func_ref =
97-
module.declare_func_in_data(personality, &mut personality_ref_data);
98-
personality_ref_data.write_function_addr(0, personality_func_ref);
99-
100-
module.define_data(personality_ref, &personality_ref_data).unwrap();
101-
102-
cie.personality = Some((code_ptr_encoding, address_for_data(personality_ref)));
43+
44+
// FIXME only add personality function and lsda when necessary: https://github.com/rust-lang/rust/blob/1f76d219c906f0112bb1872f33aa977164c53fa6/compiler/rustc_codegen_ssa/src/mir/mod.rs#L200-L204
45+
if cfg!(feature = "unwinding") {
46+
let code_ptr_encoding = if pic_eh_frame {
47+
if module.isa().triple().architecture == target_lexicon::Architecture::X86_64 {
48+
gimli::DwEhPe(
49+
gimli::DW_EH_PE_indirect.0
50+
| gimli::DW_EH_PE_pcrel.0
51+
| gimli::DW_EH_PE_sdata4.0,
52+
)
53+
} else if let target_lexicon::Architecture::Aarch64(_) =
54+
module.isa().triple().architecture
55+
{
56+
gimli::DwEhPe(
57+
gimli::DW_EH_PE_indirect.0
58+
| gimli::DW_EH_PE_pcrel.0
59+
| gimli::DW_EH_PE_sdata8.0,
60+
)
61+
} else {
62+
todo!()
63+
}
64+
} else {
65+
gimli::DwEhPe(gimli::DW_EH_PE_indirect.0 | gimli::DW_EH_PE_absptr.0)
66+
};
67+
68+
cie.lsda_encoding = Some(ptr_encoding);
69+
70+
// FIXME use eh_personality lang item instead
71+
let personality = module
72+
.declare_function(
73+
"rust_eh_personality",
74+
Linkage::Import,
75+
&Signature {
76+
params: vec![
77+
AbiParam::new(types::I32),
78+
AbiParam::new(types::I32),
79+
AbiParam::new(types::I64),
80+
AbiParam::new(module.target_config().pointer_type()),
81+
AbiParam::new(module.target_config().pointer_type()),
82+
],
83+
returns: vec![AbiParam::new(types::I32)],
84+
call_conv: module.target_config().default_call_conv,
85+
},
86+
)
87+
.unwrap();
88+
89+
// Use indirection here to support PIC the case where rust_eh_personality is defined in
90+
// another DSO.
91+
let personality_ref = module
92+
.declare_data("DW.ref.rust_eh_personality", Linkage::Local, false, false)
93+
.unwrap();
94+
95+
let mut personality_ref_data = DataDescription::new();
96+
// Note: Must not use define_zeroinit. The unwinder can't handle this being in the .bss
97+
// section.
98+
let pointer_bytes = usize::from(module.target_config().pointer_bytes());
99+
personality_ref_data.define(vec![0; pointer_bytes].into_boxed_slice());
100+
let personality_func_ref =
101+
module.declare_func_in_data(personality, &mut personality_ref_data);
102+
personality_ref_data.write_function_addr(0, personality_func_ref);
103+
104+
module.define_data(personality_ref, &personality_ref_data).unwrap();
105+
106+
cie.personality = Some((code_ptr_encoding, address_for_data(personality_ref)));
107+
}
108+
103109
Some(frame_table.add_cie(cie))
104110
} else {
105111
None
@@ -135,89 +141,94 @@ impl UnwindContext {
135141
match unwind_info {
136142
UnwindInfo::SystemV(unwind_info) => {
137143
let mut fde = unwind_info.to_fde(address_for_func(func_id));
138-
// FIXME use unique symbol name derived from function name
139-
let lsda = module.declare_anonymous_data(false, false).unwrap();
140144

141-
let encoding = Encoding {
142-
format: Format::Dwarf32,
143-
version: 1,
144-
address_size: module.isa().frontend_config().pointer_bytes(),
145-
};
145+
// FIXME only add personality function and lsda when necessary: https://github.com/rust-lang/rust/blob/1f76d219c906f0112bb1872f33aa977164c53fa6/compiler/rustc_codegen_ssa/src/mir/mod.rs#L200-L204
146+
if cfg!(feature = "unwinding") {
147+
// FIXME use unique symbol name derived from function name
148+
let lsda = module.declare_anonymous_data(false, false).unwrap();
146149

147-
let mut gcc_except_table_data = GccExceptTable {
148-
call_sites: CallSiteTable(vec![]),
149-
actions: ActionTable::new(),
150-
type_info: TypeInfoTable::new(gimli::DW_EH_PE_udata4),
151-
exception_specs: ExceptionSpecTable::new(),
152-
};
150+
let encoding = Encoding {
151+
format: Format::Dwarf32,
152+
version: 1,
153+
address_size: module.isa().frontend_config().pointer_bytes(),
154+
};
153155

154-
let catch_type = gcc_except_table_data.type_info.add(Address::Constant(0));
155-
let catch_action = gcc_except_table_data
156-
.actions
157-
.add(Action { kind: ActionKind::Catch(catch_type), next_action: None });
158-
159-
for call_site in context.compiled_code().unwrap().buffer.call_sites() {
160-
if call_site.exception_handlers.is_empty() {
161-
gcc_except_table_data.call_sites.0.push(CallSite {
162-
start: u64::from(call_site.ret_addr - 1),
163-
length: 1,
164-
landing_pad: 0,
165-
action_entry: None,
166-
});
167-
}
168-
for &(tag, landingpad) in call_site.exception_handlers {
169-
match tag.expand().unwrap().as_u32() {
170-
EXCEPTION_HANDLER_CLEANUP => {
171-
gcc_except_table_data.call_sites.0.push(CallSite {
172-
start: u64::from(call_site.ret_addr - 1),
173-
length: 1,
174-
landing_pad: u64::from(landingpad),
175-
action_entry: None,
176-
})
177-
}
178-
EXCEPTION_HANDLER_CATCH => {
179-
gcc_except_table_data.call_sites.0.push(CallSite {
180-
start: u64::from(call_site.ret_addr - 1),
181-
length: 1,
182-
landing_pad: u64::from(landingpad),
183-
action_entry: Some(catch_action),
184-
})
156+
let mut gcc_except_table_data = GccExceptTable {
157+
call_sites: CallSiteTable(vec![]),
158+
actions: ActionTable::new(),
159+
type_info: TypeInfoTable::new(gimli::DW_EH_PE_udata4),
160+
exception_specs: ExceptionSpecTable::new(),
161+
};
162+
163+
let catch_type = gcc_except_table_data.type_info.add(Address::Constant(0));
164+
let catch_action = gcc_except_table_data
165+
.actions
166+
.add(Action { kind: ActionKind::Catch(catch_type), next_action: None });
167+
168+
for call_site in context.compiled_code().unwrap().buffer.call_sites() {
169+
if call_site.exception_handlers.is_empty() {
170+
gcc_except_table_data.call_sites.0.push(CallSite {
171+
start: u64::from(call_site.ret_addr - 1),
172+
length: 1,
173+
landing_pad: 0,
174+
action_entry: None,
175+
});
176+
}
177+
for &(tag, landingpad) in call_site.exception_handlers {
178+
match tag.expand().unwrap().as_u32() {
179+
EXCEPTION_HANDLER_CLEANUP => {
180+
gcc_except_table_data.call_sites.0.push(CallSite {
181+
start: u64::from(call_site.ret_addr - 1),
182+
length: 1,
183+
landing_pad: u64::from(landingpad),
184+
action_entry: None,
185+
})
186+
}
187+
EXCEPTION_HANDLER_CATCH => {
188+
gcc_except_table_data.call_sites.0.push(CallSite {
189+
start: u64::from(call_site.ret_addr - 1),
190+
length: 1,
191+
landing_pad: u64::from(landingpad),
192+
action_entry: Some(catch_action),
193+
})
194+
}
195+
_ => unreachable!(),
185196
}
186-
_ => unreachable!(),
187197
}
188198
}
189-
}
190199

191-
let mut gcc_except_table = super::emit::WriterRelocate::new(self.endian);
192-
193-
gcc_except_table_data.write(&mut gcc_except_table, encoding).unwrap();
194-
195-
let mut data = DataDescription::new();
196-
data.define(gcc_except_table.writer.into_vec().into_boxed_slice());
197-
data.set_segment_section("", ".gcc_except_table");
198-
199-
for reloc in &gcc_except_table.relocs {
200-
match reloc.name {
201-
DebugRelocName::Section(_id) => unreachable!(),
202-
DebugRelocName::Symbol(id) => {
203-
let id = id.try_into().unwrap();
204-
if id & 1 << 31 == 0 {
205-
let func_ref =
206-
module.declare_func_in_data(FuncId::from_u32(id), &mut data);
207-
data.write_function_addr(reloc.offset, func_ref);
208-
} else {
209-
let gv = module.declare_data_in_data(
210-
DataId::from_u32(id & !(1 << 31)),
211-
&mut data,
212-
);
213-
data.write_data_addr(reloc.offset, gv, 0);
200+
let mut gcc_except_table = super::emit::WriterRelocate::new(self.endian);
201+
202+
gcc_except_table_data.write(&mut gcc_except_table, encoding).unwrap();
203+
204+
let mut data = DataDescription::new();
205+
data.define(gcc_except_table.writer.into_vec().into_boxed_slice());
206+
data.set_segment_section("", ".gcc_except_table");
207+
208+
for reloc in &gcc_except_table.relocs {
209+
match reloc.name {
210+
DebugRelocName::Section(_id) => unreachable!(),
211+
DebugRelocName::Symbol(id) => {
212+
let id = id.try_into().unwrap();
213+
if id & 1 << 31 == 0 {
214+
let func_ref = module
215+
.declare_func_in_data(FuncId::from_u32(id), &mut data);
216+
data.write_function_addr(reloc.offset, func_ref);
217+
} else {
218+
let gv = module.declare_data_in_data(
219+
DataId::from_u32(id & !(1 << 31)),
220+
&mut data,
221+
);
222+
data.write_data_addr(reloc.offset, gv, 0);
223+
}
214224
}
215-
}
216-
};
225+
};
226+
}
227+
228+
module.define_data(lsda, &data).unwrap();
229+
fde.lsda = Some(address_for_data(lsda));
217230
}
218231

219-
module.define_data(lsda, &data).unwrap();
220-
fde.lsda = Some(address_for_data(lsda));
221232
self.frame_table.add_fde(self.cie_id.unwrap(), fde);
222233
}
223234
UnwindInfo::WindowsX64(_) | UnwindInfo::WindowsArm64(_) => {

src/intrinsics/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1372,7 +1372,9 @@ fn codegen_regular_intrinsic_call<'tcx>(
13721372
returns: vec![],
13731373
});
13741374

1375-
if fx.tcx.sess.panic_strategy() == PanicStrategy::Abort {
1375+
if cfg!(not(feature = "unwinding"))
1376+
|| fx.tcx.sess.panic_strategy() == PanicStrategy::Abort
1377+
{
13761378
fx.bcx.ins().call_indirect(f_sig, f, &[data]);
13771379

13781380
let layout = fx.layout_of(fx.tcx.types.i32);

0 commit comments

Comments
 (0)