From: Anders Carlsson Date: Sun, 18 Jan 2009 01:56:57 +0000 (+0000) Subject: Add sema support for symbolic names in inline asm statements. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=42e1ee0702d8267d632df0fdb5c479a582877c6f;p=clang Add sema support for symbolic names in inline asm statements. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62441 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index ca755b907f..da14365e4d 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -202,7 +202,11 @@ public: const std::string *OutputNamesBegin, const std::string *OutputNamesEnd, ConstraintInfo &info) const; - + bool resolveSymbolicName(const char *&Name, + const std::string *OutputNamesBegin, + const std::string *OutputNamesEnd, + unsigned &Index) const; + virtual std::string convertConstraint(const char Constraint) const { return std::string(1, Constraint); } diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index 2ea1f232bf..eb912d578e 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -188,6 +188,36 @@ bool TargetInfo::validateOutputConstraint(const char *Name, return true; } +bool TargetInfo::resolveSymbolicName(const char *&Name, + const std::string *OutputNamesBegin, + const std::string *OutputNamesEnd, + unsigned &Index) const +{ + assert(*Name == '[' && "Symbolic name did not start with '['"); + + Name++; + const char *Start = Name; + while (*Name && *Name != ']') + Name++; + + if (!*Name) { + // Missing ']' + return false; + } + + std::string SymbolicName(Start, Name - Start); + + Index = 0; + for (const std::string *it = OutputNamesBegin; + it != OutputNamesEnd; + ++it, Index++) { + if (SymbolicName == *it) + return true; + } + + return false; +} + bool TargetInfo::validateInputConstraint(const char *Name, const std::string *OutputNamesBegin, const std::string *OutputNamesEnd, @@ -210,7 +240,15 @@ bool TargetInfo::validateInputConstraint(const char *Name, // add more constraints as we hit it. Eventually, an unknown // constraint should just be treated as 'g'. return false; - } + } + break; + case '[': { + unsigned Index = 0; + if (!resolveSymbolicName(Name, OutputNamesBegin, OutputNamesEnd, Index)) + return false; + + break; + } case '%': // commutative // FIXME: Fail if % is used with the last operand. break; diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index d86c3f4389..04fc26dd89 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -980,7 +980,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { S.begin_output_names(), S.end_output_names(), Info); - assert(result && "Failed to parse input constraint"); result=result; + assert(result && "Failed to parse input constraint"); if (i != 0 || S.getNumOutputs() > 0) Constraints += ','; diff --git a/test/Sema/asm.c b/test/Sema/asm.c index d29335a924..3bb7d78f5b 100644 --- a/test/Sema/asm.c +++ b/test/Sema/asm.c @@ -10,7 +10,11 @@ f() asm ("foo\n" : "=a" (f())); // expected-error {{invalid lvalue in asm output}} asm ("foo\n" : "=a" (i + 2)); // expected-error {{invalid lvalue in asm output}} - + + asm ("foo\n" : [symbolic_name] "=a" (i) : "[symbolic_name]" (i)); + asm ("foo\n" : "=a" (i) : "[" (i)); // expected-error {{invalid input constraint '[' in asm}} + asm ("foo\n" : "=a" (i) : "[foo" (i)); // expected-error {{invalid input constraint '[foo' in asm}} + asm ("foo\n" : "=a" (i) : "[symbolic_name]" (i)); // expected-error {{invalid input constraint '[symbolic_name]' in asm}} } void