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";);
Example #2
0
/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec".
/// This is a string that can appear after a .section directive in a mach-o
/// flavored .s file.  If successful, this fills in the specified Out
/// parameters and returns an empty string.  When an invalid section
/// specifier is present, this returns a string indicating the problem.
std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec,        // In.
                                                  StringRef &Segment,    // Out.
                                                  StringRef &Section,    // Out.
                                                  unsigned  &TAA,        // Out.
                                                  bool      &TAAParsed,  // Out.
                                                  unsigned  &StubSize) { // Out.
  TAAParsed = false;

  SmallVector<StringRef, 5> SplitSpec;
  Spec.split(SplitSpec, ",");
  // Remove leading and trailing whitespace.
  auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef {
    return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef();
  };
  Segment = GetEmptyOrTrim(0);
  Section = GetEmptyOrTrim(1);
  StringRef SectionType = GetEmptyOrTrim(2);
  StringRef Attrs = GetEmptyOrTrim(3);
  StringRef StubSizeStr = GetEmptyOrTrim(4);

  // Verify that the segment is present and not too long.
  if (Segment.empty() || Segment.size() > 16)
    return "mach-o section specifier requires a segment whose length is "
           "between 1 and 16 characters";

  // Verify that the section is present and not too long.
  if (Section.empty())
    return "mach-o section specifier requires a segment and section "
           "separated by a comma";

  if (Section.size() > 16)
    return "mach-o section specifier requires a section whose length is "
           "between 1 and 16 characters";

  // If there is no comma after the section, we're done.
  TAA = 0;
  StubSize = 0;
  if (SectionType.empty())
    return "";

  // Figure out which section type it is.
  auto TypeDescriptor = std::find_if(
      std::begin(SectionTypeDescriptors), std::end(SectionTypeDescriptors),
      [&](decltype(*SectionTypeDescriptors) &Descriptor) {
        return Descriptor.AssemblerName &&
               SectionType == Descriptor.AssemblerName;
      });

  // If we didn't find the section type, reject it.
  if (TypeDescriptor == std::end(SectionTypeDescriptors))
    return "mach-o section specifier uses an unknown section type";

  // Remember the TypeID.
  TAA = TypeDescriptor - std::begin(SectionTypeDescriptors);
  TAAParsed = true;

  // If we have no comma after the section type, there are no attributes.
  if (Attrs.empty()) {
    // S_SYMBOL_STUBS always require a symbol stub size specifier.
    if (TAA == MachO::S_SYMBOL_STUBS)
      return "mach-o section specifier of type 'symbol_stubs' requires a size "
             "specifier";
    return "";
  }

  // The attribute list is a '+' separated list of attributes.
  SmallVector<StringRef, 1> SectionAttrs;
  Attrs.split(SectionAttrs, "+", /*MaxSplit=*/-1, /*KeepEmpty=*/false);

  for (StringRef &SectionAttr : SectionAttrs) {
    auto AttrDescriptorI = std::find_if(
        std::begin(SectionAttrDescriptors), std::end(SectionAttrDescriptors),
        [&](decltype(*SectionAttrDescriptors) &Descriptor) {
          return Descriptor.AssemblerName &&
                 SectionAttr.trim() == Descriptor.AssemblerName;
        });
    if (AttrDescriptorI == std::end(SectionAttrDescriptors))
      return "mach-o section specifier has invalid attribute";

    TAA |= AttrDescriptorI->AttrFlag;
  }

  // Okay, we've parsed the section attributes, see if we have a stub size spec.
  if (StubSizeStr.empty()) {
    // S_SYMBOL_STUBS always require a symbol stub size specifier.
    if (TAA == MachO::S_SYMBOL_STUBS)
      return "mach-o section specifier of type 'symbol_stubs' requires a size "
      "specifier";
    return "";
  }

  // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS.
  if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS)
    return "mach-o section specifier cannot have a stub size specified because "
           "it does not have type 'symbol_stubs'";

  // Convert the stub size from a string to an integer.
  if (StubSizeStr.getAsInteger(0, StubSize))
    return "mach-o section specifier has a malformed stub size";

  return "";
}
Example #3
0
std::string ARM_MC::ParseARMTriple(const Triple &TT, StringRef CPU) {
  bool isThumb =
      TT.getArch() == Triple::thumb || TT.getArch() == Triple::thumbeb;

  bool NoCPU = CPU == "generic" || CPU.empty();
  std::string ARMArchFeature;
  switch (TT.getSubArch()) {
  default:
    llvm_unreachable("invalid sub-architecture for ARM");
  case Triple::ARMSubArch_v8:
    if (NoCPU)
      // v8a: FeatureDB, FeatureFPARMv8, FeatureNEON, FeatureDSPThumb2,
      //      FeatureMP, FeatureHWDiv, FeatureHWDivARM, FeatureTrustZone,
      //      FeatureT2XtPk, FeatureCrypto, FeatureCRC
      ARMArchFeature = "+v8,+db,+fp-armv8,+neon,+t2dsp,+mp,+hwdiv,+hwdiv-arm,"
                       "+trustzone,+t2xtpk,+crypto,+crc";
    else
      // Use CPU to figure out the exact features
      ARMArchFeature = "+v8";
    break;
  case Triple::ARMSubArch_v8_1a:
    if (NoCPU)
      // v8.1a: FeatureDB, FeatureFPARMv8, FeatureNEON, FeatureDSPThumb2,
      //      FeatureMP, FeatureHWDiv, FeatureHWDivARM, FeatureTrustZone,
      //      FeatureT2XtPk, FeatureCrypto, FeatureCRC, FeatureV8_1a
      ARMArchFeature = "+v8.1a,+db,+fp-armv8,+neon,+t2dsp,+mp,+hwdiv,+hwdiv-arm,"
                       "+trustzone,+t2xtpk,+crypto,+crc";
    else
      // Use CPU to figure out the exact features
      ARMArchFeature = "+v8.1a";
    break;
  case Triple::ARMSubArch_v7m:
    isThumb = true;
    if (NoCPU)
      // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureMClass
      ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+mclass";
    else
      // Use CPU to figure out the exact features.
      ARMArchFeature = "+v7";
    break;
  case Triple::ARMSubArch_v7em:
    if (NoCPU)
      // v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2,
      //       FeatureT2XtPk, FeatureMClass
      ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,+t2xtpk,+mclass";
    else
      // Use CPU to figure out the exact features.
      ARMArchFeature = "+v7";
    break;
  case Triple::ARMSubArch_v7s:
    if (NoCPU)
      // v7s: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureHasRAS
      //      Swift
      ARMArchFeature = "+v7,+swift,+neon,+db,+t2dsp,+ras";
    else
      // Use CPU to figure out the exact features.
      ARMArchFeature = "+v7";
    break;
  case Triple::ARMSubArch_v7:
    // v7 CPUs have lots of different feature sets. If no CPU is specified,
    // then assume v7a (e.g. cortex-a8) feature set. Otherwise, return
    // the "minimum" feature set and use CPU string to figure out the exact
    // features.
    if (NoCPU)
      // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk
      ARMArchFeature = "+v7,+neon,+db,+t2dsp,+t2xtpk";
    else
      // Use CPU to figure out the exact features.
      ARMArchFeature = "+v7";
    break;
  case Triple::ARMSubArch_v6t2:
    ARMArchFeature = "+v6t2";
    break;
  case Triple::ARMSubArch_v6k:
    ARMArchFeature = "+v6k";
    break;
  case Triple::ARMSubArch_v6m:
    isThumb = true;
    if (NoCPU)
      // v6m: FeatureNoARM, FeatureMClass
      ARMArchFeature = "+v6m,+noarm,+mclass";
    else
      ARMArchFeature = "+v6";
    break;
  case Triple::ARMSubArch_v6:
    ARMArchFeature = "+v6";
    break;
  case Triple::ARMSubArch_v5te:
    ARMArchFeature = "+v5te";
    break;
  case Triple::ARMSubArch_v5:
    ARMArchFeature = "+v5t";
    break;
  case Triple::ARMSubArch_v4t:
    ARMArchFeature = "+v4t";
    break;
  case Triple::NoSubArch:
    break;
  }

  if (isThumb) {
    if (ARMArchFeature.empty())
      ARMArchFeature = "+thumb-mode";
    else
      ARMArchFeature += ",+thumb-mode";
  }

  if (TT.isOSNaCl()) {
    if (ARMArchFeature.empty())
      ARMArchFeature = "+nacl-trap";
    else
      ARMArchFeature += ",+nacl-trap";
  }

  return ARMArchFeature;
}
Example #4
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);
}
void NamedParameterCheck::check(const MatchFinder::MatchResult &Result) {
  const SourceManager &SM = *Result.SourceManager;
  const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>("decl");
  SmallVector<std::pair<const FunctionDecl *, unsigned>, 4> UnnamedParams;

  // Ignore implicitly generated members.
  if (Function->isImplicit())
    return;

  // Ignore declarations without a definition if we're not dealing with an
  // overriden method.
  const FunctionDecl *Definition = nullptr;
  if ((!Function->isDefined(Definition) || Function->isDefaulted() ||
       Function->isDeleted()) &&
      (!isa<CXXMethodDecl>(Function) ||
       cast<CXXMethodDecl>(Function)->size_overridden_methods() == 0))
    return;

  // TODO: Handle overloads.
  // TODO: We could check that all redeclarations use the same name for
  //       arguments in the same position.
  for (unsigned I = 0, E = Function->getNumParams(); I != E; ++I) {
    const ParmVarDecl *Parm = Function->getParamDecl(I);
    if (Parm->isImplicit())
      continue;
    // Look for unnamed parameters.
    if (!Parm->getName().empty())
      continue;

    // Don't warn on the dummy argument on post-inc and post-dec operators.
    if ((Function->getOverloadedOperator() == OO_PlusPlus ||
         Function->getOverloadedOperator() == OO_MinusMinus) &&
        Parm->getType()->isSpecificBuiltinType(BuiltinType::Int))
      continue;

    // Sanity check the source locations.
    if (!Parm->getLocation().isValid() || Parm->getLocation().isMacroID() ||
        !SM.isWrittenInSameFile(Parm->getBeginLoc(), Parm->getLocation()))
      continue;

    // Skip gmock testing::Unused parameters.
    if (auto Typedef = Parm->getType()->getAs<clang::TypedefType>())
      if (Typedef->getDecl()->getQualifiedNameAsString() == "testing::Unused")
        continue;

    // Skip std::nullptr_t.
    if (Parm->getType().getCanonicalType()->isNullPtrType())
      continue;

    // Look for comments. We explicitly want to allow idioms like
    // void foo(int /*unused*/)
    const char *Begin = SM.getCharacterData(Parm->getBeginLoc());
    const char *End = SM.getCharacterData(Parm->getLocation());
    StringRef Data(Begin, End - Begin);
    if (Data.find("/*") != StringRef::npos)
      continue;

    UnnamedParams.push_back(std::make_pair(Function, I));
  }

  // Emit only one warning per function but fixits for all unnamed parameters.
  if (!UnnamedParams.empty()) {
    const ParmVarDecl *FirstParm =
        UnnamedParams.front().first->getParamDecl(UnnamedParams.front().second);
    auto D = diag(FirstParm->getLocation(),
                  "all parameters should be named in a function");

    for (auto P : UnnamedParams) {
      // Fallback to an unused marker.
      StringRef NewName = "unused";

      // If the method is overridden, try to copy the name from the base method
      // into the overrider.
      const auto *M = dyn_cast<CXXMethodDecl>(P.first);
      if (M && M->size_overridden_methods() > 0) {
        const ParmVarDecl *OtherParm =
            (*M->begin_overridden_methods())->getParamDecl(P.second);
        StringRef Name = OtherParm->getName();
        if (!Name.empty())
          NewName = Name;
      }

      // If the definition has a named parameter use that name.
      if (Definition) {
        const ParmVarDecl *DefParm = Definition->getParamDecl(P.second);
        StringRef Name = DefParm->getName();
        if (!Name.empty())
          NewName = Name;
      }

      // Now insert the comment. Note that getLocation() points to the place
      // where the name would be, this allows us to also get complex cases like
      // function pointers right.
      const ParmVarDecl *Parm = P.first->getParamDecl(P.second);
      D << FixItHint::CreateInsertion(Parm->getLocation(),
                                      " /*" + NewName.str() + "*/");
    }
  }
}
static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){
  const TargetMachine &TM = AP.TM;
  Mangler *Mang = AP.Mang;
  const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout();
  MCContext &Ctx = AP.OutContext;
  bool isDarwin = Triple(TM.getTargetTriple()).isOSDarwin();

  SmallString<128> Name;
  StringRef Suffix;
  if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB) {
    if (isDarwin)
      Suffix = "$stub";
  } else if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG)
    Suffix = "$non_lazy_ptr";

  if (!Suffix.empty())
    Name += DL->getPrivateGlobalPrefix();

  unsigned PrefixLen = Name.size();

  if (!MO.isGlobal()) {
    assert(MO.isSymbol() && "Isn't a symbol reference");
    Mang->getNameWithPrefix(Name, MO.getSymbolName());
  } else {
    const GlobalValue *GV = MO.getGlobal();
    TM.getNameWithPrefix(Name, GV, *Mang);
  }

  unsigned OrigLen = Name.size() - PrefixLen;

  Name += Suffix;
  MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
  StringRef OrigName = StringRef(Name).substr(PrefixLen, OrigLen);

  // If the target flags on the operand changes the name of the symbol, do that
  // before we return the symbol.
  if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB && isDarwin) {
    MachineModuleInfoImpl::StubValueTy &StubSym =
      getMachOMMI(AP).getFnStubEntry(Sym);
    if (StubSym.getPointer())
      return Sym;
    
    if (MO.isGlobal()) {
      StubSym =
      MachineModuleInfoImpl::
      StubValueTy(AP.getSymbol(MO.getGlobal()),
                  !MO.getGlobal()->hasInternalLinkage());
    } else {
      StubSym =
      MachineModuleInfoImpl::
      StubValueTy(Ctx.GetOrCreateSymbol(OrigName), false);
    }
    return Sym;
  }

  // If the symbol reference is actually to a non_lazy_ptr, not to the symbol,
  // then add the suffix.
  if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) {
    MachineModuleInfoMachO &MachO = getMachOMMI(AP);
    
    MachineModuleInfoImpl::StubValueTy &StubSym =
      (MO.getTargetFlags() & PPCII::MO_NLP_HIDDEN_FLAG) ? 
         MachO.getHiddenGVStubEntry(Sym) : MachO.getGVStubEntry(Sym);
    
    if (!StubSym.getPointer()) {
      assert(MO.isGlobal() && "Extern symbol not handled yet");
      StubSym = MachineModuleInfoImpl::
                   StubValueTy(AP.getSymbol(MO.getGlobal()),
                               !MO.getGlobal()->hasInternalLinkage());
    }
    return Sym;
  }
  
  return Sym;
}
Example #7
0
/// createStructType - Create StructType for struct or union or class.
DIType DebugInfo::createStructType(tree type) {

  // struct { a; b; ... z; }; | union { a; b; ... z; };
  unsigned Tag = TREE_CODE(type) == RECORD_TYPE ? DW_TAG_structure_type :
    DW_TAG_union_type;
  
  unsigned RunTimeLang = 0;
  if (TYPE_LANG_SPECIFIC (type)
      && lang_hooks.types.is_runtime_specific_type (type))
    {
      unsigned CULang = TheCU.getLanguage();
      switch (CULang) {
      case DW_LANG_ObjC_plus_plus :
        RunTimeLang = DW_LANG_ObjC_plus_plus;
        break;
      case DW_LANG_ObjC :
        RunTimeLang = DW_LANG_ObjC;
        break;
      case DW_LANG_C_plus_plus :
        RunTimeLang = DW_LANG_C_plus_plus;
        break;
      default:
        break;
      }
    }
    
  // Records and classes and unions can all be recursive.  To handle them,
  // we first generate a debug descriptor for the struct as a forward 
  // declaration. Then (if it is a definition) we go through and get debug 
  // info for all of its members.  Finally, we create a descriptor for the
  // complete type (which may refer to the forward decl if the struct is 
  // recursive) and replace all  uses of the forward declaration with the 
  // final definition. 
  expanded_location Loc = GetNodeLocation(TREE_CHAIN(type), false);
  // FIXME: findRegion() is not able to find context all the time. This
  // means when type names in different context match then FwdDecl is
  // reused because MDNodes are uniqued. To avoid this, use type context
  /// also while creating FwdDecl for now.
  std::string FwdName;
  if (TYPE_CONTEXT(type)) {
    StringRef TypeContextName = GetNodeName(TYPE_CONTEXT(type));
    if (!TypeContextName.empty())
      FwdName = TypeContextName;
  }
  StringRef TypeName = GetNodeName(type);
  if (!TypeName.empty())
    FwdName = FwdName + TypeName.data();
  unsigned SFlags = 0;
  if (TYPE_BLOCK_IMPL_STRUCT(type))
    SFlags |= llvm::DIType::FlagAppleBlock;
  if (type_is_block_byref_struct(type))
    SFlags |= llvm::DIType::FlagBlockByrefStruct;
  DIDescriptor TyContext =  findRegion(TYPE_CONTEXT(type));

  // Check if this type is created while creating context information 
  // descriptor. 
  std::map<tree_node *, WeakVH >::iterator I = TypeCache.find(type);
  if (I != TypeCache.end())
    if (MDNode *TN = dyn_cast_or_null<MDNode>(I->second))
      return DIType(TN);
  
  llvm::DICompositeType FwdDecl =
    DebugFactory.CreateCompositeType(Tag, 
                                     TyContext,
                                     FwdName.c_str(),
                                     getOrCreateFile(Loc.file), 
                                     Loc.line, 
                                     0, 0, 0, SFlags | llvm::DIType::FlagFwdDecl,
                                     llvm::DIType(), llvm::DIArray(),
                                     RunTimeLang);
  
  // forward declaration, 
  if (TYPE_SIZE(type) == 0) 
    return FwdDecl;
  
  // Insert into the TypeCache so that recursive uses will find it.
  llvm::TrackingVH<llvm::MDNode> FwdDeclNode = FwdDecl.getNode();
  TypeCache[type] =  WeakVH(FwdDecl.getNode());

  // Push the struct on region stack.
  RegionStack.push_back(WeakVH(FwdDecl.getNode()));
  RegionMap[type] = WeakVH(FwdDecl.getNode());
  
  // Convert all the elements.
  llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
  
  if (tree binfo = TYPE_BINFO(type)) {
    VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo);

    for (unsigned i = 0, e = BINFO_N_BASE_BINFOS(binfo); i != e; ++i) {
      tree BInfo = BINFO_BASE_BINFO(binfo, i);
      tree BInfoType = BINFO_TYPE (BInfo);
      DIType BaseClass = getOrCreateType(BInfoType);
      unsigned BFlags = 0;
      if (BINFO_VIRTUAL_P (BInfo))
        BFlags = llvm::DIType::FlagVirtual;
      if (accesses) {
        tree access = VEC_index (tree, accesses, i);
        if (access == access_protected_node)
          BFlags |= llvm::DIType::FlagProtected;
        else if (access == access_private_node)
          BFlags |= llvm::DIType::FlagPrivate;
      }

      // Check for zero BINFO_OFFSET. 
      // FIXME : Is this correct ?
      unsigned Offset = BINFO_OFFSET(BInfo) ? 
	getINTEGER_CSTVal(BINFO_OFFSET(BInfo))*8 : 0;

      if (BINFO_VIRTUAL_P (BInfo))
        Offset = 0 - getINTEGER_CSTVal(BINFO_VPTR_FIELD (BInfo));
      // FIXME : name, size, align etc...
      DIType DTy = 
        DebugFactory.CreateDerivedType(DW_TAG_inheritance, 
                                       findRegion(TYPE_CONTEXT(type)), StringRef(),
                                       llvm::DIFile(), 0,0,0, 
                                       Offset,
                                       BFlags, BaseClass);
      EltTys.push_back(DTy);
    }
  }
  
  // Now add members of this class.
  for (tree Member = TYPE_FIELDS(type); Member;
       Member = TREE_CHAIN(Member)) {
    // Should we skip.
    if (DECL_P(Member) && DECL_IGNORED_P(Member)) continue;

    // Get the location of the member.
    expanded_location MemLoc = GetNodeLocation(Member, false);

    if (TREE_CODE(Member) != FIELD_DECL)
      // otherwise is a static variable, whose debug info is emitted
      // when through EmitGlobalVariable().
      continue;
      
    if (DECL_FIELD_OFFSET(Member) == 0 ||
        TREE_CODE(DECL_FIELD_OFFSET(Member)) != INTEGER_CST)
      // FIXME: field with variable position, skip it for now.
      continue;
    
    /* Ignore nameless fields.  */
    if (DECL_NAME (Member) == NULL_TREE
        && !(TREE_CODE (TREE_TYPE (Member)) == UNION_TYPE
             || TREE_CODE (TREE_TYPE (Member)) == RECORD_TYPE))
      continue;
    
    // Field type is the declared type of the field.
    tree FieldNodeType = FieldType(Member);
    DIType MemberType = getOrCreateType(FieldNodeType);
    StringRef MemberName = GetNodeName(Member);
    unsigned MFlags = 0;
    if (TREE_PROTECTED(Member))
      MFlags = llvm::DIType::FlagProtected;
    else if (TREE_PRIVATE(Member))
      MFlags = llvm::DIType::FlagPrivate;
    
    DIType DTy =
      DebugFactory.CreateDerivedType(DW_TAG_member, 
                                     findRegion(DECL_CONTEXT(Member)),
                                     MemberName, 
                                     getOrCreateFile(MemLoc.file),
                                     MemLoc.line, NodeSizeInBits(Member),
                                     NodeAlignInBits(FieldNodeType),
                                     int_bit_position(Member), 
                                     MFlags, MemberType);
    EltTys.push_back(DTy);
  }
  
  for (tree Member = TYPE_METHODS(type); Member;
       Member = TREE_CHAIN(Member)) {
    
    if (DECL_ABSTRACT_ORIGIN (Member)) continue;
    // Ignore unused aritificial members.
    if (DECL_ARTIFICIAL (Member) && !TREE_USED (Member)) continue;
    // In C++, TEMPLATE_DECLs are marked Ignored, and should be.
    if (DECL_P (Member) && DECL_IGNORED_P (Member)) continue;

    std::map<tree_node *, WeakVH >::iterator I = SPCache.find(Member);
    if (I != SPCache.end())
      EltTys.push_back(DISubprogram(cast<MDNode>(I->second)));
    else {
      // Get the location of the member.
      expanded_location MemLoc = GetNodeLocation(Member, false);
      StringRef MemberName = getFunctionName(Member);
      StringRef LinkageName = getLinkageName(Member);
      DIType SPTy = getOrCreateType(TREE_TYPE(Member));
      unsigned Virtuality = 0;
      unsigned VIndex = 0;
      DIType ContainingType;
      if (DECL_VINDEX (Member)) {
        if (host_integerp (DECL_VINDEX (Member), 0))
          VIndex = tree_low_cst (DECL_VINDEX (Member), 0);
        Virtuality = dwarf::DW_VIRTUALITY_virtual;
        ContainingType = getOrCreateType(DECL_CONTEXT(Member));
      }
      DISubprogram SP = 
        DebugFactory.CreateSubprogram(findRegion(DECL_CONTEXT(Member)), 
                                      MemberName, MemberName,
                                      LinkageName, 
                                      getOrCreateFile(MemLoc.file),
                                      MemLoc.line, SPTy, false, false,
                                      Virtuality, VIndex, ContainingType,
                                      DECL_ARTIFICIAL (Member), optimize);
      EltTys.push_back(SP);
      SPCache[Member] = WeakVH(SP.getNode());
    }
  }
  
  llvm::DIArray Elements =
    DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());

  RegionStack.pop_back();
  std::map<tree_node *, WeakVH>::iterator RI = RegionMap.find(type);
  if (RI != RegionMap.end())
    RegionMap.erase(RI);

  llvm::DIType ContainingType;
  if (TYPE_VFIELD (type)) {
    tree vtype = DECL_FCONTEXT (TYPE_VFIELD (type));
    ContainingType = getOrCreateType(vtype);
  }
  llvm::DICompositeType RealDecl =
    DebugFactory.CreateCompositeType(Tag, findRegion(TYPE_CONTEXT(type)),
                                     GetNodeName(type),
                                     getOrCreateFile(Loc.file),
                                     Loc.line, 
                                     NodeSizeInBits(type), NodeAlignInBits(type),
                                     0, SFlags, llvm::DIType(), Elements,
                                     RunTimeLang, ContainingType.getNode());
  RegionMap[type] = WeakVH(RealDecl.getNode());

  // Now that we have a real decl for the struct, replace anything using the
  // old decl with the new one.  This will recursively update the debug info.
  llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl);

  return RealDecl;
}
Example #8
0
bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
  PatternLoc = SMLoc::getFromPointer(PatternStr.data());

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      RegExStr += ')';
    }

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

  return false;
}
Example #9
0
/// Match - Match the pattern string against the input buffer Buffer.  This
/// returns the position that is matched or npos if there is no match.  If
/// there is a match, the size of the matched string is returned in MatchLen.
size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
                      StringMap<StringRef> &VariableTable) const {
  // If this is the EOF pattern, match it immediately.
  if (MatchEOF) {
    MatchLen = 0;
    return Buffer.size();
  }

  // If this is a fixed string pattern, just match it now.
  if (!FixedStr.empty()) {
    MatchLen = FixedStr.size();
    return Buffer.find(FixedStr);
  }

  // Regex match.

  // If there are variable uses, we need to create a temporary string with the
  // actual value.
  StringRef RegExToMatch = RegExStr;
  std::string TmpStr;
  if (!VariableUses.empty()) {
    TmpStr = RegExStr;

    unsigned InsertOffset = 0;
    for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
      StringMap<StringRef>::iterator it =
        VariableTable.find(VariableUses[i].first);
      // If the variable is undefined, return an error.
      if (it == VariableTable.end())
        return StringRef::npos;

      // Look up the value and escape it so that we can plop it into the regex.
      std::string Value;
      AddFixedStringToRegEx(it->second, Value);

      // Plop it into the regex at the adjusted offset.
      TmpStr.insert(TmpStr.begin()+VariableUses[i].second+InsertOffset,
                    Value.begin(), Value.end());
      InsertOffset += Value.size();
    }

    // Match the newly constructed regex.
    RegExToMatch = TmpStr;
  }


  SmallVector<StringRef, 4> MatchInfo;
  if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
    return StringRef::npos;

  // Successful regex match.
  assert(!MatchInfo.empty() && "Didn't get any match");
  StringRef FullMatch = MatchInfo[0];

  // If this defines any variables, remember their values.
  for (unsigned i = 0, e = VariableDefs.size(); i != e; ++i) {
    assert(VariableDefs[i].second < MatchInfo.size() &&
           "Internal paren error");
    VariableTable[VariableDefs[i].first] = MatchInfo[VariableDefs[i].second];
  }

  MatchLen = FullMatch.size();
  return FullMatch.data()-Buffer.data();
}
bool Punycode::decodePunycode(StringRef InputPunycode,
                              std::vector<uint32_t> &OutCodePoints) {
  OutCodePoints.clear();
  OutCodePoints.reserve(InputPunycode.size());

  // -- Build the decoded string as UTF32 first because we need random access.
  uint32_t n = initial_n;
  int i = 0;
  int bias = initial_bias;
  /// let output = an empty string indexed from 0
  // consume all code points before the last delimiter (if there is one)
  //  and copy them to output,
  size_t lastDelimiter = InputPunycode.find_last_of(delimiter);
  if (lastDelimiter != StringRef::npos) {
    for (char c : InputPunycode.slice(0, lastDelimiter)) {
      // fail on any non-basic code point
      if (static_cast<unsigned char>(c) > 0x7f)
        return true;
      OutCodePoints.push_back(c);
    }
    // if more than zero code points were consumed then consume one more
    //  (which will be the last delimiter)
    InputPunycode =
        InputPunycode.slice(lastDelimiter + 1, InputPunycode.size());
  }
  
  while (!InputPunycode.empty()) {
    int oldi = i;
    int w = 1;
    for (int k = base; ; k += base) {
      // consume a code point, or fail if there was none to consume
      if (InputPunycode.empty())
        return true;
      char codePoint = InputPunycode.front();
      InputPunycode = InputPunycode.slice(1, InputPunycode.size());
      // let digit = the code point's digit-value, fail if it has none
      int digit = digit_index(codePoint);
      if (digit < 0)
        return true;
      
      i = i + digit * w;
      int t = k <= bias ? tmin
            : k >= bias + tmax ? tmax
            : k - bias;
      if (digit < t)
        break;
      w = w * (base - t);
    }
    bias = adapt(i - oldi, OutCodePoints.size() + 1, oldi == 0);
    n = n + i / (OutCodePoints.size() + 1);
    i = i % (OutCodePoints.size() + 1);
    // if n is a basic code point then fail
    if (n < 0x80)
      return true;
    // insert n into output at position i
    OutCodePoints.insert(OutCodePoints.begin() + i, n);
    i++;
  }
  
  return true;
}
void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
  // Any decl can be declared with __asm("foo") on it, and this takes precedence
  // over all other naming in the .o file.
  if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
    // If we have an asm name, then we use it as the mangling.

    // Adding the prefix can cause problems when one file has a "foo" and
    // another has a "\01foo". That is known to happen on ELF with the
    // tricks normally used for producing aliases (PR9177). Fortunately the
    // llvm mangler on ELF is a nop, so we can just avoid adding the \01
    // marker.  We also avoid adding the marker if this is an alias for an
    // LLVM intrinsic.
    StringRef UserLabelPrefix =
        getASTContext().getTargetInfo().getUserLabelPrefix();
    if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm."))
      Out << '\01'; // LLVM IR Marker for __asm("foo")

    Out << ALA->getLabel();
    return;
  }

  const ASTContext &ASTContext = getASTContext();
  StdOrFastCC CC = getStdOrFastCallMangling(ASTContext, D);
  bool MCXX = shouldMangleCXXName(D);
  const TargetInfo &TI = Context.getTargetInfo();
  if (CC == SOF_OTHER || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
    mangleCXXName(D, Out);
    return;
  }

  Out << '\01';
  if (CC == SOF_STD)
    Out << '_';
  else
    Out << '@';

  if (!MCXX)
    Out << D->getIdentifier()->getName();
  else
    mangleCXXName(D, Out);

  const FunctionDecl *FD = cast<FunctionDecl>(D);
  const FunctionType *FT = FD->getType()->castAs<FunctionType>();
  const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT);
  Out << '@';
  if (!Proto) {
    Out << '0';
    return;
  }
  assert(!Proto->isVariadic());
  unsigned ArgWords = 0;
  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
    if (!MD->isStatic())
      ++ArgWords;
  for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
         ArgEnd = Proto->arg_type_end();
       Arg != ArgEnd; ++Arg) {
    QualType AT = *Arg;
    // Size should be aligned to DWORD boundary
    ArgWords += llvm::RoundUpToAlignment(ASTContext.getTypeSize(AT), 32) / 32;
  }
  Out << 4 * ArgWords;
}
SIMachineFunctionInfo::SIMachineFunctionInfo(const MachineFunction &MF)
  : AMDGPUMachineFunction(MF),
    BufferPSV(*(MF.getSubtarget().getInstrInfo())),
    ImagePSV(*(MF.getSubtarget().getInstrInfo())),
    PrivateSegmentBuffer(false),
    DispatchPtr(false),
    QueuePtr(false),
    KernargSegmentPtr(false),
    DispatchID(false),
    FlatScratchInit(false),
    GridWorkgroupCountX(false),
    GridWorkgroupCountY(false),
    GridWorkgroupCountZ(false),
    WorkGroupIDX(false),
    WorkGroupIDY(false),
    WorkGroupIDZ(false),
    WorkGroupInfo(false),
    PrivateSegmentWaveByteOffset(false),
    WorkItemIDX(false),
    WorkItemIDY(false),
    WorkItemIDZ(false),
    ImplicitBufferPtr(false),
    ImplicitArgPtr(false),
    GITPtrHigh(0xffffffff) {
  const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
  const Function &F = MF.getFunction();
  FlatWorkGroupSizes = ST.getFlatWorkGroupSizes(F);
  WavesPerEU = ST.getWavesPerEU(F);

  if (!isEntryFunction()) {
    // Non-entry functions have no special inputs for now, other registers
    // required for scratch access.
    ScratchRSrcReg = AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3;
    ScratchWaveOffsetReg = AMDGPU::SGPR4;
    FrameOffsetReg = AMDGPU::SGPR5;
    StackPtrOffsetReg = AMDGPU::SGPR32;

    ArgInfo.PrivateSegmentBuffer =
      ArgDescriptor::createRegister(ScratchRSrcReg);
    ArgInfo.PrivateSegmentWaveByteOffset =
      ArgDescriptor::createRegister(ScratchWaveOffsetReg);

    if (F.hasFnAttribute("amdgpu-implicitarg-ptr"))
      ImplicitArgPtr = true;
  } else {
    if (F.hasFnAttribute("amdgpu-implicitarg-ptr"))
      KernargSegmentPtr = true;
  }

  CallingConv::ID CC = F.getCallingConv();
  if (CC == CallingConv::AMDGPU_KERNEL || CC == CallingConv::SPIR_KERNEL) {
    if (!F.arg_empty())
      KernargSegmentPtr = true;
    WorkGroupIDX = true;
    WorkItemIDX = true;
  } else if (CC == CallingConv::AMDGPU_PS) {
    PSInputAddr = AMDGPU::getInitialPSInputAddr(F);
  }

  if (ST.debuggerEmitPrologue()) {
    // Enable everything.
    WorkGroupIDX = true;
    WorkGroupIDY = true;
    WorkGroupIDZ = true;
    WorkItemIDX = true;
    WorkItemIDY = true;
    WorkItemIDZ = true;
  } else {
    if (F.hasFnAttribute("amdgpu-work-group-id-x"))
      WorkGroupIDX = true;

    if (F.hasFnAttribute("amdgpu-work-group-id-y"))
      WorkGroupIDY = true;

    if (F.hasFnAttribute("amdgpu-work-group-id-z"))
      WorkGroupIDZ = true;

    if (F.hasFnAttribute("amdgpu-work-item-id-x"))
      WorkItemIDX = true;

    if (F.hasFnAttribute("amdgpu-work-item-id-y"))
      WorkItemIDY = true;

    if (F.hasFnAttribute("amdgpu-work-item-id-z"))
      WorkItemIDZ = true;
  }

  const MachineFrameInfo &FrameInfo = MF.getFrameInfo();
  bool MaySpill = ST.isVGPRSpillingEnabled(F);
  bool HasStackObjects = FrameInfo.hasStackObjects();

  if (isEntryFunction()) {
    // X, XY, and XYZ are the only supported combinations, so make sure Y is
    // enabled if Z is.
    if (WorkItemIDZ)
      WorkItemIDY = true;

    if (HasStackObjects || MaySpill) {
      PrivateSegmentWaveByteOffset = true;

    // HS and GS always have the scratch wave offset in SGPR5 on GFX9.
    if (ST.getGeneration() >= AMDGPUSubtarget::GFX9 &&
        (CC == CallingConv::AMDGPU_HS || CC == CallingConv::AMDGPU_GS))
      ArgInfo.PrivateSegmentWaveByteOffset
        = ArgDescriptor::createRegister(AMDGPU::SGPR5);
    }
  }

  bool IsCOV2 = ST.isAmdCodeObjectV2(MF);
  if (IsCOV2) {
    if (HasStackObjects || MaySpill)
      PrivateSegmentBuffer = true;

    if (F.hasFnAttribute("amdgpu-dispatch-ptr"))
      DispatchPtr = true;

    if (F.hasFnAttribute("amdgpu-queue-ptr"))
      QueuePtr = true;

    if (F.hasFnAttribute("amdgpu-dispatch-id"))
      DispatchID = true;
  } else if (ST.isMesaGfxShader(MF)) {
    if (HasStackObjects || MaySpill)
      ImplicitBufferPtr = true;
  }

  if (F.hasFnAttribute("amdgpu-kernarg-segment-ptr"))
    KernargSegmentPtr = true;

  if (ST.hasFlatAddressSpace() && isEntryFunction() && IsCOV2) {
    // TODO: This could be refined a lot. The attribute is a poor way of
    // detecting calls that may require it before argument lowering.
    if (HasStackObjects || F.hasFnAttribute("amdgpu-flat-scratch"))
      FlatScratchInit = true;
  }

  Attribute A = F.getFnAttribute("amdgpu-git-ptr-high");
  StringRef S = A.getValueAsString();
  if (!S.empty())
    S.consumeInteger(0, GITPtrHigh);
}
static std::string mangleConstant(SILDeclRef c, StringRef prefix) {
  using namespace Mangle;
  Mangler mangler;

  // Almost everything below gets one of the common prefixes:
  //   mangled-name ::= '_T' global     // Native symbol
  //   mangled-name ::= '_TTo' global   // ObjC interop thunk
  //   mangled-name ::= '_TTO' global   // Foreign function thunk
  //   mangled-name ::= '_TTd' global   // Direct
  StringRef introducer = "_T";
  if (!prefix.empty()) {
    introducer = prefix;
  } else if (c.isForeign) {
    assert(prefix.empty() && "can't have custom prefix on thunk");
    introducer = "_TTo";
  } else if (c.isDirectReference) {
    introducer = "_TTd";
  } else if (c.isForeignToNativeThunk()) {
    assert(prefix.empty() && "can't have custom prefix on thunk");
    introducer = "_TTO";
  }
  
  // As a special case, Clang functions and globals don't get mangled at all.
  if (c.hasDecl()) {
    if (auto clangDecl = c.getDecl()->getClangDecl()) {
      if (!c.isForeignToNativeThunk() && !c.isNativeToForeignThunk()
          && !c.isCurried) {
        if (auto namedClangDecl = dyn_cast<clang::DeclaratorDecl>(clangDecl)) {
          if (auto asmLabel = namedClangDecl->getAttr<clang::AsmLabelAttr>()) {
            mangler.append('\01');
            mangler.append(asmLabel->getLabel());
          } else if (namedClangDecl->hasAttr<clang::OverloadableAttr>()) {
            std::string storage;
            llvm::raw_string_ostream SS(storage);
            // FIXME: When we can import C++, use Clang's mangler all the time.
            mangleClangDecl(SS, namedClangDecl,
                            c.getDecl()->getASTContext());
            mangler.append(SS.str());
          } else {
            mangler.append(namedClangDecl->getName());
          }
          return mangler.finalize();
        }
      }
    }
  }
  
  switch (c.kind) {
  //   entity ::= declaration                     // other declaration
  case SILDeclRef::Kind::Func:
    if (!c.hasDecl()) {
      mangler.append(introducer);
      mangler.mangleClosureEntity(c.getAbstractClosureExpr(),
                                  c.uncurryLevel);
      return mangler.finalize();
    }

    // As a special case, functions can have manually mangled names.
    // Use the SILGen name only for the original non-thunked, non-curried entry
    // point.
    if (auto NameA = c.getDecl()->getAttrs().getAttribute<SILGenNameAttr>())
      if (!c.isForeignToNativeThunk() && !c.isNativeToForeignThunk()
          && !c.isCurried) {
        mangler.append(NameA->Name);
        return mangler.finalize();
      }
      
    // Use a given cdecl name for native-to-foreign thunks.
    if (auto CDeclA = c.getDecl()->getAttrs().getAttribute<CDeclAttr>())
      if (c.isNativeToForeignThunk()) {
        mangler.append(CDeclA->Name);
        return mangler.finalize();
      }

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

  case SILDeclRef::Kind::EnumElement:
    mangler.append(introducer);
    mangler.mangleEntity(c.getDecl(), c.uncurryLevel);
    return mangler.finalize();

  //   entity ::= context 'D'                     // deallocating destructor
  case SILDeclRef::Kind::Deallocator:
    mangler.append(introducer);
    mangler.mangleDestructorEntity(cast<DestructorDecl>(c.getDecl()),
                                   /*isDeallocating*/ true);
    return mangler.finalize();

  //   entity ::= context 'd'                     // destroying destructor
  case SILDeclRef::Kind::Destroyer:
    mangler.append(introducer);
    mangler.mangleDestructorEntity(cast<DestructorDecl>(c.getDecl()),
                                   /*isDeallocating*/ false);
    return mangler.finalize();

  //   entity ::= context 'C' type                // allocating constructor
  case SILDeclRef::Kind::Allocator:
    mangler.append(introducer);
    mangler.mangleConstructorEntity(cast<ConstructorDecl>(c.getDecl()),
                                    /*allocating*/ true,
                                    c.uncurryLevel);
    return mangler.finalize();

  //   entity ::= context 'c' type                // initializing constructor
  case SILDeclRef::Kind::Initializer:
    mangler.append(introducer);
    mangler.mangleConstructorEntity(cast<ConstructorDecl>(c.getDecl()),
                                    /*allocating*/ false,
                                    c.uncurryLevel);
    return mangler.finalize();

  //   entity ::= declaration 'e'                 // ivar initializer
  //   entity ::= declaration 'E'                 // ivar destroyer
  case SILDeclRef::Kind::IVarInitializer:
  case SILDeclRef::Kind::IVarDestroyer:
    mangler.append(introducer);
    mangler.mangleIVarInitDestroyEntity(
      cast<ClassDecl>(c.getDecl()),
      c.kind == SILDeclRef::Kind::IVarDestroyer);
    return mangler.finalize();

  //   entity ::= declaration 'a'                 // addressor
  case SILDeclRef::Kind::GlobalAccessor:
    mangler.append(introducer);
    mangler.mangleAddressorEntity(c.getDecl());
    return mangler.finalize();

  //   entity ::= declaration 'G'                 // getter
  case SILDeclRef::Kind::GlobalGetter:
    mangler.append(introducer);
    mangler.mangleGlobalGetterEntity(c.getDecl());
    return mangler.finalize();

  //   entity ::= context 'e' index           // default arg generator
  case SILDeclRef::Kind::DefaultArgGenerator:
    mangler.append(introducer);
    mangler.mangleDefaultArgumentEntity(cast<AbstractFunctionDecl>(c.getDecl()),
                                        c.defaultArgIndex);
    return mangler.finalize();
  }

  llvm_unreachable("bad entity kind!");
}
Example #14
0
std::string Triple::normalize(StringRef Str) {
  bool IsMinGW32 = false;
  bool IsCygwin = false;

  // Parse into components.
  SmallVector<StringRef, 4> Components;
  Str.split(Components, "-");

  // If the first component corresponds to a known architecture, preferentially
  // use it for the architecture.  If the second component corresponds to a
  // known vendor, preferentially use it for the vendor, etc.  This avoids silly
  // component movement when a component parses as (eg) both a valid arch and a
  // valid os.
  ArchType Arch = UnknownArch;
  if (Components.size() > 0)
    Arch = parseArch(Components[0]);
  VendorType Vendor = UnknownVendor;
  if (Components.size() > 1)
    Vendor = parseVendor(Components[1]);
  OSType OS = UnknownOS;
  if (Components.size() > 2) {
    OS = parseOS(Components[2]);
    IsCygwin = Components[2].startswith("cygwin");
    IsMinGW32 = Components[2].startswith("mingw");
  }
  EnvironmentType Environment = UnknownEnvironment;
  if (Components.size() > 3)
    Environment = parseEnvironment(Components[3]);
  ObjectFormatType ObjectFormat = UnknownObjectFormat;
  if (Components.size() > 4)
    ObjectFormat = parseFormat(Components[4]);

  // Note which components are already in their final position.  These will not
  // be moved.
  bool Found[4];
  Found[0] = Arch != UnknownArch;
  Found[1] = Vendor != UnknownVendor;
  Found[2] = OS != UnknownOS;
  Found[3] = Environment != UnknownEnvironment;

  // If they are not there already, permute the components into their canonical
  // positions by seeing if they parse as a valid architecture, and if so moving
  // the component to the architecture position etc.
  for (unsigned Pos = 0; Pos != array_lengthof(Found); ++Pos) {
    if (Found[Pos])
      continue; // Already in the canonical position.

    for (unsigned Idx = 0; Idx != Components.size(); ++Idx) {
      // Do not reparse any components that already matched.
      if (Idx < array_lengthof(Found) && Found[Idx])
        continue;

      // Does this component parse as valid for the target position?
      bool Valid = false;
      StringRef Comp = Components[Idx];
      switch (Pos) {
      default: llvm_unreachable("unexpected component type!");
      case 0:
        Arch = parseArch(Comp);
        Valid = Arch != UnknownArch;
        break;
      case 1:
        Vendor = parseVendor(Comp);
        Valid = Vendor != UnknownVendor;
        break;
      case 2:
        OS = parseOS(Comp);
        IsCygwin = Comp.startswith("cygwin");
        IsMinGW32 = Comp.startswith("mingw");
        Valid = OS != UnknownOS || IsCygwin || IsMinGW32;
        break;
      case 3:
        Environment = parseEnvironment(Comp);
        Valid = Environment != UnknownEnvironment;
        if (!Valid) {
          ObjectFormat = parseFormat(Comp);
          Valid = ObjectFormat != UnknownObjectFormat;
        }
        break;
      }
      if (!Valid)
        continue; // Nope, try the next component.

      // Move the component to the target position, pushing any non-fixed
      // components that are in the way to the right.  This tends to give
      // good results in the common cases of a forgotten vendor component
      // or a wrongly positioned environment.
      if (Pos < Idx) {
        // Insert left, pushing the existing components to the right.  For
        // example, a-b-i386 -> i386-a-b when moving i386 to the front.
        StringRef CurrentComponent(""); // The empty component.
        // Replace the component we are moving with an empty component.
        std::swap(CurrentComponent, Components[Idx]);
        // Insert the component being moved at Pos, displacing any existing
        // components to the right.
        for (unsigned i = Pos; !CurrentComponent.empty(); ++i) {
          // Skip over any fixed components.
          while (i < array_lengthof(Found) && Found[i])
            ++i;
          // Place the component at the new position, getting the component
          // that was at this position - it will be moved right.
          std::swap(CurrentComponent, Components[i]);
        }
      } else if (Pos > Idx) {
        // Push right by inserting empty components until the component at Idx
        // reaches the target position Pos.  For example, pc-a -> -pc-a when
        // moving pc to the second position.
        do {
          // Insert one empty component at Idx.
          StringRef CurrentComponent(""); // The empty component.
          for (unsigned i = Idx; i < Components.size();) {
            // Place the component at the new position, getting the component
            // that was at this position - it will be moved right.
            std::swap(CurrentComponent, Components[i]);
            // If it was placed on top of an empty component then we are done.
            if (CurrentComponent.empty())
              break;
            // Advance to the next component, skipping any fixed components.
            while (++i < array_lengthof(Found) && Found[i])
              ;
          }
          // The last component was pushed off the end - append it.
          if (!CurrentComponent.empty())
            Components.push_back(CurrentComponent);

          // Advance Idx to the component's new position.
          while (++Idx < array_lengthof(Found) && Found[Idx])
            ;
        } while (Idx < Pos); // Add more until the final position is reached.
      }
      assert(Pos < Components.size() && Components[Pos] == Comp &&
             "Component moved wrong!");
      Found[Pos] = true;
      break;
    }
  }

  // Special case logic goes here.  At this point Arch, Vendor and OS have the
  // correct values for the computed components.
  std::string NormalizedEnvironment;
  if (Environment == Triple::Android && Components[3].startswith("androideabi")) {
    StringRef AndroidVersion = Components[3].drop_front(strlen("androideabi"));
    if (AndroidVersion.empty()) {
      Components[3] = "android";
    } else {
      NormalizedEnvironment = Twine("android", AndroidVersion).str();
      Components[3] = NormalizedEnvironment;
    }
  }

  if (OS == Triple::Win32) {
    Components.resize(4);
    Components[2] = "windows";
    if (Environment == UnknownEnvironment) {
      if (ObjectFormat == UnknownObjectFormat || ObjectFormat == Triple::COFF)
        Components[3] = "msvc";
      else
        Components[3] = getObjectFormatTypeName(ObjectFormat);
    }
  } else if (IsMinGW32) {
    Components.resize(4);
    Components[2] = "windows";
    Components[3] = "gnu";
  } else if (IsCygwin) {
    Components.resize(4);
    Components[2] = "windows";
    Components[3] = "cygnus";
  }
  if (IsMinGW32 || IsCygwin ||
      (OS == Triple::Win32 && Environment != UnknownEnvironment)) {
    if (ObjectFormat != UnknownObjectFormat && ObjectFormat != Triple::COFF) {
      Components.resize(5);
      Components[4] = getObjectFormatTypeName(ObjectFormat);
    }
  }

  // Stick the corrected components back together to form the normalized string.
  std::string Normalized;
  for (unsigned i = 0, e = Components.size(); i != e; ++i) {
    if (i) Normalized += '-';
    Normalized += Components[i];
  }
  return Normalized;
}
// Unbundle the files. Return true if an error was found.
static bool UnbundleFiles() {
  // Open Input file.
  ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
      MemoryBuffer::getFileOrSTDIN(InputFileNames.front());
  if (std::error_code EC = CodeOrErr.getError()) {
    errs() << "error: Can't open file " << InputFileNames.front() << ": "
           << EC.message() << "\n";
    return true;
  }

  MemoryBuffer &Input = *CodeOrErr.get();

  // Select the right files handler.
  std::unique_ptr<FileHandler> FH;
  FH.reset(CreateFileHandler(Input));

  // Quit if we don't have a handler.
  if (!FH.get())
    return true;

  // Read the header of the bundled file.
  FH.get()->ReadHeader(Input);

  // Create a work list that consist of the map triple/output file.
  StringMap<StringRef> Worklist;
  auto Output = OutputFileNames.begin();
  for (auto &Triple : TargetNames) {
    Worklist[Triple] = *Output;
    ++Output;
  }

  // Read all the bundles that are in the work list. If we find no bundles we
  // assume the file is meant for the host target.
  bool FoundHostBundle = false;
  while (!Worklist.empty()) {
    StringRef CurTriple = FH.get()->ReadBundleStart(Input);

    // We don't have more bundles.
    if (CurTriple.empty())
      break;

    auto Output = Worklist.find(CurTriple);
    // The file may have more bundles for other targets, that we don't care
    // about. Therefore, move on to the next triple
    if (Output == Worklist.end()) {
      continue;
    }

    // Check if the output file can be opened and copy the bundle to it.
    std::error_code EC;
    raw_fd_ostream OutputFile(Output->second, EC, sys::fs::F_None);
    if (EC) {
      errs() << "error: Can't open file " << Output->second << ": "
             << EC.message() << "\n";
      return true;
    }
    FH.get()->ReadBundle(OutputFile, Input);
    FH.get()->ReadBundleEnd(Input);
    Worklist.erase(Output);

    // Record if we found the host bundle.
    if (hasHostKind(CurTriple))
      FoundHostBundle = true;
  }

  // If no bundles were found, assume the input file is the host bundle and
  // create empty files for the remaining targets.
  if (Worklist.size() == TargetNames.size()) {
    for (auto &E : Worklist) {
      std::error_code EC;
      raw_fd_ostream OutputFile(E.second, EC, sys::fs::F_None);
      if (EC) {
        errs() << "error: Can't open file " << E.second << ": " << EC.message()
               << "\n";
        return true;
      }

      // If this entry has a host kind, copy the input file to the output file.
      if (hasHostKind(E.first()))
        OutputFile.write(Input.getBufferStart(), Input.getBufferSize());
    }
    return false;
  }

  // If we found elements, we emit an error if none of those were for the host.
  if (!FoundHostBundle) {
    errs() << "error: Can't find bundle for the host target\n";
    return true;
  }

  // If we still have any elements in the worklist, create empty files for them.
  for (auto &E : Worklist) {
    std::error_code EC;
    raw_fd_ostream OutputFile(E.second, EC, sys::fs::F_None);
    if (EC) {
      errs() << "error: Can't open file " << E.second << ": "  << EC.message()
             << "\n";
      return true;
    }
  }

  return false;
}
Example #16
0
/// ReadCheckFile - Read the check file, which specifies the sequence of
/// expected strings.  The strings are added to the CheckStrings vector.
static bool ReadCheckFile(SourceMgr &SM,
                          std::vector<CheckString> &CheckStrings) {
  // Open the check file, and tell SourceMgr about it.
  OwningPtr<MemoryBuffer> File;
  if (error_code ec =
        MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), File)) {
    errs() << "Could not open check file '" << CheckFilename << "': "
           << ec.message() << '\n';
    return true;
  }
  MemoryBuffer *F = File.take();

  // If we want to canonicalize whitespace, strip excess whitespace from the
  // buffer containing the CHECK lines.
  if (!NoCanonicalizeWhiteSpace)
    F = CanonicalizeInputFile(F);

  SM.AddNewSourceBuffer(F, SMLoc());

  // Find all instances of CheckPrefix followed by : in the file.
  StringRef Buffer = F->getBuffer();

  std::vector<std::pair<SMLoc, Pattern> > NotMatches;

  while (1) {
    // See if Prefix occurs in the memory buffer.
    Buffer = Buffer.substr(Buffer.find(CheckPrefix));

    // If we didn't find a match, we're done.
    if (Buffer.empty())
      break;

    const char *CheckPrefixStart = Buffer.data();

    // When we find a check prefix, keep track of whether we find CHECK: or
    // CHECK-NEXT:
    bool IsCheckNext = false, IsCheckNot = false;

    // Verify that the : is present after the prefix.
    if (Buffer[CheckPrefix.size()] == ':') {
      Buffer = Buffer.substr(CheckPrefix.size()+1);
    } else if (Buffer.size() > CheckPrefix.size()+6 &&
               memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
      Buffer = Buffer.substr(CheckPrefix.size()+7);
      IsCheckNext = true;
    } else if (Buffer.size() > CheckPrefix.size()+5 &&
               memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
      Buffer = Buffer.substr(CheckPrefix.size()+6);
      IsCheckNot = true;
    } else {
      Buffer = Buffer.substr(1);
      continue;
    }

    // Okay, we found the prefix, yay.  Remember the rest of the line, but
    // ignore leading and trailing whitespace.
    Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));

    // Scan ahead to the end of line.
    size_t EOL = Buffer.find_first_of("\n\r");

    // Remember the location of the start of the pattern, for diagnostics.
    SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());

    // Parse the pattern.
    Pattern P;
    if (P.ParsePattern(Buffer.substr(0, EOL), SM))
      return true;

    Buffer = Buffer.substr(EOL);


    // Verify that CHECK-NEXT lines have at least one CHECK line before them.
    if (IsCheckNext && CheckStrings.empty()) {
      SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
                      "found '"+CheckPrefix+"-NEXT:' without previous '"+
                      CheckPrefix+ ": line", "error");
      return true;
    }

    // Handle CHECK-NOT.
    if (IsCheckNot) {
      NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
                                          P));
      continue;
    }


    // Okay, add the string we captured to the output vector and move on.
    CheckStrings.push_back(CheckString(P,
                                       PatternLoc,
                                       IsCheckNext));
    std::swap(NotMatches, CheckStrings.back().NotStrings);
  }

  // Add an EOF pattern for any trailing CHECK-NOTs.
  if (!NotMatches.empty()) {
    CheckStrings.push_back(CheckString(Pattern(true),
                                       SMLoc::getFromPointer(Buffer.data()),
                                       false));
    std::swap(NotMatches, CheckStrings.back().NotStrings);
  }

  if (CheckStrings.empty()) {
    errs() << "error: no check strings found with prefix '" << CheckPrefix
           << ":'\n";
    return true;
  }

  return false;
}
int main(int argc, const char **argv) {
  sys::PrintStackTraceOnErrorSignal(argv[0]);

  cl::HideUnrelatedOptions(ClangOffloadBundlerCategory);
  cl::SetVersionPrinter(PrintVersion);
  cl::ParseCommandLineOptions(
      argc, argv,
      "A tool to bundle several input files of the specified type <type> \n"
      "referring to the same source file but different targets into a single \n"
      "one. The resulting file can also be unbundled into different files by \n"
      "this tool if -unbundle is provided.\n");

  if (Help) {
    cl::PrintHelpMessage();
    return 0;
  }

  bool Error = false;
  if (Unbundle) {
    if (InputFileNames.size() != 1) {
      Error = true;
      errs() << "error: only one input file supported in unbundling mode.\n";
    }
    if (OutputFileNames.size() != TargetNames.size()) {
      Error = true;
      errs() << "error: number of output files and targets should match in "
                "unbundling mode.\n";
    }
  } else {
    if (OutputFileNames.size() != 1) {
      Error = true;
      errs() << "error: only one output file supported in bundling mode.\n";
    }
    if (InputFileNames.size() != TargetNames.size()) {
      Error = true;
      errs() << "error: number of input files and targets should match in "
                "bundling mode.\n";
    }
  }

  // Verify that the offload kinds and triples are known. We also check that we
  // have exactly one host target.
  unsigned Index = 0u;
  unsigned HostTargetNum = 0u;
  for (StringRef Target : TargetNames) {
    StringRef Kind;
    StringRef Triple;
    getOffloadKindAndTriple(Target, Kind, Triple);

    bool KindIsValid = !Kind.empty();
    KindIsValid = KindIsValid && StringSwitch<bool>(Kind)
                                     .Case("host", true)
                                     .Case("openmp", true)
                                     .Case("hip", true)
                                     .Default(false);

    bool TripleIsValid = !Triple.empty();
    llvm::Triple T(Triple);
    TripleIsValid &= T.getArch() != Triple::UnknownArch;

    if (!KindIsValid || !TripleIsValid) {
      Error = true;
      errs() << "error: invalid target '" << Target << "'";

      if (!KindIsValid)
        errs() << ", unknown offloading kind '" << Kind << "'";
      if (!TripleIsValid)
        errs() << ", unknown target triple '" << Triple << "'";
      errs() << ".\n";
    }

    if (KindIsValid && Kind == "host") {
      ++HostTargetNum;
      // Save the index of the input that refers to the host.
      HostInputIndex = Index;
    }

    ++Index;
  }

  if (HostTargetNum != 1) {
    Error = true;
    errs() << "error: expecting exactly one host target but got "
           << HostTargetNum << ".\n";
  }

  if (Error)
    return 1;

  // Save the current executable directory as it will be useful to find other
  // tools.
  BundlerExecutable = sys::fs::getMainExecutable(argv[0], &BundlerExecutable);

  return Unbundle ? UnbundleFiles() : BundleFiles();
}
Example #18
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;
  }
}
Example #19
0
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode,
                               InlineAsm::AsmDialect Dialect) const {
  assert(!Str.empty() && "Can't emit empty inline asm block");

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

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

  SourceMgr SrcMgr;
  SrcMgrDiagInfo DiagInfo;

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

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

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

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

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

  // Don't implicitly switch to the text section before the asm.
  int Res = Parser->Run(/*NoInitialTextSection*/ true,
                        /*NoFinalize*/ true);
  if (Res && !HasDiagHandler)
    report_fatal_error("Error parsing inline asm\n");
}
Example #20
0
void cl::ParseCommandLineOptions(int argc, char **argv,
                                 const char *Overview, bool ReadResponseFiles) {
  // Process all registered options.
  SmallVector<Option*, 4> PositionalOpts;
  SmallVector<Option*, 4> SinkOpts;
  StringMap<Option*> Opts;
  GetOptionInfo(PositionalOpts, SinkOpts, Opts);

  assert((!Opts.empty() || !PositionalOpts.empty()) &&
         "No options specified!");

  // Expand response files.
  std::vector<char*> newArgv;
  if (ReadResponseFiles) {
    newArgv.push_back(strdup(argv[0]));
    ExpandResponseFiles(argc, argv, newArgv);
    argv = &newArgv[0];
    argc = static_cast<int>(newArgv.size());
  }

  // Copy the program name into ProgName, making sure not to overflow it.
  std::string ProgName = sys::path::filename(argv[0]);
  size_t Len = std::min(ProgName.size(), size_t(79));
  memcpy(ProgramName, ProgName.data(), Len);
  ProgramName[Len] = '\0';

  ProgramOverview = Overview;
  bool ErrorParsing = false;

  // Check out the positional arguments to collect information about them.
  unsigned NumPositionalRequired = 0;

  // Determine whether or not there are an unlimited number of positionals
  bool HasUnlimitedPositionals = false;

  Option *ConsumeAfterOpt = 0;
  if (!PositionalOpts.empty()) {
    if (PositionalOpts[0]->getNumOccurrencesFlag() == cl::ConsumeAfter) {
      assert(PositionalOpts.size() > 1 &&
             "Cannot specify cl::ConsumeAfter without a positional argument!");
      ConsumeAfterOpt = PositionalOpts[0];
    }

    // Calculate how many positional values are _required_.
    bool UnboundedFound = false;
    for (size_t i = ConsumeAfterOpt != 0, e = PositionalOpts.size();
         i != e; ++i) {
      Option *Opt = PositionalOpts[i];
      if (RequiresValue(Opt))
        ++NumPositionalRequired;
      else if (ConsumeAfterOpt) {
        // ConsumeAfter cannot be combined with "optional" positional options
        // unless there is only one positional argument...
        if (PositionalOpts.size() > 2)
          ErrorParsing |=
            Opt->error("error - this positional option will never be matched, "
                       "because it does not Require a value, and a "
                       "cl::ConsumeAfter option is active!");
      } else if (UnboundedFound && !Opt->ArgStr[0]) {
        // This option does not "require" a value...  Make sure this option is
        // not specified after an option that eats all extra arguments, or this
        // one will never get any!
        //
        ErrorParsing |= Opt->error("error - option can never match, because "
                                   "another positional argument will match an "
                                   "unbounded number of values, and this option"
                                   " does not require a value!");
      }
      UnboundedFound |= EatsUnboundedNumberOfValues(Opt);
    }
    HasUnlimitedPositionals = UnboundedFound || ConsumeAfterOpt;
  }

  // PositionalVals - A vector of "positional" arguments we accumulate into
  // the process at the end.
  //
  SmallVector<std::pair<StringRef,unsigned>, 4> PositionalVals;

  // If the program has named positional arguments, and the name has been run
  // across, keep track of which positional argument was named.  Otherwise put
  // the positional args into the PositionalVals list...
  Option *ActivePositionalArg = 0;

  // Loop over all of the arguments... processing them.
  bool DashDashFound = false;  // Have we read '--'?
  for (int i = 1; i < argc; ++i) {
    Option *Handler = 0;
    Option *NearestHandler = 0;
    std::string NearestHandlerString;
    StringRef Value;
    StringRef ArgName = "";

    // If the option list changed, this means that some command line
    // option has just been registered or deregistered.  This can occur in
    // response to things like -load, etc.  If this happens, rescan the options.
    if (OptionListChanged) {
      PositionalOpts.clear();
      SinkOpts.clear();
      Opts.clear();
      GetOptionInfo(PositionalOpts, SinkOpts, Opts);
      OptionListChanged = false;
    }

    // Check to see if this is a positional argument.  This argument is
    // considered to be positional if it doesn't start with '-', if it is "-"
    // itself, or if we have seen "--" already.
    //
    if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) {
      // Positional argument!
      if (ActivePositionalArg) {
        ProvidePositionalOption(ActivePositionalArg, argv[i], i);
        continue;  // We are done!
      }

      if (!PositionalOpts.empty()) {
        PositionalVals.push_back(std::make_pair(argv[i],i));

        // All of the positional arguments have been fulfulled, give the rest to
        // the consume after option... if it's specified...
        //
        if (PositionalVals.size() >= NumPositionalRequired &&
            ConsumeAfterOpt != 0) {
          for (++i; i < argc; ++i)
            PositionalVals.push_back(std::make_pair(argv[i],i));
          break;   // Handle outside of the argument processing loop...
        }

        // Delay processing positional arguments until the end...
        continue;
      }
    } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 &&
               !DashDashFound) {
      DashDashFound = true;  // This is the mythical "--"?
      continue;              // Don't try to process it as an argument itself.
    } else if (ActivePositionalArg &&
               (ActivePositionalArg->getMiscFlags() & PositionalEatsArgs)) {
      // If there is a positional argument eating options, check to see if this
      // option is another positional argument.  If so, treat it as an argument,
      // otherwise feed it to the eating positional.
      ArgName = argv[i]+1;
      // Eat leading dashes.
      while (!ArgName.empty() && ArgName[0] == '-')
        ArgName = ArgName.substr(1);

      Handler = LookupOption(ArgName, Value, Opts);
      if (!Handler || Handler->getFormattingFlag() != cl::Positional) {
        ProvidePositionalOption(ActivePositionalArg, argv[i], i);
        continue;  // We are done!
      }

    } else {     // We start with a '-', must be an argument.
      ArgName = argv[i]+1;
      // Eat leading dashes.
      while (!ArgName.empty() && ArgName[0] == '-')
        ArgName = ArgName.substr(1);

      Handler = LookupOption(ArgName, Value, Opts);

      // Check to see if this "option" is really a prefixed or grouped argument.
      if (Handler == 0)
        Handler = HandlePrefixedOrGroupedOption(ArgName, Value,
                                                ErrorParsing, Opts);

      // Otherwise, look for the closest available option to report to the user
      // in the upcoming error.
      if (Handler == 0 && SinkOpts.empty())
        NearestHandler = LookupNearestOption(ArgName, Opts,
                                             NearestHandlerString);
    }

    if (Handler == 0) {
      if (SinkOpts.empty()) {
        errs() << ProgramName << ": Unknown command line argument '"
             << argv[i] << "'.  Try: '" << argv[0] << " -help'\n";

        if (NearestHandler) {
          // If we know a near match, report it as well.
          errs() << ProgramName << ": Did you mean '-"
                 << NearestHandlerString << "'?\n";
        }

        ErrorParsing = true;
      } else {
        for (SmallVectorImpl<Option*>::iterator I = SinkOpts.begin(),
               E = SinkOpts.end(); I != E ; ++I)
          (*I)->addOccurrence(i, "", argv[i]);
      }
      continue;
    }

    // If this is a named positional argument, just remember that it is the
    // active one...
    if (Handler->getFormattingFlag() == cl::Positional)
      ActivePositionalArg = Handler;
    else
      ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i);
  }

  // Check and handle positional arguments now...
  if (NumPositionalRequired > PositionalVals.size()) {
    errs() << ProgramName
         << ": Not enough positional command line arguments specified!\n"
         << "Must specify at least " << NumPositionalRequired
         << " positional arguments: See: " << argv[0] << " -help\n";

    ErrorParsing = true;
  } else if (!HasUnlimitedPositionals &&
             PositionalVals.size() > PositionalOpts.size()) {
    errs() << ProgramName
         << ": Too many positional arguments specified!\n"
         << "Can specify at most " << PositionalOpts.size()
         << " positional arguments: See: " << argv[0] << " -help\n";
    ErrorParsing = true;

  } else if (ConsumeAfterOpt == 0) {
    // Positional args have already been handled if ConsumeAfter is specified.
    unsigned ValNo = 0, NumVals = static_cast<unsigned>(PositionalVals.size());
    for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) {
      if (RequiresValue(PositionalOpts[i])) {
        ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo].first,
                                PositionalVals[ValNo].second);
        ValNo++;
        --NumPositionalRequired;  // We fulfilled our duty...
      }

      // If we _can_ give this option more arguments, do so now, as long as we
      // do not give it values that others need.  'Done' controls whether the
      // option even _WANTS_ any more.
      //
      bool Done = PositionalOpts[i]->getNumOccurrencesFlag() == cl::Required;
      while (NumVals-ValNo > NumPositionalRequired && !Done) {
        switch (PositionalOpts[i]->getNumOccurrencesFlag()) {
        case cl::Optional:
          Done = true;          // Optional arguments want _at most_ one value
          // FALL THROUGH
        case cl::ZeroOrMore:    // Zero or more will take all they can get...
        case cl::OneOrMore:     // One or more will take all they can get...
          ProvidePositionalOption(PositionalOpts[i],
                                  PositionalVals[ValNo].first,
                                  PositionalVals[ValNo].second);
          ValNo++;
          break;
        default:
          llvm_unreachable("Internal error, unexpected NumOccurrences flag in "
                 "positional argument processing!");
        }
      }
    }
  } else {
    assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size());
    unsigned ValNo = 0;
    for (size_t j = 1, e = PositionalOpts.size(); j != e; ++j)
      if (RequiresValue(PositionalOpts[j])) {
        ErrorParsing |= ProvidePositionalOption(PositionalOpts[j],
                                                PositionalVals[ValNo].first,
                                                PositionalVals[ValNo].second);
        ValNo++;
      }

    // Handle the case where there is just one positional option, and it's
    // optional.  In this case, we want to give JUST THE FIRST option to the
    // positional option and keep the rest for the consume after.  The above
    // loop would have assigned no values to positional options in this case.
    //
    if (PositionalOpts.size() == 2 && ValNo == 0 && !PositionalVals.empty()) {
      ErrorParsing |= ProvidePositionalOption(PositionalOpts[1],
                                              PositionalVals[ValNo].first,
                                              PositionalVals[ValNo].second);
      ValNo++;
    }

    // Handle over all of the rest of the arguments to the
    // cl::ConsumeAfter command line option...
    for (; ValNo != PositionalVals.size(); ++ValNo)
      ErrorParsing |= ProvidePositionalOption(ConsumeAfterOpt,
                                              PositionalVals[ValNo].first,
                                              PositionalVals[ValNo].second);
  }

  // Loop over args and make sure all required args are specified!
  for (StringMap<Option*>::iterator I = Opts.begin(),
         E = Opts.end(); I != E; ++I) {
    switch (I->second->getNumOccurrencesFlag()) {
    case Required:
    case OneOrMore:
      if (I->second->getNumOccurrences() == 0) {
        I->second->error("must be specified at least once!");
        ErrorParsing = true;
      }
      // Fall through
    default:
      break;
    }
  }

  // Now that we know if -debug is specified, we can use it.
  // Note that if ReadResponseFiles == true, this must be done before the
  // memory allocated for the expanded command line is free()d below.
  DEBUG(dbgs() << "Args: ";
        for (int i = 0; i < argc; ++i)
          dbgs() << argv[i] << ' ';
        dbgs() << '\n';
       );
