Add function to call bitcode

This commit is contained in:
Dimitar Apostolov 2020-09-17 13:37:30 +02:00
parent e89af31015
commit 9276fd8c9d
2 changed files with 27 additions and 34 deletions

View file

@ -33,6 +33,8 @@ the `cargo rustc` command above to regenerate it.
> $ cargo rustc --release --lib -- --emit=llvm-ir > $ cargo rustc --release --lib -- --emit=llvm-ir
> ``` > ```
**Note**: In order to be able to address the bitcode functions by name, they need to be defined with the `#[no_mangle]` attribute.
## Importing the bitcode ## Importing the bitcode
The bitcode is a bunch of bytes that aren't particularly human-readable. The bitcode is a bunch of bytes that aren't particularly human-readable.
@ -54,3 +56,7 @@ compiler/gen/src/llvm/builtins.bc
Once that's done, `git status` should show that the `builtins.bc` file Once that's done, `git status` should show that the `builtins.bc` file
has been changed. Commit that change and you're done! has been changed. Commit that change and you're done!
## Calling bitcode functions
Use the `call_bitcode_fn` function defined in `llvm/src/build.rs` to call bitcode funcitons.

View file

@ -2270,28 +2270,30 @@ fn build_int_binop<'a, 'ctx, 'env>(
NumLte => bd.build_int_compare(SLE, lhs, rhs, "int_lte").into(), NumLte => bd.build_int_compare(SLE, lhs, rhs, "int_lte").into(),
NumRemUnchecked => bd.build_int_signed_rem(lhs, rhs, "rem_int").into(), NumRemUnchecked => bd.build_int_signed_rem(lhs, rhs, "rem_int").into(),
NumDivUnchecked => bd.build_int_signed_div(lhs, rhs, "div_int").into(), NumDivUnchecked => bd.build_int_signed_div(lhs, rhs, "div_int").into(),
NumPowInt => { NumPowInt => call_bitcode_fn(NumPowInt, env, &[lhs.into(), rhs.into()], "pow_int_"),
let builtin_fn_name = "pow_int_"; _ => {
unreachable!("Unrecognized int binary operation: {:?}", op);
}
}
}
fn call_bitcode_fn<'a, 'ctx, 'env>(
op: LowLevel,
env: &Env<'a, 'ctx, 'env>,
args: &[BasicValueEnum<'ctx>],
fn_name: &str,
) -> BasicValueEnum<'ctx> {
let fn_val = env let fn_val = env
.module .module
.get_function(builtin_fn_name) .get_function(fn_name)
.unwrap_or_else(|| panic!("Unrecognized builtin function: {:?} - if you're working on the Roc compiler, do you need to rebuild the bitcode? See compiler/builtins/bitcode/README.md", builtin_fn_name)); .unwrap_or_else(|| panic!("Unrecognized builtin function: {:?} - if you're working on the Roc compiler, do you need to rebuild the bitcode? See compiler/builtins/bitcode/README.md", fn_name));
let call = env.builder.build_call(fn_val, args, "call_builtin");
let call = env
.builder
.build_call(fn_val, &[lhs.into(), rhs.into()], "call_builtin");
call.set_call_convention(fn_val.get_call_conventions()); call.set_call_convention(fn_val.get_call_conventions());
call.try_as_basic_value() call.try_as_basic_value()
.left() .left()
.unwrap_or_else(|| panic!("LLVM error: Invalid call for low-level op {:?}", op)) .unwrap_or_else(|| panic!("LLVM error: Invalid call for low-level op {:?}", op))
}
_ => {
unreachable!("Unrecognized int binary operation: {:?}", op);
}
}
} }
fn build_float_binop<'a, 'ctx, 'env>( fn build_float_binop<'a, 'ctx, 'env>(
@ -2375,22 +2377,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
} }
NumToFloat => { NumToFloat => {
// TODO specialize this to be not just for i64! // TODO specialize this to be not just for i64!
let builtin_fn_name = "i64_to_f64_"; call_bitcode_fn(NumToFloat, env, &[arg.into()], "i64_to_f64_")
let fn_val = env
.module
.get_function(builtin_fn_name)
.unwrap_or_else(|| panic!("Unrecognized builtin function: {:?} - if you're working on the Roc compiler, do you need to rebuild the bitcode? See compiler/builtins/bitcode/README.md", builtin_fn_name));
let call = env
.builder
.build_call(fn_val, &[arg.into()], "call_builtin");
call.set_call_convention(fn_val.get_call_conventions());
call.try_as_basic_value()
.left()
.unwrap_or_else(|| panic!("LLVM error: Invalid call for low-level op {:?}", op))
} }
_ => { _ => {
unreachable!("Unrecognized int unary operation: {:?}", op); unreachable!("Unrecognized int unary operation: {:?}", op);