Building latest llvm/clang targeting mingw-64/gcc-6.2 on Windows

I am building clang from source on Windows using CMake, Ninja, and mingw-64/gcc-6.2. I am building in Release mode ( CMAKE_BUILD_TYPE = Release ).

When I build with the x64 version of mingw-64/gcc-6.2 with a triple of x86_64-w64-mingw32 ( LLVM_DEFAULT_TARGET_TRIPLE = x86_64-w64-mingw32 ),
everything builds fine and I can produce clang that works properly with a 64-bit compilation using the 64-bit version of mingw-64/gcc-6.2.

When I build with the x32 version of mingw-64/gcc-6.2 with a triple of i686-pc-mingw32 ( LLVM_DEFAULT_TARGET_TRIPLE = i686-pc-mingw32 ),
the build fails with:

[8/1856] Building AArch64GenSubtargetInfo.inc...
FAILED: lib/Target/AArch64/AArch64GenSubtargetInfo.inc.tmp
cmd.exe /C "cd /D C:\Programming\VersionControl\bninja_clang\lib\Target\AArch64
&& C:\Programming\VersionControl\bninja_clang\bin\llvm-tblgen.exe -gen-subtarget
-I E:/Programming/VersionControl/llvm/lib/Target/AArch64 -I E:/Programming/VersionControl/llvm/include
-I E:/Programming/VersionControl/llvm/lib/Target E:/Programming/VersionControl/llvm/lib/Target/AArch64/AArch64.td
-o C:/Programming/VersionControl/bninja_clang/lib/Target/AArch64/AArch64GenSubtargetInfo.inc.tmp"
Wrote crash dump file "C:\Users\eldiener\AppData\Local\Temp\llvm-tblgen.exe-0c060b.dmp"
0x004EFB0A (0x0166FA48 0x00000007 0x63724141 0x00343668)
0x03172858 (0x77CEE172 0x769B0100 0x00000000 0x00000008) <unknown module>
0x77CEE40C (0x001F9A18 0x004F51D0 0x005F40CC 0x00000000), RtlInitUnicodeString() + 0x164 bytes(s)
0x005CD6B1 (0x0000000B 0x001F99E0 0x001F2B50 0x00000000)
0x004013E2 (0x7EFDE000 0x0166FFD4 0x77CF9902 0x7EFDE000)
0x768E336A (0x7EFDE000 0x73B4F3DA 0x00000000 0x00000000), BaseThreadInitThunk()+ 0x12 bytes(s)
0x77CF9902 (0x004014E0 0x7EFDE000 0x00000000 0x00000000), RtlInitializeExceptionChain() + 0x63 bytes(s)
0x77CF98D5 (0x004014E0 0x7EFDE000 0x00000000 0x00000000), RtlInitializeExceptionChain() + 0x36 bytes(s)
[9/1856] Building AMDGPUGenMCPseudoLowering.inc...
ninja: build stopped: subcommand failed.

I notice that AArch64 is listed as a target type even when building with a 32-bit compiler and am guessing that this is what is causing the build to fail.

Is this an LLVM problem or a clang problem ?

How can I get someone to correct this in the CMake files in the LLVM/clang project ?

Is there some way I myself can tell CMake to not build for the AArch64 target ?

You can buld X86 target only using -DLLVM_TARGETS_TO_BUILD=X86

You can buld X86 target only using -DLLVM_TARGETS_TO_BUILD=X86

I did this but I am still seeing the same general problem with the build of clang with the 32 bit version of mingw-64/gcc-6.2:

[10/1057] Building X86GenSubtargetInfo.inc...
FAILED: lib/Target/X86/X86GenSubtargetInfo.inc.tmp
cmd.exe /C "cd /D C:\Programming\VersionControl\bninja_clang\lib\Target\X86 &&
C:\Programming\VersionControl\bninja_clang\bin\llvm-tblgen.exe -gen-subtarget
-I E:/Programming/VersionControl/llvm/lib/Target/X86
-I E:/Programming/VersionControl/llvm/include
-I E:/Programming/VersionControl/llvm/lib/Target
E:/Programming/VersionControl/llvm/lib/Target/X86/X86.td
-o C:/Programming/VersionControl/bninja_clang/lib/Target/X86/X86GenSubtargetInfo.inc.tmp"
Wrote crash dump file "C:\Users\eldiener\AppData\Local\Temp\llvm-tblgen.exe-c8ae4d.dmp"
0x004EFB0A (0x0166FA48 0x00000003 0x00363858 0x00000020)
0x03E7FED0 (0x77CEE172 0x769B0100 0x00000000 0x00000008) <unknown module>
0x77CEE40C (0x01A69A10 0x004F51D0 0x005F40CC 0x00000000), RtlInitUnicodeString() + 0x164 bytes(s)
0x005CD6B1 (0x0000000B 0x01A699D8 0x01A62B48 0x00000000)
0x004013E2 (0x7EFDE000 0x0166FFD4 0x77CF9902 0x7EFDE000)
0x768E336A (0x7EFDE000 0x73310E5D 0x00000000 0x00000000), BaseThreadInitThunk()> + 0x12 bytes(s)
0x77CF9902 (0x004014E0 0x7EFDE000 0x00000000 0x00000000), RtlInitializeExceptionChain() + 0x63 bytes(s)
0x77CF98D5 (0x004014E0 0x7EFDE000 0x00000000 0x3ED2DFE2), RtlInitializeExceptionChain() + 0x36 bytes(s)
[15/1057] Building CXX object lib/AsmP...les/LLVMAsmParser.dir/LLParser.cpp.obj
ninja: build stopped: subcommand failed.

Evidently this problem has nothing to do with 64 bit targets. But what it actually means I do not know other than that llvm-tblgen.exe is crashing.

I spent some time debugging this, and it’s either a GCC miscompile or instance of UB in tablegen that I can’t identify. The ‘this’ pointer is corrupted in this call sequence:

llvm::errs() << "this before EmitProcessorProp: " << (void *)this << ‘\n’;
EmitProcessorProp(OS, PM.ModelDef, “IssueWidth”, ‘,’);
EmitProcessorProp(OS, PM.ModelDef, “MicroOpBufferSize”, ‘,’);
EmitProcessorProp(OS, PM.ModelDef, “LoopMicroOpBufferSize”, ‘,’);
EmitProcessorProp(OS, PM.ModelDef, “LoadLatency”, ‘,’);
EmitProcessorProp(OS, PM.ModelDef, “HighLatency”, ‘,’);
EmitProcessorProp(OS, PM.ModelDef, “MispredictPenalty”, ‘,’);
llvm::errs() << "this after EmitProcessorProp: " << (void *)this << ‘\n’;

I suspect a GCC miscompile. The problem goes away when I disable frame pointer omission, and GCC is doing some interesting IPO transformation, based on the mangled name of this function: __ZN12_GLOBAL__N_116SubtargetEmitter17EmitProcessorPropERN4llvm11raw_ostreamEPKNS1_6RecordENS1_9StringRefEc.constprop.549 (note the .constprop)

I think this GCC getting the thiscall calling convention confused. Here’s here it calls EmitProcessorProp:

7c06: e8 15 97 ff ff call 1320 <_ZN12…constprop.549>
7c0b: 8b 53 1c mov 0x1c(%ebx),%edx
7c0e: 83 ec 08 sub $0x8,%esp

Note the subtraction from ESP. This usually indicates that the callee is expected to pop 8 bytes off the stack. However, the epilogue of EmitProcessorProp doesn’t do that:

13c3: 8d 65 f4 lea -0xc(%ebp),%esp
13c6: 5b pop %ebx
13c7: 5e pop %esi
13c8: 5f pop %edi
13c9: 5d pop %ebp
13ca: c3 ret

Note that it doesn’t say “ret $0x8”.

Do you want to follow up filing this issue with upstream GCC?

I spent some time debugging this, and it's either a GCC miscompile or
instance of UB in tablegen that I can't identify. The 'this' pointer is
corrupted in this call sequence:
    llvm::errs() << "this before EmitProcessorProp: " << (void *)this <<
'\n';
    EmitProcessorProp(OS, PM.ModelDef, "IssueWidth", ',');
    EmitProcessorProp(OS, PM.ModelDef, "MicroOpBufferSize", ',');
    EmitProcessorProp(OS, PM.ModelDef, "LoopMicroOpBufferSize", ',');
    EmitProcessorProp(OS, PM.ModelDef, "LoadLatency", ',');
    EmitProcessorProp(OS, PM.ModelDef, "HighLatency", ',');
    EmitProcessorProp(OS, PM.ModelDef, "MispredictPenalty", ',');
    llvm::errs() << "this after EmitProcessorProp: " << (void *)this <<
'\n';

I suspect a GCC miscompile. The problem goes away when I disable frame
pointer omission, and GCC is doing some interesting IPO transformation,
based on the mangled name of this
function: __ZN12_GLOBAL__N_116SubtargetEmitter17EmitProcessorPropERN4llvm11raw_ostreamEPKNS1_6RecordENS1_9StringRefEc.constprop.549
(note the .constprop)

I think this GCC getting the thiscall calling convention confused.
Here's here it calls EmitProcessorProp:
    7c06:e8 15 97 ff ff call 1320 <__ZN12_....constprop.549>
    7c0b:8b 53 1c mov 0x1c(%ebx),%edx
    7c0e:83 ec 08 sub $0x8,%esp

Note the subtraction from ESP. This usually indicates that the callee is
expected to pop 8 bytes off the stack. However, the epilogue of
EmitProcessorProp doesn't do that:
    13c3:8d 65 f4 lea -0xc(%ebp),%esp
    13c6:5b pop %ebx
    13c7:5e pop %esi
    13c8:5f pop %edi
    13c9:5d pop %ebp
    13ca:c3 ret

Note that it doesn't say "ret $0x8".

Do you want to follow up filing this issue with upstream GCC?

I really appreciate your taking a look at this. If I report this issue to GCC I will need to reduce it to code which shows the bug. Since I am not a clang developer it is difficult for me to know which llvm/clang source illustrates this problem, so I can reduce it to a bug report.

You said that the problem goes away when you "disable frame pointer omission". Does this mean that compiling with "-fomit-frame-pointer" temporarily solves the problem ? Also do you have any idea why the bug occurs for 32-bit generation and not 64-bit code generation ?

I really appreciate your taking a look at this. If I report this issue to
GCC I will need to reduce it to code which shows the bug. Since I am not a
clang developer it is difficult for me to know which llvm/clang source
illustrates this problem, so I can reduce it to a bug report.

I went ahead and filed https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78936

Thanks for the offer, though. I linked the pre-processed source off of
there, which could be further reduced.

You said that the problem goes away when you "disable frame pointer
omission". Does this mean that compiling with "-fomit-frame-pointer"
temporarily solves the problem ?

Compiling with -fno-omit-frame-pointer hides the problem. Compiling with
-O0 also hides the problem.

Also do you have any idea why the bug occurs for 32-bit generation and not
64-bit code generation ?

It has to do with thiscall being the default C++ member function calling
convention, which is 32-bit only.

    I really appreciate your taking a look at this. If I report this
    issue to GCC I will need to reduce it to code which shows the bug.
    Since I am not a clang developer it is difficult for me to know
    which llvm/clang source illustrates this problem, so I can reduce it
    to a bug report.

I went ahead and filed https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78936

Thanks !

Thanks for the offer, though. I linked the pre-processed source off of
there, which could be further reduced.

    You said that the problem goes away when you "disable frame pointer
    omission". Does this mean that compiling with "-fomit-frame-pointer"
    temporarily solves the problem ?

Compiling with -fno-omit-frame-pointer hides the problem. Compiling with
-O0 also hides the problem.

When I compiled with -O0 the problem still occurred. When instead I compiled with -fno-omit-frame-pointer the problem disappeared.

    Also do you have any idea why the bug occurs for 32-bit generation
    and not 64-bit code generation ?

It has to do with thiscall being the default C++ member function calling
convention, which is 32-bit only.

Ah !!! Makes sense.