Informationen, die besagen, dass die Inline-Assembly einen bestimmten Speicherbereich liest
GCC (alle Versionen, die ich bequem testen kann) zeigt an, dass eine Inline-Assembly-Anweisung eine bestimmte Speicherregion liest (ausgedrückt als Zeigerp
und eine Größen
) mit diesem zugegebenermaßen umständlichen Konstrukt:
asm ("..." : : "m" (*(struct { char x[n]; } *)p));
Das funktioniert jedoch nicht in Clang (3. [45]), es wird ein schwerer Fehler angezeigt:
error: fields must have a constant size: 'variable
length array in structure' extension will never be supported
asm ("..." : : "m" (*(struct {char x[n];} *)p));
^
Ist es (idealerweise) ein anderes Konstrukt, das in beiden Compilern den gleichen Effekt erzeugt, oder (falls dies nicht der Fall ist) ein anderes Konstrukt, das nur in clang den gleichen Effekt erzeugt?
Beachten Sie, dass ich für den Fall, dass es mir wichtig ist, keine tatsächlichen Montageanweisungen einfüge. Der Zweck des Konstrukts besteht darin, den Compiler anzuweisen, ein scheinbar totes @ nicht zu löschememset
. Somit könnte das "andere Konstrukt" durchaus überhaupt keine Inline-Montage beinhalten. Bitte schlagen Sie jedoch Konstrukte vor, die wie folgt lautewillkürlic memory oder generieren Sie zusätzlichen Code, wenn es keine Alternative gibt. Schlagen Sie auch NICHT @ vmemset_s
, explicit_bzero
, o.ä; Dies ist ein Versuch,implementiere ein Fallback für diese Funktionen, ohne den Compiler hacken zu müssen.
Full-Scale-Demo-Programm folgt -
#include <string.h>
extern void foo(const char *a, const char *b, const char *c, char *d);
void bar(const char *x, char *y, size_t n)
{
char w[16];
char v[n];
memset(w, 0x11, n);
memset(v, 0x22, n);
foo(w, v, x, y);
memset(w, 0, 16);
memset(v, 0, n);
asm ("" : : "m" (*(struct {char _[n];} *)v));
}
- wie von gcc 5.0 um @ kompilie-O2 -S
, x86-64, CFI goo elided -
bar:
pushq %rbp
leaq 15(%rdx), %rax
movq %rsp, %rbp
pushq %r14
andq $-16, %rax
movq %rsi, %r14
pushq %r13
movl $17, %esi
movq %rdi, %r13
pushq %r12
leaq -48(%rbp), %rdi
pushq %rbx
movq %rdx, %rbx
subq $16, %rsp
subq %rax, %rsp
call memset
movq %rbx, %rdx
movq %rsp, %rdi
movl $34, %esi
call memset
movq %r14, %rcx
movq %r13, %rdx
movq %rsp, %rsi
leaq -48(%rbp), %rdi
call foo
movq %rbx, %rdx
xorl %esi, %esi
movq %rsp, %rdi
call memset
leaq -32(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %rbp
ret
- das Ziel ist es, das @ zu bekommselbe Numme des Blockspeichers füllt sich mit Klirren. Zwei ist falsch, aber vier ist auch falsch.