static void mergeInstrProfile(const cl::list<std::string> &Inputs, StringRef OutputFilename) { if (OutputFilename.compare("-") == 0) exitWithError("Cannot write indexed profdata format to stdout."); std::error_code EC; raw_fd_ostream Output(OutputFilename.data(), EC, sys::fs::F_None); if (EC) exitWithError(EC.message(), OutputFilename); InstrProfWriter Writer; for (const auto &Filename : Inputs) { auto ReaderOrErr = InstrProfReader::create(Filename); if (std::error_code ec = ReaderOrErr.getError()) exitWithError(ec.message(), Filename); auto Reader = std::move(ReaderOrErr.get()); for (auto &I : *Reader) if (std::error_code EC = Writer.addRecord(std::move(I))) errs() << Filename << ": " << I.Name << ": " << EC.message() << "\n"; if (Reader->hasError()) exitWithError(Reader->getError().message(), Filename); } Writer.write(Output); }
int FunctionComparator::cmpMem(StringRef L, StringRef R) const { // Prevent heavy comparison, compare sizes first. if (int Res = cmpNumbers(L.size(), R.size())) return Res; // Compare strings lexicographically only when it is necessary: only when // strings are equal in size. return L.compare(R); }
bool clang::operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y) { std::string XSaved, YSaved; StringRef XStr = getOrderedName(X, XSaved); StringRef YStr = getOrderedName(Y, YSaved); int cmp = XStr.compare_lower(YStr); if (cmp) return cmp < 0; // If case-insensitive comparison fails, try case-sensitive comparison. cmp = XStr.compare(YStr); if (cmp) return cmp < 0; return false; }
static void mergeInstrProfile(const WeightedFileVector &Inputs, StringRef OutputFilename, ProfileFormat OutputFormat, bool OutputSparse) { if (OutputFilename.compare("-") == 0) exitWithError("Cannot write indexed profdata format to stdout."); if (OutputFormat != PF_Binary && OutputFormat != PF_Text) exitWithError("Unknown format is specified."); std::error_code EC; raw_fd_ostream Output(OutputFilename.data(), EC, sys::fs::F_None); if (EC) exitWithErrorCode(EC, OutputFilename); InstrProfWriter Writer(OutputSparse); SmallSet<instrprof_error, 4> WriterErrorCodes; for (const auto &Input : Inputs) { auto ReaderOrErr = InstrProfReader::create(Input.Filename); if (Error E = ReaderOrErr.takeError()) exitWithError(std::move(E), Input.Filename); auto Reader = std::move(ReaderOrErr.get()); bool IsIRProfile = Reader->isIRLevelProfile(); if (Writer.setIsIRLevelProfile(IsIRProfile)) exitWithError("Merge IR generated profile with Clang generated profile."); for (auto &I : *Reader) { if (Error E = Writer.addRecord(std::move(I), Input.Weight)) { // Only show hint the first time an error occurs. instrprof_error IPE = InstrProfError::take(std::move(E)); bool firstTime = WriterErrorCodes.insert(IPE).second; handleMergeWriterError(make_error<InstrProfError>(IPE), Input.Filename, I.Name, firstTime); } } if (Reader->hasError()) exitWithError(Reader->getError(), Input.Filename); } if (OutputFormat == PF_Text) Writer.writeText(Output); else Writer.write(Output); }
void ObjectLoadListener::recordRelocations( const ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &L) { for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { section_iterator Section = SI->getRelocatedSection(); if (Section == SE) { continue; } StringRef SectionName; std::error_code ErrorCode = Section->getName(SectionName); if (ErrorCode) { assert(false && ErrorCode.message().c_str()); } if (SectionName.startswith(".debug") || SectionName.startswith(".rela.debug") || !SectionName.compare(".pdata") || SectionName.startswith(".eh_frame") || SectionName.startswith(".rela.eh_frame")) { // Skip sections whose contents are not directly reported to the EE continue; } relocation_iterator I = SI->relocation_begin(); relocation_iterator E = SI->relocation_end(); for (; I != E; ++I) { symbol_iterator Symbol = I->getSymbol(); assert(Symbol != Obj.symbol_end()); ErrorOr<section_iterator> SymbolSectionOrErr = Symbol->getSection(); assert(!SymbolSectionOrErr.getError()); object::section_iterator SymbolSection = *SymbolSectionOrErr; const bool IsExtern = SymbolSection == Obj.section_end(); uint64_t RelType = I->getType(); uint64_t Offset = I->getOffset(); uint8_t *RelocationTarget; if (IsExtern) { // This is an external symbol. Verify that it's one we created for // a global variable and report the relocation via Jit interface. ErrorOr<StringRef> NameOrError = Symbol->getName(); assert(NameOrError); StringRef TargetName = NameOrError.get(); auto MapIter = Context->NameToHandleMap.find(TargetName); if (MapIter == Context->NameToHandleMap.end()) { // The xdata gets a pointer to our personality routine, which we // dummied up. We can safely skip it since the EE isn't actually // going to use the value (it inserts the correct one before handing // the xdata off to the OS). assert(!TargetName.compare("ProcessCLRException")); assert(SectionName.startswith(".xdata")); continue; } else { assert(MapIter->second == Context->NameToHandleMap[TargetName]); RelocationTarget = (uint8_t *)MapIter->second; } } else { RelocationTarget = (uint8_t *)(L.getSectionLoadAddress(*SymbolSection) + Symbol->getValue()); } uint64_t Addend = 0; uint64_t EERelType = getRelocationType(RelType); uint64_t SectionAddress = L.getSectionLoadAddress(*Section); assert(SectionAddress != 0); uint8_t *FixupAddress = (uint8_t *)(SectionAddress + Offset); if (Obj.isELF()) { // Addend is part of the relocation ELFRelocationRef ElfReloc(*I); ErrorOr<uint64_t> ElfAddend = ElfReloc.getAddend(); assert(!ElfAddend.getError()); Addend = ElfAddend.get(); } else { // Addend is read from the location to be fixed up Addend = getRelocationAddend(RelType, FixupAddress); } Context->JitInfo->recordRelocation(FixupAddress, RelocationTarget + Addend, EERelType); } } }
void llvm::DisassembleInputMachO(StringRef Filename) { OwningPtr<MemoryBuffer> Buff; if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) { errs() << "llvm-objdump: " << Filename << ": " << ec.message() << "\n"; return; } OwningPtr<MachOObjectFile> MachOOF(static_cast<MachOObjectFile*>( ObjectFile::createMachOObjectFile(Buff.take()))); MachOObject *MachOObj = MachOOF->getObject(); const Target *TheTarget = GetTarget(MachOObj); if (!TheTarget) { // GetTarget prints out stuff. return; } OwningPtr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); OwningPtr<MCInstrAnalysis> InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo.get())); // Set up disassembler. OwningPtr<const MCAsmInfo> AsmInfo(TheTarget->createMCAsmInfo(TripleName)); OwningPtr<const MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, "", "")); OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI, *STI)); if (!InstrAnalysis || !AsmInfo || !STI || !DisAsm || !IP) { errs() << "error: couldn't initialize disassembler for target " << TripleName << '\n'; return; } outs() << '\n' << Filename << ":\n\n"; const macho::Header &Header = MachOObj->getHeader(); const MachOObject::LoadCommandInfo *SymtabLCI = 0; // First, find the symbol table segment. for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i); if (LCI.Command.Type == macho::LCT_Symtab) { SymtabLCI = &LCI; break; } } // Read and register the symbol table data. InMemoryStruct<macho::SymtabLoadCommand> SymtabLC; if (SymtabLCI) { MachOObj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC); MachOObj->RegisterStringTable(*SymtabLC); } std::vector<SectionRef> Sections; std::vector<SymbolRef> Symbols; SmallVector<uint64_t, 8> FoundFns; getSectionsAndSymbols(Header, MachOOF.get(), &SymtabLC, Sections, Symbols, FoundFns); // Make a copy of the unsorted symbol list. FIXME: duplication std::vector<SymbolRef> UnsortedSymbols(Symbols); // Sort the symbols by address, just in case they didn't come in that way. std::sort(Symbols.begin(), Symbols.end(), SymbolSorter()); #ifndef NDEBUG raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); #else raw_ostream &DebugOut = nulls(); #endif StringRef DebugAbbrevSection, DebugInfoSection, DebugArangesSection, DebugLineSection, DebugStrSection; OwningPtr<DIContext> diContext; OwningPtr<MachOObjectFile> DSYMObj; MachOObject *DbgInfoObj = MachOObj; // Try to find debug info and set up the DIContext for it. if (UseDbg) { ArrayRef<SectionRef> DebugSections = Sections; std::vector<SectionRef> DSYMSections; // A separate DSym file path was specified, parse it as a macho file, // get the sections and supply it to the section name parsing machinery. if (!DSYMFile.empty()) { OwningPtr<MemoryBuffer> Buf; if (error_code ec = MemoryBuffer::getFileOrSTDIN(DSYMFile.c_str(), Buf)) { errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n'; return; } DSYMObj.reset(static_cast<MachOObjectFile*>( ObjectFile::createMachOObjectFile(Buf.take()))); const macho::Header &Header = DSYMObj->getObject()->getHeader(); std::vector<SymbolRef> Symbols; SmallVector<uint64_t, 8> FoundFns; getSectionsAndSymbols(Header, DSYMObj.get(), 0, DSYMSections, Symbols, FoundFns); DebugSections = DSYMSections; DbgInfoObj = DSYMObj.get()->getObject(); } // Find the named debug info sections. for (unsigned SectIdx = 0; SectIdx != DebugSections.size(); SectIdx++) { StringRef SectName; if (!DebugSections[SectIdx].getName(SectName)) { if (SectName.equals("__DWARF,__debug_abbrev")) DebugSections[SectIdx].getContents(DebugAbbrevSection); else if (SectName.equals("__DWARF,__debug_info")) DebugSections[SectIdx].getContents(DebugInfoSection); else if (SectName.equals("__DWARF,__debug_aranges")) DebugSections[SectIdx].getContents(DebugArangesSection); else if (SectName.equals("__DWARF,__debug_line")) DebugSections[SectIdx].getContents(DebugLineSection); else if (SectName.equals("__DWARF,__debug_str")) DebugSections[SectIdx].getContents(DebugStrSection); } } // Setup the DIContext. diContext.reset(DIContext::getDWARFContext(DbgInfoObj->isLittleEndian(), DebugInfoSection, DebugAbbrevSection, DebugArangesSection, DebugLineSection, DebugStrSection)); } FunctionMapTy FunctionMap; FunctionListTy Functions; for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { StringRef SectName; if (Sections[SectIdx].getName(SectName) || SectName.compare("__TEXT,__text")) continue; // Skip non-text sections // Insert the functions from the function starts segment into our map. uint64_t VMAddr; Sections[SectIdx].getAddress(VMAddr); for (unsigned i = 0, e = FoundFns.size(); i != e; ++i) { StringRef SectBegin; Sections[SectIdx].getContents(SectBegin); uint64_t Offset = (uint64_t)SectBegin.data(); FunctionMap.insert(std::make_pair(VMAddr + FoundFns[i]-Offset, (MCFunction*)0)); } StringRef Bytes; Sections[SectIdx].getContents(Bytes); StringRefMemoryObject memoryObject(Bytes); bool symbolTableWorked = false; // Parse relocations. std::vector<std::pair<uint64_t, SymbolRef> > Relocs; error_code ec; for (relocation_iterator RI = Sections[SectIdx].begin_relocations(), RE = Sections[SectIdx].end_relocations(); RI != RE; RI.increment(ec)) { uint64_t RelocOffset, SectionAddress; RI->getAddress(RelocOffset); Sections[SectIdx].getAddress(SectionAddress); RelocOffset -= SectionAddress; SymbolRef RelocSym; RI->getSymbol(RelocSym); Relocs.push_back(std::make_pair(RelocOffset, RelocSym)); } array_pod_sort(Relocs.begin(), Relocs.end()); // Disassemble symbol by symbol. for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { StringRef SymName; Symbols[SymIdx].getName(SymName); SymbolRef::Type ST; Symbols[SymIdx].getType(ST); if (ST != SymbolRef::ST_Function) continue; // Make sure the symbol is defined in this section. bool containsSym = false; Sections[SectIdx].containsSymbol(Symbols[SymIdx], containsSym); if (!containsSym) continue; // Start at the address of the symbol relative to the section's address. uint64_t SectionAddress = 0; uint64_t Start = 0; Sections[SectIdx].getAddress(SectionAddress); Symbols[SymIdx].getAddress(Start); Start -= SectionAddress; // Stop disassembling either at the beginning of the next symbol or at // the end of the section. bool containsNextSym = false; uint64_t NextSym = 0; uint64_t NextSymIdx = SymIdx+1; while (Symbols.size() > NextSymIdx) { SymbolRef::Type NextSymType; Symbols[NextSymIdx].getType(NextSymType); if (NextSymType == SymbolRef::ST_Function) { Sections[SectIdx].containsSymbol(Symbols[NextSymIdx], containsNextSym); Symbols[NextSymIdx].getAddress(NextSym); NextSym -= SectionAddress; break; } ++NextSymIdx; } uint64_t SectSize; Sections[SectIdx].getSize(SectSize); uint64_t End = containsNextSym ? NextSym : SectSize; uint64_t Size; symbolTableWorked = true; if (!CFG) { // Normal disassembly, print addresses, bytes and mnemonic form. StringRef SymName; Symbols[SymIdx].getName(SymName); outs() << SymName << ":\n"; DILineInfo lastLine; for (uint64_t Index = Start; Index < End; Index += Size) { MCInst Inst; if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, DebugOut, nulls())) { uint64_t SectAddress = 0; Sections[SectIdx].getAddress(SectAddress); outs() << format("%8" PRIx64 ":\t", SectAddress + Index); DumpBytes(StringRef(Bytes.data() + Index, Size)); IP->printInst(&Inst, outs(), ""); // Print debug info. if (diContext) { DILineInfo dli = diContext->getLineInfoForAddress(SectAddress + Index); // Print valid line info if it changed. if (dli != lastLine && dli.getLine() != 0) outs() << "\t## " << dli.getFileName() << ':' << dli.getLine() << ':' << dli.getColumn(); lastLine = dli; } outs() << "\n"; } else { errs() << "llvm-objdump: warning: invalid instruction encoding\n"; if (Size == 0) Size = 1; // skip illegible bytes } } } else { // Create CFG and use it for disassembly. StringRef SymName; Symbols[SymIdx].getName(SymName); createMCFunctionAndSaveCalls( SymName, DisAsm.get(), memoryObject, Start, End, InstrAnalysis.get(), Start, DebugOut, FunctionMap, Functions); } } if (!CFG && !symbolTableWorked) { // Reading the symbol table didn't work, disassemble the whole section. uint64_t SectAddress; Sections[SectIdx].getAddress(SectAddress); uint64_t SectSize; Sections[SectIdx].getSize(SectSize); uint64_t InstSize; for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { MCInst Inst; if (DisAsm->getInstruction(Inst, InstSize, memoryObject, Index, DebugOut, nulls())) { outs() << format("%8" PRIx64 ":\t", SectAddress + Index); DumpBytes(StringRef(Bytes.data() + Index, InstSize)); IP->printInst(&Inst, outs(), ""); outs() << "\n"; } else { errs() << "llvm-objdump: warning: invalid instruction encoding\n"; if (InstSize == 0) InstSize = 1; // skip illegible bytes } } } if (CFG) { if (!symbolTableWorked) { // Reading the symbol table didn't work, create a big __TEXT symbol. uint64_t SectSize = 0, SectAddress = 0; Sections[SectIdx].getSize(SectSize); Sections[SectIdx].getAddress(SectAddress); createMCFunctionAndSaveCalls("__TEXT", DisAsm.get(), memoryObject, 0, SectSize, InstrAnalysis.get(), SectAddress, DebugOut, FunctionMap, Functions); } for (std::map<uint64_t, MCFunction*>::iterator mi = FunctionMap.begin(), me = FunctionMap.end(); mi != me; ++mi) if (mi->second == 0) { // Create functions for the remaining callees we have gathered, // but we didn't find a name for them. uint64_t SectSize = 0; Sections[SectIdx].getSize(SectSize); SmallVector<uint64_t, 16> Calls; MCFunction f = MCFunction::createFunctionFromMC("unknown", DisAsm.get(), memoryObject, mi->first, SectSize, InstrAnalysis.get(), DebugOut, Calls); Functions.push_back(f); mi->second = &Functions.back(); for (unsigned i = 0, e = Calls.size(); i != e; ++i) { std::pair<uint64_t, MCFunction*> p(Calls[i], (MCFunction*)0); if (FunctionMap.insert(p).second) mi = FunctionMap.begin(); } } DenseSet<uint64_t> PrintedBlocks; for (unsigned ffi = 0, ffe = Functions.size(); ffi != ffe; ++ffi) { MCFunction &f = Functions[ffi]; for (MCFunction::iterator fi = f.begin(), fe = f.end(); fi != fe; ++fi){ if (!PrintedBlocks.insert(fi->first).second) continue; // We already printed this block. // We assume a block has predecessors when it's the first block after // a symbol. bool hasPreds = FunctionMap.find(fi->first) != FunctionMap.end(); // See if this block has predecessors. // FIXME: Slow. for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe; ++pi) if (pi->second.contains(fi->first)) { hasPreds = true; break; } uint64_t SectSize = 0, SectAddress; Sections[SectIdx].getSize(SectSize); Sections[SectIdx].getAddress(SectAddress); // No predecessors, this is a data block. Print as .byte directives. if (!hasPreds) { uint64_t End = llvm::next(fi) == fe ? SectSize : llvm::next(fi)->first; outs() << "# " << End-fi->first << " bytes of data:\n"; for (unsigned pos = fi->first; pos != End; ++pos) { outs() << format("%8x:\t", SectAddress + pos); DumpBytes(StringRef(Bytes.data() + pos, 1)); outs() << format("\t.byte 0x%02x\n", (uint8_t)Bytes[pos]); } continue; } if (fi->second.contains(fi->first)) // Print a header for simple loops outs() << "# Loop begin:\n"; DILineInfo lastLine; // Walk over the instructions and print them. for (unsigned ii = 0, ie = fi->second.getInsts().size(); ii != ie; ++ii) { const MCDecodedInst &Inst = fi->second.getInsts()[ii]; // If there's a symbol at this address, print its name. if (FunctionMap.find(SectAddress + Inst.Address) != FunctionMap.end()) outs() << FunctionMap[SectAddress + Inst.Address]-> getName() << ":\n"; outs() << format("%8" PRIx64 ":\t", SectAddress + Inst.Address); DumpBytes(StringRef(Bytes.data() + Inst.Address, Inst.Size)); if (fi->second.contains(fi->first)) // Indent simple loops. outs() << '\t'; IP->printInst(&Inst.Inst, outs(), ""); // Look for relocations inside this instructions, if there is one // print its target and additional information if available. for (unsigned j = 0; j != Relocs.size(); ++j) if (Relocs[j].first >= SectAddress + Inst.Address && Relocs[j].first < SectAddress + Inst.Address + Inst.Size) { StringRef SymName; uint64_t Addr; Relocs[j].second.getAddress(Addr); Relocs[j].second.getName(SymName); outs() << "\t# " << SymName << ' '; DumpAddress(Addr, Sections, MachOObj, outs()); } // If this instructions contains an address, see if we can evaluate // it and print additional information. uint64_t targ = InstrAnalysis->evaluateBranch(Inst.Inst, Inst.Address, Inst.Size); if (targ != -1ULL) DumpAddress(targ, Sections, MachOObj, outs()); // Print debug info. if (diContext) { DILineInfo dli = diContext->getLineInfoForAddress(SectAddress + Inst.Address); // Print valid line info if it changed. if (dli != lastLine && dli.getLine() != 0) outs() << "\t## " << dli.getFileName() << ':' << dli.getLine() << ':' << dli.getColumn(); lastLine = dli; } outs() << '\n'; } } emitDOTFile((f.getName().str() + ".dot").c_str(), f, IP.get()); } } } }
int main(int argc, char **argv){ // Load the bitcode cl::ParseCommandLineOptions(argc, argv, "helper_call_modifier\n"); SMDiagnostic Err; LLVMContext &Context = getGlobalContext(); Module *Mod = ParseIRFile(InputFile, Err, Context); if (!Mod) { Err.print(argv[0], errs()); exit(1); } /* * This iterates through the list of functions, copies/renames, and deletes * the original function. This is how we have to do it with the while loop * because of how the LLVM function list is implemented. */ Module::iterator i = Mod->begin(); while (i != Mod->end()){ Function *f = i; i++; Module *m = f->getParent(); assert(m); if (!f->isDeclaration()){ // internal functions only StringRef fname = f->getName(); if (!fname.compare("__ldb_mmu") || !fname.compare("__ldw_mmu") || !fname.compare("__ldl_mmu") || !fname.compare("__ldq_mmu") || !fname.compare("__stb_mmu") || !fname.compare("__stw_mmu") || !fname.compare("__stl_mmu") || !fname.compare("__stq_mmu")){ /* Replace LLVM memory functions with ASM panda (logging) memory * functions and delete original. For example, we want to call * out of the LLVM module to __ldb_mmu_panda(). */ Function *pandaFunc = m->getFunction(StringRef(f->getName().str() + "_panda")); assert(pandaFunc); if (!pandaFunc->isDeclaration()){ pandaFunc->deleteBody(); } f->replaceAllUsesWith(pandaFunc); f->eraseFromParent(); } else if (!fname.compare("slow_ldb_mmu") || !fname.compare("slow_ldw_mmu") || !fname.compare("slow_ldl_mmu") || !fname.compare("slow_ldq_mmu") || !fname.compare("slow_stb_mmu") || !fname.compare("slow_stw_mmu") || !fname.compare("slow_stl_mmu") || !fname.compare("slow_stq_mmu") || !fname.compare("slow_ldb_mmu_panda") || !fname.compare("slow_ldw_mmu_panda") || !fname.compare("slow_ldl_mmu_panda") || !fname.compare("slow_ldq_mmu_panda") || !fname.compare("slow_stb_mmu_panda") || !fname.compare("slow_stw_mmu_panda") || !fname.compare("slow_stl_mmu_panda") || !fname.compare("slow_stq_mmu_panda")){ /* These functions are just artifacts, and are only contained * within the previous functions. We want these deleted from * the LLVM module too, this is just kind of a hacky way to make * sure the functions are deleted in the right order without * making LLVM angry. */ if (f->hasNUsesOrMore(3)){ m->getFunctionList().remove(f); m->getFunctionList().push_back(f); continue; } else { f->eraseFromParent(); } } else { ValueToValueMapTy VMap; Function *newFunc = CloneFunction(f, VMap, false); std::string origName = f->getName(); std::string newName = origName.append("_llvm"); newFunc->setName(newName); /* * XXX: We need to remove stack smash protection from helper * functions that are to be compiled with the JIT. There is a bug * in LLVM 3.0 that causes the JIT to generate stack protection code * that causes the program to segfault. More information available * here: http://llvm.org/bugs/show_bug.cgi?id=11089 */ const AttributeSet AS = newFunc->getAttributes(); newFunc->setAttributes(AS.removeAttribute(newFunc->getContext(), AttributeSet::FunctionIndex, Attribute::StackProtectReq)); // push to the front so the iterator doesn't see them again m->getFunctionList().push_front(newFunc); f->replaceAllUsesWith(newFunc); f->eraseFromParent(); } } } // Verify the new bitcode and write it out, printing errors if necessary std::string errstring; verifyModule(*Mod, PrintMessageAction, &errstring); raw_fd_ostream *fstream = new raw_fd_ostream(OutputFile.c_str(), errstring); WriteBitcodeToFile(Mod, *fstream); printf("%s", errstring.c_str()); fstream->close(); return 0; }
bool operator>=(const StringRef strRef, const char* cstr) { return strRef.compare(StringRef(cstr)) >= 0; }
bool operator>=(const StringRef strRef1, const StringRef strRef2) { return strRef1.compare(strRef2) >= 0; }
bool operator<(const StringRef strRef1, const StringRef strRef2) { return strRef1.compare(strRef2) < 0; }
int SSPParser::getNextToken(void *Val) { YYSTYPE *Value = static_cast<YYSTYPE*>(Val); StringRef BufferData = Buf->getBuffer(); const char *Data = BufferData.data(); const char* CurCh = Data+CurPos; while (CurPos < BufferData.size() && (*CurCh == '\t' || *CurCh == ' ' || *CurCh == '\r' || *CurCh == '\n')) { CurPos++; CurCh = Data+CurPos; } if (CurPos >= BufferData.size()) return 0; // EOF if (*CurCh == '+') { CurPos++; return PLUS; } else if (*CurCh == '-') { CurPos++; return MINUS; } else if (*CurCh == '*') { CurPos++; return ASTERISK; } else if (*CurCh == '/') { CurPos++; return SLASH; } else if (*CurCh == '$') { CurPos++; return DOLLAR; } else if (*CurCh == '@') { CurPos++; return AT; } else if (IsAlpha(*CurCh)) { const char *Start = CurCh; size_t Length = 0; do { Length++; CurPos++; CurCh = Data+CurPos; } while (CurPos < BufferData.size() && (IsAlphaOrDigit(*CurCh) || *CurCh == '_')); StringRef *Str = new StringRef(Start, Length); // Check for keywords if (Str->compare("double") == 0) { return DOUBLE; } else if (Str->compare("field") == 0) { return FIELD; } else if (Str->compare("float") == 0) { return FLOAT; } else if (Str->compare("grid") == 0) { return GRID; } else if (Str->compare("in") == 0) { return IN; } else if (Str->compare("inout") == 0) { return INOUT; } else if (Str->compare("is") == 0) { return IS; } else if (Str->compare("let") == 0) { return LET; } else if (Str->compare("out") == 0) { return OUT; } else if (Str->compare("param") == 0) { return PARAM; } else if (Str->compare("program") == 0) { return PROGRAM; } // Not a keyword InternedStrings.push_back(Str); Value->Ident = Str; return IDENT; } else if (IsDigit(*CurCh)) { const char *Start = CurCh; size_t Length = 0; bool IsFloat = false; do { if (*CurCh == '.') IsFloat = true; Length++; CurPos++; CurCh = Data+CurPos; } while (CurPos < BufferData.size() && (IsDigit(*CurCh) || *CurCh == '.')); if (CurPos < BufferData.size() && (*CurCh == 'e' || *CurCh == 'E')) { // Start of an exponent IsFloat = true; CurPos++; CurCh = Data+CurPos; Length++; if (CurPos == BufferData.size() || (!IsDigit(*CurCh) && *CurCh != '-')) { SrcMgr.PrintMessage(SMLoc::getFromPointer(Data+CurPos), SourceMgr::DK_Error, "Missing exponent"); return 0; } if (*CurCh == '-') { Length++; CurPos++; CurCh = Data+CurPos; if (CurPos == BufferData.size() || !IsDigit(*CurCh)) { SrcMgr.PrintMessage(SMLoc::getFromPointer(Data+CurPos), SourceMgr::DK_Error, "Missing exponent"); return 0; } } do { Length++; CurPos++; CurCh = Data+CurPos; } while (CurPos < BufferData.size() && IsDigit(*CurCh)); } StringRef Str = StringRef(Start, Length); if (IsFloat) { APFloat DoubleValue = APFloat(APFloat::IEEEdouble, Str); Value->DoubleConst = DoubleValue.convertToDouble(); return DOUBLECONST; } else { long IntValue = atol(Str.data()); Value->IntConst = IntValue; return INTCONST; } } else if (*CurCh == '=') { CurPos++; return EQUALS; } else if (*CurCh == '(') { CurPos++; return OPENPARENS; } else if (*CurCh == ')') { CurPos++; return CLOSEPARENS; } else if (*CurCh == '[') { CurPos++; return OPENBRACE; } else if (*CurCh == ']') { CurPos++; return CLOSEBRACE; } else if (*CurCh == ',') { CurPos++; return COMMA; } else if (*CurCh == ':') { CurPos++; return COLON; } CurPos++; // If we get here, then we have no idea how to lex this! printError("Unknown symbol"); return 0; }
static void mergeInstrProfile(const WeightedFileVector &Inputs, StringRef OutputFilename, ProfileFormat OutputFormat, bool OutputSparse, unsigned NumThreads) { if (OutputFilename.compare("-") == 0) exitWithError("Cannot write indexed profdata format to stdout."); if (OutputFormat != PF_Binary && OutputFormat != PF_Text) exitWithError("Unknown format is specified."); std::error_code EC; raw_fd_ostream Output(OutputFilename.data(), EC, sys::fs::F_None); if (EC) exitWithErrorCode(EC, OutputFilename); std::mutex ErrorLock; SmallSet<instrprof_error, 4> WriterErrorCodes; // If NumThreads is not specified, auto-detect a good default. if (NumThreads == 0) NumThreads = std::max(1U, std::min(std::thread::hardware_concurrency(), unsigned(Inputs.size() / 2))); // Initialize the writer contexts. SmallVector<std::unique_ptr<WriterContext>, 4> Contexts; for (unsigned I = 0; I < NumThreads; ++I) Contexts.emplace_back(llvm::make_unique<WriterContext>( OutputSparse, ErrorLock, WriterErrorCodes)); if (NumThreads == 1) { for (const auto &Input : Inputs) loadInput(Input, Contexts[0].get()); } else { ThreadPool Pool(NumThreads); // Load the inputs in parallel (N/NumThreads serial steps). unsigned Ctx = 0; for (const auto &Input : Inputs) { Pool.async(loadInput, Input, Contexts[Ctx].get()); Ctx = (Ctx + 1) % NumThreads; } Pool.wait(); // Merge the writer contexts together (~ lg(NumThreads) serial steps). unsigned Mid = Contexts.size() / 2; unsigned End = Contexts.size(); assert(Mid > 0 && "Expected more than one context"); do { for (unsigned I = 0; I < Mid; ++I) Pool.async(mergeWriterContexts, Contexts[I].get(), Contexts[I + Mid].get()); Pool.wait(); if (End & 1) { Pool.async(mergeWriterContexts, Contexts[0].get(), Contexts[End - 1].get()); Pool.wait(); } End = Mid; Mid /= 2; } while (Mid > 0); } // Handle deferred hard errors encountered during merging. for (std::unique_ptr<WriterContext> &WC : Contexts) if (WC->Err) exitWithError(std::move(WC->Err), WC->ErrWhence); InstrProfWriter &Writer = Contexts[0]->Writer; if (OutputFormat == PF_Text) Writer.writeText(Output); else Writer.write(Output); }
void swift::ide::printSubmoduleInterface( Module *M, ArrayRef<StringRef> FullModuleName, Optional<StringRef> GroupName, ModuleTraversalOptions TraversalOptions, ASTPrinter &Printer, const PrintOptions &Options, const bool PrintSynthesizedExtensions) { auto AdjustedOptions = Options; adjustPrintOptions(AdjustedOptions); SmallVector<Decl *, 1> Decls; M->getDisplayDecls(Decls); auto &SwiftContext = M->getASTContext(); auto &Importer = static_cast<ClangImporter &>(*SwiftContext.getClangModuleLoader()); const clang::Module *InterestingClangModule = nullptr; SmallVector<ImportDecl *, 1> ImportDecls; llvm::DenseSet<const clang::Module *> ClangModulesForImports; SmallVector<Decl *, 1> SwiftDecls; llvm::DenseMap<const clang::Module *, SmallVector<std::pair<Decl *, clang::SourceLocation>, 1>> ClangDecls; // Drop top-level module name. FullModuleName = FullModuleName.slice(1); InterestingClangModule = M->findUnderlyingClangModule(); if (InterestingClangModule) { for (StringRef Name : FullModuleName) { InterestingClangModule = InterestingClangModule->findSubmodule(Name); if (!InterestingClangModule) return; } } else { assert(FullModuleName.empty()); } // If we're printing recursively, find all of the submodules to print. if (InterestingClangModule) { if (TraversalOptions) { SmallVector<const clang::Module *, 8> Worklist; SmallPtrSet<const clang::Module *, 8> Visited; Worklist.push_back(InterestingClangModule); Visited.insert(InterestingClangModule); while (!Worklist.empty()) { const clang::Module *CM = Worklist.pop_back_val(); if (!(TraversalOptions & ModuleTraversal::VisitHidden) && CM->IsExplicit) continue; ClangDecls.insert({ CM, {} }); // If we're supposed to visit submodules, add them now. if (TraversalOptions & ModuleTraversal::VisitSubmodules) { for (auto Sub = CM->submodule_begin(), SubEnd = CM->submodule_end(); Sub != SubEnd; ++Sub) { if (Visited.insert(*Sub).second) Worklist.push_back(*Sub); } } } } else { ClangDecls.insert({ InterestingClangModule, {} }); } } // Collect those submodules that are actually imported but have no import decls // in the module. llvm::SmallPtrSet<const clang::Module *, 16> NoImportSubModules; if (InterestingClangModule) { // Assume all submodules are missing. for (auto It =InterestingClangModule->submodule_begin(); It != InterestingClangModule->submodule_end(); It ++) { NoImportSubModules.insert(*It); } } // Separate the declarations that we are going to print into different // buckets. for (Decl *D : Decls) { // Skip declarations that are not accessible. if (auto *VD = dyn_cast<ValueDecl>(D)) { if (Options.AccessibilityFilter > Accessibility::Private && VD->hasAccessibility() && VD->getFormalAccess() < Options.AccessibilityFilter) continue; } auto ShouldPrintImport = [&](ImportDecl *ImportD) -> bool { if (!InterestingClangModule) return true; auto ClangMod = ImportD->getClangModule(); if (!ClangMod) return true; if (!ClangMod->isSubModule()) return true; if (ClangMod == InterestingClangModule) return false; // FIXME: const-ness on the clang API. return ClangMod->isSubModuleOf( const_cast<clang::Module*>(InterestingClangModule)); }; if (auto ID = dyn_cast<ImportDecl>(D)) { if (ShouldPrintImport(ID)) { if (ID->getClangModule()) // Erase those submodules that are not missing. NoImportSubModules.erase(ID->getClangModule()); if (ID->getImportKind() == ImportKind::Module) { // Make sure we don't print duplicate imports, due to getting imports // for both a clang module and its overlay. if (auto *ClangMod = getUnderlyingClangModuleForImport(ID)) { auto P = ClangModulesForImports.insert(ClangMod); bool IsNew = P.second; if (!IsNew) continue; } } ImportDecls.push_back(ID); } continue; } auto addToClangDecls = [&](Decl *D) { assert(D->hasClangNode()); auto CN = D->getClangNode(); clang::SourceLocation Loc = CN.getLocation(); auto *OwningModule = Importer.getClangOwningModule(CN); auto I = ClangDecls.find(OwningModule); if (I != ClangDecls.end()) { I->second.push_back({ D, Loc }); } }; if (D->hasClangNode()) { addToClangDecls(D); continue; } if (FullModuleName.empty()) { // If group name is given and the decl does not belong to the group, skip it. if (GroupName && (!D->getGroupName() || D->getGroupName().getValue() != GroupName.getValue())) continue; // Add Swift decls if we are printing the top-level module. SwiftDecls.push_back(D); } } // Create the missing import decls and add to the collector. for (auto *SM : NoImportSubModules) { ImportDecls.push_back(createImportDecl(M->getASTContext(), M, SM, {})); } auto &ClangSourceManager = Importer.getClangASTContext().getSourceManager(); // Sort imported declarations in source order *within a submodule*. for (auto &P : ClangDecls) { std::sort(P.second.begin(), P.second.end(), [&](std::pair<Decl *, clang::SourceLocation> LHS, std::pair<Decl *, clang::SourceLocation> RHS) -> bool { return ClangSourceManager.isBeforeInTranslationUnit(LHS.second, RHS.second); }); } // Sort Swift declarations so that we print them in a consistent order. std::sort(ImportDecls.begin(), ImportDecls.end(), [](ImportDecl *LHS, ImportDecl *RHS) -> bool { auto LHSPath = LHS->getFullAccessPath(); auto RHSPath = RHS->getFullAccessPath(); for (unsigned i = 0, e = std::min(LHSPath.size(), RHSPath.size()); i != e; i++) { if (int Ret = LHSPath[i].first.str().compare(RHSPath[i].first.str())) return Ret < 0; } return false; }); // If the group name is specified, we sort them according to their source order, // which is the order preserved by getTopLeveDecls. if (!GroupName) { std::sort(SwiftDecls.begin(), SwiftDecls.end(), [&](Decl *LHS, Decl *RHS) -> bool { auto *LHSValue = dyn_cast<ValueDecl>(LHS); auto *RHSValue = dyn_cast<ValueDecl>(RHS); if (LHSValue && RHSValue) { StringRef LHSName = LHSValue->getName().str(); StringRef RHSName = RHSValue->getName().str(); if (int Ret = LHSName.compare(RHSName)) return Ret < 0; // FIXME: this is not sufficient to establish a total order for overloaded // decls. return LHS->getKind() < RHS->getKind(); } return LHS->getKind() < RHS->getKind(); }); } ASTPrinter *PrinterToUse = &Printer; ClangCommentPrinter RegularCommentPrinter(Printer, Importer); if (Options.PrintRegularClangComments) PrinterToUse = &RegularCommentPrinter; auto PrintDecl = [&](Decl *D) -> bool { ASTPrinter &Printer = *PrinterToUse; if (!shouldPrint(D, AdjustedOptions)) { Printer.avoidPrintDeclPost(D); return false; } if (auto Ext = dyn_cast<ExtensionDecl>(D)) { // Clang extensions (categories) are always printed in source order. // Swift extensions are printed with their associated type unless it's // a cross-module extension. if (!Ext->hasClangNode()) { auto ExtendedNominal = Ext->getExtendedType()->getAnyNominal(); if (Ext->getModuleContext() == ExtendedNominal->getModuleContext()) return false; } } if (D->print(Printer, AdjustedOptions)) { Printer << "\n"; if (auto NTD = dyn_cast<NominalTypeDecl>(D)) { std::queue<NominalTypeDecl *> SubDecls{{NTD}}; while (!SubDecls.empty()) { auto NTD = SubDecls.front(); SubDecls.pop(); // Add sub-types of NTD. for (auto Sub : NTD->getMembers()) if (auto N = dyn_cast<NominalTypeDecl>(Sub)) SubDecls.push(N); // Print Ext and add sub-types of Ext. for (auto Ext : NTD->getExtensions()) { if (!shouldPrint(Ext, AdjustedOptions)) { Printer.avoidPrintDeclPost(Ext); continue; } if (Ext->hasClangNode()) continue; // will be printed in its source location, see above. Printer << "\n"; Ext->print(Printer, AdjustedOptions); Printer << "\n"; for (auto Sub : Ext->getMembers()) if (auto N = dyn_cast<NominalTypeDecl>(Sub)) SubDecls.push(N); } if (!PrintSynthesizedExtensions) continue; // Print synthesized extensions. llvm::SmallPtrSet<ExtensionDecl *, 10> ExtensionsFromConformances; findExtensionsFromConformingProtocols(D, ExtensionsFromConformances); AdjustedOptions.initArchetypeTransformerForSynthesizedExtensions(NTD); for (auto ET : ExtensionsFromConformances) { if (!shouldPrint(ET, AdjustedOptions)) continue; Printer << "\n"; Printer << "/// Synthesized extension from "; ET->getExtendedTypeLoc().getType().print(Printer, AdjustedOptions); Printer << "\n"; ET->print(Printer, AdjustedOptions); Printer << "\n"; } AdjustedOptions.clearArchetypeTransformerForSynthesizedExtensions(); } } return true; } return false; }; // Imports from the stdlib are internal details that don't need to be exposed. if (!M->isStdlibModule()) { for (auto *D : ImportDecls) PrintDecl(D); Printer << "\n"; } { using ModuleAndName = std::pair<const clang::Module *, std::string>; SmallVector<ModuleAndName, 8> ClangModules; for (auto P : ClangDecls) { ClangModules.push_back({ P.first, P.first->getFullModuleName() }); } // Sort modules by name. std::sort(ClangModules.begin(), ClangModules.end(), [](const ModuleAndName &LHS, const ModuleAndName &RHS) -> bool { return LHS.second < RHS.second; }); for (auto CM : ClangModules) { for (auto DeclAndLoc : ClangDecls[CM.first]) PrintDecl(DeclAndLoc.first); } } if (!(TraversalOptions & ModuleTraversal::SkipOverlay) || !InterestingClangModule) { for (auto *D : SwiftDecls) { if (PrintDecl(D)) Printer << "\n"; } } }
void ObjectLoadListener::recordRelocations( const ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &L) { for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { section_iterator Section = SI->getRelocatedSection(); if (Section == SE) { continue; } StringRef SectionName; std::error_code ErrorCode = Section->getName(SectionName); if (ErrorCode) { assert(false && ErrorCode.message().c_str()); } if (SectionName.startswith(".debug") || SectionName.startswith(".rela.debug") || !SectionName.compare(".pdata") || SectionName.startswith(".eh_frame") || SectionName.startswith(".rela.eh_frame")) { // Skip sections whose contents are not directly reported to the EE continue; } relocation_iterator I = SI->relocation_begin(); relocation_iterator E = SI->relocation_end(); for (; I != E; ++I) { symbol_iterator Symbol = I->getSymbol(); assert(Symbol != Obj.symbol_end()); ErrorOr<section_iterator> SymbolSectionOrErr = Symbol->getSection(); assert(!SymbolSectionOrErr.getError()); object::section_iterator SymbolSection = *SymbolSectionOrErr; const bool IsExtern = SymbolSection == Obj.section_end(); uint64_t RelType = I->getType(); uint64_t Offset = I->getOffset(); uint8_t *RelocationTarget = nullptr; if (IsExtern) { // This is an external symbol. Verify that it's one we created for // a global variable and report the relocation via Jit interface. ErrorOr<StringRef> NameOrError = Symbol->getName(); assert(NameOrError); StringRef TargetName = NameOrError.get(); assert(Context->NameToHandleMap.count(TargetName) == 1); RelocationTarget = (uint8_t *)Context->NameToHandleMap[TargetName]; } else { RelocationTarget = (uint8_t *)(L.getSectionLoadAddress(*SymbolSection) + Symbol->getValue()); } uint64_t Addend = 0; uint64_t EERelType = getRelocationType(RelType); uint64_t SectionAddress = L.getSectionLoadAddress(*Section); assert(SectionAddress != 0); uint8_t *FixupAddress = (uint8_t *)(SectionAddress + Offset); if (Obj.isELF()) { // Addend is part of the relocation ELFRelocationRef ElfReloc(*I); ErrorOr<uint64_t> ElfAddend = ElfReloc.getAddend(); assert(!ElfAddend.getError()); Addend = ElfAddend.get(); } else { // Addend is read from the location to be fixed up Addend = getRelocationAddend(RelType, FixupAddress); } Context->JitInfo->recordRelocation(FixupAddress, RelocationTarget + Addend, EERelType); } } }
inline bool ends_with(const StringRef& input, const StringRef& target) { return input.length() >= target.length() && input.compare(input.length() - target.length(), target.length(), target) == 0; }