コード例 #1
0
ファイル: X86WinEHState.cpp プロジェクト: midwinter1993/llvm
bool WinEHStatePass::runOnFunction(Function &F) {
  // If this is an outlined handler, don't do anything. We'll do state insertion
  // for it in the parent.
  StringRef WinEHParentName =
      F.getFnAttribute("wineh-parent").getValueAsString();
  if (WinEHParentName != F.getName() && !WinEHParentName.empty())
    return false;

  // Check the personality. Do nothing if this is not an MSVC personality.
  if (!F.hasPersonalityFn())
    return false;
  PersonalityFn =
      dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
  if (!PersonalityFn)
    return false;
  Personality = classifyEHPersonality(PersonalityFn);
  if (!isMSVCEHPersonality(Personality))
    return false;

  // Skip this function if there are no EH pads and we aren't using IR-level
  // outlining.
  if (WinEHParentName.empty()) {
    bool HasPads = false;
    for (BasicBlock &BB : F) {
      if (BB.isEHPad()) {
        HasPads = true;
        break;
      }
    }
    if (!HasPads)
      return false;
  }

  // Disable frame pointer elimination in this function.
  // FIXME: Do the nested handlers need to keep the parent ebp in ebp, or can we
  // use an arbitrary register?
  F.addFnAttr("no-frame-pointer-elim", "true");

  emitExceptionRegistrationRecord(&F);

  auto *MMI = getAnalysisIfAvailable<MachineModuleInfo>();
  // If MMI is null, create our own WinEHFuncInfo.  This only happens in opt
  // tests.
  std::unique_ptr<WinEHFuncInfo> FuncInfoPtr;
  if (!MMI)
    FuncInfoPtr.reset(new WinEHFuncInfo());
  WinEHFuncInfo &FuncInfo =
      *(MMI ? &MMI->getWinEHFuncInfo(&F) : FuncInfoPtr.get());

  FuncInfo.EHRegNode = RegNode;

  switch (Personality) {
  default: llvm_unreachable("unexpected personality function");
  case EHPersonality::MSVC_CXX:
    addCXXStateStores(F, FuncInfo);
    break;
  case EHPersonality::MSVC_X86SEH:
    addSEHStateStores(F, FuncInfo);
    break;
  }

  // Reset per-function state.
  PersonalityFn = nullptr;
  Personality = EHPersonality::Unknown;
  return true;
}
コード例 #2
0
ファイル: IRGen.cpp プロジェクト: wsyxyxs/swift
/// Run the LLVM passes. In multi-threaded compilation this will be done for
/// multiple LLVM modules in parallel.
static bool performLLVM(IRGenOptions &Opts, DiagnosticEngine &Diags,
                        llvm::sys::Mutex *DiagMutex,
                        llvm::Module *Module,
                        llvm::TargetMachine *TargetMachine,
                        StringRef OutputFilename) {
  llvm::SmallString<0> Buffer;
  std::unique_ptr<raw_pwrite_stream> RawOS;
  if (!OutputFilename.empty()) {
    // Try to open the output file.  Clobbering an existing file is fine.
    // Open in binary mode if we're doing binary output.
    llvm::sys::fs::OpenFlags OSFlags = llvm::sys::fs::F_None;
    std::error_code EC;
    auto *FDOS = new raw_fd_ostream(OutputFilename, EC, OSFlags);
    RawOS.reset(FDOS);
    if (FDOS->has_error() || EC) {
      if (DiagMutex)
        DiagMutex->lock();
      Diags.diagnose(SourceLoc(), diag::error_opening_output,
                     OutputFilename, EC.message());
      if (DiagMutex)
        DiagMutex->unlock();
      FDOS->clear_error();
      return true;
    }

    // Most output kinds want a formatted output stream.  It's not clear
    // why writing an object file does.
    //if (Opts.OutputKind != IRGenOutputKind::LLVMBitcode)
    //  FormattedOS.setStream(*RawOS, formatted_raw_ostream::PRESERVE_STREAM);
  } else {
    RawOS.reset(new raw_svector_ostream(Buffer));
  }

  performLLVMOptimizations(Opts, Module, TargetMachine);

  legacy::PassManager EmitPasses;

  // Set up the final emission passes.
  switch (Opts.OutputKind) {
  case IRGenOutputKind::Module:
    break;
  case IRGenOutputKind::LLVMAssembly:
    EmitPasses.add(createPrintModulePass(*RawOS));
    break;
  case IRGenOutputKind::LLVMBitcode:
    EmitPasses.add(createBitcodeWriterPass(*RawOS));
    break;
  case IRGenOutputKind::NativeAssembly:
  case IRGenOutputKind::ObjectFile: {
    llvm::TargetMachine::CodeGenFileType FileType;
    FileType = (Opts.OutputKind == IRGenOutputKind::NativeAssembly
                  ? llvm::TargetMachine::CGFT_AssemblyFile
                  : llvm::TargetMachine::CGFT_ObjectFile);

    EmitPasses.add(createTargetTransformInfoWrapperPass(
        TargetMachine->getTargetIRAnalysis()));

    // Make sure we do ARC contraction under optimization.  We don't
    // rely on any other LLVM ARC transformations, but we do need ARC
    // contraction to add the objc_retainAutoreleasedReturnValue
    // assembly markers.
    if (Opts.Optimize)
      EmitPasses.add(createObjCARCContractPass());

    bool fail = TargetMachine->addPassesToEmitFile(EmitPasses, *RawOS,
                                                   FileType, !Opts.Verify);
    if (fail) {
      if (DiagMutex)
        DiagMutex->lock();
      Diags.diagnose(SourceLoc(), diag::error_codegen_init_fail);
      if (DiagMutex)
        DiagMutex->unlock();
      return true;
    }
    break;
  }
  }

  {
    SharedTimer timer("LLVM output");
    EmitPasses.run(*Module);
  }
  return false;
}
コード例 #3
0
ファイル: StringRef.cpp プロジェクト: 0x00evil/llvm
// Implementation of StringRef hashing.
hash_code llvm::hash_value(StringRef S) {
  return hash_combine_range(S.begin(), S.end());
}
コード例 #4
0
ファイル: Archive.cpp プロジェクト: clockmaker002/llvm
Archive::Archive(MemoryBufferRef Source, Error &Err)
    : Binary(Binary::ID_Archive, Source) {
  ErrorAsOutParameter ErrAsOutParam(&Err);
  StringRef Buffer = Data.getBuffer();
  // Check for sufficient magic.
  if (Buffer.startswith(ThinMagic)) {
    IsThin = true;
  } else if (Buffer.startswith(Magic)) {
    IsThin = false;
  } else {
    Err = make_error<GenericBinaryError>("File too small to be an archive",
                                         object_error::invalid_file_type);
    return;
  }

  // Get the special members.
  child_iterator I = child_begin(Err, false);
  if (Err)
    return;
  child_iterator E = child_end();

  // This is at least a valid empty archive. Since an empty archive is the
  // same in all formats, just claim it to be gnu to make sure Format is
  // initialized.
  Format = K_GNU;

  if (I == E) {
    Err = Error::success();
    return;
  }
  const Child *C = &*I;

  auto Increment = [&]() {
    ++I;
    if (Err)
      return true;
    C = &*I;
    return false;
  };

  StringRef Name = C->getRawName();

  // Below is the pattern that is used to figure out the archive format
  // GNU archive format
  //  First member : / (may exist, if it exists, points to the symbol table )
  //  Second member : // (may exist, if it exists, points to the string table)
  //  Note : The string table is used if the filename exceeds 15 characters
  // BSD archive format
  //  First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table)
  //  There is no string table, if the filename exceeds 15 characters or has a
  //  embedded space, the filename has #1/<size>, The size represents the size
  //  of the filename that needs to be read after the archive header
  // COFF archive format
  //  First member : /
  //  Second member : / (provides a directory of symbols)
  //  Third member : // (may exist, if it exists, contains the string table)
  //  Note: Microsoft PE/COFF Spec 8.3 says that the third member is present
  //  even if the string table is empty. However, lib.exe does not in fact
  //  seem to create the third member if there's no member whose filename
  //  exceeds 15 characters. So the third member is optional.

  if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {
    if (Name == "__.SYMDEF")
      Format = K_BSD;
    else // Name == "__.SYMDEF_64"
      Format = K_DARWIN64;
    // We know that the symbol table is not an external file, so we just assert
    // there is no error.
    SymbolTable = *C->getBuffer();
    if (Increment())
      return;
    setFirstRegular(*C);

    Err = Error::success();
    return;
  }

  if (Name.startswith("#1/")) {
    Format = K_BSD;
    // We know this is BSD, so getName will work since there is no string table.
    ErrorOr<StringRef> NameOrErr = C->getName();
    if (auto ec = NameOrErr.getError()) {
      Err = errorCodeToError(ec);
      return;
    }
    Name = NameOrErr.get();
    if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
      // We know that the symbol table is not an external file, so we just
      // assert there is no error.
      SymbolTable = *C->getBuffer();
      if (Increment())
        return;
    }
    else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {
      Format = K_DARWIN64;
      // We know that the symbol table is not an external file, so we just
      // assert there is no error.
      SymbolTable = *C->getBuffer();
      if (Increment())
        return;
    }
    setFirstRegular(*C);
    return;
  }

  // MIPS 64-bit ELF archives use a special format of a symbol table.
  // This format is marked by `ar_name` field equals to "/SYM64/".
  // For detailed description see page 96 in the following document:
  // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf

  bool has64SymTable = false;
  if (Name == "/" || Name == "/SYM64/") {
    // We know that the symbol table is not an external file, so we just assert
    // there is no error.
    SymbolTable = *C->getBuffer();
    if (Name == "/SYM64/")
      has64SymTable = true;

    if (Increment())
      return;
    if (I == E) {
      Err = Error::success();
      return;
    }
    Name = C->getRawName();
  }

  if (Name == "//") {
    Format = has64SymTable ? K_MIPS64 : K_GNU;
    // The string table is never an external member, so we just assert on the
    // ErrorOr.
    StringTable = *C->getBuffer();
    if (Increment())
      return;
    setFirstRegular(*C);
    Err = Error::success();
    return;
  }

  if (Name[0] != '/') {
    Format = has64SymTable ? K_MIPS64 : K_GNU;
    setFirstRegular(*C);
    Err = Error::success();
    return;
  }

  if (Name != "/") {
    Err = errorCodeToError(object_error::parse_failed);
    return;
  }

  Format = K_COFF;
  // We know that the symbol table is not an external file, so we just assert
  // there is no error.
  SymbolTable = *C->getBuffer();

  if (Increment())
    return;

  if (I == E) {
    setFirstRegular(*C);
    Err = Error::success();
    return;
  }

  Name = C->getRawName();

  if (Name == "//") {
    // The string table is never an external member, so we just assert on the
    // ErrorOr.
    StringTable = *C->getBuffer();
    if (Increment())
      return;
  }

  setFirstRegular(*C);
  Err = Error::success();
}
コード例 #5
0
ファイル: Value.cpp プロジェクト: MessiahAndrw/Perception
void Value::setName(const Twine &NewName) {
  assert(SubclassID != MDStringVal &&
         "Cannot set the name of MDString with this method!");

  // Fast path for common IRBuilder case of setName("") when there is no name.
  if (NewName.isTriviallyEmpty() && !hasName())
    return;

  SmallString<256> NameData;
  StringRef NameRef = NewName.toStringRef(NameData);
  assert(NameRef.find_first_of(0) == StringRef::npos &&
         "Null bytes are not allowed in names");

  // Name isn't changing?
  if (getName() == NameRef)
    return;

  assert(!getType()->isVoidTy() && "Cannot assign a name to void values!");

  // Get the symbol table to update for this object.
  ValueSymbolTable *ST;
  if (getSymTab(this, ST))
    return;  // Cannot set a name on this value (e.g. constant).

  if (Function *F = dyn_cast<Function>(this))
    getContext().pImpl->IntrinsicIDCache.erase(F);

  if (!ST) { // No symbol table to update?  Just do the change.
    if (NameRef.empty()) {
      // Free the name for this value.
      Name->Destroy();
      Name = nullptr;
      return;
    }

    if (Name)
      Name->Destroy();

    // NOTE: Could optimize for the case the name is shrinking to not deallocate
    // then reallocated.

    // Create the new name.
    Name = ValueName::Create(NameRef);
    Name->setValue(this);
    return;
  }

  // NOTE: Could optimize for the case the name is shrinking to not deallocate
  // then reallocated.
  if (hasName()) {
    // Remove old name.
    ST->removeValueName(Name);
    Name->Destroy();
    Name = nullptr;

    if (NameRef.empty())
      return;
  }

  // Name is changing to something new.
  Name = ST->createValueName(NameRef, this);
}
コード例 #6
0
/// Determine the prefix to be stripped from the names of the enum constants
/// within the given enum.
void EnumInfo::determineConstantNamePrefix(ASTContext &ctx,
                                           const clang::EnumDecl *decl) {
  switch (getKind()) {
  case EnumKind::Enum:
  case EnumKind::Options:
    // Enums are mapped to Swift enums, Options to Swift option sets, both
    // of which attempt prefix-stripping.
    break;

  case EnumKind::Constants:
  case EnumKind::Unknown:
    // Nothing to do.
    return;
  }

  // If there are no enumers, there is no prefix to compute.
  auto ec = decl->enumerator_begin(), ecEnd = decl->enumerator_end();
  if (ec == ecEnd)
    return;

  // Determine whether the given enumerator is non-deprecated and has no
  // specifically-provided name.
  auto isNonDeprecatedWithoutCustomName = [](
      const clang::EnumConstantDecl *elem) -> bool {
    if (elem->hasAttr<clang::SwiftNameAttr>())
      return false;

    clang::VersionTuple maxVersion{~0U, ~0U, ~0U};
    switch (elem->getAvailability(nullptr, maxVersion)) {
    case clang::AR_Available:
    case clang::AR_NotYetIntroduced:
      for (auto attr : elem->attrs()) {
        if (auto annotate = dyn_cast<clang::AnnotateAttr>(attr)) {
          if (annotate->getAnnotation() == "swift1_unavailable")
            return false;
        }
        if (auto avail = dyn_cast<clang::AvailabilityAttr>(attr)) {
          if (avail->getPlatform()->getName() == "swift")
            return false;
        }
      }
      return true;

    case clang::AR_Deprecated:
    case clang::AR_Unavailable:
      return false;
    }
  };

  // Move to the first non-deprecated enumerator, or non-swift_name'd
  // enumerator, if present.
  auto firstNonDeprecated =
      std::find_if(ec, ecEnd, isNonDeprecatedWithoutCustomName);
  bool hasNonDeprecated = (firstNonDeprecated != ecEnd);
  if (hasNonDeprecated) {
    ec = firstNonDeprecated;
  } else {
    // Advance to the first case without a custom name, deprecated or not.
    while (ec != ecEnd && (*ec)->hasAttr<clang::SwiftNameAttr>())
      ++ec;
    if (ec == ecEnd) {
      return;
    }
  }

  // Compute the common prefix.
  StringRef commonPrefix = (*ec)->getName();
  bool followedByNonIdentifier = false;
  for (++ec; ec != ecEnd; ++ec) {
    // Skip deprecated or swift_name'd enumerators.
    const clang::EnumConstantDecl *elem = *ec;
    if (hasNonDeprecated) {
      if (!isNonDeprecatedWithoutCustomName(elem))
        continue;
    } else {
      if (elem->hasAttr<clang::SwiftNameAttr>())
        continue;
    }

    commonPrefix = getCommonWordPrefix(commonPrefix, elem->getName(),
                                       followedByNonIdentifier);
    if (commonPrefix.empty())
      break;
  }

  if (!commonPrefix.empty()) {
    StringRef checkPrefix = commonPrefix;

    // Account for the 'kConstant' naming convention on enumerators.
    if (checkPrefix[0] == 'k') {
      bool canDropK;
      if (checkPrefix.size() >= 2)
        canDropK = clang::isUppercase(checkPrefix[1]);
      else
        canDropK = !followedByNonIdentifier;

      if (canDropK)
        checkPrefix = checkPrefix.drop_front();
    }

    // Don't use importFullName() here, we want to ignore the swift_name
    // and swift_private attributes.
    StringRef enumNameStr = decl->getName();
    StringRef commonWithEnum = getCommonPluralPrefix(checkPrefix, enumNameStr);
    size_t delta = commonPrefix.size() - checkPrefix.size();

    // Account for the 'EnumName_Constant' convention on enumerators.
    if (commonWithEnum.size() < checkPrefix.size() &&
        checkPrefix[commonWithEnum.size()] == '_' && !followedByNonIdentifier) {
      delta += 1;
    }

    commonPrefix = commonPrefix.slice(0, commonWithEnum.size() + delta);
  }

  constantNamePrefix = ctx.AllocateCopy(commonPrefix);
}
コード例 #7
0
ファイル: Archive.cpp プロジェクト: clockmaker002/llvm
Archive::Child::Child(const Archive *Parent, StringRef Data,
                      uint16_t StartOfFile)
    : Parent(Parent), Header(Parent, Data.data(), Data.size(), nullptr),
      Data(Data), StartOfFile(StartOfFile) {
}
コード例 #8
0
// Load single header list and dependencies.
std::error_code ModularizeUtilities::loadSingleHeaderListsAndDependencies(
    llvm::StringRef InputPath) {

  // By default, use the path component of the list file name.
  SmallString<256> HeaderDirectory(InputPath);
  llvm::sys::path::remove_filename(HeaderDirectory);
  SmallString<256> CurrentDirectory;
  llvm::sys::fs::current_path(CurrentDirectory);

  // Get the prefix if we have one.
  if (HeaderPrefix.size() != 0)
    HeaderDirectory = HeaderPrefix;

  // Read the header list file into a buffer.
  ErrorOr<std::unique_ptr<MemoryBuffer>> listBuffer =
    MemoryBuffer::getFile(InputPath);
  if (std::error_code EC = listBuffer.getError())
    return EC;

  // Parse the header list into strings.
  SmallVector<StringRef, 32> Strings;
  listBuffer.get()->getBuffer().split(Strings, "\n", -1, false);

  // Collect the header file names from the string list.
  for (SmallVectorImpl<StringRef>::iterator I = Strings.begin(),
    E = Strings.end();
    I != E; ++I) {
    StringRef Line = I->trim();
    // Ignore comments and empty lines.
    if (Line.empty() || (Line[0] == '#'))
      continue;
    std::pair<StringRef, StringRef> TargetAndDependents = Line.split(':');
    SmallString<256> HeaderFileName;
    // Prepend header file name prefix if it's not absolute.
    if (llvm::sys::path::is_absolute(TargetAndDependents.first))
      llvm::sys::path::native(TargetAndDependents.first, HeaderFileName);
    else {
      if (HeaderDirectory.size() != 0)
        HeaderFileName = HeaderDirectory;
      else
        HeaderFileName = CurrentDirectory;
      llvm::sys::path::append(HeaderFileName, TargetAndDependents.first);
      llvm::sys::path::native(HeaderFileName);
    }
    // Handle optional dependencies.
    DependentsVector Dependents;
    SmallVector<StringRef, 4> DependentsList;
    TargetAndDependents.second.split(DependentsList, " ", -1, false);
    int Count = DependentsList.size();
    for (int Index = 0; Index < Count; ++Index) {
      SmallString<256> Dependent;
      if (llvm::sys::path::is_absolute(DependentsList[Index]))
        Dependent = DependentsList[Index];
      else {
        if (HeaderDirectory.size() != 0)
          Dependent = HeaderDirectory;
        else
          Dependent = CurrentDirectory;
        llvm::sys::path::append(Dependent, DependentsList[Index]);
      }
      llvm::sys::path::native(Dependent);
      Dependents.push_back(getCanonicalPath(Dependent.str()));
    }
    // Get canonical form.
    HeaderFileName = getCanonicalPath(HeaderFileName);
    // Save the resulting header file path and dependencies.
    HeaderFileNames.push_back(HeaderFileName.str());
    Dependencies[HeaderFileName.str()] = Dependents;
  }
  return std::error_code();
}
コード例 #9
0
static StringRef StripTrailingDots(StringRef s) {
    for (StringRef::size_type i = s.size(); i != 0; --i)
        if (s[i - 1] != '.')
            return s.substr(0, i);
    return "";
}
コード例 #10
0
ファイル: MCContext.cpp プロジェクト: AAZemlyanukhin/freebsd
/// GetDwarfFile - takes a file name an number to place in the dwarf file and
/// directory tables.  If the file number has already been allocated it is an
/// error and zero is returned and the client reports the error, else the
/// allocated file number is returned.  The file numbers may be in any order.
unsigned MCContext::GetDwarfFile(StringRef Directory, StringRef FileName,
                                 unsigned FileNumber, unsigned CUID) {
  // TODO: a FileNumber of zero says to use the next available file number.
  // Note: in GenericAsmParser::ParseDirectiveFile() FileNumber was checked
  // to not be less than one.  This needs to be change to be not less than zero.

  SmallVectorImpl<MCDwarfFile *>& MCDwarfFiles = MCDwarfFilesCUMap[CUID];
  SmallVectorImpl<StringRef>& MCDwarfDirs = MCDwarfDirsCUMap[CUID];
  // Make space for this FileNumber in the MCDwarfFiles vector if needed.
  if (FileNumber >= MCDwarfFiles.size()) {
    MCDwarfFiles.resize(FileNumber + 1);
  } else {
    MCDwarfFile *&ExistingFile = MCDwarfFiles[FileNumber];
    if (ExistingFile)
      // It is an error to use see the same number more than once.
      return 0;
  }

  // Get the new MCDwarfFile slot for this FileNumber.
  MCDwarfFile *&File = MCDwarfFiles[FileNumber];

  if (Directory.empty()) {
    // Separate the directory part from the basename of the FileName.
    StringRef tFileName = sys::path::filename(FileName);
    if (!tFileName.empty()) {
      Directory = sys::path::parent_path(FileName);
      if (!Directory.empty())
        FileName = tFileName;
    }
  }

  // Find or make a entry in the MCDwarfDirs vector for this Directory.
  // Capture directory name.
  unsigned DirIndex;
  if (Directory.empty()) {
    // For FileNames with no directories a DirIndex of 0 is used.
    DirIndex = 0;
  } else {
    DirIndex = 0;
    for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) {
      if (Directory == MCDwarfDirs[DirIndex])
        break;
    }
    if (DirIndex >= MCDwarfDirs.size()) {
      char *Buf = static_cast<char *>(Allocate(Directory.size()));
      memcpy(Buf, Directory.data(), Directory.size());
      MCDwarfDirs.push_back(StringRef(Buf, Directory.size()));
    }
    // The DirIndex is one based, as DirIndex of 0 is used for FileNames with
    // no directories.  MCDwarfDirs[] is unlike MCDwarfFiles[] in that the
    // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames
    // are stored at MCDwarfFiles[FileNumber].Name .
    DirIndex++;
  }

  // Now make the MCDwarfFile entry and place it in the slot in the MCDwarfFiles
  // vector.
  char *Buf = static_cast<char *>(Allocate(FileName.size()));
  memcpy(Buf, FileName.data(), FileName.size());
  File = new (*this) MCDwarfFile(StringRef(Buf, FileName.size()), DirIndex);

  // return the allocated FileNumber.
  return FileNumber;
}
コード例 #11
0
/// Interpreting the given string using the normal CamelCase
/// conventions, determine whether the given string starts with the
/// given "word", which is assumed to end in a lowercase letter.
static bool startsWithWord(StringRef name, StringRef word) {
  if (name.size() < word.size()) return false;
  return ((name.size() == word.size() || !isLowercase(name[word.size()])) &&
          name.startswith(word));
}
コード例 #12
0
/// emitModuleFlags - Perform code emission for module flags.
void TargetLoweringObjectFileMachO::emitModuleFlags(
    MCStreamer &Streamer, ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
    const TargetMachine &TM) const {
  unsigned VersionVal = 0;
  unsigned ImageInfoFlags = 0;
  MDNode *LinkerOptions = nullptr;
  StringRef SectionVal;

  for (const auto &MFE : ModuleFlags) {
    // Ignore flags with 'Require' behavior.
    if (MFE.Behavior == Module::Require)
      continue;

    StringRef Key = MFE.Key->getString();
    Metadata *Val = MFE.Val;

    if (Key == "Objective-C Image Info Version") {
      VersionVal = mdconst::extract<ConstantInt>(Val)->getZExtValue();
    } else if (Key == "Objective-C Garbage Collection" ||
               Key == "Objective-C GC Only" ||
               Key == "Objective-C Is Simulated" ||
               Key == "Objective-C Class Properties" ||
               Key == "Objective-C Image Swift Version") {
      ImageInfoFlags |= mdconst::extract<ConstantInt>(Val)->getZExtValue();
    } else if (Key == "Objective-C Image Info Section") {
      SectionVal = cast<MDString>(Val)->getString();
    } else if (Key == "Linker Options") {
      LinkerOptions = cast<MDNode>(Val);
    }
  }

  // Emit the linker options if present.
  if (LinkerOptions) {
    for (const auto &Option : LinkerOptions->operands()) {
      SmallVector<std::string, 4> StrOptions;
      for (const auto &Piece : cast<MDNode>(Option)->operands())
        StrOptions.push_back(cast<MDString>(Piece)->getString());
      Streamer.EmitLinkerOptions(StrOptions);
    }
  }

  // The section is mandatory. If we don't have it, then we don't have GC info.
  if (SectionVal.empty()) return;

  StringRef Segment, Section;
  unsigned TAA = 0, StubSize = 0;
  bool TAAParsed;
  std::string ErrorCode =
    MCSectionMachO::ParseSectionSpecifier(SectionVal, Segment, Section,
                                          TAA, TAAParsed, StubSize);
  if (!ErrorCode.empty())
    // If invalid, report the error with report_fatal_error.
    report_fatal_error("Invalid section specifier '" + Section + "': " +
                       ErrorCode + ".");

  // Get the section.
  MCSectionMachO *S = getContext().getMachOSection(
      Segment, Section, TAA, StubSize, SectionKind::getData());
  Streamer.SwitchSection(S);
  Streamer.EmitLabel(getContext().
                     getOrCreateSymbol(StringRef("L_OBJC_IMAGE_INFO")));
  Streamer.EmitIntValue(VersionVal, 4);
  Streamer.EmitIntValue(ImageInfoFlags, 4);
  Streamer.AddBlankLine();
}
コード例 #13
0
static SectionKind
getELFKindForNamedSection(StringRef Name, SectionKind K) {
  // N.B.: The defaults used in here are no the same ones used in MC.
  // We follow gcc, MC follows gas. For example, given ".section .eh_frame",
  // both gas and MC will produce a section with no flags. Given
  // section(".eh_frame") gcc will produce:
  //
  //   .section   .eh_frame,"a",@progbits
  
  if (Name == getInstrProfCoverageSectionName(false))
    return SectionKind::getMetadata();

  if (Name.empty() || Name[0] != '.') return K;

  // Some lame default implementation based on some magic section names.
  if (Name == ".bss" ||
      Name.startswith(".bss.") ||
      Name.startswith(".gnu.linkonce.b.") ||
      Name.startswith(".llvm.linkonce.b.") ||
      Name == ".sbss" ||
      Name.startswith(".sbss.") ||
      Name.startswith(".gnu.linkonce.sb.") ||
      Name.startswith(".llvm.linkonce.sb."))
    return SectionKind::getBSS();

  if (Name == ".tdata" ||
      Name.startswith(".tdata.") ||
      Name.startswith(".gnu.linkonce.td.") ||
      Name.startswith(".llvm.linkonce.td."))
    return SectionKind::getThreadData();

  if (Name == ".tbss" ||
      Name.startswith(".tbss.") ||
      Name.startswith(".gnu.linkonce.tb.") ||
      Name.startswith(".llvm.linkonce.tb."))
    return SectionKind::getThreadBSS();

  return K;
}
コード例 #14
0
ファイル: InlineAsm.cpp プロジェクト: AmesianX/dagger
/// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
/// fields in this structure.  If the constraint string is not understood,
/// return true, otherwise return false.
bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
                     InlineAsm::ConstraintInfoVector &ConstraintsSoFar) {
  StringRef::iterator I = Str.begin(), E = Str.end();
  unsigned multipleAlternativeCount = Str.count('|') + 1;
  unsigned multipleAlternativeIndex = 0;
  ConstraintCodeVector *pCodes = &Codes;
  
  // Initialize
  isMultipleAlternative = (multipleAlternativeCount > 1 ? true : false);
  if (isMultipleAlternative) {
    multipleAlternatives.resize(multipleAlternativeCount);
    pCodes = &multipleAlternatives[0].Codes;
  }
  Type = isInput;
  isEarlyClobber = false;
  MatchingInput = -1;
  isCommutative = false;
  isIndirect = false;
  currentAlternativeIndex = 0;
  
  // Parse prefixes.
  if (*I == '~') {
    Type = isClobber;
    ++I;
  } else if (*I == '=') {
    ++I;
    Type = isOutput;
  }
  
  if (*I == '*') {
    isIndirect = true;
    ++I;
  }
  
  if (I == E) return true;  // Just a prefix, like "==" or "~".
  
  // Parse the modifiers.
  bool DoneWithModifiers = false;
  while (!DoneWithModifiers) {
    switch (*I) {
    default:
      DoneWithModifiers = true;
      break;
    case '&':     // Early clobber.
      if (Type != isOutput ||      // Cannot early clobber anything but output.
          isEarlyClobber)          // Reject &&&&&&
        return true;
      isEarlyClobber = true;
      break;
    case '%':     // Commutative.
      if (Type == isClobber ||     // Cannot commute clobbers.
          isCommutative)           // Reject %%%%%
        return true;
      isCommutative = true;
      break;
    case '#':     // Comment.
    case '*':     // Register preferencing.
      return true;     // Not supported.
    }
    
    if (!DoneWithModifiers) {
      ++I;
      if (I == E) return true;   // Just prefixes and modifiers!
    }
  }
  
  // Parse the various constraints.
  while (I != E) {
    if (*I == '{') {   // Physical register reference.
      // Find the end of the register name.
      StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
      if (ConstraintEnd == E) return true;  // "{foo"
      pCodes->push_back(std::string(I, ConstraintEnd+1));
      I = ConstraintEnd+1;
    } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint
      // Maximal munch numbers.
      StringRef::iterator NumStart = I;
      while (I != E && isdigit(static_cast<unsigned char>(*I)))
        ++I;
      pCodes->push_back(std::string(NumStart, I));
      unsigned N = atoi(pCodes->back().c_str());
      // Check that this is a valid matching constraint!
      if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
          Type != isInput)
        return true;  // Invalid constraint number.
      
      // If Operand N already has a matching input, reject this.  An output
      // can't be constrained to the same value as multiple inputs.
      if (isMultipleAlternative) {
        InlineAsm::SubConstraintInfo &scInfo =
          ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
        if (scInfo.MatchingInput != -1)
          return true;
        // Note that operand #n has a matching input.
        scInfo.MatchingInput = ConstraintsSoFar.size();
      } else {
        if (ConstraintsSoFar[N].hasMatchingInput())
          return true;
        // Note that operand #n has a matching input.
        ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
        }
    } else if (*I == '|') {
      multipleAlternativeIndex++;
      pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes;
      ++I;
    } else if (*I == '^') {
      // Multi-letter constraint
      // FIXME: For now assuming these are 2-character constraints.
      pCodes->push_back(std::string(I+1, I+3));
      I += 3;
    } else {
      // Single letter constraint.
      pCodes->push_back(std::string(I, I+1));
      ++I;
    }
  }

  return false;
}
コード例 #15
0
/// Parse \p Input as line sample.
///
/// \param Input input line.
/// \param IsCallsite true if the line represents an inlined callsite.
/// \param Depth the depth of the inline stack.
/// \param NumSamples total samples of the line/inlined callsite.
/// \param LineOffset line offset to the start of the function.
/// \param Discriminator discriminator of the line.
/// \param TargetCountMap map from indirect call target to count.
///
/// returns true if parsing is successful.
static bool ParseLine(const StringRef &Input, bool &IsCallsite, uint32_t &Depth,
                      uint64_t &NumSamples, uint32_t &LineOffset,
                      uint32_t &Discriminator, StringRef &CalleeName,
                      DenseMap<StringRef, uint64_t> &TargetCountMap) {
  for (Depth = 0; Input[Depth] == ' '; Depth++)
    ;
  if (Depth == 0)
    return false;

  size_t n1 = Input.find(':');
  StringRef Loc = Input.substr(Depth, n1 - Depth);
  size_t n2 = Loc.find('.');
  if (n2 == StringRef::npos) {
    if (Loc.getAsInteger(10, LineOffset) || !isOffsetLegal(LineOffset))
      return false;
    Discriminator = 0;
  } else {
    if (Loc.substr(0, n2).getAsInteger(10, LineOffset))
      return false;
    if (Loc.substr(n2 + 1).getAsInteger(10, Discriminator))
      return false;
  }

  StringRef Rest = Input.substr(n1 + 2);
  if (Rest[0] >= '0' && Rest[0] <= '9') {
    IsCallsite = false;
    size_t n3 = Rest.find(' ');
    if (n3 == StringRef::npos) {
      if (Rest.getAsInteger(10, NumSamples))
        return false;
    } else {
      if (Rest.substr(0, n3).getAsInteger(10, NumSamples))
        return false;
    }
    // Find call targets and their sample counts.
    // Note: In some cases, there are symbols in the profile which are not
    // mangled. To accommodate such cases, use colon + integer pairs as the
    // anchor points.
    // An example:
    // _M_construct<char *>:1000 string_view<std::allocator<char> >:437
    // ":1000" and ":437" are used as anchor points so the string above will
    // be interpreted as
    // target: _M_construct<char *>
    // count: 1000
    // target: string_view<std::allocator<char> >
    // count: 437
    while (n3 != StringRef::npos) {
      n3 += Rest.substr(n3).find_first_not_of(' ');
      Rest = Rest.substr(n3);
      n3 = Rest.find_first_of(':');
      if (n3 == StringRef::npos || n3 == 0)
        return false;

      StringRef Target;
      uint64_t count, n4;
      while (true) {
        // Get the segment after the current colon.
        StringRef AfterColon = Rest.substr(n3 + 1);
        // Get the target symbol before the current colon.
        Target = Rest.substr(0, n3);
        // Check if the word after the current colon is an integer.
        n4 = AfterColon.find_first_of(' ');
        n4 = (n4 != StringRef::npos) ? n3 + n4 + 1 : Rest.size();
        StringRef WordAfterColon = Rest.substr(n3 + 1, n4 - n3 - 1);
        if (!WordAfterColon.getAsInteger(10, count))
          break;

        // Try to find the next colon.
        uint64_t n5 = AfterColon.find_first_of(':');
        if (n5 == StringRef::npos)
          return false;
        n3 += n5 + 1;
      }

      // An anchor point is found. Save the {target, count} pair
      TargetCountMap[Target] = count;
      if (n4 == Rest.size())
        break;
      // Change n3 to the next blank space after colon + integer pair.
      n3 = n4;
    }
  } else {
    IsCallsite = true;
    size_t n3 = Rest.find_last_of(':');
    CalleeName = Rest.substr(0, n3);
    if (Rest.substr(n3 + 1).getAsInteger(10, NumSamples))
      return false;
  }
  return true;
}
コード例 #16
0
/// \brief Format a single diagnostic argument and write it to the given
/// stream.
static void formatDiagnosticArgument(StringRef Modifier, 
                                     StringRef ModifierArguments,
                                     ArrayRef<DiagnosticArgument> Args,
                                     unsigned ArgIndex,
                                     llvm::raw_ostream &Out) {
  const DiagnosticArgument &Arg = Args[ArgIndex];
  switch (Arg.getKind()) {
  case DiagnosticArgumentKind::Integer:
    if (Modifier == "select") {
      assert(Arg.getAsInteger() >= 0 && "Negative selection index");
      formatSelectionArgument(ModifierArguments, Args, Arg.getAsInteger(), 
                              Out);
    } else if (Modifier == "s") {
      if (Arg.getAsInteger() != 1)
        Out << 's';
    } else {
      assert(Modifier.empty() && "Improper modifier for integer argument");
      Out << Arg.getAsInteger();
    }
    break;

  case DiagnosticArgumentKind::Unsigned:
    if (Modifier == "select") {
      formatSelectionArgument(ModifierArguments, Args, Arg.getAsUnsigned(), 
                              Out);
    } else if (Modifier == "s") {
      if (Arg.getAsUnsigned() != 1)
        Out << 's';
    } else {
      assert(Modifier.empty() && "Improper modifier for unsigned argument");
      Out << Arg.getAsUnsigned();
    }
    break;

  case DiagnosticArgumentKind::String:
    assert(Modifier.empty() && "Improper modifier for string argument");
    Out << Arg.getAsString();
    break;

  case DiagnosticArgumentKind::Identifier:
    assert(Modifier.empty() && "Improper modifier for identifier argument");
    Out << '\'';
    Arg.getAsIdentifier().printPretty(Out);
    Out << '\'';
    break;

  case DiagnosticArgumentKind::ObjCSelector:
    assert(Modifier.empty() && "Improper modifier for selector argument");
    Out << '\'' << Arg.getAsObjCSelector() << '\'';
    break;

  case DiagnosticArgumentKind::Type: {
    assert(Modifier.empty() && "Improper modifier for Type argument");
    
    // Strip extraneous parentheses; they add no value.
    auto type = Arg.getAsType()->getWithoutParens();
    std::string typeName = type->getString();
    Out << '\'' << typeName << '\'';


    // Decide whether to show the desugared type or not.  We filter out some
    // cases to avoid too much noise.
    bool showAKA = !type->isCanonical();

    // Substituted types are uninteresting sugar that prevents the heuristics
    // below from kicking in.
    if (showAKA)
      if (auto *ST = dyn_cast<SubstitutedType>(type.getPointer()))
        type = ST->getReplacementType();

    // If we're complaining about a function type, don't "aka" just because of
    // differences in the argument or result types.
    if (showAKA && type->is<FunctionType>() &&
        isa<FunctionType>(type.getPointer()))
      showAKA = false;

    // Don't unwrap intentional sugar types like T? or [T].
    if (showAKA && (isa<SyntaxSugarType>(type.getPointer()) ||
                    isa<DictionaryType>(type.getPointer()) ||
                    type->is<BuiltinType>()))
      showAKA = false;

    // If they are textually the same, don't show them.  This can happen when
    // they are actually different types, because they exist in different scopes
    // (e.g. everyone names their type parameters 'T').
    if (showAKA && typeName == type->getCanonicalType()->getString())
      showAKA = false;

    // Don't show generic type parameters.
    if (showAKA && type->getCanonicalType()->hasTypeParameter())
      showAKA = false;

    if (showAKA)
      Out << " (aka '" << type->getCanonicalType() << "')";
    break;
  }
  case DiagnosticArgumentKind::TypeRepr:
    assert(Modifier.empty() && "Improper modifier for TypeRepr argument");
    Out << '\'' << Arg.getAsTypeRepr() << '\'';
    break;
  case DiagnosticArgumentKind::PatternKind:
    assert(Modifier.empty() && "Improper modifier for PatternKind argument");
    Out << Arg.getAsPatternKind();
    break;
  case DiagnosticArgumentKind::StaticSpellingKind:
    if (Modifier == "select") {
      formatSelectionArgument(ModifierArguments, Args,
                              unsigned(Arg.getAsStaticSpellingKind()), Out);
    } else {
      assert(Modifier.empty() &&
             "Improper modifier for StaticSpellingKind argument");
      Out << Arg.getAsStaticSpellingKind();
    }
    break;

  case DiagnosticArgumentKind::DescriptiveDeclKind:
    assert(Modifier.empty() &&
           "Improper modifier for DescriptiveDeclKind argument");
    Out << Decl::getDescriptiveKindName(Arg.getAsDescriptiveDeclKind());
    break;

  case DiagnosticArgumentKind::DeclAttribute:
    assert(Modifier.empty() &&
           "Improper modifier for DeclAttribute argument");
    if (Arg.getAsDeclAttribute()->isDeclModifier())
      Out << '\'' << Arg.getAsDeclAttribute()->getAttrName() << '\'';
    else
      Out << '@' << Arg.getAsDeclAttribute()->getAttrName();
    break;

  case DiagnosticArgumentKind::VersionTuple:
    assert(Modifier.empty() &&
           "Improper modifier for VersionTuple argument");
    Out << Arg.getAsVersionTuple().getAsString();
    break;
  }
}
コード例 #17
0
/// Returns the common word-prefix of two strings, allowing the second string
/// to be a common English plural form of the first.
///
/// For example, given "NSProperty" and "NSProperties", the full "NSProperty"
/// is returned. Given "NSMagicArmor" and "NSMagicArmory", only
/// "NSMagic" is returned.
///
/// The "-s", "-es", and "-ies" patterns cover every plural NS_OPTIONS name
/// in Cocoa and Cocoa Touch.
///
/// \see getCommonWordPrefix
static StringRef getCommonPluralPrefix(StringRef singular, StringRef plural) {
  assert(!plural.empty());

  if (singular.empty())
    return singular;

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

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

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

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

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

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

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

  return commonPrefix;
}
コード例 #18
0
/// \brief Format the given diagnostic text and place the result in the given
/// buffer.
static void formatDiagnosticText(StringRef InText, 
                                 ArrayRef<DiagnosticArgument> Args,
                                 llvm::raw_ostream &Out) {
  while (!InText.empty()) {
    size_t Percent = InText.find('%');
    if (Percent == StringRef::npos) {
      // Write the rest of the string; we're done.
      Out.write(InText.data(), InText.size());
      break;
    }
    
    // Write the string up to (but not including) the %, then drop that text
    // (including the %).
    Out.write(InText.data(), Percent);
    InText = InText.substr(Percent + 1);
    
    // '%%' -> '%'.
    if (InText[0] == '%') {
      Out.write('%');
      InText = InText.substr(1);
      continue;
    }

    // Parse an optional modifier.
    StringRef Modifier;
    {
      unsigned Length = 0;
      while (isalpha(InText[Length]))
        ++Length;
      Modifier = InText.substr(0, Length);
      InText = InText.substr(Length);
    }
    
    // Parse the optional argument list for a modifier, which is brace-enclosed.
    StringRef ModifierArguments;
    if (InText[0] == '{') {
      InText = InText.substr(1);
      ModifierArguments = skipToDelimiter(InText, '}');
    }
    
    // Find the digit sequence.
    unsigned Length = 0;
    for (size_t N = InText.size(); Length != N; ++Length) {
      if (!isdigit(InText[Length]))
        break;
    }
      
    // Parse the digit sequence into an argument index.
    unsigned ArgIndex;      
    bool Result = InText.substr(0, Length).getAsInteger(10, ArgIndex);
    assert(!Result && "Unparseable argument index value?");
    (void)Result;
    assert(ArgIndex < Args.size() && "Out-of-range argument index");
    InText = InText.substr(Length);

    // Convert the argument to a string.
    formatDiagnosticArgument(Modifier, ModifierArguments, Args, ArgIndex, Out);
  }
}
コード例 #19
0
ファイル: Linking.cpp プロジェクト: apple/swift
/// Mangle this entity into the given stream.
std::string LinkEntity::mangleNew() const {
  // Almost everything below gets the common prefix:
  //   mangled-name ::= '_T' global
  IRGenMangler mangler;
  switch (getKind()) {
      //   global ::= 'w' value-witness-kind          // value witness
    case Kind::ValueWitness:
      return mangler.mangleValueWitness(getType(), getValueWitness());

      //   global ::= 'WV' type                       // value witness
    case Kind::ValueWitnessTable:
      return mangler.mangleValueWitnessTable(getType());

      //   global ::= 't' type
      // Abstract type manglings just follow <type>.
    case Kind::TypeMangling:
      return mangleOld();

      //   global ::= 'Ma' type               // type metadata access function
    case Kind::TypeMetadataAccessFunction:
      return mangler.mangleTypeMetadataAccessFunction(getType());

      //   global ::= 'ML' type               // type metadata lazy cache variable
    case Kind::TypeMetadataLazyCacheVariable:
      return mangler.mangleTypeMetadataLazyCacheVariable(getType());

      //   global ::= 'Mf' type                       // 'full' type metadata
      //   global ::= 'M' directness type             // type metadata
      //   global ::= 'MP' directness type            // type metadata pattern
    case Kind::TypeMetadata:
      switch (getMetadataAddress()) {
        case TypeMetadataAddress::FullMetadata:
          return mangler.mangleTypeFullMetadataFull(getType());
        case TypeMetadataAddress::AddressPoint:
          return mangler.mangleTypeMetadataFull(getType(), isMetadataPattern());
      }
      llvm_unreachable("invalid metadata address");

      //   global ::= 'M' directness type             // type metadata
    case Kind::ForeignTypeMetadataCandidate:
      return mangler.mangleTypeMetadataFull(getType(), /*isPattern=*/false);

      //   global ::= 'Mm' type                       // class metaclass
    case Kind::SwiftMetaclassStub:
      return mangler.mangleClassMetaClass(cast<ClassDecl>(getDecl()));

      //   global ::= 'Mn' type                       // nominal type descriptor
    case Kind::NominalTypeDescriptor:
      return mangler.mangleNominalTypeDescriptor(
                                          cast<NominalTypeDecl>(getDecl()));

      //   global ::= 'Mp' type                       // protocol descriptor
    case Kind::ProtocolDescriptor:
      return mangler.mangleProtocolDescriptor(cast<ProtocolDecl>(getDecl()));

      //   global ::= 'Wo' entity
    case Kind::WitnessTableOffset:
      return mangler.mangleWitnessTableOffset(getDecl());

      //   global ::= 'Wv' directness entity
    case Kind::FieldOffset:
      return mangler.mangleFieldOffsetFull(getDecl(), isOffsetIndirect());

      //   global ::= 'WP' protocol-conformance
    case Kind::DirectProtocolWitnessTable:
      return mangler.mangleDirectProtocolWitnessTable(getProtocolConformance());

      //   global ::= 'WG' protocol-conformance
    case Kind::GenericProtocolWitnessTableCache:
      return mangler.mangleGenericProtocolWitnessTableCache(
                                                      getProtocolConformance());

      //   global ::= 'WI' protocol-conformance
    case Kind::GenericProtocolWitnessTableInstantiationFunction:
      return mangler.mangleGenericProtocolWitnessTableInstantiationFunction(
                                                      getProtocolConformance());

      //   global ::= 'Wa' protocol-conformance
    case Kind::ProtocolWitnessTableAccessFunction:
      return mangler.mangleProtocolWitnessTableAccessFunction(
                                                      getProtocolConformance());

      //   global ::= 'Wl' type protocol-conformance
    case Kind::ProtocolWitnessTableLazyAccessFunction:
      return mangler.mangleProtocolWitnessTableLazyAccessFunction(getType(),
                                                      getProtocolConformance());

      //   global ::= 'WL' type protocol-conformance
    case Kind::ProtocolWitnessTableLazyCacheVariable:
      return mangler.mangleProtocolWitnessTableLazyCacheVariable(getType(),
                                                      getProtocolConformance());

      //   global ::= 'Wt' protocol-conformance identifier
    case Kind::AssociatedTypeMetadataAccessFunction:
      return mangler.mangleAssociatedTypeMetadataAccessFunction(
                  getProtocolConformance(), getAssociatedType()->getNameStr());

      //   global ::= 'WT' protocol-conformance identifier nominal-type
    case Kind::AssociatedTypeWitnessTableAccessFunction:
      return mangler.mangleAssociatedTypeWitnessTableAccessFunction(
                  getProtocolConformance(), getAssociatedType()->getNameStr(),
                  getAssociatedProtocol());

      // For all the following, this rule was imposed above:
      //   global ::= local-marker? entity            // some identifiable thing

      //   entity ::= declaration                     // other declaration
    case Kind::Function:
      // As a special case, functions can have manually mangled names.
      if (auto AsmA = getDecl()->getAttrs().getAttribute<SILGenNameAttr>()) {
        return AsmA->Name;
      }

      // Otherwise, fall through into the 'other decl' case.
      SWIFT_FALLTHROUGH;

    case Kind::Other:
      // As a special case, Clang functions and globals don't get mangled at all.
      if (auto clangDecl = getDecl()->getClangDecl()) {
        if (auto namedClangDecl = dyn_cast<clang::DeclaratorDecl>(clangDecl)) {
          if (auto asmLabel = namedClangDecl->getAttr<clang::AsmLabelAttr>()) {
            std::string Name(1, '\01');
            Name.append(asmLabel->getLabel());
            return Name;
          }
          if (namedClangDecl->hasAttr<clang::OverloadableAttr>()) {
            // FIXME: When we can import C++, use Clang's mangler all the time.
            std::string storage;
            llvm::raw_string_ostream SS(storage);
            mangleClangDecl(SS, namedClangDecl, getDecl()->getASTContext());
            return SS.str();
          }
          return namedClangDecl->getName();
        }
      }

      if (auto type = dyn_cast<NominalTypeDecl>(getDecl())) {
        return mangler.mangleNominalType(type);
      }
      if (auto ctor = dyn_cast<ConstructorDecl>(getDecl())) {
        // FIXME: Hack. LinkInfo should be able to refer to the allocating
        // constructor rather than inferring it here.
        return mangler.mangleConstructorEntity(ctor, /*isAllocating=*/true,
                                               /*isCurried=*/false);
      }
      return mangler.mangleEntity(getDecl(), /*isCurried=*/false);

      // An Objective-C class reference reference. The symbol is private, so
      // the mangling is unimportant; it should just be readable in LLVM IR.
    case Kind::ObjCClassRef: {
      llvm::SmallString<64> tempBuffer;
      StringRef name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(tempBuffer);
      std::string Result("OBJC_CLASS_REF_$_");
      Result.append(name.data(), name.size());
      return Result;
    }

      // An Objective-C class reference;  not a swift mangling.
    case Kind::ObjCClass: {
      llvm::SmallString<64> TempBuffer;
      StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
      std::string Result("OBJC_CLASS_$_");
      Result.append(Name.data(), Name.size());
      return Result;
    }

      // An Objective-C metaclass reference;  not a swift mangling.
    case Kind::ObjCMetaclass: {
      llvm::SmallString<64> TempBuffer;
      StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
      std::string Result("OBJC_METACLASS_$_");
      Result.append(Name.data(), Name.size());
      return Result;
    }

    case Kind::SILFunction:
      return getSILFunction()->getName();
    case Kind::SILGlobalVariable:
      return getSILGlobalVariable()->getName();

    case Kind::ReflectionBuiltinDescriptor:
      return mangler.mangleReflectionBuiltinDescriptor(getType());
    case Kind::ReflectionFieldDescriptor:
      return mangler.mangleReflectionFieldDescriptor(getType());
    case Kind::ReflectionAssociatedTypeDescriptor:
      return mangler.mangleReflectionAssociatedTypeDescriptor(
                                                      getProtocolConformance());
    case Kind::ReflectionSuperclassDescriptor:
      return mangler.mangleReflectionSuperclassDescriptor(
                                                    cast<ClassDecl>(getDecl()));
  }
  llvm_unreachable("bad entity kind!");
}
コード例 #20
0
ファイル: HTMLDiagnostics.cpp プロジェクト: vkhromov/freebsd
void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
                                  const PathDiagnosticPiece& P,
                                  unsigned num, unsigned max) {

  // For now, just draw a box above the line in question, and emit the
  // warning.
  FullSourceLoc Pos = P.getLocation().asLocation();

  if (!Pos.isValid())
    return;

  SourceManager &SM = R.getSourceMgr();
  assert(&Pos.getManager() == &SM && "SourceManagers are different!");
  std::pair<FileID, unsigned> LPosInfo = SM.getDecomposedExpansionLoc(Pos);

  if (LPosInfo.first != BugFileID)
    return;

  const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first);
  const char* FileStart = Buf->getBufferStart();

  // Compute the column number.  Rewind from the current position to the start
  // of the line.
  unsigned ColNo = SM.getColumnNumber(LPosInfo.first, LPosInfo.second);
  const char *TokInstantiationPtr =Pos.getExpansionLoc().getCharacterData();
  const char *LineStart = TokInstantiationPtr-ColNo;

  // Compute LineEnd.
  const char *LineEnd = TokInstantiationPtr;
  const char* FileEnd = Buf->getBufferEnd();
  while (*LineEnd != '\n' && LineEnd != FileEnd)
    ++LineEnd;

  // Compute the margin offset by counting tabs and non-tabs.
  unsigned PosNo = 0;
  for (const char* c = LineStart; c != TokInstantiationPtr; ++c)
    PosNo += *c == '\t' ? 8 : 1;

  // Create the html for the message.

  const char *Kind = 0;
  switch (P.getKind()) {
  case PathDiagnosticPiece::Call:
      llvm_unreachable("Calls should already be handled");
  case PathDiagnosticPiece::Event:  Kind = "Event"; break;
  case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
    // Setting Kind to "Control" is intentional.
  case PathDiagnosticPiece::Macro: Kind = "Control"; break;
  }

  std::string sbuf;
  llvm::raw_string_ostream os(sbuf);

  os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\"";

  if (num == max)
    os << "EndPath";
  else
    os << "Path" << num;

  os << "\" class=\"msg";
  if (Kind)
    os << " msg" << Kind;
  os << "\" style=\"margin-left:" << PosNo << "ex";

  // Output a maximum size.
  if (!isa<PathDiagnosticMacroPiece>(P)) {
    // Get the string and determining its maximum substring.
    const std::string& Msg = P.getString();
    unsigned max_token = 0;
    unsigned cnt = 0;
    unsigned len = Msg.size();

    for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I)
      switch (*I) {
      default:
        ++cnt;
        continue;
      case ' ':
      case '\t':
      case '\n':
        if (cnt > max_token) max_token = cnt;
        cnt = 0;
      }

    if (cnt > max_token)
      max_token = cnt;

    // Determine the approximate size of the message bubble in em.
    unsigned em;
    const unsigned max_line = 120;

    if (max_token >= max_line)
      em = max_token / 2;
    else {
      unsigned characters = max_line;
      unsigned lines = len / max_line;

      if (lines > 0) {
        for (; characters > max_token; --characters)
          if (len / characters > lines) {
            ++characters;
            break;
          }
      }

      em = characters / 2;
    }

    if (em < max_line/2)
      os << "; max-width:" << em << "em";
  }
  else
    os << "; max-width:100em";

  os << "\">";

  if (max > 1) {
    os << "<table class=\"msgT\"><tr><td valign=\"top\">";
    os << "<div class=\"PathIndex";
    if (Kind) os << " PathIndex" << Kind;
    os << "\">" << num << "</div>";

    if (num > 1) {
      os << "</td><td><div class=\"PathNav\"><a href=\"#Path"
         << (num - 1)
         << "\" title=\"Previous event ("
         << (num - 1)
         << ")\">&#x2190;</a></div></td>";
    }

    os << "</td><td>";
  }

  if (const PathDiagnosticMacroPiece *MP =
        dyn_cast<PathDiagnosticMacroPiece>(&P)) {

    os << "Within the expansion of the macro '";

    // Get the name of the macro by relexing it.
    {
      FullSourceLoc L = MP->getLocation().asLocation().getExpansionLoc();
      assert(L.isFileID());
      StringRef BufferInfo = L.getBufferData();
      std::pair<FileID, unsigned> LocInfo = L.getDecomposedLoc();
      const char* MacroName = LocInfo.second + BufferInfo.data();
      Lexer rawLexer(SM.getLocForStartOfFile(LocInfo.first), PP.getLangOpts(),
                     BufferInfo.begin(), MacroName, BufferInfo.end());

      Token TheTok;
      rawLexer.LexFromRawLexer(TheTok);
      for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i)
        os << MacroName[i];
    }

    os << "':\n";

    if (max > 1) {
      os << "</td>";
      if (num < max) {
        os << "<td><div class=\"PathNav\"><a href=\"#";
        if (num == max - 1)
          os << "EndPath";
        else
          os << "Path" << (num + 1);
        os << "\" title=\"Next event ("
        << (num + 1)
        << ")\">&#x2192;</a></div></td>";
      }

      os << "</tr></table>";
    }

    // Within a macro piece.  Write out each event.
    ProcessMacroPiece(os, *MP, 0);
  }
  else {
    os << html::EscapeText(P.getString());

    if (max > 1) {
      os << "</td>";
      if (num < max) {
        os << "<td><div class=\"PathNav\"><a href=\"#";
        if (num == max - 1)
          os << "EndPath";
        else
          os << "Path" << (num + 1);
        os << "\" title=\"Next event ("
           << (num + 1)
           << ")\">&#x2192;</a></div></td>";
      }
      
      os << "</tr></table>";
    }
  }

  os << "</div></td></tr>";

  // Insert the new html.
  unsigned DisplayPos = LineEnd - FileStart;
  SourceLocation Loc =
    SM.getLocForStartOfFile(LPosInfo.first).getLocWithOffset(DisplayPos);

  R.InsertTextBefore(Loc, os.str());

  // Now highlight the ranges.
  ArrayRef<SourceRange> Ranges = P.getRanges();
  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
                                       E = Ranges.end(); I != E; ++I) {
    HighlightRange(R, LPosInfo.first, *I);
  }
}
コード例 #21
0
ファイル: Archive.cpp プロジェクト: clockmaker002/llvm
ErrorOr<StringRef> Archive::Child::getName() const {
  StringRef name = getRawName();
  // Check if it's a special name.
  if (name[0] == '/') {
    if (name.size() == 1) // Linker member.
      return name;
    if (name.size() == 2 && name[1] == '/') // String table.
      return name;
    // It's a long name.
    // Get the offset.
    std::size_t offset;
    if (name.substr(1).rtrim(' ').getAsInteger(10, offset))
      llvm_unreachable("Long name offset is not an integer");

    // Verify it.
    if (offset >= Parent->StringTable.size())
      return object_error::parse_failed;
    const char *addr = Parent->StringTable.begin() + offset;

    // GNU long file names end with a "/\n".
    if (Parent->kind() == K_GNU || Parent->kind() == K_MIPS64) {
      StringRef::size_type End = StringRef(addr).find('\n');
      return StringRef(addr, End - 1);
    }
    return StringRef(addr);
  } else if (name.startswith("#1/")) {
    uint64_t name_size;
    if (name.substr(3).rtrim(' ').getAsInteger(10, name_size))
      llvm_unreachable("Long name length is not an ingeter");
    return Data.substr(Header.getSizeOf(), name_size).rtrim('\0');
  } else {
    // It is not a long name so trim the blanks at the end of the name.
    if (name[name.size() - 1] != '/') {
      return name.rtrim(' ');
    }
  }
  // It's a simple name.
  if (name[name.size() - 1] == '/')
    return name.substr(0, name.size() - 1);
  return name;
}
コード例 #22
0
ファイル: LowerSetJmp.cpp プロジェクト: jyasskin/llvm-mirror
// IsTransformableFunction - Return true if the function name isn't one
// of the ones we don't want transformed. Currently, don't transform any
// "llvm.{setjmp,longjmp}" functions and none of the setjmp/longjmp error
// handling functions (beginning with __llvm_sjljeh_...they don't throw
// exceptions).
bool LowerSetJmp::IsTransformableFunction(StringRef Name) {
  return !Name.startswith("__llvm_sjljeh_");
}
コード例 #23
0
ファイル: PlistDiagnostics.cpp プロジェクト: adevress/root-1
void PlistDiagnostics::FlushDiagnosticsImpl(
                                    std::vector<const PathDiagnostic *> &Diags,
                                    FilesMade *filesMade) {
  // Build up a set of FIDs that we use by scanning the locations and
  // ranges of the diagnostics.
  FIDMap FM;
  SmallVector<FileID, 10> Fids;
  const SourceManager* SM = 0;

  if (!Diags.empty())
    SM = &(*(*Diags.begin())->path.begin())->getLocation().getManager();

  
  for (std::vector<const PathDiagnostic*>::iterator DI = Diags.begin(),
       DE = Diags.end(); DI != DE; ++DI) {

    const PathDiagnostic *D = *DI;

    SmallVector<const PathPieces *, 5> WorkList;
    WorkList.push_back(&D->path);

    while (!WorkList.empty()) {
      const PathPieces &path = *WorkList.pop_back_val();

      for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E;
           ++I) {
        const PathDiagnosticPiece *piece = I->getPtr();
        AddFID(FM, Fids, *SM, piece->getLocation().asLocation());
        ArrayRef<SourceRange> Ranges = piece->getRanges();
        for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
                                             E = Ranges.end(); I != E; ++I) {
          AddFID(FM, Fids, *SM, I->getBegin());
          AddFID(FM, Fids, *SM, I->getEnd());
        }

        if (const PathDiagnosticCallPiece *call =
            dyn_cast<PathDiagnosticCallPiece>(piece)) {
          IntrusiveRefCntPtr<PathDiagnosticEventPiece>
            callEnterWithin = call->getCallEnterWithinCallerEvent();
          if (callEnterWithin)
            AddFID(FM, Fids, *SM, callEnterWithin->getLocation().asLocation());

          WorkList.push_back(&call->path);
        }
        else if (const PathDiagnosticMacroPiece *macro =
                 dyn_cast<PathDiagnosticMacroPiece>(piece)) {
          WorkList.push_back(&macro->subPieces);
        }
      }
    }
  }

  // Open the file.
  std::string ErrMsg;
  llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg, llvm::sys::fs::F_Text);
  if (!ErrMsg.empty()) {
    llvm::errs() << "warning: could not create file: " << OutputFile << '\n';
    return;
  }

  // Write the plist header.
  o << PlistHeader;

  // Write the root object: a <dict> containing...
  //  - "clang_version", the string representation of clang version
  //  - "files", an <array> mapping from FIDs to file names
  //  - "diagnostics", an <array> containing the path diagnostics
  o << "<dict>\n" <<
       " <key>clang_version</key>\n";
  EmitString(o, getClangFullVersion()) << '\n';
  o << " <key>files</key>\n"
       " <array>\n";

  for (SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end();
       I!=E; ++I) {
    o << "  ";
    EmitString(o, SM->getFileEntryForID(*I)->getName()) << '\n';
  }

  o << " </array>\n"
       " <key>diagnostics</key>\n"
       " <array>\n";

  for (std::vector<const PathDiagnostic*>::iterator DI=Diags.begin(),
       DE = Diags.end(); DI!=DE; ++DI) {

    o << "  <dict>\n"
         "   <key>path</key>\n";

    const PathDiagnostic *D = *DI;

    o << "   <array>\n";

    for (PathPieces::const_iterator I = D->path.begin(), E = D->path.end(); 
         I != E; ++I)
      ReportDiag(o, **I, FM, *SM, LangOpts);

    o << "   </array>\n";

    // Output the bug type and bug category.
    o << "   <key>description</key>";
    EmitString(o, D->getShortDescription()) << '\n';
    o << "   <key>category</key>";
    EmitString(o, D->getCategory()) << '\n';
    o << "   <key>type</key>";
    EmitString(o, D->getBugType()) << '\n';
    
    // Output information about the semantic context where
    // the issue occurred.
    if (const Decl *DeclWithIssue = D->getDeclWithIssue()) {
      // FIXME: handle blocks, which have no name.
      if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) {
        StringRef declKind;
        switch (ND->getKind()) {
          case Decl::CXXRecord:
            declKind = "C++ class";
            break;
          case Decl::CXXMethod:
            declKind = "C++ method";
            break;
          case Decl::ObjCMethod:
            declKind = "Objective-C method";
            break;
          case Decl::Function:
            declKind = "function";
            break;
          default:
            break;
        }
        if (!declKind.empty()) {
          const std::string &declName = ND->getDeclName().getAsString();
          o << "  <key>issue_context_kind</key>";
          EmitString(o, declKind) << '\n';
          o << "  <key>issue_context</key>";
          EmitString(o, declName) << '\n';
        }

        // Output the bug hash for issue unique-ing. Currently, it's just an
        // offset from the beginning of the function.
        if (const Stmt *Body = DeclWithIssue->getBody()) {
          
          // If the bug uniqueing location exists, use it for the hash.
          // For example, this ensures that two leaks reported on the same line
          // will have different issue_hashes and that the hash will identify
          // the leak location even after code is added between the allocation
          // site and the end of scope (leak report location).
          PathDiagnosticLocation UPDLoc = D->getUniqueingLoc();
          if (UPDLoc.isValid()) {
            FullSourceLoc UL(SM->getExpansionLoc(UPDLoc.asLocation()),
                             *SM);
            FullSourceLoc UFunL(SM->getExpansionLoc(
              D->getUniqueingDecl()->getBody()->getLocStart()), *SM);
            o << "  <key>issue_hash</key><string>"
              << UL.getExpansionLineNumber() - UFunL.getExpansionLineNumber()
              << "</string>\n";

          // Otherwise, use the location on which the bug is reported.
          } else {
            FullSourceLoc L(SM->getExpansionLoc(D->getLocation().asLocation()),
                            *SM);
            FullSourceLoc FunL(SM->getExpansionLoc(Body->getLocStart()), *SM);
            o << "  <key>issue_hash</key><string>"
              << L.getExpansionLineNumber() - FunL.getExpansionLineNumber()
              << "</string>\n";
          }

        }
      }
    }

    // Output the location of the bug.
    o << "  <key>location</key>\n";
    EmitLocation(o, *SM, LangOpts, D->getLocation().asLocation(), FM, 2);

    // Output the diagnostic to the sub-diagnostic client, if any.
    if (!filesMade->empty()) {
      StringRef lastName;
      PDFileEntry::ConsumerFiles *files = filesMade->getFiles(*D);
      if (files) {
        for (PDFileEntry::ConsumerFiles::const_iterator CI = files->begin(),
                CE = files->end(); CI != CE; ++CI) {
          StringRef newName = CI->first;
          if (newName != lastName) {
            if (!lastName.empty()) {
              o << "  </array>\n";
            }
            lastName = newName;
            o <<  "  <key>" << lastName << "_files</key>\n";
            o << "  <array>\n";
          }
          o << "   <string>" << CI->second << "</string>\n";
        }
        o << "  </array>\n";
      }
    }

    // Close up the entry.
    o << "  </dict>\n";
  }

  o << " </array>\n";

  // Finish.
  o << "</dict>\n</plist>";  
}
コード例 #24
0
ファイル: COFFDumper.cpp プロジェクト: manu-silicon/llvm
void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
    StringRef Data;
    if (error(Section.getContents(Data)))
        return;

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

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

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

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

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

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

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

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

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

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

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

        DataExtractor DE(FunctionLineTables[Name], true, 4);
        uint32_t Offset = 8;  // Skip relocations.
        uint32_t FunctionSize = DE.getU32(&Offset);
        W.printHex("CodeSize", FunctionSize);
        while (DE.isValidOffset(Offset)) {
            // For each range of lines with the same filename, we have a segment
            // in the line table.  The filename string is accessed using double
            // indirection to the string table subsection using the index subsection.
            uint32_t OffsetInIndex = DE.getU32(&Offset),
                     SegmentLength   = DE.getU32(&Offset),
                     FullSegmentSize = DE.getU32(&Offset);
            if (FullSegmentSize != 12 + 8 * SegmentLength) {
                error(object_error::parse_failed);
                return;
            }

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

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

            StringRef Filename(CVStringTable.data() + FilenameOffset);
            ListScope S(W, "FilenameSegment");
            W.printString("Filename", Filename);
            for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
                    ++J) {
                // Then go the (PC, LineNumber) pairs.  The line number is stored in the
                // least significant 31 bits of the respective word in the table.
                uint32_t PC = DE.getU32(&Offset),
                         LineNumber = DE.getU32(&Offset) & 0x7fffffff;
                if (PC >= FunctionSize) {
                    error(object_error::parse_failed);
                    return;
                }
                char Buffer[32];
                format("+0x%X", PC).snprint(Buffer, 32);
                W.printNumber(Buffer, LineNumber);
            }
        }
    }
}
コード例 #25
0
ファイル: Pragma.cpp プロジェクト: CTSRD-TESLA/clang
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);
}
コード例 #26
0
ファイル: COFFDumper.cpp プロジェクト: manu-silicon/llvm
void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
        const SectionRef &Section,
        uint32_t OffsetInSection) {
    if (Subsection.size() == 0) {
        error(object_error::parse_failed);
        return;
    }
    DataExtractor DE(Subsection, true, 4);
    uint32_t Offset = 0;

    // Function-level subsections have "procedure start" and "procedure end"
    // commands that should come in pairs and surround relevant info.
    bool InFunctionScope = false;
    while (DE.isValidOffset(Offset)) {
        // Read subsection segments one by one.
        uint16_t Size = DE.getU16(&Offset);
        // The section size includes the size of the type identifier.
        if (Size < 2 || !DE.isValidOffsetForDataOfSize(Offset, Size)) {
            error(object_error::parse_failed);
            return;
        }
        Size -= 2;
        uint16_t Type = DE.getU16(&Offset);
        switch (Type) {
        case COFF::DEBUG_SYMBOL_TYPE_PROC_START: {
            DictScope S(W, "ProcStart");
            if (InFunctionScope || Size < 36) {
                error(object_error::parse_failed);
                return;
            }
            InFunctionScope = true;

            // We're currently interested in a limited subset of fields in this
            // segment, just ignore the rest of the fields for now.
            uint8_t Unused[12];
            DE.getU8(&Offset, Unused, 12);
            uint32_t CodeSize = DE.getU32(&Offset);
            DE.getU8(&Offset, Unused, 12);
            StringRef SectionName;
            if (error(resolveSymbolName(Obj->getCOFFSection(Section),
                                        OffsetInSection + Offset, SectionName)))
                return;
            Offset += 4;
            DE.getU8(&Offset, Unused, 3);
            StringRef DisplayName = DE.getCStr(&Offset);
            if (!DE.isValidOffset(Offset)) {
                error(object_error::parse_failed);
                return;
            }
            W.printString("DisplayName", DisplayName);
            W.printString("Section", SectionName);
            W.printHex("CodeSize", CodeSize);

            break;
        }
        case COFF::DEBUG_SYMBOL_TYPE_PROC_END: {
            W.startLine() << "ProcEnd\n";
            if (!InFunctionScope || Size > 0) {
                error(object_error::parse_failed);
                return;
            }
            InFunctionScope = false;
            break;
        }
        default: {
            if (opts::CodeViewSubsectionBytes) {
                ListScope S(W, "Record");
                W.printHex("Size", Size);
                W.printHex("Type", Type);

                StringRef Contents = DE.getData().substr(Offset, Size);
                W.printBinaryBlock("Contents", Contents);
            }

            Offset += Size;
            break;
        }
        }
    }

    if (InFunctionScope)
        error(object_error::parse_failed);
}
コード例 #27
0
ファイル: StringRef.cpp プロジェクト: 0x00evil/llvm
bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const {
  StringRef Str = *this;

  // Autosense radix if not specified.
  if (Radix == 0)
    Radix = GetAutoSenseRadix(Str);

  assert(Radix > 1 && Radix <= 36);

  // Empty strings (after the radix autosense) are invalid.
  if (Str.empty()) return true;

  // Skip leading zeroes.  This can be a significant improvement if
  // it means we don't need > 64 bits.
  while (!Str.empty() && Str.front() == '0')
    Str = Str.substr(1);

  // If it was nothing but zeroes....
  if (Str.empty()) {
    Result = APInt(64, 0);
    return false;
  }

  // (Over-)estimate the required number of bits.
  unsigned Log2Radix = 0;
  while ((1U << Log2Radix) < Radix) Log2Radix++;
  bool IsPowerOf2Radix = ((1U << Log2Radix) == Radix);

  unsigned BitWidth = Log2Radix * Str.size();
  if (BitWidth < Result.getBitWidth())
    BitWidth = Result.getBitWidth(); // don't shrink the result
  else if (BitWidth > Result.getBitWidth())
    Result = Result.zext(BitWidth);

  APInt RadixAP, CharAP; // unused unless !IsPowerOf2Radix
  if (!IsPowerOf2Radix) {
    // These must have the same bit-width as Result.
    RadixAP = APInt(BitWidth, Radix);
    CharAP = APInt(BitWidth, 0);
  }

  // Parse all the bytes of the string given this radix.
  Result = 0;
  while (!Str.empty()) {
    unsigned CharVal;
    if (Str[0] >= '0' && Str[0] <= '9')
      CharVal = Str[0]-'0';
    else if (Str[0] >= 'a' && Str[0] <= 'z')
      CharVal = Str[0]-'a'+10;
    else if (Str[0] >= 'A' && Str[0] <= 'Z')
      CharVal = Str[0]-'A'+10;
    else
      return true;

    // If the parsed value is larger than the integer radix, the string is
    // invalid.
    if (CharVal >= Radix)
      return true;

    // Add in this character.
    if (IsPowerOf2Radix) {
      Result <<= Log2Radix;
      Result |= CharVal;
    } else {
      Result *= RadixAP;
      CharAP = CharVal;
      Result += CharAP;
    }

    Str = Str.substr(1);
  }

  return false;
}
コード例 #28
0
void ExecutionEngine::addGlobalMapping(StringRef Name, uint64_t Addr) {
  MutexGuard locked(lock);

  assert(!Name.empty() && "Empty GlobalMapping symbol name!");

  DEBUG(dbgs() << "JIT: Map \'" << Name  << "\' to [" << Addr << "]\n";);
コード例 #29
0
ファイル: TargetParser.cpp プロジェクト: Lucretia/llvm
unsigned llvm::AArch64::checkArchVersion(StringRef Arch) {
  if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
    return (Arch[1] - 48);
  return 0;
}
コード例 #30
0
void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
                                                    CheckerContext &C) const {
  if (!BT) {
    BT.reset(new APIMisuse("Arguments passed to variadic method aren't all "
                           "Objective-C pointer types"));

    ASTContext &Ctx = C.getASTContext();
    arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
    dictionaryWithObjectsAndKeysS =
      GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
    setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
    orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);

    initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
    initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
  }

  if (!isVariadicMessage(msg))
      return;

  // We are not interested in the selector arguments since they have
  // well-defined types, so the compiler will issue a warning for them.
  unsigned variadicArgsBegin = msg.getSelector().getNumArgs();

  // We're not interested in the last argument since it has to be nil or the
  // compiler would have issued a warning for it elsewhere.
  unsigned variadicArgsEnd = msg.getNumArgs() - 1;

  if (variadicArgsEnd <= variadicArgsBegin)
    return;

  // Verify that all arguments have Objective-C types.
  llvm::Optional<ExplodedNode*> errorNode;
  ProgramStateRef state = C.getState();

  for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
    QualType ArgTy = msg.getArgExpr(I)->getType();
    if (ArgTy->isObjCObjectPointerType())
      continue;

    // Block pointers are treaded as Objective-C pointers.
    if (ArgTy->isBlockPointerType())
      continue;

    // Ignore pointer constants.
    if (isa<loc::ConcreteInt>(msg.getArgSVal(I)))
      continue;

    // Ignore pointer types annotated with 'NSObject' attribute.
    if (C.getASTContext().isObjCNSObjectType(ArgTy))
      continue;

    // Ignore CF references, which can be toll-free bridged.
    if (coreFoundation::isCFObjectRef(ArgTy))
      continue;

    // Generate only one error node to use for all bug reports.
    if (!errorNode.hasValue())
      errorNode = C.addTransition();

    if (!errorNode.getValue())
      continue;

    SmallString<128> sbuf;
    llvm::raw_svector_ostream os(sbuf);

    StringRef TypeName = GetReceiverInterfaceName(msg);
    if (!TypeName.empty())
      os << "Argument to '" << TypeName << "' method '";
    else
      os << "Argument to method '";

    os << msg.getSelector().getAsString()
       << "' should be an Objective-C pointer type, not '";
    ArgTy.print(os, C.getLangOpts());
    os << "'";

    BugReport *R = new BugReport(*BT, os.str(), errorNode.getValue());
    R->addRange(msg.getArgSourceRange(I));
    C.emitReport(R);
  }
}