Ejemplo n.º 1
0
/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
/// memory buffer, free it, and return a new one.
static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
  SmallString<128> NewFile;
  NewFile.reserve(MB->getBufferSize());

  for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
       Ptr != End; ++Ptr) {
    // If C is not a horizontal whitespace, skip it.
    if (*Ptr != ' ' && *Ptr != '\t') {
      NewFile.push_back(*Ptr);
      continue;
    }

    // Otherwise, add one space and advance over neighboring space.
    NewFile.push_back(' ');
    while (Ptr+1 != End &&
           (Ptr[1] == ' ' || Ptr[1] == '\t'))
      ++Ptr;
  }

  // Free the old buffer and return a new one.
  MemoryBuffer *MB2 =
    MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier());

  delete MB;
  return MB2;
}
Ejemplo n.º 2
0
/// Canonicalize whitespaces in the input file. Line endings are replaced
/// with UNIX-style '\n'.
///
/// \param PreserveHorizontal Don't squash consecutive horizontal whitespace
/// characters to a single space.
static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB,
                                           bool PreserveHorizontal) {
  SmallString<128> NewFile;
  NewFile.reserve(MB->getBufferSize());

  for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
       Ptr != End; ++Ptr) {
    // Eliminate trailing dosish \r.
    if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
      continue;
    }

    // If current char is not a horizontal whitespace or if horizontal 
    // whitespace canonicalization is disabled, dump it to output as is.
    if (PreserveHorizontal || (*Ptr != ' ' && *Ptr != '\t')) {
      NewFile.push_back(*Ptr);
      continue;
    }

    // Otherwise, add one space and advance over neighboring space.
    NewFile.push_back(' ');
    while (Ptr+1 != End &&
           (Ptr[1] == ' ' || Ptr[1] == '\t'))
      ++Ptr;
  }

  // Free the old buffer and return a new one.
  MemoryBuffer *MB2 =
    MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier());

  delete MB;
  return MB2;
}
Ejemplo n.º 3
0
/// \brief Find the end of the word starting at the given offset
/// within a string.
///
/// \returns the index pointing one character past the end of the
/// word.
static unsigned findEndOfWord(unsigned Start, StringRef Str,
                              unsigned Length, unsigned Column,
                              unsigned Columns) {
  assert(Start < Str.size() && "Invalid start position!");
  unsigned End = Start + 1;

  // If we are already at the end of the string, take that as the word.
  if (End == Str.size())
    return End;

  // Determine if the start of the string is actually opening
  // punctuation, e.g., a quote or parentheses.
  char EndPunct = findMatchingPunctuation(Str[Start]);
  if (!EndPunct) {
    // This is a normal word. Just find the first space character.
    while (End < Length && !isspace(Str[End]))
      ++End;
    return End;
  }

  // We have the start of a balanced punctuation sequence (quotes,
  // parentheses, etc.). Determine the full sequence is.
  SmallString<16> PunctuationEndStack;
  PunctuationEndStack.push_back(EndPunct);
  while (End < Length && !PunctuationEndStack.empty()) {
    if (Str[End] == PunctuationEndStack.back())
      PunctuationEndStack.pop_back();
    else if (char SubEndPunct = findMatchingPunctuation(Str[End]))
      PunctuationEndStack.push_back(SubEndPunct);

    ++End;
  }

  // Find the first space character after the punctuation ended.
  while (End < Length && !isspace(Str[End]))
    ++End;

  unsigned PunctWordLength = End - Start;
  if (// If the word fits on this line
      Column + PunctWordLength <= Columns ||
      // ... or the word is "short enough" to take up the next line
      // without too much ugly white space
      PunctWordLength < Columns/3)
    return End; // Take the whole thing as a single "word".

  // The whole quoted/parenthesized string is too long to print as a
  // single "word". Instead, find the "word" that starts just after
  // the punctuation and use that end-point instead. This will recurse
  // until it finds something small enough to consider a word.
  return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
}
Ejemplo n.º 4
0
const MCSectionMachO *MCContext::
getMachOSection(StringRef Segment, StringRef Section,
                unsigned TypeAndAttributes,
                unsigned Reserved2, SectionKind Kind) {

  // We unique sections by their segment/section pair.  The returned section
  // may not have the same flags as the requested section, if so this should be
  // diagnosed by the client as an error.

  // Create the map if it doesn't already exist.
  if (MachOUniquingMap == 0)
    MachOUniquingMap = new MachOUniqueMapTy();
  MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)MachOUniquingMap;

  // Form the name to look up.
  SmallString<64> Name;
  Name += Segment;
  Name.push_back(',');
  Name += Section;

  // Do the lookup, if we have a hit, return it.
  const MCSectionMachO *&Entry = Map[Name.str()];
  if (Entry) return Entry;

  // Otherwise, return a new section.
  return Entry = new (*this) MCSectionMachO(Segment, Section, TypeAndAttributes,
                                            Reserved2, Kind);
}
Ejemplo n.º 5
0
/// Construct initial function attributes from options.
void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs) {
  // Add DisableFPElim. 
  if (!IRGen.Opts.DisableFPElim) {
    Attrs.addAttribute("no-frame-pointer-elim", "false");
  } else {
    Attrs.addAttribute("no-frame-pointer-elim", "true");
    Attrs.addAttribute("no-frame-pointer-elim-non-leaf");
  }

  // Add target-cpu and target-features if they are non-null.
  auto *Clang = static_cast<ClangImporter *>(Context.getClangModuleLoader());
  clang::TargetOptions &ClangOpts = Clang->getTargetInfo().getTargetOpts();

  std::string &CPU = ClangOpts.CPU;
  if (CPU != "")
    Attrs.addAttribute("target-cpu", CPU);

  std::vector<std::string> Features = ClangOpts.Features;
  if (!Features.empty()) {
    SmallString<64> allFeatures;
    // Sort so that the target features string is canonical.
    std::sort(Features.begin(), Features.end());
    interleave(Features, [&](const std::string &s) {
      allFeatures.append(s);
    }, [&]{
      allFeatures.push_back(',');
    });
    Attrs.addAttribute("target-features", allFeatures);
  }
  if (IRGen.Opts.OptimizeForSize)
    Attrs.addAttribute(llvm::Attribute::OptimizeForSize);
}
static MCSectionWasm *selectWasmSectionForGlobal(
    MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
    const TargetMachine &TM, bool EmitUniqueSection, unsigned *NextUniqueID) {
  StringRef Group = "";
  checkWasmComdat(GO);

  bool UniqueSectionNames = TM.getUniqueSectionNames();
  SmallString<128> Name = getSectionPrefixForGlobal(Kind);

  if (const auto *F = dyn_cast<Function>(GO)) {
    const auto &OptionalPrefix = F->getSectionPrefix();
    if (OptionalPrefix)
      Name += *OptionalPrefix;
  }

  if (EmitUniqueSection && UniqueSectionNames) {
    Name.push_back('.');
    TM.getNameWithPrefix(Name, GO, Mang, true);
  }
  unsigned UniqueID = MCContext::GenericSectionID;
  if (EmitUniqueSection && !UniqueSectionNames) {
    UniqueID = *NextUniqueID;
    (*NextUniqueID)++;
  }
  return Ctx.getWasmSection(Name, Kind, Group, UniqueID);
}
Ejemplo n.º 7
0
static MCSectionWasm *selectWasmSectionForGlobal(
    MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
    const TargetMachine &TM, bool EmitUniqueSection, unsigned *NextUniqueID) {
  StringRef Group = "";
  if (getWasmComdat(GO))
    llvm_unreachable("comdat not yet supported for wasm");

  bool UniqueSectionNames = TM.getUniqueSectionNames();
  SmallString<128> Name = getSectionPrefixForGlobal(Kind);

  uint32_t Type = wasm::WASM_SEC_DATA;
  if (const auto *F = dyn_cast<Function>(GO)) {
    const auto &OptionalPrefix = F->getSectionPrefix();
    if (OptionalPrefix)
      Name += *OptionalPrefix;
    Type = wasm::WASM_SEC_CODE;
  }

  if (EmitUniqueSection && UniqueSectionNames) {
    Name.push_back('.');
    TM.getNameWithPrefix(Name, GO, Mang, true);
  }
  unsigned UniqueID = MCContext::GenericSectionID;
  if (EmitUniqueSection && !UniqueSectionNames) {
    UniqueID = *NextUniqueID;
    (*NextUniqueID)++;
  }
  return Ctx.getWasmSection(Name, Type, Group, UniqueID);
}
Ejemplo n.º 8
0
MCSectionMachO *MCContext::getMachOSection(StringRef Segment, StringRef Section,
                                           unsigned TypeAndAttributes,
                                           unsigned Reserved2, SectionKind Kind,
                                           const char *BeginSymName) {

  // We unique sections by their segment/section pair.  The returned section
  // may not have the same flags as the requested section, if so this should be
  // diagnosed by the client as an error.

  // Form the name to look up.
  SmallString<64> Name;
  Name += Segment;
  Name.push_back(',');
  Name += Section;

  // Do the lookup, if we have a hit, return it.
  MCSectionMachO *&Entry = MachOUniquingMap[Name];
  if (Entry)
    return Entry;

  MCSymbol *Begin = nullptr;
  if (BeginSymName)
    Begin = createTempSymbol(BeginSymName, false);

  // Otherwise, return a new section.
  return Entry = new (MachOAllocator.Allocate()) MCSectionMachO(
             Segment, Section, TypeAndAttributes, Reserved2, Kind, Begin);
}
Ejemplo n.º 9
0
/// Turn a sequence of our tokens back into a string that we can hand
/// to the MC asm parser.
static bool buildMSAsmString(Preprocessor &PP, SourceLocation AsmLoc,
                             ArrayRef<Token> AsmToks,
                             SmallVectorImpl<unsigned> &TokOffsets,
                             SmallString<512> &Asm) {
  assert(!AsmToks.empty() && "Didn't expect an empty AsmToks!");

  // Is this the start of a new assembly statement?
  bool isNewStatement = true;

  for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
    const Token &Tok = AsmToks[i];

    // Start each new statement with a newline and a tab.
    if (!isNewStatement && (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) {
      Asm += "\n\t";
      isNewStatement = true;
    }

    // Preserve the existence of leading whitespace except at the
    // start of a statement.
    if (!isNewStatement && Tok.hasLeadingSpace())
      Asm += ' ';

    // Remember the offset of this token.
    TokOffsets.push_back(Asm.size());

    // Don't actually write '__asm' into the assembly stream.
    if (Tok.is(tok::kw_asm)) {
      // Complain about __asm at the end of the stream.
      if (i + 1 == e) {
        PP.Diag(AsmLoc, diag::err_asm_empty);
        return true;
      }

      continue;
    }

    // Append the spelling of the token.
    SmallString<32> SpellingBuffer;
    bool SpellingInvalid = false;
    Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid);
    assert(!SpellingInvalid && "spelling was invalid after correct parse?");

    // We are no longer at the start of a statement.
    isNewStatement = false;
  }

  // Ensure that the buffer is null-terminated.
  Asm.push_back('\0');
  Asm.pop_back();

  assert(TokOffsets.size() == AsmToks.size());
  return false;
}
Ejemplo n.º 10
0
void XCTMigrator::migrateInclude(llvm::StringRef Filename,
                                 CharSourceRange FilenameRange,
                                 SourceLocation HashLoc, bool isAngled) {
  StringRef Parent = "SenTestingKit/";
  if (!Filename.startswith(Parent))
    return;
  if (isFromSenTestInclude(HashLoc))
    return;

  edit::Commit commit(Editor);
  StringRef HeaderName = Filename.substr(Parent.size());
  llvm::StringMap<llvm::StringRef>::iterator I = IncludesMap.find(HeaderName);
  if (I == IncludesMap.end() || I->second.empty()) {
    commit.remove(CharSourceRange::getCharRange(HashLoc,FilenameRange.getEnd()));
  } else {
    SmallString<128> NewInclude;
    NewInclude.push_back(isAngled ? '<' : '"');
    NewInclude += "XCTest/";
    NewInclude += I->second;
    NewInclude.push_back(isAngled ? '>' : '"');
    commit.replace(FilenameRange, NewInclude.str());
  }
  Editor.commit(commit);
}
Ejemplo n.º 11
0
/// StructTag - generate the name of the struct tag for a type.
/// These names are mandated by ARM's ABI.
static std::string StructTag(StringRef typestr) {
  bool quad = false;
  bool poly = false;
  bool usgn = false;
  
  // base type to get the type string for.
  char type = ClassifyType(typestr, quad, poly, usgn);
  
  SmallString<128> s;
  s += "__simd";
  s += quad ? "128_" : "64_";
  if (usgn)
    s.push_back('u');
  
  switch (type) {
    case 'c':
      s += poly ? "poly8" : "int8";
      break;
    case 's':
      s += poly ? "poly16" : "int16";
      break;
    case 'i':
      s += "int32";
      break;
    case 'l':
      s += "int64";
      break;
    case 'h':
      s += "float16";
      break;
    case 'f':
      s += "float32";
      break;
    default:
      throw "unhandled type!";
      break;
  }

  // Append _t, finishing the struct tag name.
  s += "_t";
  
  return s.str();
}
Ejemplo n.º 12
0
/// @brief Find program using shell lookup rules.
/// @param Program This is either an absolute path, relative path, or simple a
///        program name. Look in PATH for any programs that match. If no
///        extension is present, try all extensions in PATHEXT.
/// @return If ec == errc::success, The absolute path to the program. Otherwise
///         the return value is undefined.
static std::string FindProgram(const std::string &Program,
                               std::error_code &ec) {
  char PathName[MAX_PATH + 1];
  typedef SmallVector<StringRef, 12> pathext_t;
  pathext_t pathext;
  // Check for the program without an extension (in case it already has one).
  pathext.push_back("");
  SplitString(std::getenv("PATHEXT"), pathext, ";");

  for (pathext_t::iterator i = pathext.begin(), e = pathext.end(); i != e; ++i){
    SmallString<5> ext;
    for (std::size_t ii = 0, e = i->size(); ii != e; ++ii)
      ext.push_back(::tolower((*i)[ii]));
    LPCSTR Extension = NULL;
    if (ext.size() && ext[0] == '.')
      Extension = ext.c_str();
    DWORD length = ::SearchPathA(NULL,
                                 Program.c_str(),
                                 Extension,
                                 array_lengthof(PathName),
                                 PathName,
                                 NULL);
    if (length == 0)
      ec = windows_error(::GetLastError());
    else if (length > array_lengthof(PathName)) {
      // This may have been the file, return with error.
      ec = windows_error(ERROR_BUFFER_OVERFLOW);
      break;
    } else {
      // We found the path! Return it.
      ec = std::error_code();
      break;
    }
  }

  // Make sure PathName is valid.
  PathName[MAX_PATH] = 0;
  return PathName;
}
Ejemplo n.º 13
0
/// Construct initial attributes from options.
llvm::AttributeSet IRGenModule::constructInitialAttributes() {
  llvm::AttributeSet attrsUpdated;
  // Add DisableFPElim. 
  if (!Opts.DisableFPElim) {
    attrsUpdated = attrsUpdated.addAttribute(LLVMContext,
                     llvm::AttributeSet::FunctionIndex,
                     "no-frame-pointer-elim", "false");
  } else {
    attrsUpdated = attrsUpdated.addAttribute(
        LLVMContext, llvm::AttributeSet::FunctionIndex,
        "no-frame-pointer-elim", "true");
    attrsUpdated = attrsUpdated.addAttribute(
        LLVMContext, llvm::AttributeSet::FunctionIndex,
        "no-frame-pointer-elim-non-leaf");
  }

  // Add target-cpu and target-features if they are non-null.
  auto *Clang = static_cast<ClangImporter *>(Context.getClangModuleLoader());
  clang::TargetOptions &ClangOpts = Clang->getTargetInfo().getTargetOpts();

  std::string &CPU = ClangOpts.CPU;
  if (CPU != "")
    attrsUpdated = attrsUpdated.addAttribute(LLVMContext,
                     llvm::AttributeSet::FunctionIndex, "target-cpu", CPU);

  std::vector<std::string> &Features = ClangOpts.Features;
  if (!Features.empty()) {
    SmallString<64> allFeatures;
    interleave(Features, [&](const std::string &s) {
      allFeatures.append(s);
    }, [&]{
      allFeatures.push_back(',');
    });
    attrsUpdated = attrsUpdated.addAttribute(LLVMContext,
                     llvm::AttributeSet::FunctionIndex, "target-features",
                     allFeatures);
  }
  return attrsUpdated;
}
Ejemplo n.º 14
0
void clang_codeCompleteAt_Impl(void *UserData) {
  CodeCompleteAtInfo *CCAI = static_cast<CodeCompleteAtInfo*>(UserData);
  CXTranslationUnit TU = CCAI->TU;
  const char *complete_filename = CCAI->complete_filename;
  unsigned complete_line = CCAI->complete_line;
  unsigned complete_column = CCAI->complete_column;
  struct CXUnsavedFile *unsaved_files = CCAI->unsaved_files;
  unsigned num_unsaved_files = CCAI->num_unsaved_files;
  unsigned options = CCAI->options;
  bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments;
  CCAI->result = 0;

#ifdef UDP_CODE_COMPLETION_LOGGER
#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
  const llvm::TimeRecord &StartTime =  llvm::TimeRecord::getCurrentTime();
#endif
#endif

  bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != 0;

  if (cxtu::isNotUsableTU(TU)) {
    LOG_BAD_TU(TU);
    return;
  }

  ASTUnit *AST = cxtu::getASTUnit(TU);
  if (!AST)
    return;

  CIndexer *CXXIdx = TU->CIdx;
  if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
    setThreadBackgroundPriority();

  ASTUnit::ConcurrencyCheck Check(*AST);

  // Perform the remapping of source files.
  SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
  for (unsigned I = 0; I != num_unsaved_files; ++I) {
    StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
    const llvm::MemoryBuffer *Buffer
      = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
    RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
                                           Buffer));
  }
  
  if (EnableLogging) {
    // FIXME: Add logging.
  }

  // Parse the resulting source file to find code-completion results.
  AllocatedCXCodeCompleteResults *Results = 
        new AllocatedCXCodeCompleteResults(AST->getFileSystemOpts());
  Results->Results = 0;
  Results->NumResults = 0;
  
  // Create a code-completion consumer to capture the results.
  CodeCompleteOptions Opts;
  Opts.IncludeBriefComments = IncludeBriefComments;
  CaptureCompletionResults Capture(Opts, *Results, &TU);

  // Perform completion.
  AST->CodeComplete(complete_filename, complete_line, complete_column,
                    RemappedFiles,
                    (options & CXCodeComplete_IncludeMacros),
                    (options & CXCodeComplete_IncludeCodePatterns),
                    IncludeBriefComments,
                    Capture,
                    *Results->Diag, Results->LangOpts, *Results->SourceMgr,
                    *Results->FileMgr, Results->Diagnostics,
                    Results->TemporaryBuffers);
  
  // Keep a reference to the allocator used for cached global completions, so
  // that we can be sure that the memory used by our code completion strings
  // doesn't get freed due to subsequent reparses (while the code completion
  // results are still active).
  Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator();

  

