// MinGW specific. void Symbol::replaceKeepingName(Symbol *Other, size_t Size) { StringRef OrigName = getName(); memcpy(this, Other, Size); NameData = OrigName.data(); NameSize = OrigName.size(); }
static CXCodeCompleteResults * clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, unsigned complete_line, unsigned complete_column, ArrayRef<CXUnsavedFile> unsaved_files, unsigned options) { bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments; #ifdef UDP_CODE_COMPLETION_LOGGER #ifdef UDP_CODE_COMPLETION_LOGGER_PORT const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime(); #endif #endif bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr; if (cxtu::isNotUsableTU(TU)) { LOG_BAD_TU(TU); return nullptr; } ASTUnit *AST = cxtu::getASTUnit(TU); if (!AST) return nullptr; CIndexer *CXXIdx = TU->CIdx; if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing)) setThreadBackgroundPriority(); ASTUnit::ConcurrencyCheck Check(*AST); // Perform the remapping of source files. SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles; for (auto &UF : unsaved_files) { std::unique_ptr<llvm::MemoryBuffer> MB = llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename); RemappedFiles.push_back(std::make_pair(UF.Filename, MB.release())); } if (EnableLogging) { // FIXME: Add logging. } // Parse the resulting source file to find code-completion results. AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults( &AST->getFileManager()); Results->Results = nullptr; Results->NumResults = 0; // Create a code-completion consumer to capture the results. CodeCompleteOptions Opts; Opts.IncludeBriefComments = IncludeBriefComments; CaptureCompletionResults Capture(Opts, *Results, &TU); // Perform completion. AST->CodeComplete(complete_filename, complete_line, complete_column, RemappedFiles, (options & CXCodeComplete_IncludeMacros), (options & CXCodeComplete_IncludeCodePatterns), IncludeBriefComments, Capture, CXXIdx->getPCHContainerOperations(), *Results->Diag, Results->LangOpts, *Results->SourceMgr, *Results->FileMgr, Results->Diagnostics, Results->TemporaryBuffers); Results->DiagnosticsWrappers.resize(Results->Diagnostics.size()); // Keep a reference to the allocator used for cached global completions, so // that we can be sure that the memory used by our code completion strings // doesn't get freed due to subsequent reparses (while the code completion // results are still active). Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator(); #ifdef UDP_CODE_COMPLETION_LOGGER #ifdef UDP_CODE_COMPLETION_LOGGER_PORT const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime(); SmallString<256> LogResult; llvm::raw_svector_ostream os(LogResult); // Figure out the language and whether or not it uses PCH. const char *lang = 0; bool usesPCH = false; for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end(); I != E; ++I) { if (*I == 0) continue; if (strcmp(*I, "-x") == 0) { if (I + 1 != E) { lang = *(++I); continue; } } else if (strcmp(*I, "-include") == 0) { if (I+1 != E) { const char *arg = *(++I); SmallString<512> pchName; { llvm::raw_svector_ostream os(pchName); os << arg << ".pth"; } pchName.push_back('\0'); struct stat stat_results; if (stat(pchName.str().c_str(), &stat_results) == 0) usesPCH = true; continue; } } } os << "{ "; os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime()); os << ", \"numRes\": " << Results->NumResults; os << ", \"diags\": " << Results->Diagnostics.size(); os << ", \"pch\": " << (usesPCH ? "true" : "false"); os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"'; const char *name = getlogin(); os << ", \"user\": \"" << (name ? name : "unknown") << '"'; os << ", \"clangVer\": \"" << getClangFullVersion() << '"'; os << " }"; StringRef res = os.str(); if (res.size() > 0) { do { // Setup the UDP socket. struct sockaddr_in servaddr; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT); if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER, &servaddr.sin_addr) <= 0) break; int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) break; sendto(sockfd, res.data(), res.size(), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); close(sockfd); } while (false); } #endif #endif return Results; }
static void create_PRUNTIME_FUNCTION(uint8_t *Code, size_t Size, StringRef fnname, uint8_t *Section, size_t Allocated, uint8_t *UnwindData) { DWORD mod_size = 0; #if defined(_CPU_X86_64_) #if !defined(USE_MCJIT) uint8_t *catchjmp = Section+Allocated; UnwindData = (uint8_t*)(((uintptr_t)catchjmp+12+3)&~(uintptr_t)3); if (!catchjmp[0]) { catchjmp[0] = 0x48; catchjmp[1] = 0xb8; // mov RAX, QWORD PTR [...] *(uint64_t*)(&catchjmp[2]) = (uint64_t)&_seh_exception_handler; catchjmp[10] = 0xff; catchjmp[11] = 0xe0; // jmp RAX UnwindData[0] = 0x09; // version info, UNW_FLAG_EHANDLER UnwindData[1] = 4; // size of prolog (bytes) UnwindData[2] = 2; // count of unwind codes (slots) UnwindData[3] = 0x05; // frame register (rbp) = rsp UnwindData[4] = 4; // second instruction UnwindData[5] = 0x03; // mov RBP, RSP UnwindData[6] = 1; // first instruction UnwindData[7] = 0x50; // push RBP *(DWORD*)&UnwindData[8] = (DWORD)(catchjmp - Section); // relative location of catchjmp mod_size = (DWORD)Allocated+48; } PRUNTIME_FUNCTION tbl = (PRUNTIME_FUNCTION)(UnwindData+12); #else PRUNTIME_FUNCTION tbl = (PRUNTIME_FUNCTION)malloc(sizeof(RUNTIME_FUNCTION)); #endif tbl->BeginAddress = (DWORD)(Code - Section); tbl->EndAddress = (DWORD)(Code - Section + Size); tbl->UnwindData = (DWORD)(UnwindData - Section); #else // defined(_CPU_X86_64_) Section += (uintptr_t)Code; mod_size = Size; #endif if (0) { assert(!jl_in_stackwalk); jl_in_stackwalk = 1; if (mod_size && !SymLoadModuleEx(GetCurrentProcess(), NULL, NULL, NULL, (DWORD64)Section, mod_size, NULL, SLMFLAG_VIRTUAL)) { #if defined(_CPU_X86_64_) && !defined(USE_MCJIT) catchjmp[0] = 0; #endif static int warned = 0; if (!warned) { jl_printf(JL_STDERR, "WARNING: failed to insert module info for backtrace: %lu\n", GetLastError()); warned = 1; } } else { size_t len = fnname.size()+1; if (len > MAX_SYM_NAME) len = MAX_SYM_NAME; char *name = (char*)alloca(len); memcpy(name, fnname.data(), len-1); name[len-1] = 0; if (!SymAddSymbol(GetCurrentProcess(), (ULONG64)Section, name, (DWORD64)Code, (DWORD)Size, 0)) { jl_printf(JL_STDERR, "WARNING: failed to insert function name %s into debug info: %lu\n", name, GetLastError()); } } jl_in_stackwalk = 0; } #if defined(_CPU_X86_64_) if (!RtlAddFunctionTable(tbl, 1, (DWORD64)Section)) { static int warned = 0; if (!warned) { jl_printf(JL_STDERR, "WARNING: failed to insert function stack unwind info: %lu\n", GetLastError()); warned = 1; } } #endif }
void Output::output(StringRef s) { Column += s.size(); Out << s; }
/// ApplyQAOverride - Apply a list of edits to the input argument lists. /// /// The input string is a space separate list of edits to perform, /// they are applied in order to the input argument lists. Edits /// should be one of the following forms: /// /// '#': Silence information about the changes to the command line arguments. /// /// '^': Add FOO as a new argument at the beginning of the command line. /// /// '+': Add FOO as a new argument at the end of the command line. /// /// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command /// line. /// /// 'xOPTION': Removes all instances of the literal argument OPTION. /// /// 'XOPTION': Removes all instances of the literal argument OPTION, /// and the following argument. /// /// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox' /// at the end of the command line. /// /// \param OS - The stream to write edit information to. /// \param Args - The vector of command line arguments. /// \param Edit - The override command to perform. /// \param SavedStrings - Set to use for storing string representations. static void ApplyOneQAOverride(raw_ostream &OS, SmallVectorImpl<const char*> &Args, StringRef Edit, std::set<std::string> &SavedStrings) { // This does not need to be efficient. if (Edit[0] == '^') { const char *Str = SaveStringInSet(SavedStrings, Edit.substr(1)); OS << "### Adding argument " << Str << " at beginning\n"; Args.insert(Args.begin() + 1, Str); } else if (Edit[0] == '+') { const char *Str = SaveStringInSet(SavedStrings, Edit.substr(1)); OS << "### Adding argument " << Str << " at end\n"; Args.push_back(Str); } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") && Edit.slice(2, Edit.size()-1).find('/') != StringRef::npos) { StringRef MatchPattern = Edit.substr(2).split('/').first; StringRef ReplPattern = Edit.substr(2).split('/').second; ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1); for (unsigned i = 1, e = Args.size(); i != e; ++i) { std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); if (Repl != Args[i]) { OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n"; Args[i] = SaveStringInSet(SavedStrings, Repl); } } } else if (Edit[0] == 'x' || Edit[0] == 'X') { std::string Option = Edit.substr(1, std::string::npos); for (unsigned i = 1; i < Args.size();) { if (Option == Args[i]) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); if (Edit[0] == 'X') { if (i < Args.size()) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); } else OS << "### Invalid X edit, end of command line!\n"; } } else ++i; } } else if (Edit[0] == 'O') { for (unsigned i = 1; i < Args.size();) { const char *A = Args[i]; if (A[0] == '-' && A[1] == 'O' && (A[2] == '\0' || (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || ('0' <= A[2] && A[2] <= '9'))))) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); } else ++i; } OS << "### Adding argument " << Edit << " at end\n"; Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit.str())); } else { OS << "### Unrecognized edit: " << Edit << "\n"; } }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, const MCTargetOptions &MCOptions, const MDNode *LocMDNode, InlineAsm::AsmDialect Dialect) const { assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer does not have mature MC support or the integrated // assembler has been disabled, just emit the blob textually. // Otherwise parse the asm and emit it via MC support. // This is useful in case the asm parser doesn't handle something but the // system assembler does. const MCAsmInfo *MCAI = TM.getMCAsmInfo(); assert(MCAI && "No MCAsmInfo"); if (!MCAI->useIntegratedAssembler() && !OutStreamer->isIntegratedAssemblerRequired()) { emitInlineAsmStart(); OutStreamer->EmitRawText(Str); emitInlineAsmEnd(STI, nullptr); return; } if (!DiagInfo) { DiagInfo = make_unique<SrcMgrDiagInfo>(); MCContext &Context = MMI->getContext(); Context.setInlineSourceManager(&DiagInfo->SrcMgr); LLVMContext &LLVMCtx = MMI->getModule()->getContext(); if (LLVMCtx.getInlineAsmDiagnosticHandler()) { DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get()); } } SourceMgr &SrcMgr = DiagInfo->SrcMgr; SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths); std::unique_ptr<MemoryBuffer> Buffer; // The inline asm source manager will outlive Str, so make a copy of the // string for SourceMgr to own. Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); // Store LocMDNode in DiagInfo, using BufNum as an identifier. if (LocMDNode) { DiagInfo->LocInfos.resize(BufNum); DiagInfo->LocInfos[BufNum-1] = LocMDNode; } std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); // We create a new MCInstrInfo here since we might be at the module level // and not have a MachineFunction to initialize the TargetInstrInfo from and // we only need MCInstrInfo for asm parsing. We create one unconditionally // because it's not subtarget dependent. std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo()); std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser( STI, *Parser, *MII, MCOptions)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); if (Dialect == InlineAsm::AD_Intel) // We need this flag to be able to parse numbers like "0bH" Parser->setParsingInlineAsm(true); if (MF) { const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); TAP->SetFrameRegister(TRI->getFrameRegister(*MF)); } emitInlineAsmStart(); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); emitInlineAsmEnd(STI, &TAP->getSTI()); if (Res && !DiagInfo->DiagHandler) report_fatal_error("Error parsing inline asm\n"); }
Function* Decompiler::decompileFunction(unsigned Address) { // Check that Address is inside the current section. // TODO: Find a better way to do this check. What we really care about is // avoiding reads to library calls and areas of memory we can't "see". const object::SectionRef Sect = Dis->getCurrentSection(); uint64_t SectStart, SectEnd; Sect.getAddress(SectStart); Sect.getSize(SectEnd); SectEnd += SectStart; if (Address < SectStart || Address > SectEnd) { errs() << "Address out of bounds for section (is this a library call?): " << format("%1" PRIx64, Address) << "\n"; return NULL; } MachineFunction *MF = Dis->disassemble(Address); // Get Function Name // TODO: Determine Function Type FunctionType *FType = FunctionType::get(Type::getPrimitiveType(*Context, Type::VoidTyID), false); Function *F = cast<Function>(Mod->getOrInsertFunction(MF->getName(), FType)); if (!F->empty()) { return F; } // Create a basic block to hold entry point (alloca) information BasicBlock *entry = getOrCreateBasicBlock("entry", F); // For each basic block MachineFunction::iterator BI = MF->begin(), BE = MF->end(); while (BI != BE) { // Add branch from "entry" if (BI == MF->begin()) { entry->getInstList().push_back( BranchInst::Create(getOrCreateBasicBlock(BI->getName(), F))); } else { getOrCreateBasicBlock(BI->getName(), F); } ++BI; } BI = MF->begin(); while (BI != BE) { if (decompileBasicBlock(BI, F) == NULL) { printError("Unable to decompile basic block!"); } ++BI; } // During Decompilation, did any "in-between" basic blocks get created? // Nothing ever splits the entry block, so we skip it. for (Function::iterator I = ++F->begin(), E = F->end(); I != E; ++I) { if (!(I->empty())) { continue; } // Right now, the only way to get the right offset is to parse its name // it sucks, but it works. StringRef Name = I->getName(); if (Name == "end" || Name == "entry") continue; // these can be empty size_t Off = F->getName().size() + 1; size_t Size = Name.size() - Off; StringRef BBAddrStr = Name.substr(Off, Size); unsigned long long BBAddr; getAsUnsignedInteger(BBAddrStr, 10, BBAddr); BBAddr += Address; DEBUG(errs() << "Split Target: " << Name << "\t Address: " << BBAddr << "\n"); // split Block at AddrStr Function::iterator SB; // Split basic block BasicBlock::iterator SI, SE; // Split instruction // Note the ++, nothing ever splits the entry block. for (SB = ++F->begin(); SB != E; ++SB) { DEBUG(outs() << "SB: " << SB->getName() << "\tRange: " << Dis->getDebugOffset(SB->begin()->getDebugLoc()) << " " << Dis->getDebugOffset(SB->getTerminator()->getDebugLoc()) << "\n"); if (SB->empty() || BBAddr < getBasicBlockAddress(SB) || BBAddr > Dis->getDebugOffset(SB->getTerminator()->getDebugLoc())) { continue; } // Reorder instructions based on Debug Location sortBasicBlock(SB); DEBUG(errs() << "Found Split Block: " << SB->getName() << "\n"); // Find iterator to split on. for (SI = SB->begin(), SE = SB->end(); SI != SE; ++SI) { // outs() << "SI: " << SI->getDebugLoc().getLine() << "\n"; if (Dis->getDebugOffset(SI->getDebugLoc()) == BBAddr) break; if (Dis->getDebugOffset(SI->getDebugLoc()) > BBAddr) { errs() << "Could not find address inside basic block!\n" << "SI: " << Dis->getDebugOffset(SI->getDebugLoc()) << "\n" << "BBAddr: " << BBAddr << "\n"; break; } } break; } if (!SB || SI == SE || SB == E) { errs() << "Decompiler: Failed to find instruction offset in function!\n"; continue; } // outs() << SB->getName() << " " << SI->getName() << "\n"; // outs() << "Creating Block..."; splitBasicBlockIntoBlock(SB, SI, I); } // Clean up unnecessary stores and loads FunctionPassManager FPM(Mod); // FPM.add(createPromoteMemoryToRegisterPass()); // See Scalar.h for more. FPM.add(createTypeRecoveryPass()); FPM.run(*F); return F; }
/// ReadCheckFile - Read the check file, which specifies the sequence of /// expected strings. The strings are added to the CheckStrings vector. static bool ReadCheckFile(SourceMgr &SM, std::vector<CheckString> &CheckStrings) { // Open the check file, and tell SourceMgr about it. OwningPtr<MemoryBuffer> File; if (error_code ec = MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), File)) { errs() << "Could not open check file '" << CheckFilename << "': " << ec.message() << '\n'; return true; } MemoryBuffer *F = File.take(); // If we want to canonicalize whitespace, strip excess whitespace from the // buffer containing the CHECK lines. if (!NoCanonicalizeWhiteSpace) F = CanonicalizeInputFile(F); SM.AddNewSourceBuffer(F, SMLoc()); // Find all instances of CheckPrefix followed by : in the file. StringRef Buffer = F->getBuffer(); std::vector<std::pair<SMLoc, Pattern> > NotMatches; while (1) { // See if Prefix occurs in the memory buffer. Buffer = Buffer.substr(Buffer.find(CheckPrefix)); // If we didn't find a match, we're done. if (Buffer.empty()) break; const char *CheckPrefixStart = Buffer.data(); // When we find a check prefix, keep track of whether we find CHECK: or // CHECK-NEXT: bool IsCheckNext = false, IsCheckNot = false; // Verify that the : is present after the prefix. if (Buffer[CheckPrefix.size()] == ':') { Buffer = Buffer.substr(CheckPrefix.size()+1); } else if (Buffer.size() > CheckPrefix.size()+6 && memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) { Buffer = Buffer.substr(CheckPrefix.size()+7); IsCheckNext = true; } else if (Buffer.size() > CheckPrefix.size()+5 && memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) { Buffer = Buffer.substr(CheckPrefix.size()+6); IsCheckNot = true; } else { Buffer = Buffer.substr(1); continue; } // Okay, we found the prefix, yay. Remember the rest of the line, but // ignore leading and trailing whitespace. Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); // Scan ahead to the end of line. size_t EOL = Buffer.find_first_of("\n\r"); // Remember the location of the start of the pattern, for diagnostics. SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); // Parse the pattern. Pattern P; if (P.ParsePattern(Buffer.substr(0, EOL), SM)) return true; Buffer = Buffer.substr(EOL); // Verify that CHECK-NEXT lines have at least one CHECK line before them. if (IsCheckNext && CheckStrings.empty()) { SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart), "found '"+CheckPrefix+"-NEXT:' without previous '"+ CheckPrefix+ ": line", "error"); return true; } // Handle CHECK-NOT. if (IsCheckNot) { NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()), P)); continue; } // Okay, add the string we captured to the output vector and move on. CheckStrings.push_back(CheckString(P, PatternLoc, IsCheckNext)); std::swap(NotMatches, CheckStrings.back().NotStrings); } // Add an EOF pattern for any trailing CHECK-NOTs. if (!NotMatches.empty()) { CheckStrings.push_back(CheckString(Pattern(true), SMLoc::getFromPointer(Buffer.data()), false)); std::swap(NotMatches, CheckStrings.back().NotStrings); } if (CheckStrings.empty()) { errs() << "error: no check strings found with prefix '" << CheckPrefix << ":'\n"; return true; } return false; }
SourceCompleteResult ide::isSourceInputComplete(std::unique_ptr<llvm::MemoryBuffer> MemBuf) { SourceManager SM; auto BufferID = SM.addNewSourceBuffer(std::move(MemBuf)); ParserUnit Parse(SM, BufferID); Parser &P = Parse.getParser(); bool Done; do { P.parseTopLevel(); Done = P.Tok.is(tok::eof); } while (!Done); SourceCompleteResult SCR; SCR.IsComplete = !P.isInputIncomplete(); // Use the same code that was in the REPL code to track the indent level // for now. In the future we should get this from the Parser if possible. CharSourceRange entireRange = SM.getRangeForBuffer(BufferID); StringRef Buffer = SM.extractText(entireRange); const char *SourceStart = Buffer.data(); const char *SourceEnd = Buffer.data() + Buffer.size(); const char *LineStart = SourceStart; const char *LineSourceStart = nullptr; uint32_t LineIndent = 0; struct IndentInfo { StringRef Prefix; uint32_t Indent; IndentInfo(const char *s, size_t n, uint32_t i) : Prefix(s, n), Indent(i) {} }; SmallVector<IndentInfo, 4> IndentInfos; for (const char *p = SourceStart; p<SourceEnd; ++p) { switch (*p) { case '\r': case '\n': LineIndent = 0; LineSourceStart = nullptr; LineStart = p + 1; break; case '"': p = skipStringInCode (p, SourceEnd); break; case '{': case '(': case '[': ++LineIndent; if (LineSourceStart == nullptr) IndentInfos.push_back(IndentInfo(LineStart, p - LineStart, LineIndent)); else IndentInfos.push_back(IndentInfo(LineStart, LineSourceStart - LineStart, LineIndent)); break; case '}': case ')': case ']': if (LineIndent > 0) --LineIndent; if (!IndentInfos.empty()) IndentInfos.pop_back(); break; default: if (LineSourceStart == nullptr && !isspace(*p)) LineSourceStart = p; break; } if (*p == '\0') break; } if (!IndentInfos.empty()) { SCR.IndentPrefix = IndentInfos.back().Prefix.str(); // Trim off anything that follows a non-space character const size_t pos = SCR.IndentPrefix.find_first_not_of(" \t"); if (pos != std::string::npos) SCR.IndentPrefix.erase(pos); SCR.IndentLevel = IndentInfos.back().Indent; } return SCR; }
/// Match - Match the pattern string against the input buffer Buffer. This /// returns the position that is matched or npos if there is no match. If /// there is a match, the size of the matched string is returned in MatchLen. size_t Pattern::Match(StringRef Buffer, size_t &MatchLen, StringMap<StringRef> &VariableTable) const { // If this is the EOF pattern, match it immediately. if (MatchEOF) { MatchLen = 0; return Buffer.size(); } // If this is a fixed string pattern, just match it now. if (!FixedStr.empty()) { MatchLen = FixedStr.size(); return Buffer.find(FixedStr); } // Regex match. // If there are variable uses, we need to create a temporary string with the // actual value. StringRef RegExToMatch = RegExStr; std::string TmpStr; if (!VariableUses.empty()) { TmpStr = RegExStr; unsigned InsertOffset = 0; for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) { StringMap<StringRef>::iterator it = VariableTable.find(VariableUses[i].first); // If the variable is undefined, return an error. if (it == VariableTable.end()) return StringRef::npos; // Look up the value and escape it so that we can plop it into the regex. std::string Value; AddFixedStringToRegEx(it->second, Value); // Plop it into the regex at the adjusted offset. TmpStr.insert(TmpStr.begin()+VariableUses[i].second+InsertOffset, Value.begin(), Value.end()); InsertOffset += Value.size(); } // Match the newly constructed regex. RegExToMatch = TmpStr; } SmallVector<StringRef, 4> MatchInfo; if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo)) return StringRef::npos; // Successful regex match. assert(!MatchInfo.empty() && "Didn't get any match"); StringRef FullMatch = MatchInfo[0]; // If this defines any variables, remember their values. for (unsigned i = 0, e = VariableDefs.size(); i != e; ++i) { assert(VariableDefs[i].second < MatchInfo.size() && "Internal paren error"); VariableTable[VariableDefs[i].first] = MatchInfo[VariableDefs[i].second]; } MatchLen = FullMatch.size(); return FullMatch.data()-Buffer.data(); }
void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, const StringMap<StringRef> &VariableTable) const{ // If this was a regular expression using variables, print the current // variable values. if (!VariableUses.empty()) { for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) { StringRef Var = VariableUses[i].first; StringMap<StringRef>::const_iterator it = VariableTable.find(Var); SmallString<256> Msg; raw_svector_ostream OS(Msg); // Check for undefined variable references. if (it == VariableTable.end()) { OS << "uses undefined variable \""; OS.write_escaped(Var) << "\"";; } else { OS << "with variable \""; OS.write_escaped(Var) << "\" equal to \""; OS.write_escaped(it->second) << "\""; } SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), OS.str(), "note", /*ShowLine=*/false); } } // Attempt to find the closest/best fuzzy match. Usually an error happens // because some string in the output didn't exactly match. In these cases, we // would like to show the user a best guess at what "should have" matched, to // save them having to actually check the input manually. size_t NumLinesForward = 0; size_t Best = StringRef::npos; double BestQuality = 0; // Use an arbitrary 4k limit on how far we will search. for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) { if (Buffer[i] == '\n') ++NumLinesForward; // Patterns have leading whitespace stripped, so skip whitespace when // looking for something which looks like a pattern. if (Buffer[i] == ' ' || Buffer[i] == '\t') continue; // Compute the "quality" of this match as an arbitrary combination of the // match distance and the number of lines skipped to get to this match. unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable); double Quality = Distance + (NumLinesForward / 100.); if (Quality < BestQuality || Best == StringRef::npos) { Best = i; BestQuality = Quality; } } // Print the "possible intended match here" line if we found something // reasonable and not equal to what we showed in the "scanning from here" // line. if (Best && Best != StringRef::npos && BestQuality < 50) { SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best), "possible intended match here", "note"); // FIXME: If we wanted to be really friendly we would show why the match // failed, as it can be hard to spot simple one character differences. } }
bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) { PatternLoc = SMLoc::getFromPointer(PatternStr.data()); // Ignore trailing whitespace. while (!PatternStr.empty() && (PatternStr.back() == ' ' || PatternStr.back() == '\t')) PatternStr = PatternStr.substr(0, PatternStr.size()-1); // Check that there is something on the line. if (PatternStr.empty()) { SM.PrintMessage(PatternLoc, "found empty check string with prefix '" + CheckPrefix+":'", "error"); return true; } // Check to see if this is a fixed string, or if it has regex pieces. if (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos && PatternStr.find("[[") == StringRef::npos)) { FixedStr = PatternStr; return false; } // Paren value #0 is for the fully matched string. Any new parenthesized // values add from their. unsigned CurParen = 1; // Otherwise, there is at least one regex piece. Build up the regex pattern // by escaping scary characters in fixed strings, building up one big regex. while (!PatternStr.empty()) { // RegEx matches. if (PatternStr.size() >= 2 && PatternStr[0] == '{' && PatternStr[1] == '{') { // Otherwise, this is the start of a regex match. Scan for the }}. size_t End = PatternStr.find("}}"); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), "found start of regex string with no end '}}'", "error"); return true; } if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM)) return true; PatternStr = PatternStr.substr(End+2); continue; } // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .* // (or some other regex) and assigns it to the FileCheck variable 'foo'. The // second form is [[foo]] which is a reference to foo. The variable name // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject // it. This is to catch some common errors. if (PatternStr.size() >= 2 && PatternStr[0] == '[' && PatternStr[1] == '[') { // Verify that it is terminated properly. size_t End = PatternStr.find("]]"); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), "invalid named regex reference, no ]] found", "error"); return true; } StringRef MatchStr = PatternStr.substr(2, End-2); PatternStr = PatternStr.substr(End+2); // Get the regex name (e.g. "foo"). size_t NameEnd = MatchStr.find(':'); StringRef Name = MatchStr.substr(0, NameEnd); if (Name.empty()) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), "invalid name in named regex: empty name", "error"); return true; } // Verify that the name is well formed. for (unsigned i = 0, e = Name.size(); i != e; ++i) if (Name[i] != '_' && (Name[i] < 'a' || Name[i] > 'z') && (Name[i] < 'A' || Name[i] > 'Z') && (Name[i] < '0' || Name[i] > '9')) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i), "invalid name in named regex", "error"); return true; } // Name can't start with a digit. if (isdigit(Name[0])) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), "invalid name in named regex", "error"); return true; } // Handle [[foo]]. if (NameEnd == StringRef::npos) { VariableUses.push_back(std::make_pair(Name, RegExStr.size())); continue; } // Handle [[foo:.*]]. VariableDefs.push_back(std::make_pair(Name, CurParen)); RegExStr += '('; ++CurParen; if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM)) return true; RegExStr += ')'; } // Handle fixed string matches. // Find the end, which is the start of the next regex. size_t FixedMatchEnd = PatternStr.find("{{"); FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr); PatternStr = PatternStr.substr(FixedMatchEnd); continue; } return false; }
/// Interpreting the given string using the normal CamelCase /// conventions, determine whether the given string starts with the /// given "word", which is assumed to end in a lowercase letter. static bool startsWithWord(StringRef name, StringRef word) { if (name.size() < word.size()) return false; return ((name.size() == word.size() || !isLowercase(name[word.size()])) && name.startswith(word)); }
bool Punycode::decodePunycode(StringRef InputPunycode, std::vector<uint32_t> &OutCodePoints) { OutCodePoints.clear(); OutCodePoints.reserve(InputPunycode.size()); // -- Build the decoded string as UTF32 first because we need random access. uint32_t n = initial_n; int i = 0; int bias = initial_bias; /// let output = an empty string indexed from 0 // consume all code points before the last delimiter (if there is one) // and copy them to output, size_t lastDelimiter = InputPunycode.find_last_of(delimiter); if (lastDelimiter != StringRef::npos) { for (char c : InputPunycode.slice(0, lastDelimiter)) { // fail on any non-basic code point if (static_cast<unsigned char>(c) > 0x7f) return true; OutCodePoints.push_back(c); } // if more than zero code points were consumed then consume one more // (which will be the last delimiter) InputPunycode = InputPunycode.slice(lastDelimiter + 1, InputPunycode.size()); } while (!InputPunycode.empty()) { int oldi = i; int w = 1; for (int k = base; ; k += base) { // consume a code point, or fail if there was none to consume if (InputPunycode.empty()) return true; char codePoint = InputPunycode.front(); InputPunycode = InputPunycode.slice(1, InputPunycode.size()); // let digit = the code point's digit-value, fail if it has none int digit = digit_index(codePoint); if (digit < 0) return true; i = i + digit * w; int t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias; if (digit < t) break; w = w * (base - t); } bias = adapt(i - oldi, OutCodePoints.size() + 1, oldi == 0); n = n + i / (OutCodePoints.size() + 1); i = i % (OutCodePoints.size() + 1); // if n is a basic code point then fail if (n < 0x80) return true; // insert n into output at position i OutCodePoints.insert(OutCodePoints.begin() + i, n); i++; } return true; }
void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) { auto TL = *Result.Nodes.getNodeAs<TypeLoc>("tl"); SourceLocation Loc = TL.getBeginLoc(); if (Loc.isInvalid() || Loc.isMacroID()) return; // Look through qualification. if (auto QualLoc = TL.getAs<QualifiedTypeLoc>()) TL = QualLoc.getUnqualifiedLoc(); auto BuiltinLoc = TL.getAs<BuiltinTypeLoc>(); if (!BuiltinLoc) return; Token Tok = getTokenAtLoc(Loc, Result, *IdentTable); // Ensure the location actually points to one of the builting integral type // names we're interested in. Otherwise, we might be getting this match from // implicit code (e.g. an implicit assignment operator of a class containing // an array of non-POD types). if (!Tok.isOneOf(tok::kw_short, tok::kw_long, tok::kw_unsigned, tok::kw_signed)) return; bool IsSigned; unsigned Width; const TargetInfo &TargetInfo = Result.Context->getTargetInfo(); // Look for uses of short, long, long long and their unsigned versions. switch (BuiltinLoc.getTypePtr()->getKind()) { case BuiltinType::Short: Width = TargetInfo.getShortWidth(); IsSigned = true; break; case BuiltinType::Long: Width = TargetInfo.getLongWidth(); IsSigned = true; break; case BuiltinType::LongLong: Width = TargetInfo.getLongLongWidth(); IsSigned = true; break; case BuiltinType::UShort: Width = TargetInfo.getShortWidth(); IsSigned = false; break; case BuiltinType::ULong: Width = TargetInfo.getLongWidth(); IsSigned = false; break; case BuiltinType::ULongLong: Width = TargetInfo.getLongLongWidth(); IsSigned = false; break; default: return; } // We allow "unsigned short port" as that's reasonably common and required by // the sockets API. const StringRef Port = "unsigned short port"; const char *Data = Result.SourceManager->getCharacterData(Loc); if (!std::strncmp(Data, Port.data(), Port.size()) && !isIdentifierBody(Data[Port.size()])) return; std::string Replacement = ((IsSigned ? SignedTypePrefix : UnsignedTypePrefix) + Twine(Width) + TypeSuffix) .str(); // We don't add a fix-it as changing the type can easily break code, // e.g. when a function requires a 'long' argument on all platforms. // QualTypes are printed with implicit quotes. diag(Loc, "consider replacing %0 with '%1'") << BuiltinLoc.getType() << Replacement; }
/// Mangle this entity as a std::string. std::string LinkEntity::mangleAsString() const { IRGenMangler mangler; switch (getKind()) { case Kind::DispatchThunk: { auto *func = cast<FuncDecl>(getDecl()); return mangler.mangleDispatchThunk(func); } case Kind::DispatchThunkInitializer: { auto *ctor = cast<ConstructorDecl>(getDecl()); return mangler.mangleConstructorDispatchThunk(ctor, /*isAllocating=*/false); } case Kind::DispatchThunkAllocator: { auto *ctor = cast<ConstructorDecl>(getDecl()); return mangler.mangleConstructorDispatchThunk(ctor, /*isAllocating=*/true); } case Kind::MethodDescriptor: { auto *func = cast<FuncDecl>(getDecl()); return mangler.mangleMethodDescriptor(func); } case Kind::MethodDescriptorInitializer: { auto *ctor = cast<ConstructorDecl>(getDecl()); return mangler.mangleConstructorMethodDescriptor(ctor, /*isAllocating=*/false); } case Kind::MethodDescriptorAllocator: { auto *ctor = cast<ConstructorDecl>(getDecl()); return mangler.mangleConstructorMethodDescriptor(ctor, /*isAllocating=*/true); } case Kind::MethodLookupFunction: { auto *classDecl = cast<ClassDecl>(getDecl()); return mangler.mangleMethodLookupFunction(classDecl); } case Kind::ValueWitness: return mangler.mangleValueWitness(getType(), getValueWitness()); case Kind::ValueWitnessTable: return mangler.mangleValueWitnessTable(getType()); case Kind::TypeMetadataAccessFunction: return mangler.mangleTypeMetadataAccessFunction(getType()); case Kind::TypeMetadataLazyCacheVariable: return mangler.mangleTypeMetadataLazyCacheVariable(getType()); case Kind::TypeMetadataInstantiationCache: return mangler.mangleTypeMetadataInstantiationCache( cast<NominalTypeDecl>(getDecl())); case Kind::TypeMetadataInstantiationFunction: return mangler.mangleTypeMetadataInstantiationFunction( cast<NominalTypeDecl>(getDecl())); case Kind::TypeMetadataSingletonInitializationCache: return mangler.mangleTypeMetadataSingletonInitializationCache( cast<NominalTypeDecl>(getDecl())); case Kind::TypeMetadataCompletionFunction: return mangler.mangleTypeMetadataCompletionFunction( cast<NominalTypeDecl>(getDecl())); case Kind::TypeMetadata: switch (getMetadataAddress()) { case TypeMetadataAddress::FullMetadata: return mangler.mangleTypeFullMetadataFull(getType()); case TypeMetadataAddress::AddressPoint: return mangler.mangleTypeMetadataFull(getType()); } llvm_unreachable("invalid metadata address"); case Kind::TypeMetadataPattern: return mangler.mangleTypeMetadataPattern( cast<NominalTypeDecl>(getDecl())); case Kind::SwiftMetaclassStub: return mangler.mangleClassMetaClass(cast<ClassDecl>(getDecl())); case Kind::ObjCMetadataUpdateFunction: return mangler.mangleObjCMetadataUpdateFunction(cast<ClassDecl>(getDecl())); case Kind::ObjCResilientClassStub: switch (getMetadataAddress()) { case TypeMetadataAddress::FullMetadata: return mangler.mangleFullObjCResilientClassStub(cast<ClassDecl>(getDecl())); case TypeMetadataAddress::AddressPoint: return mangler.mangleObjCResilientClassStub(cast<ClassDecl>(getDecl())); } llvm_unreachable("invalid metadata address"); case Kind::ClassMetadataBaseOffset: // class metadata base offset return mangler.mangleClassMetadataBaseOffset(cast<ClassDecl>(getDecl())); case Kind::NominalTypeDescriptor: return mangler.mangleNominalTypeDescriptor( cast<NominalTypeDecl>(getDecl())); case Kind::OpaqueTypeDescriptor: return mangler.mangleOpaqueTypeDescriptor(cast<OpaqueTypeDecl>(getDecl())); case Kind::OpaqueTypeDescriptorAccessor: return mangler.mangleOpaqueTypeDescriptorAccessor( cast<OpaqueTypeDecl>(getDecl())); case Kind::OpaqueTypeDescriptorAccessorImpl: return mangler.mangleOpaqueTypeDescriptorAccessorImpl( cast<OpaqueTypeDecl>(getDecl())); case Kind::OpaqueTypeDescriptorAccessorKey: return mangler.mangleOpaqueTypeDescriptorAccessorKey( cast<OpaqueTypeDecl>(getDecl())); case Kind::OpaqueTypeDescriptorAccessorVar: return mangler.mangleOpaqueTypeDescriptorAccessorVar( cast<OpaqueTypeDecl>(getDecl())); case Kind::PropertyDescriptor: return mangler.manglePropertyDescriptor( cast<AbstractStorageDecl>(getDecl())); case Kind::ModuleDescriptor: return mangler.mangleModuleDescriptor(cast<ModuleDecl>(getDecl())); case Kind::ExtensionDescriptor: return mangler.mangleExtensionDescriptor(getExtension()); case Kind::AnonymousDescriptor: return mangler.mangleAnonymousDescriptor(getAnonymousDeclContext()); case Kind::ProtocolDescriptor: return mangler.mangleProtocolDescriptor(cast<ProtocolDecl>(getDecl())); case Kind::ProtocolRequirementsBaseDescriptor: return mangler.mangleProtocolRequirementsBaseDescriptor( cast<ProtocolDecl>(getDecl())); case Kind::AssociatedTypeDescriptor: return mangler.mangleAssociatedTypeDescriptor( cast<AssociatedTypeDecl>(getDecl())); case Kind::AssociatedConformanceDescriptor: { auto assocConformance = getAssociatedConformance(); return mangler.mangleAssociatedConformanceDescriptor( cast<ProtocolDecl>(getDecl()), assocConformance.first, assocConformance.second); } case Kind::BaseConformanceDescriptor: { auto assocConformance = getAssociatedConformance(); return mangler.mangleBaseConformanceDescriptor( cast<ProtocolDecl>(getDecl()), assocConformance.second); } case Kind::DefaultAssociatedConformanceAccessor: { auto assocConformance = getAssociatedConformance(); return mangler.mangleDefaultAssociatedConformanceAccessor( cast<ProtocolDecl>(getDecl()), assocConformance.first, assocConformance.second); } case Kind::ProtocolConformanceDescriptor: return mangler.mangleProtocolConformanceDescriptor( getRootProtocolConformance()); case Kind::EnumCase: return mangler.mangleEnumCase(getDecl()); case Kind::FieldOffset: return mangler.mangleFieldOffset(getDecl()); case Kind::ProtocolWitnessTable: return mangler.mangleWitnessTable(getRootProtocolConformance()); case Kind::GenericProtocolWitnessTableInstantiationFunction: return mangler.mangleGenericProtocolWitnessTableInstantiationFunction( getProtocolConformance()); case Kind::ProtocolWitnessTablePattern: return mangler.mangleProtocolWitnessTablePattern(getProtocolConformance()); case Kind::ProtocolWitnessTableLazyAccessFunction: return mangler.mangleProtocolWitnessTableLazyAccessFunction(getType(), getProtocolConformance()); case Kind::ProtocolWitnessTableLazyCacheVariable: return mangler.mangleProtocolWitnessTableLazyCacheVariable(getType(), getProtocolConformance()); case Kind::AssociatedTypeWitnessTableAccessFunction: { auto assocConf = getAssociatedConformance(); if (isa<GenericTypeParamType>(assocConf.first)) { return mangler.mangleBaseWitnessTableAccessFunction( getProtocolConformance(), assocConf.second); } return mangler.mangleAssociatedTypeWitnessTableAccessFunction( getProtocolConformance(), assocConf.first, assocConf.second); } case Kind::CoroutineContinuationPrototype: return mangler.mangleCoroutineContinuationPrototype( cast<SILFunctionType>(getType())); // An Objective-C class reference reference. The symbol is private, so // the mangling is unimportant; it should just be readable in LLVM IR. case Kind::ObjCClassRef: { llvm::SmallString<64> tempBuffer; StringRef name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(tempBuffer); std::string Result("OBJC_CLASS_REF_$_"); Result.append(name.data(), name.size()); return Result; } // An Objective-C class reference; not a swift mangling. case Kind::ObjCClass: { llvm::SmallString<64> TempBuffer; StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer); std::string Result("OBJC_CLASS_$_"); Result.append(Name.data(), Name.size()); return Result; } // An Objective-C metaclass reference; not a swift mangling. case Kind::ObjCMetaclass: { llvm::SmallString<64> TempBuffer; StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer); std::string Result("OBJC_METACLASS_$_"); Result.append(Name.data(), Name.size()); return Result; } case Kind::SILFunction: { std::string Result(getSILFunction()->getName()); if (isDynamicallyReplaceable()) { Result.append("TI"); } return Result; } case Kind::DynamicallyReplaceableFunctionImpl: { assert(isa<AbstractFunctionDecl>(getDecl())); std::string Result; if (auto *Constructor = dyn_cast<ConstructorDecl>(getDecl())) { Result = mangler.mangleConstructorEntity(Constructor, isAllocator(), /*isCurried=*/false); } else { Result = mangler.mangleEntity(getDecl(), /*isCurried=*/false); } Result.append("TI"); return Result; } case Kind::DynamicallyReplaceableFunctionVariable: { std::string Result(getSILFunction()->getName()); Result.append("TX"); return Result; } case Kind::DynamicallyReplaceableFunctionKey: { std::string Result(getSILFunction()->getName()); Result.append("Tx"); return Result; } case Kind::DynamicallyReplaceableFunctionVariableAST: { assert(isa<AbstractFunctionDecl>(getDecl())); std::string Result; if (auto *Constructor = dyn_cast<ConstructorDecl>(getDecl())) { Result = mangler.mangleConstructorEntity(Constructor, isAllocator(), /*isCurried=*/false); } else { Result = mangler.mangleEntity(getDecl(), /*isCurried=*/false); } Result.append("TX"); return Result; } case Kind::DynamicallyReplaceableFunctionKeyAST: { assert(isa<AbstractFunctionDecl>(getDecl())); std::string Result; if (auto *Constructor = dyn_cast<ConstructorDecl>(getDecl())) { Result = mangler.mangleConstructorEntity(Constructor, isAllocator(), /*isCurried=*/false); } else { Result = mangler.mangleEntity(getDecl(), /*isCurried=*/false); } Result.append("Tx"); return Result; } case Kind::SILGlobalVariable: return getSILGlobalVariable()->getName(); case Kind::ReflectionBuiltinDescriptor: return mangler.mangleReflectionBuiltinDescriptor(getType()); case Kind::ReflectionFieldDescriptor: return mangler.mangleReflectionFieldDescriptor(getType()); case Kind::ReflectionAssociatedTypeDescriptor: return mangler.mangleReflectionAssociatedTypeDescriptor( getProtocolConformance()); } llvm_unreachable("bad entity kind!"); }
static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL, bool SupportsForcingFramePointer, const char *ExpandChar, const OptTable &Opts) { assert(A->getOption().matches(options::OPT__SLASH_O)); StringRef OptStr = A->getValue(); for (size_t I = 0, E = OptStr.size(); I != E; ++I) { const char &OptChar = *(OptStr.data() + I); switch (OptChar) { default: break; case '1': case '2': case 'x': case 'd': if (&OptChar == ExpandChar) { if (OptChar == 'd') { DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0)); } else { if (OptChar == '1') { DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); } else if (OptChar == '2' || OptChar == 'x') { DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); } if (SupportsForcingFramePointer && !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer)) DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer)); if (OptChar == '1' || OptChar == '2') DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections)); } } break; case 'b': if (I + 1 != E && isdigit(OptStr[I + 1])) { switch (OptStr[I + 1]) { case '0': DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline)); break; case '1': DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions)); break; case '2': DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions)); break; } ++I; } break; case 'g': break; case 'i': if (I + 1 != E && OptStr[I + 1] == '-') { ++I; DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin)); } else { DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); } break; case 's': DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); break; case 't': DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); break; case 'y': { bool OmitFramePointer = true; if (I + 1 != E && OptStr[I + 1] == '-') { OmitFramePointer = false; ++I; } if (SupportsForcingFramePointer) { if (OmitFramePointer) DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer)); else DAL.AddFlagArg( A, Opts.getOption(options::OPT_fno_omit_frame_pointer)); } else { // Don't warn about /Oy- in 64-bit builds (where // SupportsForcingFramePointer is false). The flag having no effect // there is a compiler-internal optimization, and people shouldn't have // to special-case their build files for 64-bit clang-cl. A->claim(); } break; } } } }
const MCSection *TargetLoweringObjectFileELF:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const { // If we have -ffunction-section or -fdata-section then we should emit the // global value to a uniqued section specifically for it. bool EmitUniquedSection; if (Kind.isText()) EmitUniquedSection = TM.getFunctionSections(); else EmitUniquedSection = TM.getDataSections(); // If this global is linkonce/weak and the target handles this by emitting it // into a 'uniqued' section name, create and return the section now. if ((GV->isWeakForLinker() || EmitUniquedSection || GV->hasComdat()) && !Kind.isCommon()) { StringRef Prefix = getSectionPrefixForGlobal(Kind); SmallString<128> Name(Prefix); TM.getNameWithPrefix(Name, GV, Mang, true); StringRef Group = ""; unsigned Flags = getELFSectionFlags(Kind); if (GV->isWeakForLinker() || GV->hasComdat()) { if (const Comdat *C = getELFComdat(GV)) Group = C->getName(); else Group = Name.substr(Prefix.size()); Flags |= ELF::SHF_GROUP; } return getContext().getELFSection(Name.str(), getELFSectionType(Name.str(), Kind), Flags, Kind, 0, Group); } if (Kind.isText()) return TextSection; if (Kind.isMergeable1ByteCString() || Kind.isMergeable2ByteCString() || Kind.isMergeable4ByteCString()) { // We also need alignment here. // FIXME: this is getting the alignment of the character, not the // alignment of the global! unsigned Align = TM.getSubtargetImpl()->getDataLayout()->getPreferredAlignment( cast<GlobalVariable>(GV)); const char *SizeSpec = ".rodata.str1."; if (Kind.isMergeable2ByteCString()) SizeSpec = ".rodata.str2."; else if (Kind.isMergeable4ByteCString()) SizeSpec = ".rodata.str4."; else assert(Kind.isMergeable1ByteCString() && "unknown string width"); std::string Name = SizeSpec + utostr(Align); return getContext().getELFSection(Name, ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS, Kind); } if (Kind.isMergeableConst()) { if (Kind.isMergeableConst4() && MergeableConst4Section) return MergeableConst4Section; if (Kind.isMergeableConst8() && MergeableConst8Section) return MergeableConst8Section; if (Kind.isMergeableConst16() && MergeableConst16Section) return MergeableConst16Section; return ReadOnlySection; // .const } if (Kind.isReadOnly()) return ReadOnlySection; if (Kind.isThreadData()) return TLSDataSection; if (Kind.isThreadBSS()) return TLSBSSSection; // Note: we claim that common symbols are put in BSSSection, but they are // really emitted with the magic .comm directive, which creates a symbol table // entry but not a section. if (Kind.isBSS() || Kind.isCommon()) return BSSSection; if (Kind.isDataNoRel()) return DataSection; if (Kind.isDataRelLocal()) return DataRelLocalSection; if (Kind.isDataRel()) return DataRelSection; if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); return DataRelROSection; }
// Returns the offset of the first reference to a member offset. static ErrorOr<unsigned> writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, ArrayRef<NewArchiveIterator> Members, ArrayRef<MemoryBufferRef> Buffers, std::vector<unsigned> &MemberOffsetRefs, bool Deterministic) { unsigned HeaderStartOffset = 0; unsigned BodyStartOffset = 0; SmallString<128> NameBuf; raw_svector_ostream NameOS(NameBuf); LLVMContext Context; for (unsigned MemberNum = 0, N = Members.size(); MemberNum < N; ++MemberNum) { MemoryBufferRef MemberBuffer = Buffers[MemberNum]; ErrorOr<std::unique_ptr<object::SymbolicFile>> ObjOrErr = object::SymbolicFile::createSymbolicFile( MemberBuffer, sys::fs::file_magic::unknown, &Context); if (!ObjOrErr) continue; // FIXME: check only for "not an object file" errors. object::SymbolicFile &Obj = *ObjOrErr.get(); if (!HeaderStartOffset) { HeaderStartOffset = Out.tell(); if (Kind == object::Archive::K_GNU) printGNUSmallMemberHeader(Out, "", now(Deterministic), 0, 0, 0, 0); else printBSDMemberHeader(Out, "__.SYMDEF", now(Deterministic), 0, 0, 0, 0); BodyStartOffset = Out.tell(); print32(Out, Kind, 0); // number of entries or bytes } for (const object::BasicSymbolRef &S : Obj.symbols()) { uint32_t Symflags = S.getFlags(); if (Symflags & object::SymbolRef::SF_FormatSpecific) continue; if (!(Symflags & object::SymbolRef::SF_Global)) continue; if (Symflags & object::SymbolRef::SF_Undefined) continue; unsigned NameOffset = NameOS.tell(); if (auto EC = S.printName(NameOS)) return EC; NameOS << '\0'; MemberOffsetRefs.push_back(MemberNum); if (Kind == object::Archive::K_BSD) print32(Out, Kind, NameOffset); print32(Out, Kind, 0); // member offset } } if (HeaderStartOffset == 0) return 0; StringRef StringTable = NameOS.str(); if (Kind == object::Archive::K_BSD) print32(Out, Kind, StringTable.size()); // byte count of the string table Out << StringTable; // ld64 requires the next member header to start at an offset that is // 4 bytes aligned. unsigned Pad = OffsetToAlignment(Out.tell(), 4); while (Pad--) Out.write(uint8_t(0)); // Patch up the size of the symbol table now that we know how big it is. unsigned Pos = Out.tell(); const unsigned MemberHeaderSize = 60; Out.seek(HeaderStartOffset + 48); // offset of the size field. printWithSpacePadding(Out, Pos - MemberHeaderSize - HeaderStartOffset, 10); // Patch up the number of symbols. Out.seek(BodyStartOffset); unsigned NumSyms = MemberOffsetRefs.size(); if (Kind == object::Archive::K_GNU) print32(Out, Kind, NumSyms); else print32(Out, Kind, NumSyms * 8); Out.seek(Pos); return BodyStartOffset + 4; }
static void dumpCXXData(const ObjectFile *Obj) { struct CompleteObjectLocator { StringRef Symbols[2]; ArrayRef<little32_t> Data; }; struct ClassHierarchyDescriptor { StringRef Symbols[1]; ArrayRef<little32_t> Data; }; struct BaseClassDescriptor { StringRef Symbols[2]; ArrayRef<little32_t> Data; }; struct TypeDescriptor { StringRef Symbols[1]; uint64_t AlwaysZero; StringRef MangledName; }; struct ThrowInfo { uint32_t Flags; }; struct CatchableTypeArray { uint32_t NumEntries; }; struct CatchableType { uint32_t Flags; uint32_t NonVirtualBaseAdjustmentOffset; int32_t VirtualBasePointerOffset; uint32_t VirtualBaseAdjustmentOffset; uint32_t Size; StringRef Symbols[2]; }; std::map<std::pair<StringRef, uint64_t>, StringRef> VFTableEntries; std::map<std::pair<StringRef, uint64_t>, StringRef> TIEntries; std::map<std::pair<StringRef, uint64_t>, StringRef> CTAEntries; std::map<StringRef, ArrayRef<little32_t>> VBTables; std::map<StringRef, CompleteObjectLocator> COLs; std::map<StringRef, ClassHierarchyDescriptor> CHDs; std::map<std::pair<StringRef, uint64_t>, StringRef> BCAEntries; std::map<StringRef, BaseClassDescriptor> BCDs; std::map<StringRef, TypeDescriptor> TDs; std::map<StringRef, ThrowInfo> TIs; std::map<StringRef, CatchableTypeArray> CTAs; std::map<StringRef, CatchableType> CTs; std::map<std::pair<StringRef, uint64_t>, StringRef> VTableSymEntries; std::map<std::pair<StringRef, uint64_t>, int64_t> VTableDataEntries; std::map<std::pair<StringRef, uint64_t>, StringRef> VTTEntries; std::map<StringRef, StringRef> TINames; uint8_t BytesInAddress = Obj->getBytesInAddress(); for (const object::SymbolRef &Sym : Obj->symbols()) { StringRef SymName; if (error(Sym.getName(SymName))) return; object::section_iterator SecI(Obj->section_begin()); if (error(Sym.getSection(SecI))) return; // Skip external symbols. if (SecI == Obj->section_end()) continue; const SectionRef &Sec = *SecI; // Skip virtual or BSS sections. if (Sec.isBSS() || Sec.isVirtual()) continue; StringRef SecContents; if (error(Sec.getContents(SecContents))) return; uint64_t SymAddress, SymSize; if (error(Sym.getAddress(SymAddress)) || error(Sym.getSize(SymSize))) return; uint64_t SecAddress = Sec.getAddress(); uint64_t SecSize = Sec.getSize(); uint64_t SymOffset = SymAddress - SecAddress; StringRef SymContents = SecContents.substr(SymOffset, SymSize); // VFTables in the MS-ABI start with '??_7' and are contained within their // own COMDAT section. We then determine the contents of the VFTable by // looking at each relocation in the section. if (SymName.startswith("??_7")) { // Each relocation either names a virtual method or a thunk. We note the // offset into the section and the symbol used for the relocation. collectRelocationOffsets(Obj, Sec, SecAddress, SecAddress, SecSize, SymName, VFTableEntries); } // VBTables in the MS-ABI start with '??_8' and are filled with 32-bit // offsets of virtual bases. else if (SymName.startswith("??_8")) { ArrayRef<little32_t> VBTableData( reinterpret_cast<const little32_t *>(SymContents.data()), SymContents.size() / sizeof(little32_t)); VBTables[SymName] = VBTableData; } // Complete object locators in the MS-ABI start with '??_R4' else if (SymName.startswith("??_R4")) { CompleteObjectLocator COL; COL.Data = ArrayRef<little32_t>( reinterpret_cast<const little32_t *>(SymContents.data()), 3); StringRef *I = std::begin(COL.Symbols), *E = std::end(COL.Symbols); if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E)) return; COLs[SymName] = COL; } // Class hierarchy descriptors in the MS-ABI start with '??_R3' else if (SymName.startswith("??_R3")) { ClassHierarchyDescriptor CHD; CHD.Data = ArrayRef<little32_t>( reinterpret_cast<const little32_t *>(SymContents.data()), 3); StringRef *I = std::begin(CHD.Symbols), *E = std::end(CHD.Symbols); if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E)) return; CHDs[SymName] = CHD; } // Class hierarchy descriptors in the MS-ABI start with '??_R2' else if (SymName.startswith("??_R2")) { // Each relocation names a base class descriptor. We note the offset into // the section and the symbol used for the relocation. collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize, SymName, BCAEntries); } // Base class descriptors in the MS-ABI start with '??_R1' else if (SymName.startswith("??_R1")) { BaseClassDescriptor BCD; BCD.Data = ArrayRef<little32_t>( reinterpret_cast<const little32_t *>(SymContents.data()) + 1, 5); StringRef *I = std::begin(BCD.Symbols), *E = std::end(BCD.Symbols); if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E)) return; BCDs[SymName] = BCD; } // Type descriptors in the MS-ABI start with '??_R0' else if (SymName.startswith("??_R0")) { const char *DataPtr = SymContents.drop_front(BytesInAddress).data(); TypeDescriptor TD; if (BytesInAddress == 8) TD.AlwaysZero = *reinterpret_cast<const little64_t *>(DataPtr); else TD.AlwaysZero = *reinterpret_cast<const little32_t *>(DataPtr); TD.MangledName = SymContents.drop_front(BytesInAddress * 2); StringRef *I = std::begin(TD.Symbols), *E = std::end(TD.Symbols); if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E)) return; TDs[SymName] = TD; } // Throw descriptors in the MS-ABI start with '_TI' else if (SymName.startswith("_TI") || SymName.startswith("__TI")) { ThrowInfo TI; TI.Flags = *reinterpret_cast<const little32_t *>(SymContents.data()); collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize, SymName, TIEntries); TIs[SymName] = TI; } // Catchable type arrays in the MS-ABI start with _CTA or __CTA. else if (SymName.startswith("_CTA") || SymName.startswith("__CTA")) { CatchableTypeArray CTA; CTA.NumEntries = *reinterpret_cast<const little32_t *>(SymContents.data()); collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize, SymName, CTAEntries); CTAs[SymName] = CTA; } // Catchable types in the MS-ABI start with _CT or __CT. else if (SymName.startswith("_CT") || SymName.startswith("__CT")) { const little32_t *DataPtr = reinterpret_cast<const little32_t *>(SymContents.data()); CatchableType CT; CT.Flags = DataPtr[0]; CT.NonVirtualBaseAdjustmentOffset = DataPtr[2]; CT.VirtualBasePointerOffset = DataPtr[3]; CT.VirtualBaseAdjustmentOffset = DataPtr[4]; CT.Size = DataPtr[5]; StringRef *I = std::begin(CT.Symbols), *E = std::end(CT.Symbols); if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E)) return; CTs[SymName] = CT; } // Construction vtables in the Itanium ABI start with '_ZTT' or '__ZTT'. else if (SymName.startswith("_ZTT") || SymName.startswith("__ZTT")) { collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize, SymName, VTTEntries); } // Typeinfo names in the Itanium ABI start with '_ZTS' or '__ZTS'. else if (SymName.startswith("_ZTS") || SymName.startswith("__ZTS")) { TINames[SymName] = SymContents.slice(0, SymContents.find('\0')); } // Vtables in the Itanium ABI start with '_ZTV' or '__ZTV'. else if (SymName.startswith("_ZTV") || SymName.startswith("__ZTV")) { collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize, SymName, VTableSymEntries); for (uint64_t SymOffI = 0; SymOffI < SymSize; SymOffI += BytesInAddress) { auto Key = std::make_pair(SymName, SymOffI); if (VTableSymEntries.count(Key)) continue; const char *DataPtr = SymContents.substr(SymOffI, BytesInAddress).data(); int64_t VData; if (BytesInAddress == 8) VData = *reinterpret_cast<const little64_t *>(DataPtr); else VData = *reinterpret_cast<const little32_t *>(DataPtr); VTableDataEntries[Key] = VData; } } // Typeinfo structures in the Itanium ABI start with '_ZTI' or '__ZTI'. else if (SymName.startswith("_ZTI") || SymName.startswith("__ZTI")) { // FIXME: Do something with these! } } for (const auto &VFTableEntry : VFTableEntries) { StringRef VFTableName = VFTableEntry.first.first; uint64_t Offset = VFTableEntry.first.second; StringRef SymName = VFTableEntry.second; outs() << VFTableName << '[' << Offset << "]: " << SymName << '\n'; } for (const auto &VBTable : VBTables) { StringRef VBTableName = VBTable.first; uint32_t Idx = 0; for (little32_t Offset : VBTable.second) { outs() << VBTableName << '[' << Idx << "]: " << Offset << '\n'; Idx += sizeof(Offset); } } for (const auto &COLPair : COLs) { StringRef COLName = COLPair.first; const CompleteObjectLocator &COL = COLPair.second; outs() << COLName << "[IsImageRelative]: " << COL.Data[0] << '\n'; outs() << COLName << "[OffsetToTop]: " << COL.Data[1] << '\n'; outs() << COLName << "[VFPtrOffset]: " << COL.Data[2] << '\n'; outs() << COLName << "[TypeDescriptor]: " << COL.Symbols[0] << '\n'; outs() << COLName << "[ClassHierarchyDescriptor]: " << COL.Symbols[1] << '\n'; } for (const auto &CHDPair : CHDs) { StringRef CHDName = CHDPair.first; const ClassHierarchyDescriptor &CHD = CHDPair.second; outs() << CHDName << "[AlwaysZero]: " << CHD.Data[0] << '\n'; outs() << CHDName << "[Flags]: " << CHD.Data[1] << '\n'; outs() << CHDName << "[NumClasses]: " << CHD.Data[2] << '\n'; outs() << CHDName << "[BaseClassArray]: " << CHD.Symbols[0] << '\n'; } for (const auto &BCAEntry : BCAEntries) { StringRef BCAName = BCAEntry.first.first; uint64_t Offset = BCAEntry.first.second; StringRef SymName = BCAEntry.second; outs() << BCAName << '[' << Offset << "]: " << SymName << '\n'; } for (const auto &BCDPair : BCDs) { StringRef BCDName = BCDPair.first; const BaseClassDescriptor &BCD = BCDPair.second; outs() << BCDName << "[TypeDescriptor]: " << BCD.Symbols[0] << '\n'; outs() << BCDName << "[NumBases]: " << BCD.Data[0] << '\n'; outs() << BCDName << "[OffsetInVBase]: " << BCD.Data[1] << '\n'; outs() << BCDName << "[VBPtrOffset]: " << BCD.Data[2] << '\n'; outs() << BCDName << "[OffsetInVBTable]: " << BCD.Data[3] << '\n'; outs() << BCDName << "[Flags]: " << BCD.Data[4] << '\n'; outs() << BCDName << "[ClassHierarchyDescriptor]: " << BCD.Symbols[1] << '\n'; } for (const auto &TDPair : TDs) { StringRef TDName = TDPair.first; const TypeDescriptor &TD = TDPair.second; outs() << TDName << "[VFPtr]: " << TD.Symbols[0] << '\n'; outs() << TDName << "[AlwaysZero]: " << TD.AlwaysZero << '\n'; outs() << TDName << "[MangledName]: "; outs().write_escaped(TD.MangledName.rtrim(StringRef("\0", 1)), /*UseHexEscapes=*/true) << '\n'; } for (const auto &TIPair : TIs) { StringRef TIName = TIPair.first; const ThrowInfo &TI = TIPair.second; auto dumpThrowInfoFlag = [&](const char *Name, uint32_t Flag) { outs() << TIName << "[Flags." << Name << "]: " << (TI.Flags & Flag ? "true" : "false") << '\n'; }; auto dumpThrowInfoSymbol = [&](const char *Name, int Offset) { outs() << TIName << '[' << Name << "]: "; auto Entry = TIEntries.find(std::make_pair(TIName, Offset)); outs() << (Entry == TIEntries.end() ? "null" : Entry->second) << '\n'; }; outs() << TIName << "[Flags]: " << TI.Flags << '\n'; dumpThrowInfoFlag("Const", 1); dumpThrowInfoFlag("Volatile", 2); dumpThrowInfoSymbol("CleanupFn", 4); dumpThrowInfoSymbol("ForwardCompat", 8); dumpThrowInfoSymbol("CatchableTypeArray", 12); } for (const auto &CTAPair : CTAs) { StringRef CTAName = CTAPair.first; const CatchableTypeArray &CTA = CTAPair.second; outs() << CTAName << "[NumEntries]: " << CTA.NumEntries << '\n'; unsigned Idx = 0; for (auto I = CTAEntries.lower_bound(std::make_pair(CTAName, 0)), E = CTAEntries.upper_bound(std::make_pair(CTAName, UINT64_MAX)); I != E; ++I) outs() << CTAName << '[' << Idx++ << "]: " << I->second << '\n'; } for (const auto &CTPair : CTs) { StringRef CTName = CTPair.first; const CatchableType &CT = CTPair.second; auto dumpCatchableTypeFlag = [&](const char *Name, uint32_t Flag) { outs() << CTName << "[Flags." << Name << "]: " << (CT.Flags & Flag ? "true" : "false") << '\n'; }; outs() << CTName << "[Flags]: " << CT.Flags << '\n'; dumpCatchableTypeFlag("ScalarType", 1); dumpCatchableTypeFlag("VirtualInheritance", 4); outs() << CTName << "[TypeDescriptor]: " << CT.Symbols[0] << '\n'; outs() << CTName << "[NonVirtualBaseAdjustmentOffset]: " << CT.NonVirtualBaseAdjustmentOffset << '\n'; outs() << CTName << "[VirtualBasePointerOffset]: " << CT.VirtualBasePointerOffset << '\n'; outs() << CTName << "[VirtualBaseAdjustmentOffset]: " << CT.VirtualBaseAdjustmentOffset << '\n'; outs() << CTName << "[Size]: " << CT.Size << '\n'; outs() << CTName << "[CopyCtor]: " << (CT.Symbols[1].empty() ? "null" : CT.Symbols[1]) << '\n'; } for (const auto &VTTPair : VTTEntries) { StringRef VTTName = VTTPair.first.first; uint64_t VTTOffset = VTTPair.first.second; StringRef VTTEntry = VTTPair.second; outs() << VTTName << '[' << VTTOffset << "]: " << VTTEntry << '\n'; } for (const auto &TIPair : TINames) { StringRef TIName = TIPair.first; outs() << TIName << ": " << TIPair.second << '\n'; } auto VTableSymI = VTableSymEntries.begin(); auto VTableSymE = VTableSymEntries.end(); auto VTableDataI = VTableDataEntries.begin(); auto VTableDataE = VTableDataEntries.end(); for (;;) { bool SymDone = VTableSymI == VTableSymE; bool DataDone = VTableDataI == VTableDataE; if (SymDone && DataDone) break; if (!SymDone && (DataDone || VTableSymI->first < VTableDataI->first)) { StringRef VTableName = VTableSymI->first.first; uint64_t Offset = VTableSymI->first.second; StringRef VTableEntry = VTableSymI->second; outs() << VTableName << '[' << Offset << "]: "; outs() << VTableEntry; outs() << '\n'; ++VTableSymI; continue; } if (!DataDone && (SymDone || VTableDataI->first < VTableSymI->first)) { StringRef VTableName = VTableDataI->first.first; uint64_t Offset = VTableDataI->first.second; int64_t VTableEntry = VTableDataI->second; outs() << VTableName << '[' << Offset << "]: "; outs() << VTableEntry; outs() << '\n'; ++VTableDataI; continue; } } }
static StringRef copyString(llvm::BumpPtrAllocator &Allocator, StringRef Str) { char *Mem = Allocator.Allocate<char>(Str.size()); std::copy(Str.begin(), Str.end(), Mem); return StringRef(Mem, Str.size()); }
void ReadHeader(MemoryBuffer &Input) final { StringRef FC = Input.getBuffer(); // Initialize the current bundle with the end of the container. CurBundleInfo = BundlesInfo.end(); // Check if buffer is smaller than magic string. size_t ReadChars = sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1; if (ReadChars > FC.size()) return; // Check if no magic was found. StringRef Magic(FC.data(), sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1); if (!Magic.equals(OFFLOAD_BUNDLER_MAGIC_STR)) return; // Read number of bundles. if (ReadChars + 8 > FC.size()) return; uint64_t NumberOfBundles = Read8byteIntegerFromBuffer(FC, ReadChars); ReadChars += 8; // Read bundle offsets, sizes and triples. for (uint64_t i = 0; i < NumberOfBundles; ++i) { // Read offset. if (ReadChars + 8 > FC.size()) return; uint64_t Offset = Read8byteIntegerFromBuffer(FC, ReadChars); ReadChars += 8; // Read size. if (ReadChars + 8 > FC.size()) return; uint64_t Size = Read8byteIntegerFromBuffer(FC, ReadChars); ReadChars += 8; // Read triple size. if (ReadChars + 8 > FC.size()) return; uint64_t TripleSize = Read8byteIntegerFromBuffer(FC, ReadChars); ReadChars += 8; // Read triple. if (ReadChars + TripleSize > FC.size()) return; StringRef Triple(&FC.data()[ReadChars], TripleSize); ReadChars += TripleSize; // Check if the offset and size make sense. if (!Size || !Offset || Offset + Size > FC.size()) return; assert(BundlesInfo.find(Triple) == BundlesInfo.end() && "Triple is duplicated??"); BundlesInfo[Triple] = BundleInfo(Size, Offset); } // Set the iterator to where we will start to read. CurBundleInfo = BundlesInfo.begin(); }
/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". /// This is a string that can appear after a .section directive in a mach-o /// flavored .s file. If successful, this fills in the specified Out /// parameters and returns an empty string. When an invalid section /// specifier is present, this returns a string indicating the problem. std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. StringRef &Segment, // Out. StringRef &Section, // Out. unsigned &TAA, // Out. bool &TAAParsed, // Out. unsigned &StubSize) { // Out. TAAParsed = false; SmallVector<StringRef, 5> SplitSpec; Spec.split(SplitSpec, ","); // Remove leading and trailing whitespace. auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef { return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef(); }; Segment = GetEmptyOrTrim(0); Section = GetEmptyOrTrim(1); StringRef SectionType = GetEmptyOrTrim(2); StringRef Attrs = GetEmptyOrTrim(3); StringRef StubSizeStr = GetEmptyOrTrim(4); // Verify that the segment is present and not too long. if (Segment.empty() || Segment.size() > 16) return "mach-o section specifier requires a segment whose length is " "between 1 and 16 characters"; // Verify that the section is present and not too long. if (Section.empty()) return "mach-o section specifier requires a segment and section " "separated by a comma"; if (Section.size() > 16) return "mach-o section specifier requires a section whose length is " "between 1 and 16 characters"; // If there is no comma after the section, we're done. TAA = 0; StubSize = 0; if (SectionType.empty()) return ""; // Figure out which section type it is. auto TypeDescriptor = std::find_if( std::begin(SectionTypeDescriptors), std::end(SectionTypeDescriptors), [&](decltype(*SectionTypeDescriptors) &Descriptor) { return Descriptor.AssemblerName && SectionType == Descriptor.AssemblerName; }); // If we didn't find the section type, reject it. if (TypeDescriptor == std::end(SectionTypeDescriptors)) return "mach-o section specifier uses an unknown section type"; // Remember the TypeID. TAA = TypeDescriptor - std::begin(SectionTypeDescriptors); TAAParsed = true; // If we have no comma after the section type, there are no attributes. if (Attrs.empty()) { // S_SYMBOL_STUBS always require a symbol stub size specifier. if (TAA == MachO::S_SYMBOL_STUBS) return "mach-o section specifier of type 'symbol_stubs' requires a size " "specifier"; return ""; } // The attribute list is a '+' separated list of attributes. SmallVector<StringRef, 1> SectionAttrs; Attrs.split(SectionAttrs, "+", /*MaxSplit=*/-1, /*KeepEmpty=*/false); for (StringRef &SectionAttr : SectionAttrs) { auto AttrDescriptorI = std::find_if( std::begin(SectionAttrDescriptors), std::end(SectionAttrDescriptors), [&](decltype(*SectionAttrDescriptors) &Descriptor) { return Descriptor.AssemblerName && SectionAttr.trim() == Descriptor.AssemblerName; }); if (AttrDescriptorI == std::end(SectionAttrDescriptors)) return "mach-o section specifier has invalid attribute"; TAA |= AttrDescriptorI->AttrFlag; } // Okay, we've parsed the section attributes, see if we have a stub size spec. if (StubSizeStr.empty()) { // S_SYMBOL_STUBS always require a symbol stub size specifier. if (TAA == MachO::S_SYMBOL_STUBS) return "mach-o section specifier of type 'symbol_stubs' requires a size " "specifier"; return ""; } // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS. if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS) return "mach-o section specifier cannot have a stub size specified because " "it does not have type 'symbol_stubs'"; // Convert the stub size from a string to an integer. if (StubSizeStr.getAsInteger(0, StubSize)) return "mach-o section specifier has a malformed stub size"; return ""; }
/// Get the name of a profiling variable for a particular function. static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix) { StringRef NamePrefix = getInstrProfNameVarPrefix(); StringRef Name = Inc->getName()->getName().substr(NamePrefix.size()); return (Prefix + Name).str(); }
/// \brief returns a printable representation of first item from input range /// /// This function returns a printable representation of the next item in a line /// of source. If the next byte begins a valid and printable character, that /// character is returned along with 'true'. /// /// Otherwise, if the next byte begins a valid, but unprintable character, a /// printable, escaped representation of the character is returned, along with /// 'false'. Otherwise a printable, escaped representation of the next byte /// is returned along with 'false'. /// /// \note The index is updated to be used with a subsequent call to /// printableTextForNextCharacter. /// /// \param SourceLine The line of source /// \param i Pointer to byte index, /// \param TabStop used to expand tabs /// \return pair(printable text, 'true' iff original text was printable) /// static std::pair<SmallString<16>, bool> printableTextForNextCharacter(StringRef SourceLine, size_t *i, unsigned TabStop) { assert(i && "i must not be null"); assert(*i<SourceLine.size() && "must point to a valid index"); if (SourceLine[*i]=='\t') { assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop && "Invalid -ftabstop value"); unsigned col = bytesSincePreviousTabOrLineBegin(SourceLine, *i); unsigned NumSpaces = TabStop - col%TabStop; assert(0 < NumSpaces && NumSpaces <= TabStop && "Invalid computation of space amt"); ++(*i); SmallString<16> expandedTab; expandedTab.assign(NumSpaces, ' '); return std::make_pair(expandedTab, true); } unsigned char const *begin, *end; begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i)); end = begin + (SourceLine.size() - *i); if (isLegalUTF8Sequence(begin, end)) { UTF32 c; UTF32 *cptr = &c; unsigned char const *original_begin = begin; unsigned char const *cp_end = begin+getNumBytesForUTF8(SourceLine[*i]); ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1, strictConversion); (void)res; assert(conversionOK==res); assert(0 < begin-original_begin && "we must be further along in the string now"); *i += begin-original_begin; if (!llvm::sys::locale::isPrint(c)) { // If next character is valid UTF-8, but not printable SmallString<16> expandedCP("<U+>"); while (c) { expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16)); c/=16; } while (expandedCP.size() < 8) expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0)); return std::make_pair(expandedCP, false); } // If next character is valid UTF-8, and printable return std::make_pair(SmallString<16>(original_begin, cp_end), true); } // If next byte is not valid UTF-8 (and therefore not printable) SmallString<16> expandedByte("<XX>"); unsigned char byte = SourceLine[*i]; expandedByte[1] = llvm::hexdigit(byte / 16); expandedByte[2] = llvm::hexdigit(byte % 16); ++(*i); return std::make_pair(expandedByte, false); }
static StringRef StripTrailingDots(StringRef s) { for (StringRef::size_type i = s.size(); i != 0; --i) if (s[i - 1] != '.') return s.substr(0, i); return ""; }
virtual void NotifyObjectEmitted(const ObjectImage &obj) #endif { uint64_t Addr; uint64_t Size; object::SymbolRef::Type SymbolType; #ifdef LLVM36 object::section_iterator Section = obj.section_begin(); object::section_iterator EndSection = obj.section_end(); uint64_t SectionAddr = 0; StringRef sName; #else object::section_iterator Section = obj.begin_sections(); object::section_iterator EndSection = obj.end_sections(); bool isText; #ifndef _OS_LINUX_ StringRef sName; #endif #endif #ifndef LLVM36 uint64_t SectionAddr = 0; #endif uint64_t SectionSize = 0; uint64_t SectionAddrCheck = 0; // assert that all of the Sections are at the same location #if defined(_OS_WINDOWS_) #if defined(_CPU_X86_64_) uint8_t *UnwindData = NULL; uint8_t *catchjmp = NULL; for (const object::SymbolRef &sym_iter : obj.symbols()) { # ifdef LLVM37 sName = sym_iter.getName().get(); # else sym_iter.getName(sName); # endif if (sName.equals("__UnwindData")) { # ifdef LLVM37 Addr = sym_iter.getAddress().get(); # else sym_iter.getAddress(Addr); # endif sym_iter.getSection(Section); # ifdef LLVM36 assert(Section->isText()); # ifdef LLVM38 SectionAddr = L.getSectionLoadAddress(*Section); # else Section->getName(sName); SectionAddr = L.getSectionLoadAddress(sName); # endif Addr += SectionAddr; # else if (Section->isText(isText) || !isText) assert(0 && "!isText"); Section->getAddress(SectionAddr); # endif UnwindData = (uint8_t*)Addr; if (SectionAddrCheck) assert(SectionAddrCheck == SectionAddr); else SectionAddrCheck = SectionAddr; } if (sName.equals("__catchjmp")) { # ifdef LLVM37 Addr = sym_iter.getAddress().get(); # else sym_iter.getAddress(Addr); # endif sym_iter.getSection(Section); # ifdef LLVM36 assert(Section->isText()); # ifdef LLVM38 SectionAddr = L.getSectionLoadAddress(*Section); # else Section->getName(sName); SectionAddr = L.getSectionLoadAddress(sName); # endif Addr += SectionAddr; # else if (Section->isText(isText) || !isText) assert(0 && "!isText"); Section->getAddress(SectionAddr); # endif catchjmp = (uint8_t*)Addr; if (SectionAddrCheck) assert(SectionAddrCheck == SectionAddr); else SectionAddrCheck = SectionAddr; } } assert(catchjmp); assert(UnwindData); catchjmp[0] = 0x48; catchjmp[1] = 0xb8; // mov RAX, QWORD PTR [&_seh_exception_handle] *(uint64_t*)(&catchjmp[2]) = (uint64_t)&_seh_exception_handler; catchjmp[10] = 0xff; catchjmp[11] = 0xe0; // jmp RAX UnwindData[0] = 0x09; // version info, UNW_FLAG_EHANDLER UnwindData[1] = 4; // size of prolog (bytes) UnwindData[2] = 2; // count of unwind codes (slots) UnwindData[3] = 0x05; // frame register (rbp) = rsp UnwindData[4] = 4; // second instruction UnwindData[5] = 0x03; // mov RBP, RSP UnwindData[6] = 1; // first instruction UnwindData[7] = 0x50; // push RBP *(DWORD*)&UnwindData[8] = (DWORD)(catchjmp - (uint8_t*)SectionAddr); // relative location of catchjmp #else // defined(_OS_X86_64_) uint8_t *UnwindData = NULL; #endif // defined(_OS_X86_64_) #endif // defined(_OS_WINDOWS_) #ifdef LLVM35 for (const object::SymbolRef &sym_iter : obj.symbols()) { # ifdef LLVM37 SymbolType = sym_iter.getType(); # else sym_iter.getType(SymbolType); # endif if (SymbolType != object::SymbolRef::ST_Function) continue; # ifdef LLVM37 Addr = sym_iter.getAddress().get(); # else sym_iter.getAddress(Addr); # endif sym_iter.getSection(Section); if (Section == EndSection) continue; #if defined(LLVM36) if (!Section->isText()) continue; # ifdef LLVM38 SectionAddr = L.getSectionLoadAddress(*Section); # else Section->getName(sName); SectionAddr = L.getSectionLoadAddress(sName); # endif Addr += SectionAddr; #else if (Section->isText(isText) || !isText) continue; #endif #if defined(LLVM36) SectionSize = Section->getSize(); #else Section->getAddress(SectionAddr); Section->getSize(SectionSize); #endif #ifdef _OS_DARWIN_ # if defined(LLVM37) Size = Section->getSize(); sName = sym_iter.getName().get(); # else sym_iter.getName(sName); # endif # if defined(LLVM36) if (sName[0] == '_') { sName = sName.substr(1); } # else Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName, true); if (!Addr && sName[0] == '_') { sName = sName.substr(1); Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName, true); } if (!Addr) continue; # endif #elif defined(_OS_WINDOWS_) # if defined(LLVM37) assert(obj.isELF()); Size = ((llvm::object::ELFSymbolRef)sym_iter).getSize(); sName = sym_iter.getName().get(); # else sym_iter.getSize(Size); sym_iter.getName(sName); # endif # ifdef _CPU_X86_ if (sName[0] == '_') sName = sName.substr(1); # endif if (SectionAddrCheck) assert(SectionAddrCheck == SectionAddr); else SectionAddrCheck = SectionAddr; create_PRUNTIME_FUNCTION( (uint8_t*)(intptr_t)Addr, (size_t)Size, sName, (uint8_t*)(intptr_t)SectionAddr, (size_t)SectionSize, UnwindData); #endif const object::ObjectFile *objfile = #ifdef LLVM36 &obj; #else obj.getObjectFile(); #endif ObjectInfo tmp = {objfile, SectionSize #ifdef LLVM37 ,L.clone().release() #elif defined(LLVM36) ,(size_t)SectionAddr #endif #ifdef _OS_DARWIN_ ,strndup(sName.data(), sName.size()) #endif }; objectmap[Addr] = tmp; } #else //LLVM34 error_code itererr; object::symbol_iterator sym_iter = obj.begin_symbols(); object::symbol_iterator sym_end = obj.end_symbols(); for (; sym_iter != sym_end; sym_iter.increment(itererr)) { sym_iter->getType(SymbolType); if (SymbolType != object::SymbolRef::ST_Function) continue; sym_iter->getAddress(Addr); sym_iter->getSize(Size); ObjectInfo tmp = {obj.getObjectFile(), (size_t)Size}; objectmap[Addr] = tmp; } #endif }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, InlineAsm::AsmDialect Dialect) const { assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer is actually a .s file, just emit the blob textually. // This is useful in case the asm parser doesn't handle something but the // system assembler does. if (OutStreamer.hasRawTextSupport()) { OutStreamer.EmitRawText(Str); return; } SourceMgr SrcMgr; SrcMgrDiagInfo DiagInfo; // If the current LLVMContext has an inline asm handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) { // If the source manager has an issue, we arrange for srcMgrDiagHandler // to be invoked, getting DiagInfo passed into it. DiagInfo.LocInfo = LocMDNode; DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo); HasDiagHandler = true; } MemoryBuffer *Buffer; if (isNullTerminated) Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); else Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, OutContext, OutStreamer, *MAI)); // FIXME: It would be nice if we can avoid createing a new instance of // MCSubtargetInfo here given TargetSubtargetInfo is available. However, // we have to watch out for asm directives which can change subtarget // state. e.g. .code 16, .code 32. OwningPtr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); OwningPtr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(*STI, *Parser, *MII)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); if (Res && !HasDiagHandler) report_fatal_error("Error parsing inline asm\n"); }
/// CopyStringRef - Copies contents of a StringRef into a block of memory and /// null-terminates it. static void CopyStringRef(char *Memory, StringRef Data) { memcpy(Memory, Data.data(), Data.size()); Memory[Data.size()] = 0; // Null terminate string. }
static int writeStringRef(StringRef &Str, raw_ostream &OS) { encodeULEB128(Str.size(), OS); OS << Str; return 0; }