Skip to content

Commit 86d26ed

Browse files
committed
Start using MaybeUninit for outptrs
1 parent d2e9ee3 commit 86d26ed

File tree

6 files changed

+76
-50
lines changed

6 files changed

+76
-50
lines changed

Diff for: README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
[![codecov](https://codecov.io/gh/TheDan64/inkwell/branch/master/graph/badge.svg)](https://codecov.io/gh/TheDan64/inkwell)
66
[![lines of code](https://tokei.rs/b1/github/TheDan64/inkwell)](https://github.com/Aaronepower/tokei)
77
[![Join the chat at https://gitter.im/inkwell-rs/Lobby](https://badges.gitter.im/inkwell-rs/Lobby.svg)](https://gitter.im/inkwell-rs/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
8-
![Minimum rustc 1.34](https://img.shields.io/badge/rustc-1.34+-brightgreen.svg)
8+
![Minimum rustc 1.36](https://img.shields.io/badge/rustc-1.36+-brightgreen.svg)
99

1010
**I**t's a **N**ew **K**ind of **W**rapper for **E**xposing **LL**VM (*S*afely)
1111

1212
Inkwell aims to help you pen your own programming languages by safely wrapping llvm-sys. It provides a more strongly typed interface than the underlying LLVM API so that certain types of errors can be caught at compile time instead of at LLVM's runtime. This means we are trying to replicate LLVM IR's strong typing as closely as possible. The ultimate goal is to make LLVM safer from the rust end and a bit easier to learn (via documentation) and use.
1313

1414
## Requirements
1515

16-
* Rust 1.34+
16+
* Rust 1.36+
1717
* Rust Stable, Beta, or Nightly
1818
* LLVM 3.6, 3.7, 3.8, 3.9, 4.0, 5.0, 6.0, 7.0, or 8.0
1919

Diff for: src/execution_engine.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::rc::Rc;
1212
use std::ops::Deref;
1313
use std::ffi::CString;
1414
use std::fmt::{self, Debug, Display, Formatter};
15-
use std::mem::{forget, zeroed, transmute_copy, size_of};
15+
use std::mem::{forget, transmute_copy, size_of, MaybeUninit};
1616

1717
static EE_INNER_PANIC: &str = "ExecutionEngineInner should exist until Drop";
1818

@@ -224,17 +224,20 @@ impl ExecutionEngine {
224224
_ => ()
225225
}
226226

227-
let mut new_module = unsafe { zeroed() };
228-
let mut err_string = unsafe { zeroed() };
227+
let mut new_module = MaybeUninit::uninit();
228+
let mut err_string = MaybeUninit::uninit();
229229

230230
let code = unsafe {
231-
LLVMRemoveModule(self.execution_engine_inner(), module.module.get(), &mut new_module, &mut err_string)
231+
LLVMRemoveModule(self.execution_engine_inner(), module.module.get(), new_module.as_mut_ptr(), err_string.as_mut_ptr())
232232
};
233233

234234
if code == 1 {
235-
return Err(RemoveModuleError::LLVMError(LLVMString::new(err_string)));
235+
let err_str = unsafe { err_string.assume_init() };
236+
return Err(RemoveModuleError::LLVMError(LLVMString::new(err_str)));
236237
}
237238

239+
let new_module = unsafe { new_module.assume_init() };
240+
238241
module.module.set(new_module);
239242
*module.owned_by_ee.borrow_mut() = None;
240243

@@ -349,14 +352,16 @@ impl ExecutionEngine {
349352
}
350353

351354
let c_string = CString::new(fn_name).expect("Conversion to CString failed unexpectedly");
352-
let mut function = unsafe { zeroed() };
355+
let mut function = MaybeUninit::uninit();
353356

354357
let code = unsafe {
355-
LLVMFindFunction(self.execution_engine_inner(), c_string.as_ptr(), &mut function)
358+
LLVMFindFunction(self.execution_engine_inner(), c_string.as_ptr(), function.as_mut_ptr())
356359
};
357360

358361
if code == 0 {
359-
return FunctionValue::new(function).ok_or(FunctionLookupError::FunctionNotFound)
362+
let fn_val = unsafe { function.assume_init() };
363+
364+
return FunctionValue::new(fn_val).ok_or(FunctionLookupError::FunctionNotFound)
360365
};
361366

362367
Err(FunctionLookupError::FunctionNotFound)

Diff for: src/memory_buffer.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::object_file::ObjectFile;
66
use crate::support::LLVMString;
77

88
use std::ffi::CString;
9-
use std::mem::{forget, zeroed};
9+
use std::mem::{forget, MaybeUninit};
1010
use std::path::Path;
1111
use std::ptr;
1212
use std::slice;
@@ -28,32 +28,34 @@ impl MemoryBuffer {
2828
pub fn create_from_file(path: &Path) -> Result<Self, LLVMString> {
2929
let path = CString::new(path.to_str().expect("Did not find a valid Unicode path string")).expect("Failed to convert to CString");
3030
let mut memory_buffer = ptr::null_mut();
31-
let mut err_string = unsafe { zeroed() };
31+
let mut err_string = MaybeUninit::uninit();
3232

3333
let return_code = unsafe {
3434
// REVIEW: Unclear why this expects *const i8 instead of *const u8
35-
LLVMCreateMemoryBufferWithContentsOfFile(path.as_ptr() as *const i8, &mut memory_buffer, &mut err_string)
35+
LLVMCreateMemoryBufferWithContentsOfFile(path.as_ptr() as *const i8, &mut memory_buffer, err_string.as_mut_ptr())
3636
};
3737

3838
// TODO: Verify 1 is error code (LLVM can be inconsistent)
3939
if return_code == 1 {
40-
return Err(LLVMString::new(err_string));
40+
let err_str = unsafe { err_string.assume_init() };
41+
return Err(LLVMString::new(err_str));
4142
}
4243

4344
Ok(MemoryBuffer::new(memory_buffer))
4445
}
4546

4647
pub fn create_from_stdin() -> Result<Self, LLVMString> {
4748
let mut memory_buffer = ptr::null_mut();
48-
let mut err_string = unsafe { zeroed() };
49+
let mut err_string = MaybeUninit::uninit();
4950

5051
let return_code = unsafe {
51-
LLVMCreateMemoryBufferWithSTDIN(&mut memory_buffer, &mut err_string)
52+
LLVMCreateMemoryBufferWithSTDIN(&mut memory_buffer, err_string.as_mut_ptr())
5253
};
5354

5455
// TODO: Verify 1 is error code (LLVM can be inconsistent)
5556
if return_code == 1 {
56-
return Err(LLVMString::new(err_string));
57+
let err_str = unsafe { err_string.assume_init() };
58+
return Err(LLVMString::new(err_str));
5759
}
5860

5961
Ok(MemoryBuffer::new(memory_buffer))

Diff for: src/module.rs

+37-20
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::cell::{Cell, RefCell, Ref};
2020
use std::ffi::CStr;
2121
use std::ffi::CString;
2222
use std::fs::File;
23-
use std::mem::{forget, zeroed};
23+
use std::mem::{forget, MaybeUninit};
2424
use std::path::Path;
2525
use std::ptr;
2626
use std::rc::Rc;
@@ -433,17 +433,20 @@ impl Module {
433433
return Err(LLVMString::create(string));
434434
}
435435

436-
let mut execution_engine = unsafe { zeroed() };
437-
let mut err_string = unsafe { zeroed() };
436+
let mut execution_engine = MaybeUninit::uninit();
437+
let mut err_string = MaybeUninit::uninit();
438438
let code = unsafe {
439-
LLVMCreateExecutionEngineForModule(&mut execution_engine, self.module.get(), &mut err_string) // Takes ownership of module
439+
// Takes ownership of module
440+
LLVMCreateExecutionEngineForModule(execution_engine.as_mut_ptr(), self.module.get(), err_string.as_mut_ptr())
440441
};
441442

442443
if code == 1 {
444+
let err_string = unsafe { err_string.assume_init() };
443445
return Err(LLVMString::new(err_string));
444446
}
445447

446448
let context = self.non_global_context.clone();
449+
let execution_engine = unsafe { execution_engine.assume_init() };
447450
let execution_engine = ExecutionEngine::new(Rc::new(execution_engine), context, false);
448451

449452
*self.owned_by_ee.borrow_mut() = Some(execution_engine.clone());
@@ -481,18 +484,21 @@ impl Module {
481484
return Err(LLVMString::create(string));
482485
}
483486

484-
let mut execution_engine = unsafe { zeroed() };
485-
let mut err_string = unsafe { zeroed() };
487+
let mut execution_engine = MaybeUninit::uninit();
488+
let mut err_string = MaybeUninit::uninit();
486489

487490
let code = unsafe {
488-
LLVMCreateInterpreterForModule(&mut execution_engine, self.module.get(), &mut err_string) // Takes ownership of module
491+
// Takes ownership of module
492+
LLVMCreateInterpreterForModule(execution_engine.as_mut_ptr(), self.module.get(), err_string.as_mut_ptr())
489493
};
490494

491495
if code == 1 {
496+
let err_string = unsafe { err_string.assume_init() };
492497
return Err(LLVMString::new(err_string));
493498
}
494499

495500
let context = self.non_global_context.clone();
501+
let execution_engine = unsafe { execution_engine.assume_init() };
496502
let execution_engine = ExecutionEngine::new(Rc::new(execution_engine), context, false);
497503

498504
*self.owned_by_ee.borrow_mut() = Some(execution_engine.clone());
@@ -531,18 +537,21 @@ impl Module {
531537
return Err(LLVMString::create(string));
532538
}
533539

534-
let mut execution_engine = unsafe { zeroed() };
535-
let mut err_string = unsafe { zeroed() };
540+
let mut execution_engine = MaybeUninit::uninit();
541+
let mut err_string = MaybeUninit::uninit();
536542

537543
let code = unsafe {
538-
LLVMCreateJITCompilerForModule(&mut execution_engine, self.module.get(), opt_level as u32, &mut err_string) // Takes ownership of module
544+
// Takes ownership of module
545+
LLVMCreateJITCompilerForModule(execution_engine.as_mut_ptr(), self.module.get(), opt_level as u32, err_string.as_mut_ptr())
539546
};
540547

541548
if code == 1 {
549+
let err_string = unsafe { err_string.assume_init() };
542550
return Err(LLVMString::new(err_string));
543551
}
544552

545553
let context = self.non_global_context.clone();
554+
let execution_engine = unsafe { execution_engine.assume_init() };
546555
let execution_engine = ExecutionEngine::new(Rc::new(execution_engine), context, true);
547556

548557
*self.owned_by_ee.borrow_mut() = Some(execution_engine.clone());
@@ -659,14 +668,15 @@ impl Module {
659668
/// # Remarks
660669
/// See also: http://llvm.org/doxygen/Analysis_2Analysis_8cpp_source.html
661670
pub fn verify(&self) -> Result<(), LLVMString> {
662-
let mut err_str = unsafe { zeroed() };
671+
let mut err_str = MaybeUninit::uninit();
663672

664673
let action = LLVMVerifierFailureAction::LLVMReturnStatusAction;
665674

666675
let code = unsafe {
667-
LLVMVerifyModule(self.module.get(), action, &mut err_str)
676+
LLVMVerifyModule(self.module.get(), action, err_str.as_mut_ptr())
668677
};
669678

679+
let err_str = unsafe { err_str.assume_init() };
670680
if code == 1 && !err_str.is_null() {
671681
return Err(LLVMString::new(err_str));
672682
}
@@ -767,12 +777,13 @@ impl Module {
767777
pub fn print_to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), LLVMString> {
768778
let path_str = path.as_ref().to_str().expect("Did not find a valid Unicode path string");
769779
let path = CString::new(path_str).expect("Could not convert path to CString");
770-
let mut err_string = unsafe { zeroed() };
780+
let mut err_string = MaybeUninit::uninit();
771781
let return_code = unsafe {
772-
LLVMPrintModuleToFile(self.module.get(), path.as_ptr() as *const i8, &mut err_string)
782+
LLVMPrintModuleToFile(self.module.get(), path.as_ptr() as *const i8, err_string.as_mut_ptr())
773783
};
774784

775785
if return_code == 1 {
786+
let err_string = unsafe { err_string.assume_init() };
776787
return Err(LLVMString::new(err_string));
777788
}
778789

@@ -1063,21 +1074,24 @@ impl Module {
10631074
///
10641075
/// ```
10651076
pub fn parse_bitcode_from_buffer(buffer: &MemoryBuffer) -> Result<Self, LLVMString> {
1066-
let mut module = unsafe { zeroed() };
1067-
let mut err_string = unsafe { zeroed() };
1077+
let mut module = MaybeUninit::uninit();
1078+
let mut err_string = MaybeUninit::uninit();
10681079

10691080
// LLVM has a newer version of this function w/o the error result since 3.8 but this deprecated function
10701081
// hasen't yet been removed even in the unreleased LLVM 7. Seems fine to use instead of switching to their
10711082
// error diagnostics handler
10721083
#[allow(deprecated)]
10731084
let success = unsafe {
1074-
LLVMParseBitcode(buffer.memory_buffer, &mut module, &mut err_string)
1085+
LLVMParseBitcode(buffer.memory_buffer, module.as_mut_ptr(), err_string.as_mut_ptr())
10751086
};
10761087

10771088
if success != 0 {
1089+
let err_string = unsafe { err_string.assume_init() };
10781090
return Err(LLVMString::new(err_string));
10791091
}
10801092

1093+
let module = unsafe { module.assume_init() };
1094+
10811095
Ok(Module::new(module, None))
10821096
}
10831097

@@ -1100,21 +1114,24 @@ impl Module {
11001114
///
11011115
/// ```
11021116
pub fn parse_bitcode_from_buffer_in_context(buffer: &MemoryBuffer, context: &Context) -> Result<Self, LLVMString> {
1103-
let mut module = unsafe { zeroed() };
1104-
let mut err_string = unsafe { zeroed() };
1117+
let mut module = MaybeUninit::uninit();
1118+
let mut err_string = MaybeUninit::uninit();
11051119

11061120
// LLVM has a newer version of this function w/o the error result since 3.8 but this deprecated function
11071121
// hasen't yet been removed even in the unreleased LLVM 7. Seems fine to use instead of switching to their
11081122
// error diagnostics handler
11091123
#[allow(deprecated)]
11101124
let success = unsafe {
1111-
LLVMParseBitcodeInContext(*context.context, buffer.memory_buffer, &mut module, &mut err_string)
1125+
LLVMParseBitcodeInContext(*context.context, buffer.memory_buffer, module.as_mut_ptr(), err_string.as_mut_ptr())
11121126
};
11131127

11141128
if success != 0 {
1129+
let err_string = unsafe { err_string.assume_init() };
11151130
return Err(LLVMString::new(err_string));
11161131
}
11171132

1133+
let module = unsafe { module.assume_init() };
1134+
11181135
Ok(Module::new(module, Some(&context)))
11191136
}
11201137

Diff for: src/targets.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use crate::{AddressSpace, OptimizationLevel};
3333

3434
use std::default::Default;
3535
use std::ffi::{CStr, CString};
36-
use std::mem::zeroed;
36+
use std::mem::MaybeUninit;
3737
use std::path::Path;
3838
use std::ptr;
3939
use std::sync::RwLock;
@@ -961,16 +961,15 @@ impl Target {
961961
pub fn from_triple(triple: &str) -> Result<Self, LLVMString> {
962962
let c_string = CString::new(triple).expect("Conversion to CString failed unexpectedly");
963963
let mut target = ptr::null_mut();
964-
let mut err_string = unsafe { zeroed() };
964+
let mut err_string = MaybeUninit::uninit();
965965

966-
let code =
967-
{
966+
let code = {
968967
let _guard = TARGET_LOCK.read().unwrap();
969-
unsafe { LLVMGetTargetFromTriple(c_string.as_ptr(), &mut target, &mut err_string) }
968+
unsafe { LLVMGetTargetFromTriple(c_string.as_ptr(), &mut target, err_string.as_mut_ptr()) }
970969
};
971970

972971
if code == 1 {
973-
// REVIEW: 1 is error value
972+
let err_string = unsafe { err_string.assume_init() };
974973
return Err(LLVMString::new(err_string));
975974
}
976975

@@ -1139,7 +1138,7 @@ impl TargetMachine {
11391138
file_type: FileType,
11401139
) -> Result<MemoryBuffer, LLVMString> {
11411140
let mut memory_buffer = ptr::null_mut();
1142-
let mut err_string = unsafe { zeroed() };
1141+
let mut err_string = MaybeUninit::uninit();
11431142
let return_code = unsafe {
11441143
let module_ptr = module.module.get();
11451144
let file_type_ptr = file_type.as_llvm_file_type();
@@ -1148,12 +1147,13 @@ impl TargetMachine {
11481147
self.target_machine,
11491148
module_ptr,
11501149
file_type_ptr,
1151-
&mut err_string,
1150+
err_string.as_mut_ptr(),
11521151
&mut memory_buffer,
11531152
)
11541153
};
11551154

11561155
if return_code == 1 {
1156+
let err_string = unsafe { err_string.assume_init() };
11571157
return Err(LLVMString::new(err_string));
11581158
}
11591159

@@ -1199,7 +1199,7 @@ impl TargetMachine {
11991199
.to_str()
12001200
.expect("Did not find a valid Unicode path string");
12011201
let path_c_string = CString::new(path).expect("Conversion to CString failed unexpectedly");
1202-
let mut err_string = unsafe { zeroed() };
1202+
let mut err_string = MaybeUninit::uninit();
12031203
let return_code = unsafe {
12041204
// REVIEW: Why does LLVM need a mutable ptr to path...?
12051205
let module_ptr = module.module.get();
@@ -1211,11 +1211,12 @@ impl TargetMachine {
12111211
module_ptr,
12121212
path_ptr,
12131213
file_type_ptr,
1214-
&mut err_string,
1214+
err_string.as_mut_ptr(),
12151215
)
12161216
};
12171217

12181218
if return_code == 1 {
1219+
let err_string = unsafe { err_string.assume_init() };
12191220
return Err(LLVMString::new(err_string));
12201221
}
12211222

Diff for: tests/all/test_targets.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,15 @@ use std::str::from_utf8;
6666

6767
#[test]
6868
fn test_target_and_target_machine() {
69+
Target::initialize_native(&InitializationConfig::default()).expect("Failed to initialize native target");
70+
6971
let bad_target = Target::from_name("asd");
7072

7173
assert!(bad_target.is_none());
7274

73-
let _bad_target2 = Target::from_triple("x86_64-pc-linux-gnu");
75+
let bad_target2 = Target::from_triple("sadas");
7476

75-
// REVIEW: Inconsistent success :(
76-
// assert_eq!(*bad_target2.unwrap_err(), *CString::new("Unable to find target for this triple (no targets are registered)").unwrap());
77+
assert_eq!(bad_target2.unwrap_err().to_string(), "No available targets are compatible with this triple.");
7778

7879
Target::initialize_x86(&InitializationConfig::default());
7980

0 commit comments

Comments
 (0)