forked from OSchip/llvm-project
[Targets] Implement getConstraintRegister for ARM and AArch64
Summary: The getConstraintRegister method is used by semantic checking of inline assembly statements in order to diagnose conflicts between clobber list and input/output lists. Currently ARM and AArch64 don't override getConstraintRegister, so conflicts between registers assigned to variables in asm labels and clobber lists are not diagnosed. Such conflicts can cause assertion failures in the back end and even miscompilations. This patch implements getConstraintRegister for ARM and AArch64 targets. Since these targets don't have single-register constraints, the implementation is trivial and just returns the register specified in an asm label (if any). Reviewers: eli.friedman, javed.absar, thopre Reviewed By: thopre Subscribers: rengolin, eraman, rogfer01, myatsina, kristof.beyls, cfe-commits, chrib Differential Revision: https://reviews.llvm.org/D45965 llvm-svn: 331164
This commit is contained in:
parent
6c33998ce1
commit
89f7b46b7a
|
@ -629,6 +629,12 @@ public:
|
||||||
StringRef getNormalizedGCCRegisterName(StringRef Name,
|
StringRef getNormalizedGCCRegisterName(StringRef Name,
|
||||||
bool ReturnCanonical = false) const;
|
bool ReturnCanonical = false) const;
|
||||||
|
|
||||||
|
/// \brief Extracts a register from the passed constraint (if it is a
|
||||||
|
/// single-register constraint) and the asm label expression related to a
|
||||||
|
/// variable in the input or output list of an inline asm statement.
|
||||||
|
///
|
||||||
|
/// This function is used by Sema in order to diagnose conflicts between
|
||||||
|
/// the clobber list and the input/output lists.
|
||||||
virtual StringRef getConstraintRegister(StringRef Constraint,
|
virtual StringRef getConstraintRegister(StringRef Constraint,
|
||||||
StringRef Expression) const {
|
StringRef Expression) const {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -82,6 +82,11 @@ public:
|
||||||
std::string &SuggestedModifier) const override;
|
std::string &SuggestedModifier) const override;
|
||||||
const char *getClobbers() const override;
|
const char *getClobbers() const override;
|
||||||
|
|
||||||
|
StringRef getConstraintRegister(StringRef Constraint,
|
||||||
|
StringRef Expression) const override {
|
||||||
|
return Expression;
|
||||||
|
}
|
||||||
|
|
||||||
int getEHDataRegisterNumber(unsigned RegNo) const override;
|
int getEHDataRegisterNumber(unsigned RegNo) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,11 @@ public:
|
||||||
std::string &SuggestedModifier) const override;
|
std::string &SuggestedModifier) const override;
|
||||||
const char *getClobbers() const override;
|
const char *getClobbers() const override;
|
||||||
|
|
||||||
|
StringRef getConstraintRegister(StringRef Constraint,
|
||||||
|
StringRef Expression) const override {
|
||||||
|
return Expression;
|
||||||
|
}
|
||||||
|
|
||||||
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
|
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
|
||||||
|
|
||||||
int getEHDataRegisterNumber(unsigned RegNo) const override;
|
int getEHDataRegisterNumber(unsigned RegNo) const override;
|
||||||
|
|
|
@ -10,3 +10,10 @@ void test_64bit_r(void) {
|
||||||
long long foo = 0, bar = 0;
|
long long foo = 0, bar = 0;
|
||||||
asm volatile("INST %0, %1" : "=r"(foo) : "r"(bar));
|
asm volatile("INST %0, %1" : "=r"(foo) : "r"(bar));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_clobber_conflict(void) {
|
||||||
|
register int x asm("r1");
|
||||||
|
asm volatile("nop" :: "r"(x) : "%r1"); // expected-error {{conflicts with asm clobber list}}
|
||||||
|
asm volatile("nop" :: "l"(x) : "%r1"); // expected-error {{conflicts with asm clobber list}}
|
||||||
|
asm volatile("nop" : "=r"(x) :: "%r1"); // expected-error {{conflicts with asm clobber list}}
|
||||||
|
}
|
||||||
|
|
|
@ -7,3 +7,9 @@ void foo() {
|
||||||
|
|
||||||
asm volatile("USE(%0)" :: "z"(0)); // expected-warning {{value size does not match register size specified by the constraint and modifier}} expected-note {{use constraint modifier "w"}}
|
asm volatile("USE(%0)" :: "z"(0)); // expected-warning {{value size does not match register size specified by the constraint and modifier}} expected-note {{use constraint modifier "w"}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_clobber_conflict(void) {
|
||||||
|
register long x asm("x1");
|
||||||
|
asm volatile("nop" :: "r"(x) : "%x1"); // expected-error {{conflicts with asm clobber list}}
|
||||||
|
asm volatile("nop" : "=r"(x) :: "%x1"); // expected-error {{conflicts with asm clobber list}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue