format source
[kazan.git] / shader-compiler-backend-llvm-7 / src / backend.rs
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
3 use llvm;
4 use shader_compiler_backend as backend;
5 use std::cell::RefCell;
6 use std::collections::HashMap;
7 use std::collections::HashSet;
8 use std::ffi::{CStr, CString};
9 use std::fmt;
10 use std::hash::Hash;
11 use std::mem;
12 use std::mem::ManuallyDrop;
13 use std::ops::Deref;
14 use std::os::raw::{c_char, c_uint};
15 use std::ptr::null_mut;
16 use std::ptr::NonNull;
17 use std::sync::{Once, ONCE_INIT};
18
19 const EMPTY_C_STR: &[c_char] = &[b'0' as c_char];
20
21 fn to_bool(v: llvm::LLVMBool) -> bool {
22 v != 0
23 }
24
25 #[derive(Clone, Debug)]
26 pub struct LLVM7CompilerConfig {
27 pub variable_vector_length_multiplier: u32,
28 pub optimization_mode: backend::OptimizationMode,
29 }
30
31 impl Default for LLVM7CompilerConfig {
32 fn default() -> Self {
33 backend::CompilerIndependentConfig::default().into()
34 }
35 }
36
37 impl From<backend::CompilerIndependentConfig> for LLVM7CompilerConfig {
38 fn from(v: backend::CompilerIndependentConfig) -> Self {
39 let backend::CompilerIndependentConfig { optimization_mode } = v;
40 Self {
41 variable_vector_length_multiplier: 1,
42 optimization_mode,
43 }
44 }
45 }
46
47 #[repr(transparent)]
48 struct LLVM7String(NonNull<c_char>);
49
50 impl Drop for LLVM7String {
51 fn drop(&mut self) {
52 unsafe {
53 llvm::LLVMDisposeMessage(self.0.as_ptr());
54 }
55 }
56 }
57
58 impl Deref for LLVM7String {
59 type Target = CStr;
60 fn deref(&self) -> &CStr {
61 unsafe { CStr::from_ptr(self.0.as_ptr()) }
62 }
63 }
64
65 impl Clone for LLVM7String {
66 fn clone(&self) -> Self {
67 Self::new(self)
68 }
69 }
70
71 impl LLVM7String {
72 fn new(v: &CStr) -> Self {
73 unsafe { Self::from_ptr(llvm::LLVMCreateMessage(v.as_ptr())).unwrap() }
74 }
75 unsafe fn from_nonnull(v: NonNull<c_char>) -> Self {
76 LLVM7String(v)
77 }
78 unsafe fn from_ptr(v: *mut c_char) -> Option<Self> {
79 NonNull::new(v).map(|v| Self::from_nonnull(v))
80 }
81 }
82
83 impl fmt::Debug for LLVM7String {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 (**self).fmt(f)
86 }
87 }
88
89 #[derive(Clone, Eq, PartialEq, Hash)]
90 #[repr(transparent)]
91 pub struct LLVM7Type(llvm::LLVMTypeRef);
92
93 impl fmt::Debug for LLVM7Type {
94 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95 unsafe {
96 let string =
97 LLVM7String::from_ptr(llvm::LLVMPrintTypeToString(self.0)).ok_or(fmt::Error)?;
98 f.write_str(&string.to_string_lossy())
99 }
100 }
101 }
102
103 impl<'a> backend::types::Type<'a> for LLVM7Type {
104 type Context = LLVM7Context;
105 }
106
107 pub struct LLVM7TypeBuilder {
108 context: llvm::LLVMContextRef,
109 variable_vector_length_multiplier: u32,
110 }
111
112 impl<'a> backend::types::TypeBuilder<'a, LLVM7Type> for LLVM7TypeBuilder {
113 fn build_bool(&self) -> LLVM7Type {
114 unsafe { LLVM7Type(llvm::LLVMInt1TypeInContext(self.context)) }
115 }
116 fn build_i8(&self) -> LLVM7Type {
117 unsafe { LLVM7Type(llvm::LLVMInt8TypeInContext(self.context)) }
118 }
119 fn build_u8(&self) -> LLVM7Type {
120 unsafe { LLVM7Type(llvm::LLVMInt8TypeInContext(self.context)) }
121 }
122 fn build_i16(&self) -> LLVM7Type {
123 unsafe { LLVM7Type(llvm::LLVMInt16TypeInContext(self.context)) }
124 }
125 fn build_u16(&self) -> LLVM7Type {
126 unsafe { LLVM7Type(llvm::LLVMInt16TypeInContext(self.context)) }
127 }
128 fn build_i32(&self) -> LLVM7Type {
129 unsafe { LLVM7Type(llvm::LLVMInt32TypeInContext(self.context)) }
130 }
131 fn build_u32(&self) -> LLVM7Type {
132 unsafe { LLVM7Type(llvm::LLVMInt32TypeInContext(self.context)) }
133 }
134 fn build_i64(&self) -> LLVM7Type {
135 unsafe { LLVM7Type(llvm::LLVMInt64TypeInContext(self.context)) }
136 }
137 fn build_u64(&self) -> LLVM7Type {
138 unsafe { LLVM7Type(llvm::LLVMInt64TypeInContext(self.context)) }
139 }
140 fn build_f32(&self) -> LLVM7Type {
141 unsafe { LLVM7Type(llvm::LLVMFloatTypeInContext(self.context)) }
142 }
143 fn build_f64(&self) -> LLVM7Type {
144 unsafe { LLVM7Type(llvm::LLVMDoubleTypeInContext(self.context)) }
145 }
146 fn build_pointer(&self, target: LLVM7Type) -> LLVM7Type {
147 unsafe { LLVM7Type(llvm::LLVMPointerType(target.0, 0)) }
148 }
149 fn build_array(&self, element: LLVM7Type, count: usize) -> LLVM7Type {
150 assert_eq!(count as u32 as usize, count);
151 unsafe { LLVM7Type(llvm::LLVMArrayType(element.0, count as u32)) }
152 }
153 fn build_vector(&self, element: LLVM7Type, length: backend::types::VectorLength) -> LLVM7Type {
154 use self::backend::types::VectorLength::*;
155 let length = match length {
156 Fixed { length } => length,
157 Variable { base_length } => base_length
158 .checked_mul(self.variable_vector_length_multiplier)
159 .unwrap(),
160 };
161 assert_ne!(length, 0);
162 unsafe { LLVM7Type(llvm::LLVMVectorType(element.0, length)) }
163 }
164 fn build_struct(&self, members: &[LLVM7Type]) -> LLVM7Type {
165 assert_eq!(members.len() as c_uint as usize, members.len());
166 unsafe {
167 LLVM7Type(llvm::LLVMStructTypeInContext(
168 self.context,
169 members.as_ptr() as *mut llvm::LLVMTypeRef,
170 members.len() as c_uint,
171 false as llvm::LLVMBool,
172 ))
173 }
174 }
175 fn build_function(&self, arguments: &[LLVM7Type], return_type: Option<LLVM7Type>) -> LLVM7Type {
176 assert_eq!(arguments.len() as c_uint as usize, arguments.len());
177 unsafe {
178 LLVM7Type(llvm::LLVMFunctionType(
179 return_type
180 .unwrap_or_else(|| LLVM7Type(llvm::LLVMVoidTypeInContext(self.context)))
181 .0,
182 arguments.as_ptr() as *mut llvm::LLVMTypeRef,
183 arguments.len() as c_uint,
184 false as llvm::LLVMBool,
185 ))
186 }
187 }
188 }
189
190 #[derive(Clone)]
191 #[repr(transparent)]
192 pub struct LLVM7Value(llvm::LLVMValueRef);
193
194 impl fmt::Debug for LLVM7Value {
195 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196 unsafe {
197 let string =
198 LLVM7String::from_ptr(llvm::LLVMPrintValueToString(self.0)).ok_or(fmt::Error)?;
199 f.write_str(&string.to_string_lossy())
200 }
201 }
202 }
203
204 impl<'a> backend::Value<'a> for LLVM7Value {
205 type Context = LLVM7Context;
206 }
207
208 #[derive(Clone)]
209 #[repr(transparent)]
210 pub struct LLVM7BasicBlock(llvm::LLVMBasicBlockRef);
211
212 impl fmt::Debug for LLVM7BasicBlock {
213 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214 use self::backend::BasicBlock;
215 unsafe {
216 let string = LLVM7String::from_ptr(llvm::LLVMPrintValueToString(self.as_value().0))
217 .ok_or(fmt::Error)?;
218 f.write_str(&string.to_string_lossy())
219 }
220 }
221 }
222
223 impl<'a> backend::BasicBlock<'a> for LLVM7BasicBlock {
224 type Context = LLVM7Context;
225 fn as_value(&self) -> LLVM7Value {
226 unsafe { LLVM7Value(llvm::LLVMBasicBlockAsValue(self.0)) }
227 }
228 }
229
230 impl<'a> backend::BuildableBasicBlock<'a> for LLVM7BasicBlock {
231 type Context = LLVM7Context;
232 fn as_basic_block(&self) -> LLVM7BasicBlock {
233 self.clone()
234 }
235 }
236
237 pub struct LLVM7Function {
238 context: llvm::LLVMContextRef,
239 function: llvm::LLVMValueRef,
240 parameters: Box<[LLVM7Value]>,
241 }
242
243 impl fmt::Debug for LLVM7Function {
244 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
245 unsafe {
246 let string = LLVM7String::from_ptr(llvm::LLVMPrintValueToString(self.function))
247 .ok_or(fmt::Error)?;
248 f.write_str(&string.to_string_lossy())
249 }
250 }
251 }
252
253 impl<'a> backend::Function<'a> for LLVM7Function {
254 type Context = LLVM7Context;
255 fn as_value(&self) -> LLVM7Value {
256 LLVM7Value(self.function)
257 }
258 fn append_new_basic_block(&mut self, name: Option<&str>) -> LLVM7BasicBlock {
259 let name = CString::new(name.unwrap_or("")).unwrap();
260 unsafe {
261 LLVM7BasicBlock(llvm::LLVMAppendBasicBlockInContext(
262 self.context,
263 self.function,
264 name.as_ptr(),
265 ))
266 }
267 }
268 fn parameters(&self) -> &[LLVM7Value] {
269 &self.parameters
270 }
271 }
272
273 pub struct LLVM7Context {
274 context: Option<ManuallyDrop<OwnedContext>>,
275 modules: ManuallyDrop<RefCell<Vec<OwnedModule>>>,
276 config: LLVM7CompilerConfig,
277 }
278
279 impl fmt::Debug for LLVM7Context {
280 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
281 f.debug_struct("LLVM7Context")
282 .field("config", &self.config)
283 .finish()
284 }
285 }
286
287 impl Drop for LLVM7Context {
288 fn drop(&mut self) {
289 unsafe {
290 ManuallyDrop::drop(&mut self.modules);
291 if let Some(context) = &mut self.context {
292 ManuallyDrop::drop(context);
293 }
294 }
295 }
296 }
297
298 impl<'a> backend::Context<'a> for LLVM7Context {
299 type Value = LLVM7Value;
300 type BasicBlock = LLVM7BasicBlock;
301 type BuildableBasicBlock = LLVM7BasicBlock;
302 type Function = LLVM7Function;
303 type Type = LLVM7Type;
304 type TypeBuilder = LLVM7TypeBuilder;
305 type Module = LLVM7Module;
306 type VerifiedModule = LLVM7Module;
307 type AttachedBuilder = LLVM7Builder;
308 type DetachedBuilder = LLVM7Builder;
309 fn create_module(&self, name: &str) -> LLVM7Module {
310 let name = CString::new(name).unwrap();
311 let mut modules = self.modules.borrow_mut();
312 unsafe {
313 let module = OwnedModule(llvm::LLVMModuleCreateWithNameInContext(
314 name.as_ptr(),
315 self.context.as_ref().unwrap().0,
316 ));
317 let module_ref = module.0;
318 modules.push(module);
319 LLVM7Module {
320 context: self.context.as_ref().unwrap().0,
321 module: module_ref,
322 name_set: HashSet::new(),
323 }
324 }
325 }
326 fn create_builder(&self) -> LLVM7Builder {
327 unsafe {
328 LLVM7Builder(llvm::LLVMCreateBuilderInContext(
329 self.context.as_ref().unwrap().0,
330 ))
331 }
332 }
333 fn create_type_builder(&self) -> LLVM7TypeBuilder {
334 LLVM7TypeBuilder {
335 context: self.context.as_ref().unwrap().0,
336 variable_vector_length_multiplier: self.config.variable_vector_length_multiplier,
337 }
338 }
339 }
340
341 #[repr(transparent)]
342 pub struct LLVM7Builder(llvm::LLVMBuilderRef);
343
344 impl Drop for LLVM7Builder {
345 fn drop(&mut self) {
346 unsafe {
347 llvm::LLVMDisposeBuilder(self.0);
348 }
349 }
350 }
351
352 impl<'a> backend::AttachedBuilder<'a> for LLVM7Builder {
353 type Context = LLVM7Context;
354 fn current_basic_block(&self) -> LLVM7BasicBlock {
355 unsafe { LLVM7BasicBlock(llvm::LLVMGetInsertBlock(self.0)) }
356 }
357 fn build_alloca(&mut self, variable_type: LLVM7Type) -> LLVM7Value {
358 unsafe {
359 LLVM7Value(llvm::LLVMBuildAlloca(
360 self.0,
361 variable_type.0,
362 EMPTY_C_STR.as_ptr(),
363 ))
364 }
365 }
366 fn build_return(self, value: Option<LLVM7Value>) -> LLVM7Builder {
367 unsafe {
368 match value {
369 Some(value) => llvm::LLVMBuildRet(self.0, value.0),
370 None => llvm::LLVMBuildRetVoid(self.0),
371 };
372 llvm::LLVMClearInsertionPosition(self.0);
373 }
374 self
375 }
376 }
377
378 impl<'a> backend::DetachedBuilder<'a> for LLVM7Builder {
379 type Context = LLVM7Context;
380 fn attach(self, basic_block: LLVM7BasicBlock) -> LLVM7Builder {
381 unsafe {
382 llvm::LLVMPositionBuilderAtEnd(self.0, basic_block.0);
383 }
384 self
385 }
386 }
387
388 struct OwnedModule(llvm::LLVMModuleRef);
389
390 impl Drop for OwnedModule {
391 fn drop(&mut self) {
392 unsafe {
393 llvm::LLVMDisposeModule(self.0);
394 }
395 }
396 }
397
398 impl OwnedModule {
399 unsafe fn take(mut self) -> llvm::LLVMModuleRef {
400 let retval = self.0;
401 self.0 = null_mut();
402 retval
403 }
404 }
405
406 struct OwnedContext(llvm::LLVMContextRef);
407
408 impl Drop for OwnedContext {
409 fn drop(&mut self) {
410 unsafe {
411 llvm::LLVMContextDispose(self.0);
412 }
413 }
414 }
415
416 pub struct LLVM7Module {
417 context: llvm::LLVMContextRef,
418 module: llvm::LLVMModuleRef,
419 name_set: HashSet<String>,
420 }
421
422 impl fmt::Debug for LLVM7Module {
423 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
424 unsafe {
425 let string = LLVM7String::from_ptr(llvm::LLVMPrintModuleToString(self.module))
426 .ok_or(fmt::Error)?;
427 f.write_str(&string.to_string_lossy())
428 }
429 }
430 }
431
432 impl<'a> backend::Module<'a> for LLVM7Module {
433 type Context = LLVM7Context;
434 fn set_source_file_name(&mut self, source_file_name: &str) {
435 unsafe {
436 llvm::LLVMSetSourceFileName(
437 self.module,
438 source_file_name.as_ptr() as *const c_char,
439 source_file_name.len(),
440 )
441 }
442 }
443 fn add_function(&mut self, name: &str, ty: LLVM7Type) -> LLVM7Function {
444 fn is_start_char(c: char) -> bool {
445 if c.is_ascii_alphabetic() {
446 true
447 } else {
448 match c {
449 '_' | '.' | '$' | '-' => true,
450 _ => false,
451 }
452 }
453 }
454 fn is_continue_char(c: char) -> bool {
455 is_start_char(c) || c.is_ascii_digit()
456 }
457 assert!(is_start_char(name.chars().next().unwrap()));
458 assert!(name.chars().all(is_continue_char));
459 assert!(self.name_set.insert(name.into()));
460 let name = CString::new(name).unwrap();
461 unsafe {
462 let function = llvm::LLVMAddFunction(self.module, name.as_ptr(), ty.0);
463 let mut parameters = Vec::new();
464 parameters.resize(llvm::LLVMCountParams(function) as usize, null_mut());
465 llvm::LLVMGetParams(function, parameters.as_mut_ptr());
466 let parameters: Vec<_> = parameters.into_iter().map(LLVM7Value).collect();
467 LLVM7Function {
468 context: self.context,
469 function: llvm::LLVMAddFunction(self.module, name.as_ptr(), ty.0),
470 parameters: parameters.into_boxed_slice(),
471 }
472 }
473 }
474 fn verify(self) -> Result<LLVM7Module, backend::VerificationFailure<'a, LLVM7Module>> {
475 unsafe {
476 let mut message = null_mut();
477 let broken = to_bool(llvm::LLVMVerifyModule(
478 self.module,
479 llvm::LLVMReturnStatusAction,
480 &mut message,
481 ));
482 if broken {
483 let message = LLVM7String::from_ptr(message).unwrap();
484 let message = message.to_string_lossy();
485 Err(backend::VerificationFailure::new(self, message.as_ref()))
486 } else {
487 Ok(self)
488 }
489 }
490 }
491 unsafe fn to_verified_module_unchecked(self) -> LLVM7Module {
492 self
493 }
494 }
495
496 impl<'a> backend::VerifiedModule<'a> for LLVM7Module {
497 type Context = LLVM7Context;
498 fn into_module(self) -> LLVM7Module {
499 self
500 }
501 }
502
503 struct LLVM7TargetMachine(llvm::LLVMTargetMachineRef);
504
505 impl Drop for LLVM7TargetMachine {
506 fn drop(&mut self) {
507 unsafe {
508 llvm::LLVMDisposeTargetMachine(self.0);
509 }
510 }
511 }
512
513 impl LLVM7TargetMachine {
514 fn take(mut self) -> llvm::LLVMTargetMachineRef {
515 let retval = self.0;
516 self.0 = null_mut();
517 retval
518 }
519 }
520
521 struct LLVM7OrcJITStack(llvm::LLVMOrcJITStackRef);
522
523 impl Drop for LLVM7OrcJITStack {
524 fn drop(&mut self) {
525 unsafe {
526 match llvm::LLVMOrcDisposeInstance(self.0) {
527 llvm::LLVMOrcErrSuccess => {}
528 _ => {
529 panic!("LLVMOrcDisposeInstance failed");
530 }
531 }
532 }
533 }
534 }
535
536 fn initialize_native_target() {
537 static ONCE: Once = ONCE_INIT;
538 ONCE.call_once(|| unsafe {
539 llvm::LLVM_InitializeNativeTarget();
540 llvm::LLVM_InitializeNativeAsmPrinter();
541 llvm::LLVM_InitializeNativeAsmParser();
542 });
543 }
544
545 extern "C" fn symbol_resolver_fn<Void>(name: *const c_char, _lookup_context: *mut Void) -> u64 {
546 let name = unsafe { CStr::from_ptr(name) };
547 panic!("symbol_resolver_fn is unimplemented: name = {:?}", name)
548 }
549
550 #[derive(Copy, Clone)]
551 pub struct LLVM7Compiler;
552
553 impl backend::Compiler for LLVM7Compiler {
554 type Config = LLVM7CompilerConfig;
555 fn name(self) -> &'static str {
556 "LLVM 7"
557 }
558 fn run<U: backend::CompilerUser>(
559 self,
560 user: U,
561 config: LLVM7CompilerConfig,
562 ) -> Result<Box<dyn backend::CompiledCode<U::FunctionKey>>, U::Error> {
563 unsafe {
564 initialize_native_target();
565 let context = OwnedContext(llvm::LLVMContextCreate());
566 let modules = Vec::new();
567 let mut context = LLVM7Context {
568 context: Some(ManuallyDrop::new(context)),
569 modules: ManuallyDrop::new(RefCell::new(modules)),
570 config: config.clone(),
571 };
572 let backend::CompileInputs {
573 module,
574 callable_functions,
575 } = user.run(&context)?;
576 let callable_functions: Vec<_> = callable_functions
577 .into_iter()
578 .map(|(key, callable_function)| {
579 assert_eq!(
580 llvm::LLVMGetGlobalParent(callable_function.function),
581 module.module
582 );
583 let name: CString =
584 CStr::from_ptr(llvm::LLVMGetValueName(callable_function.function)).into();
585 assert_ne!(name.to_bytes().len(), 0);
586 (key, name)
587 })
588 .collect();
589 let module = context
590 .modules
591 .get_mut()
592 .drain(..)
593 .find(|v| v.0 == module.module)
594 .unwrap();
595 let target_triple = LLVM7String::from_ptr(llvm::LLVMGetDefaultTargetTriple()).unwrap();
596 let mut target = null_mut();
597 let mut error = null_mut();
598 let success = !to_bool(llvm::LLVMGetTargetFromTriple(
599 target_triple.as_ptr(),
600 &mut target,
601 &mut error,
602 ));
603 if !success {
604 let error = LLVM7String::from_ptr(error).unwrap();
605 return Err(U::create_error(error.to_string_lossy().into()));
606 }
607 if !to_bool(llvm::LLVMTargetHasJIT(target)) {
608 return Err(U::create_error(format!(
609 "target {:?} doesn't support JIT",
610 target_triple
611 )));
612 }
613 let host_cpu_name = LLVM7String::from_ptr(llvm::LLVMGetHostCPUName()).unwrap();
614 let host_cpu_features = LLVM7String::from_ptr(llvm::LLVMGetHostCPUFeatures()).unwrap();
615 let target_machine = LLVM7TargetMachine(llvm::LLVMCreateTargetMachine(
616 target,
617 target_triple.as_ptr(),
618 host_cpu_name.as_ptr(),
619 host_cpu_features.as_ptr(),
620 match config.optimization_mode {
621 backend::OptimizationMode::NoOptimizations => llvm::LLVMCodeGenLevelNone,
622 backend::OptimizationMode::Normal => llvm::LLVMCodeGenLevelDefault,
623 },
624 llvm::LLVMRelocDefault,
625 llvm::LLVMCodeModelJITDefault,
626 ));
627 assert!(!target_machine.0.is_null());
628 let orc_jit_stack =
629 LLVM7OrcJITStack(llvm::LLVMOrcCreateInstance(target_machine.take()));
630 let mut module_handle = 0;
631 if llvm::LLVMOrcErrSuccess
632 != llvm::LLVMOrcAddEagerlyCompiledIR(
633 orc_jit_stack.0,
634 &mut module_handle,
635 module.take(),
636 Some(symbol_resolver_fn),
637 null_mut(),
638 )
639 {
640 return Err(U::create_error("compilation failed".into()));
641 }
642 let mut functions: HashMap<_, _> = HashMap::new();
643 for (key, name) in callable_functions {
644 let mut address: llvm::LLVMOrcTargetAddress = mem::zeroed();
645 if llvm::LLVMOrcErrSuccess
646 != llvm::LLVMOrcGetSymbolAddressIn(
647 orc_jit_stack.0,
648 &mut address,
649 module_handle,
650 name.as_ptr(),
651 )
652 {
653 return Err(U::create_error(format!(
654 "function not found in compiled module: {:?}",
655 name
656 )));
657 }
658 let address: Option<unsafe extern "C" fn()> = mem::transmute(address as usize);
659 if functions.insert(key, address.unwrap()).is_some() {
660 return Err(U::create_error(format!("duplicate function: {:?}", name)));
661 }
662 }
663 struct CompiledCode<K: Hash + Eq + Send + Sync + 'static> {
664 functions: HashMap<K, unsafe extern "C" fn()>,
665 orc_jit_stack: ManuallyDrop<LLVM7OrcJITStack>,
666 context: ManuallyDrop<OwnedContext>,
667 }
668 unsafe impl<K: Hash + Eq + Send + Sync + 'static> Send for CompiledCode<K> {}
669 unsafe impl<K: Hash + Eq + Send + Sync + 'static> Sync for CompiledCode<K> {}
670 impl<K: Hash + Eq + Send + Sync + 'static> Drop for CompiledCode<K> {
671 fn drop(&mut self) {
672 unsafe {
673 ManuallyDrop::drop(&mut self.orc_jit_stack);
674 ManuallyDrop::drop(&mut self.context);
675 }
676 }
677 }
678 impl<K: Hash + Eq + Send + Sync + 'static> backend::CompiledCode<K> for CompiledCode<K> {
679 fn get(&self, key: &K) -> Option<unsafe extern "C" fn()> {
680 Some(*self.functions.get(key)?)
681 }
682 }
683 Ok(Box::new(CompiledCode {
684 functions,
685 orc_jit_stack: ManuallyDrop::new(orc_jit_stack),
686 context: context.context.take().unwrap(),
687 }))
688 }
689 }
690 }