From 589f4a4405f605df95852c0b06995e18a38cb643 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 11 Oct 2020 16:18:27 +0200 Subject: [PATCH] Re-introduce finalize_definitions and get_finalized_* for simplejit --- cranelift/simplejit/src/backend.rs | 64 +++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/cranelift/simplejit/src/backend.rs b/cranelift/simplejit/src/backend.rs index b5c5f1f87a..4324817add 100644 --- a/cranelift/simplejit/src/backend.rs +++ b/cranelift/simplejit/src/backend.rs @@ -252,6 +252,32 @@ impl SimpleJITModule { } } + /// Returns the address of a finalized function. + pub fn get_finalized_function(&self, func_id: FuncId) -> *const u8 { + let info = &self.functions[func_id]; + debug_assert!( + !self.functions_to_finalize.iter().any(|x| *x == func_id), + "function not yet finalized" + ); + info.as_ref() + .expect("function must be compiled before it can be finalized") + .code + } + + /// Returns the address and size of a finalized data object. + pub fn get_finalized_data(&self, data_id: DataId) -> (*const u8, usize) { + let info = &self.data_objects[data_id]; + debug_assert!( + !self.data_objects_to_finalize.iter().any(|x| *x == data_id), + "data object not yet finalized" + ); + let compiled = info + .as_ref() + .expect("data object must be compiled before it can be finalized"); + + (compiled.storage, compiled.size) + } + fn record_function_for_perf(&self, ptr: *mut u8, size: usize, name: &str) { // The Linux perf tool supports JIT code via a /tmp/perf-$PID.map file, // which contains memory regions and their associated names. If we @@ -360,6 +386,29 @@ impl SimpleJITModule { } } + /// Finalize all functions and data objects that are defined but not yet finalized. + /// All symbols referenced in their bodies that are declared as needing a definition + /// must be defined by this point. + /// + /// Use `get_finalized_function` and `get_finalized_data` to obtain the final + /// artifacts. + pub fn finalize_definitions(&mut self) { + for func in std::mem::take(&mut self.functions_to_finalize) { + let decl = self.declarations.get_function_decl(func); + debug_assert!(decl.linkage.is_definable()); + self.finalize_function(func); + } + for data in std::mem::take(&mut self.data_objects_to_finalize) { + let decl = self.declarations.get_data_decl(data); + debug_assert!(decl.linkage.is_definable()); + self.finalize_data(data); + } + + // Now that we're done patching, prepare the memory for execution! + self.memory.readonly.set_readonly(); + self.memory.code.set_readable_and_executable(); + } + /// Create a new `SimpleJITModule`. pub fn new(builder: SimpleJITBuilder) -> Self { let memory = SimpleJITMemoryHandle { @@ -606,20 +655,7 @@ impl SimpleJITModule { /// This method does not need to be called when access to the memory /// handle is not required. pub fn finish(mut self) -> SimpleJITProduct { - for func in std::mem::take(&mut self.functions_to_finalize) { - let decl = self.declarations.get_function_decl(func); - debug_assert!(decl.linkage.is_definable()); - self.finalize_function(func); - } - for data in std::mem::take(&mut self.data_objects_to_finalize) { - let decl = self.declarations.get_data_decl(data); - debug_assert!(decl.linkage.is_definable()); - self.finalize_data(data); - } - - // Now that we're done patching, prepare the memory for execution! - self.memory.readonly.set_readonly(); - self.memory.code.set_readable_and_executable(); + self.finalize_definitions(); SimpleJITProduct { memory: self.memory,