This is an archive of the discontinued LLVM Phabricator instance.

[clang] Don't pass multiple backend options if mixing -mimplicit-it and -Wa,-mimplicit-it
ClosedPublic

Authored by mstorsjo on May 19 2021, 2:15 PM.

Details

Summary

If multiple instances of the -arm-implicit-it option is passed to
the backend, it errors out.

Also fix cases where there are multiple -Wa,-mimplicit-it; the existing
tests indicate that the last one specified takes effect, while in
practice it passed double options, which didn't work as intended.

This goes on top of a reverted 2919222d8017f2425a85765b95e4b7c6f8e70ca4.

Diff Detail

Event Timeline

mstorsjo created this revision.May 19 2021, 2:15 PM
mstorsjo requested review of this revision.May 19 2021, 2:15 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 19 2021, 2:15 PM
mstorsjo updated this revision to Diff 346568.May 19 2021, 2:19 PM

Rebased on top of the revert.

mstorsjo added inline comments.May 19 2021, 11:44 PM
clang/lib/Driver/ToolChains/Clang.cpp
2371

I guess this could be a StringSwitch<bool> too if you think that's nicer.

clang/test/Driver/arm-target-as-mimplicit-it.s
42

This pattern wouldn't detct if there's e.g. -arm-implicit-it=never -arm-implicit-it=always, but I added test cases that pass -Wa,-mimplicit-it=always twice, where this check should be able to verify that we only output it once.

mstorsjo added inline comments.May 19 2021, 11:52 PM
clang/lib/Driver/ToolChains/Clang.cpp
2411–2429

We could also just add options::OPT_mimplicit_it_EQ into this loop here, and we'd know for certain which value was set last on the command line, so there wouldn't be any ambiguity and we could remove the error case altogether. (The fact that you can have several differing options and the last one takes effect seems to be the intended behaviour from D96285.)

If multiple instances of the -arm-implicit-it option is passed to
the backend, it errors out.

Does it make sense to fix that side too?

Seems like we have a few options to handle this on clang's side:

  1. Last of -mimplicit-it and -Wa,-mimplicit-it wins
  2. If they're the same, accept it, if they mismatch, error
  3. Take the (last) one that matches the current input type

There is some precedent for number 3 in 1d51c699b9e2ebc5bcfdbe85c74cc871426333d4. Quoting from the commit msg:

Now the same rules will apply to -Wa,-march/-mcpu as would
if you just passed them to the compiler:
* -Wa/-Xassembler options only apply to assembly files.
* Architecture derived from mcpu beats any march options.
* When there are multiple mcpu or multiple march, the last
  one wins.
* If there is a compiler option and an assembler option of
  the same type, we prefer the one that fits the input type.
* If there is an applicable mcpu option but it is overruled
  by an march, the cpu value is still used for the "-target-cpu"
  cc1 option.

I'm not up on all the background to this change so perhaps doing number 3 is going to break existing use cases.

clang/lib/Driver/ToolChains/Clang.cpp
2585
if (ImplicitItCompiler.size() && ImplicitItAsm.size()) {
clang/test/Driver/arm-target-as-mimplicit-it.s
42

Could you do:

// ALWAYS-NOT: "-mllvm" "-arm-implicit-it=never"
// ALWAYS: "-mllvm" "-arm-implicit-it=always"

Not sure if doing the NOT moves the check forward to beyond where the always would be.

47–48

Can you do this check without the regex?

Reading it as is this doesn't look like a very helpful error. I'd expect something like:

error: mismatched values for implicit-it "thumb" and "arm"

If multiple instances of the -arm-implicit-it option is passed to
the backend, it errors out.

Does it make sense to fix that side too?

I guess it could, although I didn't look into whether it's trivial or tricky. This particular case was at least easy, as all options are handled at once place in one single function.

Seems like we have a few options to handle this on clang's side:

  1. Last of -mimplicit-it and -Wa,-mimplicit-it wins
  2. If they're the same, accept it, if they mismatch, error
  3. Take the (last) one that matches the current input type

There is some precedent for number 3 in 1d51c699b9e2ebc5bcfdbe85c74cc871426333d4. Quoting from the commit msg:

Now the same rules will apply to -Wa,-march/-mcpu as would
if you just passed them to the compiler:
* -Wa/-Xassembler options only apply to assembly files.
* Architecture derived from mcpu beats any march options.
* When there are multiple mcpu or multiple march, the last
  one wins.
* If there is a compiler option and an assembler option of
  the same type, we prefer the one that fits the input type.
* If there is an applicable mcpu option but it is overruled
  by an march, the cpu value is still used for the "-target-cpu"
  cc1 option.

I'm not up on all the background to this change so perhaps doing number 3 is going to break existing use cases.

If case 3 would mean that -mimplicit-it= is ignored when compiling assembly files, that would indeed break existing use cases. If using the input file type to disambiguate cases when there's conflicts, then that's fine, although I'm not sure if there's need for it really.

In this case, the compiler level option is around for historical reasons, and we're aiming to phase out its use within some time frame (although there's much less urgency with it now if we get this resolved more cleanly), so I'm not sure if it's worth to complicate things for it.

