]> granicus.if.org Git - clang/commitdiff
[Targets] Implement getConstraintRegister for ARM and AArch64
authorMikhail Maltsev <mikhail.maltsev@arm.com>
Mon, 30 Apr 2018 09:11:08 +0000 (09:11 +0000)
committerMikhail Maltsev <mikhail.maltsev@arm.com>
Mon, 30 Apr 2018 09:11:08 +0000 (09:11 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331164 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/TargetInfo.h
lib/Basic/Targets/AArch64.h
lib/Basic/Targets/ARM.h
test/Sema/arm-asm.c
test/Sema/arm64-inline-asm.c

index 8fbda351ff39bc71c41f56e1813d6a6540548bf2..ddf737c7449aa01abc1e704fbde17fe54b1cc1e5 100644 (file)
@@ -629,6 +629,12 @@ public:
   StringRef getNormalizedGCCRegisterName(StringRef Name,
                                          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,
                                           StringRef Expression) const {
     return "";
index 0634565bc78fd6246a8285820cf80f8c6150b80b..f493ff28d31d5635c5ce1f91770f175d55353bb5 100644 (file)
@@ -82,6 +82,11 @@ public:
                              std::string &SuggestedModifier) const override;
   const char *getClobbers() const override;
 
+  StringRef getConstraintRegister(StringRef Constraint,
+                                  StringRef Expression) const override {
+    return Expression;
+  }
+
   int getEHDataRegisterNumber(unsigned RegNo) const override;
 };
 
index 4e8e514d4188356921e4b5d981600e0a802ea1f0..9c72c3387f7a93a2694f0c51d7ebe0b64d7fae81 100644 (file)
@@ -156,6 +156,11 @@ public:
                              std::string &SuggestedModifier) const override;
   const char *getClobbers() const override;
 
+  StringRef getConstraintRegister(StringRef Constraint,
+                                  StringRef Expression) const override {
+    return Expression;
+  }
+
   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
 
   int getEHDataRegisterNumber(unsigned RegNo) const override;
index e48718b0a2acaf02fb60d320f66a0bfee1654eb7..24fb5a7ecd82a2c393e33b26ff48736e8f4c351f 100644 (file)
@@ -10,3 +10,10 @@ void test_64bit_r(void) {
   long long foo = 0, bar = 0;
   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}}
+}
index d8e16a6872cc23fe000e76089d7e82ad08e138a7..541c190e6116d797653e836f7e31bcc79feba022 100644 (file)
@@ -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"}}
 }
+
+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}}
+}