Odd behaviour with '-save-temps' and OpenCL files

I’m not sure whether to direct this message to LLVM-Dev or CFE-Dev, but I think CFE is more appropriate.

This is in respect to our out-of-tree implementation, derived from the v3.9.0 sources.

If I am compiling a source file, and I use ‘-c -save-temps’ (or ‘-c -save-temps=obj’), the intermediate files ‘.i’ or ‘.ii’, ‘.bc’ and ‘.s’ are retained as expected; but in an odd twist, I get errors when I compile OpenCL files with the ‘.cl’ extension.

This only happens if the OpenCL source uses the keyword ‘half’. If I do not use ‘-save-temps’ then everything works correctly, but when I do use ‘-save-temps’ it fails to parse ‘half’ as being valid. The errors I get when I use ‘-save-temps’ are:

warning: unknown pragma ignored

for:

#pragma OPENCL EXTENSION cl_khr_fp16 : enable

and then subsequent uses of ‘half’ such as:

typedef attribute((ext_vector_type(2))) half half2;

result in:

error: unknown type name ‘half’

When I omit ‘-save-temps’ the source compiles correctly with no warnings or errors.

Any idea what might be happening here? Are there changes in OpenCL support that I need to update my library sources for? Most of these are from the ‘libclc’ sources, though I do have local edits that might be stale with respect to recent changes for OpenCL support.

Thanks,

MartinO

My guess, and it’s only a guess, is that -save-temps causes the compiler to run each step on those files, by executing independent processes, rather than the usual “run all steps in parallel” - in my understanding, Clang doesn’t actually work in the “old style cc way” and running several processes with files produced between each step. And as a result, with -save-temps, when the compiler comes to process the second step (processing the .i file), it has “lost” the fact that you are compiling CL code (and I suspect this would happen to other types than half, just not types that are “same as C”)

Yes and no. -svae-temps will run the parser on the preprocessed output,
so all macro-expansion knowledge is missing. That changes the impact of
a number of warnings like redundant braces. Pragmas are still preserved
in the code though. It would be a bug in the OpenCL integration if the
pragmas are no longer processed OR if pragmas are silently attached to
macros by position.

Joerg

And how does the parser know from the preprocessed output that it is CL rather than C that it’s parsing? I suspect it’s the “.cl” part of the name of “filename.cl” that determines that it’s CL code in the first place, if that gets replaced with “filename.i”, the parser will just say “Ah, it’s C-code and has already been preprocessed”.

Maybe the parser needs a -x cl or similar to ensure that the parser knows it’s CL-code?

I know that many of the CL parsing things have if (langOpts.OpenCL) ... in the parser and various other places. If we have a multi-pass way of running the compiler, it will potentially lose that information when it gets to the next step, is my thinking. I may of course be wrong, and the problem is with something else.

And how does the parser know from the preprocessed output that it is CL
rather than C that it's parsing? I suspect it's the ".cl" part of the name
of "filename.cl" that determines that it's CL code in the first place, if
that gets replaced with "filename.i", the parser will just say "Ah, it's
C-code and has already been preprocessed".

Likely.

Maybe the parser needs a `-x cl` or similar to ensure that the parser knows
it's CL-code?

A better idea might be to emit an appropiate "#pragma clang language
OpenCL" or so at the top of the file.

Joerg

When the source is a C file, the pre-processed file has the extension ‘.i’, and when it is a C++ file the pre-processed file has the extension ‘.ii’. Perhaps CL files need a 3rd convention for naming the pre-processed file, and eventually something similar if the FORTRAN front-end is available? I don’t compile CUDA files, and they may have a similar problem.

Even passing ‘-x cl -c -save-temps’ does not solve it, so the knowledge that it is an OpenCL source appears to be lost.

MartinO

Assuming #pragma clang language OpenCL works, that seems like a neat thing that can be inserted as a “pre-include header” (as a constant string in the compiler). However, I’m not sure that clang does this in conjunction with the preprocessor as it is now - or that there is a simple way to achieve it - in which case, the other solution is to add some code to “remember” the language picked from the extension, and passing that to the parser step (cc1?) after preprocessing.

@Martin: Have you tried to run clang -v ... to show the actual processing, and assuming it gives a sensible output, try to re-run the failing step (which I think is cc1 ... filename.i) with -x cl, and see if that resolves it?

@Martin: Have you tried to run clang -v ... to show the actual processing, and assuming it gives a sensible output, try to re-run the failing step (which I think is cc1 ... filename.i) with -x cl, and see if that resolves it?

This is interesting. So I used ‘-v’ and I see ‘-x cpp-output’ in the command-line - didn’t even know that value existed! - and if I replace it with ‘-x cl’ is works perfectly, so your hunch is spot-on. But is also means that the ‘-x cpp-output’ option is determining source language based on the extension (‘.i’ or ‘.ii’).

MartinO

Good to know that at least SOMETIMES my "gut feel" points in the right
general direction.

I'm not sure what the best solution for actually solving the next step -
communicating the actual language. Using `.icl` or some such would work,
but my personal feeling is that this is a slipperly slope that just gets
worse and worse the more languages and flavours of languages that you want
to support... the #pragma solution may work, but it kind of requires the
preprocessor to add stuff to the output - I'm sure it does already, but I'm
not sure it's the right place either.

In short, I'm sure it can be resolved, I'm not sure what is the RIGHT WAY,
and I also don't know where in the code this should be done (for any of the
suggested solutions), or who would be the right person to discuss this.
Maybe Joerg has some ideas?