]> granicus.if.org Git - clang/commitdiff
[ms-inline asm] Handle the enumeration of input and output expressions in a
authorChad Rosier <mcrosier@apple.com>
Thu, 13 Sep 2012 00:06:55 +0000 (00:06 +0000)
committerChad Rosier <mcrosier@apple.com>
Thu, 13 Sep 2012 00:06:55 +0000 (00:06 +0000)
more robust way to address a few FIXMEs.

The initial implementation, r163342, built the IR asm string and then tried to
patch things on the fly without enough context.  Specifically, it didn't skip
mnemonics nor did it track with assembly instruction an expression was related
to.  The new implementation patches the operands and then builds the final
IR string.

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

lib/Sema/SemaStmtAsm.cpp
test/CodeGen/ms-inline-asm.c

index 9109bcb854ae5c6f20bd9c0bee839a680ae78247..3bc53f70f9ea5baf676436bd71e5cbe8d679c8e5 100644 (file)
@@ -414,15 +414,13 @@ static void buildMSAsmPieces(std::vector<std::string> &AsmStrings,
     buildMSAsmPieces(AsmStrings[i], Pieces[i]);
 }
 
-// Build the AsmString used by the IR.  Also build the individual asm
-// instruction(s) and place them in the AsmStrings vector; these are fed to the
-// AsmParser.
-static std::string buildMSAsmString(Sema &SemaRef, ArrayRef<Token> AsmToks,
-                                    std::vector<std::string> &AsmStrings,
+// Build the individual assembly instruction(s) and place them in the AsmStrings
+// vector.  These strings are fed to the AsmParser.
+static void buildMSAsmStrings(Sema &SemaRef, ArrayRef<Token> AsmToks,
+                              std::vector<std::string> &AsmStrings,
                      std::vector<std::pair<unsigned,unsigned> > &AsmTokRanges) {
   assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
 
-  SmallString<512> Res;
   SmallString<512> Asm;
   unsigned startTok = 0;
   for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
@@ -435,7 +433,6 @@ static std::string buildMSAsmString(Sema &SemaRef, ArrayRef<Token> AsmToks,
         AsmTokRanges.push_back(std::make_pair(startTok, i-1));
         startTok = i;
         Asm.clear();
-        Res += "\n\t";
       }
       if (AsmToks[i].is(tok::kw_asm)) {
         i++; // Skip __asm
@@ -443,21 +440,14 @@ static std::string buildMSAsmString(Sema &SemaRef, ArrayRef<Token> AsmToks,
       }
     }
 
-    if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) {
+    if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm)
       Asm += ' ';
-      Res += ' ';
-    }
-
-    if (AsmToks[i].is(tok::numeric_constant))
-      Res += "$$";
 
     StringRef Spelling = getSpelling(SemaRef, AsmToks[i]);
     Asm += Spelling;
-    Res += Spelling;
   }
   AsmStrings.push_back(Asm.str());
   AsmTokRanges.push_back(std::make_pair(startTok, AsmToks.size()-1));
-  return Res.str();
 }
 
 #define DEF_SIMPLE_MSASM(STR)                                                \
@@ -467,21 +457,23 @@ static std::string buildMSAsmString(Sema &SemaRef, ArrayRef<Token> AsmToks,
                             InputExprs, OutputExprs, STR, Constraints,       \
                             Clobbers, EndLoc);
 
-StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
-                                SourceLocation LBraceLoc,
-                                ArrayRef<Token> AsmToks,
-                                SourceLocation EndLoc) {
+StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
+                                ArrayRef<Token> AsmToks,SourceLocation EndLoc) {
   SmallVector<StringRef, 4> Constraints;
   std::vector<std::string> InputConstraints;
   std::vector<std::string> OutputConstraints;
   SmallVector<StringRef, 4> Clobbers;
   std::set<std::string> ClobberRegs;
+
+  // FIXME: Use a struct to hold the various expression information.
   SmallVector<IdentifierInfo*, 4> Inputs;
   SmallVector<IdentifierInfo*, 4> Outputs;
   SmallVector<Expr*, 4> InputExprs;
   SmallVector<Expr*, 4> OutputExprs;
   SmallVector<std::string, 4> InputExprNames;
   SmallVector<std::string, 4> OutputExprNames;
+  SmallVector<unsigned, 4> InputExprStrIdx;
+  SmallVector<unsigned, 4> OutputExprStrIdx;
 
   // Empty asm statements don't need to instantiate the AsmParser, etc.
   StringRef EmptyAsmStr;
@@ -489,8 +481,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
 
   std::vector<std::string> AsmStrings;
   std::vector<std::pair<unsigned,unsigned> > AsmTokRanges;
-  std::string AsmString = buildMSAsmString(*this, AsmToks, AsmStrings,
-                                           AsmTokRanges);
+  buildMSAsmStrings(*this, AsmToks, AsmStrings, AsmTokRanges);
 
   std::vector<std::vector<StringRef> > Pieces(AsmStrings.size());
   buildMSAsmPieces(AsmStrings, Pieces);
@@ -628,11 +619,13 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
                   Outputs.push_back(II);
                   OutputExprs.push_back(Result.take());
                   OutputExprNames.push_back(Name.str());
+                  OutputExprStrIdx.push_back(StrIdx);
                   OutputConstraints.push_back("=r");
                 } else {
                   Inputs.push_back(II);
                   InputExprs.push_back(Result.take());
                   InputExprNames.push_back(Name.str());
+                  InputExprStrIdx.push_back(StrIdx);
                   InputConstraints.push_back("r");
                 }
               }
@@ -657,24 +650,101 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
     Constraints.push_back(*I);
 
   // Enumerate the AsmString expressions.
