brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 97430a1 Raw
209 lines · cpp
1//===- AsmWriterInst.h - Classes encapsulating a printable inst -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// These classes implement a parser for assembly strings.10//11//===----------------------------------------------------------------------===//12 13#include "AsmWriterInst.h"14#include "CodeGenInstruction.h"15#include "llvm/ADT/StringExtras.h"16#include "llvm/TableGen/Error.h"17#include "llvm/TableGen/Record.h"18 19using namespace llvm;20 21static bool isIdentChar(char C) { return isAlnum(C) || C == '_'; }22 23std::string AsmWriterOperand::getCode(bool PassSubtarget) const {24  if (OperandType == isLiteralTextOperand) {25    if (Str.size() == 1)26      return "O << '" + Str + "';";27    return "O << \"" + Str + "\";";28  }29 30  if (OperandType == isLiteralStatementOperand)31    return Str;32 33  std::string Result = Str + "(MI";34  if (PCRel)35    Result += ", Address";36  if (MIOpNo != ~0U)37    Result += ", " + utostr(MIOpNo);38  if (PassSubtarget)39    Result += ", STI";40  Result += ", O";41  if (!MiModifier.empty())42    Result += ", \"" + MiModifier + '"';43  return Result + ");";44}45 46/// ParseAsmString - Parse the specified Instruction's AsmString into this47/// AsmWriterInst.48///49AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,50                             unsigned Variant)51    : CGI(&CGI), CGIIndex(CGIIndex) {52 53  // NOTE: Any extensions to this code need to be mirrored in the54  // AsmPrinter::printInlineAsm code that executes as compile time (assuming55  // that inline asm strings should also get the new feature)!56  std::string AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, Variant);57  std::string::size_type LastEmitted = 0;58  while (LastEmitted != AsmString.size()) {59    std::string::size_type DollarPos =60        AsmString.find_first_of("$\\", LastEmitted);61    if (DollarPos == std::string::npos)62      DollarPos = AsmString.size();63 64    // Emit a constant string fragment.65    if (DollarPos != LastEmitted) {66      for (; LastEmitted != DollarPos; ++LastEmitted)67        switch (AsmString[LastEmitted]) {68        case '\n':69          AddLiteralString("\\n");70          break;71        case '\t':72          AddLiteralString("\\t");73          break;74        case '"':75          AddLiteralString("\\\"");76          break;77        case '\\':78          AddLiteralString("\\\\");79          break;80        default:81          AddLiteralString(std::string(1, AsmString[LastEmitted]));82          break;83        }84    } else if (AsmString[DollarPos] == '\\') {85      if (DollarPos + 1 != AsmString.size()) {86        if (AsmString[DollarPos + 1] == 'n') {87          AddLiteralString("\\n");88        } else if (AsmString[DollarPos + 1] == 't') {89          AddLiteralString("\\t");90        } else if (std::string("${|}\\").find(AsmString[DollarPos + 1]) !=91                   std::string::npos) {92          AddLiteralString(std::string(1, AsmString[DollarPos + 1]));93        } else {94          PrintFatalError(95              CGI.TheDef->getLoc(),96              "Non-supported escaped character found in instruction '" +97                  CGI.getName() + "'!");98        }99        LastEmitted = DollarPos + 2;100        continue;101      }102    } else if (DollarPos + 1 != AsmString.size() &&103               AsmString[DollarPos + 1] == '$') {104      AddLiteralString("$"); // "$$" -> $105      LastEmitted = DollarPos + 2;106    } else {107      // Get the name of the variable.108      std::string::size_type VarEnd = DollarPos + 1;109 110      // handle ${foo}bar as $foo by detecting whether the character following111      // the dollar sign is a curly brace.  If so, advance VarEnd and DollarPos112      // so the variable name does not contain the leading curly brace.113      bool hasCurlyBraces = false;114      if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) {115        hasCurlyBraces = true;116        ++DollarPos;117        ++VarEnd;118      }119 120      while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))121        ++VarEnd;122      StringRef VarName(AsmString.data() + DollarPos + 1,123                        VarEnd - DollarPos - 1);124 125      // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed126      // into printOperand.  Also support ${:feature}, which is passed into127      // PrintSpecial.128      std::string Modifier;129 130      // In order to avoid starting the next string at the terminating curly131      // brace, advance the end position past it if we found an opening curly132      // brace.133      if (hasCurlyBraces) {134        if (VarEnd >= AsmString.size())135          PrintFatalError(136              CGI.TheDef->getLoc(),137              "Reached end of string before terminating curly brace in '" +138                  CGI.getName() + "'");139 140        // Look for a modifier string.141        if (AsmString[VarEnd] == ':') {142          ++VarEnd;143          if (VarEnd >= AsmString.size())144            PrintFatalError(145                CGI.TheDef->getLoc(),146                "Reached end of string before terminating curly brace in '" +147                    CGI.getName() + "'");148 149          std::string::size_type ModifierStart = VarEnd;150          while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))151            ++VarEnd;152          Modifier = AsmString.substr(ModifierStart, VarEnd - ModifierStart);153          if (Modifier.empty())154            PrintFatalError(CGI.TheDef->getLoc(),155                            "Bad operand modifier name in '" + CGI.getName() +156                                "'");157        }158 159        if (AsmString[VarEnd] != '}')160          PrintFatalError(161              CGI.TheDef->getLoc(),162              "Variable name beginning with '{' did not end with '}' in '" +163                  CGI.getName() + "'");164        ++VarEnd;165      }166      if (VarName.empty() && Modifier.empty())167        PrintFatalError(CGI.TheDef->getLoc(),168                        "Stray '$' in '" + CGI.getName() +169                            "' asm string, maybe you want $$?");170 171      if (VarName.empty()) {172        // Just a modifier, pass this into PrintSpecial.173        Operands.emplace_back("PrintSpecial", ~0U, Modifier);174      } else {175        // Otherwise, normal operand.176        unsigned OpNo = CGI.Operands.getOperandNamed(VarName);177        CGIOperandList::OperandInfo OpInfo = CGI.Operands[OpNo];178 179        unsigned MIOp = OpInfo.MIOperandNo;180        Operands.emplace_back(OpInfo.PrinterMethodName.str(), MIOp, Modifier,181                              AsmWriterOperand::isMachineInstrOperand,182                              OpInfo.OperandType == "MCOI::OPERAND_PCREL");183      }184      LastEmitted = VarEnd;185    }186  }187 188  Operands.emplace_back("return;", AsmWriterOperand::isLiteralStatementOperand);189}190 191/// MatchesAllButOneOp - If this instruction is exactly identical to the192/// specified instruction except for one differing operand, return the differing193/// operand number.  If more than one operand mismatches, return ~1, otherwise194/// if the instructions are identical return ~0.195unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other) const {196  if (Operands.size() != Other.Operands.size())197    return ~1;198 199  unsigned MismatchOperand = ~0U;200  for (unsigned i = 0, e = Operands.size(); i != e; ++i) {201    if (Operands[i] != Other.Operands[i]) {202      if (MismatchOperand != ~0U) // Already have one mismatch?203        return ~1U;204      MismatchOperand = i;205    }206  }207  return MismatchOperand;208}209