Möglicher GCC-Fehler bei der Rückgabe von Struct aus einer Funktion

Lesezeit: 3 Minuten

Benutzeravatar von vitorhnn
vitorhnn

Ich glaube, ich habe bei der Implementierung von O’Neills PCG PRNG einen Fehler in GCC gefunden. (Ursprünglicher Code im Compiler Explorer von Godbolt)

Nach dem Multiplizieren oldstate durch MULTIPLIER(Ergebnis in rdi gespeichert), fügt GCC dieses Ergebnis nicht hinzu INCREMENTmovabs’ing INCREMENT stattdessen an rdx, das dann als Rückgabewert von rand32_ret.state verwendet wird

Ein minimal reproduzierbares Beispiel (Compiler-Explorer):

#include <stdint.h>

struct retstruct {
    uint32_t a;
    uint64_t b;
};

struct retstruct fn(uint64_t input)
{
    struct retstruct ret;

    ret.a = 0;
    ret.b = input * 11111111111 + 111111111111;

    return ret;
}

Generierte Assembly (GCC 9.2, x86_64, -O3):

fn:
  movabs rdx, 11111111111     # multiplier constant (doesn't fit in imm32)
  xor eax, eax                # ret.a = 0
  imul rdi, rdx
  movabs rdx, 111111111111    # add constant; one more 1 than multiplier
     # missing   add rdx, rdi   # ret.b=... that we get with clang or older gcc
  ret
# returns RDX:RAX = constant 111111111111 : 0
# independent of input RDI, and not using the imul result it just computed

Interessanterweise wird die Struktur so geändert, dass uint64_t das erste Mitglied ist erzeugt korrekten Codeebenso wie Ändern Sie beide Mitglieder in uint64_t

x86-64 System V gibt Strukturen kleiner als 16 Byte in RDX:RAX zurück, wenn sie trivial kopierbar sind. In diesem Fall befindet sich das 2. Mitglied in RDX, da die obere Hälfte von RAX die Polsterung für die Ausrichtung oder ist .b Wenn .a ist ein schmaler Typ. (sizeof(retstruct) ist so oder so 16; wir verwenden nicht __attribute__((packed)) es respektiert also alignof(uint64_t) = 8.)

Enthält dieser Code ein undefiniertes Verhalten, das es GCC ermöglichen würde, die “falsche” Assembly auszugeben?

Wenn nicht, sollte dies gemeldet werden https://gcc.gnu.org/bugzilla/

  • Kommentare sind nicht für längere Diskussionen gedacht; diese Konversation wurde in den Chat verschoben.

    – Samuel Liew

    24. Januar 2020 um 5:06 Uhr

  • Ich habe es gemeldet

    – vitorhnn

    23. Januar 2020 um 14:42 Uhr

  • @vitorhnn Sieht aus, als wäre es behoben worden master.

    – SS Anne

    24. Januar 2020 um 0:50 Uhr

  • GCC erzeugt eine eigenständige Definition der Funktion; das ist es, was wir betrachten, unabhängig davon, ob es das ist, was läuft, wenn Sie es zusammen mit anderen Funktionen in einer Übersetzungseinheit kompilieren. Sie könnten es genauso einfach testen, ohne es tatsächlich zu verwenden __attribute__((noinline)) B. durch Kompilieren in einer Übersetzungseinheit selbst und Verlinken ohne LTO oder durch Kompilieren mit -fPIC was impliziert, dass alle globalen Symbole (standardmäßig) interponierbar sind, also nicht in Anrufer eingebunden werden können. Aber wirklich ist das Problem erkennbar, wenn man sich das generierte asm ansieht, unabhängig von Anrufern.

    – Peter Cordes

    23. Januar 2020 um 5:03 Uhr


  • Fair genug, @PeterCordes, obwohl ich einigermaßen zuversichtlich bin, dass dieses Detail in Godbolt unter mir geändert wurde.

    – Johannes Bollinger

    23. Januar 2020 um 5:15 Uhr

  • Version 1 der mit Godbolt verknüpften Frage mit nur der Funktion in einer Übersetzungseinheit, wie der Status der Frage selbst, als Sie geantwortet haben. Ich habe nicht alle Überarbeitungen oder Kommentare überprüft, die Sie sich hätten ansehen können. Wasser unter der Brücke, aber ich glaube nicht, dass jemals behauptet wurde, dass die eigenständige Asm-Definition nur gebrochen wurde, wenn die Quelle verwendet wurde __attribute__((noinline)). (Das wäre schockierend, nicht nur überraschend, wie ein GCC-Korrektheitsfehler ist). Wahrscheinlich wurde das nur erwähnt, um einen Testanrufer zu machen, der das Ergebnis druckt.

    – Peter Cordes

    23. Januar 2020 um 5:27 Uhr


1423310cookie-checkMöglicher GCC-Fehler bei der Rückgabe von Struct aus einer Funktion

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy