pcwang-thead added a comment. Herald added a subscriber: StephenFan. In D70401#3391561 <https://reviews.llvm.org/D70401#3391561>, @khchen wrote:
> I found > https://github.com/llvm/llvm-test-suite/blob/main/SingleSource/UnitTests/2003-05-26-Shorts.c > result is mismatched with gcc's (-march=rv32e -mabi=ilp32e). > Did you have same issue? I got the same issue, but it may be not this patch's problem. Here is the reduced case: #include <stdio.h> unsigned long long getL() { return 0xafafafafc5c5b8a3ull; } int main(int argc, char **argv) { unsigned long long UL = getL(); /* 0xafafafafc5c5b8a3 */ unsigned int ui = (unsigned int)UL; /* 0xc5c5b8a3 = 3318069411 */ printf("ui = %u (0x%x)\t\tUL-ui = %lld (0x%llx)\n", ui, ui, UL - ui, UL - ui); } GCC output is: ui = 3318069411 (0xc5c5b8a3) UL-ui = -5787213829993660416 (0xafafafaf00000000) LLVM output is: ui = 3318069411 (0xc5c5b8a3) UL-ui = 0 (0xafafafaf) The problem is the way to pass arguments to `printf`. GCC asm: li a4,-1347440640 addi sp,sp,-24 addi a4,a4,-81 sw a4,8(sp) lw a5,8(sp) li a2,-976896000 addi a2,a2,-1885 lui a0,%hi(.LC1) sw a5,0(sp) li a3,0 li a5,0 mv a1,a2 addi a0,a0,%lo(.LC1) sw ra,20(sp) sw a3,4(sp) call printf LLVM asm: addi sp, sp, -16 sw ra, 12(sp) # 4-byte Folded Spill sw s0, 8(sp) # 4-byte Folded Spill addi s0, sp, 16 andi sp, sp, -8 lui a0, 719611 addi a5, a0, -81 sw a5, 4(sp) lui a0, %hi(.L.str) addi a0, a0, %lo(.L.str) lui a1, 810076 addi a1, a1, -1885 sw zero, 0(sp) mv a2, a1 mv a4, zero call printf Both GCC and LLVM pass format string and two `ui` by `a0, a1, a2`, the difference is how they pass rest variadic arguments. `UL-ui` is with 2*XLEN size, so it will be spilt to two part (low and high 32-bits). Low part is 0x00000000, high part is 0xafafafaf. For GCC: First UL-ui : low -> a3, high -> a4 Second UL-ui : low -> a5, high -> stack.0 For LLVM: First UL-ui : low -> a4, high -> a5 Second UL-ui : low -> stack.0, high -> stack.1 Because we use GLIBC compiled by GCC while linking with LLVM's output, so in `printf`'s view: a3 -> undefined, so it is zero. a4 -> low part, 0x00000000 a5 -> high part, 0xafafafaf stack.0 -> low part, 0x00000000 stack.1 -> not used It get `0x0000000000000000` and `0x00000000afafafaf` for two `UL-ui` (seen as the output). In the ABI specification, it says (Integer Calling Convention <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#integer-calling-convention>): In the base integer calling convention, variadic arguments are passed in the same manner as named arguments, with one exception. Variadic arguments with 2×XLEN-bit alignment and size at most 2×XLEN bits are passed in an aligned register pair (i.e., the first register in the pair is even-numbered), or on the stack by value if none is available. After a variadic argument has been passed on the stack, all future arguments will also be passed on the stack (i.e. the last argument register may be left unused due to the aligned register pair rule). And this is what LLVM do for ILP32E currently. I saw the same issue on Github(Inconsistent variadic argument passing behavior between ilp32 and ilp32e for long long/double <https://github.com/riscv-collab/riscv-gcc/issues/148>), so shall LLVM be compatible with GCC's behavior? @kito-cheng @khchen Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D70401/new/ https://reviews.llvm.org/D70401 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits