[cfe-commits] r66596 - in /cfe/trunk: include/clang/AST/Stmt.h lib/AST/Stmt.cpp lib/CodeGen/CGStmt.cpp

Chris Lattner sabre at nondot.org
Tue Mar 10 16:21:47 PDT 2009


Author: lattner
Date: Tue Mar 10 18:21:44 2009
New Revision: 66596

URL: http://llvm.org/viewvc/llvm-project?rev=66596&view=rev
Log:
move the asm string analysis code out of codegen into common 
code where Sema can get to it.  No functionality change.

Modified:
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/lib/AST/Stmt.cpp
    cfe/trunk/lib/CodeGen/CGStmt.cpp

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=66596&r1=66595&r2=66596&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Tue Mar 10 18:21:44 2009
@@ -24,7 +24,6 @@
 #include "llvm/Bitcode/SerializationFwd.h"
 #include "clang/AST/ASTContext.h"
 #include <string>
-
 using llvm::dyn_cast_or_null;
 
 namespace clang {
@@ -923,6 +922,61 @@
   bool isVolatile() const { return IsVolatile; }
   bool isSimple() const { return IsSimple; }
 
+  //===--- Asm String Analysis ---===//
+
+  const StringLiteral *getAsmString() const { return AsmStr; }
+  StringLiteral *getAsmString() { return AsmStr; }
+  
+  /// AsmStringPiece - this is part of a decomposed asm string specification
+  /// (for use with the AnalyzeAsmString function below).  An asm string is
+  /// considered to be a concatenation of these parts.
+  class AsmStringPiece {
+  public:
+    enum Kind {
+      String,  // String in .ll asm string form, "$" -> "$$" and "%%" -> "%".
+      Operand  // Operand reference, with optional modifier %c4.
+    };
+  private:
+    Kind MyKind;
+    std::string Str;
+    unsigned OperandNo;
+  public:
+    AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {}
+    AsmStringPiece(unsigned OpNo, char Modifier)
+      : MyKind(Operand), Str(), OperandNo(OpNo) {
+      Str += Modifier;
+    }
+    
+    bool isString() const { return MyKind == String; }
+    bool isOperand() const { return MyKind == Operand; }
+    
+    const std::string &getString() const {
+      assert(isString());
+      return Str;
+    }
+
+    unsigned getOperandNo() const {
+      assert(isOperand());
+      return OperandNo;
+    }
+    
+    /// getModifier - Get the modifier for this operand, if present.  This
+    /// returns '\0' if there was no modifier.
+    char getModifier() const {
+      assert(isOperand());
+      return Str[0];
+    }
+  };
+  
+  /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
+  /// it into pieces.  If the asm string is erroneous, emit errors and return
+  /// true, otherwise return false.  This handles canonicalization and
+  /// translation of strings from GCC syntax to LLVM IR syntax, and handles
+  //// flattening of named references like %[foo] to Operand AsmStringPiece's. 
+  bool AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece> &Pieces,
+                        ASTContext &C) const;
+  
+  
   //===--- Output operands ---===//
 
   unsigned getNumOutputs() const { return NumOutputs; }
@@ -992,9 +1046,6 @@
 
   
 
-  const StringLiteral *getAsmString() const { return AsmStr; }
-  StringLiteral *getAsmString() { return AsmStr; }
-
   unsigned getNumClobbers() const { return Clobbers.size(); }
   StringLiteral *getClobber(unsigned i) { return Clobbers[i]; }
   const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; }

Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=66596&r1=66595&r2=66596&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Tue Mar 10 18:21:44 2009
@@ -179,6 +179,118 @@
 }
 
 
+/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
+/// it into pieces.  If the asm string is erroneous, emit errors and return
+/// true, otherwise return false.
+bool AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece> &Pieces,
+                               ASTContext &C) const {
+  const char *StrStart = getAsmString()->getStrData();
+  const char *StrEnd = StrStart + getAsmString()->getByteLength();
+  
+  // "Simple" inline asms have no constraints or operands, just convert the asm
+  // string to escape $'s.
+  if (isSimple()) {
+    std::string Result;
+    for (; StrStart != StrEnd; ++StrStart) {
+      switch (*StrStart) {
+      case '$':
+        Result += "$$";
+        break;
+      default:
+        Result += *StrStart;
+        break;
+      }
+    }
+    Pieces.push_back(AsmStringPiece(Result));
+    return false;
+  }
+
+  // CurStringPiece - The current string that we are building up as we scan the
+  // asm string.
+  std::string CurStringPiece;
+  
+  while (1) {
+    // Done with the string?
+    if (StrStart == StrEnd) {
+      if (!CurStringPiece.empty())
+        Pieces.push_back(AsmStringPiece(CurStringPiece));
+      return false;
+    }
+    
+    char CurChar = *StrStart++;
+    if (CurChar == '$') {
+      CurStringPiece += "$$";
+      continue;
+    } else if (CurChar != '%') {
+      CurStringPiece += CurChar;
+      continue;
+    }
+    
+    // Escaped "%" character in asm string.
+    // FIXME: This should be caught during Sema.
+    assert(StrStart != StrEnd && "Trailing '%' in asm string.");
+    
+    char EscapedChar = *StrStart++;
+    if (EscapedChar == '%') {  // %% -> %
+      // Escaped percentage sign.
+      CurStringPiece += '%';
+      continue;
+    }
+    
+    if (EscapedChar == '=') {  // %= -> Generate an unique ID.
+      CurStringPiece += "${:uid}";
+      continue;
+    }
+    
+    // Otherwise, we have an operand.  If we have accumulated a string so far,
+    // add it to the Pieces list.
+    if (!CurStringPiece.empty()) {
+      Pieces.push_back(AsmStringPiece(CurStringPiece));
+      CurStringPiece.clear();
+    }
+    
+    // Handle %x4 and %x[foo] by capturing x as the modifier character.
+    char Modifier = '\0';
+    if (isalpha(EscapedChar)) {
+      Modifier = EscapedChar;
+      EscapedChar = *StrStart++;
+    }
+    
+    if (isdigit(EscapedChar)) {
+      // %n - Assembler operand n
+      char *End;
+      unsigned long N = strtoul(StrStart-1, &End, 10);
+      assert(End != StrStart-1 && "We know that EscapedChar is a digit!");
+      StrStart = End;
+      
+      // FIXME: This should be caught during Sema.
+      //unsigned NumOperands = S.getNumOutputs() + S.getNumInputs();
+      //assert(N < NumOperands && "Operand number out of range!");
+      
+      Pieces.push_back(AsmStringPiece(N, Modifier));
+      continue;
+    }
+    
+    // Handle %[foo], a symbolic operand reference.
+    if (EscapedChar == '[') {
+      const char *NameEnd = (const char*)memchr(StrStart, ']', StrEnd-StrStart);
+      // FIXME: Should be caught by sema.
+      // FIXME: Does sema catch multiple operands with the same name?
+      assert(NameEnd != 0 && "Could not parse symbolic name");
+      std::string SymbolicName(StrStart, NameEnd);
+      StrStart = NameEnd+1;
+      
+      int N = getNamedOperand(SymbolicName);
+      assert(N != -1 && "FIXME: Catch in Sema.");
+      Pieces.push_back(AsmStringPiece(N, Modifier));
+      continue;
+    }
+    
+    assert(0 && "FIXME: Reject");
+    return true;
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // Constructors
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=66596&r1=66595&r2=66596&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Tue Mar 10 18:21:44 2009
@@ -680,112 +680,6 @@
   CaseRangeBlock = SavedCRBlock;
 }
 
-/// ConvertAsmString - Convert the GNU-style asm string to the LLVM-style asm
-/// string.
-static std::string ConvertAsmString(const AsmStmt& S, bool &Failed) {
-  Failed = false;
-  
-  const char *StrStart = S.getAsmString()->getStrData();
-  const char *StrEnd = StrStart + S.getAsmString()->getByteLength();
-
-  // "Simple" inline asms have no constraints or operands, just convert the asm
-  // string to escape $'s.
-  if (S.isSimple()) {
-    std::string Result;
-    for (; StrStart != StrEnd; ++StrStart) {
-      switch (*StrStart) {
-      case '$':
-        Result += "$$";
-        break;
-      default:
-        Result += *StrStart;
-        break;
-      }
-    }
-    return Result;
-  }
-  
-  std::string Result;
-  
-  while (1) {
-    // Done with the string?
-    if (StrStart == StrEnd)
-      return Result;
-
-    char CurChar = *StrStart++;
-    if (CurChar == '$') {
-      Result += "$$";
-      continue;
-    } else if (CurChar != '%') {
-      Result += CurChar;
-      continue;
-    }
-
-    // Escaped "%" character in asm string.
-    // FIXME: This should be caught during Sema.
-    assert(StrStart != StrEnd && "Trailing '%' in asm string.");
-      
-    char EscapedChar = *StrStart++;
-    if (EscapedChar == '%') {  // %% -> %
-      // Escaped percentage sign.
-      Result += '%';
-      continue;
-    }
-    
-    if (EscapedChar == '=') {  // %= -> Generate an unique ID.
-      Result += "${:uid}";
-      continue;
-    }
-    
-    // Handle %x4 and %x[foo] by capturing x as the modifier character.
-    char Modifier = '\0';
-    if (isalpha(EscapedChar)) {
-      Modifier = EscapedChar;
-      EscapedChar = *StrStart++;
-    }
-    
-    if (isdigit(EscapedChar)) {
-      // %n - Assembler operand n
-      char *End;
-      unsigned long N = strtoul(StrStart-1, &End, 10);
-      assert(End != StrStart-1 && "We know that EscapedChar is a digit!");
-      StrStart = End;
-      
-      // FIXME: This should be caught during Sema.
-      //unsigned NumOperands = S.getNumOutputs() + S.getNumInputs();
-      //assert(N < NumOperands && "Operand number out of range!");
-      
-      if (Modifier == '\0')
-        Result += '$' + llvm::utostr(N);
-      else
-        Result += "${" + llvm::utostr(N) + ':' + Modifier + '}';
-      continue;
-    }
-    
-    // Handle %[foo], a symbolic operand reference.
-    if (EscapedChar == '[') {
-      const char *NameEnd = (const char*)memchr(StrStart, ']', StrEnd-StrStart);
-      // FIXME: Should be caught by sema.
-      // FIXME: Does sema catch multiple operands with the same name?
-      assert(NameEnd != 0 && "Could not parse symbolic name");
-      std::string SymbolicName(StrStart, NameEnd);
-      StrStart = NameEnd+1;
-      
-      int N = S.getNamedOperand(SymbolicName);
-      assert(N != -1 && "FIXME: Catch in Sema.");
-
-      if (Modifier == '\0')
-        Result += '$' + llvm::utostr(N);
-      else
-        Result += "${" + llvm::utostr(N) + ':' + Modifier + '}';
-      continue;
-    }
-     
-    Failed = true;
-    return "";
-  }
-}
-
 static std::string SimplifyConstraint(const char* Constraint,
                                       TargetInfo &Target,
                                       const std::string *OutputNamesBegin = 0,
@@ -859,12 +753,21 @@
 }
 
 void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
-  bool Failed;
-  std::string AsmString = ConvertAsmString(S, Failed);
-
-  if (Failed) {
-    ErrorUnsupported(&S, "asm string");
-    return;
+  // Analyze the asm string to decompose it into its pieces.  We know that Sema
+  // has already done this, so it is guaranteed to be successful.
+  llvm::SmallVector<AsmStmt::AsmStringPiece, 4> Pieces;
+  S.AnalyzeAsmString(Pieces, getContext());
+  
+  // Assemble the pieces into the final asm string.
+  std::string AsmString;
+  for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
+    if (Pieces[i].isString())
+      AsmString += Pieces[i].getString();
+    else if (Pieces[i].getModifier() == '\0')
+      AsmString += '$' + llvm::utostr(Pieces[i].getOperandNo());
+    else
+      AsmString += "${" + llvm::utostr(Pieces[i].getOperandNo()) + ':' +
+                   Pieces[i].getModifier() + '}';
   }
   
   std::string Constraints;





More information about the cfe-commits mailing list