Example #21
0
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
                               const MCTargetOptions &MCOptions,
                               const MDNode *LocMDNode,
                               InlineAsm::AsmDialect Dialect) const {
  assert(!Str.empty() && "Can't emit empty inline asm block");

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

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

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

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

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

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

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

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

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

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

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

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

  if (Res && !DiagInfo->DiagHandler)
    report_fatal_error("Error parsing inline asm\n");
}
Example #22
0
void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
                                           CheckerContext &C) const {
  unsigned idx = InvalidIdx;
  const ProgramState *State = C.getState();

  StringRef funName = C.getCalleeName(CE);
  if (funName.empty())
    return;

  // If it is a call to an allocator function, it could be a double allocation.
  idx = getTrackedFunctionIndex(funName, true);
  if (idx != InvalidIdx) {
    const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
    if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C))
      if (const AllocationState *AS = State->get<AllocatedData>(V)) {
        if (!definitelyReturnedError(AS->Region, State, C.getSValBuilder())) {
          // Remove the value from the state. The new symbol will be added for
          // tracking when the second allocator is processed in checkPostStmt().
          State = State->remove<AllocatedData>(V);
          ExplodedNode *N = C.addTransition(State);
          if (!N)
            return;
          initBugType();
          llvm::SmallString<128> sbuf;
          llvm::raw_svector_ostream os(sbuf);
          unsigned int DIdx = FunctionsToTrack[AS->AllocatorIdx].DeallocatorIdx;
          os << "Allocated data should be released before another call to "
              << "the allocator: missing a call to '"
              << FunctionsToTrack[DIdx].Name
              << "'.";
          BugReport *Report = new BugReport(*BT, os.str(), N);
          Report->addVisitor(new SecKeychainBugVisitor(V));
          Report->addRange(ArgExpr->getSourceRange());
          C.EmitReport(Report);
        }
      }
    return;
  }

  // Is it a call to one of deallocator functions?
  idx = getTrackedFunctionIndex(funName, false);
  if (idx == InvalidIdx)
    return;

  // Check the argument to the deallocator.
  const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
  SVal ArgSVal = State->getSVal(ArgExpr);

  // Undef is reported by another checker.
  if (ArgSVal.isUndef())
    return;

  const MemRegion *Arg = ArgSVal.getAsRegion();
  if (!Arg)
    return;

  SymbolRef ArgSM = getSymbolForRegion(C, Arg);
  bool RegionArgIsBad = ArgSM ? false : isBadDeallocationArgument(Arg);
  // If the argument is coming from the heap, globals, or unknown, do not
  // report it.
  if (!ArgSM && !RegionArgIsBad)
    return;

  // Is the argument to the call being tracked?
  const AllocationState *AS = State->get<AllocatedData>(ArgSM);
  if (!AS && FunctionsToTrack[idx].Kind != ValidAPI) {
    return;
  }
  // If trying to free data which has not been allocated yet, report as a bug.
  // TODO: We might want a more precise diagnostic for double free
  // (that would involve tracking all the freed symbols in the checker state).
  if (!AS || RegionArgIsBad) {
    // It is possible that this is a false positive - the argument might
    // have entered as an enclosing function parameter.
    if (isEnclosingFunctionParam(ArgExpr))
      return;

    ExplodedNode *N = C.addTransition(State);
    if (!N)
      return;
    initBugType();
    BugReport *Report = new BugReport(*BT,
        "Trying to free data which has not been allocated.", N);
    Report->addRange(ArgExpr->getSourceRange());
    C.EmitReport(Report);
    return;
  }

  // Process functions which might deallocate.
  if (FunctionsToTrack[idx].Kind == PossibleAPI) {

    if (funName == "CFStringCreateWithBytesNoCopy") {
      const Expr *DeallocatorExpr = CE->getArg(5)->IgnoreParenCasts();
      // NULL ~ default deallocator, so warn.
      if (DeallocatorExpr->isNullPointerConstant(C.getASTContext(),
          Expr::NPC_ValueDependentIsNotNull)) {
        const AllocationPair AP = std::make_pair(ArgSM, AS);
        generateDeallocatorMismatchReport(AP, ArgExpr, C);
        return;
      }
      // One of the default allocators, so warn.
      if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(DeallocatorExpr)) {
        StringRef DeallocatorName = DE->getFoundDecl()->getName();
        if (DeallocatorName == "kCFAllocatorDefault" ||
            DeallocatorName == "kCFAllocatorSystemDefault" ||
            DeallocatorName == "kCFAllocatorMalloc") {
          const AllocationPair AP = std::make_pair(ArgSM, AS);
          generateDeallocatorMismatchReport(AP, ArgExpr, C);
          return;
        }
        // If kCFAllocatorNull, which does not deallocate, we still have to
        // find the deallocator. Otherwise, assume that the user had written a
        // custom deallocator which does the right thing.
        if (DE->getFoundDecl()->getName() != "kCFAllocatorNull") {
          State = State->remove<AllocatedData>(ArgSM);
          C.addTransition(State);
          return;
        }
      }
    }
    return;
  }

  // The call is deallocating a value we previously allocated, so remove it
  // from the next state.
  State = State->remove<AllocatedData>(ArgSM);

  // Check if the proper deallocator is used.
  unsigned int PDeallocIdx = FunctionsToTrack[AS->AllocatorIdx].DeallocatorIdx;
  if (PDeallocIdx != idx || (FunctionsToTrack[idx].Kind == ErrorAPI)) {
    const AllocationPair AP = std::make_pair(ArgSM, AS);
    generateDeallocatorMismatchReport(AP, ArgExpr, C);
    return;
  }

  // If the buffer can be null and the return status can be an error,
  // report a bad call to free.
  if (State->assume(cast<DefinedSVal>(ArgSVal), false) &&
      !definitelyDidnotReturnError(AS->Region, State, C.getSValBuilder())) {
    ExplodedNode *N = C.addTransition(State);
    if (!N)
      return;
    initBugType();
    BugReport *Report = new BugReport(*BT,
        "Only call free if a valid (non-NULL) buffer was returned.", N);
    Report->addVisitor(new SecKeychainBugVisitor(ArgSM));
    Report->addRange(ArgExpr->getSourceRange());
    C.EmitReport(Report);
    return;
  }

  C.addTransition(State);
}
Example #23
0
void CodeCoverageTool::error(const Twine &Message, StringRef Whence) {
  errs() << "error: ";
  if (!Whence.empty())
    errs() << Whence << ": ";
  errs() << Message << "\n";
}
Example #24
0
static bool initDocEntityInfo(const Decl *D, const Decl *SynthesizedTarget,
                              const Decl *DefaultImplementationOf,
                              bool IsRef, bool IsSynthesizedExtension,
                              DocEntityInfo &Info,
                              StringRef Arg = StringRef()) {
  if (!D || isa<ParamDecl>(D) ||
      (isa<VarDecl>(D) && D->getDeclContext()->isLocalContext())) {
    Info.Kind = SwiftLangSupport::getUIDForLocalVar(IsRef);
    if (D) {
      llvm::raw_svector_ostream OS(Info.Name);
      SwiftLangSupport::printDisplayName(cast<ValueDecl>(D), OS);
    } else {
      Info.Name = "_";
    }

    if (!Arg.empty())
      Info.Argument = Arg.str();

    return false;
  }

  if (IsSynthesizedExtension)
    Info.Kind = SwiftLangSupport::getUIDForExtensionOfDecl(SynthesizedTarget);
  else
    Info.Kind = SwiftLangSupport::getUIDForDecl(D, IsRef);

  if (Info.Kind.isInvalid())
    return true;
  if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
    llvm::raw_svector_ostream NameOS(Info.Name);
    SwiftLangSupport::printDisplayName(VD, NameOS);
    {
      llvm::raw_svector_ostream OS(Info.USR);
      SwiftLangSupport::printUSR(VD, OS);
      if (SynthesizedTarget) {
        OS << SwiftLangSupport::SynthesizedUSRSeparator;
        SwiftLangSupport::printUSR(dyn_cast<ValueDecl>(SynthesizedTarget), OS);
        {
          llvm::raw_svector_ostream OS(Info.OriginalUSR);
          SwiftLangSupport::printUSR(VD, OS);
        }
      }
    }
  }

  if (DefaultImplementationOf) {
    llvm::raw_svector_ostream OS(Info.ProvideImplementationOfUSR);
    SwiftLangSupport::printUSR((ValueDecl*)DefaultImplementationOf, OS);
  }

  Info.IsUnavailable = AvailableAttr::isUnavailable(D);
  Info.IsDeprecated = D->getAttrs().getDeprecated(D->getASTContext()) != nullptr;
  Info.IsOptional = D->getAttrs().hasAttribute<OptionalAttr>();

  if (!IsRef) {
    llvm::raw_svector_ostream OS(Info.DocComment);

    {
      llvm::SmallString<128> DocBuffer;
      {
        llvm::raw_svector_ostream OSS(DocBuffer);
        ide::getDocumentationCommentAsXML(D, OSS);
      }
      StringRef DocRef = (StringRef)DocBuffer;
      if (IsSynthesizedExtension &&
          DocRef.find("<Declaration>") != StringRef::npos) {
        StringRef Open = "<Declaration>extension ";
        assert(DocRef.find(Open) != StringRef::npos);
        auto FirstPart = DocRef.substr(0, DocRef.find(Open) + (Open).size());
        auto SecondPart = DocRef.substr(FirstPart.size());
        auto ExtendedName = ((ExtensionDecl*)D)->getExtendedType()->
          getAnyNominal()->getName().str();
        assert(SecondPart.startswith(ExtendedName));
        SecondPart = SecondPart.substr(ExtendedName.size());
        llvm::SmallString<128> UpdatedDocBuffer;
        UpdatedDocBuffer.append(FirstPart);
        UpdatedDocBuffer.append(((NominalTypeDecl*)SynthesizedTarget)->getName().
                                str());
        UpdatedDocBuffer.append(SecondPart);
        OS << UpdatedDocBuffer;
      } else
        OS << DocBuffer;
    }

    initDocGenericParams(D, Info);

    if (auto *VD = dyn_cast<ValueDecl>(D)) {
      llvm::raw_svector_ostream OS(Info.FullyAnnotatedDecl);
      if (SynthesizedTarget)
        SwiftLangSupport::printFullyAnnotatedSynthesizedDeclaration(VD,
          (NominalTypeDecl*)SynthesizedTarget, OS);
      else
        SwiftLangSupport::printFullyAnnotatedDeclaration(VD, Type(), OS);
    }
  }

  return false;
}
/// emitModuleFlags - Perform code emission for module flags.
void TargetLoweringObjectFileMachO::
emitModuleFlags(MCStreamer &Streamer,
                ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
                Mangler &Mang, const TargetMachine &TM) const {
  unsigned VersionVal = 0;
  unsigned ImageInfoFlags = 0;
  MDNode *LinkerOptions = nullptr;
  StringRef SectionVal;

  for (ArrayRef<Module::ModuleFlagEntry>::iterator
         i = ModuleFlags.begin(), e = ModuleFlags.end(); i != e; ++i) {
    const Module::ModuleFlagEntry &MFE = *i;

    // 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 (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) {
      MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i));
      SmallVector<std::string, 4> StrOptions;

      // Convert to strings.
      for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) {
        MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii));
        StrOptions.push_back(MDOption->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();
}
Example #26
0
/// LookupFile - Lookup the specified file in this search path, returning it
/// if it exists or returning null if not.
const FileEntry *DirectoryLookup::LookupFile(
    StringRef &Filename,
    HeaderSearch &HS,
    SmallVectorImpl<char> *SearchPath,
    SmallVectorImpl<char> *RelativePath,
    ModuleMap::KnownHeader *SuggestedModule,
    bool &InUserSpecifiedSystemFramework,
    bool &HasBeenMapped,
    SmallVectorImpl<char> &MappedName) const {
  InUserSpecifiedSystemFramework = false;
  HasBeenMapped = false;

  SmallString<1024> TmpDir;
  if (isNormalDir()) {
    // Concatenate the requested file onto the directory.
    TmpDir = getDir()->getName();
    llvm::sys::path::append(TmpDir, Filename);
    if (SearchPath) {
      StringRef SearchPathRef(getDir()->getName());
      SearchPath->clear();
      SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
    }
    if (RelativePath) {
      RelativePath->clear();
      RelativePath->append(Filename.begin(), Filename.end());
    }

    return getFileAndSuggestModule(HS, TmpDir, getDir(),
                                   isSystemHeaderDirectory(),
                                   SuggestedModule);
  }

  if (isFramework())
    return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
                             SuggestedModule, InUserSpecifiedSystemFramework);

  assert(isHeaderMap() && "Unknown directory lookup");
  const HeaderMap *HM = getHeaderMap();
  SmallString<1024> Path;
  StringRef Dest = HM->lookupFilename(Filename, Path);
  if (Dest.empty())
    return nullptr;

  const FileEntry *Result;

  // Check if the headermap maps the filename to a framework include
  // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the
  // framework include.
  if (llvm::sys::path::is_relative(Dest)) {
    MappedName.clear();
    MappedName.append(Dest.begin(), Dest.end());
    Filename = StringRef(MappedName.begin(), MappedName.size());
    HasBeenMapped = true;
    Result = HM->LookupFile(Filename, HS.getFileMgr());

  } else {
    Result = HS.getFileMgr().getFile(Dest);
  }

  if (Result) {
    if (SearchPath) {
      StringRef SearchPathRef(getName());
      SearchPath->clear();
      SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
    }
    if (RelativePath) {
      RelativePath->clear();
      RelativePath->append(Filename.begin(), Filename.end());
    }
  }
  return Result;
}
Example #27
0
static void ParseProgName(SmallVectorImpl<const char *> &ArgVector,
                          std::set<std::string> &SavedStrings,
                          Driver &TheDriver)
{
  // Try to infer frontend type and default target from the program name.

  // suffixes[] contains the list of known driver suffixes.
  // Suffixes are compared against the program name in order.
  // If there is a match, the frontend type is updated as necessary (CPP/C++).
  // If there is no match, a second round is done after stripping the last
  // hyphen and everything following it. This allows using something like
  // "clang++-2.9".

  // If there is a match in either the first or second round,
  // the function tries to identify a target as prefix. E.g.
  // "x86_64-linux-clang" as interpreted as suffix "clang" with
  // target prefix "x86_64-linux". If such a target prefix is found,
  // is gets added via -target as implicit first argument.
  static const struct {
    const char *Suffix;
    const char *ModeFlag;
  } suffixes [] = {
    { "clang",     nullptr },
    { "clang++",   "--driver-mode=g++" },
    { "clang-c++", "--driver-mode=g++" },
    { "clang-upc", "--driver-mode=gupc" },
    { "clang-cc",  nullptr },
    { "clang-cpp", "--driver-mode=cpp" },
    { "clang-g++", "--driver-mode=g++" },
    { "clang-gcc", nullptr },
    { "clang-cl",  "--driver-mode=cl"  },
    { "cc",        nullptr },
    { "cpp",       "--driver-mode=cpp" },
    { "cl" ,       "--driver-mode=cl"  },
    { "++",        "--driver-mode=g++" },
    { "upc",       "--driver-mode=gupc" }
  };
  std::string ProgName(llvm::sys::path::stem(ArgVector[0]));
#ifdef LLVM_ON_WIN32
  // Transform to lowercase for case insensitive file systems.
  std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),
                 toLowercase);