#ifdef UDP_CODE_COMPLETION_LOGGER
#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
  const llvm::TimeRecord &EndTime =  llvm::TimeRecord::getCurrentTime();
  SmallString<256> LogResult;
  llvm::raw_svector_ostream os(LogResult);

  // Figure out the language and whether or not it uses PCH.
  const char *lang = 0;
  bool usesPCH = false;

  for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
       I != E; ++I) {
    if (*I == 0)
      continue;
    if (strcmp(*I, "-x") == 0) {
      if (I + 1 != E) {
        lang = *(++I);
        continue;
      }
    }
    else if (strcmp(*I, "-include") == 0) {
      if (I+1 != E) {
        const char *arg = *(++I);
        SmallString<512> pchName;
        {
          llvm::raw_svector_ostream os(pchName);
          os << arg << ".pth";
        }
        pchName.push_back('\0');
        struct stat stat_results;
        if (stat(pchName.str().c_str(), &stat_results) == 0)
          usesPCH = true;
        continue;
      }
    }
  }

  os << "{ ";
  os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
  os << ", \"numRes\": " << Results->NumResults;
  os << ", \"diags\": " << Results->Diagnostics.size();
  os << ", \"pch\": " << (usesPCH ? "true" : "false");
  os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
  const char *name = getlogin();
  os << ", \"user\": \"" << (name ? name : "unknown") << '"';
  os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
  os << " }";

  StringRef res = os.str();
  if (res.size() > 0) {
    do {
      // Setup the UDP socket.
      struct sockaddr_in servaddr;
      bzero(&servaddr, sizeof(servaddr));
      servaddr.sin_family = AF_INET;
      servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
      if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
                    &servaddr.sin_addr) <= 0)
        break;

      int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
      if (sockfd < 0)
        break;

      sendto(sockfd, res.data(), res.size(), 0,
             (struct sockaddr *)&servaddr, sizeof(servaddr));
      close(sockfd);
    }
    while (false);
  }
#endif
#endif
  CCAI->result = Results;
}
Ejemplo n.º 15
0
static LoadResult
parseDependencyFile(llvm::MemoryBuffer &buffer,
                    llvm::function_ref<DependencyCallbackTy> providesCallback,
                    llvm::function_ref<DependencyCallbackTy> dependsCallback,
                    llvm::function_ref<InterfaceHashCallbackTy> interfaceHashCallback) {
  namespace yaml = llvm::yaml;

  // FIXME: Switch to a format other than YAML.
  llvm::SourceMgr SM;
  yaml::Stream stream(buffer.getMemBufferRef(), SM);
  auto I = stream.begin();
  if (I == stream.end() || !I->getRoot())
    return LoadResult::HadError;

  auto *topLevelMap = dyn_cast<yaml::MappingNode>(I->getRoot());
  if (!topLevelMap) {
    if (isa<yaml::NullNode>(I->getRoot()))
      return LoadResult::UpToDate;
    return LoadResult::HadError;
  }

  LoadResult result = LoadResult::UpToDate;
  SmallString<64> scratch;

  // After an entry, we know more about the node as a whole.
  // Update the "result" variable above.
  // This is a macro rather than a lambda because it contains a return.
#define UPDATE_RESULT(update) switch (update) {\
    case LoadResult::HadError: \
      return LoadResult::HadError; \
    case LoadResult::UpToDate: \
      break; \
    case LoadResult::AffectsDownstream: \
      result = LoadResult::AffectsDownstream; \
      break; \
    } \

  // FIXME: LLVM's YAML support does incremental parsing in such a way that
  // for-range loops break.
  for (auto i = topLevelMap->begin(), e = topLevelMap->end(); i != e; ++i) {
    if (isa<yaml::NullNode>(i->getValue()))
      continue;

    auto *key = dyn_cast<yaml::ScalarNode>(i->getKey());
    if (!key)
      return LoadResult::HadError;
    StringRef keyString = key->getValue(scratch);

    using namespace reference_dependency_keys;

    if (keyString == interfaceHash) {
      auto *value = dyn_cast<yaml::ScalarNode>(i->getValue());
      if (!value)
        return LoadResult::HadError;

      StringRef valueString = value->getValue(scratch);
      UPDATE_RESULT(interfaceHashCallback(valueString));

    } else {
      enum class DependencyDirection : bool {
        Depends,
        Provides
      };
      using KindPair = std::pair<DependencyKind, DependencyDirection>;

      KindPair dirAndKind = llvm::StringSwitch<KindPair>(key->getValue(scratch))
        .Case(dependsTopLevel,
              std::make_pair(DependencyKind::TopLevelName,
                             DependencyDirection::Depends))
        .Case(dependsNominal,
              std::make_pair(DependencyKind::NominalType,
                             DependencyDirection::Depends))
        .Case(dependsMember,
              std::make_pair(DependencyKind::NominalTypeMember,
                             DependencyDirection::Depends))
        .Case(dependsDynamicLookup,
              std::make_pair(DependencyKind::DynamicLookupName,
                             DependencyDirection::Depends))
        .Case(dependsExternal,
              std::make_pair(DependencyKind::ExternalFile,
                             DependencyDirection::Depends))
        .Case(providesTopLevel,
              std::make_pair(DependencyKind::TopLevelName,
                             DependencyDirection::Provides))
        .Case(providesNominal,
              std::make_pair(DependencyKind::NominalType,
                             DependencyDirection::Provides))
        .Case(providesMember,
              std::make_pair(DependencyKind::NominalTypeMember,
                             DependencyDirection::Provides))
        .Case(providesDynamicLookup,
              std::make_pair(DependencyKind::DynamicLookupName,
                             DependencyDirection::Provides))
        .Default(std::make_pair(DependencyKind(),
                                DependencyDirection::Depends));
      if (dirAndKind.first == DependencyKind())
        return LoadResult::HadError;

      auto *entries = dyn_cast<yaml::SequenceNode>(i->getValue());
      if (!entries)
        return LoadResult::HadError;

      if (dirAndKind.first == DependencyKind::NominalTypeMember) {
        // Handle member dependencies specially. Rather than being a single
        // string, they come in the form ["{MangledBaseName}", "memberName"].
        for (yaml::Node &rawEntry : *entries) {
          bool isCascading = rawEntry.getRawTag() != "!private";

          auto *entry = dyn_cast<yaml::SequenceNode>(&rawEntry);
          if (!entry)
            return LoadResult::HadError;

          auto iter = entry->begin();
          auto *base = dyn_cast<yaml::ScalarNode>(&*iter);
          if (!base)
            return LoadResult::HadError;
          ++iter;

          auto *member = dyn_cast<yaml::ScalarNode>(&*iter);
          if (!member)
            return LoadResult::HadError;
          ++iter;

          // FIXME: LLVM's YAML support doesn't implement == correctly for end
          // iterators.
          assert(!(iter != entry->end()));

          bool isDepends = dirAndKind.second == DependencyDirection::Depends;
          auto &callback = isDepends ? dependsCallback : providesCallback;

          // Smash the type and member names together so we can continue using
          // StringMap.
          SmallString<64> appended;
          appended += base->getValue(scratch);
          appended.push_back('\0');
          appended += member->getValue(scratch);

          UPDATE_RESULT(callback(appended.str(), dirAndKind.first,
                                 isCascading));
        }
      } else {
        for (const yaml::Node &rawEntry : *entries) {
          auto *entry = dyn_cast<yaml::ScalarNode>(&rawEntry);
          if (!entry)
            return LoadResult::HadError;

          bool isDepends = dirAndKind.second == DependencyDirection::Depends;
          auto &callback = isDepends ? dependsCallback : providesCallback;

          UPDATE_RESULT(callback(entry->getValue(scratch), dirAndKind.first,
                                 entry->getRawTag() != "!private"));
        }
      }
    }
  }

  return result;
}
Ejemplo n.º 16
0
/// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,
/// return null on failure.  isAngled indicates whether the file reference is
/// for system \#include's or not (i.e. using <> instead of ""). Includers, if
/// non-empty, indicates where the \#including file(s) are, in case a relative
/// search is needed. Microsoft mode will pass all \#including files.
const FileEntry *HeaderSearch::LookupFile(
    StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
    const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
    ArrayRef<const FileEntry *> Includers, SmallVectorImpl<char> *SearchPath,
    SmallVectorImpl<char> *RelativePath,
    ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) {
  if (!HSOpts->ModuleMapFiles.empty()) {
    // Preload all explicitly specified module map files. This enables modules
    // map files lying in a directory structure separate from the header files
    // that they describe. These cannot be loaded lazily upon encountering a
    // header file, as there is no other known mapping from a header file to its
    // module map file.
    for (llvm::SetVector<std::string>::iterator
             I = HSOpts->ModuleMapFiles.begin(),
             E = HSOpts->ModuleMapFiles.end();
         I != E; ++I) {
      const FileEntry *File = FileMgr.getFile(*I);
      if (!File)
        continue;
      loadModuleMapFile(File, /*IsSystem=*/false);
    }
    HSOpts->ModuleMapFiles.clear();
  }

  if (SuggestedModule)
    *SuggestedModule = ModuleMap::KnownHeader();
    
  // If 'Filename' is absolute, check to see if it exists and no searching.
  if (llvm::sys::path::is_absolute(Filename)) {
    CurDir = 0;

    // If this was an #include_next "/absolute/file", fail.
    if (FromDir) return 0;

    if (SearchPath != NULL)
      SearchPath->clear();
    if (RelativePath != NULL) {
      RelativePath->clear();
      RelativePath->append(Filename.begin(), Filename.end());
    }
    // Otherwise, just return the file.
    return FileMgr.getFile(Filename, /*openFile=*/true);
  }

  // This is the header that MSVC's header search would have found.
  const FileEntry *MSFE = 0;

  // Unless disabled, check to see if the file is in the #includer's
  // directory.  This cannot be based on CurDir, because each includer could be
  // a #include of a subdirectory (#include "foo/bar.h") and a subsequent
  // include of "baz.h" should resolve to "whatever/foo/baz.h".
  // This search is not done for <> headers.
  if (!Includers.empty() && !isAngled && !NoCurDirSearch) {
    SmallString<1024> TmpDir;
    for (ArrayRef<const FileEntry *>::iterator I = Includers.begin(),
                                               E = Includers.end();
         I != E; ++I) {
      const FileEntry *Includer = *I;
      // Concatenate the requested file onto the directory.
      // FIXME: Portability.  Filename concatenation should be in sys::Path.
      TmpDir = Includer->getDir()->getName();
      TmpDir.push_back('/');
      TmpDir.append(Filename.begin(), Filename.end());
      if (const FileEntry *FE =
              FileMgr.getFile(TmpDir.str(), /*openFile=*/true)) {
        // Leave CurDir unset.
        // This file is a system header or C++ unfriendly if the old file is.
        //
        // Note that we only use one of FromHFI/ToHFI at once, due to potential
        // reallocation of the underlying vector potentially making the first
        // reference binding dangling.
        HeaderFileInfo &FromHFI = getFileInfo(Includer);
        unsigned DirInfo = FromHFI.DirInfo;
        bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader;
        StringRef Framework = FromHFI.Framework;

        HeaderFileInfo &ToHFI = getFileInfo(FE);
        ToHFI.DirInfo = DirInfo;
        ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader;
        ToHFI.Framework = Framework;

        if (SearchPath != NULL) {
          StringRef SearchPathRef(Includer->getDir()->getName());
          SearchPath->clear();
          SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
        }
        if (RelativePath != NULL) {
          RelativePath->clear();
          RelativePath->append(Filename.begin(), Filename.end());
        }
        if (I == Includers.begin())
          return FE;

        // Otherwise, we found the path via MSVC header search rules.  If
        // -Wmsvc-include is enabled, we have to keep searching to see if we
        // would've found this header in -I or -isystem directories.
        if (Diags.getDiagnosticLevel(diag::ext_pp_include_search_ms,
                                     IncludeLoc) ==
            DiagnosticsEngine::Ignored) {
          return FE;
        } else {
          MSFE = FE;
          break;
        }
      }
    }
  }

  CurDir = 0;

  // If this is a system #include, ignore the user #include locs.
  unsigned i = isAngled ? AngledDirIdx : 0;

  // If this is a #include_next request, start searching after the directory the
  // file was found in.
  if (FromDir)
    i = FromDir-&SearchDirs[0];

  // Cache all of the lookups performed by this method.  Many headers are
  // multiply included, and the "pragma once" optimization prevents them from
  // being relex/pp'd, but they would still have to search through a
  // (potentially huge) series of SearchDirs to find it.
  std::pair<unsigned, unsigned> &CacheLookup =
    LookupFileCache.GetOrCreateValue(Filename).getValue();

  // If the entry has been previously looked up, the first value will be
  // non-zero.  If the value is equal to i (the start point of our search), then
  // this is a matching hit.
  if (!SkipCache && CacheLookup.first == i+1) {
    // Skip querying potentially lots of directories for this lookup.
    i = CacheLookup.second;
  } else {
    // Otherwise, this is the first query, or the previous query didn't match
    // our search start.  We will fill in our found location below, so prime the
    // start point value.
    CacheLookup.first = i+1;
  }

  SmallString<64> MappedName;

  // Check each directory in sequence to see if it contains this file.
  for (; i != SearchDirs.size(); ++i) {
    bool InUserSpecifiedSystemFramework = false;
    const FileEntry *FE =
      SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
                               SuggestedModule, InUserSpecifiedSystemFramework,
                               MappedName);
    if (!FE) continue;

    CurDir = &SearchDirs[i];

    // This file is a system header or C++ unfriendly if the dir is.
    HeaderFileInfo &HFI = getFileInfo(FE);
    HFI.DirInfo = CurDir->getDirCharacteristic();

    // If the directory characteristic is User but this framework was
    // user-specified to be treated as a system framework, promote the
    // characteristic.
    if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
      HFI.DirInfo = SrcMgr::C_System;

    // If the filename matches a known system header prefix, override
    // whether the file is a system header.
    for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {
      if (Filename.startswith(SystemHeaderPrefixes[j-1].first)) {
        HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System
                                                       : SrcMgr::C_User;
        break;
      }
    }

    // If this file is found in a header map and uses the framework style of
    // includes, then this header is part of a framework we're building.
    if (CurDir->isIndexHeaderMap()) {
      size_t SlashPos = Filename.find('/');
      if (SlashPos != StringRef::npos) {
        HFI.IndexHeaderMapHeader = 1;
        HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), 
                                                         SlashPos));
      }
    }

    if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc))
      return MSFE;

    // Remember this location for the next lookup we do.
    CacheLookup.second = i;
    return FE;
  }

  // If we are including a file with a quoted include "foo.h" from inside
  // a header in a framework that is currently being built, and we couldn't
  // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where
  // "Foo" is the name of the framework in which the including header was found.
  if (!Includers.empty() && !isAngled &&
      Filename.find('/') == StringRef::npos) {
    HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front());
    if (IncludingHFI.IndexHeaderMapHeader) {
      SmallString<128> ScratchFilename;
      ScratchFilename += IncludingHFI.Framework;
      ScratchFilename += '/';
      ScratchFilename += Filename;

      const FileEntry *FE = LookupFile(
          ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir,
          Includers.front(), SearchPath, RelativePath, SuggestedModule);

      if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc))
        return MSFE;

      std::pair<unsigned, unsigned> &CacheLookup 
        = LookupFileCache.GetOrCreateValue(Filename).getValue();
      CacheLookup.second
        = LookupFileCache.GetOrCreateValue(ScratchFilename).getValue().second;
      return FE;
    }
  }

  if (checkMSVCHeaderSearch(Diags, MSFE, 0, IncludeLoc))
    return MSFE;

  // Otherwise, didn't find it. Remember we didn't find this.
  CacheLookup.second = SearchDirs.size();
  return 0;
}
Ejemplo n.º 17
0
bool DirectoryImporter::load(StringRef qualName, Module *& module) {
  // Transform dots into path separators to get the relative path.
  SmallString<128> relpath;
  for (StringRef::const_iterator ch = qualName.begin(); ch != qualName.end(); ++ch) {
    if (*ch == '.') {
      relpath.push_back('/');
    } else {
      relpath.push_back(*ch);
    }
  }

  // Transform dots into path separators.
  SmallString<128> filepath(path_);
  path::append(filepath, Twine(relpath));
  path::replace_extension(filepath, ".tart");

  // Check for source file
  bool exists = false;
  if (fs::exists(Twine(filepath), exists) == errc::success && exists) {
    // Get the file timestamp.
    llvm::sys::TimeValue timestamp = filetime(filepath);
    // TODO: We should get the timestamp and store them in the
    // module, along with the file size and other info.

    // If we haven't already found a bitcode file for this module.
    if (module == NULL) {
      module = new Module(qualName, &Builtins::module);
    } else if (module->timestamp() > timestamp) {
      diag.debug() << "Import: Module '" << qualName << "' exists, and is newer than timestamp";
    } else {
      diag.debug() << "Import: Module '" << qualName << "' exists, and is older than timestamp";
    }

    module->setModuleSource(new SourceFile(filepath));
    if (ShowImports) {
      diag.debug() << "Import: Found source module '" << qualName << "' at " << filepath;
    }

    Parser parser(module->moduleSource(), module);
    if (parser.parse()) {
      return true;
    } else {
      delete module;
      module = NULL;
      return true;
    }
  }

#if 0
  // If we haven't found a module yet, check for bitcode file
  if (module == NULL) {
    path::replace_extension(filepath, ".bc");
    if (fs::exists(Twine(filepath), exists) == errc::success && exists) {
      module = new Module(qualName, &Builtins::module);
      module->timestamp() == filetime(filepath);
      // Load the bitcode file.
      if (ShowImports) {
        diag.debug() << "Import: Found bitcode module '" << qualName << "' at " << filepath;
      }
      DFAIL("Implewent");
      return true;
    }

    if (ShowImports) {
      diag.debug() << "Import: Didn't find module '" << qualName << "' at " << filepath;
    }
  }
#endif

  return false;
}
Ejemplo n.º 18
0
/// DoFrameworkLookup - Do a lookup of the specified file in the current
/// DirectoryLookup, which is a framework directory.
const FileEntry *DirectoryLookup::DoFrameworkLookup(
    StringRef Filename,
    HeaderSearch &HS,
    SmallVectorImpl<char> *SearchPath,
    SmallVectorImpl<char> *RelativePath,
    ModuleMap::KnownHeader *SuggestedModule,
    bool &InUserSpecifiedSystemFramework) const
{
  FileManager &FileMgr = HS.getFileMgr();

  // Framework names must have a '/' in the filename.
  size_t SlashPos = Filename.find('/');
  if (SlashPos == StringRef::npos) return nullptr;

  // Find out if this is the home for the specified framework, by checking
  // HeaderSearch.  Possible answers are yes/no and unknown.
  HeaderSearch::FrameworkCacheEntry &CacheEntry =
    HS.LookupFrameworkCache(Filename.substr(0, SlashPos));

  // If it is known and in some other directory, fail.
  if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir())
    return nullptr;

  // Otherwise, construct the path to this framework dir.

  // FrameworkName = "/System/Library/Frameworks/"
  SmallString<1024> FrameworkName;
  FrameworkName += getFrameworkDir()->getName();
  if (FrameworkName.empty() || FrameworkName.back() != '/')
    FrameworkName.push_back('/');

  // FrameworkName = "/System/Library/Frameworks/Cocoa"
  StringRef ModuleName(Filename.begin(), SlashPos);
  FrameworkName += ModuleName;

  // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
  FrameworkName += ".framework/";

  // If the cache entry was unresolved, populate it now.
  if (!CacheEntry.Directory) {
    HS.IncrementFrameworkLookupCount();

    // If the framework dir doesn't exist, we fail.
    const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
    if (!Dir) return nullptr;

    // Otherwise, if it does, remember that this is the right direntry for this
    // framework.
    CacheEntry.Directory = getFrameworkDir();

    // If this is a user search directory, check if the framework has been
    // user-specified as a system framework.
    if (getDirCharacteristic() == SrcMgr::C_User) {
      SmallString<1024> SystemFrameworkMarker(FrameworkName);
      SystemFrameworkMarker += ".system_framework";
      if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) {
        CacheEntry.IsUserSpecifiedSystemFramework = true;
      }
    }
  }

  // Set the 'user-specified system framework' flag.
  InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;

  if (RelativePath) {
    RelativePath->clear();
    RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
  }

  // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
  unsigned OrigSize = FrameworkName.size();

  FrameworkName += "Headers/";

  if (SearchPath) {
    SearchPath->clear();
    // Without trailing '/'.
    SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
  }

  FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
  const FileEntry *FE = FileMgr.getFile(FrameworkName.str(),
                                        /*openFile=*/!SuggestedModule);
  if (!FE) {
    // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
    const char *Private = "Private";
    FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
                         Private+strlen(Private));
    if (SearchPath)
      SearchPath->insert(SearchPath->begin()+OrigSize, Private,
                         Private+strlen(Private));

    FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/!SuggestedModule);
  }

  // If we found the header and are allowed to suggest a module, do so now.
  if (FE && SuggestedModule) {
    // Find the framework in which this header occurs.
    StringRef FrameworkPath = FE->getDir()->getName();
    bool FoundFramework = false;
    do {
      // Determine whether this directory exists.
      const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath);
      if (!Dir)
        break;

      // If this is a framework directory, then we're a subframework of this
      // framework.
      if (llvm::sys::path::extension(FrameworkPath) == ".framework") {
        FoundFramework = true;
        break;
      }

      // Get the parent directory name.
      FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
      if (FrameworkPath.empty())
        break;
    } while (true);

    if (FoundFramework) {
      // Find the top-level framework based on this framework.
      SmallVector<std::string, 4> SubmodulePath;
      const DirectoryEntry *TopFrameworkDir
        = ::getTopFrameworkDir(FileMgr, FrameworkPath, SubmodulePath);

      // Determine the name of the top-level framework.
      StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());

      // Load this framework module. If that succeeds, find the suggested module
      // for this header, if any.
      bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
      if (HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) {
        *SuggestedModule = HS.findModuleForHeader(FE);
      }
    } else {
      *SuggestedModule = HS.findModuleForHeader(FE);
    }
  }
  return FE;
}
Ejemplo n.º 19
0
/// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,
/// return null on failure.  isAngled indicates whether the file reference is
/// for system \#include's or not (i.e. using <> instead of ""). Includers, if
/// non-empty, indicates where the \#including file(s) are, in case a relative
/// search is needed. Microsoft mode will pass all \#including files.
const FileEntry *HeaderSearch::LookupFile(
    StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
    const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
    ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
    SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
    ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) {
  if (SuggestedModule)
    *SuggestedModule = ModuleMap::KnownHeader();

  // If 'Filename' is absolute, check to see if it exists and no searching.
  if (llvm::sys::path::is_absolute(Filename)) {
    CurDir = nullptr;

    // If this was an #include_next "/absolute/file", fail.
    if (FromDir) return nullptr;

    if (SearchPath)
      SearchPath->clear();
    if (RelativePath) {
      RelativePath->clear();
      RelativePath->append(Filename.begin(), Filename.end());
    }
    // Otherwise, just return the file.
    return FileMgr.getFile(Filename, /*openFile=*/true);
  }

  // This is the header that MSVC's header search would have found.
  const FileEntry *MSFE = nullptr;
  ModuleMap::KnownHeader MSSuggestedModule;

  // Unless disabled, check to see if the file is in the #includer's
  // directory.  This cannot be based on CurDir, because each includer could be
  // a #include of a subdirectory (#include "foo/bar.h") and a subsequent
  // include of "baz.h" should resolve to "whatever/foo/baz.h".
  // This search is not done for <> headers.
  if (!Includers.empty() && !isAngled && !NoCurDirSearch) {
    SmallString<1024> TmpDir;
    bool First = true;
    for (const auto &IncluderAndDir : Includers) {
      const FileEntry *Includer = IncluderAndDir.first;

      // Concatenate the requested file onto the directory.
      // FIXME: Portability.  Filename concatenation should be in sys::Path.
      TmpDir = IncluderAndDir.second->getName();
      TmpDir.push_back('/');
      TmpDir.append(Filename.begin(), Filename.end());

      // FIXME: We don't cache the result of getFileInfo across the call to
      // getFileAndSuggestModule, because it's a reference to an element of
      // a container that could be reallocated across this call.
      //
      // FIXME: If we have no includer, that means we're processing a #include
      // from a module build. We should treat this as a system header if we're
      // building a [system] module.
      bool IncluderIsSystemHeader =
          Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User;
      if (const FileEntry *FE = getFileAndSuggestModule(
              *this, TmpDir.str(), IncluderAndDir.second,
              IncluderIsSystemHeader, SuggestedModule)) {
        if (!Includer) {
          assert(First && "only first includer can have no file");
          return FE;
        }

        // Leave CurDir unset.
        // This file is a system header or C++ unfriendly if the old file is.
        //
        // Note that we only use one of FromHFI/ToHFI at once, due to potential
        // reallocation of the underlying vector potentially making the first
        // reference binding dangling.
        HeaderFileInfo &FromHFI = getFileInfo(Includer);
        unsigned DirInfo = FromHFI.DirInfo;
        bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader;
        StringRef Framework = FromHFI.Framework;

        HeaderFileInfo &ToHFI = getFileInfo(FE);
        ToHFI.DirInfo = DirInfo;
        ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader;
        ToHFI.Framework = Framework;

        if (SearchPath) {
          StringRef SearchPathRef(IncluderAndDir.second->getName());
          SearchPath->clear();
          SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
        }
        if (RelativePath) {
          RelativePath->clear();
          RelativePath->append(Filename.begin(), Filename.end());
        }
        if (First)
          return FE;

        // Otherwise, we found the path via MSVC header search rules.  If
        // -Wmsvc-include is enabled, we have to keep searching to see if we
        // would've found this header in -I or -isystem directories.
        if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
          return FE;
        } else {
          MSFE = FE;
          if (SuggestedModule) {
            MSSuggestedModule = *SuggestedModule;
            *SuggestedModule = ModuleMap::KnownHeader();
          }
          break;
        }
      }
      First = false;
    }
  }

  CurDir = nullptr;

  // If this is a system #include, ignore the user #include locs.
  unsigned i = isAngled ? AngledDirIdx : 0;

  // If this is a #include_next request, start searching after the directory the
  // file was found in.
  if (FromDir)
    i = FromDir-&SearchDirs[0];

  // Cache all of the lookups performed by this method.  Many headers are
  // multiply included, and the "pragma once" optimization prevents them from
  // being relex/pp'd, but they would still have to search through a
  // (potentially huge) series of SearchDirs to find it.
  LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];

  // If the entry has been previously looked up, the first value will be
  // non-zero.  If the value is equal to i (the start point of our search), then
  // this is a matching hit.
  if (!SkipCache && CacheLookup.StartIdx == i+1) {
    // Skip querying potentially lots of directories for this lookup.
    i = CacheLookup.HitIdx;
    if (CacheLookup.MappedName)
      Filename = CacheLookup.MappedName;
  } else {
    // Otherwise, this is the first query, or the previous query didn't match
    // our search start.  We will fill in our found location below, so prime the
    // start point value.
    CacheLookup.reset(/*StartIdx=*/i+1);
  }

  SmallString<64> MappedName;

  // Check each directory in sequence to see if it contains this file.
  for (; i != SearchDirs.size(); ++i) {
    bool InUserSpecifiedSystemFramework = false;
    bool HasBeenMapped = false;
    const FileEntry *FE =
      SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
                               SuggestedModule, InUserSpecifiedSystemFramework,
                               HasBeenMapped, MappedName);
    if (HasBeenMapped) {
      CacheLookup.MappedName =
          copyString(Filename, LookupFileCache.getAllocator());
    }
    if (!FE) continue;

    CurDir = &SearchDirs[i];

    // This file is a system header or C++ unfriendly if the dir is.
    HeaderFileInfo &HFI = getFileInfo(FE);
    HFI.DirInfo = CurDir->getDirCharacteristic();

    // If the directory characteristic is User but this framework was
    // user-specified to be treated as a system framework, promote the
    // characteristic.
    if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
      HFI.DirInfo = SrcMgr::C_System;

    // If the filename matches a known system header prefix, override
    // whether the file is a system header.
    for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {
      if (Filename.startswith(SystemHeaderPrefixes[j-1].first)) {
        HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System
                                                       : SrcMgr::C_User;
        break;
      }
    }

    // If this file is found in a header map and uses the framework style of
    // includes, then this header is part of a framework we're building.
    if (CurDir->isIndexHeaderMap()) {
      size_t SlashPos = Filename.find('/');
      if (SlashPos != StringRef::npos) {
        HFI.IndexHeaderMapHeader = 1;
        HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(),
                                                         SlashPos));
      }
    }

    if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) {
      if (SuggestedModule)
        *SuggestedModule = MSSuggestedModule;
      return MSFE;
    }

    // Remember this location for the next lookup we do.
    CacheLookup.HitIdx = i;
    return FE;
  }

  // If we are including a file with a quoted include "foo.h" from inside
  // a header in a framework that is currently being built, and we couldn't
  // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where
  // "Foo" is the name of the framework in which the including header was found.
  if (!Includers.empty() && Includers.front().first && !isAngled &&
      Filename.find('/') == StringRef::npos) {
    HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front().first);
    if (IncludingHFI.IndexHeaderMapHeader) {
      SmallString<128> ScratchFilename;
      ScratchFilename += IncludingHFI.Framework;
      ScratchFilename += '/';
      ScratchFilename += Filename;

      const FileEntry *FE = LookupFile(
          ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir,
          Includers.front(), SearchPath, RelativePath, SuggestedModule);

      if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) {
        if (SuggestedModule)
          *SuggestedModule = MSSuggestedModule;
        return MSFE;
      }

      LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
      CacheLookup.HitIdx = LookupFileCache[ScratchFilename].HitIdx;
      // FIXME: SuggestedModule.
      return FE;
    }
  }

  if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) {
    if (SuggestedModule)
      *SuggestedModule = MSSuggestedModule;
    return MSFE;
  }

  // Otherwise, didn't find it. Remember we didn't find this.
  CacheLookup.HitIdx = SearchDirs.size();
  return nullptr;
}
Ejemplo n.º 20
0
/// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,
/// return null on failure.  isAngled indicates whether the file reference is
/// for system \#include's or not (i.e. using <> instead of "").  CurFileEnt, if
/// non-null, indicates where the \#including file is, in case a relative search
/// is needed.
const FileEntry *HeaderSearch::LookupFile(
    StringRef Filename,
    bool isAngled,
    const DirectoryLookup *FromDir,
    const DirectoryLookup *&CurDir,
    const FileEntry *CurFileEnt,
    SmallVectorImpl<char> *SearchPath,
    SmallVectorImpl<char> *RelativePath,
    Module **SuggestedModule,
    bool SkipCache)
{
  if (SuggestedModule)
    *SuggestedModule = 0;
    
  // If 'Filename' is absolute, check to see if it exists and no searching.
  if (llvm::sys::path::is_absolute(Filename)) {
    CurDir = 0;

    // If this was an #include_next "/absolute/file", fail.
    if (FromDir) return 0;

    if (SearchPath != NULL)
      SearchPath->clear();
    if (RelativePath != NULL) {
      RelativePath->clear();
      RelativePath->append(Filename.begin(), Filename.end());
    }
    // Otherwise, just return the file.
    return FileMgr.getFile(Filename, /*openFile=*/true);
  }

  // Unless disabled, check to see if the file is in the #includer's
  // directory.  This has to be based on CurFileEnt, not CurDir, because
  // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and
  // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h".
  // This search is not done for <> headers.
  if (CurFileEnt && !isAngled && !NoCurDirSearch) {
    SmallString<1024> TmpDir;
    // Concatenate the requested file onto the directory.
    // FIXME: Portability.  Filename concatenation should be in sys::Path.
    TmpDir += CurFileEnt->getDir()->getName();
    TmpDir.push_back('/');
    TmpDir.append(Filename.begin(), Filename.end());
    if (const FileEntry *FE = FileMgr.getFile(TmpDir.str(),/*openFile=*/true)) {
      // Leave CurDir unset.
      // This file is a system header or C++ unfriendly if the old file is.
      //
      // Note that the temporary 'DirInfo' is required here, as either call to
      // getFileInfo could resize the vector and we don't want to rely on order
      // of evaluation.
      unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo;
      getFileInfo(FE).DirInfo = DirInfo;
      if (SearchPath != NULL) {
        StringRef SearchPathRef(CurFileEnt->getDir()->getName());
        SearchPath->clear();
        SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
      }
      if (RelativePath != NULL) {
        RelativePath->clear();
        RelativePath->append(Filename.begin(), Filename.end());
      }
      return FE;
    }
  }

  CurDir = 0;

  // If this is a system #include, ignore the user #include locs.
  unsigned i = isAngled ? AngledDirIdx : 0;

  // If this is a #include_next request, start searching after the directory the
  // file was found in.
  if (FromDir)
    i = FromDir-&SearchDirs[0];

  // Cache all of the lookups performed by this method.  Many headers are
  // multiply included, and the "pragma once" optimization prevents them from
  // being relex/pp'd, but they would still have to search through a
  // (potentially huge) series of SearchDirs to find it.
  std::pair<unsigned, unsigned> &CacheLookup =
    LookupFileCache.GetOrCreateValue(Filename).getValue();

  // If the entry has been previously looked up, the first value will be
  // non-zero.  If the value is equal to i (the start point of our search), then
  // this is a matching hit.
  if (!SkipCache && CacheLookup.first == i+1) {
    // Skip querying potentially lots of directories for this lookup.
    i = CacheLookup.second;
  } else {
    // Otherwise, this is the first query, or the previous query didn't match
    // our search start.  We will fill in our found location below, so prime the
    // start point value.
    CacheLookup.first = i+1;
  }

  // Check each directory in sequence to see if it contains this file.
  for (; i != SearchDirs.size(); ++i) {
    bool InUserSpecifiedSystemFramework = false;
    const FileEntry *FE =
      SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
                               SuggestedModule, InUserSpecifiedSystemFramework);
    if (!FE) continue;

    CurDir = &SearchDirs[i];

    // This file is a system header or C++ unfriendly if the dir is.
    HeaderFileInfo &HFI = getFileInfo(FE);
    HFI.DirInfo = CurDir->getDirCharacteristic();

    // If the directory characteristic is User but this framework was
    // user-specified to be treated as a system framework, promote the
    // characteristic.
    if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
      HFI.DirInfo = SrcMgr::C_System;

    // If the filename matches a known system header prefix, override
    // whether the file is a system header.
    for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {
      if (Filename.startswith(SystemHeaderPrefixes[j-1].first)) {
        HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System
                                                       : SrcMgr::C_User;
        break;
      }
    }

    // If this file is found in a header map and uses the framework style of
    // includes, then this header is part of a framework we're building.
    if (CurDir->isIndexHeaderMap()) {
      size_t SlashPos = Filename.find('/');
      if (SlashPos != StringRef::npos) {
        HFI.IndexHeaderMapHeader = 1;
        HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), 
                                                         SlashPos));
      }
    }
    
    // Remember this location for the next lookup we do.
    CacheLookup.second = i;
    return FE;
  }

  // If we are including a file with a quoted include "foo.h" from inside
  // a header in a framework that is currently being built, and we couldn't
  // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where
  // "Foo" is the name of the framework in which the including header was found.
  if (CurFileEnt && !isAngled && Filename.find('/') == StringRef::npos) {
    HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt);
    if (IncludingHFI.IndexHeaderMapHeader) {
      SmallString<128> ScratchFilename;
      ScratchFilename += IncludingHFI.Framework;
      ScratchFilename += '/';
      ScratchFilename += Filename;
      
      const FileEntry *Result = LookupFile(ScratchFilename, /*isAngled=*/true,
                                           FromDir, CurDir, CurFileEnt, 
                                           SearchPath, RelativePath,
                                           SuggestedModule);
      std::pair<unsigned, unsigned> &CacheLookup 
        = LookupFileCache.GetOrCreateValue(Filename).getValue();
      CacheLookup.second
        = LookupFileCache.GetOrCreateValue(ScratchFilename).getValue().second;
      return Result;
    }
  }

  // Otherwise, didn't find it. Remember we didn't find this.
  CacheLookup.second = SearchDirs.size();
  return 0;
}
Ejemplo n.º 21
0
/// EvaluateHasIncludeCommon - Process a '__has_include("path")'
/// or '__has_include_next("path")' expression.
/// Returns true if successful.
static bool EvaluateHasIncludeCommon(Token &Tok,
                                     IdentifierInfo *II, Preprocessor &PP,
                                     const DirectoryLookup *LookupFrom) {
  SourceLocation LParenLoc;

  // Get '('.
  PP.LexNonComment(Tok);

  // Ensure we have a '('.
  if (Tok.isNot(tok::l_paren)) {
    PP.Diag(Tok.getLocation(), diag::err_pp_missing_lparen) << II->getName();
    return false;
  }

  // Save '(' location for possible missing ')' message.
  LParenLoc = Tok.getLocation();

  // Get the file name.
  PP.getCurrentLexer()->LexIncludeFilename(Tok);

  // Reserve a buffer to get the spelling.
  SmallString<128> FilenameBuffer;
  StringRef Filename;
  SourceLocation EndLoc;
  
  switch (Tok.getKind()) {
  case tok::eod:
    // If the token kind is EOD, the error has already been diagnosed.
    return false;

  case tok::angle_string_literal:
  case tok::string_literal: {
    bool Invalid = false;
    Filename = PP.getSpelling(Tok, FilenameBuffer, &Invalid);
    if (Invalid)
      return false;
    break;
  }

  case tok::less:
    // This could be a <foo/bar.h> file coming from a macro expansion.  In this
    // case, glue the tokens together into FilenameBuffer and interpret those.
    FilenameBuffer.push_back('<');
    if (PP.ConcatenateIncludeName(FilenameBuffer, EndLoc))
      return false;   // Found <eod> but no ">"?  Diagnostic already emitted.
    Filename = FilenameBuffer.str();
    break;
  default:
    PP.Diag(Tok.getLocation(), diag::err_pp_expects_filename);
    return false;
  }

  // Get ')'.
  PP.LexNonComment(Tok);

  // Ensure we have a trailing ).
  if (Tok.isNot(tok::r_paren)) {
    PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName();
    PP.Diag(LParenLoc, diag::note_matching) << "(";
    return false;
  }

  bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
  // If GetIncludeFilenameSpelling set the start ptr to null, there was an
  // error.
  if (Filename.empty())
    return false;

  // Search include directories.
  const DirectoryLookup *CurDir;
  const FileEntry *File =
      PP.LookupFile(Filename, isAngled, LookupFrom, CurDir, NULL, NULL, NULL);

  // Get the result value.  A result of true means the file exists.
  return File != 0;
}
Ejemplo n.º 22
0
SmallString<256> FuzzyMatcher::dumpLast(raw_ostream &OS) const {
  SmallString<256> Result;
  OS << "=== Match \"" << StringRef(Word, WordN) << "\" against ["
     << StringRef(Pat, PatN) << "] ===\n";
  if (PatN == 0) {
    OS << "Pattern is empty: perfect match.\n";
    return Result = StringRef(Word, WordN);
  }
  if (WordN == 0) {
    OS << "Word is empty: no match.\n";
    return Result;
  }
  if (!WordContainsPattern) {
    OS << "Substring check failed.\n";
    return Result;
  } else if (isAwful(std::max(Scores[PatN][WordN][Match].Score,
                              Scores[PatN][WordN][Miss].Score))) {
    OS << "Substring check passed, but all matches are forbidden\n";
  }
  if (!(PatTypeSet & 1 << Upper))
    OS << "Lowercase query, so scoring ignores case\n";

  // Traverse Matched table backwards to reconstruct the Pattern/Word mapping.
  // The Score table has cumulative scores, subtracting along this path gives
  // us the per-letter scores.
  Action Last =
      (Scores[PatN][WordN][Match].Score > Scores[PatN][WordN][Miss].Score)
          ? Match
          : Miss;
  int S[MaxWord];
  Action A[MaxWord];
  for (int W = WordN - 1, P = PatN - 1; W >= 0; --W) {
    A[W] = Last;
    const auto &Cell = Scores[P + 1][W + 1][Last];
    if (Last == Match)
      --P;
    const auto &Prev = Scores[P + 1][W][Cell.Prev];
    S[W] = Cell.Score - Prev.Score;
    Last = Cell.Prev;
  }
  for (int I = 0; I < WordN; ++I) {
    if (A[I] == Match && (I == 0 || A[I - 1] == Miss))
      Result.push_back('[');
    if (A[I] == Miss && I > 0 && A[I - 1] == Match)
      Result.push_back(']');
    Result.push_back(Word[I]);
  }
  if (A[WordN - 1] == Match)
    Result.push_back(']');

  for (char C : StringRef(Word, WordN))
    OS << " " << C << " ";
  OS << "\n";
  for (int I = 0, J = 0; I < WordN; I++)
    OS << " " << (A[I] == Match ? Pat[J++] : ' ') << " ";
  OS << "\n";
  for (int I = 0; I < WordN; I++)
    OS << format("%2d ", S[I]);
  OS << "\n";

  OS << "\nSegmentation:";
  OS << "\n'" << StringRef(Word, WordN) << "'\n ";
  for (int I = 0; I < WordN; ++I)
    OS << "?-+ "[static_cast<int>(WordRole[I])];
  OS << "\n[" << StringRef(Pat, PatN) << "]\n ";
  for (int I = 0; I < PatN; ++I)
    OS << "?-+ "[static_cast<int>(PatRole[I])];
  OS << "\n";

  OS << "\nScoring table (last-Miss, last-Match):\n";
  OS << " |    ";
  for (char C : StringRef(Word, WordN))
    OS << "  " << C << " ";
  OS << "\n";
  OS << "-+----" << std::string(WordN * 4, '-') << "\n";
  for (int I = 0; I <= PatN; ++I) {
    for (Action A : {Miss, Match}) {
      OS << ((I && A == Miss) ? Pat[I - 1] : ' ') << "|";
      for (int J = 0; J <= WordN; ++J) {
        if (!isAwful(Scores[I][J][A].Score))
          OS << format("%3d%c", Scores[I][J][A].Score,
                       Scores[I][J][A].Prev == Match ? '*' : ' ');
        else
          OS << "    ";
      }
      OS << "\n";
    }
  }

  return Result;
}
Ejemplo n.º 23
0
void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
  // We will either get a quoted filename or a bracketed filename, and we
  // have to track which we got.  The first filename is the source name,
  // and the second name is the mapped filename.  If the first is quoted,
  // the second must be as well (cannot mix and match quotes and brackets).

  // Get the open paren
  Lex(Tok);
  if (Tok.isNot(tok::l_paren)) {
    Diag(Tok, diag::warn_pragma_include_alias_expected) << "(";
    return;
  }

  // We expect either a quoted string literal, or a bracketed name
  Token SourceFilenameTok;
  CurPPLexer->LexIncludeFilename(SourceFilenameTok);
  if (SourceFilenameTok.is(tok::eod)) {
    // The diagnostic has already been handled
    return;
  }

  StringRef SourceFileName;
  SmallString<128> FileNameBuffer;
  if (SourceFilenameTok.is(tok::string_literal) ||
      SourceFilenameTok.is(tok::angle_string_literal)) {
    SourceFileName = getSpelling(SourceFilenameTok, FileNameBuffer);
  } else if (SourceFilenameTok.is(tok::less)) {
    // This could be a path instead of just a name
    FileNameBuffer.push_back('<');
    SourceLocation End;
    if (ConcatenateIncludeName(FileNameBuffer, End))
      return; // Diagnostic already emitted
    SourceFileName = FileNameBuffer.str();
  } else {
    Diag(Tok, diag::warn_pragma_include_alias_expected_filename);
    return;
  }
  FileNameBuffer.clear();

  // Now we expect a comma, followed by another include name
  Lex(Tok);
  if (Tok.isNot(tok::comma)) {
    Diag(Tok, diag::warn_pragma_include_alias_expected) << ",";
    return;
  }

  Token ReplaceFilenameTok;
  CurPPLexer->LexIncludeFilename(ReplaceFilenameTok);
  if (ReplaceFilenameTok.is(tok::eod)) {
    // The diagnostic has already been handled
    return;
  }

  StringRef ReplaceFileName;
  if (ReplaceFilenameTok.is(tok::string_literal) ||
      ReplaceFilenameTok.is(tok::angle_string_literal)) {
    ReplaceFileName = getSpelling(ReplaceFilenameTok, FileNameBuffer);
  } else if (ReplaceFilenameTok.is(tok::less)) {
    // This could be a path instead of just a name
    FileNameBuffer.push_back('<');
    SourceLocation End;
    if (ConcatenateIncludeName(FileNameBuffer, End))
      return; // Diagnostic already emitted
    ReplaceFileName = FileNameBuffer.str();
  } else {
    Diag(Tok, diag::warn_pragma_include_alias_expected_filename);
    return;
  }

  // Finally, we expect the closing paren
  Lex(Tok);
  if (Tok.isNot(tok::r_paren)) {
    Diag(Tok, diag::warn_pragma_include_alias_expected) << ")";
    return;
  }

  // Now that we have the source and target filenames, we need to make sure
  // they're both of the same type (angled vs non-angled)
  StringRef OriginalSource = SourceFileName;

  bool SourceIsAngled =
    GetIncludeFilenameSpelling(SourceFilenameTok.getLocation(),
                                SourceFileName);
  bool ReplaceIsAngled =
    GetIncludeFilenameSpelling(ReplaceFilenameTok.getLocation(),
                                ReplaceFileName);
  if (!SourceFileName.empty() && !ReplaceFileName.empty() &&
      (SourceIsAngled != ReplaceIsAngled)) {
    unsigned int DiagID;
    if (SourceIsAngled)
      DiagID = diag::warn_pragma_include_alias_mismatch_angle;
    else
      DiagID = diag::warn_pragma_include_alias_mismatch_quote;

    Diag(SourceFilenameTok.getLocation(), DiagID)
      << SourceFileName
      << ReplaceFileName;

    return;
  }

  // Now we can let the include handler know about this mapping
  getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName);
}
Ejemplo n.º 24
0
/// TypeString - for a modifier and type, generate the name of the typedef for
/// that type.  QUc -> uint8x8_t.
static std::string TypeString(const char mod, StringRef typestr) {
  bool quad = false;
  bool poly = false;
  bool usgn = false;
  bool scal = false;
  bool cnst = false;
  bool pntr = false;

  if (mod == 'v')
    return "void";
  if (mod == 'i')
    return "int";

  // base type to get the type string for.
  char type = ClassifyType(typestr, quad, poly, usgn);

  // Based on the modifying character, change the type and width if necessary.
  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);

  SmallString<128> s;

  if (usgn)
    s.push_back('u');

  switch (type) {
    case 'c':
      s += poly ? "poly8" : "int8";
      if (scal)
        break;
      s += quad ? "x16" : "x8";
      break;
    case 's':
      s += poly ? "poly16" : "int16";
      if (scal)
        break;
      s += quad ? "x8" : "x4";
      break;
    case 'i':
      s += "int32";
      if (scal)
        break;
      s += quad ? "x4" : "x2";
      break;
    case 'l':
      s += "int64";
      if (scal)
        break;
      s += quad ? "x2" : "x1";
      break;
    case 'h':
      s += "float16";
      if (scal)
        break;
      s += quad ? "x8" : "x4";
      break;
    case 'f':
      s += "float32";
      if (scal)
        break;
      s += quad ? "x4" : "x2";
      break;
    default:
      throw "unhandled type!";
      break;
  }

  if (mod == '2')
    s += "x2";
  if (mod == '3')
    s += "x3";
  if (mod == '4')
    s += "x4";

  // Append _t, finishing the type string typedef type.
  s += "_t";

  if (cnst)
    s += " const";

  if (pntr)
    s += " *";

  return s.str();
}
Ejemplo n.º 25
0
/// BuiltinTypeString - for a modifier and type, generate the clang
/// BuiltinsARM.def prototype code for the function.  See the top of clang's
/// Builtins.def for a description of the type strings.
static std::string BuiltinTypeString(const char mod, StringRef typestr,
                                     ClassKind ck, bool ret) {
  bool quad = false;
  bool poly = false;
  bool usgn = false;
  bool scal = false;
  bool cnst = false;
  bool pntr = false;

  if (mod == 'v')
    return "v"; // void
  if (mod == 'i')
    return "i"; // int

  // base type to get the type string for.
  char type = ClassifyType(typestr, quad, poly, usgn);

  // Based on the modifying character, change the type and width if necessary.
  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);

  // All pointers are void* pointers.  Change type to 'v' now.
  if (pntr) {
    usgn = false;
    poly = false;
    type = 'v';
  }
  // Treat half-float ('h') types as unsigned short ('s') types.
  if (type == 'h') {
    type = 's';
    usgn = true;
  }
  usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');

  if (scal) {
    SmallString<128> s;

    if (usgn)
      s.push_back('U');
    else if (type == 'c')
      s.push_back('S'); // make chars explicitly signed

    if (type == 'l') // 64-bit long
      s += "LLi";
    else
      s.push_back(type);

    if (cnst)
      s.push_back('C');
    if (pntr)
      s.push_back('*');
    return s.str();
  }

  // Since the return value must be one type, return a vector type of the
  // appropriate width which we will bitcast.  An exception is made for
  // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
  // fashion, storing them to a pointer arg.
  if (ret) {
    if (mod >= '2' && mod <= '4')
      return "vv*"; // void result with void* first argument
    if (mod == 'f' || (ck != ClassB && type == 'f'))
      return quad ? "V4f" : "V2f";
    if (ck != ClassB && type == 's')
      return quad ? "V8s" : "V4s";
    if (ck != ClassB && type == 'i')
      return quad ? "V4i" : "V2i";
    if (ck != ClassB && type == 'l')
      return quad ? "V2LLi" : "V1LLi";

    return quad ? "V16Sc" : "V8Sc";
  }

  // Non-return array types are passed as individual vectors.
  if (mod == '2')
    return quad ? "V16ScV16Sc" : "V8ScV8Sc";
  if (mod == '3')
    return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
  if (mod == '4')
    return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";

  if (mod == 'f' || (ck != ClassB && type == 'f'))
    return quad ? "V4f" : "V2f";
  if (ck != ClassB && type == 's')
    return quad ? "V8s" : "V4s";
  if (ck != ClassB && type == 'i')
    return quad ? "V4i" : "V2i";
  if (ck != ClassB && type == 'l')
    return quad ? "V2LLi" : "V1LLi";

  return quad ? "V16Sc" : "V8Sc";
}
Ejemplo n.º 26
0
static const MCSectionELF *
selectELFSectionForGlobal(MCContext &Ctx, const GlobalValue *GV,
                          SectionKind Kind, Mangler &Mang,
                          const TargetMachine &TM, bool EmitUniqueSection,
                          unsigned Flags, unsigned *NextUniqueID) {
  unsigned EntrySize = 0;
  if (Kind.isMergeableCString()) {
    if (Kind.isMergeable2ByteCString()) {
      EntrySize = 2;
    } else if (Kind.isMergeable4ByteCString()) {
      EntrySize = 4;
    } else {
      EntrySize = 1;
      assert(Kind.isMergeable1ByteCString() && "unknown string width");
    }
  } else if (Kind.isMergeableConst()) {
    if (Kind.isMergeableConst4()) {
      EntrySize = 4;
    } else if (Kind.isMergeableConst8()) {
      EntrySize = 8;
    } else {
      assert(Kind.isMergeableConst16() && "unknown data width");
      EntrySize = 16;
    }
  }

  StringRef Group = "";
  if (const Comdat *C = getELFComdat(GV)) {
    Flags |= ELF::SHF_GROUP;
    Group = C->getName();
  }

  bool UniqueSectionNames = TM.getUniqueSectionNames();
  SmallString<128> Name;
  if (Kind.isMergeableCString()) {
    // We also need alignment here.
    // FIXME: this is getting the alignment of the character, not the
    // alignment of the global!
    unsigned Align =
        TM.getDataLayout()->getPreferredAlignment(cast<GlobalVariable>(GV));

    std::string SizeSpec = ".rodata.str" + utostr(EntrySize) + ".";
    Name = SizeSpec + utostr(Align);
  } else if (Kind.isMergeableConst()) {
    Name = ".rodata.cst";
    Name += utostr(EntrySize);
  } else {
    Name = getSectionPrefixForGlobal(Kind);
  }

  if (EmitUniqueSection && UniqueSectionNames) {
    Name.push_back('.');
    TM.getNameWithPrefix(Name, GV, Mang, true);
  }
  unsigned UniqueID = ~0;
  if (EmitUniqueSection && !UniqueSectionNames) {
    UniqueID = *NextUniqueID;
    (*NextUniqueID)++;
  }
  return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags,
                           EntrySize, Group, UniqueID);
}
Ejemplo n.º 27
0
static MCSectionELF *selectELFSectionForGlobal(
    MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
    const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags,
    unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol) {
  unsigned EntrySize = 0;
  if (Kind.isMergeableCString()) {
    if (Kind.isMergeable2ByteCString()) {
      EntrySize = 2;
    } else if (Kind.isMergeable4ByteCString()) {
      EntrySize = 4;
    } else {
      EntrySize = 1;
      assert(Kind.isMergeable1ByteCString() && "unknown string width");
    }
  } else if (Kind.isMergeableConst()) {
    if (Kind.isMergeableConst4()) {
      EntrySize = 4;
    } else if (Kind.isMergeableConst8()) {
      EntrySize = 8;
    } else if (Kind.isMergeableConst16()) {
      EntrySize = 16;
    } else {
      assert(Kind.isMergeableConst32() && "unknown data width");
      EntrySize = 32;
    }
  }

  StringRef Group = "";
  if (const Comdat *C = getELFComdat(GO)) {
    Flags |= ELF::SHF_GROUP;
    Group = C->getName();
  }

  bool UniqueSectionNames = TM.getUniqueSectionNames();
  SmallString<128> Name;
  if (Kind.isMergeableCString()) {
    // We also need alignment here.
    // FIXME: this is getting the alignment of the character, not the
    // alignment of the global!
    unsigned Align = GO->getParent()->getDataLayout().getPreferredAlignment(
        cast<GlobalVariable>(GO));

    std::string SizeSpec = ".rodata.str" + utostr(EntrySize) + ".";
    Name = SizeSpec + utostr(Align);
  } else if (Kind.isMergeableConst()) {
    Name = ".rodata.cst";
    Name += utostr(EntrySize);
  } else {
    Name = getSectionPrefixForGlobal(Kind);
  }

  if (const auto *F = dyn_cast<Function>(GO)) {
    const auto &OptionalPrefix = F->getSectionPrefix();
    if (OptionalPrefix)
      Name += *OptionalPrefix;
  }

  if (EmitUniqueSection && UniqueSectionNames) {
    Name.push_back('.');
    TM.getNameWithPrefix(Name, GO, Mang, true);
  }
  unsigned UniqueID = MCContext::GenericSectionID;
  if (EmitUniqueSection && !UniqueSectionNames) {
    UniqueID = *NextUniqueID;
    (*NextUniqueID)++;
  }
  // Use 0 as the unique ID for execute-only text
  if (Kind.isExecuteOnly())
    UniqueID = 0;
  return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags,
                           EntrySize, Group, UniqueID, AssociatedSymbol);
}
static CXCodeCompleteResults *
clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename,
                          unsigned complete_line, unsigned complete_column,
                          ArrayRef<CXUnsavedFile> unsaved_files,
                          unsigned options) {
  bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments;
  bool SkipPreamble = options & CXCodeComplete_SkipPreamble;
  bool IncludeFixIts = options & CXCodeComplete_IncludeCompletionsWithFixIts;

#ifdef UDP_CODE_COMPLETION_LOGGER
#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
  const llvm::TimeRecord &StartTime =  llvm::TimeRecord::getCurrentTime();
#endif
#endif
  bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr;

  if (cxtu::isNotUsableTU(TU)) {
    LOG_BAD_TU(TU);
    return nullptr;
  }

  ASTUnit *AST = cxtu::getASTUnit(TU);
  if (!AST)
    return nullptr;

  CIndexer *CXXIdx = TU->CIdx;
  if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
    setThreadBackgroundPriority();

  ASTUnit::ConcurrencyCheck Check(*AST);

  // Perform the remapping of source files.
  SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;

  for (auto &UF : unsaved_files) {
    std::unique_ptr<llvm::MemoryBuffer> MB =
        llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
    RemappedFiles.push_back(std::make_pair(UF.Filename, MB.release()));
  }

  if (EnableLogging) {
    // FIXME: Add logging.
  }

  // Parse the resulting source file to find code-completion results.
  AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults(
      &AST->getFileManager());
  Results->Results = nullptr;
  Results->NumResults = 0;
  
  // Create a code-completion consumer to capture the results.
  CodeCompleteOptions Opts;
  Opts.IncludeBriefComments = IncludeBriefComments;
  Opts.LoadExternal = !SkipPreamble;
  Opts.IncludeFixIts = IncludeFixIts;
  CaptureCompletionResults Capture(Opts, *Results, &TU);

  // Perform completion.
  std::vector<const char *> CArgs;
  for (const auto &Arg : TU->Arguments)
    CArgs.push_back(Arg.c_str());
  std::string CompletionInvocation =
      llvm::formatv("-code-completion-at={0}:{1}:{2}", complete_filename,
                    complete_line, complete_column)
          .str();
  LibclangInvocationReporter InvocationReporter(
      *CXXIdx, LibclangInvocationReporter::OperationKind::CompletionOperation,
      TU->ParsingOptions, CArgs, CompletionInvocation, unsaved_files);
  AST->CodeComplete(complete_filename, complete_line, complete_column,
                    RemappedFiles, (options & CXCodeComplete_IncludeMacros),
                    (options & CXCodeComplete_IncludeCodePatterns),
                    IncludeBriefComments, Capture,
                    CXXIdx->getPCHContainerOperations(), *Results->Diag,
                    Results->LangOpts, *Results->SourceMgr, *Results->FileMgr,
                    Results->Diagnostics, Results->TemporaryBuffers);

  Results->DiagnosticsWrappers.resize(Results->Diagnostics.size());

  // Keep a reference to the allocator used for cached global completions, so
  // that we can be sure that the memory used by our code completion strings
  // doesn't get freed due to subsequent reparses (while the code completion
  // results are still active).
  Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator();

  

#ifdef UDP_CODE_COMPLETION_LOGGER
#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
  const llvm::TimeRecord &EndTime =  llvm::TimeRecord::getCurrentTime();
  SmallString<256> LogResult;
  llvm::raw_svector_ostream os(LogResult);

  // Figure out the language and whether or not it uses PCH.
  const char *lang = 0;
  bool usesPCH = false;

  for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
       I != E; ++I) {
    if (*I == 0)
      continue;
    if (strcmp(*I, "-x") == 0) {
      if (I + 1 != E) {
        lang = *(++I);
        continue;
      }
    }
    else if (strcmp(*I, "-include") == 0) {
      if (I+1 != E) {
        const char *arg = *(++I);
        SmallString<512> pchName;
        {
          llvm::raw_svector_ostream os(pchName);
          os << arg << ".pth";
        }
        pchName.push_back('\0');
        struct stat stat_results;
        if (stat(pchName.str().c_str(), &stat_results) == 0)
          usesPCH = true;
        continue;
      }
    }
  }

  os << "{ ";
  os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
  os << ", \"numRes\": " << Results->NumResults;
  os << ", \"diags\": " << Results->Diagnostics.size();
  os << ", \"pch\": " << (usesPCH ? "true" : "false");
  os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
  const char *name = getlogin();
  os << ", \"user\": \"" << (name ? name : "unknown") << '"';
  os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
  os << " }";

  StringRef res = os.str();
  if (res.size() > 0) {
    do {
      // Setup the UDP socket.
      struct sockaddr_in servaddr;
      bzero(&servaddr, sizeof(servaddr));
      servaddr.sin_family = AF_INET;
      servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
      if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
                    &servaddr.sin_addr) <= 0)
        break;

      int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
      if (sockfd < 0)
        break;

      sendto(sockfd, res.data(), res.size(), 0,
             (struct sockaddr *)&servaddr, sizeof(servaddr));
      close(sockfd);
    }
    while (false);
  }
