Skip to content

Commit ad1c738

Browse files
committed
Added docs for build_call and build_aggregate_return
1 parent 81455dd commit ad1c738

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

src/builder.rs

+52-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,29 @@ impl Builder {
7373
InstructionValue::new(value)
7474
}
7575

76+
/// Builds a function return instruction for a return type which is an aggregate type (ie structs and arrays).
77+
/// It is not necessary to use this over `build_return` but may be more convenient to use.
78+
///
79+
/// # Example
80+
///
81+
/// ```no_run
82+
/// use inkwell::context::Context;
83+
///
84+
/// // This builds a simple function which returns a struct (tuple) of two ints.
85+
/// let context = Context::create();
86+
/// let module = context.create_module("ret");
87+
/// let builder = context.create_builder();
88+
/// let i32_type = context.i32_type();
89+
/// let i32_three = i32_type.const_int(3, false);
90+
/// let i32_seven = i32_type.const_int(7, false);
91+
/// let struct_type = context.struct_type(&[i32_type.into(), i32_type.into()], false);
92+
/// let fn_type = struct_type.fn_type(&[], false);
93+
/// let fn_value = module.add_function("ret", fn_type, None);
94+
/// let entry = fn_value.append_basic_block("entry");
95+
///
96+
/// builder.position_at_end(&entry);
97+
/// builder.build_aggregate_return(&[i32_three.into(), i32_seven.into()]);
98+
/// ```
7699
pub fn build_aggregate_return(&self, values: &[BasicValueEnum]) -> InstructionValue {
77100
let mut args: Vec<LLVMValueRef> = values.iter()
78101
.map(|val| val.as_value_ref())
@@ -84,6 +107,34 @@ impl Builder {
84107
InstructionValue::new(value)
85108
}
86109

110+
/// Builds a function call instruction. It can take either a `FunctionValue` or a `PointerValue`
111+
/// which is a function pointer. It will panic if the `PointerValue` is not a function pointer.
112+
/// This may be turned into a Result in the future, however.
113+
///
114+
/// # Example
115+
///
116+
/// ```no_run
117+
/// use inkwell::context::Context;
118+
///
119+
/// // A simple function which calls itself:
120+
/// let context = Context::create();
121+
/// let module = context.create_module("ret");
122+
/// let builder = context.create_builder();
123+
/// let i32_type = context.i32_type();
124+
/// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
125+
/// let fn_value = module.add_function("ret", fn_type, None);
126+
/// let entry = fn_value.append_basic_block("entry");
127+
/// let i32_arg = fn_value.get_first_param().unwrap();
128+
///
129+
/// builder.position_at_end(&entry);
130+
///
131+
/// let ret_val = builder.build_call(fn_value, &[i32_arg], "call")
132+
/// .try_as_basic_value()
133+
/// .left()
134+
/// .unwrap();
135+
///
136+
/// builder.build_return(Some(&ret_val));
137+
/// ```
87138
pub fn build_call<F>(&self, function: F, args: &[BasicValueEnum], name: &str) -> CallSiteValue
88139
where
89140
F: Into<FunctionOrPointerValue>,
@@ -1327,7 +1378,7 @@ impl Builder {
13271378
// REVIEW: Is return type correct?
13281379
// SubTypes: I think this should be type: BT -> BT::Value
13291380
// https://llvm.org/docs/LangRef.html#i-va-arg
1330-
pub fn build_va_arg<BT: BasicType>(&self, list: PointerValue, type_: BT , name: &str) -> BasicValueEnum {
1381+
pub fn build_va_arg<BT: BasicType>(&self, list: PointerValue, type_: BT, name: &str) -> BasicValueEnum {
13311382
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
13321383

13331384
let value = unsafe {

tests/all/test_values.rs

+19
Original file line numberDiff line numberDiff line change
@@ -1220,3 +1220,22 @@ fn test_vectors() {
12201220

12211221
assert!(module.verify().is_ok());
12221222
}
1223+
1224+
#[test]
1225+
fn test_aggregate_returns() {
1226+
let context = Context::create();
1227+
let builder = context.create_builder();
1228+
let module = context.create_module("my_mod");
1229+
let i32_type = context.i32_type();
1230+
let i32_three = i32_type.const_int(3, false);
1231+
let i32_seven = i32_type.const_int(7, false);
1232+
let struct_type = context.struct_type(&[i32_type.into(), i32_type.into()], false);
1233+
let fn_type = struct_type.fn_type(&[], false);
1234+
let fn_value = module.add_function("my_func", fn_type, None);
1235+
let bb = fn_value.append_basic_block("entry");
1236+
1237+
builder.position_at_end(&bb);
1238+
builder.build_aggregate_return(&[i32_three.into(), i32_seven.into()]);
1239+
1240+
assert!(module.verify().is_ok());
1241+
}

0 commit comments

Comments
 (0)