Clang x86-64 can't move segment registers

Since clang 6, the following code produces `error: invalid operand for instruction`:

void f()
  asm("movq %cs, 160(%rsp);");
  asm("movq %fs, 168(%rsp);");
  asm("movq %gs, 176(%rsp);");

(see Compiler Explorer)

Two questions: 1. Is this a bug or a feature? 2. Is this a clang bug/feature or an llvm one (a.k.a what is the right place to report this)?

(Background: I ran into this while trying to roll clang to a new version in a project containing PLCrashReporter, which uses these instructions while capturing a thread context, see [1]. I'm now trying to figure out if this is a compiler bug or if PLCrashReporter needs to be patched.)


[1] plcrashreporter/PLCrashAsyncThread_current.S at master · microsoft/plcrashreporter · GitHub

Ableton AG, Schoenhauser Allee 6-7, 10119 Berlin, Germany
Sitz (Registered Office) Berlin, Amtsgericht Berlin-Charlottenburg, HRB 72838
Vorstand (Management Board): Gerhard Behles, Jan Bohl
Vorsitzender des Aufsichtsrats (Chair of the Supervisory Board): Uwe Struck

It should be movw. The segment registers are only 16-bits wide. We used to accept it because the Intel documentation sort of makes it look valid because you can use a 64-bit GPR as the destination, but it doesn’t make any sense to use 64-bits when writing to memory. GNU assembler 2.30 feels the same way so it probably doesn’t work in gcc either.

Thanks, that fixes it. I'll file it against PLCrashReporter. FWIW, gcc trunk still seems to accept it: Compiler Explorer

Thanks again!

I think if you press the binary button on the godbolt output it will fail on gcc. I don’t think it feeds it to the assembler without that.

Oh indeed, it does `:)