<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/56469>56469</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            PowerPC 32-bit passes float with wrong alignment
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          kernigh
      </td>
    </tr>
</table>

<pre>
    If clang targets 32-bit PowerPC and passes a 4-byte float on the stack, then clang uses a wrong alignment of 8 bytes. This is not compatible with gcc, libffcall, nor libffi, which expect an alignment of 4 bytes. This issue is rare: it can only happen when a function has more than 8 floating-point arguments (because the 32-bit ELF ABI passes 8 such arguments in registers, without allocating stack space) and the 9th or later argument is a float in the prototype.

Given this _pass.c_,

```c
#include <stdio.h>
void pass(float a, float b, float c, float d, float e, float f,
          float g, float h, float i, float j, float k, float l)
{
  printf("i = %g, j = %g, k = %g, l = %g\n", i, j, k, l);
}
```

Today's clang miscompiles it,

```
$ clang-15 -v
clang version 15.0.0 (git@github.com:llvm/llvm-project.git 28b41237e6b296bf777d2f0c13c48031525fcdc4)
Target: powerpc-unknown-openbsd
Thread model: posix
InstalledDir: /home/kernigh/bin
$ clang-15 -S -O1 pass.c
```

I see wrong offsets in _pass.s_,

```
        stwu 1, -16(1)
        lfs 1, 24(1)
        lfs 2, 32(1)
        lfs 3, 40(1)
        lfs 4, 48(1)
```

The stack arguments i, j, k, l are at 8(%r1) before _pass_ allocates its stack frame, or 24(%r1) after. The code must load them into %f1, %f2, %f3, %f4 for _printf_. The correct offsets are 24, 28, 32, 36 (every 4 bytes), but clang uses 24, 32, 40, 48 (every 8 bytes).

I expose the problem by building a shared object `cc -shared -o libpass.so pass.c` (with clang 13, which has the same problem), then calling it with libffcall or libffi.

This _call.lisp_ for GNU CLISP will use libffcall,

```lisp
(ffi:default-foreign-language :stdc)
(ffi:def-call-out pass (:return-type nil)
  (:arguments (a single-float) (b single-float) (c single-float)
              (d single-float) (e single-float) (f single-float)
              (g single-float) (h single-float) (i single-float)
              (j single-float) (k single-float) (l single-float))
  (:library "./libpass.so"))
(pass 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0)
```

This _call.rb_ for Ruby will use libffi,

```rb
require 'fiddle/import'
module Pass
  extend Fiddle::Importer
  dlload './libpass.so'
  extern 'void pass(float, float, float, float, float, float,
                    float, float, float, float, float, float)'
end
Pass.pass 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
```

The output is wrong,

```
$ clisp call.lisp
i = 9, j = 11, k = 3.54381e-29, l = 4.04994e-29
$ ruby call.rb                                                        
i = 9, j = 11, k = 1.875, l = 2
```