#endif
#endif
  return Results;
}
Ejemplo n.º 29
0
/// ComputeSymbolTable - Compute the symbol table data
///
/// \param StringTable [out] - The string table data.
/// \param StringIndexMap [out] - Map from symbol names to offsets in the
/// string table.
void MachObjectWriter::
ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
                   std::vector<MachSymbolData> &LocalSymbolData,
                   std::vector<MachSymbolData> &ExternalSymbolData,
                   std::vector<MachSymbolData> &UndefinedSymbolData) {
  // Build section lookup table.
  DenseMap<const MCSection*, uint8_t> SectionIndexMap;
  unsigned Index = 1;
  for (MCAssembler::iterator it = Asm.begin(),
         ie = Asm.end(); it != ie; ++it, ++Index)
    SectionIndexMap[&it->getSection()] = Index;
  assert(Index <= 256 && "Too many sections!");

  // Index 0 is always the empty string.
  StringMap<uint64_t> StringIndexMap;
  StringTable += '\x00';

  // Build the symbol arrays and the string table, but only for non-local
  // symbols.
  //
  // The particular order that we collect the symbols and create the string
  // table, then sort the symbols is chosen to match 'as'. Even though it
  // doesn't matter for correctness, this is important for letting us diff .o
  // files.
  for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
         ie = Asm.symbol_end(); it != ie; ++it) {
    const MCSymbol &Symbol = it->getSymbol();

    // Ignore non-linker visible symbols.
    if (!Asm.isSymbolLinkerVisible(it->getSymbol()))
      continue;

    if (!it->isExternal() && !Symbol.isUndefined())
      continue;

    uint64_t &Entry = StringIndexMap[Symbol.getName()];
    if (!Entry) {
      Entry = StringTable.size();
      StringTable += Symbol.getName();
      StringTable += '\x00';
    }

    MachSymbolData MSD;
    MSD.SymbolData = it;
    MSD.StringIndex = Entry;

    if (Symbol.isUndefined()) {
      MSD.SectionIndex = 0;
      UndefinedSymbolData.push_back(MSD);
    } else if (Symbol.isAbsolute()) {
      MSD.SectionIndex = 0;
      ExternalSymbolData.push_back(MSD);
    } else {
      MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
      assert(MSD.SectionIndex && "Invalid section index!");
      ExternalSymbolData.push_back(MSD);
    }
  }

  // Now add the data for local symbols.
  for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
         ie = Asm.symbol_end(); it != ie; ++it) {
    const MCSymbol &Symbol = it->getSymbol();

    // Ignore non-linker visible symbols.
    if (!Asm.isSymbolLinkerVisible(it->getSymbol()))
      continue;

    if (it->isExternal() || Symbol.isUndefined())
      continue;

    uint64_t &Entry = StringIndexMap[Symbol.getName()];
    if (!Entry) {
      Entry = StringTable.size();
      StringTable += Symbol.getName();
      StringTable += '\x00';
    }

    MachSymbolData MSD;
    MSD.SymbolData = it;
    MSD.StringIndex = Entry;

    if (Symbol.isAbsolute()) {
      MSD.SectionIndex = 0;
      LocalSymbolData.push_back(MSD);
    } else {
      MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
      assert(MSD.SectionIndex && "Invalid section index!");
      LocalSymbolData.push_back(MSD);
    }
  }

  // External and undefined symbols are required to be in lexicographic order.
  std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
  std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());

  // Set the symbol indices.
  Index = 0;
  for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
    LocalSymbolData[i].SymbolData->setIndex(Index++);
  for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
    ExternalSymbolData[i].SymbolData->setIndex(Index++);
  for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
    UndefinedSymbolData[i].SymbolData->setIndex(Index++);

  // The string table is padded to a multiple of 4.
  while (StringTable.size() % 4)
    StringTable += '\x00';
}
Ejemplo n.º 30
0
/// DoFrameworkLookup - Do a lookup of the specified file in the current
/// DirectoryLookup, which is a framework directory.
const FileEntry *DirectoryLookup::DoFrameworkLookup(
    StringRef Filename,
    HeaderSearch &HS,
    SmallVectorImpl<char> *SearchPath,
    SmallVectorImpl<char> *RelativePath,
    Module **SuggestedModule,
    bool &InUserSpecifiedSystemFramework) const
{
  FileManager &FileMgr = HS.getFileMgr();

  // Framework names must have a '/' in the filename.
  size_t SlashPos = Filename.find('/');
  if (SlashPos == StringRef::npos) return 0;

  // Find out if this is the home for the specified framework, by checking
  // HeaderSearch.  Possible answers are yes/no and unknown.
  HeaderSearch::FrameworkCacheEntry &CacheEntry =
    HS.LookupFrameworkCache(Filename.substr(0, SlashPos));

  // If it is known and in some other directory, fail.
  if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir())
    return 0;

  // Otherwise, construct the path to this framework dir.

  // FrameworkName = "/System/Library/Frameworks/"
  SmallString<1024> FrameworkName;
  FrameworkName += getFrameworkDir()->getName();
  if (FrameworkName.empty() || FrameworkName.back() != '/')
    FrameworkName.push_back('/');

  // FrameworkName = "/System/Library/Frameworks/Cocoa"
  StringRef ModuleName(Filename.begin(), SlashPos);
  FrameworkName += ModuleName;

  // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
  FrameworkName += ".framework/";

  // If the cache entry was unresolved, populate it now.
  if (CacheEntry.Directory == 0) {
    HS.IncrementFrameworkLookupCount();

    // If the framework dir doesn't exist, we fail.
    const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
    if (Dir == 0) return 0;

    // Otherwise, if it does, remember that this is the right direntry for this
    // framework.
    CacheEntry.Directory = getFrameworkDir();

    // If this is a user search directory, check if the framework has been
    // user-specified as a system framework.
    if (getDirCharacteristic() == SrcMgr::C_User) {
      SmallString<1024> SystemFrameworkMarker(FrameworkName);
      SystemFrameworkMarker += ".system_framework";
      if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) {
        CacheEntry.IsUserSpecifiedSystemFramework = true;
      }
    }
  }

  // Set the 'user-specified system framework' flag.
  InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;

  if (RelativePath != NULL) {
    RelativePath->clear();
    RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
  }

  // If we're allowed to look for modules, try to load or create the module
  // corresponding to this framework.
  Module *Module = 0;
  if (SuggestedModule) {
    if (const DirectoryEntry *FrameworkDir
                                        = FileMgr.getDirectory(FrameworkName)) {
      bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
      Module = HS.loadFrameworkModule(ModuleName, FrameworkDir, IsSystem);
    }
  }
  
  // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
  unsigned OrigSize = FrameworkName.size();

  FrameworkName += "Headers/";

  if (SearchPath != NULL) {
    SearchPath->clear();
    // Without trailing '/'.
    SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
  }

  // Determine whether this is the module we're building or not.
  bool AutomaticImport = Module;  
  FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
  if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(),
                                            /*openFile=*/!AutomaticImport)) {
    if (AutomaticImport)
      *SuggestedModule = HS.findModuleForHeader(FE);
    return FE;
  }

  // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
  const char *Private = "Private";
  FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
                       Private+strlen(Private));
  if (SearchPath != NULL)
    SearchPath->insert(SearchPath->begin()+OrigSize, Private,
                       Private+strlen(Private));

  const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), 
                                        /*openFile=*/!AutomaticImport);
  if (FE && AutomaticImport)
    *SuggestedModule = HS.findModuleForHeader(FE);
  return FE;
}