**Problem** In Rust, checked math functions (like `checked_mul`, `overflowing_mul`, `saturating_mul`) are part of the primitive implementation of integers ([see u64](https://doc.rust-lang.org/std/primitive.u64.html) for instance). The Rust compiler builds the Rust [compiler-builtins](https://github.com/rust-lang/compiler-builtins) crate as a step in the compilation processes, since it contains the math builtins to be lowered in the target. For BPF, however, when using those functions in Rust we hit the following errors: ``` ERROR llvm: <unknown>:0:0: in function func i64 (i64, i64): A call to built-in function '__multi3' is not supported. ERROR llvm: <unknown>:0:0: in function func i64 (i64, i64): only small returns supported ``` Those errors come from the following code: ``` pub fn func(a: u64, b: u64) -> u64 { a.saturating_mul(b) } ``` Those functions invoke underneath the llvm instrinc `{ i64, i1 } @llvm.umul.with.overflow.i64(i64, i64)` or its variants. It is very useful to use safe math operations when writing BPF code in Rust, and I would like to add support for those in the target. **Changes** 1. Create a target feature `allow-builtin-calls` to enable code generation for builtin functions. 2. Implement `CanLowerReturn` to fix the error `only small returns supported`. 3. Add code to correctly invoke lib functions. 4. Add a test case together with the corresponding C code.
28 lines
1.1 KiB
LLVM
28 lines
1.1 KiB
LLVM
; RUN: not llc -mtriple=bpf < %s 2> %t1
|
|
; RUN: FileCheck %s < %t1
|
|
; CHECK: error: <unknown>:0:0: in function bar { i64, i32 } (i32, i32, i32, i32, i32): stack arguments are not supported
|
|
|
|
%struct.S = type { i32, i32, i32 }
|
|
|
|
@s = common global %struct.S zeroinitializer, align 4
|
|
|
|
; Function Attrs: nounwind readonly uwtable
|
|
define { i64, i32 } @bar(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) #0 {
|
|
entry:
|
|
%retval.sroa.0.0.copyload = load i64, ptr @s, align 4
|
|
%retval.sroa.2.0.copyload = load i32, ptr getelementptr inbounds (%struct.S, ptr @s, i64 0, i32 2), align 4
|
|
%.fca.0.insert = insertvalue { i64, i32 } undef, i64 %retval.sroa.0.0.copyload, 0
|
|
%.fca.1.insert = insertvalue { i64, i32 } %.fca.0.insert, i32 %retval.sroa.2.0.copyload, 1
|
|
ret { i64, i32 } %.fca.1.insert
|
|
}
|
|
|
|
; CHECK: error: <unknown>:0:0: in function baz void (ptr): aggregate returns are not supported
|
|
|
|
%struct.B = type { [100 x i64] }
|
|
|
|
; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
define dso_local void @baz(ptr noalias nocapture sret(%struct.B) align 8 %agg.result) local_unnamed_addr #0 {
|
|
entry:
|
|
ret void
|
|
}
|