If I rebuild libpass.so with gcc, then they give the correct output `i = 9, j = 10, k = 11, l = 12`
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyVV9lyozgU_Rr7RQXFavCDH7J0ulLVNZOa6XlOCRBGCQZGgqT993OuxGK7ne5MyhBtd9W5C1lbHHePJctr3uxZz9Ve9JqFgZPJnj2170I93THeFKzjWgvNOIuc7NgLVtYt71nbsL4STPc8f10FdzRpRl6DPf6uWkx4LffNQTSgKFnKiIN22fdKaoZf0_Ysbw8d72VWC_Yu-4rt85wY1jIry5zXNU2aVtkFSbP3SuYVEz86kfdQ8VxGdCFDD4IkKa7EKrxhMC4HSdvUR1bxroPW76Q6Z-XQ5L2EXRXX7NAqAZtwMrUGy2bvdK2EDHhqIGGarYI0EzmHvcYXo---fHtgN7ePk99Spgdou1DJhimxl7oXShtrYHQ7gG9dt7kRZL3KdMdzsQq25hZIwBbeIUdwkM4MyTg-Xoq0l9Kptm_7YyfclXe_8m7s-6t8E7SP88-km5s_Q_zpidXGs798nAehbPJ6KARbhXe6L2TrVqvwi919a6UFB9xgxXMyxw6zZZgvw2IZimVYzmqw-c_u7JdD1TKUy_BlGb4uQ0BmO1qQ3E6cO4XLg6h0FQQS9tzj-mIj4OVs9no2q5dZfNeAlBaNAka0EWrEhbeTxPsLZ556-Htb8OMqSPQYKgepCf6yBlBk_9F1TLcRWSrHj5nzZhctmzdAiZDrx67neoTLPbhFHt7VkLkQAejX9dthFTzQPwcIeUHwuDjAAOLID8JEbLJgu8nKJEmKoPRyP8yj1Av9OIjLvMij2anfTa6gYOooTXS5MzSvTfveOC3CKdPFeKxSgheIpELU9rCWP-zWYwOE17Uo7qWiLahVtQdA4uFVqEbucdkPmWyu2f03c_70mcXvLxz9yLQQYwpqy1ILG3gW-PpD4J_DUPfvA_Ppih1_A6f6swumE3Wp7YEg-nDfQCYMPtwPaT_yPtyPzH56tn8dXFM-Pk02F1DFlmAIkdQEQqyIJctESenOOOd5ykMGkXpkWCp-MBGL9GNMnWl5iWREyVYgkSNRHAaNAGy5yVgH-LxvKXxK4yUaBNMgnAYRg3hINwH6PPFSirL7dHekdmA8QbKtP_HeENYF4H-c8j65CDsZEupJNbKklohcTQ5dSNOZ1D3HEEpMOyZ3RAwq1AEnwVvWBaVpznQFxQrWZhRNjDJnzpxx0WmpZFnAtRNiNyY6TZ2z6vnhUtGo8JiiCmdPAkd7bHnF1ZBcBK3hMJdINpdH9xwQlOvpgFtL3T0bP3_94x929-3x7yfwACUVr9NSezUsiHoKxpSKcHhTiJIPde8QclB9HTJm4HuqFDeoFPkC1RMKh4Q4VOzIHeQJrCvRD6pxqF6xRtYnMWD3z-otXA4P1MIxmZ4ASEX42mJ-uXhZYugP54prxOLaYvlJjvtrxNW1RflJji_XiF-vLdY_cbx0Jy4bvdARs8ClcjBD1BS37em9mUvyUVACPCGeCA9KDNvgSfCkeLZ4fKo6Pp30cfR3WWoGpcosJP8aEFXnaJQfQVFldkGJfweJpIBiWsqiqKl4yEPXKhid2COoPAOayidqUUYXiB-9QDP1YCnCG_weDZFQ05GiNtkLXC7dk5xyUQ0d-akHmpuQTw6uXfhJB_Q_2W1nJWGlHZD1rr1Ikz1NHjQJkF4xvTb0SuhlUqvJN75Jkr6h8YPfFB0EdDeYRtQU3M-0MUgobE5MdsM2ZdulI7PSbT8WunEUpr5wbDq0bRngGG23kVmceSsC0wiva379zN8nFPLdNIkXVX7lInxkPaLlN2XjtCScfu2Y_I7Xke3RppsqMJdA610w_Vkh70Qhf9EGN7bx1sUuLLbhlq972ddiN33TjZ8p4-eJ7ZiNKhcfbOtB1buq7ztNgRI84HfST9pG8qKfpBikDy6Ew0O8iTbbdbUrRZkWSbr1PB75sUCjWYg8TDdluQm3aRiva56JWu9W8e0qvl_LXeAFgZf4vhcGESpy6SdBnkVZwvM0LGKOtlYcuARyINht1X6tdkaHbNhrbAJQvV42YSXsEWLizwd8band2Geujbo7o-t_6zldDw">