-  // FIXME: This isn't going to work if:
-  //  1. The symbol name and an opcode/reg share the same, or are a substring of
-  //     the, name.
-  //  2. The symbol name appears more then once in the asm string.
   unsigned OpNum = 0;
   for (unsigned i = 0, e = OutputExprNames.size(); i != e; ++i, ++OpNum) {
-    size_t found = AsmString.find(OutputExprNames[i]);
-    SmallString<32> Res;
-    llvm::raw_svector_ostream OS(Res);
-    OS << '$' << OpNum;
-    AsmString.replace(found, OutputExprNames[i].size(), OS.str());
+    unsigned StrIdx = OutputExprStrIdx[i];
+    // Iterate over the assembly instruction pieces, skipping the mnemonic.
+    for (unsigned j = 1, f = Pieces[StrIdx].size(); j != f; ++j) {
+      // If the operand and the expression name match, then rewrite the operand.
+      if (OutputExprNames[i] == Pieces[StrIdx][j]) {
+        SmallString<32> Res;
+        llvm::raw_svector_ostream OS(Res);
+        OS << '$' << OpNum;
+        OutputExprNames[i] = OS.str();
+        Pieces[StrIdx][j] = OutputExprNames[i];
+        break;
+      }
+      // Check to see if the expression is a substring of the asm piece.
+      std::pair< StringRef, StringRef > Split =        Pieces[StrIdx][j].split(' ');
+      bool isKeyword = llvm::StringSwitch<bool>(Split.first)
+        .Cases("BYTE", "byte", "WORD", "word", "DWORD", true)
+        .Cases("dword", "QWORD", "qword", "XWORD", "xword", true)
+        .Cases("XMMWORD", "xmmword", "YMMWORD", "ymmword", true)
+        .Default(false);
+      if (isKeyword &&
+          Split.second.find_first_of(OutputExprNames[i]) != StringRef::npos) {
+        // Is is a substring, do the replacement.
+        SmallString<32> Res;
+        llvm::raw_svector_ostream OS(Res);
+        OS << '$' << OpNum;
+        std::string piece = Pieces[StrIdx][j].str();
+        size_t found = piece.find(InputExprNames[i]);
+        piece.replace(found, InputExprNames[i].size(), OS.str());
+        OutputExprNames[i] = piece;
+        Pieces[StrIdx][j] = OutputExprNames[i];
+        break;
+      }
+    }
   }
   for (unsigned i = 0, e = InputExprNames.size(); i != e; ++i, ++OpNum) {
-    size_t found = AsmString.find(InputExprNames[i]);
-    SmallString<32> Res;
-    llvm::raw_svector_ostream OS(Res);
-    OS << '$' << OpNum;
-    AsmString.replace(found, InputExprNames[i].size(), OS.str());
+    unsigned StrIdx = InputExprStrIdx[i];
+    // Iterate over the assembly instruction pieces, skipping the mnemonic.
+    for (unsigned j = 1, f = Pieces[StrIdx].size(); j != f; ++j) {
+      // If the operand and the expression name match, then rewrite the operand.
+      if (InputExprNames[i] == Pieces[StrIdx][j]) {
+        SmallString<32> Res;
+        llvm::raw_svector_ostream OS(Res);
+        OS << '$' << OpNum;
+        InputExprNames[i] = OS.str();
+        Pieces[StrIdx][j] = InputExprNames[i];
+        break;
+      }
+      // Check to see if the expression is a substring of the asm piece.
+      std::pair< StringRef, StringRef > Split =        Pieces[StrIdx][j].split(' ');
+      bool isKeyword = llvm::StringSwitch<bool>(Split.first)
+        .Cases("BYTE", "byte", "WORD", "word", "DWORD", true)
+        .Cases("dword", "QWORD", "qword", "XWORD", "xword", true)
+        .Cases("XMMWORD", "xmmword", "YMMWORD", "ymmword", true)
+        .Default(false);
+      if (isKeyword &&
+          Split.second.find_first_of(InputExprNames[i]) != StringRef::npos) {
+        // It is a substring, do the replacement.
+        SmallString<32> Res;
+        llvm::raw_svector_ostream OS(Res);
+        OS << '$' << OpNum;
+        std::string piece = Pieces[StrIdx][j].str();
+        size_t found = piece.find(InputExprNames[i]);
+        piece.replace(found, InputExprNames[i].size(), OS.str());
+        InputExprNames[i] = piece;
+        Pieces[StrIdx][j] = InputExprNames[i];
+        break;
+      }
+    }
+  }
+
+  // Emit the IR assembly string.
+  std::string AsmString;
+  for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
+    // Skip empty asm stmts.
+    if (Pieces[i].empty()) continue;
+
+    if (i > 0)
+      AsmString += "\n\t";
+
+    // Emit the mnemonic.
+    AsmString += Pieces[i][0];
+    if (Pieces[i].size() > 1)
+      AsmString += ' ';
+
+    // Emit the operands adding $$ to constants.
+    for (unsigned j = 1, f = Pieces[i].size(); j != f; ++j) {
+      if (j > 1) AsmString += ", ";
+      unsigned Val;
+      if (!Pieces[i][j].getAsInteger(0, Val))
+        AsmString += "$$";
+
+      AsmString += Pieces[i][j];
+    }
   }
 
   MSAsmStmt *NS =
index b08f869ac44bffd1351e6e4ad7681d684a5e770b..b6bc3853f5c85fa3670c7aa2dd937d798279f73c 100644 (file)
@@ -151,3 +151,16 @@ void t18(void) {
 // CHECK: t18
 // CHECK: call void asm sideeffect inteldialect "mov dword ptr [eax], eax", "~{dirflag},~{fpsr},~{flags}"() nounwind
 }
+
+unsigned t19(void) {
+  unsigned i = 1, j, l = 1, m;
+  __asm {
+    mov eax, i
+    mov j, eax
+    mov eax, l
+    mov m, eax
+  }
+  return j + m;
+// CHECK: t19
+// CHECK: call { i32, i32 } asm sideeffect inteldialect "mov eax, $2\0A\09mov $0, eax\0A\09mov eax, $3\0A\09mov $1, eax", "=r,=r,r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32 %{{.*}}, i32 %{{.*}}) nounwind
+}