~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/utils/TableGen/AsmWriterInst.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//===- AsmWriterInst.h - Classes encapsulating a printable inst -----------===//
2
 
//
3
 
//                     The LLVM Compiler Infrastructure
4
 
//
5
 
// This file is distributed under the University of Illinois Open Source
6
 
// License. See LICENSE.TXT for details.
7
 
//
8
 
//===----------------------------------------------------------------------===//
9
 
//
10
 
// These classes implement a parser for assembly strings.
11
 
//
12
 
//===----------------------------------------------------------------------===//
13
 
 
14
 
#include "AsmWriterInst.h"
15
 
#include "CodeGenTarget.h"
16
 
#include "Record.h"
17
 
#include "llvm/ADT/StringExtras.h"
18
 
 
19
 
using namespace llvm;
20
 
 
21
 
static bool isIdentChar(char C) {
22
 
  return (C >= 'a' && C <= 'z') ||
23
 
  (C >= 'A' && C <= 'Z') ||
24
 
  (C >= '0' && C <= '9') ||
25
 
  C == '_';
26
 
}
27
 
 
28
 
std::string AsmWriterOperand::getCode() const {
29
 
  if (OperandType == isLiteralTextOperand) {
30
 
    if (Str.size() == 1)
31
 
      return "O << '" + Str + "'; ";
32
 
    return "O << \"" + Str + "\"; ";
33
 
  }
34
 
  
35
 
  if (OperandType == isLiteralStatementOperand)
36
 
    return Str;
37
 
  
38
 
  std::string Result = Str + "(MI";
39
 
  if (MIOpNo != ~0U)
40
 
    Result += ", " + utostr(MIOpNo);
41
 
  Result += ", O";
42
 
  if (!MiModifier.empty())
43
 
    Result += ", \"" + MiModifier + '"';
44
 
  return Result + "); ";
45
 
}
46
 
 
47
 
/// ParseAsmString - Parse the specified Instruction's AsmString into this
48
 
/// AsmWriterInst.
49
 
///
50
 
AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
51
 
                             unsigned Variant,
52
 
                             int FirstOperandColumn,
