/// Move the given iterators to the next leaf type in depth first traversal. /// /// Performs a depth-first traversal of the type as specified by its arguments, /// stopping at the next leaf node (which may be a legitimate scalar type or an /// empty struct or array). /// /// @param SubTypes List of the partial components making up the type from /// outermost to innermost non-empty aggregate. The element currently /// represented is SubTypes.back()->getTypeAtIndex(Path.back() - 1). /// /// @param Path Set of extractvalue indices leading from the outermost type /// (SubTypes[0]) to the leaf node currently represented. /// /// @returns true if a new type was found, false otherwise. Calling this /// function again on a finished iterator will repeatedly return /// false. SubTypes.back()->getTypeAtIndex(Path.back()) is either an empty /// aggregate or a non-aggregate static bool advanceToNextLeafType(SmallVectorImpl<CompositeType *> &SubTypes, SmallVectorImpl<unsigned> &Path) { // First march back up the tree until we can successfully increment one of the // coordinates in Path. while (!Path.empty() && !indexReallyValid(SubTypes.back(), Path.back() + 1)) { Path.pop_back(); SubTypes.pop_back(); } // If we reached the top, then the iterator is done. if (Path.empty()) return false; // We know there's *some* valid leaf now, so march back down the tree picking // out the left-most element at each node. ++Path.back(); Type *DeeperType = SubTypes.back()->getTypeAtIndex(Path.back()); while (DeeperType->isAggregateType()) { CompositeType *CT = cast<CompositeType>(DeeperType); if (!indexReallyValid(CT, 0)) return true; SubTypes.push_back(CT); Path.push_back(0); DeeperType = CT->getTypeAtIndex(0U); } return true; }
bool TokenLexer::MaybeRemoveCommaBeforeVaArgs( SmallVectorImpl<Token> &ResultToks, bool HasPasteOperator, MacroInfo *Macro, unsigned MacroArgNo, Preprocessor &PP) { // Is the macro argument __VA_ARGS__? if (!Macro->isVariadic() || MacroArgNo != Macro->getNumArgs()-1) return false; // In Microsoft-compatibility mode, a comma is removed in the expansion // of " ... , __VA_ARGS__ " if __VA_ARGS__ is empty. This extension is // not supported by gcc. if (!HasPasteOperator && !PP.getLangOpts().MSVCCompat) return false; // GCC removes the comma in the expansion of " ... , ## __VA_ARGS__ " if // __VA_ARGS__ is empty, but not in strict C99 mode where there are no // named arguments, where it remains. In all other modes, including C99 // with GNU extensions, it is removed regardless of named arguments. // Microsoft also appears to support this extension, unofficially. if (PP.getLangOpts().C99 && !PP.getLangOpts().GNUMode && Macro->getNumArgs() < 2) return false; // Is a comma available to be removed? if (ResultToks.empty() || !ResultToks.back().is(tok::comma)) return false; // Issue an extension diagnostic for the paste operator. if (HasPasteOperator) PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma); // Remove the comma. ResultToks.pop_back(); if (!ResultToks.empty()) { // If the comma was right after another paste (e.g. "X##,##__VA_ARGS__"), // then removal of the comma should produce a placemarker token (in C99 // terms) which we model by popping off the previous ##, giving us a plain // "X" when __VA_ARGS__ is empty. if (ResultToks.back().is(tok::hashhash)) ResultToks.pop_back(); // Remember that this comma was elided. ResultToks.back().setFlag(Token::CommaAfterElided); } // Never add a space, even if the comma, ##, or arg had a space. NextTokGetsSpace = false; return true; }
bool convertUTF8ToUTF16String(StringRef SrcUTF8, SmallVectorImpl<UTF16> &DstUTF16) { assert(DstUTF16.empty()); // Avoid OOB by returning early on empty input. if (SrcUTF8.empty()) return true; const UTF8 *Src = reinterpret_cast<const UTF8 *>(SrcUTF8.begin()); const UTF8 *SrcEnd = reinterpret_cast<const UTF8 *>(SrcUTF8.end()); // Allocate the same number of UTF-16 code units as UTF-8 code units. Encoding // as UTF-16 should always require the same amount or less code units than the // UTF-8 encoding. Allocate one extra byte for the null terminator though, // so that someone calling DstUTF16.data() gets a null terminated string. // We resize down later so we don't have to worry that this over allocates. DstUTF16.resize(SrcUTF8.size()+1); UTF16 *Dst = &DstUTF16[0]; UTF16 *DstEnd = Dst + DstUTF16.size(); ConversionResult CR = ConvertUTF8toUTF16(&Src, SrcEnd, &Dst, DstEnd, strictConversion); assert(CR != targetExhausted); if (CR != conversionOK) { DstUTF16.clear(); return false; } DstUTF16.resize(Dst - &DstUTF16[0]); DstUTF16.push_back(0); DstUTF16.pop_back(); return true; }
void LiveVariables::UpdatePhysRegDefs(MachineInstr *MI, SmallVectorImpl<unsigned> &Defs) { while (!Defs.empty()) { unsigned Reg = Defs.back(); Defs.pop_back(); for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true); SubRegs.isValid(); ++SubRegs) { unsigned SubReg = *SubRegs; PhysRegDef[SubReg] = MI; PhysRegUse[SubReg] = nullptr; } } }
StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const { if (isUnary()) { switch (getLHSKind()) { case CStringKind: // Already null terminated, yay! return StringRef(LHS.cString); case StdStringKind: { const std::string *str = LHS.stdString; return StringRef(str->c_str(), str->size()); } default: break; } } toVector(Out); Out.push_back(0); Out.pop_back(); return StringRef(Out.data(), Out.size()); }
void Scop::buildScop(TempScop &tempScop, const Region &CurRegion, SmallVectorImpl<Loop*> &NestLoops, SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI) { Loop *L = castToLoop(CurRegion, LI); if (L) NestLoops.push_back(L); unsigned loopDepth = NestLoops.size(); assert(Scatter.size() > loopDepth && "Scatter not big enough!"); for (Region::const_element_iterator I = CurRegion.element_begin(), E = CurRegion.element_end(); I != E; ++I) if (I->isSubRegion()) buildScop(tempScop, *(I->getNodeAs<Region>()), NestLoops, Scatter, LI); else { BasicBlock *BB = I->getNodeAs<BasicBlock>(); if (isTrivialBB(BB, tempScop)) continue; Stmts.push_back(new ScopStmt(*this, tempScop, CurRegion, *BB, NestLoops, Scatter)); // Increasing the Scattering function is OK for the moment, because // we are using a depth first iterator and the program is well structured. ++Scatter[loopDepth]; } if (!L) return; // Exiting a loop region. Scatter[loopDepth] = 0; NestLoops.pop_back(); ++Scatter[loopDepth-1]; }
MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify, SmallVectorImpl<MachineInstr *> &BranchInstrs) const { MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); // Skip all the debug instructions. while (I != REnd && I->isDebugValue()) ++I; if (I == REnd || !isUnpredicatedTerminator(*I)) { // This block ends with no branches (it just falls through to its succ). // Leave TBB/FBB null. TBB = FBB = nullptr; return BT_NoBranch; } MachineInstr *LastInst = &*I; unsigned LastOpc = LastInst->getOpcode(); BranchInstrs.push_back(LastInst); // Not an analyzable branch (e.g., indirect jump). if (!getAnalyzableBrOpc(LastOpc)) return LastInst->isIndirectBranch() ? BT_Indirect : BT_None; // Get the second to last instruction in the block. unsigned SecondLastOpc = 0; MachineInstr *SecondLastInst = nullptr; if (++I != REnd) { SecondLastInst = &*I; SecondLastOpc = getAnalyzableBrOpc(SecondLastInst->getOpcode()); // Not an analyzable branch (must be an indirect jump). if (isUnpredicatedTerminator(*SecondLastInst) && !SecondLastOpc) return BT_None; } // If there is only one terminator instruction, process it. if (!SecondLastOpc) { // Unconditional branch. if (LastInst->isUnconditionalBranch()) { TBB = LastInst->getOperand(0).getMBB(); return BT_Uncond; } // Conditional branch AnalyzeCondBr(LastInst, LastOpc, TBB, Cond); return BT_Cond; } // If we reached here, there are two branches. // If there are three terminators, we don't know what sort of block this is. if (++I != REnd && isUnpredicatedTerminator(*I)) return BT_None; BranchInstrs.insert(BranchInstrs.begin(), SecondLastInst); // If second to last instruction is an unconditional branch, // analyze it and remove the last instruction. if (SecondLastInst->isUnconditionalBranch()) { // Return if the last instruction cannot be removed. if (!AllowModify) return BT_None; TBB = SecondLastInst->getOperand(0).getMBB(); LastInst->eraseFromParent(); BranchInstrs.pop_back(); return BT_Uncond; } // Conditional branch followed by an unconditional branch. // The last one must be unconditional. if (!LastInst->isUnconditionalBranch()) return BT_None; AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond); FBB = LastInst->getOperand(0).getMBB(); return BT_CondUncond; }
static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, SmallVectorImpl<char> &ResultPath, bool MakeAbsolute, unsigned Mode, FSEntity Type) { SmallString<128> ModelStorage; Model.toVector(ModelStorage); if (MakeAbsolute) { // Make model absolute by prepending a temp directory if it's not already. if (!sys::path::is_absolute(Twine(ModelStorage))) { SmallString<128> TDir; sys::path::system_temp_directory(true, TDir); sys::path::append(TDir, Twine(ModelStorage)); ModelStorage.swap(TDir); } } // From here on, DO NOT modify model. It may be needed if the randomly chosen // path already exists. ResultPath = ModelStorage; // Null terminate. ResultPath.push_back(0); ResultPath.pop_back(); retry_random_path: // Replace '%' with random chars. for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) { if (ModelStorage[i] == '%') ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15]; } // Try to open + create the file. switch (Type) { case FS_File: { if (std::error_code EC = sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD, sys::fs::F_RW | sys::fs::F_Excl, Mode)) { if (EC == errc::file_exists) goto retry_random_path; return EC; } return std::error_code(); } case FS_Name: { std::error_code EC = sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist); if (EC == errc::no_such_file_or_directory) return std::error_code(); if (EC) return EC; goto retry_random_path; } case FS_Dir: { if (std::error_code EC = sys::fs::create_directory(ResultPath.begin(), false)) { if (EC == errc::file_exists) goto retry_random_path; return EC; } return std::error_code(); } } llvm_unreachable("Invalid Type"); }
/// CalcTypeName - Write the specified type to the specified raw_ostream, making /// use of type names or up references to shorten the type name where possible. void TypeGen::CalcTypeName( const Type *Ty, SmallVectorImpl<const Type *> &TypeStack, raw_ostream &OS, bool IgnoreTopLevelName) { // Check to see if the type is named. if (!IgnoreTopLevelName) { DenseMap<const Type *, std::string> &TM = getTypeNamesMap(TypeNames); DenseMap<const Type *, std::string>::iterator I = TM.find(Ty); if (I != TM.end()) { OS << I->second; return; } } // Check to see if the Type is already on the stack... unsigned Slot = 0, CurSize = TypeStack.size(); while (Slot < CurSize && TypeStack[Slot] != Ty) ++Slot; // Scan for type // This is another base case for the recursion. In this case, we know // that we have looped back to a type that we have previously visited. // Generate the appropriate upreference to handle this. if (Slot < CurSize) { OS << '\\' << unsigned(CurSize-Slot); // Here's the upreference return; } TypeStack.push_back(Ty); // Recursive case: Add us to the stack.. switch (Ty->getTypeID()) { case Type::VoidTyID: OS << "void"; break; case Type::FloatTyID: break; case Type::DoubleTyID: break; case Type::X86_FP80TyID: break; case Type::FP128TyID: break; case Type::PPC_FP128TyID: break; case Type::LabelTyID: OS << "label"; break; case Type::MetadataTyID: OS << "metadata"; break; case Type::X86_MMXTyID: break; case Type::IntegerTyID: { unsigned bitWidth=cast<IntegerType>(Ty)->getBitWidth(); switch (bitWidth){ case 1: OS << "bit"; break; case 8: OS << "int"; break; case 16: OS << "int"; break; case 32: OS << "int"; break; default: break; } break; } case Type::FunctionTyID: { const FunctionType *FTy = cast<FunctionType>(Ty); CalcTypeName(FTy->getReturnType(), TypeStack, OS); OS << " ("; for (FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end(); I != E; ++I) { if (I != FTy->param_begin()) OS << ", "; CalcTypeName(*I, TypeStack, OS); } if (FTy->isVarArg()) { if (FTy->getNumParams()) OS << ", "; OS << "..."; } OS << ')'; break; } case Type::StructTyID: { const StructType *STy = cast<StructType>(Ty); OS << "TYPEDEF "; CalcTypeName(Ty,TypeStack,OS); OS << " {"; int i=0; for (StructType::element_iterator I = STy->element_begin(), E = STy->element_end(); I != E; ++I) { OS << ' '; CalcTypeName(*I, TypeStack, OS); OS << " u"<<i; i++; if (llvm::next(I) == STy->element_end()) OS << ' '; else OS << ';'; } OS << '}'; break; } case Type::PointerTyID: { const PointerType *PTy = cast<PointerType>(Ty); CalcTypeName(PTy->getElementType(), TypeStack, OS); // if (unsigned AddressSpace = PTy->getAddressSpace()) // OS << " addrspace(" << AddressSpace << ')'; // OS << '*'; break; } case Type::ArrayTyID: { const ArrayType *ATy = cast<ArrayType>(Ty); CalcTypeName(ATy->getElementType(),TypeStack,OS); OS << '[' << ATy->getNumElements() << ']'; break; } case Type::VectorTyID: { const VectorType *PTy = cast<VectorType>(Ty); OS << "<" << PTy->getNumElements() << " x "; CalcTypeName(PTy->getElementType(), TypeStack, OS); OS << '>'; break; } case Type::OpaqueTyID: OS << "opaque"; break; default: OS << "<unrecognized-type>"; break; } TypeStack.pop_back(); // Remove self from stack. }
static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, SmallVectorImpl<char> &ResultPath, bool MakeAbsolute, unsigned Mode, FSEntity Type, sys::fs::OpenFlags Flags = sys::fs::OF_None) { SmallString<128> ModelStorage; Model.toVector(ModelStorage); if (MakeAbsolute) { // Make model absolute by prepending a temp directory if it's not already. if (!sys::path::is_absolute(Twine(ModelStorage))) { SmallString<128> TDir; sys::path::system_temp_directory(true, TDir); sys::path::append(TDir, Twine(ModelStorage)); ModelStorage.swap(TDir); } } // From here on, DO NOT modify model. It may be needed if the randomly chosen // path already exists. ResultPath = ModelStorage; // Null terminate. ResultPath.push_back(0); ResultPath.pop_back(); // Limit the number of attempts we make, so that we don't infinite loop. E.g. // "permission denied" could be for a specific file (so we retry with a // different name) or for the whole directory (retry would always fail). // Checking which is racy, so we try a number of times, then give up. std::error_code EC; for (int Retries = 128; Retries > 0; --Retries) { // Replace '%' with random chars. for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) { if (ModelStorage[i] == '%') ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15]; } // Try to open + create the file. switch (Type) { case FS_File: { EC = sys::fs::openFileForReadWrite(Twine(ResultPath.begin()), ResultFD, sys::fs::CD_CreateNew, Flags, Mode); if (EC) { // errc::permission_denied happens on Windows when we try to open a file // that has been marked for deletion. if (EC == errc::file_exists || EC == errc::permission_denied) continue; return EC; } return std::error_code(); } case FS_Name: { EC = sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist); if (EC == errc::no_such_file_or_directory) return std::error_code(); if (EC) return EC; continue; } case FS_Dir: { EC = sys::fs::create_directory(ResultPath.begin(), false); if (EC) { if (EC == errc::file_exists) continue; return EC; } return std::error_code(); } } llvm_unreachable("Invalid Type"); } return EC; }