#endif
  StringRef ProgNameRef(ProgName);
  StringRef Prefix;

  for (int Components = 2; Components; --Components) {
    bool FoundMatch = false;
    size_t i;

    for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
      if (ProgNameRef.endswith(suffixes[i].Suffix)) {
        FoundMatch = true;
        SmallVectorImpl<const char *>::iterator it = ArgVector.begin();
        if (it != ArgVector.end())
          ++it;
        if (suffixes[i].ModeFlag)
          ArgVector.insert(it, suffixes[i].ModeFlag);
        break;
      }
    }

    if (FoundMatch) {
      StringRef::size_type LastComponent = ProgNameRef.rfind('-',
        ProgNameRef.size() - strlen(suffixes[i].Suffix));
      if (LastComponent != StringRef::npos)
        Prefix = ProgNameRef.slice(0, LastComponent);
      break;
    }

    StringRef::size_type LastComponent = ProgNameRef.rfind('-');
    if (LastComponent == StringRef::npos)
      break;
    ProgNameRef = ProgNameRef.slice(0, LastComponent);
  }

  if (Prefix.empty())
    return;

  std::string IgnoredError;
  if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
    SmallVectorImpl<const char *>::iterator it = ArgVector.begin();
    if (it != ArgVector.end())
      ++it;
    const char* Strings[] =
      { SaveStringInSet(SavedStrings, std::string("-target")),
        SaveStringInSet(SavedStrings, Prefix) };
    ArgVector.insert(it, Strings, Strings + llvm::array_lengthof(Strings));
  }
}
Example #28
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);
    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)) {
        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,
                                        /*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, /*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;
}
Example #29
0
void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
  if (CPUString.empty()) {
    CPUString = "generic";

    if (isTargetDarwin()) {
      StringRef ArchName = TargetTriple.getArchName();
      if (ArchName.endswith("v7s"))
        // Default to the Swift CPU when targeting armv7s/thumbv7s.
        CPUString = "swift";
      else if (ArchName.endswith("v7k"))
        // Default to the Cortex-a7 CPU when targeting armv7k/thumbv7k.
        // ARMv7k does not use SjLj exception handling.
        CPUString = "cortex-a7";
    }
  }

  // Insert the architecture feature derived from the target triple into the
  // feature string. This is important for setting features that are implied
  // based on the architecture version.
  std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple, CPUString);
  if (!FS.empty()) {
    if (!ArchFS.empty())
      ArchFS = (Twine(ArchFS) + "," + FS).str();
    else
      ArchFS = FS;
  }
  ParseSubtargetFeatures(CPUString, ArchFS);

  // FIXME: This used enable V6T2 support implicitly for Thumb2 mode.
  // Assert this for now to make the change obvious.
  assert(hasV6T2Ops() || !hasThumb2());

  // Keep a pointer to static instruction cost data for the specified CPU.
  SchedModel = getSchedModelForCPU(CPUString);

  // Initialize scheduling itinerary for the specified CPU.
  InstrItins = getInstrItineraryForCPU(CPUString);

  // FIXME: this is invalid for WindowsCE
  if (isTargetWindows())
    NoARM = true;

  if (isAAPCS_ABI())
    stackAlignment = 8;
  if (isTargetNaCl() || isAAPCS16_ABI())
    stackAlignment = 16;

  // FIXME: Completely disable sibcall for Thumb1 since ThumbRegisterInfo::
  // emitEpilogue is not ready for them. Thumb tail calls also use t2B, as
  // the Thumb1 16-bit unconditional branch doesn't have sufficient relocation
  // support in the assembler and linker to be used. This would need to be
  // fixed to fully support tail calls in Thumb1.
  //
  // Doing this is tricky, since the LDM/POP instruction on Thumb doesn't take
  // LR.  This means if we need to reload LR, it takes an extra instructions,
  // which outweighs the value of the tail call; but here we don't know yet
  // whether LR is going to be used.  Probably the right approach is to
  // generate the tail call here and turn it back into CALL/RET in
  // emitEpilogue if LR is used.

  // Thumb1 PIC calls to external symbols use BX, so they can be tail calls,
  // but we need to make sure there are enough registers; the only valid
  // registers are the 4 used for parameters.  We don't currently do this
  // case.

  SupportsTailCall = !isThumb() || hasV8MBaselineOps();

  if (isTargetMachO() && isTargetIOS() && getTargetTriple().isOSVersionLT(5, 0))
    SupportsTailCall = false;

  switch (IT) {
  case DefaultIT:
    RestrictIT = hasV8Ops();
    break;
  case RestrictedIT:
    RestrictIT = true;
    break;
  case NoRestrictedIT:
    RestrictIT = false;
    break;
  }

  // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.
  const FeatureBitset &Bits = getFeatureBits();
  if ((Bits[ARM::ProcA5] || Bits[ARM::ProcA8]) && // Where this matters
      (Options.UnsafeFPMath || isTargetDarwin()))
    UseNEONForSinglePrecisionFP = true;

  // FIXME: Teach TableGen to deal with these instead of doing it manually here.
  switch (ARMProcFamily) {
  case Others:
  case CortexA5:
    break;
  case CortexA7:
    LdStMultipleTiming = DoubleIssue;
    break;
  case CortexA8:
    LdStMultipleTiming = DoubleIssue;
    break;
  case CortexA9:
    LdStMultipleTiming = DoubleIssueCheckUnalignedAccess;
    PreISelOperandLatencyAdjustment = 1;
    break;
  case CortexA12:
    break;
  case CortexA15:
    MaxInterleaveFactor = 2;
    PreISelOperandLatencyAdjustment = 1;
    break;
  case CortexA17:
  case CortexA32:
  case CortexA35:
  case CortexA53:
  case CortexA57:
  case CortexA72:
  case CortexA73:
  case CortexR4:
  case CortexR4F:
  case CortexR5:
  case CortexR7:
  case CortexM3:
  case ExynosM1:
    break;
  case Krait:
    PreISelOperandLatencyAdjustment = 1;
    break;
  case Swift:
    MaxInterleaveFactor = 2;
    LdStMultipleTiming = SingleIssuePlusExtras;
    PreISelOperandLatencyAdjustment = 1;
    break;
  }
}
Example #30
0
std::string Regex::sub(StringRef Repl, StringRef String,
                       std::string *Error) {
  SmallVector<StringRef, 8> Matches;

  // Reset error, if given.
  if (Error && !Error->empty()) *Error = "";

  // Return the input if there was no match.
  if (!match(String, &Matches))
    return String;

  // Otherwise splice in the replacement string, starting with the prefix before
  // the match.
  std::string Res(String.begin(), Matches[0].begin());

  // Then the replacement string, honoring possible substitutions.
  while (!Repl.empty()) {
    // Skip to the next escape.
    std::pair<StringRef, StringRef> Split = Repl.split('\\');

    // Add the skipped substring.
    Res += Split.first;

    // Check for terminimation and trailing backslash.
    if (Split.second.empty()) {
      if (Repl.size() != Split.first.size() &&
          Error && Error->empty())
        *Error = "replacement string contained trailing backslash";
      break;
    }

    // Otherwise update the replacement string and interpret escapes.
    Repl = Split.second;

    // FIXME: We should have a StringExtras function for mapping C99 escapes.
    switch (Repl[0]) {
      // Treat all unrecognized characters as self-quoting.
    default:
      Res += Repl[0];
      Repl = Repl.substr(1);
      break;

      // Single character escapes.
    case 't':
      Res += '\t';
      Repl = Repl.substr(1);
      break;
    case 'n':
      Res += '\n';
      Repl = Repl.substr(1);
      break;

      // Decimal escapes are backreferences.
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9': {
      // Extract the backreference number.
      StringRef Ref = Repl.slice(0, Repl.find_first_not_of("0123456789"));
      Repl = Repl.substr(Ref.size());

      unsigned RefValue;
      if (!Ref.getAsInteger(10, RefValue) &&
          RefValue < Matches.size())
        Res += Matches[RefValue];
      else if (Error && Error->empty())
        *Error = ("invalid backreference string '" + Twine(Ref) + "'").str();
      break;
    }
    }
  }

  // And finally the suffix.
  Res += StringRef(Matches[0].end(), String.end() - Matches[0].end());

  return Res;
}