Skip to content

Commit d9c05d6

Browse files
committed
adjust for FnAbi changes
1 parent 9983e0f commit d9c05d6

File tree

4 files changed

+70
-63
lines changed

4 files changed

+70
-63
lines changed

src/helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
687687
link_name: Symbol,
688688
) -> InterpResult<'tcx, ()> {
689689
self.check_abi(abi, exp_abi)?;
690-
if let Some(body) = self.eval_context_mut().lookup_exported_symbol(link_name)? {
690+
if let Some((body, _)) = self.eval_context_mut().lookup_exported_symbol(link_name)? {
691691
throw_machine_stop!(TerminationInfo::SymbolShimClashing {
692692
link_name,
693693
span: body.span.data(),

src/machine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
452452
args: &[OpTy<'tcx, Tag>],
453453
ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
454454
unwind: StackPopUnwind,
455-
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
455+
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
456456
ecx.find_mir_or_eval_fn(instance, abi, args, ret, unwind)
457457
}
458458

src/shims/foreign_items.rs

Lines changed: 66 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::{
22
convert::{TryFrom, TryInto},
33
iter,
4+
collections::hash_map::Entry,
45
};
56

67
use log::trace;
@@ -34,7 +35,7 @@ pub enum EmulateByNameResult<'mir, 'tcx> {
3435
/// Jumping has already been taken care of.
3536
AlreadyJumped,
3637
/// A MIR body has been found for the function
37-
MirBody(&'mir mir::Body<'tcx>),
38+
MirBody(&'mir mir::Body<'tcx>, ty::Instance<'tcx>),
3839
/// The item is not supported.
3940
NotSupported,
4041
}
@@ -135,68 +136,74 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
135136
fn lookup_exported_symbol(
136137
&mut self,
137138
link_name: Symbol,
138-
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
139+
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
139140
let this = self.eval_context_mut();
140141
let tcx = this.tcx.tcx;
141142

142143
// If the result was cached, just return it.
143-
if let Some(instance) = this.machine.exported_symbols_cache.get(&link_name) {
144-
return instance.map(|instance| this.load_mir(instance.def, None)).transpose();
145-
}
146-
147-
// Find it if it was not cached.
148-
let mut instance_and_crate: Option<(ty::Instance<'_>, CrateNum)> = None;
149-
// `dependency_formats` includes all the transitive informations needed to link a crate,
150-
// which is what we need here since we need to dig out `exported_symbols` from all transitive
151-
// dependencies.
152-
let dependency_formats = tcx.dependency_formats(());
153-
let dependency_format = dependency_formats
154-
.iter()
155-
.find(|(crate_type, _)| *crate_type == CrateType::Executable)
156-
.expect("interpreting a non-executable crate");
157-
for cnum in
158-
iter::once(LOCAL_CRATE).chain(dependency_format.1.iter().enumerate().filter_map(
159-
|(num, &linkage)| (linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1)),
160-
))
161-
{
162-
// We can ignore `_export_level` here: we are a Rust crate, and everything is exported
163-
// from a Rust crate.
164-
for &(symbol, _export_level) in tcx.exported_symbols(cnum) {
165-
if let ExportedSymbol::NonGeneric(def_id) = symbol {
166-
let attrs = tcx.codegen_fn_attrs(def_id);
167-
let symbol_name = if let Some(export_name) = attrs.export_name {
168-
export_name
169-
} else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
170-
tcx.item_name(def_id)
171-
} else {
172-
// Skip over items without an explicitly defined symbol name.
173-
continue;
174-
};
175-
if symbol_name == link_name {
176-
if let Some((instance, original_cnum)) = instance_and_crate {
177-
throw_machine_stop!(TerminationInfo::MultipleSymbolDefinitions {
178-
link_name,
179-
first: tcx.def_span(instance.def_id()).data(),
180-
first_crate: tcx.crate_name(original_cnum),
181-
second: tcx.def_span(def_id).data(),
182-
second_crate: tcx.crate_name(cnum),
183-
});
184-
}
185-
if !matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
186-
throw_ub_format!(
187-
"attempt to call an exported symbol that is not defined as a function"
188-
);
144+
// (Cannot use `or_insert` since the code below might have to throw an error.)
145+
let entry = this.machine.exported_symbols_cache.entry(link_name);
146+
let instance = *match entry {
147+
Entry::Occupied(e) => e.into_mut(),
148+
Entry::Vacant(e) => {
149+
// Find it if it was not cached.
150+
let mut instance_and_crate: Option<(ty::Instance<'_>, CrateNum)> = None;
151+
// `dependency_formats` includes all the transitive informations needed to link a crate,
152+
// which is what we need here since we need to dig out `exported_symbols` from all transitive
153+
// dependencies.
154+
let dependency_formats = tcx.dependency_formats(());
155+
let dependency_format = dependency_formats
156+
.iter()
157+
.find(|(crate_type, _)| *crate_type == CrateType::Executable)
158+
.expect("interpreting a non-executable crate");
159+
for cnum in
160+
iter::once(LOCAL_CRATE).chain(dependency_format.1.iter().enumerate().filter_map(
161+
|(num, &linkage)| (linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1)),
162+
))
163+
{
164+
// We can ignore `_export_level` here: we are a Rust crate, and everything is exported
165+
// from a Rust crate.
166+
for &(symbol, _export_level) in tcx.exported_symbols(cnum) {
167+
if let ExportedSymbol::NonGeneric(def_id) = symbol {
168+
let attrs = tcx.codegen_fn_attrs(def_id);
169+
let symbol_name = if let Some(export_name) = attrs.export_name {
170+
export_name
171+
} else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
172+
tcx.item_name(def_id)
173+
} else {
174+
// Skip over items without an explicitly defined symbol name.
175+
continue;
176+
};
177+
if symbol_name == link_name {
178+
if let Some((instance, original_cnum)) = instance_and_crate {
179+
throw_machine_stop!(TerminationInfo::MultipleSymbolDefinitions {
180+
link_name,
181+
first: tcx.def_span(instance.def_id()).data(),
182+
first_crate: tcx.crate_name(original_cnum),
183+
second: tcx.def_span(def_id).data(),
184+
second_crate: tcx.crate_name(cnum),
185+
});
186+
}
187+
if !matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
188+
throw_ub_format!(
189+
"attempt to call an exported symbol that is not defined as a function"
190+
);
191+
}
192+
instance_and_crate = Some((ty::Instance::mono(tcx, def_id), cnum));
193+
}
189194
}
190-
instance_and_crate = Some((ty::Instance::mono(tcx, def_id), cnum));
191195
}
192196
}
197+
198+
e.insert(instance_and_crate.map(|ic| ic.0))
199+
}
200+
};
201+
match instance {
202+
None => Ok(None), // no symbol with this name
203+
Some(instance) => {
204+
Ok(Some((this.load_mir(instance.def, None)?, instance)))
193205
}
194206
}
195-
196-
let instance = instance_and_crate.map(|ic| ic.0);
197-
// Cache it and load its MIR, if found.
198-
this.machine.exported_symbols_cache.try_insert(link_name, instance).unwrap();
199-
instance.map(|instance| this.load_mir(instance.def, None)).transpose()
200207
}
201208

202209
/// Emulates calling a foreign item, failing if the item is not supported.
@@ -212,7 +219,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
212219
args: &[OpTy<'tcx, Tag>],
213220
ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
214221
unwind: StackPopUnwind,
215-
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
222+
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
216223
let this = self.eval_context_mut();
217224
let attrs = this.tcx.get_attrs(def_id);
218225
let link_name = this
@@ -240,7 +247,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
240247
this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?;
241248
let panic_impl_id = tcx.lang_items().panic_impl().unwrap();
242249
let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id);
243-
return Ok(Some(&*this.load_mir(panic_impl_instance.def, None)?));
250+
return Ok(Some((&*this.load_mir(panic_impl_instance.def, None)?, panic_impl_instance)));
244251
}
245252
#[rustfmt::skip]
246253
| "exit"
@@ -284,7 +291,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
284291
this.go_to_block(ret);
285292
}
286293
EmulateByNameResult::AlreadyJumped => (),
287-
EmulateByNameResult::MirBody(mir) => return Ok(Some(mir)),
294+
EmulateByNameResult::MirBody(mir, instance) => return Ok(Some((mir, instance))),
288295
EmulateByNameResult::NotSupported => {
289296
if let Some(body) = this.lookup_exported_symbol(link_name)? {
290297
return Ok(Some(body));
@@ -315,11 +322,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
315322

316323
match allocator_kind {
317324
AllocatorKind::Global => {
318-
let body = this
325+
let (body, instance) = this
319326
.lookup_exported_symbol(symbol)?
320327
.expect("symbol should be present if there is a global allocator");
321328

322-
Ok(EmulateByNameResult::MirBody(body))
329+
Ok(EmulateByNameResult::MirBody(body, instance))
323330
}
324331
AllocatorKind::Default => {
325332
default(this)?;

src/shims/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
3030
args: &[OpTy<'tcx, Tag>],
3131
ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
3232
unwind: StackPopUnwind,
33-
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
33+
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
3434
let this = self.eval_context_mut();
3535
trace!("eval_fn_call: {:#?}, {:?}", instance, ret.map(|p| p.0));
3636

@@ -54,7 +54,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
5454
}
5555

5656
// Otherwise, load the MIR.
57-
Ok(Some(&*this.load_mir(instance.def, None)?))
57+
Ok(Some((&*this.load_mir(instance.def, None)?, instance)))
5858
}
5959

6060
/// Returns `true` if the computation was performed, and `false` if we should just evaluate

0 commit comments

Comments
 (0)