summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2015-01-10 10:43:19 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2015-01-10 10:43:19 +0000
commita0040df38c96866f6f970ad0ab45e3185faceb02 (patch)
treecdafccdf358585b2c5b6c5836268ec7e8fc9b66f /clang
parent9e6d12b98c2663046a257b0c3a84a6c74ccafbdc (diff)
downloadbcm5719-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.h3
-rw-r--r--clang/lib/Basic/TargetInfo.cpp7
-rw-r--r--clang/test/Sema/asm.c6
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}}
+}
OpenPOWER on IntegriCloud