Also, if considering the predecent for how the option behaves from GCC/binutils; there, there's only the -Wa level option, and one could plausibly compile a C file with inline assembly that requires adding implicit IT instructions, so there, the -Wa option needs to be respected even when the original source is C.

clang/lib/Driver/ToolChains/Clang.cpp
2585

Thanks, that'd be even nicer.

clang/test/Driver/arm-target-as-mimplicit-it.s
42

Thanks, I think that could work to further guard against that case.

47–48

Yeah this is mostly me being lazy in the first iteration of the patch (I wrote it late last night and wanted to have something to show before finishing) and reusing existing diagnostic messages - it does print unsupported argument 'always and never' to option '-mimplicit-it' in the current form, which is a bit odd indeed.

But I guess if I'd handle both option variants in the same loop, so we can be certain about which one was set last, we could simply define it as last one set wins and we could get rid of the error case altogether.

DavidSpickett added a comment.EditedMay 20 2021, 4:18 AM

If case 3 would mean that -mimplicit-it= is ignored when compiling assembly files, that would indeed break existing use cases. If using the input file type to disambiguate cases when there's conflicts, then that's fine, although I'm not sure if there's need for it really.

Yes, I mis-stated that one. Let me try again.

You have both options: use the one that applies to the input type
You have 2 of one option: choose the last one
You have 2 of each option: choose the last one that applies to the input type

I think that would accommodate the C with inline asm case. I only suggest it because that's what I did in the past, I don't have specific use cases to support it.

That said we've had issues downstream with -mcpu and -march options that conflict, or should conflict, and they don't warn in any way. I would like to avoid another situation like that.

Given that using both options currently crashes clang (therefore no one is relying on this yet) and GCC doesn't have -mimplicit-it I think what you have is actually the best way to go. If the two options agree, fine, if they don't, error. Let's not make it more complicated than it has to be.

MaskRay added inline comments.May 20 2021, 10:40 AM
clang/lib/Driver/ToolChains/Clang.cpp
2369–2374

Use functionName for new functions.

clang/test/Driver/arm-target-as-mimplicit-it.s
42

The NOT pattern can omit the value to catch more cases.

Given that using both options currently crashes clang (therefore no one is relying on this yet) and GCC doesn't have -mimplicit-it I think what you have is actually the best way to go. If the two options agree, fine, if they don't, error. Let's not make it more complicated than it has to be.

Well it's complicated in the sense that there is an error diagnostic that we need to provide, and all that. Just picking the last set value should be fine too and simplifies the code in that sense.

I'll update the patch with the code in that form, and let you say what you think of that form. If you think we should keep the error though, I'll add it back (and see if I need to add a new diagnostic id for that case, to get a proper error mesasge). It's a bit inconsistent in the sense that one can pass multiple conflicting options via each of the options (where the last one of each wins); gas does handle it in that way too, but two different kinds of options error out instead.

clang/lib/Driver/ToolChains/Clang.cpp
2369–2374

Hmm, the whole rest of the file uses function names starting with a capital, so they do look a bit out of place if adding one new that differs...

mstorsjo updated this revision to Diff 346856.May 20 2021, 2:28 PM

Updated to allow mismatches and just picking the value that is set last on the command line - what do you think of this version?

MaskRay accepted this revision.May 20 2021, 2:46 PM

Thanks!

This revision is now accepted and ready to land.May 20 2021, 2:46 PM

Updated to allow mismatches and just picking the value that is set last on the command line - what do you think of this version?

My initial reaction was that I'd prefer to take the last one that matches the input type, to be consistent with -march and -mcpu. march and mcpu effect both so it makes sense to switch on the input type.
However this is an option that only effects asm/inline asm (even when passed as a compiler option) so you could think of -mimplicit-it as an alias to -Wa,-mimplicit-it. So taking the last value we find sounds good to me.

Ideally we would warn about conflicting values but that's an enhancement that can be done another time if we see situations where it could have been useful.

LGTM

Updated to allow mismatches and just picking the value that is set last on the command line - what do you think of this version?

My initial reaction was that I'd prefer to take the last one that matches the input type, to be consistent with -march and -mcpu. march and mcpu effect both so it makes sense to switch on the input type.
However this is an option that only effects asm/inline asm (even when passed as a compiler option) so you could think of -mimplicit-it as an alias to -Wa,-mimplicit-it. So taking the last value we find sounds good to me.

Ideally we would warn about conflicting values but that's an enhancement that can be done another time if we see situations where it could have been useful.

Thanks for your input!

This revision was landed with ongoing or failed builds.May 21 2021, 2:06 PM
This revision was automatically updated to reflect the committed changes.