コード例 #1
0
ファイル: StringExtras.cpp プロジェクト: JerryEdensjr/swift
PartOfSpeech swift::getPartOfSpeech(StringRef word) {
  // FIXME: This implementation is woefully inefficient.
#define PREPOSITION(Word)                       \
  if (word.equals_lower(#Word))                 \
    return PartOfSpeech::Preposition;
#define VERB(Word)                              \
  if (word.equals_lower(#Word))                 \
    return PartOfSpeech::Verb;
#include "PartsOfSpeech.def"

  // Identify gerunds, which always end in "ing".
  if (word.endswith("ing") && word.size() > 4) {
    StringRef possibleVerb = word.substr(0, word.size()-3);

    // If what remains is a verb, we have a gerund.
    if (getPartOfSpeech(possibleVerb) == PartOfSpeech::Verb)
      return PartOfSpeech::Gerund;

    // Try adding an "e" and look for that as a verb.
    if (possibleVerb.back() != 'e') {
      SmallString<16> possibleVerbWithE;
      possibleVerbWithE += possibleVerb;
      possibleVerbWithE += 'e';
      if (getPartOfSpeech(possibleVerbWithE) == PartOfSpeech::Verb)
        return PartOfSpeech::Gerund;
    }

    // If there is a repeated letter at the back, drop that second
    // instance of that letter and try again.
    unsigned count = possibleVerb.size();
    if (possibleVerb[count-1] == possibleVerb[count-2] &&
        getPartOfSpeech(possibleVerb.substr(0, count-1)) == PartOfSpeech::Verb)
      return PartOfSpeech::Gerund;
  }

  // "auto" tends to be used as a verb prefix.
  if (startsWithIgnoreFirstCase(word, "auto") && word.size() > 4) {
    if (getPartOfSpeech(word.substr(4)) == PartOfSpeech::Verb)
      return PartOfSpeech::Verb;
  }

  // "re" can prefix a verb.
  if (startsWithIgnoreFirstCase(word, "re") && word.size() > 2) {
    if (getPartOfSpeech(word.substr(2)) == PartOfSpeech::Verb)
      return PartOfSpeech::Verb;
  }

  // "de" can prefix a verb.
  if (startsWithIgnoreFirstCase(word, "de") && word.size() > 2) {
    if (getPartOfSpeech(word.substr(2)) == PartOfSpeech::Verb)
      return PartOfSpeech::Verb;
  }

  return PartOfSpeech::Unknown;
}
コード例 #2
0
ファイル: ImportEnumInfo.cpp プロジェクト: 0x4d4746h/swift
/// Returns the common word-prefix of two strings, allowing the second string
/// to be a common English plural form of the first.
///
/// For example, given "NSProperty" and "NSProperties", the full "NSProperty"
/// is returned. Given "NSMagicArmor" and "NSMagicArmory", only
/// "NSMagic" is returned.
///
/// The "-s", "-es", and "-ies" patterns cover every plural NS_OPTIONS name
/// in Cocoa and Cocoa Touch.
///
/// \see getCommonWordPrefix
StringRef importer::getCommonPluralPrefix(StringRef singular,
                                          StringRef plural) {
  assert(!plural.empty());

  if (singular.empty())
    return singular;

  bool ignored;
  StringRef commonPrefix = getCommonWordPrefix(singular, plural, ignored);
  if (commonPrefix.size() == singular.size() || plural.back() != 's')
    return commonPrefix;

  StringRef leftover = singular.substr(commonPrefix.size());
  StringRef firstLeftoverWord = camel_case::getFirstWord(leftover);
  StringRef commonPrefixPlusWord =
      singular.substr(0, commonPrefix.size() + firstLeftoverWord.size());

  // Is the plural string just "[singular]s"?
  plural = plural.drop_back();
  if (plural.endswith(firstLeftoverWord))
    return commonPrefixPlusWord;

  if (plural.empty() || plural.back() != 'e')
    return commonPrefix;

  // Is the plural string "[singular]es"?
  plural = plural.drop_back();
  if (plural.endswith(firstLeftoverWord))
    return commonPrefixPlusWord;

  if (plural.empty() || !(plural.back() == 'i' && singular.back() == 'y'))
    return commonPrefix;

  // Is the plural string "[prefix]ies" and the singular "[prefix]y"?
  plural = plural.drop_back();
  firstLeftoverWord = firstLeftoverWord.drop_back();
  if (plural.endswith(firstLeftoverWord))
    return commonPrefixPlusWord;

  return commonPrefix;
}
コード例 #3
0
ファイル: AsmPrinterInlineAsm.cpp プロジェクト: CPFL/guc
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
void AsmPrinter::EmitInlineAsm(StringRef Str, unsigned LocCookie) const {
  assert(!Str.empty() && "Can't emit empty inline asm block");
  
  // Remember if the buffer is nul terminated or not so we can avoid a copy.
  bool isNullTerminated = Str.back() == 0;
  if (isNullTerminated)
    Str = Str.substr(0, Str.size()-1);
  
  // If the output streamer is actually a .s file, just emit the blob textually.
  // This is useful in case the asm parser doesn't handle something but the
  // system assembler does.
  if (OutStreamer.hasRawTextSupport()) {
    OutStreamer.EmitRawText(Str);
    return;
  }
  
  SourceMgr SrcMgr;
  
  // If the current LLVMContext has an inline asm handler, set it in SourceMgr.
  LLVMContext &LLVMCtx = MMI->getModule()->getContext();
  bool HasDiagHandler = false;
  if (void *DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler()) {
    SrcMgr.setDiagHandler((SourceMgr::DiagHandlerTy)(intptr_t)DiagHandler,
                          LLVMCtx.getInlineAsmDiagnosticContext(), LocCookie);
    HasDiagHandler = true;
  }
  
  MemoryBuffer *Buffer;
  if (isNullTerminated)
    Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>");
  else
    Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");

  // Tell SrcMgr about this buffer, it takes ownership of the buffer.
  SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
  
  OwningPtr<MCAsmParser> Parser(createMCAsmParser(TM.getTarget(), SrcMgr,
                                                  OutContext, OutStreamer,
                                                  *MAI));
  OwningPtr<TargetAsmParser> TAP(TM.getTarget().createAsmParser(*Parser, TM));
  if (!TAP)
    report_fatal_error("Inline asm not supported by this streamer because"
                       " we don't have an asm parser for this target\n");
  Parser->setTargetParser(*TAP.get());

  // Don't implicitly switch to the text section before the asm.
  int Res = Parser->Run(/*NoInitialTextSection*/ true,
                        /*NoFinalize*/ true);
  if (Res && !HasDiagHandler)
    report_fatal_error("Error parsing inline asm\n");
}
コード例 #4
0
ファイル: TypePrinter.cpp プロジェクト: nico/gong
void
TemplateSpecializationType::PrintTemplateArgumentList(
                                                raw_ostream &OS,
                                                const TemplateArgument *Args,
                                                unsigned NumArgs,
                                                  const PrintingPolicy &Policy,
                                                      bool SkipBrackets) {
  if (!SkipBrackets)
    OS << '<';
  
  bool needSpace = false;
  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
    if (Arg > 0)
      OS << ", ";
    
    // Print the argument into a string.
    SmallString<128> Buf;
    llvm::raw_svector_ostream ArgOS(Buf);
    if (Args[Arg].getKind() == TemplateArgument::Pack) {
      PrintTemplateArgumentList(ArgOS,
                                Args[Arg].pack_begin(), 
                                Args[Arg].pack_size(), 
                                Policy, true);
    } else {
      Args[Arg].print(Policy, ArgOS);
    }
    StringRef ArgString = ArgOS.str();

    // If this is the first argument and its string representation
    // begins with the global scope specifier ('::foo'), add a space
    // to avoid printing the diagraph '<:'.
    if (!Arg && !ArgString.empty() && ArgString[0] == ':')
      OS << ' ';

    OS << ArgString;

    needSpace = (!ArgString.empty() && ArgString.back() == '>');
  }

  // If the last character of our string is '>', add another space to
  // keep the two '>''s separate tokens. We don't *have* to do this in
  // C++0x, but it's still good hygiene.
  if (needSpace)
    OS << ' ';

  if (!SkipBrackets)
    OS << '>';
}
コード例 #5
0
size_t QueryRequest::get_indices(StringRef name, IndexVec* indices) {
  set_has_names_for_values(true);

  if (value_names_.get_indices(name, indices) == 0) {
    if (value_names_.size() > elements_count()) {
      // No more space left for new named values
      return 0;
    }
    if (name.size() > 0 && name.front() == '"' && name.back() == '"') {
      name = name.substr(1, name.size() - 2);
    }
    indices->push_back(value_names_.add(ValueName(name.to_string())));
  }

  return indices->size();
}
コード例 #6
0
// Replace .. embedded in path for purposes of having
// a canonical path.
static std::string replaceDotDot(StringRef Path) {
  SmallString<128> Buffer;
  llvm::sys::path::const_iterator B = llvm::sys::path::begin(Path),
    E = llvm::sys::path::end(Path);
  while (B != E) {
    if (B->compare(".") == 0) {
    }
    else if (B->compare("..") == 0)
      llvm::sys::path::remove_filename(Buffer);
    else
      llvm::sys::path::append(Buffer, *B);
    ++B;
  }
  if (Path.endswith("/") || Path.endswith("\\"))
    Buffer.append(1, Path.back());
  return Buffer.c_str();
}
コード例 #7
0
ファイル: Parser.cpp プロジェクト: dkk009/swift
/// Parse a stringified Swift declaration name, e.g. "init(frame:)".
StringRef swift::parseDeclName(StringRef name,
                               SmallVectorImpl<StringRef> &argumentLabels,
                               bool &isFunctionName) {
  if (name.empty()) return "";

  if (name.back() != ')') {
    isFunctionName = false;
    if (Lexer::isIdentifier(name) && name != "_")
      return name;

    return "";
  }

  isFunctionName = true;

  StringRef BaseName, Parameters;
  std::tie(BaseName, Parameters) = name.split('(');
  if (!Lexer::isIdentifier(BaseName) || BaseName == "_")
    return "";

  if (Parameters.empty())
    return "";
  Parameters = Parameters.drop_back(); // ')'

  if (Parameters.empty())
    return BaseName;

  if (Parameters.back() != ':')
    return "";

  do {
    StringRef NextParam;
    std::tie(NextParam, Parameters) = Parameters.split(':');

    if (!Lexer::isIdentifier(NextParam))
      return "";
    if (NextParam == "_")
      argumentLabels.push_back("");
    else
      argumentLabels.push_back(NextParam);
  } while (!Parameters.empty());

  return BaseName;
}
コード例 #8
0
ファイル: hash_table.hpp プロジェクト: Shauwe/cpp-driver
size_t CaseInsensitiveHashTable<T>::get_indices(StringRef name, IndexVec* result) const {
  result->clear();
  bool is_case_sensitive = false;

  if (name.size() > 0 && name.front() == '"' && name.back() == '"') {
    is_case_sensitive = true;
    name = name.substr(1, name.size() - 2);
  }

  size_t h = fnv1a_hash_lower(name) & index_mask_;

  size_t start = h;
  while (index_[h] != NULL && !iequals(name, index_[h]->name)) {
    h = (h + 1) & index_mask_;
    if (h == start) {
      return 0;
    }
  }

  const T* entry = index_[h];

  if (entry == NULL) {
    return 0;
  }

  if (!is_case_sensitive) {
    while (entry != NULL) {
      result->push_back(entry->index);
      entry = entry->next;
    }
  } else {
    while (entry != NULL) {
      if (name.equals(entry->name)) {
        result->push_back(entry->index);
      }
      entry = entry->next;
    }
  }

  return result->size();
}
コード例 #9
0
ファイル: StringExtras.cpp プロジェクト: 6008/swift
/// Skip a type suffix that can be dropped.
static Optional<StringRef> skipTypeSuffix(StringRef typeName) {
  if (typeName.empty()) return None;

  auto lastWord = camel_case::getLastWord(typeName);

  // "Type" suffix.
  if (lastWord == "Type" && typeName.size() > 4) {
    return typeName.drop_back(4);
  }

  // "Ref" suffix.
  if (lastWord == "Ref" && typeName.size() > 3) {
    return typeName.drop_back(3);
  }

  // "Mask" suffix.
  if (lastWord == "Mask" && typeName.size() > 4) {
    return typeName.drop_back(4);
  }

  // \d+D for dimensionality.
  if (typeName.back() == 'D' && typeName.size() > 1) {
    unsigned firstDigit = typeName.size() - 1;
    while (firstDigit > 0) {
      if (!isdigit(typeName[firstDigit-1])) break;
      --firstDigit;
    }

    if (firstDigit < typeName.size()-1) {
      return typeName.substr(0, firstDigit);
    }
  }

  // _t.
  if (typeName.size() > 2 && typeName.endswith("_t")) {
    return typeName.drop_back(2);
  }
  return None;
}
コード例 #10
0
static Expected<std::chrono::seconds> parseDuration(StringRef Duration) {
  if (Duration.empty())
    return make_error<StringError>("Duration must not be empty",
                                   inconvertibleErrorCode());

  StringRef NumStr = Duration.slice(0, Duration.size()-1);
  uint64_t Num;
  if (NumStr.getAsInteger(0, Num))
    return make_error<StringError>("'" + NumStr + "' not an integer",
                                   inconvertibleErrorCode());

  switch (Duration.back()) {
  case 's':
    return std::chrono::seconds(Num);
  case 'm':
    return std::chrono::minutes(Num);
  case 'h':
    return std::chrono::hours(Num);
  default:
    return make_error<StringError>("'" + Duration +
                                       "' must end with one of 's', 'm' or 'h'",
                                   inconvertibleErrorCode());
  }
}
コード例 #11
0
ファイル: Parser.cpp プロジェクト: randomstep/swift
ParsedDeclName swift::parseDeclName(StringRef name) {
  if (name.empty()) return ParsedDeclName();

  // Local function to handle the parsing of the base name + context.
  //
  // Returns true if an error occurred, without recording the base name.
  ParsedDeclName result;
  auto parseBaseName = [&](StringRef text) -> bool {
    // Split the text into context name and base name.
    StringRef contextName, baseName;
    std::tie(contextName, baseName) = text.rsplit('.');
    if (baseName.empty()) {
      baseName = contextName;
      contextName = StringRef();
    } else if (contextName.empty()) {
      return true;
    }

    auto isValidIdentifier = [](StringRef text) -> bool {
      return Lexer::isIdentifier(text) && text != "_";
    };

    // Make sure we have an identifier for the base name.
    if (!isValidIdentifier(baseName))
      return true;

    // If we have a context, make sure it is an identifier, or a series of
    // dot-separated identifiers.
    // FIXME: What about generic parameters?
    if (!contextName.empty()) {
      StringRef first;
      StringRef rest = contextName;
      do {
        std::tie(first, rest) = rest.split('.');
        if (!isValidIdentifier(first))
          return true;
      } while (!rest.empty());
    }

    // Record the results.
    result.ContextName = contextName;
    result.BaseName = baseName;
    return false;
  };

  // If this is not a function name, just parse the base name and
  // we're done.
  if (name.back() != ')') {
    if (Lexer::isOperator(name))
      result.BaseName = name;
    else if (parseBaseName(name))
      return ParsedDeclName();
    return result;
  }

  // We have a function name.
  result.IsFunctionName = true;

  // Split the base name from the parameters.
  StringRef baseName, parameters;
  std::tie(baseName, parameters) = name.split('(');
  if (parameters.empty()) return ParsedDeclName();

  // If the base name is prefixed by "getter:" or "setter:", it's an
  // accessor.
  if (baseName.startswith("getter:")) {
    result.IsGetter = true;
    result.IsFunctionName = false;
    baseName = baseName.substr(7);
  } else if (baseName.startswith("setter:")) {
    result.IsSetter = true;
    result.IsFunctionName = false;
    baseName = baseName.substr(7);
  }

  // Parse the base name.
  if (parseBaseName(baseName)) return ParsedDeclName();

  parameters = parameters.drop_back(); // ')'
  if (parameters.empty()) return result;

  if (parameters.back() != ':')
    return ParsedDeclName();

  bool isMember = !result.ContextName.empty();
  do {
    StringRef NextParam;
    std::tie(NextParam, parameters) = parameters.split(':');

    if (!Lexer::isIdentifier(NextParam))
      return ParsedDeclName();
    if (NextParam == "_") {
      result.ArgumentLabels.push_back("");
    } else if (isMember && NextParam == "self") {
      // For a member, "self" indicates the self parameter. There can
      // only be one such parameter.
      if (result.SelfIndex) return ParsedDeclName();
      result.SelfIndex = result.ArgumentLabels.size();
    } else {
      result.ArgumentLabels.push_back(NextParam);
    }
  } while (!parameters.empty());

  // Drop the argument labels for a property accessor; they aren't used.
  if (result.isPropertyAccessor())
    result.ArgumentLabels.clear();

  return result;
}
コード例 #12
0
ファイル: InitPreprocessor.cpp プロジェクト: OpenKimono/clang
static bool MacroBodyEndsInBackslash(StringRef MacroBody) {
  while (!MacroBody.empty() && isWhitespace(MacroBody.back()))
    MacroBody = MacroBody.drop_back();
  return !MacroBody.empty() && MacroBody.back() == '\\';
}
コード例 #13
0
ファイル: FileCheck.cpp プロジェクト: Persper/PTMC
bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
  PatternLoc = SMLoc::getFromPointer(PatternStr.data());

  // Ignore trailing whitespace.
  while (!PatternStr.empty() &&
         (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
    PatternStr = PatternStr.substr(0, PatternStr.size()-1);

  // Check that there is something on the line.
  if (PatternStr.empty()) {
    SM.PrintMessage(PatternLoc, "found empty check string with prefix '" +
                    CheckPrefix+":'", "error");
    return true;
  }

  // Check to see if this is a fixed string, or if it has regex pieces.
  if (PatternStr.size() < 2 ||
      (PatternStr.find("{{") == StringRef::npos &&
       PatternStr.find("[[") == StringRef::npos)) {
    FixedStr = PatternStr;
    return false;
  }

  // Paren value #0 is for the fully matched string.  Any new parenthesized
  // values add from their.
  unsigned CurParen = 1;

  // Otherwise, there is at least one regex piece.  Build up the regex pattern
  // by escaping scary characters in fixed strings, building up one big regex.
  while (!PatternStr.empty()) {
    // RegEx matches.
    if (PatternStr.size() >= 2 &&
        PatternStr[0] == '{' && PatternStr[1] == '{') {

      // Otherwise, this is the start of a regex match.  Scan for the }}.
      size_t End = PatternStr.find("}}");
      if (End == StringRef::npos) {
        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
                        "found start of regex string with no end '}}'", "error");
        return true;
      }

      if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM))
        return true;
      PatternStr = PatternStr.substr(End+2);
      continue;
    }

    // Named RegEx matches.  These are of two forms: [[foo:.*]] which matches .*
    // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
    // second form is [[foo]] which is a reference to foo.  The variable name
    // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
    // it.  This is to catch some common errors.
    if (PatternStr.size() >= 2 &&
        PatternStr[0] == '[' && PatternStr[1] == '[') {
      // Verify that it is terminated properly.
      size_t End = PatternStr.find("]]");
      if (End == StringRef::npos) {
        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
                        "invalid named regex reference, no ]] found", "error");
        return true;
      }

      StringRef MatchStr = PatternStr.substr(2, End-2);
      PatternStr = PatternStr.substr(End+2);

      // Get the regex name (e.g. "foo").
      size_t NameEnd = MatchStr.find(':');
      StringRef Name = MatchStr.substr(0, NameEnd);

      if (Name.empty()) {
        SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
                        "invalid name in named regex: empty name", "error");
        return true;
      }

      // Verify that the name is well formed.
      for (unsigned i = 0, e = Name.size(); i != e; ++i)
        if (Name[i] != '_' &&
            (Name[i] < 'a' || Name[i] > 'z') &&
            (Name[i] < 'A' || Name[i] > 'Z') &&
            (Name[i] < '0' || Name[i] > '9')) {
          SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i),
                          "invalid name in named regex", "error");
          return true;
        }

      // Name can't start with a digit.
      if (isdigit(Name[0])) {
        SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
                        "invalid name in named regex", "error");
        return true;
      }

      // Handle [[foo]].
      if (NameEnd == StringRef::npos) {
        VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
        continue;
      }

      // Handle [[foo:.*]].
      VariableDefs.push_back(std::make_pair(Name, CurParen));
      RegExStr += '(';
      ++CurParen;

      if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM))
        return true;

      RegExStr += ')';
    }

    // Handle fixed string matches.
    // Find the end, which is the start of the next regex.
    size_t FixedMatchEnd = PatternStr.find("{{");
    FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
    AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr);
    PatternStr = PatternStr.substr(FixedMatchEnd);
    continue;
  }

  return false;
}
コード例 #14
0
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode) const {
#ifndef ANDROID_TARGET_BUILD
  assert(!Str.empty() && "Can't emit empty inline asm block");

  // Remember if the buffer is nul terminated or not so we can avoid a copy.
  bool isNullTerminated = Str.back() == 0;
  if (isNullTerminated)
    Str = Str.substr(0, Str.size()-1);

  // If the output streamer is actually a .s file, just emit the blob textually.
  // This is useful in case the asm parser doesn't handle something but the
  // system assembler does.
  if (OutStreamer.hasRawTextSupport()) {
    OutStreamer.EmitRawText(Str);
    return;
  }

  SourceMgr SrcMgr;
  SrcMgrDiagInfo DiagInfo;

  // If the current LLVMContext has an inline asm handler, set it in SourceMgr.
  LLVMContext &LLVMCtx = MMI->getModule()->getContext();
  bool HasDiagHandler = false;
  if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) {
    // If the source manager has an issue, we arrange for SrcMgrDiagHandler
    // to be invoked, getting DiagInfo passed into it.
    DiagInfo.LocInfo = LocMDNode;
    DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
    DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
    SrcMgr.setDiagHandler(SrcMgrDiagHandler, &DiagInfo);
    HasDiagHandler = true;
  }

  MemoryBuffer *Buffer;
  if (isNullTerminated)
    Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>");
  else
    Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");

  // Tell SrcMgr about this buffer, it takes ownership of the buffer.
  SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());

  OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr,
                                                  OutContext, OutStreamer,
                                                  *MAI));

  // FIXME: It would be nice if we can avoid createing a new instance of
  // MCSubtargetInfo here given TargetSubtargetInfo is available. However,
  // we have to watch out for asm directives which can change subtarget
  // state. e.g. .code 16, .code 32.
  OwningPtr<MCSubtargetInfo>
    STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(),
                                             TM.getTargetCPU(),
                                             TM.getTargetFeatureString()));
  OwningPtr<MCTargetAsmParser>
    TAP(TM.getTarget().createMCAsmParser(*STI, *Parser));
  if (!TAP)
    report_fatal_error("Inline asm not supported by this streamer because"
                       " we don't have an asm parser for this target\n");
  Parser->setTargetParser(*TAP.get());

  // Don't implicitly switch to the text section before the asm.
  int Res = Parser->Run(/*NoInitialTextSection*/ true,
                        /*NoFinalize*/ true);
  if (Res && !HasDiagHandler)
    report_fatal_error("Error parsing inline asm\n");
