Prevent finalize being called more than once per func/data (fixes #407)

This commit is contained in:
bjorn3
2018-08-14 17:10:49 +02:00
committed by Dan Gohman
parent dbc547091f
commit 3f0103f936
2 changed files with 62 additions and 0 deletions

View File

@@ -1,9 +1,14 @@
extern crate cranelift_codegen; extern crate cranelift_codegen;
extern crate cranelift_entity;
extern crate cranelift_frontend;
extern crate cranelift_module; extern crate cranelift_module;
extern crate cranelift_simplejit; extern crate cranelift_simplejit;
use cranelift_codegen::ir::*; use cranelift_codegen::ir::*;
use cranelift_codegen::settings::*; use cranelift_codegen::settings::*;
use cranelift_codegen::Context;
use cranelift_entity::EntityRef;
use cranelift_frontend::*;
use cranelift_module::*; use cranelift_module::*;
use cranelift_simplejit::*; use cranelift_simplejit::*;
@@ -25,3 +30,50 @@ fn error_on_incompatible_sig_in_declare_function() {
.err() .err()
.unwrap(); // Make sure this is an error .unwrap(); // Make sure this is an error
} }
fn define_simple_function(module: &mut Module<SimpleJITBackend>) -> FuncId {
let sig = Signature {
params: vec![],
returns: vec![],
call_conv: CallConv::SystemV,
argument_bytes: None,
};
let func_id = module
.declare_function("abc", Linkage::Local, &sig)
.unwrap();
let mut ctx = Context::new();
ctx.func = Function::with_name_signature(ExternalName::user(0, func_id.index() as u32), sig);
let mut func_ctx = FunctionBuilderContext::new();
{
let mut bcx: FunctionBuilder<Variable> = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
let ebb = bcx.create_ebb();
bcx.switch_to_block(ebb);
bcx.ins().return_(&[]);
}
module.define_function(func_id, &mut ctx).unwrap();
func_id
}
#[test]
#[should_panic(expected = "function can't be finalized twice")]
fn panic_on_double_finalize() {
let mut module: Module<SimpleJITBackend> = Module::new(SimpleJITBuilder::new());
let func_id = define_simple_function(&mut module);
module.finalize_function(func_id);
module.finalize_function(func_id);
}
#[test]
#[should_panic(expected = "Result::unwrap()` on an `Err` value: DuplicateDefinition(\"abc\")")]
fn panic_on_define_after_finalize() {
let mut module: Module<SimpleJITBackend> = Module::new(SimpleJITBuilder::new());
let func_id = define_simple_function(&mut module);
module.finalize_function(func_id);
define_simple_function(&mut module);
}

View File

@@ -562,6 +562,10 @@ where
/// Perform all outstanding relocations on the given function. This requires all `Local` /// Perform all outstanding relocations on the given function. This requires all `Local`
/// and `Export` entities referenced to be defined. /// and `Export` entities referenced to be defined.
///
/// # Panics
///
/// When the function has already been finalized this panics
pub fn finalize_function(&mut self, func: FuncId) -> B::FinalizedFunction { pub fn finalize_function(&mut self, func: FuncId) -> B::FinalizedFunction {
let output = { let output = {
let info = &self.contents.functions[func]; let info = &self.contents.functions[func];
@@ -569,6 +573,7 @@ where
info.decl.linkage.is_definable(), info.decl.linkage.is_definable(),
"imported function cannot be finalized" "imported function cannot be finalized"
); );
assert!(!info.finalized, "function can't be finalized twice");
self.backend.finalize_function( self.backend.finalize_function(
info.compiled info.compiled
.as_ref() .as_ref()
@@ -584,6 +589,10 @@ where
/// Perform all outstanding relocations on the given data object. This requires all /// Perform all outstanding relocations on the given data object. This requires all
/// `Local` and `Export` entities referenced to be defined. /// `Local` and `Export` entities referenced to be defined.
///
/// # Panics
///
/// When the data object has already been finalized this panics
pub fn finalize_data(&mut self, data: DataId) -> B::FinalizedData { pub fn finalize_data(&mut self, data: DataId) -> B::FinalizedData {
let output = { let output = {
let info = &self.contents.data_objects[data]; let info = &self.contents.data_objects[data];
@@ -591,6 +600,7 @@ where
info.decl.linkage.is_definable(), info.decl.linkage.is_definable(),
"imported data cannot be finalized" "imported data cannot be finalized"
); );
assert!(!info.finalized, "data object can't be finalized twice");
self.backend.finalize_data( self.backend.finalize_data(
info.compiled info.compiled
.as_ref() .as_ref()