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";);
/// 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 ""; }
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; }
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; }
/// 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; }
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; }
/// 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!"); }
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; }
/// 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(); }
/// \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; } }
/// 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"); }
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'; );
/// 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"); }
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); }
void CodeCoverageTool::error(const Twine &Message, StringRef Whence) { errs() << "error: "; if (!Whence.empty()) errs() << Whence << ": "; errs() << Message << "\n"; }
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(); }
/// 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; }
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)); } }
/// 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; }
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; } }
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; }