aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/TargetInfo.h10
-rw-r--r--lib/AST/Stmt.cpp9
-rw-r--r--lib/Basic/TargetInfo.cpp1
-rw-r--r--lib/Basic/Targets.cpp4
-rw-r--r--test/CodeGen/arm_asm_clobber.c13
5 files changed, 33 insertions, 4 deletions
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index f89d5649e7..5bb0079dc1 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -45,6 +45,7 @@ protected:
// Target values set by the ctor of the actual target implementation. Default
// values are specified by the TargetInfo constructor.
bool TLSSupported;
+ bool NoAsmVariants; // True if {|} are normal characters.
unsigned char PointerWidth, PointerAlign;
unsigned char IntWidth, IntAlign;
unsigned char FloatWidth, FloatAlign;
@@ -414,6 +415,15 @@ public:
return TLSSupported;
}
+ /// hasNoAsmVariants - Return true if {|} are normal characters in the
+ /// asm string. If this returns false (the default), then {abc|xyz} is syntax
+ /// that says that when compmiling for asm variant #0, "abc" should be
+ /// generated, but when compiling for asm variant #1, "xyz" should be
+ /// generated.
+ bool hasNoAsmVariants() const {
+ return NoAsmVariants;
+ }
+
/// getEHDataRegisterNumber - Return the register number that
/// __builtin_eh_return_regno would return with the specified argument.
virtual int getEHDataRegisterNumber(unsigned RegNo) const {
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 97023820e2..ee4a74a612 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
#include <cstdio>
using namespace clang;
@@ -240,6 +241,8 @@ unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
// asm string.
std::string CurStringPiece;
+ bool HasVariants = !C.Target.hasNoAsmVariants();
+
while (1) {
// Done with the string?
if (CurPtr == StrEnd) {
@@ -251,9 +254,9 @@ unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
char CurChar = *CurPtr++;
switch (CurChar) {
case '$': CurStringPiece += "$$"; continue;
- case '{': CurStringPiece += "$("; continue;
- case '|': CurStringPiece += "$|"; continue;
- case '}': CurStringPiece += "$)"; continue;
+ case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue;
+ case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue;
+ case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue;
case '%':
break;
default:
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index b259facbb7..4c0c59a109 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -23,6 +23,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
// Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or
// SPARC. These should be overridden by concrete targets as needed.
TLSSupported = true;
+ NoAsmVariants = false;
PointerWidth = PointerAlign = 32;
IntWidth = IntAlign = 32;
LongWidth = LongAlign = 32;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 832c91cfb6..3d5048ccb9 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -1396,6 +1396,10 @@ public:
SizeType = UnsignedInt;
PtrDiffType = SignedInt;
+ // {} in inline assembly are neon specifiers, not assembly variant
+ // specifiers.
+ NoAsmVariants = true;
+
// FIXME: Should we just treat this as a feature?
IsThumb = getTriple().getArchName().startswith("thumb");
if (IsThumb) {
diff --git a/test/CodeGen/arm_asm_clobber.c b/test/CodeGen/arm_asm_clobber.c
index a7ca0b5332..aac47d57dc 100644
--- a/test/CodeGen/arm_asm_clobber.c
+++ b/test/CodeGen/arm_asm_clobber.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple armv6-unknown-unknown -emit-llvm -o %t %s
+// RUN: %clang_cc1 -triple armv6-unknown-unknown -emit-llvm -o - %s | FileCheck %s
void test0(void) {
asm volatile("mov r0, r0" :: );
@@ -19,3 +19,14 @@ void test3(void) {
asm volatile("mov r0, r0" :::
"v1", "v2", "v3", "v5");
}
+
+
+// {} should not be treated as asm variants.
+void test4(float *a, float *b) {
+ // CHECK: @test4
+ // CHECK: call void asm sideeffect "vld1.32 {d8[],d9[]},
+ __asm__ volatile (
+ "vld1.32 {d8[],d9[]}, [%1,:32] \n\t"
+ "vst1.32 {q4}, [%0,:128] \n\t"
+ :: "r"(a), "r"(b));
+}