#endif // ANDROID_TARGET_BUILD
}
コード例 #15
0
ファイル: COFFDumper.cpp プロジェクト: zhiyongLee/llvm
void COFFDumper::printCodeViewSection(const SectionRef &Section) {
  StringRef Data;
  error(Section.getContents(Data));

  SmallVector<StringRef, 10> FunctionNames;
  StringMap<StringRef> FunctionLineTables;

  ListScope D(W, "CodeViewDebugInfo");
  {
    // FIXME: Add more offset correctness checks.
    DataExtractor DE(Data, true, 4);
    uint32_t Offset = 0,
             Magic = DE.getU32(&Offset);
    W.printHex("Magic", Magic);
    if (Magic != COFF::DEBUG_SECTION_MAGIC) {
      error(object_error::parse_failed);
      return;
    }

    bool Finished = false;
    while (DE.isValidOffset(Offset) && !Finished) {
      // The section consists of a number of subsection in the following format:
      // |Type|PayloadSize|Payload...|
      uint32_t SubSectionType = DE.getU32(&Offset),
               PayloadSize = DE.getU32(&Offset);
      ListScope S(W, "Subsection");
      W.printHex("Type", SubSectionType);
      W.printHex("PayloadSize", PayloadSize);
      if (PayloadSize > Data.size() - Offset) {
        error(object_error::parse_failed);
        return;
      }

      StringRef Contents = Data.substr(Offset, PayloadSize);
      if (opts::CodeViewSubsectionBytes) {
        // Print the raw contents to simplify debugging if anything goes wrong
        // afterwards.
        W.printBinaryBlock("Contents", Contents);
      }

      switch (SubSectionType) {
      case COFF::DEBUG_SYMBOL_SUBSECTION:
        printCodeViewSymbolsSubsection(Contents, Section, Offset);
        break;
      case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
        // Holds a PC to file:line table.  Some data to parse this subsection is
        // stored in the other subsections, so just check sanity and store the
        // pointers for deferred processing.

        if (PayloadSize < 12) {
          // There should be at least three words to store two function
          // relocations and size of the code.
          error(object_error::parse_failed);
          return;
        }

        StringRef LinkageName;
        error(resolveSymbolName(Obj->getCOFFSection(Section), Offset,
                                LinkageName));
        W.printString("LinkageName", LinkageName);
        if (FunctionLineTables.count(LinkageName) != 0) {
          // Saw debug info for this function already?
          error(object_error::parse_failed);
          return;
        }

        FunctionLineTables[LinkageName] = Contents;
        FunctionNames.push_back(LinkageName);
        break;
      }
      case COFF::DEBUG_STRING_TABLE_SUBSECTION:
        if (PayloadSize == 0 || CVStringTable.data() != nullptr ||
            Contents.back() != '\0') {
          // Empty or duplicate or non-null-terminated subsection.
          error(object_error::parse_failed);
          return;
        }
        CVStringTable = Contents;
        break;
      case COFF::DEBUG_INDEX_SUBSECTION:
        // Holds the translation table from file indices
        // to offsets in the string table.

        if (PayloadSize == 0 ||
            CVFileIndexToStringOffsetTable.data() != nullptr) {
          // Empty or duplicate subsection.
          error(object_error::parse_failed);
          return;
        }
        CVFileIndexToStringOffsetTable = Contents;
        break;
      }
      Offset += PayloadSize;

      // Align the reading pointer by 4.
      Offset += (-Offset) % 4;
    }
  }

  // Dump the line tables now that we've read all the subsections and know all
  // the required information.
  for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) {
    StringRef Name = FunctionNames[I];
    ListScope S(W, "FunctionLineTable");
    W.printString("LinkageName", Name);

    DataExtractor DE(FunctionLineTables[Name], true, 4);
    uint32_t Offset = 6;  // Skip relocations.
    uint16_t Flags = DE.getU16(&Offset);
    W.printHex("Flags", Flags);
    bool HasColumnInformation =
        Flags & COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS;
    uint32_t FunctionSize = DE.getU32(&Offset);
    W.printHex("CodeSize", FunctionSize);
    while (DE.isValidOffset(Offset)) {
      // For each range of lines with the same filename, we have a segment
      // in the line table.  The filename string is accessed using double
      // indirection to the string table subsection using the index subsection.
      uint32_t OffsetInIndex = DE.getU32(&Offset),
               SegmentLength = DE.getU32(&Offset),
               FullSegmentSize = DE.getU32(&Offset);

      if (FullSegmentSize !=
          12 + 8 * SegmentLength +
              (HasColumnInformation ? 4 * SegmentLength : 0)) {
        error(object_error::parse_failed);
        return;
      }

      uint32_t FilenameOffset;
      {
        DataExtractor SDE(CVFileIndexToStringOffsetTable, true, 4);
        uint32_t OffsetInSDE = OffsetInIndex;
        if (!SDE.isValidOffset(OffsetInSDE)) {
          error(object_error::parse_failed);
          return;
        }
        FilenameOffset = SDE.getU32(&OffsetInSDE);
      }

      if (FilenameOffset == 0 || FilenameOffset + 1 >= CVStringTable.size() ||
          CVStringTable.data()[FilenameOffset - 1] != '\0') {
        // Each string in an F3 subsection should be preceded by a null
        // character.
        error(object_error::parse_failed);
        return;
      }

      StringRef Filename(CVStringTable.data() + FilenameOffset);
      ListScope S(W, "FilenameSegment");
      W.printString("Filename", Filename);
      for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
           ++J) {
        // Then go the (PC, LineNumber) pairs.  The line number is stored in the
        // least significant 31 bits of the respective word in the table.
        uint32_t PC = DE.getU32(&Offset),
                 LineNumber = DE.getU32(&Offset) & 0x7fffffff;
        if (PC >= FunctionSize) {
          error(object_error::parse_failed);
          return;
        }
        char Buffer[32];
        format("+0x%X", PC).snprint(Buffer, 32);
        W.printNumber(Buffer, LineNumber);
      }
      if (HasColumnInformation) {
        for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
             ++J) {
          uint16_t ColStart = DE.getU16(&Offset);
          W.printNumber("ColStart", ColStart);
          uint16_t ColEnd = DE.getU16(&Offset);
          W.printNumber("ColEnd", ColEnd);
        }
      }
    }
  }
}
コード例 #16
0
ファイル: FileCheck.cpp プロジェクト: agheorghiu/root
bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM,
                           unsigned LineNumber) {
  this->LineNumber = LineNumber;
  PatternLoc = SMLoc::getFromPointer(PatternStr.data());

  // Ignore trailing whitespace.
  while (!PatternStr.empty() &&
         (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
    PatternStr = PatternStr.substr(0, PatternStr.size()-1);

  // Check that there is something on the line.
  if (PatternStr.empty()) {
    SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
                    "found empty check string with prefix '" +
                    CheckPrefix+":'");
    return true;
  }

  // Check to see if this is a fixed string, or if it has regex pieces.
  if (PatternStr.size() < 2 ||
      (PatternStr.find("{{") == StringRef::npos &&
       PatternStr.find("[[") == StringRef::npos)) {
    FixedStr = PatternStr;
    return false;
  }

  // Paren value #0 is for the fully matched string.  Any new parenthesized
  // values add from there.
  unsigned CurParen = 1;

  // Otherwise, there is at least one regex piece.  Build up the regex pattern
  // by escaping scary characters in fixed strings, building up one big regex.
  while (!PatternStr.empty()) {
    // RegEx matches.
    if (PatternStr.startswith("{{")) {
      // This is the start of a regex match.  Scan for the }}.
      size_t End = PatternStr.find("}}");
      if (End == StringRef::npos) {
        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
                        SourceMgr::DK_Error,
                        "found start of regex string with no end '}}'");
        return true;
      }

      // Enclose {{}} patterns in parens just like [[]] even though we're not
      // capturing the result for any purpose.  This is required in case the
      // expression contains an alternation like: CHECK:  abc{{x|z}}def.  We
      // want this to turn into: "abc(x|z)def" not "abcx|zdef".
      RegExStr += '(';
      ++CurParen;

      if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM))
        return true;
      RegExStr += ')';

      PatternStr = PatternStr.substr(End+2);
      continue;
    }

    // Named RegEx matches.  These are of two forms: [[foo:.*]] which matches .*
    // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
    // second form is [[foo]] which is a reference to foo.  The variable name
    // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
    // it.  This is to catch some common errors.
    if (PatternStr.startswith("[[")) {
      // Find the closing bracket pair ending the match.  End is going to be an
      // offset relative to the beginning of the match string.
      size_t End = FindRegexVarEnd(PatternStr.substr(2));

      if (End == StringRef::npos) {
        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
                        SourceMgr::DK_Error,
                        "invalid named regex reference, no ]] found");
        return true;
      }

      StringRef MatchStr = PatternStr.substr(2, End);
      PatternStr = PatternStr.substr(End+4);

      // Get the regex name (e.g. "foo").
      size_t NameEnd = MatchStr.find(':');
      StringRef Name = MatchStr.substr(0, NameEnd);

      if (Name.empty()) {
        SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
                        "invalid name in named regex: empty name");
        return true;
      }

      // Verify that the name/expression is well formed. FileCheck currently
      // supports @LINE, @LINE+number, @LINE-number expressions. The check here
      // is relaxed, more strict check is performed in \c EvaluateExpression.
      bool IsExpression = false;
      for (unsigned i = 0, e = Name.size(); i != e; ++i) {
        if (i == 0 && Name[i] == '@') {
          if (NameEnd != StringRef::npos) {
            SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
                            SourceMgr::DK_Error,
                            "invalid name in named regex definition");
            return true;
          }
          IsExpression = true;
          continue;
        }
        if (Name[i] != '_' && !isalnum(Name[i]) &&
            (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) {
          SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i),
                          SourceMgr::DK_Error, "invalid name in named regex");
          return true;
        }
      }

      // Name can't start with a digit.
      if (isdigit(static_cast<unsigned char>(Name[0]))) {
        SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
                        "invalid name in named regex");
        return true;
      }

      // Handle [[foo]].
      if (NameEnd == StringRef::npos) {
        // Handle variables that were defined earlier on the same line by
        // emitting a backreference.
        if (VariableDefs.find(Name) != VariableDefs.end()) {
          unsigned VarParenNum = VariableDefs[Name];
          if (VarParenNum < 1 || VarParenNum > 9) {
            SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
                            SourceMgr::DK_Error,
                            "Can't back-reference more than 9 variables");
            return true;
          }
          AddBackrefToRegEx(VarParenNum);
        } else {
          VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
        }
        continue;
      }

      // Handle [[foo:.*]].
      VariableDefs[Name] = CurParen;
      RegExStr += '(';
      ++CurParen;

      if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM))
        return true;

      RegExStr += ')';
    }

    // Handle fixed string matches.
    // Find the end, which is the start of the next regex.
    size_t FixedMatchEnd = PatternStr.find("{{");
    FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
    AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr);
    PatternStr = PatternStr.substr(FixedMatchEnd);
  }

  return false;
}
コード例 #17
0
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
                               const MCTargetOptions &MCOptions,
                               const MDNode *LocMDNode,
                               InlineAsm::AsmDialect Dialect) const {
  assert(!Str.empty() && "Can't emit empty inline asm block");

  // Remember if the buffer is nul terminated or not so we can avoid a copy.
  bool isNullTerminated = Str.back() == 0;
  if (isNullTerminated)
    Str = Str.substr(0, Str.size()-1);

  // If the output streamer does not have mature MC support or the integrated
  // assembler has been disabled, just emit the blob textually.
  // Otherwise parse the asm and emit it via MC support.
  // This is useful in case the asm parser doesn't handle something but the
  // system assembler does.
  const MCAsmInfo *MCAI = TM.getMCAsmInfo();
  assert(MCAI && "No MCAsmInfo");
  if (!MCAI->useIntegratedAssembler() &&
      !OutStreamer->isIntegratedAssemblerRequired()) {
    emitInlineAsmStart();
    OutStreamer->EmitRawText(Str);
    emitInlineAsmEnd(STI, nullptr);
    return;
  }

  unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode);
  DiagInfo->SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths);

  std::unique_ptr<MCAsmParser> Parser(createMCAsmParser(
          DiagInfo->SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));

  // Do not use assembler-level information for parsing inline assembly.
  OutStreamer->setUseAssemblerInfoForParsing(false);

  // We create a new MCInstrInfo here since we might be at the module level
  // and not have a MachineFunction to initialize the TargetInstrInfo from and
  // we only need MCInstrInfo for asm parsing. We create one unconditionally
  // because it's not subtarget dependent.
  std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo());
  std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(
      STI, *Parser, *MII, MCOptions));
  if (!TAP)
    report_fatal_error("Inline asm not supported by this streamer because"
                       " we don't have an asm parser for this target\n");
  Parser->setAssemblerDialect(Dialect);
  Parser->setTargetParser(*TAP.get());
  // Enable lexing Masm binary and hex integer literals in intel inline
  // assembly.
  if (Dialect == InlineAsm::AD_Intel)
    Parser->getLexer().setLexMasmIntegers(true);

  emitInlineAsmStart();
  // Don't implicitly switch to the text section before the asm.
  int Res = Parser->Run(/*NoInitialTextSection*/ true,
                        /*NoFinalize*/ true);
  emitInlineAsmEnd(STI, &TAP->getSTI());

  if (Res && !DiagInfo->DiagHandler)
    report_fatal_error("Error parsing inline asm\n");
}
コード例 #18
0
ファイル: AsmPrinterInlineAsm.cpp プロジェクト: 8l/SPIRV-LLVM
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
                               const MCTargetOptions &MCOptions,
                               const MDNode *LocMDNode,
                               InlineAsm::AsmDialect Dialect) const {
  assert(!Str.empty() && "Can't emit empty inline asm block");

  // Remember if the buffer is nul terminated or not so we can avoid a copy.
  bool isNullTerminated = Str.back() == 0;
  if (isNullTerminated)
    Str = Str.substr(0, Str.size()-1);

  // If the output streamer does not have mature MC support or the integrated
  // assembler has been disabled, just emit the blob textually.
  // Otherwise parse the asm and emit it via MC support.
  // This is useful in case the asm parser doesn't handle something but the
  // system assembler does.
  const MCAsmInfo *MCAI = TM.getMCAsmInfo();
  assert(MCAI && "No MCAsmInfo");
  if (!MCAI->useIntegratedAssembler() &&
      !OutStreamer->isIntegratedAssemblerRequired()) {
    emitInlineAsmStart();
    OutStreamer->EmitRawText(Str);
    emitInlineAsmEnd(STI, nullptr);
    return;
  }

  SourceMgr SrcMgr;
  SrcMgrDiagInfo DiagInfo;

  // If the current LLVMContext has an inline asm handler, set it in SourceMgr.
  LLVMContext &LLVMCtx = MMI->getModule()->getContext();
  bool HasDiagHandler = false;
  if (LLVMCtx.getInlineAsmDiagnosticHandler() != nullptr) {
    // If the source manager has an issue, we arrange for srcMgrDiagHandler
    // to be invoked, getting DiagInfo passed into it.
    DiagInfo.LocInfo = LocMDNode;
    DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
    DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
    SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo);
    HasDiagHandler = true;
  }

  std::unique_ptr<MemoryBuffer> Buffer;
  if (isNullTerminated)
    Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>");
  else
    Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");

  // Tell SrcMgr about this buffer, it takes ownership of the buffer.
  SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());

  std::unique_ptr<MCAsmParser> Parser(
      createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI));

  // Create a temporary copy of the original STI because the parser may modify
  // it. For example, when switching between arm and thumb mode. If the target
  // needs to emit code to return to the original state it can do so in
  // emitInlineAsmEnd().
  MCSubtargetInfo TmpSTI = STI;

  // We create a new MCInstrInfo here since we might be at the module level
  // and not have a MachineFunction to initialize the TargetInstrInfo from and
  // we only need MCInstrInfo for asm parsing. We create one unconditionally
  // because it's not subtarget dependent.
  std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo());
  std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(
      TmpSTI, *Parser, *MII, MCOptions));
  if (!TAP)
    report_fatal_error("Inline asm not supported by this streamer because"
                       " we don't have an asm parser for this target\n");
  Parser->setAssemblerDialect(Dialect);
  Parser->setTargetParser(*TAP.get());
  if (MF) {
    const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
    TAP->SetFrameRegister(TRI->getFrameRegister(*MF));
  }

  emitInlineAsmStart();
  // Don't implicitly switch to the text section before the asm.
  int Res = Parser->Run(/*NoInitialTextSection*/ true,
                        /*NoFinalize*/ true);
  emitInlineAsmEnd(STI, &TmpSTI);
  if (Res && !HasDiagHandler)
    report_fatal_error("Error parsing inline asm\n");
}
コード例 #19
0
ファイル: AsmPrinterInlineAsm.cpp プロジェクト: 0mp/freebsd
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
                               const MCTargetOptions &MCOptions,
                               const MDNode *LocMDNode,
                               InlineAsm::AsmDialect Dialect) const {
  assert(!Str.empty() && "Can't emit empty inline asm block");

  // Remember if the buffer is nul terminated or not so we can avoid a copy.
  bool isNullTerminated = Str.back() == 0;
  if (isNullTerminated)
    Str = Str.substr(0, Str.size()-1);

  // If the output streamer does not have mature MC support or the integrated
  // assembler has been disabled, just emit the blob textually.
  // Otherwise parse the asm and emit it via MC support.
  // This is useful in case the asm parser doesn't handle something but the
  // system assembler does.
  const MCAsmInfo *MCAI = TM.getMCAsmInfo();
  assert(MCAI && "No MCAsmInfo");
  if (!MCAI->useIntegratedAssembler() &&
      !OutStreamer->isIntegratedAssemblerRequired()) {
    emitInlineAsmStart();
    OutStreamer->EmitRawText(Str);
    emitInlineAsmEnd(STI, nullptr);
    return;
  }

  if (!DiagInfo) {
    DiagInfo = make_unique<SrcMgrDiagInfo>();

    MCContext &Context = MMI->getContext();
    Context.setInlineSourceManager(&DiagInfo->SrcMgr);

    LLVMContext &LLVMCtx = MMI->getModule()->getContext();
    if (LLVMCtx.getInlineAsmDiagnosticHandler()) {
      DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
      DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
      DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get());
    }
  }

  SourceMgr &SrcMgr = DiagInfo->SrcMgr;
  SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths);

  std::unique_ptr<MemoryBuffer> Buffer;
  // The inline asm source manager will outlive Str, so make a copy of the
  // string for SourceMgr to own.
  Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");

  // Tell SrcMgr about this buffer, it takes ownership of the buffer.
  unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());

  // Store LocMDNode in DiagInfo, using BufNum as an identifier.
  if (LocMDNode) {
    DiagInfo->LocInfos.resize(BufNum);
    DiagInfo->LocInfos[BufNum-1] = LocMDNode;
  }

  std::unique_ptr<MCAsmParser> Parser(
      createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));

  // We create a new MCInstrInfo here since we might be at the module level
  // and not have a MachineFunction to initialize the TargetInstrInfo from and
  // we only need MCInstrInfo for asm parsing. We create one unconditionally
  // because it's not subtarget dependent.
  std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo());
  std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(
      STI, *Parser, *MII, MCOptions));
  if (!TAP)
    report_fatal_error("Inline asm not supported by this streamer because"
                       " we don't have an asm parser for this target\n");
  Parser->setAssemblerDialect(Dialect);
  Parser->setTargetParser(*TAP.get());
  Parser->setEnablePrintSchedInfo(EnablePrintSchedInfo);
  if (Dialect == InlineAsm::AD_Intel)
    // We need this flag to be able to parse numbers like "0bH"
    Parser->setParsingInlineAsm(true);
  if (MF) {
    const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
    TAP->SetFrameRegister(TRI->getFrameRegister(*MF));
  }

  emitInlineAsmStart();
  // Don't implicitly switch to the text section before the asm.
  int Res = Parser->Run(/*NoInitialTextSection*/ true,
                        /*NoFinalize*/ true);
  emitInlineAsmEnd(STI, &TAP->getSTI());

  if (Res && !DiagInfo->DiagHandler)
    report_fatal_error("Error parsing inline asm\n");
}
コード例 #20
0
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode,
                               InlineAsm::AsmDialect Dialect) const {
  assert(!Str.empty() && "Can't emit empty inline asm block");

  // Remember if the buffer is nul terminated or not so we can avoid a copy.
  bool isNullTerminated = Str.back() == 0;
  if (isNullTerminated)
    Str = Str.substr(0, Str.size()-1);

  // If the output streamer does not have mature MC support or the integrated
  // assembler has been disabled, just emit the blob textually.
  // Otherwise parse the asm and emit it via MC support.
  // This is useful in case the asm parser doesn't handle something but the
  // system assembler does.
  const MCAsmInfo *MCAI = TM.getMCAsmInfo();
  assert(MCAI && "No MCAsmInfo");
  if (!MCAI->useIntegratedAssembler() &&
      !OutStreamer.isIntegratedAssemblerRequired()) {
    emitInlineAsmStart(TM.getSubtarget<MCSubtargetInfo>());
    OutStreamer.EmitRawText(Str);
    emitInlineAsmEnd(TM.getSubtarget<MCSubtargetInfo>(), nullptr);
    return;
  }

  SourceMgr SrcMgr;
  SrcMgrDiagInfo DiagInfo;

  // If the current LLVMContext has an inline asm handler, set it in SourceMgr.
  LLVMContext &LLVMCtx = MMI->getModule()->getContext();
  bool HasDiagHandler = false;
  if (LLVMCtx.getInlineAsmDiagnosticHandler() != nullptr) {
    // If the source manager has an issue, we arrange for srcMgrDiagHandler
    // to be invoked, getting DiagInfo passed into it.
    DiagInfo.LocInfo = LocMDNode;
    DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
    DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
    SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo);
    HasDiagHandler = true;
  }

  std::unique_ptr<MemoryBuffer> Buffer;
  if (isNullTerminated)
    Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>");
  else
    Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");

  // Tell SrcMgr about this buffer, it takes ownership of the buffer.
  SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());

  std::unique_ptr<MCAsmParser> Parser(
      createMCAsmParser(SrcMgr, OutContext, OutStreamer, *MAI));

  // Initialize the parser with a fresh subtarget info. It is better to use a
  // new STI here because the parser may modify it and we do not want those
  // modifications to persist after parsing the inlineasm. The modifications
  // made by the parser will be seen by the code emitters because it passes
  // the current STI down to the EncodeInstruction() method.
  std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo(
      TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString()));

  // Preserve a copy of the original STI because the parser may modify it.  For
  // example, when switching between arm and thumb mode. If the target needs to
  // emit code to return to the original state it can do so in
  // emitInlineAsmEnd().
  MCSubtargetInfo STIOrig = *STI;

  MCTargetOptions MCOptions;
  if (MF)
    MCOptions = MF->getTarget().Options.MCOptions;
  std::unique_ptr<MCTargetAsmParser> TAP(
      TM.getTarget().createMCAsmParser(*STI, *Parser, *MII, MCOptions));
  if (!TAP)
    report_fatal_error("Inline asm not supported by this streamer because"
                       " we don't have an asm parser for this target\n");
  Parser->setAssemblerDialect(Dialect);
  Parser->setTargetParser(*TAP.get());
  if (MF) {
    const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
    TAP->SetFrameRegister(TRI->getFrameRegister(*MF));
  }

  emitInlineAsmStart(STIOrig);
  // Don't implicitly switch to the text section before the asm.
  int Res = Parser->Run(/*NoInitialTextSection*/ true,
                        /*NoFinalize*/ true);
  emitInlineAsmEnd(STIOrig, STI.get());
  if (Res && !HasDiagHandler)
    report_fatal_error("Error parsing inline asm\n");
}
コード例 #21
0
/// StripSpaces - This removes leading and trailing spaces from the StringRef.
static void StripSpaces(StringRef &Str) {
  while (!Str.empty() && isspace(Str[0]))
    Str = Str.substr(1);
  while (!Str.empty() && isspace(Str.back()))
    Str = Str.substr(0, Str.size()-1);
}