An inline asm call may result in an immediate input value after inlining.
Therefore, don't emit a diagnostic here if the input isn't an immediate.
Details
- Reviewers
joerg eli.friedman rsmith - Commits
- rG87e914c5113d: Merging r368104 and r368202:
rL368422: Merging r368104 and r368202:
rGce29291fc3be: Delay diagnosing asm constraints that require immediates until after inlining
rL368104: Delay diagnosing asm constraints that require immediates until after inlining
rC368104: Delay diagnosing asm constraints that require immediates until after inlining
Diff Detail
- Repository
- rL LLVM
Event Timeline
I'm in the process of testing this, but feedback will take a bit.
On the more meaty parts of this change, I think further iterations will be necessary in-tree to extend this to the other constraints.
Thanks, Joerg. I was wondering about other constraints. This can be easily extended to encompass them. I just didn't want to jump the gun and come up with a "fix" that wasn't necessary.
I don't like making the validity of an input depend on optimizations, but I presume this is necessary to build Linux or similar? I'd be more comfortable with this if we still did the eager check if the enclosing function doesn't have the always_inline attribute. Is that sufficient to satisfy the use cases?
Here's the motivating bug report: https://bugs.llvm.org/show_bug.cgi?id=41027
In general, I agree with you that diagnostics shouldn't depend on optimization levels, but inline assembly subverts this paradigm because it was originally a gcc extension. :-( That said, I don't know if looking at the always_inline attribute would work. I'll let @joerg and others comment on that.
Thanks, that's illuminating. OK, if we want to support that code, then there's really not much validation we can do in the frontend for constraints that require immediate constants. Is "n" really special in this regard, or is it just the first one that we've encountered?
In general, I agree with you that diagnostics shouldn't depend on optimization levels, but inline assembly subverts this paradigm because it was originally a gcc extension. :-(
There is a question of how much weird stuff we should accept in the name of GCC compatibility. In this case, the fact that the frontend rejects seems like the tip of an iceberg: the code in the PR is also relying on the control flow of the && inside the if to be emitted in a very particular way (or to be optimized to that form), and for dead-code elimination to be considered and to actually fire, and probably more things besides. Do we at least still produce a nice diagnostic if the value ends up not being a constant?
I think it's just the first one we've encountered. There could be other constraints which require immediates, but they're probably target-specific. E.g. e and K for x86.
In general, I agree with you that diagnostics shouldn't depend on optimization levels, but inline assembly subverts this paradigm because it was originally a gcc extension. :-(
There is a question of how much weird stuff we should accept in the name of GCC compatibility. In this case, the fact that the frontend rejects seems like the tip of an iceberg: the code in the PR is also relying on the control flow of the && inside the if to be emitted in a very particular way (or to be optimized to that form), and for dead-code elimination to be considered and to actually fire, and probably more things besides. Do we at least still produce a nice diagnostic if the value ends up not being a constant?
It does, but for the wrong line:
[morbo@fawn:llvm] cat bad.c static __attribute__((always_inline)) void outl(unsigned port, unsigned data) { asm volatile("outl %0,%w1" : : "a"(data), "n"(port)); } void f(unsigned port) { outl(port, 1); } [morbo@fawn:llvm] ./llvm.opt.install/bin/clang -c bad.c bad.c:2:16: error: constraint 'n' expects an integer constant expression asm volatile("outl %0,%w1" : : "a"(data), "n"(port)); ^ 1 error generated.
I'll need to modify the LLVM patch to output the correct location.
OK, then I think we should apply whatever we do here to all constraints for which Info.requiresImmediateConstant() is true.
Modify so that no diagnistics are emitted until we can determine if it's an
immediate or not.
You lost the changes to lib/Sema/SemaStmtAsm.cpp to actually do the delaying for immediate operands?
In case you haven't seen, this commit breaks non-x86 build bots due to the combination of '-triple x86_64*' and '-S'. Some tests that use this target are only looking for AST dumps, and do not actually require such a target. This is not one of those tests, as it's inspecting assembly.
See clang/test/CodeGen/addrsig.c to see how that is handled (via REQUIRES: x86-registered-target).
Oddly enough, other tests that use -triple x86_64* and only inspect the AST don't require the registered target.