[llvm-commits] [dragonegg] r126374 - /dragonegg/trunk/llvm-convert.cpp

Duncan Sands baldrick at free.fr
Thu Feb 24 01:22:05 PST 2011


Author: baldrick
Date: Thu Feb 24 03:22:05 2011
New Revision: 126374

URL: http://llvm.org/viewvc/llvm-project?rev=126374&view=rev
Log:
Simplify part of asm handling, and add some explanatory comments.  In
particular there is no need to resolve symbolic names because nowadays
it is done before getting here.

Modified:
    dragonegg/trunk/llvm-convert.cpp

Modified: dragonegg/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-convert.cpp?rev=126374&r1=126373&r2=126374&view=diff
==============================================================================
--- dragonegg/trunk/llvm-convert.cpp (original)
+++ dragonegg/trunk/llvm-convert.cpp Thu Feb 24 03:22:05 2011
@@ -3112,8 +3112,7 @@
 ///       punctuation.
 /// Other %xN expressions are turned into LLVM ${N:x} operands.
 ///
-static std::string ConvertInlineAsmStr(gimple stmt, tree outputs, tree inputs,
-                                       tree labels, unsigned NumOperands) {
+static std::string ConvertInlineAsmStr(gimple stmt, unsigned NumOperands) {
   const char *AsmStr = gimple_asm_string(stmt);
 
   // gimple_asm_input_p - This flag is set if this is a non-extended ASM,
@@ -3131,17 +3130,11 @@
     }
   }
 
-  // Expand [name] symbolic operand names.
-  tree str = resolve_asm_operand_names(build_string (strlen (AsmStr), AsmStr),
-                                       outputs, inputs, labels);
-
-  const char *InStr = TREE_STRING_POINTER(str);
-
   std::string Result;
   while (1) {
-    switch (*InStr++) {
+    switch (*AsmStr++) {
     case 0: return Result;                 // End of string.
-    default: Result += InStr[-1]; break;   // Normal character.
+    default: Result += AsmStr[-1]; break;  // Normal character.
     case '$': Result += "$$"; break;       // Escape '$' characters.
 #ifdef ASSEMBLER_DIALECT
     // Note that we can't escape to ${, because that is the syntax for vars.
@@ -3150,23 +3143,23 @@
     case '|': Result += "$|"; break;       // Escape '|' character.
 #endif
     case '%':                              // GCC escape character.
-      char EscapedChar = *InStr++;
+      char EscapedChar = *AsmStr++;
       if (EscapedChar == '%') {            // Escaped '%' character
         Result += '%';
       } else if (EscapedChar == '=') {     // Unique ID for the asm instance.
         Result += "${:uid}";
       }
 #ifdef LLVM_ASM_EXTENSIONS
-      LLVM_ASM_EXTENSIONS(EscapedChar, InStr, Result)
+      LLVM_ASM_EXTENSIONS(EscapedChar, AsmStr, Result)
 #endif
       else if (ISALPHA(EscapedChar)) {
         // % followed by a letter and some digits. This outputs an operand in a
         // special way depending on the letter.  We turn this into LLVM ${N:o}
         // syntax.
         char *EndPtr;
-        unsigned long OpNum = strtoul(InStr, &EndPtr, 10);
+        unsigned long OpNum = strtoul(AsmStr, &EndPtr, 10);
 
-        if (InStr == EndPtr) {
+        if (AsmStr == EndPtr) {
           error_at(gimple_location(stmt),
                    "operand number missing after %%-letter");
           return Result;
@@ -3175,11 +3168,11 @@
           return Result;
         }
         Result += "${" + utostr(OpNum) + ":" + EscapedChar + "}";
-        InStr = EndPtr;
+        AsmStr = EndPtr;
       } else if (ISDIGIT(EscapedChar)) {
         char *EndPtr;
-        unsigned long OpNum = strtoul(InStr-1, &EndPtr, 10);
-        InStr = EndPtr;
+        unsigned long OpNum = strtoul(AsmStr-1, &EndPtr, 10);
+        AsmStr = EndPtr;
         Result += "$" + utostr(OpNum);
 #ifdef PRINT_OPERAND_PUNCT_VALID_P
       } else if (PRINT_OPERAND_PUNCT_VALID_P((unsigned char)EscapedChar)) {
@@ -3460,8 +3453,9 @@
 
 static void FreeConstTupleStrings(const char **ReplacementStrings,
                                   unsigned int Size) {
-  for (unsigned int i=0; i<Size; i++)
-    free(const_cast<char *>(ReplacementStrings[i]));
+  if (ReplacementStrings)
+    for (unsigned int i=0; i<Size; i++)
+      free(const_cast<char *>(ReplacementStrings[i]));
 }
 
 
@@ -6699,6 +6693,51 @@
 //===----------------------------------------------------------------------===//
 
 void TreeToLLVM::RenderGIMPLE_ASM(gimple stmt) {
+  // A gimple asm statement consists of an asm string, a list of outputs, a list
+  // of inputs, a list of clobbers, a list of labels and a "volatile" flag.
+  // These correspond directly to the elements of an asm statement.  For example
+  //   asm ("combine %2,%0" : "=r" (x) : "0" (x), "g" (y));
+  // Here the asm string is "combine %2,%0" and can be obtained as a const char*
+  // by calling gimple_asm_string.  The only output is "=r" (x).  The number of
+  // outputs is given by gimple_asm_noutputs, 1 in this case, and the outputs
+  // themselves can be obtained by calling gimple_asm_output_op.  This returns a
+  // TREE_LIST node with an SSA name for "x" as the TREE_VALUE; the TREE_PURPOSE
+  // is also a TREE_LIST with TREE_VALUE a string constant holding "=r".  There
+  // are two inputs, "0" (x) and "g" (y), so gimple_asm_ninputs returns 2.  The
+  // routine gimple_asm_input_op returns them in the same format as for outputs.
+  // The number of clobbers is returned by gimple_asm_nclobbers, 0 in this case.
+  // To get the clobbers use gimple_asm_clobber_op.  This returns a TREE_LIST
+  // node with TREE_VALUE a string constant holding the clobber.  To find out if
+  // the asm is volatile call gimple_asm_volatile_p, which returns true if so.
+  // See below for labels (this example does not have any).
+
+  // Note that symbolic names have been substituted before getting here.  For
+  // example this
+  //   asm ("cmoveq %1,%2,%[result]" : [result] "=r"(result)
+  //        : "r"(test), "r"(new), "[result]"(old));
+  // turns up as
+  //   asm ("cmoveq %1,%2,%0" : "=r"(result) : "r"(test), "r"(new), "0"(old));
+
+  // Note that clobbers may not turn up in the same order as in the original, eg
+  //   asm volatile ("movc3 %0,%1,%2" : /* no outputs */
+  //                 : "g" (from), "g" (to), "g" (count)
+  //                 : "r0", "r1", "r2", "r3", "r4", "r5");
+  // The clobbers turn up as "r5", "r4", "r3", "r2", "r1", "r0".
+
+  // Here is an example of the "asm goto" construct (not yet supported by LLVM):
+  //   int frob(int x) {
+  //     int y;
+  //     asm goto ("frob %%r5, %1; jc %l[error]; mov (%2), %%r5"
+  //               : : "r"(x), "r"(&y) : "r5", "memory" : error);
+  //     return y;
+  //   error:
+  //     return -1;
+  //   }
+  // The number of labels, one in this case, is returned by gimple_asm_nlabels.
+  // The labels themselves are returned by gimple_asm_label_op as a TREE_LIST
+  // node with TREE_PURPOSE a string constant holding the label name ("error")
+  // and TREE_VALUE holding the appropriate LABEL_DECL.
+
   // TODO: Add support for labels.
   if (gimple_asm_nlabels(stmt) > 0) {
     sorry("'asm goto' not supported");
@@ -6820,8 +6859,6 @@
 
   std::vector<Value*> CallOps;
   std::vector<const Type*> CallArgTypes;
-  std::string NewAsmStr = ConvertInlineAsmStr(stmt, outputs, inputs, labels,
-                                              NumOutputs+NumInputs);
   std::string ConstraintStr;
   bool HasSideEffects = gimple_asm_volatile_p(stmt) || !outputs;
 
@@ -6843,8 +6880,7 @@
     bool IsInOut, AllowsReg, AllowsMem;
     if (!parse_output_constraint(&Constraint, ValNum, NumInputs, NumOutputs,
                                  &AllowsMem, &AllowsReg, &IsInOut)) {
-      if (NumChoices>1)
-        FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
+      FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
       return;
     }
     assert(Constraint[0] == '=' && "Not an output constraint?");
@@ -6930,8 +6966,7 @@
     if (!parse_input_constraint(Constraints+ValNum, ValNum-NumOutputs,
                                 NumInputs, NumOutputs, NumInOut,
                                 Constraints, &AllowsMem, &AllowsReg)) {
-      if (NumChoices>1)
-        FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
+      FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
       return;
     }
     bool isIndirect = false;
@@ -7008,8 +7043,7 @@
             error_at(gimple_location(stmt),
                      "unsupported inline asm: input constraint with a matching "
                      "output constraint of incompatible type!");
-            if (NumChoices>1)
-              FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
+            FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
             return;
           }
           unsigned OTyBits = TD.getTypeSizeInBits(OTy);
@@ -7089,8 +7123,7 @@
     case -2:     // Invalid.
       error_at(gimple_location(stmt), "unknown register name %qs in %<asm%>",
                RegName);
-      if (NumChoices>1)
-        FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
+      FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
       return;
     case -3:     // cc
       ConstraintStr += ",~{cc}";
@@ -7128,11 +7161,11 @@
   // Make sure we're created a valid inline asm expression.
   if (!InlineAsm::Verify(FTy, ConstraintStr)) {
     error_at(gimple_location(stmt), "Invalid or unsupported inline assembly!");
-    if (NumChoices>1)
-      FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
+    FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
     return;
   }
 
+  std::string NewAsmStr = ConvertInlineAsmStr(stmt, NumOutputs+NumInputs);
   Value *Asm = InlineAsm::get(FTy, NewAsmStr, ConstraintStr, HasSideEffects);
   CallInst *CV = Builder.CreateCall(Asm, CallOps.begin(), CallOps.end(),
                                     CallResultTypes.empty() ? "" : "asmtmp");
@@ -7162,8 +7195,7 @@
   if (const TargetLowering *TLI = TheTarget->getTargetLowering())
     TLI->ExpandInlineAsm(CV);
 
-  if (NumChoices>1)
-    FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
+  FreeConstTupleStrings(ReplacementStrings, NumInputs+NumOutputs);
 }
 
 void TreeToLLVM::RenderGIMPLE_ASSIGN(gimple stmt) {





More information about the llvm-commits mailing list