Skip to content

Commit e934a51

Browse files
committed
Simplified Module & ExecutionEngine API relationship. Fixed rust-lang#27
1 parent c426075 commit e934a51

12 files changed

+207
-105
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ extern crate inkwell;
4141

4242
```rust
4343
use inkwell::context::Context;
44+
use inkwell::OptimizationLevel;
4445
use inkwell::targets::{InitializationConfig, Target};
4546
use std::mem::transmute;
4647

@@ -49,8 +50,7 @@ Target::initialize_native(&InitializationConfig::default())?;
4950
let context = Context::create();
5051
let module = context.create_module("sum");
5152
let builder = context.create_builder();
52-
let execution_engine = module.create_jit_execution_engine(0)?;
53-
let module = execution_engine.get_module_at(0);
53+
let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None)?;
5454

5555
let i64_type = context.i64_type();
5656
let fn_type = i64_type.fn_type(&[&i64_type, &i64_type, &i64_type], false);

src/basic_block.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use values::{FunctionValue, InstructionValue};
66

77
use std::fmt;
88
use std::ffi::{CStr, CString};
9+
use std::rc::Rc;
910

1011
// Apparently BasicBlocks count as LabelTypeKinds, which is
1112
// why they're allow to be casted to values?
@@ -133,7 +134,8 @@ impl BasicBlock {
133134
LLVMGetTypeContext(LLVMTypeOf(LLVMBasicBlockAsValue(self.basic_block)))
134135
};
135136

136-
ContextRef::new(Context::new(context))
137+
// REVIEW: This probably should be somehow using the existing context Rc
138+
ContextRef::new(Context::new(Rc::new(context)))
137139
}
138140
}
139141

src/context.rs

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,21 @@ use std::ffi::{CStr, CString};
1313
use std::mem::forget;
1414
use std::ops::Deref;
1515
use std::ptr;
16+
use std::rc::Rc;
1617

1718
// From Docs: A single context is not thread safe.
1819
// However, different contexts can execute on different threads simultaneously.
1920
#[derive(Debug, PartialEq, Eq)]
2021
pub struct Context {
21-
pub(crate) context: LLVMContextRef,
22+
pub(crate) context: Rc<LLVMContextRef>,
2223
}
2324

2425
impl Context {
25-
pub(crate) fn new(context: LLVMContextRef) -> Self {
26+
pub(crate) fn new(context: Rc<LLVMContextRef>) -> Self {
2627
assert!(!context.is_null());
2728

2829
Context {
29-
context: context
30+
context,
3031
}
3132
}
3233

@@ -44,7 +45,7 @@ impl Context {
4445
LLVMContextCreate()
4546
};
4647

47-
Context::new(context)
48+
Context::new(Rc::new(context))
4849
}
4950

5051
/// Creates a `ContextRef` which references the global context singleton.
@@ -61,7 +62,7 @@ impl Context {
6162
LLVMGetGlobalContext()
6263
};
6364

64-
ContextRef::new(Context::new(context))
65+
ContextRef::new(Context::new(Rc::new(context)))
6566
}
6667

6768
/// Creates a new `Builder` for a `Context`.
@@ -76,7 +77,7 @@ impl Context {
7677
/// ```
7778
pub fn create_builder(&self) -> Builder {
7879
let builder = unsafe {
79-
LLVMCreateBuilderInContext(self.context)
80+
LLVMCreateBuilderInContext(*self.context)
8081
};
8182

8283
Builder::new(builder)
@@ -96,10 +97,10 @@ impl Context {
9697
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
9798

9899
let module = unsafe {
99-
LLVMModuleCreateWithNameInContext(c_string.as_ptr(), self.context)
100+
LLVMModuleCreateWithNameInContext(c_string.as_ptr(), *self.context)
100101
};
101102

102-
Module::new(module)
103+
Module::new(module, Some(&self))
103104
}
104105

105106
// REVIEW: I haven't yet been able to find docs or other wrappers that confirm, but my suspicion
@@ -111,13 +112,13 @@ impl Context {
111112
let mut err_str = ptr::null_mut();
112113

113114
let code = unsafe {
114-
LLVMParseIRInContext(self.context, memory_buffer.memory_buffer, &mut module, &mut err_str)
115+
LLVMParseIRInContext(*self.context, memory_buffer.memory_buffer, &mut module, &mut err_str)
115116
};
116117

117118
forget(memory_buffer);
118119

119120
if code == 0 {
120-
return Ok(Module::new(module));
121+
return Ok(Module::new(module, Some(&self)));
121122
}
122123

123124
let rust_str = unsafe {
@@ -133,47 +134,47 @@ impl Context {
133134

134135
pub fn void_type(&self) -> VoidType {
135136
let void_type = unsafe {
136-
LLVMVoidTypeInContext(self.context)
137+
LLVMVoidTypeInContext(*self.context)
137138
};
138139

139140
VoidType::new(void_type)
140141
}
141142

142143
pub fn bool_type(&self) -> IntType {
143144
let bool_type = unsafe {
144-
LLVMInt1TypeInContext(self.context)
145+
LLVMInt1TypeInContext(*self.context)
145146
};
146147

147148
IntType::new(bool_type)
148149
}
149150

150151
pub fn i8_type(&self) -> IntType {
151152
let i8_type = unsafe {
152-
LLVMInt8TypeInContext(self.context)
153+
LLVMInt8TypeInContext(*self.context)
153154
};
154155

155156
IntType::new(i8_type)
156157
}
157158

158159
pub fn i16_type(&self) -> IntType {
159160
let i16_type = unsafe {
160-
LLVMInt16TypeInContext(self.context)
161+
LLVMInt16TypeInContext(*self.context)
161162
};
162163

163164
IntType::new(i16_type)
164165
}
165166

166167
pub fn i32_type(&self) -> IntType {
167168
let i32_type = unsafe {
168-
LLVMInt32TypeInContext(self.context)
169+
LLVMInt32TypeInContext(*self.context)
169170
};
170171

171172
IntType::new(i32_type)
172173
}
173174

174175
pub fn i64_type(&self) -> IntType {
175176
let i64_type = unsafe {
176-
LLVMInt64TypeInContext(self.context)
177+
LLVMInt64TypeInContext(*self.context)
177178
};
178179

179180
IntType::new(i64_type)
@@ -188,47 +189,47 @@ impl Context {
188189

189190
pub fn custom_width_int_type(&self, bits: u32) -> IntType {
190191
let int_type = unsafe {
191-
LLVMIntTypeInContext(self.context, bits)
192+
LLVMIntTypeInContext(*self.context, bits)
192193
};
193194

194195
IntType::new(int_type)
195196
}
196197

197198
pub fn f16_type(&self) -> FloatType {
198199
let f16_type = unsafe {
199-
LLVMHalfTypeInContext(self.context)
200+
LLVMHalfTypeInContext(*self.context)
200201
};
201202

202203
FloatType::new(f16_type)
203204
}
204205

205206
pub fn f32_type(&self) -> FloatType {
206207
let f32_type = unsafe {
207-
LLVMFloatTypeInContext(self.context)
208+
LLVMFloatTypeInContext(*self.context)
208209
};
209210

210211
FloatType::new(f32_type)
211212
}
212213

213214
pub fn f64_type(&self) -> FloatType {
214215
let f64_type = unsafe {
215-
LLVMDoubleTypeInContext(self.context)
216+
LLVMDoubleTypeInContext(*self.context)
216217
};
217218

218219
FloatType::new(f64_type)
219220
}
220221

221222
pub fn f128_type(&self) -> FloatType {
222223
let f128_type = unsafe {
223-
LLVMFP128TypeInContext(self.context)
224+
LLVMFP128TypeInContext(*self.context)
224225
};
225226

226227
FloatType::new(f128_type)
227228
}
228229

229230
pub fn ppc_f128_type(&self) -> FloatType {
230231
let f128_type = unsafe {
231-
LLVMPPCFP128TypeInContext(self.context)
232+
LLVMPPCFP128TypeInContext(*self.context)
232233
};
233234

234235
FloatType::new(f128_type)
@@ -240,7 +241,7 @@ impl Context {
240241
.map(|val| val.as_type_ref())
241242
.collect();
242243
let struct_type = unsafe {
243-
LLVMStructTypeInContext(self.context, field_types.as_mut_ptr(), field_types.len() as u32, packed as i32)
244+
LLVMStructTypeInContext(*self.context, field_types.as_mut_ptr(), field_types.len() as u32, packed as i32)
244245
};
245246

246247
StructType::new(struct_type)
@@ -250,7 +251,7 @@ impl Context {
250251
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
251252

252253
let struct_type = unsafe {
253-
LLVMStructCreateNamed(self.context, c_string.as_ptr())
254+
LLVMStructCreateNamed(*self.context, c_string.as_ptr())
254255
};
255256

256257
StructType::new(struct_type)
@@ -260,7 +261,7 @@ impl Context {
260261
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
261262

262263
let bb = unsafe {
263-
LLVMAppendBasicBlockInContext(self.context, function.as_value_ref(), c_string.as_ptr())
264+
LLVMAppendBasicBlockInContext(*self.context, function.as_value_ref(), c_string.as_ptr())
264265
};
265266

266267
BasicBlock::new(bb).expect("Appending basic block should never fail")
@@ -284,7 +285,7 @@ impl Context {
284285
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
285286

286287
let bb = unsafe {
287-
LLVMInsertBasicBlockInContext(self.context, basic_block.basic_block, c_string.as_ptr())
288+
LLVMInsertBasicBlockInContext(*self.context, basic_block.basic_block, c_string.as_ptr())
288289
};
289290

290291
BasicBlock::new(bb).expect("Prepending basic block should never fail")
@@ -295,7 +296,7 @@ impl Context {
295296
.map(|val| val.as_value_ref())
296297
.collect();
297298
let value = unsafe {
298-
LLVMConstStructInContext(self.context, args.as_mut_ptr(), args.len() as u32, packed as i32)
299+
LLVMConstStructInContext(*self.context, args.as_mut_ptr(), args.len() as u32, packed as i32)
299300
};
300301

301302
StructValue::new(value)
@@ -308,7 +309,7 @@ impl Context {
308309
.map(|val| val.as_value_ref())
309310
.collect();
310311
let metadata_value = unsafe {
311-
LLVMMDNodeInContext(self.context, tuple_values.as_mut_ptr(), tuple_values.len() as u32)
312+
LLVMMDNodeInContext(*self.context, tuple_values.as_mut_ptr(), tuple_values.len() as u32)
312313
};
313314

314315
MetadataValue::new(metadata_value)
@@ -319,30 +320,36 @@ impl Context {
319320
let c_string = CString::new(string).expect("Conversion to CString failed unexpectedly");
320321

321322
let metadata_value = unsafe {
322-
LLVMMDStringInContext(self.context, c_string.as_ptr(), string.len() as u32)
323+
LLVMMDStringInContext(*self.context, c_string.as_ptr(), string.len() as u32)
323324
};
324325

325326
MetadataValue::new(metadata_value)
326327
}
327328

328329
pub fn get_kind_id(&self, key: &str) -> u32 {
329330
unsafe {
330-
LLVMGetMDKindIDInContext(self.context, key.as_ptr() as *const i8, key.len() as u32)
331+
LLVMGetMDKindIDInContext(*self.context, key.as_ptr() as *const i8, key.len() as u32)
331332
}
332333
}
333334
}
334335

335336
impl Drop for Context {
336337
fn drop(&mut self) {
337-
unsafe {
338-
LLVMContextDispose(self.context);
338+
if Rc::strong_count(&self.context) == 1 {
339+
unsafe {
340+
LLVMContextDispose(*self.context);
341+
}
339342
}
340343
}
341344
}
342345

343346
// Alternate strategy would be to just define ownership parameter
344347
// on Context, and only call destructor if true. Not sure of pros/cons
345348
// compared to this approach other than not needing Deref trait's ugly syntax
349+
// REVIEW: Now that Contexts are ref counted, it may not be necessary to
350+
// have this ContextRef type, however Global Contexts throw a wrench in that
351+
// a bit as it is a special case. get_context() methods as well since they do
352+
// not have access to the original Rc.
346353
#[derive(Debug, PartialEq, Eq)]
347354
pub struct ContextRef {
348355
context: Option<Context>,
@@ -366,6 +373,7 @@ impl Deref for ContextRef {
366373

367374
impl Drop for ContextRef {
368375
fn drop(&mut self) {
376+
// REVIEW: If you forget an Rc type like Context, does that mean it never gets decremented?
369377
forget(self.context.take());
370378
}
371379
}

0 commit comments

Comments
 (0)