Skip to content

Commit 0267deb

Browse files
committed
Put unwinding support behind the unwinding cargo feature
1 parent 30c47e4 commit 0267deb

File tree

5 files changed

+166
-141
lines changed

5 files changed

+166
-141
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
@@ -844,7 +844,7 @@ pub(crate) fn codegen_call_with_unwind_action(
844844
fx: &mut FunctionCx<'_, '_, '_>,
845845
span: Span,
846846
func_ref: CallTarget,
847-
unwind: UnwindAction,
847+
mut unwind: UnwindAction,
848848
call_args: &[Value],
849849
target_block: Option<Block>,
850850
) -> SmallVec<[Value; 2]> {
@@ -856,6 +856,11 @@ pub(crate) fn codegen_call_with_unwind_action(
856856
if target_block.is_some() {
857857
assert!(fx.bcx.func.dfg.signatures[sig_ref].returns.is_empty());
858858
}
859+
860+
if cfg!(not(feature = "unwinding")) {
861+
unwind = UnwindAction::Unreachable;
862+
}
863+
859864
match unwind {
860865
UnwindAction::Continue | UnwindAction::Unreachable => {
861866
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, 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: 143 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -37,68 +37,74 @@ impl UnwindContext {
3737
} else {
3838
gimli::DW_EH_PE_absptr
3939
};
40-
let code_ptr_encoding = if pic_eh_frame {
41-
if module.isa().triple().architecture == target_lexicon::Architecture::X86_64 {
42-
gimli::DwEhPe(
43-
gimli::DW_EH_PE_indirect.0
44-
| gimli::DW_EH_PE_pcrel.0
45-
| gimli::DW_EH_PE_sdata4.0,
46-
)
47-
} else if let target_lexicon::Architecture::Aarch64(_) =
48-
module.isa().triple().architecture
49-
{
50-
gimli::DwEhPe(
51-
gimli::DW_EH_PE_indirect.0
52-
| gimli::DW_EH_PE_pcrel.0
53-
| gimli::DW_EH_PE_sdata8.0,
54-
)
55-
} else {
56-
todo!()
57-
}
58-
} else {
59-
gimli::DwEhPe(gimli::DW_EH_PE_indirect.0 | gimli::DW_EH_PE_absptr.0)
60-
};
6140

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

140-
let encoding = Encoding {
141-
format: Format::Dwarf32,
142-
version: 1,
143-
address_size: module.isa().frontend_config().pointer_bytes(),
144-
};
144+
// 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
145+
if cfg!(feature = "unwinding") {
146+
// FIXME use unique symbol name derived from function name
147+
let lsda = module.declare_anonymous_data(false, false).unwrap();
145148

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

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

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

217-
module.define_data(lsda, &data).unwrap();
218-
fde.lsda = Some(address_for_data(lsda));
219230
self.frame_table.add_fde(self.cie_id.unwrap(), fde);
220231
}
221232
UnwindInfo::WindowsX64(_) | UnwindInfo::WindowsArm64(_) => {

src/intrinsics/mod.rs

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

1370-
if fx.tcx.sess.panic_strategy() == PanicStrategy::Abort {
1370+
if cfg!(not(feature = "unwinding"))
1371+
|| fx.tcx.sess.panic_strategy() == PanicStrategy::Abort
1372+
{
13711373
fx.bcx.ins().call_indirect(f_sig, f, &[data]);
13721374

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

0 commit comments

Comments
 (0)