diff options
author | David Majnemer <david.majnemer@gmail.com> | 2015-01-10 10:43:19 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2015-01-10 10:43:19 +0000 |
commit | a0040df38c96866f6f970ad0ab45e3185faceb02 (patch) | |
tree | cdafccdf358585b2c5b6c5836268ec7e8fc9b66f /clang | |
parent | 9e6d12b98c2663046a257b0c3a84a6c74ccafbdc (diff) | |
download | bcm5719-llvm-a0040df38c96866f6f970ad0ab45e3185faceb02.tar.gz bcm5719-llvm-a0040df38c96866f6f970ad0ab45e3185faceb02.zip |
Sema: The asm constraint '+&m' isn't valid, reject it
Don't permit '+&m' to make it to CodeGen, it's invalid.
llvm-svn: 225586
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/TargetInfo.h | 3 | ||||
-rw-r--r-- | clang/lib/Basic/TargetInfo.cpp | 7 | ||||
-rw-r--r-- | clang/test/Sema/asm.c | 6 |
3 files changed, 16 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index a2ff7e2541f..69a54044680 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -531,6 +531,7 @@ public: CI_ReadWrite = 0x04, // "+r" output constraint (read and write). CI_HasMatchingInput = 0x08, // This output operand has a matching input. CI_ImmediateConstant = 0x10, // This operand must be an immediate constant + CI_EarlyClobber = 0x20, // "&" output constraint (early clobber). }; unsigned Flags; int TiedOperand; @@ -551,6 +552,7 @@ public: const std::string &getConstraintStr() const { return ConstraintStr; } const std::string &getName() const { return Name; } bool isReadWrite() const { return (Flags & CI_ReadWrite) != 0; } + bool earlyClobber() { return (Flags & CI_EarlyClobber) != 0; } bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; } bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; } @@ -576,6 +578,7 @@ public: int getImmConstantMax() const { return ImmRange.Max; } void setIsReadWrite() { Flags |= CI_ReadWrite; } + void setEarlyClobber() { Flags |= CI_EarlyClobber; } void setAllowsMemory() { Flags |= CI_AllowsMemory; } void setAllowsRegister() { Flags |= CI_AllowsRegister; } void setHasMatchingInput() { Flags |= CI_HasMatchingInput; } diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index f2dc84fa034..aabb70dd6b1 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -459,7 +459,9 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { // Eventually, an unknown constraint should just be treated as 'g'. return false; } + break; case '&': // early clobber. + Info.setEarlyClobber(); break; case '%': // commutative. // FIXME: Check that there is a another register after this one. @@ -494,6 +496,11 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { Name++; } + // Early clobber with a read-write constraint which doesn't permit registers + // is invalid. + if (Info.earlyClobber() && Info.isReadWrite() && !Info.allowsRegister()) + return false; + // If a constraint allows neither memory nor register operands it contains // only modifiers. Reject it. return Info.allowsMemory() || Info.allowsRegister(); diff --git a/clang/test/Sema/asm.c b/clang/test/Sema/asm.c index e49888ff3eb..2867acb1d36 100644 --- a/clang/test/Sema/asm.c +++ b/clang/test/Sema/asm.c @@ -171,3 +171,9 @@ void fn1() { : [l] "=r"(l) : "[l],m"(l)); // expected-error {{asm constraint has an unexpected number of alternatives: 1 vs 2}} } + +void fn2() { + int l; + __asm__("" + : "+&m"(l)); // expected-error {{invalid output constraint '+&m' in asm}} +} |