@@ -13,20 +13,21 @@ use std::ffi::{CStr, CString};
13
13
use std:: mem:: forget;
14
14
use std:: ops:: Deref ;
15
15
use std:: ptr;
16
+ use std:: rc:: Rc ;
16
17
17
18
// From Docs: A single context is not thread safe.
18
19
// However, different contexts can execute on different threads simultaneously.
19
20
#[ derive( Debug , PartialEq , Eq ) ]
20
21
pub struct Context {
21
- pub ( crate ) context : LLVMContextRef ,
22
+ pub ( crate ) context : Rc < LLVMContextRef > ,
22
23
}
23
24
24
25
impl Context {
25
- pub ( crate ) fn new ( context : LLVMContextRef ) -> Self {
26
+ pub ( crate ) fn new ( context : Rc < LLVMContextRef > ) -> Self {
26
27
assert ! ( !context. is_null( ) ) ;
27
28
28
29
Context {
29
- context : context
30
+ context,
30
31
}
31
32
}
32
33
@@ -44,7 +45,7 @@ impl Context {
44
45
LLVMContextCreate ( )
45
46
} ;
46
47
47
- Context :: new ( context)
48
+ Context :: new ( Rc :: new ( context) )
48
49
}
49
50
50
51
/// Creates a `ContextRef` which references the global context singleton.
@@ -61,7 +62,7 @@ impl Context {
61
62
LLVMGetGlobalContext ( )
62
63
} ;
63
64
64
- ContextRef :: new ( Context :: new ( context) )
65
+ ContextRef :: new ( Context :: new ( Rc :: new ( context) ) )
65
66
}
66
67
67
68
/// Creates a new `Builder` for a `Context`.
@@ -76,7 +77,7 @@ impl Context {
76
77
/// ```
77
78
pub fn create_builder ( & self ) -> Builder {
78
79
let builder = unsafe {
79
- LLVMCreateBuilderInContext ( self . context )
80
+ LLVMCreateBuilderInContext ( * self . context )
80
81
} ;
81
82
82
83
Builder :: new ( builder)
@@ -96,10 +97,10 @@ impl Context {
96
97
let c_string = CString :: new ( name) . expect ( "Conversion to CString failed unexpectedly" ) ;
97
98
98
99
let module = unsafe {
99
- LLVMModuleCreateWithNameInContext ( c_string. as_ptr ( ) , self . context )
100
+ LLVMModuleCreateWithNameInContext ( c_string. as_ptr ( ) , * self . context )
100
101
} ;
101
102
102
- Module :: new ( module)
103
+ Module :: new ( module, Some ( & self ) )
103
104
}
104
105
105
106
// REVIEW: I haven't yet been able to find docs or other wrappers that confirm, but my suspicion
@@ -111,13 +112,13 @@ impl Context {
111
112
let mut err_str = ptr:: null_mut ( ) ;
112
113
113
114
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)
115
116
} ;
116
117
117
118
forget ( memory_buffer) ;
118
119
119
120
if code == 0 {
120
- return Ok ( Module :: new ( module) ) ;
121
+ return Ok ( Module :: new ( module, Some ( & self ) ) ) ;
121
122
}
122
123
123
124
let rust_str = unsafe {
@@ -133,47 +134,47 @@ impl Context {
133
134
134
135
pub fn void_type ( & self ) -> VoidType {
135
136
let void_type = unsafe {
136
- LLVMVoidTypeInContext ( self . context )
137
+ LLVMVoidTypeInContext ( * self . context )
137
138
} ;
138
139
139
140
VoidType :: new ( void_type)
140
141
}
141
142
142
143
pub fn bool_type ( & self ) -> IntType {
143
144
let bool_type = unsafe {
144
- LLVMInt1TypeInContext ( self . context )
145
+ LLVMInt1TypeInContext ( * self . context )
145
146
} ;
146
147
147
148
IntType :: new ( bool_type)
148
149
}
149
150
150
151
pub fn i8_type ( & self ) -> IntType {
151
152
let i8_type = unsafe {
152
- LLVMInt8TypeInContext ( self . context )
153
+ LLVMInt8TypeInContext ( * self . context )
153
154
} ;
154
155
155
156
IntType :: new ( i8_type)
156
157
}
157
158
158
159
pub fn i16_type ( & self ) -> IntType {
159
160
let i16_type = unsafe {
160
- LLVMInt16TypeInContext ( self . context )
161
+ LLVMInt16TypeInContext ( * self . context )
161
162
} ;
162
163
163
164
IntType :: new ( i16_type)
164
165
}
165
166
166
167
pub fn i32_type ( & self ) -> IntType {
167
168
let i32_type = unsafe {
168
- LLVMInt32TypeInContext ( self . context )
169
+ LLVMInt32TypeInContext ( * self . context )
169
170
} ;
170
171
171
172
IntType :: new ( i32_type)
172
173
}
173
174
174
175
pub fn i64_type ( & self ) -> IntType {
175
176
let i64_type = unsafe {
176
- LLVMInt64TypeInContext ( self . context )
177
+ LLVMInt64TypeInContext ( * self . context )
177
178
} ;
178
179
179
180
IntType :: new ( i64_type)
@@ -188,47 +189,47 @@ impl Context {
188
189
189
190
pub fn custom_width_int_type ( & self , bits : u32 ) -> IntType {
190
191
let int_type = unsafe {
191
- LLVMIntTypeInContext ( self . context , bits)
192
+ LLVMIntTypeInContext ( * self . context , bits)
192
193
} ;
193
194
194
195
IntType :: new ( int_type)
195
196
}
196
197
197
198
pub fn f16_type ( & self ) -> FloatType {
198
199
let f16_type = unsafe {
199
- LLVMHalfTypeInContext ( self . context )
200
+ LLVMHalfTypeInContext ( * self . context )
200
201
} ;
201
202
202
203
FloatType :: new ( f16_type)
203
204
}
204
205
205
206
pub fn f32_type ( & self ) -> FloatType {
206
207
let f32_type = unsafe {
207
- LLVMFloatTypeInContext ( self . context )
208
+ LLVMFloatTypeInContext ( * self . context )
208
209
} ;
209
210
210
211
FloatType :: new ( f32_type)
211
212
}
212
213
213
214
pub fn f64_type ( & self ) -> FloatType {
214
215
let f64_type = unsafe {
215
- LLVMDoubleTypeInContext ( self . context )
216
+ LLVMDoubleTypeInContext ( * self . context )
216
217
} ;
217
218
218
219
FloatType :: new ( f64_type)
219
220
}
220
221
221
222
pub fn f128_type ( & self ) -> FloatType {
222
223
let f128_type = unsafe {
223
- LLVMFP128TypeInContext ( self . context )
224
+ LLVMFP128TypeInContext ( * self . context )
224
225
} ;
225
226
226
227
FloatType :: new ( f128_type)
227
228
}
228
229
229
230
pub fn ppc_f128_type ( & self ) -> FloatType {
230
231
let f128_type = unsafe {
231
- LLVMPPCFP128TypeInContext ( self . context )
232
+ LLVMPPCFP128TypeInContext ( * self . context )
232
233
} ;
233
234
234
235
FloatType :: new ( f128_type)
@@ -240,7 +241,7 @@ impl Context {
240
241
. map ( |val| val. as_type_ref ( ) )
241
242
. collect ( ) ;
242
243
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 )
244
245
} ;
245
246
246
247
StructType :: new ( struct_type)
@@ -250,7 +251,7 @@ impl Context {
250
251
let c_string = CString :: new ( name) . expect ( "Conversion to CString failed unexpectedly" ) ;
251
252
252
253
let struct_type = unsafe {
253
- LLVMStructCreateNamed ( self . context , c_string. as_ptr ( ) )
254
+ LLVMStructCreateNamed ( * self . context , c_string. as_ptr ( ) )
254
255
} ;
255
256
256
257
StructType :: new ( struct_type)
@@ -260,7 +261,7 @@ impl Context {
260
261
let c_string = CString :: new ( name) . expect ( "Conversion to CString failed unexpectedly" ) ;
261
262
262
263
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 ( ) )
264
265
} ;
265
266
266
267
BasicBlock :: new ( bb) . expect ( "Appending basic block should never fail" )
@@ -284,7 +285,7 @@ impl Context {
284
285
let c_string = CString :: new ( name) . expect ( "Conversion to CString failed unexpectedly" ) ;
285
286
286
287
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 ( ) )
288
289
} ;
289
290
290
291
BasicBlock :: new ( bb) . expect ( "Prepending basic block should never fail" )
@@ -295,7 +296,7 @@ impl Context {
295
296
. map ( |val| val. as_value_ref ( ) )
296
297
. collect ( ) ;
297
298
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 )
299
300
} ;
300
301
301
302
StructValue :: new ( value)
@@ -308,7 +309,7 @@ impl Context {
308
309
. map ( |val| val. as_value_ref ( ) )
309
310
. collect ( ) ;
310
311
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 )
312
313
} ;
313
314
314
315
MetadataValue :: new ( metadata_value)
@@ -319,30 +320,36 @@ impl Context {
319
320
let c_string = CString :: new ( string) . expect ( "Conversion to CString failed unexpectedly" ) ;
320
321
321
322
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 )
323
324
} ;
324
325
325
326
MetadataValue :: new ( metadata_value)
326
327
}
327
328
328
329
pub fn get_kind_id ( & self , key : & str ) -> u32 {
329
330
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 )
331
332
}
332
333
}
333
334
}
334
335
335
336
impl Drop for Context {
336
337
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
+ }
339
342
}
340
343
}
341
344
}
342
345
343
346
// Alternate strategy would be to just define ownership parameter
344
347
// on Context, and only call destructor if true. Not sure of pros/cons
345
348
// 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.
346
353
#[ derive( Debug , PartialEq , Eq ) ]
347
354
pub struct ContextRef {
348
355
context : Option < Context > ,
@@ -366,6 +373,7 @@ impl Deref for ContextRef {
366
373
367
374
impl Drop for ContextRef {
368
375
fn drop ( & mut self ) {
376
+ // REVIEW: If you forget an Rc type like Context, does that mean it never gets decremented?
369
377
forget ( self . context . take ( ) ) ;
370
378
}
371
379
}
0 commit comments