53
 
                             int OperandSpacing) {
54
 
  this->CGI = &CGI;
55
 
  
56
 
  unsigned CurVariant = ~0U;  // ~0 if we are outside a {.|.|.} region, other #.
57
 
  
58
 
  // This is the number of tabs we've seen if we're doing columnar layout.
59
 
  unsigned CurColumn = 0;
60
 
  
61
 
  
62
 
  // NOTE: Any extensions to this code need to be mirrored in the 
63
 
  // AsmPrinter::printInlineAsm code that executes as compile time (assuming
64
 
  // that inline asm strings should also get the new feature)!
65
 
  const std::string &AsmString = CGI.AsmString;
66
 
  std::string::size_type LastEmitted = 0;
67
 
  while (LastEmitted != AsmString.size()) {
68
 
    std::string::size_type DollarPos =
69
 
    AsmString.find_first_of("${|}\\", LastEmitted);
70
 
    if (DollarPos == std::string::npos) DollarPos = AsmString.size();
71
 
    
72
 
    // Emit a constant string fragment.
73
 
    
74
 
    if (DollarPos != LastEmitted) {
75
 
      if (CurVariant == Variant || CurVariant == ~0U) {
76
 
        for (; LastEmitted != DollarPos; ++LastEmitted)
77
 
          switch (AsmString[LastEmitted]) {
78
 
            case '\n':
79
 
              AddLiteralString("\\n");
80
 
              break;
81
 
            case '\t':
82
 
              // If the asm writer is not using a columnar layout, \t is not
83
 
              // magic.
84
 
              if (FirstOperandColumn == -1 || OperandSpacing == -1) {
85
 
                AddLiteralString("\\t");
86
 
              } else {
87
 
                // We recognize a tab as an operand delimeter.
88
 
                unsigned DestColumn = FirstOperandColumn + 
89
 
                CurColumn++ * OperandSpacing;
90
 
                Operands.push_back(
91
 
                  AsmWriterOperand(
92
 
                    "O.PadToColumn(" +
93
 
                    utostr(DestColumn) + ");\n",
94
 
                    AsmWriterOperand::isLiteralStatementOperand));
95
 
              }
96
 
              break;
97
 
            case '"':
98
 
              AddLiteralString("\\\"");
99
 
              break;
100
 
            case '\\':
101
 
              AddLiteralString("\\\\");
102
 
              break;
103
 
            default:
104
 
              AddLiteralString(std::string(1, AsmString[LastEmitted]));
105
 
              break;
106
 
          }
107
 
      } else {
108
 
        LastEmitted = DollarPos;
109
 
      }
110
 
    } else if (AsmString[DollarPos] == '\\') {
111
 
      if (DollarPos+1 != AsmString.size() &&
112
 
          (CurVariant == Variant || CurVariant == ~0U)) {
113
 
        if (AsmString[DollarPos+1] == 'n') {
114
 
          AddLiteralString("\\n");
115
 
        } else if (AsmString[DollarPos+1] == 't') {
116
 
          // If the asm writer is not using a columnar layout, \t is not
117
 
          // magic.
118
 
          if (FirstOperandColumn == -1 || OperandSpacing == -1) {
119
 
            AddLiteralString("\\t");
120
 
            break;
121
 
          }
122
 
          
123
 
          // We recognize a tab as an operand delimeter.
124
 
          unsigned DestColumn = FirstOperandColumn + 
125
 
          CurColumn++ * OperandSpacing;
126
 
          Operands.push_back(
127
 
            AsmWriterOperand("O.PadToColumn(" + utostr(DestColumn) + ");\n",
128
 
                             AsmWriterOperand::isLiteralStatementOperand));
129
 
          break;
130
 
        } else if (std::string("${|}\\").find(AsmString[DollarPos+1]) 
131
 
                   != std::string::npos) {
132
 
          AddLiteralString(std::string(1, AsmString[DollarPos+1]));
133
 
        } else {
134
 
          throw "Non-supported escaped character found in instruction '" +
135
 
          CGI.TheDef->getName() + "'!";
136
 
        }
137
 
        LastEmitted = DollarPos+2;
138
 
        continue;
139
 
      }
140
 
    } else if (AsmString[DollarPos] == '{') {
141
 
      if (CurVariant != ~0U)
142
 
        throw "Nested variants found for instruction '" +
143
 
        CGI.TheDef->getName() + "'!";
144
 
      LastEmitted = DollarPos+1;
145
 
      CurVariant = 0;   // We are now inside of the variant!
146
 
    } else if (AsmString[DollarPos] == '|') {
147
 
      if (CurVariant == ~0U)
148
 
        throw "'|' character found outside of a variant in instruction '"
149
 
        + CGI.TheDef->getName() + "'!";
150
 
      ++CurVariant;
151
 
      ++LastEmitted;
152
 
    } else if (AsmString[DollarPos] == '}') {
153
 
      if (CurVariant == ~0U)
154
 
        throw "'}' character found outside of a variant in instruction '"
155
 
        + CGI.TheDef->getName() + "'!";
156
 
      ++LastEmitted;
157
 
      CurVariant = ~0U;
158
 
    } else if (DollarPos+1 != AsmString.size() &&
159
 
               AsmString[DollarPos+1] == '$') {
160
 
      if (CurVariant == Variant || CurVariant == ~0U) {
161
 
        AddLiteralString("$");  // "$$" -> $
162
 
      }
163
 
      LastEmitted = DollarPos+2;
164
 
    } else {
165
 
      // Get the name of the variable.
166
 
      std::string::size_type VarEnd = DollarPos+1;
167
 
      
168
 
      // handle ${foo}bar as $foo by detecting whether the character following
169
 
      // the dollar sign is a curly brace.  If so, advance VarEnd and DollarPos
170
 
      // so the variable name does not contain the leading curly brace.
171
 
      bool hasCurlyBraces = false;
172
 
      if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) {
173
 
        hasCurlyBraces = true;
174
 
        ++DollarPos;
175
 
        ++VarEnd;
176
 
      }
177
 
      
178
 
      while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
179
 
        ++VarEnd;
180
 
      std::string VarName(AsmString.begin()+DollarPos+1,
181
 
                          AsmString.begin()+VarEnd);
182
 
      
183
 
      // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed
184
 
      // into printOperand.  Also support ${:feature}, which is passed into
185
 
      // PrintSpecial.
186
 
      std::string Modifier;
187
 
      
188
 
      // In order to avoid starting the next string at the terminating curly
189
 
      // brace, advance the end position past it if we found an opening curly
190
 
      // brace.
191
 
      if (hasCurlyBraces) {
192
 
        if (VarEnd >= AsmString.size())
193
 
          throw "Reached end of string before terminating curly brace in '"
194
 
          + CGI.TheDef->getName() + "'";
195
 
        
196
 
        // Look for a modifier string.
197
 
        if (AsmString[VarEnd] == ':') {
198
 
          ++VarEnd;
199
 
          if (VarEnd >= AsmString.size())
200
 
            throw "Reached end of string before terminating curly brace in '"
201
 
            + CGI.TheDef->getName() + "'";
202
 
          
203
 
          unsigned ModifierStart = VarEnd;
204
 
          while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
205
 
            ++VarEnd;
206
 
          Modifier = std::string(AsmString.begin()+ModifierStart,
207
 
                                 AsmString.begin()+VarEnd);
208
 
          if (Modifier.empty())
209
 
            throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'";
210
 
        }
211
 
        
212
 
        if (AsmString[VarEnd] != '}')
213
 
          throw "Variable name beginning with '{' did not end with '}' in '"
214
 
          + CGI.TheDef->getName() + "'";
215
 
        ++VarEnd;
216
 
      }
217
 
      if (VarName.empty() && Modifier.empty())
218
 
        throw "Stray '$' in '" + CGI.TheDef->getName() +
219
 
        "' asm string, maybe you want $$?";
220
 
      
221
 
      if (VarName.empty()) {
222
 
        // Just a modifier, pass this into PrintSpecial.
223
 
        Operands.push_back(AsmWriterOperand("PrintSpecial", 
224
 
                                            ~0U, 
225
 
                                            ~0U, 
226
 
                                            Modifier));
227
 
      } else {
228
 
        // Otherwise, normal operand.
229
 
        unsigned OpNo = CGI.getOperandNamed(VarName);
230
 
        CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo];
231
 
        
232
 
        if (CurVariant == Variant || CurVariant == ~0U) {
233
 
          unsigned MIOp = OpInfo.MIOperandNo;
234
 
          Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, 
235
 
                                              OpNo,
236
 
                                              MIOp,
237
 
                                              Modifier));
238
 
        }
239
 
      }
240
 
      LastEmitted = VarEnd;
241
 
    }
242
 
  }
243
 
  
244
 
  Operands.push_back(AsmWriterOperand("return;",
245
 
    AsmWriterOperand::isLiteralStatementOperand));
246
 
}
247
 
 
248
 
/// MatchesAllButOneOp - If this instruction is exactly identical to the
249
 
/// specified instruction except for one differing operand, return the differing
250
 
/// operand number.  If more than one operand mismatches, return ~1, otherwise
251
 
/// if the instructions are identical return ~0.
252
 
unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
253
 
  if (Operands.size() != Other.Operands.size()) return ~1;
254
 
  
255
 
  unsigned MismatchOperand = ~0U;
256
 
  for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
257
 
    if (Operands[i] != Other.Operands[i]) {
258
 
      if (MismatchOperand != ~0U)  // Already have one mismatch?
259
 
        return ~1U;
260
 
      else
261
 
        MismatchOperand = i;
262
 
    }
263
 
  }
264
 
  return MismatchOperand;
265
 
}