/// initialize - Initialize the set of available library functions based on the /// specified target triple. This should be carefully written so that a missing /// target triple gets a sane set of defaults. static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef<const char *> StandardNames) { // Verify that the StandardNames array is in alphabetical order. assert(std::is_sorted(StandardNames.begin(), StandardNames.end(), [](const char *LHS, const char *RHS) { return strcmp(LHS, RHS) < 0; }) && "TargetLibraryInfoImpl function names must be sorted"); if (T.getArch() == Triple::r600 || T.getArch() == Triple::amdgcn) { TLI.setUnavailable(LibFunc::ldexp); TLI.setUnavailable(LibFunc::ldexpf); TLI.setUnavailable(LibFunc::ldexpl); } // There are no library implementations of mempcy and memset for AMD gpus and // these can be difficult to lower in the backend. if (T.getArch() == Triple::r600 || T.getArch() == Triple::amdgcn) { TLI.setUnavailable(LibFunc::memcpy); TLI.setUnavailable(LibFunc::memset); TLI.setUnavailable(LibFunc::memset_pattern16); return; } // memset_pattern16 is only available on iOS 3.0 and Mac OS X 10.5 and later. // All versions of watchOS support it. if (T.isMacOSX()) { if (T.isMacOSXVersionLT(10, 5)) TLI.setUnavailable(LibFunc::memset_pattern16); } else if (T.isiOS()) { if (T.isOSVersionLT(3, 0)) TLI.setUnavailable(LibFunc::memset_pattern16); } else if (!T.isWatchOS()) { TLI.setUnavailable(LibFunc::memset_pattern16); } if (!hasSinCosPiStret(T)) { TLI.setUnavailable(LibFunc::sinpi); TLI.setUnavailable(LibFunc::sinpif); TLI.setUnavailable(LibFunc::cospi); TLI.setUnavailable(LibFunc::cospif); TLI.setUnavailable(LibFunc::sincospi_stret); TLI.setUnavailable(LibFunc::sincospif_stret); } if (T.isMacOSX() && T.getArch() == Triple::x86 && !T.isMacOSXVersionLT(10, 7)) { // x86-32 OSX has a scheme where fwrite and fputs (and some other functions // we don't care about) have two versions; on recent OSX, the one we want // has a $UNIX2003 suffix. The two implementations are identical except // for the return value in some edge cases. However, we don't want to // generate code that depends on the old symbols. TLI.setAvailableWithName(LibFunc::fwrite, "fwrite$UNIX2003"); TLI.setAvailableWithName(LibFunc::fputs, "fputs$UNIX2003"); } // iprintf and friends are only available on XCore and TCE. if (T.getArch() != Triple::xcore && T.getArch() != Triple::tce) { TLI.setUnavailable(LibFunc::iprintf); TLI.setUnavailable(LibFunc::siprintf); TLI.setUnavailable(LibFunc::fiprintf); } if (T.isOSWindows() && !T.isOSCygMing()) { // Win32 does not support long double TLI.setUnavailable(LibFunc::acosl); TLI.setUnavailable(LibFunc::asinl); TLI.setUnavailable(LibFunc::atanl); TLI.setUnavailable(LibFunc::atan2l); TLI.setUnavailable(LibFunc::ceill); TLI.setUnavailable(LibFunc::copysignl); TLI.setUnavailable(LibFunc::cosl); TLI.setUnavailable(LibFunc::coshl); TLI.setUnavailable(LibFunc::expl); TLI.setUnavailable(LibFunc::fabsf); // Win32 and Win64 both lack fabsf TLI.setUnavailable(LibFunc::fabsl); TLI.setUnavailable(LibFunc::floorl); TLI.setUnavailable(LibFunc::fmaxl); TLI.setUnavailable(LibFunc::fminl); TLI.setUnavailable(LibFunc::fmodl); TLI.setUnavailable(LibFunc::frexpl); TLI.setUnavailable(LibFunc::ldexpf); TLI.setUnavailable(LibFunc::ldexpl); TLI.setUnavailable(LibFunc::logl); TLI.setUnavailable(LibFunc::modfl); TLI.setUnavailable(LibFunc::powl); TLI.setUnavailable(LibFunc::sinl); TLI.setUnavailable(LibFunc::sinhl); TLI.setUnavailable(LibFunc::sqrtl); TLI.setUnavailable(LibFunc::tanl); TLI.setUnavailable(LibFunc::tanhl); // Win32 only has C89 math TLI.setUnavailable(LibFunc::acosh); TLI.setUnavailable(LibFunc::acoshf); TLI.setUnavailable(LibFunc::acoshl); TLI.setUnavailable(LibFunc::asinh); TLI.setUnavailable(LibFunc::asinhf); TLI.setUnavailable(LibFunc::asinhl); TLI.setUnavailable(LibFunc::atanh); TLI.setUnavailable(LibFunc::atanhf); TLI.setUnavailable(LibFunc::atanhl); TLI.setUnavailable(LibFunc::cbrt); TLI.setUnavailable(LibFunc::cbrtf); TLI.setUnavailable(LibFunc::cbrtl); TLI.setUnavailable(LibFunc::exp2); TLI.setUnavailable(LibFunc::exp2f); TLI.setUnavailable(LibFunc::exp2l); TLI.setUnavailable(LibFunc::expm1); TLI.setUnavailable(LibFunc::expm1f); TLI.setUnavailable(LibFunc::expm1l); TLI.setUnavailable(LibFunc::log2); TLI.setUnavailable(LibFunc::log2f); TLI.setUnavailable(LibFunc::log2l); TLI.setUnavailable(LibFunc::log1p); TLI.setUnavailable(LibFunc::log1pf); TLI.setUnavailable(LibFunc::log1pl); TLI.setUnavailable(LibFunc::logb); TLI.setUnavailable(LibFunc::logbf); TLI.setUnavailable(LibFunc::logbl); TLI.setUnavailable(LibFunc::nearbyint); TLI.setUnavailable(LibFunc::nearbyintf); TLI.setUnavailable(LibFunc::nearbyintl); TLI.setUnavailable(LibFunc::rint); TLI.setUnavailable(LibFunc::rintf); TLI.setUnavailable(LibFunc::rintl); TLI.setUnavailable(LibFunc::round); TLI.setUnavailable(LibFunc::roundf); TLI.setUnavailable(LibFunc::roundl); TLI.setUnavailable(LibFunc::trunc); TLI.setUnavailable(LibFunc::truncf); TLI.setUnavailable(LibFunc::truncl); // Win32 provides some C99 math with mangled names TLI.setAvailableWithName(LibFunc::copysign, "_copysign"); if (T.getArch() == Triple::x86) { // Win32 on x86 implements single-precision math functions as macros TLI.setUnavailable(LibFunc::acosf); TLI.setUnavailable(LibFunc::asinf); TLI.setUnavailable(LibFunc::atanf); TLI.setUnavailable(LibFunc::atan2f); TLI.setUnavailable(LibFunc::ceilf); TLI.setUnavailable(LibFunc::copysignf); TLI.setUnavailable(LibFunc::cosf); TLI.setUnavailable(LibFunc::coshf); TLI.setUnavailable(LibFunc::expf); TLI.setUnavailable(LibFunc::floorf); TLI.setUnavailable(LibFunc::fminf); TLI.setUnavailable(LibFunc::fmaxf); TLI.setUnavailable(LibFunc::fmodf); TLI.setUnavailable(LibFunc::logf); TLI.setUnavailable(LibFunc::powf); TLI.setUnavailable(LibFunc::sinf); TLI.setUnavailable(LibFunc::sinhf); TLI.setUnavailable(LibFunc::sqrtf); TLI.setUnavailable(LibFunc::tanf); TLI.setUnavailable(LibFunc::tanhf); } // Win32 does *not* provide provide these functions, but they are // generally available on POSIX-compliant systems: TLI.setUnavailable(LibFunc::access); TLI.setUnavailable(LibFunc::bcmp); TLI.setUnavailable(LibFunc::bcopy); TLI.setUnavailable(LibFunc::bzero); TLI.setUnavailable(LibFunc::chmod); TLI.setUnavailable(LibFunc::chown); TLI.setUnavailable(LibFunc::closedir); TLI.setUnavailable(LibFunc::ctermid); TLI.setUnavailable(LibFunc::fdopen); TLI.setUnavailable(LibFunc::ffs); TLI.setUnavailable(LibFunc::fileno); TLI.setUnavailable(LibFunc::flockfile); TLI.setUnavailable(LibFunc::fseeko); TLI.setUnavailable(LibFunc::fstat); TLI.setUnavailable(LibFunc::fstatvfs); TLI.setUnavailable(LibFunc::ftello); TLI.setUnavailable(LibFunc::ftrylockfile); TLI.setUnavailable(LibFunc::funlockfile); TLI.setUnavailable(LibFunc::getc_unlocked); TLI.setUnavailable(LibFunc::getitimer); TLI.setUnavailable(LibFunc::getlogin_r); TLI.setUnavailable(LibFunc::getpwnam); TLI.setUnavailable(LibFunc::gettimeofday); TLI.setUnavailable(LibFunc::htonl); TLI.setUnavailable(LibFunc::htons); TLI.setUnavailable(LibFunc::lchown); TLI.setUnavailable(LibFunc::lstat); TLI.setUnavailable(LibFunc::memccpy); TLI.setUnavailable(LibFunc::mkdir); TLI.setUnavailable(LibFunc::ntohl); TLI.setUnavailable(LibFunc::ntohs); TLI.setUnavailable(LibFunc::open); TLI.setUnavailable(LibFunc::opendir); TLI.setUnavailable(LibFunc::pclose); TLI.setUnavailable(LibFunc::popen); TLI.setUnavailable(LibFunc::pread); TLI.setUnavailable(LibFunc::pwrite); TLI.setUnavailable(LibFunc::read); TLI.setUnavailable(LibFunc::readlink); TLI.setUnavailable(LibFunc::realpath); TLI.setUnavailable(LibFunc::rmdir); TLI.setUnavailable(LibFunc::setitimer); TLI.setUnavailable(LibFunc::stat); TLI.setUnavailable(LibFunc::statvfs); TLI.setUnavailable(LibFunc::stpcpy); TLI.setUnavailable(LibFunc::stpncpy); TLI.setUnavailable(LibFunc::strcasecmp); TLI.setUnavailable(LibFunc::strncasecmp); TLI.setUnavailable(LibFunc::times); TLI.setUnavailable(LibFunc::uname); TLI.setUnavailable(LibFunc::unlink); TLI.setUnavailable(LibFunc::unsetenv); TLI.setUnavailable(LibFunc::utime); TLI.setUnavailable(LibFunc::utimes); TLI.setUnavailable(LibFunc::write); // Win32 does *not* provide provide these functions, but they are // specified by C99: TLI.setUnavailable(LibFunc::atoll); TLI.setUnavailable(LibFunc::frexpf); TLI.setUnavailable(LibFunc::llabs); } switch (T.getOS()) { case Triple::MacOSX: // exp10 and exp10f are not available on OS X until 10.9 and iOS until 7.0 // and their names are __exp10 and __exp10f. exp10l is not available on // OS X or iOS. TLI.setUnavailable(LibFunc::exp10l); if (T.isMacOSXVersionLT(10, 9)) { TLI.setUnavailable(LibFunc::exp10); TLI.setUnavailable(LibFunc::exp10f); } else { TLI.setAvailableWithName(LibFunc::exp10, "__exp10"); TLI.setAvailableWithName(LibFunc::exp10f, "__exp10f"); } break; case Triple::IOS: case Triple::TvOS: case Triple::WatchOS: TLI.setUnavailable(LibFunc::exp10l); if (!T.isWatchOS() && (T.isOSVersionLT(7, 0) || (T.isOSVersionLT(9, 0) && (T.getArch() == Triple::x86 || T.getArch() == Triple::x86_64)))) { TLI.setUnavailable(LibFunc::exp10); TLI.setUnavailable(LibFunc::exp10f); } else { TLI.setAvailableWithName(LibFunc::exp10, "__exp10"); TLI.setAvailableWithName(LibFunc::exp10f, "__exp10f"); } break; case Triple::Linux: // exp10, exp10f, exp10l is available on Linux (GLIBC) but are extremely // buggy prior to glibc version 2.18. Until this version is widely deployed // or we have a reasonable detection strategy, we cannot use exp10 reliably // on Linux. // // Fall through to disable all of them. default: TLI.setUnavailable(LibFunc::exp10); TLI.setUnavailable(LibFunc::exp10f); TLI.setUnavailable(LibFunc::exp10l); } // ffsl is available on at least Darwin, Mac OS X, iOS, FreeBSD, and // Linux (GLIBC): // http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/ffsl.3.html // http://svn.freebsd.org/base/head/lib/libc/string/ffsl.c // http://www.gnu.org/software/gnulib/manual/html_node/ffsl.html switch (T.getOS()) { case Triple::Darwin: case Triple::MacOSX: case Triple::IOS: case Triple::TvOS: case Triple::WatchOS: case Triple::FreeBSD: case Triple::Linux: break; default: TLI.setUnavailable(LibFunc::ffsl); } // ffsll is available on at least FreeBSD and Linux (GLIBC): // http://svn.freebsd.org/base/head/lib/libc/string/ffsll.c // http://www.gnu.org/software/gnulib/manual/html_node/ffsll.html switch (T.getOS()) { case Triple::Darwin: case Triple::MacOSX: case Triple::IOS: case Triple::TvOS: case Triple::WatchOS: case Triple::FreeBSD: case Triple::Linux: break; default: TLI.setUnavailable(LibFunc::ffsll); } // The following functions are available on at least FreeBSD: // http://svn.freebsd.org/base/head/lib/libc/string/fls.c // http://svn.freebsd.org/base/head/lib/libc/string/flsl.c // http://svn.freebsd.org/base/head/lib/libc/string/flsll.c if (!T.isOSFreeBSD()) { TLI.setUnavailable(LibFunc::fls); TLI.setUnavailable(LibFunc::flsl); TLI.setUnavailable(LibFunc::flsll); } // The following functions are available on at least Linux: if (!T.isOSLinux()) { TLI.setUnavailable(LibFunc::dunder_strdup); TLI.setUnavailable(LibFunc::dunder_strtok_r); TLI.setUnavailable(LibFunc::dunder_isoc99_scanf); TLI.setUnavailable(LibFunc::dunder_isoc99_sscanf); TLI.setUnavailable(LibFunc::under_IO_getc); TLI.setUnavailable(LibFunc::under_IO_putc); TLI.setUnavailable(LibFunc::memalign); TLI.setUnavailable(LibFunc::fopen64); TLI.setUnavailable(LibFunc::fseeko64); TLI.setUnavailable(LibFunc::fstat64); TLI.setUnavailable(LibFunc::fstatvfs64); TLI.setUnavailable(LibFunc::ftello64); TLI.setUnavailable(LibFunc::lstat64); TLI.setUnavailable(LibFunc::open64); TLI.setUnavailable(LibFunc::stat64); TLI.setUnavailable(LibFunc::statvfs64); TLI.setUnavailable(LibFunc::tmpfile64); } // As currently implemented in clang, NVPTX code has no standard library to // speak of. Headers provide a standard-ish library implementation, but many // of the signatures are wrong -- for example, many libm functions are not // extern "C". // // libdevice, an IR library provided by nvidia, is linked in by the front-end, // but only used functions are provided to llvm. Moreover, most of the // functions in libdevice don't map precisely to standard library functions. // // FIXME: Having no standard library prevents e.g. many fastmath // optimizations, so this situation should be fixed. if (T.isNVPTX()) { TLI.disableAllFunctions(); TLI.setAvailable(LibFunc::nvvm_reflect); } else { TLI.setUnavailable(LibFunc::nvvm_reflect); } TLI.addVectorizableFunctionsFromVecLib(ClVectorLibrary); }
void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) { assert(UL.size() == varlist_size() && "Number of updates is not the same as the preallocated buffer"); std::copy(UL.begin(), UL.end(), getInits().end()); }
void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " "not the same as the " "preallocated buffer"); std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end()); }
static void buildFixItLine(std::string &CaretLine, std::string &FixItLine, ArrayRef<SMFixIt> FixIts, ArrayRef<char> SourceLine){ if (FixIts.empty()) return; const char *LineStart = SourceLine.begin(); const char *LineEnd = SourceLine.end(); size_t PrevHintEndCol = 0; for (ArrayRef<SMFixIt>::iterator I = FixIts.begin(), E = FixIts.end(); I != E; ++I) { // If the fixit contains a newline or tab, ignore it. if (I->getText().find_first_of("\n\r\t") != StringRef::npos) continue; SMRange R = I->getRange(); // If the line doesn't contain any part of the range, then ignore it. if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart) continue; // Translate from SMLoc to column. // Ignore pieces of the range that go onto other lines. // FIXME: Handle multibyte characters in the source line. unsigned FirstCol; if (R.Start.getPointer() < LineStart) FirstCol = 0; else FirstCol = R.Start.getPointer() - LineStart; // If we inserted a long previous hint, push this one forwards, and add // an extra space to show that this is not part of the previous // completion. This is sort of the best we can do when two hints appear // to overlap. // // Note that if this hint is located immediately after the previous // hint, no space will be added, since the location is more important. unsigned HintCol = FirstCol; if (HintCol < PrevHintEndCol) HintCol = PrevHintEndCol + 1; // This relies on one byte per column in our fixit hints. unsigned LastColumnModified = HintCol + I->getText().size(); if (LastColumnModified > FixItLine.size()) FixItLine.resize(LastColumnModified, ' '); std::copy(I->getText().begin(), I->getText().end(), FixItLine.begin() + HintCol); PrevHintEndCol = LastColumnModified; // For replacements, mark the removal range with '~'. // FIXME: Handle multibyte characters in the source line. unsigned LastCol; if (R.End.getPointer() >= LineEnd) LastCol = LineEnd - LineStart; else LastCol = R.End.getPointer() - LineStart; std::fill(&CaretLine[FirstCol], &CaretLine[LastCol], '~'); } }
void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) { assert(PrivateCopies.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end()); }
void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, const PathDiagnosticPiece& P, unsigned num, unsigned max) { // For now, just draw a box above the line in question, and emit the // warning. FullSourceLoc Pos = P.getLocation().asLocation(); if (!Pos.isValid()) return; SourceManager &SM = R.getSourceMgr(); assert(&Pos.getManager() == &SM && "SourceManagers are different!"); std::pair<FileID, unsigned> LPosInfo = SM.getDecomposedExpansionLoc(Pos); if (LPosInfo.first != BugFileID) return; const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first); const char* FileStart = Buf->getBufferStart(); // Compute the column number. Rewind from the current position to the start // of the line. unsigned ColNo = SM.getColumnNumber(LPosInfo.first, LPosInfo.second); const char *TokInstantiationPtr =Pos.getExpansionLoc().getCharacterData(); const char *LineStart = TokInstantiationPtr-ColNo; // Compute LineEnd. const char *LineEnd = TokInstantiationPtr; const char* FileEnd = Buf->getBufferEnd(); while (*LineEnd != '\n' && LineEnd != FileEnd) ++LineEnd; // Compute the margin offset by counting tabs and non-tabs. unsigned PosNo = 0; for (const char* c = LineStart; c != TokInstantiationPtr; ++c) PosNo += *c == '\t' ? 8 : 1; // Create the html for the message. const char *Kind = nullptr; switch (P.getKind()) { case PathDiagnosticPiece::Call: llvm_unreachable("Calls should already be handled"); case PathDiagnosticPiece::Event: Kind = "Event"; break; case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break; // Setting Kind to "Control" is intentional. case PathDiagnosticPiece::Macro: Kind = "Control"; break; } std::string sbuf; llvm::raw_string_ostream os(sbuf); os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\""; if (num == max) os << "EndPath"; else os << "Path" << num; os << "\" class=\"msg"; if (Kind) os << " msg" << Kind; os << "\" style=\"margin-left:" << PosNo << "ex"; // Output a maximum size. if (!isa<PathDiagnosticMacroPiece>(P)) { // Get the string and determining its maximum substring. const std::string& Msg = P.getString(); unsigned max_token = 0; unsigned cnt = 0; unsigned len = Msg.size(); for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I) switch (*I) { default: ++cnt; continue; case ' ': case '\t': case '\n': if (cnt > max_token) max_token = cnt; cnt = 0; } if (cnt > max_token) max_token = cnt; // Determine the approximate size of the message bubble in em. unsigned em; const unsigned max_line = 120; if (max_token >= max_line) em = max_token / 2; else { unsigned characters = max_line; unsigned lines = len / max_line; if (lines > 0) { for (; characters > max_token; --characters) if (len / characters > lines) { ++characters; break; } } em = characters / 2; } if (em < max_line/2) os << "; max-width:" << em << "em"; } else os << "; max-width:100em"; os << "\">"; if (max > 1) { os << "<table class=\"msgT\"><tr><td valign=\"top\">"; os << "<div class=\"PathIndex"; if (Kind) os << " PathIndex" << Kind; os << "\">" << num << "</div>"; if (num > 1) { os << "</td><td><div class=\"PathNav\"><a href=\"#Path" << (num - 1) << "\" title=\"Previous event (" << (num - 1) << ")\">←</a></div></td>"; } os << "</td><td>"; } if (const PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(&P)) { os << "Within the expansion of the macro '"; // Get the name of the macro by relexing it. { FullSourceLoc L = MP->getLocation().asLocation().getExpansionLoc(); assert(L.isFileID()); StringRef BufferInfo = L.getBufferData(); std::pair<FileID, unsigned> LocInfo = L.getDecomposedLoc(); const char* MacroName = LocInfo.second + BufferInfo.data(); Lexer rawLexer(SM.getLocForStartOfFile(LocInfo.first), PP.getLangOpts(), BufferInfo.begin(), MacroName, BufferInfo.end()); Token TheTok; rawLexer.LexFromRawLexer(TheTok); for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i) os << MacroName[i]; } os << "':\n"; if (max > 1) { os << "</td>"; if (num < max) { os << "<td><div class=\"PathNav\"><a href=\"#"; if (num == max - 1) os << "EndPath"; else os << "Path" << (num + 1); os << "\" title=\"Next event (" << (num + 1) << ")\">→</a></div></td>"; } os << "</tr></table>"; } // Within a macro piece. Write out each event. ProcessMacroPiece(os, *MP, 0); } else { os << html::EscapeText(P.getString()); if (max > 1) { os << "</td>"; if (num < max) { os << "<td><div class=\"PathNav\"><a href=\"#"; if (num == max - 1) os << "EndPath"; else os << "Path" << (num + 1); os << "\" title=\"Next event (" << (num + 1) << ")\">→</a></div></td>"; } os << "</tr></table>"; } } os << "</div></td></tr>"; // Insert the new html. unsigned DisplayPos = LineEnd - FileStart; SourceLocation Loc = SM.getLocForStartOfFile(LPosInfo.first).getLocWithOffset(DisplayPos); R.InsertTextBefore(Loc, os.str()); // Now highlight the ranges. ArrayRef<SourceRange> Ranges = P.getRanges(); for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { HighlightRange(R, LPosInfo.first, *I); } }
/// Update the PHI nodes in OrigBB to include the values coming from NewBB. /// This also updates AliasAnalysis, if available. static void UpdatePHINodes(BasicBlock *OrigBB, BasicBlock *NewBB, ArrayRef<BasicBlock *> Preds, BranchInst *BI, bool HasLoopExit) { // Otherwise, create a new PHI node in NewBB for each PHI node in OrigBB. SmallPtrSet<BasicBlock *, 16> PredSet(Preds.begin(), Preds.end()); for (BasicBlock::iterator I = OrigBB->begin(); isa<PHINode>(I); ) { PHINode *PN = cast<PHINode>(I++); // Check to see if all of the values coming in are the same. If so, we // don't need to create a new PHI node, unless it's needed for LCSSA. Value *InVal = nullptr; if (!HasLoopExit) { InVal = PN->getIncomingValueForBlock(Preds[0]); for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { if (!PredSet.count(PN->getIncomingBlock(i))) continue; if (!InVal) InVal = PN->getIncomingValue(i); else if (InVal != PN->getIncomingValue(i)) { InVal = nullptr; break; } } } if (InVal) { // If all incoming values for the new PHI would be the same, just don't // make a new PHI. Instead, just remove the incoming values from the old // PHI. // NOTE! This loop walks backwards for a reason! First off, this minimizes // the cost of removal if we end up removing a large number of values, and // second off, this ensures that the indices for the incoming values // aren't invalidated when we remove one. for (int64_t i = PN->getNumIncomingValues() - 1; i >= 0; --i) if (PredSet.count(PN->getIncomingBlock(i))) PN->removeIncomingValue(i, false); // Add an incoming value to the PHI node in the loop for the preheader // edge. PN->addIncoming(InVal, NewBB); continue; } // If the values coming into the block are not the same, we need a new // PHI. // Create the new PHI node, insert it into NewBB at the end of the block PHINode *NewPHI = PHINode::Create(PN->getType(), Preds.size(), PN->getName() + ".ph", BI); // NOTE! This loop walks backwards for a reason! First off, this minimizes // the cost of removal if we end up removing a large number of values, and // second off, this ensures that the indices for the incoming values aren't // invalidated when we remove one. for (int64_t i = PN->getNumIncomingValues() - 1; i >= 0; --i) { BasicBlock *IncomingBB = PN->getIncomingBlock(i); if (PredSet.count(IncomingBB)) { Value *V = PN->removeIncomingValue(i, false); NewPHI->addIncoming(V, IncomingBB); } } PN->addIncoming(NewPHI, NewBB); } }
void arcmt::writeARCDiagsToPlist(const std::string &outPath, ArrayRef<StoredDiagnostic> diags, SourceManager &SM, const LangOptions &LangOpts) { DiagnosticIDs DiagIDs; // Build up a set of FIDs that we use by scanning the locations and // ranges of the diagnostics. FIDMap FM; SmallVector<FileID, 10> Fids; for (ArrayRef<StoredDiagnostic>::iterator I = diags.begin(), E = diags.end(); I != E; ++I) { const StoredDiagnostic &D = *I; AddFID(FM, Fids, SM, D.getLocation()); for (StoredDiagnostic::range_iterator RI = D.range_begin(), RE = D.range_end(); RI != RE; ++RI) { AddFID(FM, Fids, SM, RI->getBegin()); AddFID(FM, Fids, SM, RI->getEnd()); } } std::string errMsg; llvm::raw_fd_ostream o(outPath.c_str(), errMsg); if (!errMsg.empty()) { llvm::errs() << "error: could not create file: " << outPath << '\n'; return; } // Write the plist header. o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" " "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" "<plist version=\"1.0\">\n"; // Write the root object: a <dict> containing... // - "files", an <array> mapping from FIDs to file names // - "diagnostics", an <array> containing the diagnostics o << "<dict>\n" " <key>files</key>\n" " <array>\n"; for (SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end(); I!=E; ++I) { o << " "; EmitString(o, SM.getFileEntryForID(*I)->getName()) << '\n'; } o << " </array>\n" " <key>diagnostics</key>\n" " <array>\n"; for (ArrayRef<StoredDiagnostic>::iterator DI = diags.begin(), DE = diags.end(); DI != DE; ++DI) { const StoredDiagnostic &D = *DI; if (D.getLevel() == DiagnosticsEngine::Ignored) continue; o << " <dict>\n"; // Output the diagnostic. o << " <key>description</key>"; EmitString(o, D.getMessage()) << '\n'; o << " <key>category</key>"; EmitString(o, DiagIDs.getCategoryNameFromID( DiagIDs.getCategoryNumberForDiag(D.getID()))) << '\n'; o << " <key>type</key>"; if (D.getLevel() >= DiagnosticsEngine::Error) EmitString(o, "error") << '\n'; else if (D.getLevel() == DiagnosticsEngine::Warning) EmitString(o, "warning") << '\n'; else EmitString(o, "note") << '\n'; // Output the location of the bug. o << " <key>location</key>\n"; EmitLocation(o, SM, LangOpts, D.getLocation(), FM, 2); // Output the ranges (if any). StoredDiagnostic::range_iterator RI = D.range_begin(), RE = D.range_end(); if (RI != RE) { o << " <key>ranges</key>\n"; o << " <array>\n"; for (; RI != RE; ++RI) EmitRange(o, SM, LangOpts, *RI, FM, 4); o << " </array>\n"; } // Close up the entry. o << " </dict>\n"; } o << " </array>\n"; // Finish. o << "</dict>\n</plist>"; }
void LLVM_General_GetInstStructureIndices(LLVMValueRef v, unsigned *is) { ArrayRef<unsigned> a; if (ExtractValueInst *i = dyn_cast<ExtractValueInst>(unwrap(v))) a = i->getIndices(); if (InsertValueInst *i = dyn_cast<InsertValueInst>(unwrap(v))) a = i->getIndices(); std::copy(a.begin(), a.end(), is); }
/// UpdateAnalysisInformation - Update DominatorTree, LoopInfo, and LCCSA /// analysis information. static void UpdateAnalysisInformation(BasicBlock *OldBB, BasicBlock *NewBB, ArrayRef<BasicBlock *> Preds, Pass *P, bool &HasLoopExit) { if (!P) return; LoopInfo *LI = P->getAnalysisIfAvailable<LoopInfo>(); Loop *L = LI ? LI->getLoopFor(OldBB) : 0; // If we need to preserve loop analyses, collect some information about how // this split will affect loops. bool IsLoopEntry = !!L; bool SplitMakesNewLoopHeader = false; if (LI) { bool PreserveLCSSA = P->mustPreserveAnalysisID(LCSSAID); for (ArrayRef<BasicBlock*>::iterator i = Preds.begin(), e = Preds.end(); i != e; ++i) { BasicBlock *Pred = *i; // If we need to preserve LCSSA, determine if any of the preds is a loop // exit. if (PreserveLCSSA) if (Loop *PL = LI->getLoopFor(Pred)) if (!PL->contains(OldBB)) HasLoopExit = true; // If we need to preserve LoopInfo, note whether any of the preds crosses // an interesting loop boundary. if (!L) continue; if (L->contains(Pred)) IsLoopEntry = false; else SplitMakesNewLoopHeader = true; } } // Update dominator tree if available. DominatorTree *DT = P->getAnalysisIfAvailable<DominatorTree>(); if (DT) DT->splitBlock(NewBB); if (!L) return; if (IsLoopEntry) { // Add the new block to the nearest enclosing loop (and not an adjacent // loop). To find this, examine each of the predecessors and determine which // loops enclose them, and select the most-nested loop which contains the // loop containing the block being split. Loop *InnermostPredLoop = 0; for (ArrayRef<BasicBlock*>::iterator i = Preds.begin(), e = Preds.end(); i != e; ++i) { BasicBlock *Pred = *i; if (Loop *PredLoop = LI->getLoopFor(Pred)) { // Seek a loop which actually contains the block being split (to avoid // adjacent loops). while (PredLoop && !PredLoop->contains(OldBB)) PredLoop = PredLoop->getParentLoop(); // Select the most-nested of these loops which contains the block. if (PredLoop && PredLoop->contains(OldBB) && (!InnermostPredLoop || InnermostPredLoop->getLoopDepth() < PredLoop->getLoopDepth())) InnermostPredLoop = PredLoop; } } if (InnermostPredLoop) InnermostPredLoop->addBasicBlockToLoop(NewBB, LI->getBase()); } else { L->addBasicBlockToLoop(NewBB, LI->getBase()); if (SplitMakesNewLoopHeader) L->moveToHeader(NewBB); } }
static void writeSymbolTable( raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members, std::vector<std::pair<unsigned, unsigned> > &MemberOffsetRefs) { unsigned StartOffset = 0; unsigned MemberNum = 0; std::vector<StringRef> SymNames; std::vector<object::ObjectFile *> DeleteIt; for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(), E = Members.end(); I != E; ++I, ++MemberNum) { object::ObjectFile *Obj; if (I->isNewMember()) { const char *Filename = I->getNew(); Obj = object::ObjectFile::createObjectFile(Filename); } else { object::Archive::child_iterator OldMember = I->getOld(); OwningPtr<object::Binary> Binary; error_code EC = OldMember->getAsBinary(Binary); if (EC) { // FIXME: check only for "not an object file" errors. Obj = NULL; } else { Obj = dyn_cast<object::ObjectFile>(Binary.get()); if (Obj) Binary.take(); } } if (!Obj) continue; DeleteIt.push_back(Obj); if (!StartOffset) { printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0); StartOffset = Out.tell(); print32BE(Out, 0); } error_code Err; for (object::symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E; I.increment(Err), failIfError(Err)) { uint32_t Symflags; failIfError(I->getFlags(Symflags)); if (Symflags & object::SymbolRef::SF_FormatSpecific) continue; if (!(Symflags & object::SymbolRef::SF_Global)) continue; if (Symflags & object::SymbolRef::SF_Undefined) continue; StringRef Name; failIfError(I->getName(Name)); SymNames.push_back(Name); MemberOffsetRefs.push_back(std::make_pair(Out.tell(), MemberNum)); print32BE(Out, 0); } } for (std::vector<StringRef>::iterator I = SymNames.begin(), E = SymNames.end(); I != E; ++I) { Out << *I; Out << '\0'; } for (std::vector<object::ObjectFile *>::iterator I = DeleteIt.begin(), E = DeleteIt.end(); I != E; ++I) { object::ObjectFile *O = *I; delete O; } if (StartOffset == 0) return; if (Out.tell() % 2) Out << '\0'; unsigned Pos = Out.tell(); Out.seek(StartOffset - 12); printWithSpacePadding(Out, Pos - StartOffset, 10); Out.seek(StartOffset); print32BE(Out, SymNames.size()); Out.seek(Pos); }
// // runMCDesc - Print out MC register descriptions. // void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, CodeGenRegBank &RegBank) { emitSourceFileHeader("MC Register Information", OS); OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; OS << "#undef GET_REGINFO_MC_DESC\n"; const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); // The lists of sub-registers and super-registers go in the same array. That // allows us to share suffixes. typedef std::vector<const CodeGenRegister*> RegVec; // Differentially encoded lists. SequenceToOffsetTable<DiffVec> DiffSeqs; SmallVector<DiffVec, 4> SubRegLists(Regs.size()); SmallVector<DiffVec, 4> SuperRegLists(Regs.size()); SmallVector<DiffVec, 4> RegUnitLists(Regs.size()); SmallVector<unsigned, 4> RegUnitInitScale(Regs.size()); // Keep track of sub-register names as well. These are not differentially // encoded. typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec; SequenceToOffsetTable<SubRegIdxVec, CodeGenSubRegIndex::Less> SubRegIdxSeqs; SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size()); SequenceToOffsetTable<std::string> RegStrings; // Precompute register lists for the SequenceToOffsetTable. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister *Reg = Regs[i]; RegStrings.add(Reg->getName()); // Compute the ordered sub-register list. SetVector<const CodeGenRegister*> SR; Reg->addSubRegsPreOrder(SR, RegBank); diffEncode(SubRegLists[i], Reg->EnumValue, SR.begin(), SR.end()); DiffSeqs.add(SubRegLists[i]); // Compute the corresponding sub-register indexes. SubRegIdxVec &SRIs = SubRegIdxLists[i]; for (unsigned j = 0, je = SR.size(); j != je; ++j) SRIs.push_back(Reg->getSubRegIndex(SR[j])); SubRegIdxSeqs.add(SRIs); // Super-registers are already computed. const RegVec &SuperRegList = Reg->getSuperRegs(); diffEncode(SuperRegLists[i], Reg->EnumValue, SuperRegList.begin(), SuperRegList.end()); DiffSeqs.add(SuperRegLists[i]); // Differentially encode the register unit list, seeded by register number. // First compute a scale factor that allows more diff-lists to be reused: // // D0 -> (S0, S1) // D1 -> (S2, S3) // // A scale factor of 2 allows D0 and D1 to share a diff-list. The initial // value for the differential decoder is the register number multiplied by // the scale. // // Check the neighboring registers for arithmetic progressions. unsigned ScaleA = ~0u, ScaleB = ~0u; ArrayRef<unsigned> RUs = Reg->getNativeRegUnits(); if (i > 0 && Regs[i-1]->getNativeRegUnits().size() == RUs.size()) ScaleB = RUs.front() - Regs[i-1]->getNativeRegUnits().front(); if (i+1 != Regs.size() && Regs[i+1]->getNativeRegUnits().size() == RUs.size()) ScaleA = Regs[i+1]->getNativeRegUnits().front() - RUs.front(); unsigned Scale = std::min(ScaleB, ScaleA); // Default the scale to 0 if it can't be encoded in 4 bits. if (Scale >= 16) Scale = 0; RegUnitInitScale[i] = Scale; DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg->EnumValue, RUs)); } // Compute the final layout of the sequence table. DiffSeqs.layout(); SubRegIdxSeqs.layout(); OS << "namespace llvm {\n\n"; const std::string &TargetName = Target.getName(); // Emit the shared table of differential lists. OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[] = {\n"; DiffSeqs.emit(OS, printDiff16); OS << "};\n\n"; // Emit the table of sub-register indexes. OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n"; SubRegIdxSeqs.emit(OS, printSubRegIndex); OS << "};\n\n"; // Emit the table of sub-register index sizes. OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName << "SubRegIdxRanges[] = {\n"; OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; for (ArrayRef<CodeGenSubRegIndex*>::const_iterator SRI = SubRegIndices.begin(), SRE = SubRegIndices.end(); SRI != SRE; ++SRI) { OS << " { " << (*SRI)->Offset << ", " << (*SRI)->Size << " },\t// " << (*SRI)->getName() << "\n"; } OS << "};\n\n"; // Emit the string table. RegStrings.layout(); OS << "extern const char " << TargetName << "RegStrings[] = {\n"; RegStrings.emit(OS, printChar); OS << "};\n\n"; OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[] = { // Descriptors\n"; OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0 },\n"; // Emit the register descriptors now. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister *Reg = Regs[i]; OS << " { " << RegStrings.get(Reg->getName()) << ", " << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i]) << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " << (DiffSeqs.get(RegUnitLists[i])*16 + RegUnitInitScale[i]) << " },\n"; } OS << "};\n\n"; // End of register descriptors... // Emit the table of register unit roots. Each regunit has one or two root // registers. OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2] = {\n"; for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) { ArrayRef<const CodeGenRegister*> Roots = RegBank.getRegUnit(i).getRoots(); assert(!Roots.empty() && "All regunits must have a root register."); assert(Roots.size() <= 2 && "More than two roots not supported yet."); OS << " { " << getQualifiedName(Roots.front()->TheDef); for (unsigned r = 1; r != Roots.size(); ++r) OS << ", " << getQualifiedName(Roots[r]->TheDef); OS << " },\n"; } OS << "};\n\n"; ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; // Emit the register enum value arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; ArrayRef<Record*> Order = RC.getOrder(); // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " const uint16_t " << Name << "[] = {\n "; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; OS << getQualifiedName(Reg) << ", "; } OS << "\n };\n\n"; OS << " // " << Name << " Bit set.\n" << " const uint8_t " << Name << "Bits[] = {\n "; BitVectorEmitter BVE; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; BVE.add(Target.getRegBank().getReg(Reg)->EnumValue); } BVE.print(OS); OS << "\n };\n\n"; } OS << "}\n\n"; OS << "extern const MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; // Asserts to make sure values will fit in table assuming types from // MCRegisterInfo.h assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large."); assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); OS << " { " << '\"' << RC.getName() << "\", " << RC.getName() << ", " << RC.getName() << "Bits, " << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " << RC.SpillAlignment/8 << ", " << RC.CopyCost << ", " << RC.Allocatable << " },\n"; } OS << "};\n\n"; EmitRegMappingTables(OS, Regs, false); // Emit Reg encoding table OS << "extern const uint16_t " << TargetName; OS << "RegEncodingTable[] = {\n"; // Add entry for NoRegister OS << " 0,\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { Record *Reg = Regs[i]->TheDef; BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding"); uint64_t Value = 0; for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { if (BitInit *B = dyn_cast<BitInit>(BI->getBit(b))) Value |= (uint64_t)B->getValue() << b; } OS << " " << Value << ",\n"; } OS << "};\n"; // End of HW encoding table // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) {\n" << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " << TargetName << "RegStrings, " << TargetName << "SubRegIdxLists, " << (SubRegIndices.size() + 1) << ",\n" << TargetName << "SubRegIdxRanges, " << " " << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); OS << "}\n\n"; OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_MC_DESC\n\n"; }
void RegisterInfoEmitter:: EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, const std::string &ClassName) { unsigned NumRCs = RegBank.getRegClasses().size(); unsigned NumSets = RegBank.getNumRegPressureSets(); OS << "/// Get the weight in units of pressure for this register class.\n" << "const RegClassWeight &" << ClassName << "::\n" << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" << " static const RegClassWeight RCWeightTable[] = {\n"; for (unsigned i = 0, e = NumRCs; i != e; ++i) { const CodeGenRegisterClass &RC = *RegBank.getRegClasses()[i]; const CodeGenRegister::Set &Regs = RC.getMembers(); if (Regs.empty()) OS << " {0, 0"; else { std::vector<unsigned> RegUnits; RC.buildRegUnitSet(RegUnits); OS << " {" << (*Regs.begin())->getWeight(RegBank) << ", " << RegBank.getRegUnitSetWeight(RegUnits); } OS << "}, \t// " << RC.getName() << "\n"; } OS << " {0, 0} };\n" << " return RCWeightTable[RC->getID()];\n" << "}\n\n"; // Reasonable targets (not ARMv7) have unit weight for all units, so don't // bother generating a table. bool RegUnitsHaveUnitWeight = true; for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); UnitIdx < UnitEnd; ++UnitIdx) { if (RegBank.getRegUnit(UnitIdx).Weight > 1) RegUnitsHaveUnitWeight = false; } OS << "/// Get the weight in units of pressure for this register unit.\n" << "unsigned " << ClassName << "::\n" << "getRegUnitWeight(unsigned RegUnit) const {\n" << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() << " && \"invalid register unit\");\n"; if (!RegUnitsHaveUnitWeight) { OS << " static const uint8_t RUWeightTable[] = {\n "; for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); UnitIdx < UnitEnd; ++UnitIdx) { const RegUnit &RU = RegBank.getRegUnit(UnitIdx); assert(RU.Weight < 256 && "RegUnit too heavy"); OS << RU.Weight << ", "; } OS << "0 };\n" << " return RUWeightTable[RegUnit];\n"; } else { OS << " // All register units have unit weight.\n" << " return 1;\n"; } OS << "}\n\n"; OS << "\n" << "// Get the number of dimensions of register pressure.\n" << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n" << " return " << NumSets << ";\n}\n\n"; OS << "// Get the name of this register unit pressure set.\n" << "const char *" << ClassName << "::\n" << "getRegPressureSetName(unsigned Idx) const {\n" << " static const char *PressureNameTable[] = {\n"; for (unsigned i = 0; i < NumSets; ++i ) { OS << " \"" << RegBank.getRegSetAt(i).Name << "\",\n"; } OS << " 0 };\n" << " return PressureNameTable[Idx];\n" << "}\n\n"; OS << "// Get the register unit pressure limit for this dimension.\n" << "// This limit must be adjusted dynamically for reserved registers.\n" << "unsigned " << ClassName << "::\n" << "getRegPressureSetLimit(unsigned Idx) const {\n" << " static const unsigned PressureLimitTable[] = {\n"; for (unsigned i = 0; i < NumSets; ++i ) { const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); OS << " " << RegUnits.Weight << ", \t// " << i << ": " << RegUnits.Name << "\n"; } OS << " 0 };\n" << " return PressureLimitTable[Idx];\n" << "}\n\n"; // This table may be larger than NumRCs if some register units needed a list // of unit sets that did not correspond to a register class. unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists(); OS << "/// Table of pressure sets per register class or unit.\n" << "static const int RCSetsTable[] = {\n "; std::vector<unsigned> RCSetStarts(NumRCUnitSets); for (unsigned i = 0, StartIdx = 0, e = NumRCUnitSets; i != e; ++i) { RCSetStarts[i] = StartIdx; ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(i); std::vector<unsigned> PSets; PSets.reserve(PSetIDs.size()); for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(), PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { PSets.push_back(RegBank.getRegPressureSet(*PSetI).Order); } std::sort(PSets.begin(), PSets.end()); for (unsigned j = 0, e = PSets.size(); j < e; ++j) { OS << PSets[j] << ", "; ++StartIdx; } OS << "-1, \t// #" << RCSetStarts[i] << " "; if (i < NumRCs) OS << RegBank.getRegClasses()[i]->getName(); else { OS << "inferred"; for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(), PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { OS << "~" << RegBank.getRegSetAt(*PSetI).Name; } } OS << "\n "; ++StartIdx; } OS << "-1 };\n\n"; OS << "/// Get the dimensions of register pressure impacted by this " << "register class.\n" << "/// Returns a -1 terminated array of pressure set IDs\n" << "const int* " << ClassName << "::\n" << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n"; OS << " static const unsigned RCSetStartTable[] = {\n "; for (unsigned i = 0, e = NumRCs; i != e; ++i) { OS << RCSetStarts[i] << ","; } OS << "0 };\n" << " unsigned SetListStart = RCSetStartTable[RC->getID()];\n" << " return &RCSetsTable[SetListStart];\n" << "}\n\n"; OS << "/// Get the dimensions of register pressure impacted by this " << "register unit.\n" << "/// Returns a -1 terminated array of pressure set IDs\n" << "const int* " << ClassName << "::\n" << "getRegUnitPressureSets(unsigned RegUnit) const {\n" << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() << " && \"invalid register unit\");\n"; OS << " static const unsigned RUSetStartTable[] = {\n "; for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); UnitIdx < UnitEnd; ++UnitIdx) { OS << RCSetStarts[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx] << ","; } OS << "0 };\n" << " unsigned SetListStart = RUSetStartTable[RegUnit];\n" << " return &RCSetsTable[SetListStart];\n" << "}\n\n"; }
// // runTargetDesc - Output the target register and register file descriptions. // void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, CodeGenRegBank &RegBank){ emitSourceFileHeader("Target Register and Register Classes Information", OS); OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n"; OS << "#undef GET_REGINFO_TARGET_DESC\n"; OS << "namespace llvm {\n\n"; // Get access to MCRegisterClass data. OS << "extern const MCRegisterClass " << Target.getName() << "MCRegisterClasses[];\n"; // Start out by emitting each of the register classes. ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); // Collect all registers belonging to any allocatable class. std::set<Record*> AllocatableRegs; // Collect allocatable registers. for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; ArrayRef<Record*> Order = RC.getOrder(); if (RC.Allocatable) AllocatableRegs.insert(Order.begin(), Order.end()); } // Build a shared array of value types. SequenceToOffsetTable<SmallVector<MVT::SimpleValueType, 4> > VTSeqs; for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) VTSeqs.add(RegisterClasses[rc]->VTs); VTSeqs.layout(); OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n"; VTSeqs.emit(OS, printSimpleValueType, "MVT::Other"); OS << "};\n"; // Emit SubRegIndex names, skipping 0. OS << "\nstatic const char *const SubRegIndexNameTable[] = { \""; for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { OS << SubRegIndices[i]->getName(); if (i + 1 != e) OS << "\", \""; } OS << "\" };\n\n"; // Emit SubRegIndex lane masks, including 0. OS << "\nstatic const unsigned SubRegIndexLaneMaskTable[] = {\n ~0u,\n"; for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { OS << format(" 0x%08x, // ", SubRegIndices[i]->LaneMask) << SubRegIndices[i]->getName() << '\n'; } OS << " };\n\n"; OS << "\n"; // Now that all of the structs have been emitted, emit the instances. if (!RegisterClasses.empty()) { OS << "\nstatic const TargetRegisterClass *const " << "NullRegClasses[] = { NULL };\n\n"; // Emit register class bit mask tables. The first bit mask emitted for a // register class, RC, is the set of sub-classes, including RC itself. // // If RC has super-registers, also create a list of subreg indices and bit // masks, (Idx, Mask). The bit mask has a bit for every superreg regclass, // SuperRC, that satisfies: // // For all SuperReg in SuperRC: SuperReg:Idx in RC // // The 0-terminated list of subreg indices starts at: // // RC->getSuperRegIndices() = SuperRegIdxSeqs + ... // // The corresponding bitmasks follow the sub-class mask in memory. Each // mask has RCMaskWords uint32_t entries. // // Every bit mask present in the list has at least one bit set. // Compress the sub-reg index lists. typedef std::vector<const CodeGenSubRegIndex*> IdxList; SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size()); SequenceToOffsetTable<IdxList, CodeGenSubRegIndex::Less> SuperRegIdxSeqs; BitVector MaskBV(RegisterClasses.size()); for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; OS << "static const uint32_t " << RC.getName() << "SubClassMask[] = {\n "; printBitVectorAsHex(OS, RC.getSubClasses(), 32); // Emit super-reg class masks for any relevant SubRegIndices that can // project into RC. IdxList &SRIList = SuperRegIdxLists[rc]; for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { CodeGenSubRegIndex *Idx = SubRegIndices[sri]; MaskBV.reset(); RC.getSuperRegClasses(Idx, MaskBV); if (MaskBV.none()) continue; SRIList.push_back(Idx); OS << "\n "; printBitVectorAsHex(OS, MaskBV, 32); OS << "// " << Idx->getName(); } SuperRegIdxSeqs.add(SRIList); OS << "\n};\n\n"; } OS << "static const uint16_t SuperRegIdxSeqs[] = {\n"; SuperRegIdxSeqs.layout(); SuperRegIdxSeqs.emit(OS, printSubRegIndex); OS << "};\n\n"; // Emit NULL terminated super-class lists. for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; ArrayRef<CodeGenRegisterClass*> Supers = RC.getSuperClasses(); // Skip classes without supers. We can reuse NullRegClasses. if (Supers.empty()) continue; OS << "static const TargetRegisterClass *const " << RC.getName() << "Superclasses[] = {\n"; for (unsigned i = 0; i != Supers.size(); ++i) OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n"; OS << " NULL\n};\n\n"; } // Emit methods. for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { const CodeGenRegisterClass &RC = *RegisterClasses[i]; if (!RC.AltOrderSelect.empty()) { OS << "\nstatic inline unsigned " << RC.getName() << "AltOrderSelect(const MachineFunction &MF) {" << RC.AltOrderSelect << "}\n\n" << "static ArrayRef<MCPhysReg> " << RC.getName() << "GetRawAllocationOrder(const MachineFunction &MF) {\n"; for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) { ArrayRef<Record*> Elems = RC.getOrder(oi); if (!Elems.empty()) { OS << " static const MCPhysReg AltOrder" << oi << "[] = {"; for (unsigned elem = 0; elem != Elems.size(); ++elem) OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); OS << " };\n"; } } OS << " const MCRegisterClass &MCR = " << Target.getName() << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n" << " const ArrayRef<MCPhysReg> Order[] = {\n" << " makeArrayRef(MCR.begin(), MCR.getNumRegs()"; for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) if (RC.getOrder(oi).empty()) OS << "),\n ArrayRef<MCPhysReg>("; else OS << "),\n makeArrayRef(AltOrder" << oi; OS << ")\n };\n const unsigned Select = " << RC.getName() << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() << ");\n return Order[Select];\n}\n"; } } // Now emit the actual value-initialized register class instances. OS << "namespace " << RegisterClasses[0]->Namespace << " { // Register class instances\n"; for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { const CodeGenRegisterClass &RC = *RegisterClasses[i]; OS << " extern const TargetRegisterClass " << RegisterClasses[i]->getName() << "RegClass = {\n " << '&' << Target.getName() << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n " << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + " << SuperRegIdxSeqs.get(SuperRegIdxLists[i]) << ",\n "; if (RC.getSuperClasses().empty()) OS << "NullRegClasses,\n "; else OS << RC.getName() << "Superclasses,\n "; if (RC.AltOrderSelect.empty()) OS << "0\n"; else OS << RC.getName() << "GetRawAllocationOrder\n"; OS << " };\n\n"; } OS << "}\n"; } OS << "\nnamespace {\n"; OS << " const TargetRegisterClass* const RegisterClasses[] = {\n"; for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) OS << " &" << RegisterClasses[i]->getQualifiedName() << "RegClass,\n"; OS << " };\n"; OS << "}\n"; // End of anonymous namespace... // Emit extra information about registers. const std::string &TargetName = Target.getName(); OS << "\nstatic const TargetRegisterInfoDesc " << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n"; OS << " { 0, 0 },\n"; const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister &Reg = *Regs[i]; OS << " { "; OS << Reg.CostPerUse << ", " << int(AllocatableRegs.count(Reg.TheDef)) << " },\n"; } OS << "};\n"; // End of register descriptors... std::string ClassName = Target.getName() + "GenRegisterInfo"; if (!SubRegIndices.empty()) emitComposeSubRegIndices(OS, RegBank, ClassName); // Emit getSubClassWithSubReg. if (!SubRegIndices.empty()) { OS << "const TargetRegisterClass *" << ClassName << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)" << " const {\n"; // Use the smallest type that can hold a regclass ID with room for a // sentinel. if (RegisterClasses.size() < UINT8_MAX) OS << " static const uint8_t Table["; else if (RegisterClasses.size() < UINT16_MAX) OS << " static const uint16_t Table["; else PrintFatalError("Too many register classes."); OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n"; for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { const CodeGenRegisterClass &RC = *RegisterClasses[rci]; OS << " {\t// " << RC.getName() << "\n"; for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { CodeGenSubRegIndex *Idx = SubRegIndices[sri]; if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx)) OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName() << " -> " << SRC->getName() << "\n"; else OS << " 0,\t// " << Idx->getName() << "\n"; } OS << " },\n"; } OS << " };\n assert(RC && \"Missing regclass\");\n" << " if (!Idx) return RC;\n --Idx;\n" << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" << " unsigned TV = Table[RC->getID()][Idx];\n" << " return TV ? getRegClass(TV - 1) : 0;\n}\n\n"; } EmitRegUnitPressure(OS, RegBank, ClassName); // Emit the constructor of the class... OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; OS << "extern const char " << TargetName << "RegStrings[];\n"; OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2];\n"; OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName << "SubRegIdxRanges[];\n"; OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n"; EmitRegMappingTables(OS, Regs, true); OS << ClassName << "::\n" << ClassName << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour, unsigned PC)\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" << " SubRegIndexNameTable, SubRegIndexLaneMaskTable, 0x"; OS.write_hex(RegBank.CoveringLanes); OS << ") {\n" << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ", RA, PC,\n " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" << " " << TargetName << "RegUnitRoots,\n" << " " << RegBank.getNumNativeRegUnits() << ",\n" << " " << TargetName << "RegDiffLists,\n" << " " << TargetName << "RegStrings,\n" << " " << TargetName << "SubRegIdxLists,\n" << " " << SubRegIndices.size() + 1 << ",\n" << " " << TargetName << "SubRegIdxRanges,\n" << " " << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, true); OS << "}\n\n"; // Emit CalleeSavedRegs information. std::vector<Record*> CSRSets = Records.getAllDerivedDefinitions("CalleeSavedRegs"); for (unsigned i = 0, e = CSRSets.size(); i != e; ++i) { Record *CSRSet = CSRSets[i]; const SetTheory::RecVec *Regs = RegBank.getSets().expand(CSRSet); assert(Regs && "Cannot expand CalleeSavedRegs instance"); // Emit the *_SaveList list of callee-saved registers. OS << "static const MCPhysReg " << CSRSet->getName() << "_SaveList[] = { "; for (unsigned r = 0, re = Regs->size(); r != re; ++r) OS << getQualifiedName((*Regs)[r]) << ", "; OS << "0 };\n"; // Emit the *_RegMask bit mask of call-preserved registers. BitVector Covered = RegBank.computeCoveredRegisters(*Regs); // Check for an optional OtherPreserved set. // Add those registers to RegMask, but not to SaveList. if (DagInit *OPDag = dyn_cast<DagInit>(CSRSet->getValueInit("OtherPreserved"))) { SetTheory::RecSet OPSet; RegBank.getSets().evaluate(OPDag, OPSet, CSRSet->getLoc()); Covered |= RegBank.computeCoveredRegisters( ArrayRef<Record*>(OPSet.begin(), OPSet.end())); } OS << "static const uint32_t " << CSRSet->getName() << "_RegMask[] = { "; printBitVectorAsHex(OS, Covered, 32); OS << "};\n"; } OS << "\n\n"; OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; }
static std::string buildFixItInsertionLine(unsigned LineNo, const SourceColumnMap &map, ArrayRef<FixItHint> Hints, const SourceManager &SM, const DiagnosticOptions *DiagOpts) { std::string FixItInsertionLine; if (Hints.empty() || !DiagOpts->ShowFixits) return FixItInsertionLine; unsigned PrevHintEndCol = 0; for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end(); I != E; ++I) { if (!I->CodeToInsert.empty()) { // We have an insertion hint. Determine whether the inserted // code contains no newlines and is on the same line as the caret. std::pair<FileID, unsigned> HintLocInfo = SM.getDecomposedExpansionLoc(I->RemoveRange.getBegin()); if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) && StringRef(I->CodeToInsert).find_first_of("\n\r") == StringRef::npos) { // Insert the new code into the line just below the code // that the user wrote. // Note: When modifying this function, be very careful about what is a // "column" (printed width, platform-dependent) and what is a // "byte offset" (SourceManager "column"). unsigned HintByteOffset = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1; // The hint must start inside the source or right at the end assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1); unsigned HintCol = map.byteToContainingColumn(HintByteOffset); // If we inserted a long previous hint, push this one forwards, and add // an extra space to show that this is not part of the previous // completion. This is sort of the best we can do when two hints appear // to overlap. // // Note that if this hint is located immediately after the previous // hint, no space will be added, since the location is more important. if (HintCol < PrevHintEndCol) HintCol = PrevHintEndCol + 1; // FIXME: This function handles multibyte characters in the source, but // not in the fixits. This assertion is intended to catch unintended // use of multibyte characters in fixits. If we decide to do this, we'll // have to track separate byte widths for the source and fixit lines. assert((size_t)llvm::sys::locale::columnWidth(I->CodeToInsert) == I->CodeToInsert.size()); // This relies on one byte per column in our fixit hints. // This should NOT use HintByteOffset, because the source might have // Unicode characters in earlier columns. unsigned LastColumnModified = HintCol + I->CodeToInsert.size(); if (LastColumnModified > FixItInsertionLine.size()) FixItInsertionLine.resize(LastColumnModified, ' '); std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(), FixItInsertionLine.begin() + HintCol); PrevHintEndCol = LastColumnModified; } else { FixItInsertionLine.clear(); break; } } } expandTabs(FixItInsertionLine, DiagOpts->TabStop); return FixItInsertionLine; }
/// \brief Compares macro tokens with a specified token value sequence. static bool MacroDefinitionEquals(const MacroInfo *MI, ArrayRef<TokenValue> Tokens) { return Tokens.size() == MI->getNumTokens() && std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()); }
bool Sema::CheckParameterPacksForExpansion( SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef<UnexpandedParameterPack> Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, bool &RetainExpansion, Optional<unsigned> &NumExpansions) { ShouldExpand = true; RetainExpansion = false; std::pair<IdentifierInfo *, SourceLocation> FirstPack; bool HaveFirstPack = false; for (ArrayRef<UnexpandedParameterPack>::iterator i = Unexpanded.begin(), end = Unexpanded.end(); i != end; ++i) { // Compute the depth and index for this parameter pack. unsigned Depth = 0, Index = 0; IdentifierInfo *Name; bool IsFunctionParameterPack = false; if (const TemplateTypeParmType *TTP = i->first.dyn_cast<const TemplateTypeParmType *>()) { Depth = TTP->getDepth(); Index = TTP->getIndex(); Name = TTP->getIdentifier(); } else { NamedDecl *ND = i->first.get<NamedDecl *>(); if (isa<ParmVarDecl>(ND)) IsFunctionParameterPack = true; else llvm::tie(Depth, Index) = getDepthAndIndex(ND); Name = ND->getIdentifier(); } // Determine the size of this argument pack. unsigned NewPackSize; if (IsFunctionParameterPack) { // Figure out whether we're instantiating to an argument pack or not. typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation = CurrentInstantiationScope->findInstantiationOf( i->first.get<NamedDecl *>()); if (Instantiation->is<DeclArgumentPack *>()) { // We could expand this function parameter pack. NewPackSize = Instantiation->get<DeclArgumentPack *>()->size(); } else { // We can't expand this function parameter pack, so we can't expand // the pack expansion. ShouldExpand = false; continue; } } else { // If we don't have a template argument at this depth/index, then we // cannot expand the pack expansion. Make a note of this, but we still // want to check any parameter packs we *do* have arguments for. if (Depth >= TemplateArgs.getNumLevels() || !TemplateArgs.hasTemplateArgument(Depth, Index)) { ShouldExpand = false; continue; } // Determine the size of the argument pack. NewPackSize = TemplateArgs(Depth, Index).pack_size(); } // C++0x [temp.arg.explicit]p9: // Template argument deduction can extend the sequence of template // arguments corresponding to a template parameter pack, even when the // sequence contains explicitly specified template arguments. if (!IsFunctionParameterPack) { if (NamedDecl *PartialPack = CurrentInstantiationScope->getPartiallySubstitutedPack()){ unsigned PartialDepth, PartialIndex; llvm::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack); if (PartialDepth == Depth && PartialIndex == Index) RetainExpansion = true; } } if (!NumExpansions) { // The is the first pack we've seen for which we have an argument. // Record it. NumExpansions = NewPackSize; FirstPack.first = Name; FirstPack.second = i->second; HaveFirstPack = true; continue; } if (NewPackSize != *NumExpansions) { // C++0x [temp.variadic]p5: // All of the parameter packs expanded by a pack expansion shall have // the same number of arguments specified. if (HaveFirstPack) Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict) << FirstPack.first << Name << *NumExpansions << NewPackSize << SourceRange(FirstPack.second) << SourceRange(i->second); else Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel) << Name << *NumExpansions << NewPackSize << SourceRange(i->second); return true; } } return false; }
void PlistDiagnostics::FlushDiagnosticsImpl( std::vector<const PathDiagnostic *> &Diags, FilesMade *filesMade) { // Build up a set of FIDs that we use by scanning the locations and // ranges of the diagnostics. FIDMap FM; SmallVector<FileID, 10> Fids; const SourceManager* SM = 0; if (!Diags.empty()) SM = &(*(*Diags.begin())->path.begin())->getLocation().getManager(); for (std::vector<const PathDiagnostic*>::iterator DI = Diags.begin(), DE = Diags.end(); DI != DE; ++DI) { const PathDiagnostic *D = *DI; llvm::SmallVector<const PathPieces *, 5> WorkList; WorkList.push_back(&D->path); while (!WorkList.empty()) { const PathPieces &path = *WorkList.back(); WorkList.pop_back(); for (PathPieces::const_iterator I = path.begin(), E = path.end(); I!=E; ++I) { const PathDiagnosticPiece *piece = I->getPtr(); AddFID(FM, Fids, SM, piece->getLocation().asLocation()); ArrayRef<SourceRange> Ranges = piece->getRanges(); for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { AddFID(FM, Fids, SM, I->getBegin()); AddFID(FM, Fids, SM, I->getEnd()); } if (const PathDiagnosticCallPiece *call = dyn_cast<PathDiagnosticCallPiece>(piece)) { IntrusiveRefCntPtr<PathDiagnosticEventPiece> callEnterWithin = call->getCallEnterWithinCallerEvent(); if (callEnterWithin) AddFID(FM, Fids, SM, callEnterWithin->getLocation().asLocation()); WorkList.push_back(&call->path); } else if (const PathDiagnosticMacroPiece *macro = dyn_cast<PathDiagnosticMacroPiece>(piece)) { WorkList.push_back(¯o->subPieces); } } } } // Open the file. std::string ErrMsg; llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg); if (!ErrMsg.empty()) { llvm::errs() << "warning: could not create file: " << OutputFile << '\n'; return; } // Write the plist header. o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" " "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" "<plist version=\"1.0\">\n"; // Write the root object: a <dict> containing... // - "files", an <array> mapping from FIDs to file names // - "diagnostics", an <array> containing the path diagnostics o << "<dict>\n" " <key>files</key>\n" " <array>\n"; for (SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end(); I!=E; ++I) { o << " "; EmitString(o, SM->getFileEntryForID(*I)->getName()) << '\n'; } o << " </array>\n" " <key>diagnostics</key>\n" " <array>\n"; for (std::vector<const PathDiagnostic*>::iterator DI=Diags.begin(), DE = Diags.end(); DI!=DE; ++DI) { o << " <dict>\n" " <key>path</key>\n"; const PathDiagnostic *D = *DI; o << " <array>\n"; for (PathPieces::const_iterator I = D->path.begin(), E = D->path.end(); I != E; ++I) ReportDiag(o, **I, FM, *SM, LangOpts); o << " </array>\n"; // Output the bug type and bug category. o << " <key>description</key>"; EmitString(o, D->getShortDescription()) << '\n'; o << " <key>category</key>"; EmitString(o, D->getCategory()) << '\n'; o << " <key>type</key>"; EmitString(o, D->getBugType()) << '\n'; // Output information about the semantic context where // the issue occurred. if (const Decl *DeclWithIssue = D->getDeclWithIssue()) { // FIXME: handle blocks, which have no name. if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) { StringRef declKind; switch (ND->getKind()) { case Decl::CXXRecord: declKind = "C++ class"; break; case Decl::CXXMethod: declKind = "C++ method"; break; case Decl::ObjCMethod: declKind = "Objective-C method"; break; case Decl::Function: declKind = "function"; break; default: break; } if (!declKind.empty()) { const std::string &declName = ND->getDeclName().getAsString(); o << " <key>issue_context_kind</key>"; EmitString(o, declKind) << '\n'; o << " <key>issue_context</key>"; EmitString(o, declName) << '\n'; } // Output the bug hash for issue unique-ing. Currently, it's just an // offset from the beginning of the function. if (const Stmt *Body = DeclWithIssue->getBody()) { FullSourceLoc Loc(SM->getExpansionLoc(D->getLocation().asLocation()), *SM); FullSourceLoc FunLoc(SM->getExpansionLoc(Body->getLocStart()), *SM); o << " <key>issue_hash</key><integer>" << Loc.getExpansionLineNumber() - FunLoc.getExpansionLineNumber() << "</integer>\n"; } } } // Output the location of the bug. o << " <key>location</key>\n"; EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2); // Output the diagnostic to the sub-diagnostic client, if any. if (!filesMade->empty()) { StringRef lastName; PDFileEntry::ConsumerFiles *files = filesMade->getFiles(*D); if (files) { for (PDFileEntry::ConsumerFiles::const_iterator CI = files->begin(), CE = files->end(); CI != CE; ++CI) { StringRef newName = CI->first; if (newName != lastName) { if (!lastName.empty()) { o << " </array>\n"; } lastName = newName; o << " <key>" << lastName << "_files</key>\n"; o << " <array>\n"; } o << " <string>" << CI->second << "</string>\n"; } o << " </array>\n"; } } // Close up the entry. o << " </dict>\n"; } o << " </array>\n"; // Finish. o << "</dict>\n</plist>"; }
/// allocVirtReg - Allocate a physical register for VirtReg. RAFast::LiveRegMap::iterator RAFast::allocVirtReg(MachineInstr *MI, LiveRegMap::iterator LRI, unsigned Hint) { const unsigned VirtReg = LRI->VirtReg; assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && "Can only allocate virtual registers"); const TargetRegisterClass *RC = MRI->getRegClass(VirtReg); // Ignore invalid hints. if (Hint && (!TargetRegisterInfo::isPhysicalRegister(Hint) || !RC->contains(Hint) || !RegClassInfo.isAllocatable(Hint))) Hint = 0; // Take hint when possible. if (Hint) { // Ignore the hint if we would have to spill a dirty register. unsigned Cost = calcSpillCost(Hint); if (Cost < spillDirty) { if (Cost) definePhysReg(MI, Hint, regFree); // definePhysReg may kill virtual registers and modify LiveVirtRegs. // That invalidates LRI, so run a new lookup for VirtReg. return assignVirtToPhysReg(VirtReg, Hint); } } ArrayRef<unsigned> AO = RegClassInfo.getOrder(RC); // First try to find a completely free register. for (ArrayRef<unsigned>::iterator I = AO.begin(), E = AO.end(); I != E; ++I) { unsigned PhysReg = *I; if (PhysRegState[PhysReg] == regFree && !UsedInInstr.test(PhysReg)) { assignVirtToPhysReg(*LRI, PhysReg); return LRI; } } DEBUG(dbgs() << "Allocating " << PrintReg(VirtReg) << " from " << RC->getName() << "\n"); unsigned BestReg = 0, BestCost = spillImpossible; for (ArrayRef<unsigned>::iterator I = AO.begin(), E = AO.end(); I != E; ++I) { unsigned Cost = calcSpillCost(*I); DEBUG(dbgs() << "\tRegister: " << PrintReg(*I, TRI) << "\n"); DEBUG(dbgs() << "\tCost: " << Cost << "\n"); DEBUG(dbgs() << "\tBestCost: " << BestCost << "\n"); // Cost is 0 when all aliases are already disabled. if (Cost == 0) { assignVirtToPhysReg(*LRI, *I); return LRI; } if (Cost < BestCost) BestReg = *I, BestCost = Cost; } if (BestReg) { definePhysReg(MI, BestReg, regFree); // definePhysReg may kill virtual registers and modify LiveVirtRegs. // That invalidates LRI, so run a new lookup for VirtReg. return assignVirtToPhysReg(VirtReg, BestReg); } // Nothing we can do. Report an error and keep going with a bad allocation. MI->emitError("ran out of registers during register allocation"); definePhysReg(MI, *AO.begin(), regFree); return assignVirtToPhysReg(VirtReg, *AO.begin()); }
void PathDiagnosticConsumer::HandlePathDiagnostic( std::unique_ptr<PathDiagnostic> D) { if (!D || D->path.empty()) return; // We need to flatten the locations (convert Stmt* to locations) because // the referenced statements may be freed by the time the diagnostics // are emitted. D->flattenLocations(); // If the PathDiagnosticConsumer does not support diagnostics that // cross file boundaries, prune out such diagnostics now. if (!supportsCrossFileDiagnostics()) { // Verify that the entire path is from the same FileID. FileID FID; const SourceManager &SMgr = D->path.front()->getLocation().getManager(); SmallVector<const PathPieces *, 5> WorkList; WorkList.push_back(&D->path); while (!WorkList.empty()) { const PathPieces &path = *WorkList.pop_back_val(); for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I) { const PathDiagnosticPiece *piece = I->get(); FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc(); if (FID.isInvalid()) { FID = SMgr.getFileID(L); } else if (SMgr.getFileID(L) != FID) return; // FIXME: Emit a warning? // Check the source ranges. ArrayRef<SourceRange> Ranges = piece->getRanges(); for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { SourceLocation L = SMgr.getExpansionLoc(I->getBegin()); if (!L.isFileID() || SMgr.getFileID(L) != FID) return; // FIXME: Emit a warning? L = SMgr.getExpansionLoc(I->getEnd()); if (!L.isFileID() || SMgr.getFileID(L) != FID) return; // FIXME: Emit a warning? } if (const PathDiagnosticCallPiece *call = dyn_cast<PathDiagnosticCallPiece>(piece)) { WorkList.push_back(&call->path); } else if (const PathDiagnosticMacroPiece *macro = dyn_cast<PathDiagnosticMacroPiece>(piece)) { WorkList.push_back(¯o->subPieces); } } } if (FID.isInvalid()) return; // FIXME: Emit a warning? } // Profile the node to see if we already have something matching it llvm::FoldingSetNodeID profile; D->Profile(profile); void *InsertPos = nullptr; if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) { // Keep the PathDiagnostic with the shorter path. // Note, the enclosing routine is called in deterministic order, so the // results will be consistent between runs (no reason to break ties if the // size is the same). const unsigned orig_size = orig->full_size(); const unsigned new_size = D->full_size(); if (orig_size <= new_size) return; assert(orig != D.get()); Diags.RemoveNode(orig); delete orig; } Diags.InsertNode(D.release()); }
SILSpecializeAttr::SILSpecializeAttr(ArrayRef<Requirement> requirements, bool exported, SpecializationKind kind) : numRequirements(requirements.size()), kind(kind), exported(exported) { std::copy(requirements.begin(), requirements.end(), getRequirementsData()); }
static bool verifyTransformedFiles(ArrayRef<std::string> resultFiles) { using namespace llvm; assert(!resultFiles.empty()); std::map<StringRef, StringRef> resultMap; for (ArrayRef<std::string>::iterator I = resultFiles.begin(), E = resultFiles.end(); I != E; ++I) { StringRef fname(*I); if (!fname.endswith(".result")) { errs() << "error: filename '" << fname << "' does not have '.result' extension\n"; return true; } resultMap[sys::path::stem(fname)] = fname; } ErrorOr<std::unique_ptr<MemoryBuffer>> inputBuf = std::error_code(); if (RemappingsFile.empty()) inputBuf = MemoryBuffer::getSTDIN(); else inputBuf = MemoryBuffer::getFile(RemappingsFile); if (!inputBuf) { errs() << "error: could not read remappings input\n"; return true; } SmallVector<StringRef, 8> strs; inputBuf.get()->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); if (strs.empty()) { errs() << "error: no files to verify from stdin\n"; return true; } if (strs.size() % 2 != 0) { errs() << "error: files to verify are not original/result pairs\n"; return true; } for (unsigned i = 0, e = strs.size(); i != e; i += 2) { StringRef inputOrigFname = strs[i]; StringRef inputResultFname = strs[i+1]; std::map<StringRef, StringRef>::iterator It; It = resultMap.find(sys::path::filename(inputOrigFname)); if (It == resultMap.end()) { errs() << "error: '" << inputOrigFname << "' is not in the list of " << "transformed files to verify\n"; return true; } if (!sys::fs::exists(It->second)) { errs() << "error: '" << It->second << "' does not exist\n"; return true; } if (!sys::fs::exists(inputResultFname)) { errs() << "error: '" << inputResultFname << "' does not exist\n"; return true; } if (!filesCompareEqual(It->second, inputResultFname)) { errs() << "error: '" << It->second << "' is different than " << "'" << inputResultFname << "'\n"; return true; } resultMap.erase(It); } if (!resultMap.empty()) { for (std::map<StringRef, StringRef>::iterator I = resultMap.begin(), E = resultMap.end(); I != E; ++I) errs() << "error: '" << I->second << "' was not verified!\n"; return true; } return false; }
void OMPFirstprivateClause::setInits(ArrayRef<Expr *> VL) { assert(VL.size() == varlist_size() && "Number of inits is not the same as the preallocated buffer"); std::copy(VL.begin(), VL.end(), getPrivateCopies().end()); }
/// setCallSiteLandingPad - Map the landing pad's EH symbol to the call site /// indexes. void MachineModuleInfo::setCallSiteLandingPad(MCSymbol *Sym, ArrayRef<unsigned> Sites) { LPadToCallSiteMap[Sym].append(Sites.begin(), Sites.end()); }
void OMPLinearClause::setPrivates(ArrayRef<Expr *> PL) { assert(PL.size() == varlist_size() && "Number of privates is not the same as the preallocated buffer"); std::copy(PL.begin(), PL.end(), varlist_end()); }
/// 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(); Value *Val = MFE.Val; if (Key == "Objective-C Image Info Version") { VersionVal = cast<ConstantInt>(Val)->getZExtValue(); } else if (Key == "Objective-C Garbage Collection" || Key == "Objective-C GC Only" || Key == "Objective-C Is Simulated") { ImageInfoFlags |= cast<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. const MCSectionMachO *S = getContext().getMachOSection(Segment, Section, TAA, StubSize, SectionKind::getDataNoRel()); Streamer.SwitchSection(S); Streamer.EmitLabel(getContext(). GetOrCreateSymbol(StringRef("L_OBJC_IMAGE_INFO"))); Streamer.EmitIntValue(VersionVal, 4); Streamer.EmitIntValue(ImageInfoFlags, 4); Streamer.AddBlankLine(); }
void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) { assert(FL.size() == varlist_size() && "Number of final updates is not the same as the preallocated buffer"); std::copy(FL.begin(), FL.end(), getUpdates().end()); }
/// \brief Print out the file/line/column information and include trace. /// /// This method handlen the emission of the diagnostic location information. /// This includes extracting as much location information as is present for /// the diagnostic and printing it, as well as any include stack or source /// ranges necessary. void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, ArrayRef<CharSourceRange> Ranges, const SourceManager &SM) { if (PLoc.isInvalid()) { // At least print the file name if available: FileID FID = SM.getFileID(Loc); if (!FID.isInvalid()) { const FileEntry* FE = SM.getFileEntryForID(FID); if (FE && FE->getName()) { OS << FE->getName(); if (FE->getDevice() == 0 && FE->getInode() == 0 && FE->getFileMode() == 0) { // in PCH is a guess, but a good one: OS << " (in PCH)"; } OS << ": "; } } return; } unsigned LineNo = PLoc.getLine(); if (!DiagOpts->ShowLocation) return; if (DiagOpts->ShowColors) OS.changeColor(savedColor, true); OS << PLoc.getFilename(); switch (DiagOpts->getFormat()) { case DiagnosticOptions::LFort: OS << ':' << LineNo; break; case DiagnosticOptions::Msvc: OS << '(' << LineNo; break; case DiagnosticOptions::Vi: OS << " +" << LineNo; break; } if (DiagOpts->ShowColumn) // Compute the column number. if (unsigned ColNo = PLoc.getColumn()) { if (DiagOpts->getFormat() == DiagnosticOptions::Msvc) { OS << ','; ColNo--; } else OS << ':'; OS << ColNo; } switch (DiagOpts->getFormat()) { case DiagnosticOptions::LFort: case DiagnosticOptions::Vi: OS << ':'; break; case DiagnosticOptions::Msvc: OS << ") : "; break; } if (DiagOpts->ShowSourceRanges && !Ranges.empty()) { FileID CaretFileID = SM.getFileID(SM.getExpansionLoc(Loc)); bool PrintedRange = false; for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { // Ignore invalid ranges. if (!RI->isValid()) continue; SourceLocation B = SM.getExpansionLoc(RI->getBegin()); SourceLocation E = SM.getExpansionLoc(RI->getEnd()); // If the End location and the start location are the same and are a // macro location, then the range was something that came from a // macro expansion or _Pragma. If this is an object-like macro, the // best we can do is to highlight the range. If this is a // function-like macro, we'd also like to highlight the arguments. if (B == E && RI->getEnd().isMacroID()) E = SM.getExpansionRange(RI->getEnd()).second; std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B); std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E); // If the start or end of the range is in another file, just discard // it. if (BInfo.first != CaretFileID || EInfo.first != CaretFileID) continue; // Add in the length of the token, so that we cover multi-char // tokens. unsigned TokSize = 0; if (RI->isTokenRange()) TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts); OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':' << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' << SM.getLineNumber(EInfo.first, EInfo.second) << ':' << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize) << '}'; PrintedRange = true; } if (PrintedRange) OS << ':'; } OS << ' '; }
void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { assert(DstExprs.size() == varlist_size() && "Number of destination " "expressions is not the same as " "the preallocated buffer"); std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); }
// // runTargetDesc - Output the target register and register file descriptions. // void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, CodeGenRegBank &RegBank) { EmitSourceFileHeader("Target Register and Register Classes Information", OS); OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n"; OS << "#undef GET_REGINFO_TARGET_DESC\n"; OS << "namespace llvm {\n\n"; // Get access to MCRegisterClass data. OS << "extern const MCRegisterClass " << Target.getName() << "MCRegisterClasses[];\n"; // Start out by emitting each of the register classes. ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); // Collect all registers belonging to any allocatable class. std::set<Record*> AllocatableRegs; // Collect allocatable registers. for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; ArrayRef<Record*> Order = RC.getOrder(); if (RC.Allocatable) AllocatableRegs.insert(Order.begin(), Order.end()); } OS << "namespace { // Register classes...\n"; // Emit the ValueType arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName() + "VTs"; // Emit the register list now. OS << " // " << Name << " Register Class Value Types...\n" << " const MVT::SimpleValueType " << Name << "[] = {\n "; for (unsigned i = 0, e = RC.VTs.size(); i != e; ++i) OS << getEnumName(RC.VTs[i]) << ", "; OS << "MVT::Other\n };\n\n"; } OS << "} // end anonymous namespace\n\n"; // Now that all of the structs have been emitted, emit the instances. if (!RegisterClasses.empty()) { std::map<unsigned, std::set<unsigned> > SuperRegClassMap; OS << "\nstatic const TargetRegisterClass *const " << "NullRegClasses[] = { NULL };\n\n"; unsigned NumSubRegIndices = RegBank.getSubRegIndices().size(); if (NumSubRegIndices) { // Compute the super-register classes for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; for (DenseMap<Record*,Record*>::const_iterator i = RC.SubRegClasses.begin(), e = RC.SubRegClasses.end(); i != e; ++i) { // Find the register class number of i->second for SuperRegClassMap. const CodeGenRegisterClass *RC2 = RegBank.getRegClass(i->second); assert(RC2 && "Invalid register class in SubRegClasses"); SuperRegClassMap[RC2->EnumValue].insert(rc); } } // Emit the super-register classes for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); OS << "// " << Name << " Super-register Classes...\n" << "static const TargetRegisterClass *const " << Name << "SuperRegClasses[] = {\n "; bool Empty = true; std::map<unsigned, std::set<unsigned> >::iterator I = SuperRegClassMap.find(rc); if (I != SuperRegClassMap.end()) { for (std::set<unsigned>::iterator II = I->second.begin(), EE = I->second.end(); II != EE; ++II) { const CodeGenRegisterClass &RC2 = *RegisterClasses[*II]; if (!Empty) OS << ", "; OS << "&" << RC2.getQualifiedName() << "RegClass"; Empty = false; } } OS << (!Empty ? ", " : "") << "NULL"; OS << "\n};\n\n"; } } // Emit the sub-classes array for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); OS << "static const uint32_t " << Name << "SubclassMask[] = {\n "; printBitVectorAsHex(OS, RC.getSubClasses(), 32); OS << "\n};\n\n"; } // Emit NULL terminated super-class lists. for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; ArrayRef<CodeGenRegisterClass*> Supers = RC.getSuperClasses(); // Skip classes without supers. We can reuse NullRegClasses. if (Supers.empty()) continue; OS << "static const TargetRegisterClass *const " << RC.getName() << "Superclasses[] = {\n"; for (unsigned i = 0; i != Supers.size(); ++i) OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n"; OS << " NULL\n};\n\n"; } // Emit methods. for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { const CodeGenRegisterClass &RC = *RegisterClasses[i]; if (!RC.AltOrderSelect.empty()) { OS << "\nstatic inline unsigned " << RC.getName() << "AltOrderSelect(const MachineFunction &MF) {" << RC.AltOrderSelect << "}\n\n" << "static ArrayRef<uint16_t> " << RC.getName() << "GetRawAllocationOrder(const MachineFunction &MF) {\n"; for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) { ArrayRef<Record*> Elems = RC.getOrder(oi); if (!Elems.empty()) { OS << " static const uint16_t AltOrder" << oi << "[] = {"; for (unsigned elem = 0; elem != Elems.size(); ++elem) OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); OS << " };\n"; } } OS << " const MCRegisterClass &MCR = " << Target.getName() << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n" << " const ArrayRef<uint16_t> Order[] = {\n" << " makeArrayRef(MCR.begin(), MCR.getNumRegs()"; for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) if (RC.getOrder(oi).empty()) OS << "),\n ArrayRef<uint16_t>("; else OS << "),\n makeArrayRef(AltOrder" << oi; OS << ")\n };\n const unsigned Select = " << RC.getName() << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() << ");\n return Order[Select];\n}\n"; } } // Now emit the actual value-initialized register class instances. OS << "namespace " << RegisterClasses[0]->Namespace << " { // Register class instances\n"; for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { const CodeGenRegisterClass &RC = *RegisterClasses[i]; OS << " extern const TargetRegisterClass " << RegisterClasses[i]->getName() << "RegClass = {\n " << '&' << Target.getName() << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n " << RC.getName() << "VTs,\n " << RC.getName() << "SubclassMask,\n "; if (RC.getSuperClasses().empty()) OS << "NullRegClasses,\n "; else OS << RC.getName() << "Superclasses,\n "; OS << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null")) << "RegClasses,\n "; if (RC.AltOrderSelect.empty()) OS << "0\n"; else OS << RC.getName() << "GetRawAllocationOrder\n"; OS << " };\n\n"; } OS << "}\n"; } OS << "\nnamespace {\n"; OS << " const TargetRegisterClass* const RegisterClasses[] = {\n"; for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) OS << " &" << RegisterClasses[i]->getQualifiedName() << "RegClass,\n"; OS << " };\n"; OS << "}\n"; // End of anonymous namespace... // Emit extra information about registers. const std::string &TargetName = Target.getName(); OS << "\n static const TargetRegisterInfoDesc " << TargetName << "RegInfoDesc[] = " << "{ // Extra Descriptors\n"; OS << " { 0, 0 },\n"; const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister &Reg = *Regs[i]; OS << " { "; OS << Reg.CostPerUse << ", " << int(AllocatableRegs.count(Reg.TheDef)) << " },\n"; } OS << " };\n"; // End of register descriptors... // Calculate the mapping of subregister+index pairs to physical registers. // This will also create further anonymous indices. unsigned NamedIndices = RegBank.getNumNamedIndices(); // Emit SubRegIndex names, skipping 0 ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); OS << "\n static const char *const " << TargetName << "SubRegIndexTable[] = { \""; for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { OS << SubRegIndices[i]->getName(); if (i+1 != e) OS << "\", \""; } OS << "\" };\n\n"; // Emit names of the anonymous subreg indices. if (SubRegIndices.size() > NamedIndices) { OS << " enum {"; for (unsigned i = NamedIndices, e = SubRegIndices.size(); i != e; ++i) { OS << "\n " << SubRegIndices[i]->getName() << " = " << i+1; if (i+1 != e) OS << ','; } OS << "\n };\n\n"; } OS << "\n"; std::string ClassName = Target.getName() + "GenRegisterInfo"; // Emit composeSubRegIndices OS << "unsigned " << ClassName << "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n" << " switch (IdxA) {\n" << " default:\n return IdxB;\n"; for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { bool Open = false; for (unsigned j = 0; j != e; ++j) { if (CodeGenSubRegIndex *Comp = SubRegIndices[i]->compose(SubRegIndices[j])) { if (!Open) { OS << " case " << SubRegIndices[i]->getQualifiedName() << ": switch(IdxB) {\n default: return IdxB;\n"; Open = true; } OS << " case " << SubRegIndices[j]->getQualifiedName() << ": return " << Comp->getQualifiedName() << ";\n"; } } if (Open) OS << " }\n"; } OS << " }\n}\n\n"; // Emit getSubClassWithSubReg. OS << "const TargetRegisterClass *" << ClassName << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)" " const {\n"; if (SubRegIndices.empty()) { OS << " assert(Idx == 0 && \"Target has no sub-registers\");\n" << " return RC;\n"; } else { // Use the smallest type that can hold a regclass ID with room for a // sentinel. if (RegisterClasses.size() < UINT8_MAX) OS << " static const uint8_t Table["; else if (RegisterClasses.size() < UINT16_MAX) OS << " static const uint16_t Table["; else throw "Too many register classes."; OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n"; for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { const CodeGenRegisterClass &RC = *RegisterClasses[rci]; OS << " {\t// " << RC.getName() << "\n"; for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { CodeGenSubRegIndex *Idx = SubRegIndices[sri]; if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx)) OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName() << " -> " << SRC->getName() << "\n"; else OS << " 0,\t// " << Idx->getName() << "\n"; } OS << " },\n"; } OS << " };\n assert(RC && \"Missing regclass\");\n" << " if (!Idx) return RC;\n --Idx;\n" << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" << " unsigned TV = Table[RC->getID()][Idx];\n" << " return TV ? getRegClass(TV - 1) : 0;\n"; } OS << "}\n\n"; // Emit getMatchingSuperRegClass. OS << "const TargetRegisterClass *" << ClassName << "::getMatchingSuperRegClass(const TargetRegisterClass *A," " const TargetRegisterClass *B, unsigned Idx) const {\n"; if (SubRegIndices.empty()) { OS << " llvm_unreachable(\"Target has no sub-registers\");\n"; } else { // We need to find the largest sub-class of A such that every register has // an Idx sub-register in B. Map (B, Idx) to a bit-vector of // super-register classes that map into B. Then compute the largest common // sub-class with A by taking advantage of the register class ordering, // like getCommonSubClass(). // Bitvector table is NumRCs x NumSubIndexes x BVWords, where BVWords is // the number of 32-bit words required to represent all register classes. const unsigned BVWords = (RegisterClasses.size()+31)/32; BitVector BV(RegisterClasses.size()); OS << " static const uint32_t Table[" << RegisterClasses.size() << "][" << SubRegIndices.size() << "][" << BVWords << "] = {\n"; for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { const CodeGenRegisterClass &RC = *RegisterClasses[rci]; OS << " {\t// " << RC.getName() << "\n"; for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { CodeGenSubRegIndex *Idx = SubRegIndices[sri]; BV.reset(); RC.getSuperRegClasses(Idx, BV); OS << " { "; printBitVectorAsHex(OS, BV, 32); OS << "},\t// " << Idx->getName() << '\n'; } OS << " },\n"; } OS << " };\n assert(A && B && \"Missing regclass\");\n" << " --Idx;\n" << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" << " const uint32_t *TV = Table[B->getID()][Idx];\n" << " const uint32_t *SC = A->getSubClassMask();\n" << " for (unsigned i = 0; i != " << BVWords << "; ++i)\n" << " if (unsigned Common = TV[i] & SC[i])\n" << " return getRegClass(32*i + CountTrailingZeros_32(Common));\n" << " return 0;\n"; } OS << "}\n\n"; // Emit the constructor of the class... OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; OS << "extern const uint16_t " << TargetName << "RegOverlaps[];\n"; OS << "extern const uint16_t " << TargetName << "SubRegsSet[];\n"; OS << "extern const uint16_t " << TargetName << "SuperRegsSet[];\n"; if (SubRegIndices.size() != 0) OS << "extern const uint16_t *get" << TargetName << "SubRegTable();\n"; OS << ClassName << "::\n" << ClassName << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" << " " << TargetName << "SubRegIndexTable) {\n" << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ", RA,\n " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" << " " << TargetName << "RegOverlaps, " << TargetName << "SubRegsSet, " << TargetName << "SuperRegsSet,\n" << " "; if (SubRegIndices.size() != 0) OS << "get" << TargetName << "SubRegTable(), " << SubRegIndices.size() << ");\n\n"; else OS << "NULL, 0);\n\n"; EmitRegMapping(OS, Regs, true); OS << "}\n\n"; // Emit CalleeSavedRegs information. std::vector<Record*> CSRSets = Records.getAllDerivedDefinitions("CalleeSavedRegs"); for (unsigned i = 0, e = CSRSets.size(); i != e; ++i) { Record *CSRSet = CSRSets[i]; const SetTheory::RecVec *Regs = RegBank.getSets().expand(CSRSet); assert(Regs && "Cannot expand CalleeSavedRegs instance"); // Emit the *_SaveList list of callee-saved registers. OS << "static const uint16_t " << CSRSet->getName() << "_SaveList[] = { "; for (unsigned r = 0, re = Regs->size(); r != re; ++r) OS << getQualifiedName((*Regs)[r]) << ", "; OS << "0 };\n"; // Emit the *_RegMask bit mask of call-preserved registers. OS << "static const uint32_t " << CSRSet->getName() << "_RegMask[] = { "; printBitVectorAsHex(OS, RegBank.computeCoveredRegisters(*Regs), 32); OS << "};\n"; } OS << "\n\n"; OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; }