No, rustc_target::abi::call
is for native calling conventions, I'm not sure we have any support for avoiding the use of the i128
LLVM type (though @nagisa might know something I don't).
Based on the #2
in your error, if I had to guess, the lowering of a LLVM i128
return type to 4 registers (each 32-bit) is failing on the third register.
That is, it seems to me that not only does LLVM already internally treat it like -> (i64, i64)
, it goes all the way to -> (i32, i32, i32, i32)
which requires four return registers.
Now, many architectures likely only have two registers (if that) reserved for returning values, so you may be wondering, how does that even work on other targets?
Looking at a x64 example of -> (i128, i128)
, the LLVM IR simply returns the two values as if they would go into registers:
define { i128, i128 } @test() unnamed_addr #0 {
ret { i128, i128 } { i128 1, i128 2 }
}
But you can also see that the assembly doesn't actually return in any registers:
test:
mov rax, rdi
mov qword ptr [rdi + 24], 0
mov qword ptr [rdi + 16], 2
mov qword ptr [rdi + 8], 0
mov qword ptr [rdi], 1
ret
Instead, it appears that LLVM implicitly converted the function to use an indirect return pointer aka sret
(which Rust would do explicitly for large enough types - my pair would qualify if not for the "scalar pair" optimization).
Now looking at some relevant LLVM source code, it seems that it offers this functionality independent of target, and most targets seem to call CheckReturn
from their own CanLowerReturn
. And in that case, SelectionDAGBuilder::visitRet
will automatically switch to indirect returns (there's a few more places in that file where CanLowerReturn
is checked, like in LowerArguments
).
Given all the automation, my best guess is that the LLVM target you have there lacks a valid implementation of TargetLowering::CanLowerReturn
- the default is return true;
so if omitted, it will invalidly try to return everything in registers.
Not sure how to best test it, but note that i128
isn't necessary and -> (i64, i64)
will also drain all of your return registers when CanLowerReturn
is not implemented.
But anyway, this should be trivial to fix, just reuse any of the minimal impls, e.g. the MSP430 one - AFAICT all that's needed is to replace RetCC_MSP430
with RetCC_Opus3
(and RetCC_Opus3
should already exist, in order to be able to call AnalyzeReturn
with it, since that's where you're getting the error right now).