[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