Skip to content

Commit 39976ab

Browse files
committed
language tweaks
1 parent 4c385c2 commit 39976ab

File tree

1 file changed

+33
-23
lines changed

1 file changed

+33
-23
lines changed

src/builder.rs

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,19 @@ impl<'ctx> Builder<'ctx> {
163163
}
164164
}
165165

166-
/// Builds an invoke instruction. An invoke is similar to a normal function call, but used to
166+
/// An invoke is similar to a normal function call, but used to
167167
/// call functions that may throw an exception, and then respond to the exception.
168168
///
169169
/// When the called function returns normally, the `then` block is evaluated next. If instead
170-
/// the function threw an exception, the `catch` block is intered. The first non-phi
170+
/// the function threw an exception, the `catch` block is entered. The first non-phi
171171
/// instruction of the catch block must be a `landingpad` instruction. See also
172172
/// [`Builder::build_landing_pad`].
173173
///
174+
/// The [`add_prune_eh_pass`] turns an invoke into a call when the called function is
175+
/// guaranteed to never throw an exception.
176+
///
177+
/// [`add_prune_eh_pass`]: crate::passes::PassManager::add_prune_eh_pass
178+
///
174179
/// This example catches C++ exceptions of type `int`, and returns `0` if an exceptions is thrown.
175180
/// For usage of a cleanup landing pad and the `resume` instruction, see [`Builder::build_resume`]
176181
/// ```no_run
@@ -219,8 +224,9 @@ impl<'ctx> Builder<'ctx> {
219224
/// // the personality function used by C++
220225
/// let personality_function = {
221226
/// let name = "__gxx_personality_v0";
227+
/// let linkage = Some(Linkage::External);
222228
///
223-
/// module.add_function(name, context.i64_type().fn_type(&[], false), None)
229+
/// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
224230
/// };
225231
///
226232
/// // type of an exception in C++
@@ -276,15 +282,17 @@ impl<'ctx> Builder<'ctx> {
276282
}
277283

278284
/// Landing pads are places where control flow jumps to if a [`Builder::build_invoke`] triggered an exception.
279-
/// The landing pad will inspect the exception, and either handle the exception, or after some optional cleanup,
280-
/// will resume the exception handling, causing the exception to bubble up.
285+
/// The landing pad will match the exception against its *clauses*. Depending on the clause
286+
/// that is matched, the exception can then be handled, or resumed after some optional cleanup,
287+
/// causing the exception to bubble up.
281288
///
282289
/// Exceptions in LLVM are designed based on the needs of a C++ compiler, but can be used more generally.
283-
/// Here are some specific examples of landing pads. For a full example, see [`Builder::build_invoke`].
290+
/// Here are some specific examples of landing pads. For a full example of handling an exception, see [`Builder::build_invoke`].
284291
///
285292
/// * **cleanup**: a cleanup landing pad is always visited when unwinding the stack.
286293
/// A cleanup is extra code that needs to be run when unwinding a scope. C++ destructors are a typical example.
287294
/// In a language with reference counting, the cleanup block can decrement the refcount of values in scope.
295+
/// The [`Builder::build_resume`] function has a full example using a cleanup lading pad.
288296
///
289297
/// ```no_run
290298
/// use inkwell::context::Context;
@@ -302,13 +310,13 @@ impl<'ctx> Builder<'ctx> {
302310
/// // the personality function used by C++
303311
/// let personality_function = {
304312
/// let name = "__gxx_personality_v0";
305-
///
306-
/// module.add_function(name, context.i64_type().fn_type(&[], false), None)
313+
/// let linkage = Some(Linkage::External);
314+
///
315+
/// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
307316
/// };
308317
///
309318
/// // make the cleanup landing pad
310-
/// let clauses: &[inkwell::values::PointerValue] = &[];
311-
/// let res = builder.build_landing_pad( exception_type, personality_function, clauses, true, "res");
319+
/// let res = builder.build_landing_pad( exception_type, personality_function, &[], true, "res");
312320
/// ```
313321
///
314322
/// * **catch all**: An implementation of the C++ `catch(...)`, which catches all exceptions.
@@ -330,8 +338,9 @@ impl<'ctx> Builder<'ctx> {
330338
/// // the personality function used by C++
331339
/// let personality_function = {
332340
/// let name = "__gxx_personality_v0";
333-
///
334-
/// module.add_function(name, context.i64_type().fn_type(&[], false), None)
341+
/// let linkage = Some(Linkage::External);
342+
///
343+
/// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
335344
/// };
336345
///
337346
/// // make a null pointer of type i8
@@ -341,7 +350,7 @@ impl<'ctx> Builder<'ctx> {
341350
/// let res = builder.build_landing_pad(exception_type, personality_function, &[null], false, "res");
342351
/// ```
343352
///
344-
/// * **catch a typeinfo**: Catch a specific type of exception. The example uses C++'s type info.
353+
/// * **catch a type of exception**: Catch a specific type of exception. The example uses C++'s type info.
345354
///
346355
/// ```no_run
347356
/// use inkwell::context::Context;
@@ -360,8 +369,9 @@ impl<'ctx> Builder<'ctx> {
360369
/// // the personality function used by C++
361370
/// let personality_function = {
362371
/// let name = "__gxx_personality_v0";
363-
///
364-
/// module.add_function(name, context.i64_type().fn_type(&[], false), None)
372+
/// let linkage = Some(Linkage::External);
373+
///
374+
/// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
365375
/// };
366376
///
367377
/// // link in the C++ type info for the `int` type
@@ -393,8 +403,9 @@ impl<'ctx> Builder<'ctx> {
393403
/// // the personality function used by C++
394404
/// let personality_function = {
395405
/// let name = "__gxx_personality_v0";
396-
///
397-
/// module.add_function(name, context.i64_type().fn_type(&[], false), None)
406+
/// let linkage = Some(Linkage::External);
407+
///
408+
/// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
398409
/// };
399410
///
400411
/// // link in the C++ type info for the `int` type
@@ -405,17 +416,16 @@ impl<'ctx> Builder<'ctx> {
405416
/// let filter_pattern = i8_ptr_type.const_array(&[type_info_int.as_any_value_enum().into_pointer_value()]);
406417
/// let res = builder.build_landing_pad(exception_type, personality_function, &[filter_pattern], false, "res");
407418
/// ```
408-
pub fn build_landing_pad<T, V>(
419+
pub fn build_landing_pad<T>(
409420
&self,
410421
exception_type: T,
411422
personality_function: FunctionValue<'ctx>,
412-
clauses: &[V],
423+
clauses: &[BasicValueEnum<'ctx>],
413424
is_cleanup: bool,
414425
name: &str
415426
) -> BasicValueEnum<'ctx>
416427
where
417428
T: BasicType<'ctx>,
418-
V: BasicValue<'ctx>,
419429
{
420430
let c_string = to_c_str(name);
421431
let num_clauses = clauses.len() as u32;
@@ -498,8 +508,9 @@ impl<'ctx> Builder<'ctx> {
498508
/// // the personality function used by C++
499509
/// let personality_function = {
500510
/// let name = "__gxx_personality_v0";
511+
/// let linkage = Some(Linkage::External);
501512
///
502-
/// module.add_function(name, context.i64_type().fn_type(&[], false), None)
513+
/// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
503514
/// };
504515
///
505516
/// // type of an exception in C++
@@ -508,8 +519,7 @@ impl<'ctx> Builder<'ctx> {
508519
/// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
509520
///
510521
/// // make the landing pad; must give a concrete type to the slice
511-
/// let clauses: &[inkwell::values::PointerValue] = &[];
512-
/// let res = builder.build_landing_pad( exception_type, personality_function, clauses, true, "res");
522+
/// let res = builder.build_landing_pad( exception_type, personality_function, &[], true, "res");
513523
///
514524
/// // do cleanup ...
515525
///

0 commit comments

Comments
 (0)