mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	Profile: Add a library for the instrumentation based profiling format
This provides a library to work with the instrumentation based profiling format that is used by clang's -fprofile-instr-* options and by the llvm-profdata tool. This is a binary format, rather than the textual one that's currently in use. The tests are in the subsequent commits that use this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203703 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		
							
								
								
									
										55
									
								
								include/llvm/Profile/ProfileData.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								include/llvm/Profile/ProfileData.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| //=-- ProfileData.h - Instrumented profiling format support -------*- C++ -*-=// | ||||
| // | ||||
| //                     The LLVM Compiler Infrastructure | ||||
| // | ||||
| // This file is distributed under the University of Illinois Open Source | ||||
| // License. See LICENSE.TXT for details. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
| // | ||||
| // This file contains support for instrumentation based PGO and coverage. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
|  | ||||
| #ifndef LLVM_PROFILE_PROFILEDATA_H__ | ||||
| #define LLVM_PROFILE_PROFILEDATA_H__ | ||||
|  | ||||
| #include "llvm/Support/DataTypes.h" | ||||
| #include "llvm/Support/system_error.h" | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| namespace llvm { | ||||
|  | ||||
| const char PROFILEDATA_MAGIC[4] = {'L', 'P', 'R', 'F'}; | ||||
| const uint32_t PROFILEDATA_VERSION = 1; | ||||
|  | ||||
| const error_category &profiledata_category(); | ||||
|  | ||||
| struct profiledata_error { | ||||
|   enum ErrorType { | ||||
|     success = 0, | ||||
|     bad_magic, | ||||
|     unsupported_version, | ||||
|     too_large, | ||||
|     truncated, | ||||
|     malformed, | ||||
|     unknown_function | ||||
|   }; | ||||
|   ErrorType V; | ||||
|  | ||||
|   profiledata_error(ErrorType V) : V(V) {} | ||||
|   operator ErrorType() const { return V; } | ||||
| }; | ||||
|  | ||||
| inline error_code make_error_code(profiledata_error E) { | ||||
|   return error_code(static_cast<int>(E), profiledata_category()); | ||||
| } | ||||
|  | ||||
| template <> struct is_error_code_enum<profiledata_error> : std::true_type {}; | ||||
| template <> struct is_error_code_enum<profiledata_error::ErrorType> | ||||
|   : std::true_type {}; | ||||
|  | ||||
| } // end namespace llvm | ||||
|  | ||||
| #endif // LLVM_PROFILE_PROFILEDATA_H__ | ||||
							
								
								
									
										93
									
								
								include/llvm/Profile/ProfileDataReader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								include/llvm/Profile/ProfileDataReader.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| //=-- ProfileDataReader.h - Instrumented profiling reader ---------*- C++ -*-=// | ||||
| // | ||||
| //                     The LLVM Compiler Infrastructure | ||||
| // | ||||
| // This file is distributed under the University of Illinois Open Source | ||||
| // License. See LICENSE.TXT for details. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
| // | ||||
| // This file contains support for reading profiling data for instrumentation | ||||
| // based PGO and coverage. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
|  | ||||
| #ifndef LLVM_PROFILE_PROFILEDATA_READER_H__ | ||||
| #define LLVM_PROFILE_PROFILEDATA_READER_H__ | ||||
|  | ||||
| #include "llvm/ADT/StringMap.h" | ||||
| #include "llvm/Support/Compiler.h" | ||||
| #include "llvm/Support/DataTypes.h" | ||||
| #include "llvm/Support/ErrorOr.h" | ||||
| #include "llvm/Support/MemoryBuffer.h" | ||||
| #include "llvm/Support/raw_ostream.h" | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| namespace llvm { | ||||
|  | ||||
| class ProfileDataCursor; | ||||
|  | ||||
| /// Reader for the profile data that is used for instrumentation based PGO. | ||||
| class ProfileDataReader { | ||||
| private: | ||||
|   /// The profile data file contents. | ||||
|   std::unique_ptr<MemoryBuffer> DataBuffer; | ||||
|   /// Offsets into DataBuffer for each function's counters. | ||||
|   StringMap<uint32_t> DataOffsets; | ||||
|   /// The maximal execution count among all functions. | ||||
|   uint64_t MaxFunctionCount; | ||||
|  | ||||
|   ProfileDataReader(const ProfileDataReader &) LLVM_DELETED_FUNCTION; | ||||
|   ProfileDataReader &operator=(const ProfileDataReader &) LLVM_DELETED_FUNCTION; | ||||
| protected: | ||||
|   ProfileDataReader(std::unique_ptr<MemoryBuffer> &DataBuffer) | ||||
|       : DataBuffer(DataBuffer.release()) {} | ||||
|  | ||||
|   /// Populate internal state using the profile data's index | ||||
|   error_code readIndex(); | ||||
| public: | ||||
|  | ||||
|   class name_iterator { | ||||
|     typedef StringMap<unsigned>::const_iterator IterTy; | ||||
|     IterTy Ix; | ||||
|   public: | ||||
|     explicit name_iterator(const IterTy &Ix) : Ix(Ix) {} | ||||
|  | ||||
|     StringRef operator*() const { return Ix->getKey(); } | ||||
|  | ||||
|     bool operator==(const name_iterator &RHS) const { return Ix == RHS.Ix; } | ||||
|     bool operator!=(const name_iterator &RHS) const { return Ix != RHS.Ix; } | ||||
|  | ||||
|     inline name_iterator& operator++() { ++Ix; return *this; } | ||||
|   }; | ||||
|  | ||||
|   /// Iterators over the names of indexed items | ||||
|   name_iterator begin() const { | ||||
|     return name_iterator(DataOffsets.begin()); | ||||
|   } | ||||
|   name_iterator end() const { | ||||
|     return name_iterator(DataOffsets.end()); | ||||
|   } | ||||
|  | ||||
| private: | ||||
|   error_code findFunctionCounts(StringRef FuncName, uint64_t &FunctionHash, | ||||
|                                 ProfileDataCursor &Cursor); | ||||
| public: | ||||
|   /// The number of profiled functions | ||||
|   size_t numProfiledFunctions() { return DataOffsets.size(); } | ||||
|   /// Fill Counts with the profile data for the given function name. | ||||
|   error_code getFunctionCounts(StringRef FuncName, uint64_t &FunctionHash, | ||||
|                                std::vector<uint64_t> &Counts); | ||||
|   /// Get the frequency with which a function is called relative to the function | ||||
|   /// that is called most often in the program. | ||||
|   error_code getCallFrequency(StringRef FuncName, uint64_t &FunctionHash, | ||||
|                               double &F); | ||||
|  | ||||
|   static error_code create(std::string Path, | ||||
|                            std::unique_ptr<ProfileDataReader> &Result); | ||||
| }; | ||||
|  | ||||
| } // end namespace llvm | ||||
|  | ||||
| #endif // LLVM_PROFILE_PROFILEDATA_READER_H__ | ||||
							
								
								
									
										54
									
								
								include/llvm/Profile/ProfileDataWriter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								include/llvm/Profile/ProfileDataWriter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| //=-- ProfileDataWriter.h - Instrumented profiling writer ---------*- C++ -*-=// | ||||
| // | ||||
| //                     The LLVM Compiler Infrastructure | ||||
| // | ||||
| // This file is distributed under the University of Illinois Open Source | ||||
| // License. See LICENSE.TXT for details. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
| // | ||||
| // This file contains support for writing profiling data for instrumentation | ||||
| // based PGO and coverage. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
|  | ||||
| #ifndef LLVM_PROFILE_PROFILEDATA_WRITER_H__ | ||||
| #define LLVM_PROFILE_PROFILEDATA_WRITER_H__ | ||||
|  | ||||
| #include "llvm/ADT/StringMap.h" | ||||
| #include "llvm/Support/DataTypes.h" | ||||
| #include "llvm/Support/raw_ostream.h" | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| namespace llvm { | ||||
|  | ||||
| struct __attribute__((packed)) ProfileDataHeader { | ||||
|   char     Magic[4]; | ||||
|   uint32_t Version; | ||||
|   uint32_t DataStart; | ||||
|   uint32_t Padding; | ||||
|   uint64_t MaxFunctionCount; | ||||
| }; | ||||
|  | ||||
| /// Writer for instrumentation based profile data | ||||
| class ProfileDataWriter { | ||||
|   StringMap<size_t> FunctionOffsets; | ||||
|   std::vector<uint64_t> FunctionData; | ||||
|   uint32_t DataStart; | ||||
|   uint64_t MaxFunctionCount; | ||||
|  | ||||
|   void write32(raw_ostream &OS, uint32_t Value); | ||||
|   void write64(raw_ostream &OS, uint64_t Value); | ||||
| public: | ||||
|   ProfileDataWriter() | ||||
|       : DataStart(sizeof(ProfileDataHeader)), MaxFunctionCount(0) {} | ||||
|  | ||||
|   void addFunctionCounts(StringRef FuncName, uint64_t FunctionHash, | ||||
|                          uint64_t NumCounters, const uint64_t *Counters); | ||||
|   void write(raw_ostream &OS); | ||||
| }; | ||||
|  | ||||
| } // end namespace llvm | ||||
|  | ||||
| #endif // LLVM_PROFILE_PROFILEDATA_WRITER_H__ | ||||
| @@ -16,3 +16,4 @@ add_subdirectory(ExecutionEngine) | ||||
| add_subdirectory(Target) | ||||
| add_subdirectory(AsmParser) | ||||
| add_subdirectory(LineEditor) | ||||
| add_subdirectory(Profile) | ||||
|   | ||||
| @@ -16,7 +16,7 @@ | ||||
| ;===------------------------------------------------------------------------===; | ||||
|  | ||||
| [common] | ||||
| subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine LineEditor Linker IR IRReader LTO MC Object Option Support TableGen Target Transforms | ||||
| subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine LineEditor Linker IR IRReader LTO MC Object Option Profile Support TableGen Target Transforms | ||||
|  | ||||
| [component_0] | ||||
| type = Group | ||||
|   | ||||
| @@ -12,6 +12,6 @@ include $(LEVEL)/Makefile.config | ||||
|  | ||||
| PARALLEL_DIRS := IR AsmParser Bitcode Analysis Transforms CodeGen Target \ | ||||
|                  ExecutionEngine Linker LTO MC Object Option DebugInfo   \ | ||||
|                  IRReader LineEditor | ||||
|                  IRReader LineEditor Profile | ||||
|  | ||||
| include $(LEVEL)/Makefile.common | ||||
|   | ||||
							
								
								
									
										5
									
								
								lib/Profile/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								lib/Profile/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| add_llvm_library(LLVMProfile | ||||
|   ProfileData.cpp | ||||
|   ProfileDataReader.cpp | ||||
|   ProfileDataWriter.cpp | ||||
|   ) | ||||
							
								
								
									
										21
									
								
								lib/Profile/LLVMBuild.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								lib/Profile/LLVMBuild.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| ;===- ./lib/Profile/LLVMBuild.txt ------------------------------*- Conf -*--===; | ||||
| ; | ||||
| ;                     The LLVM Compiler Infrastructure | ||||
| ; | ||||
| ; This file is distributed under the University of Illinois Open Source | ||||
| ; License. See LICENSE.TXT for details. | ||||
| ; | ||||
| ;===------------------------------------------------------------------------===; | ||||
| ; | ||||
| ; This is an LLVMBuild description file for the components in this subdirectory. | ||||
| ; | ||||
| ; For more information on the LLVMBuild system, please see: | ||||
| ; | ||||
| ;   http://llvm.org/docs/LLVMBuild.html | ||||
| ; | ||||
| ;===------------------------------------------------------------------------===; | ||||
|  | ||||
| [component_0] | ||||
| type = Library | ||||
| name = Profile | ||||
| parent = Libraries | ||||
							
								
								
									
										14
									
								
								lib/Profile/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								lib/Profile/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| ##===- lib/Profile/Makefile --------------------------------*- Makefile -*-===## | ||||
| # | ||||
| #                     The LLVM Compiler Infrastructure | ||||
| # | ||||
| # This file is distributed under the University of Illinois Open Source | ||||
| # License. See LICENSE.TXT for details. | ||||
| # | ||||
| ##===----------------------------------------------------------------------===## | ||||
|  | ||||
| LEVEL = ../.. | ||||
| LIBRARYNAME = LLVMProfile | ||||
| BUILD_ARCHIVE := 1 | ||||
|  | ||||
| include $(LEVEL)/Makefile.common | ||||
							
								
								
									
										54
									
								
								lib/Profile/ProfileData.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								lib/Profile/ProfileData.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| //=-- ProfileData.cpp - Instrumented profiling format support ---------------=// | ||||
| // | ||||
| //                     The LLVM Compiler Infrastructure | ||||
| // | ||||
| // This file is distributed under the University of Illinois Open Source | ||||
| // License. See LICENSE.TXT for details. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
| // | ||||
| // This file contains support for clang's instrumentation based PGO and | ||||
| // coverage. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
|  | ||||
| #include "llvm/Profile/ProfileData.h" | ||||
| #include "llvm/Support/ErrorHandling.h" | ||||
|  | ||||
| using namespace llvm; | ||||
|  | ||||
| namespace { | ||||
| class ProfileDataErrorCategoryType : public _do_message { | ||||
|   const char *name() const override { return "llvm.profiledata"; } | ||||
|   std::string message(int IE) const { | ||||
|     profiledata_error::ErrorType E = | ||||
|         static_cast<profiledata_error::ErrorType>(IE); | ||||
|     switch (E) { | ||||
|     case profiledata_error::success: return "Success"; | ||||
|     case profiledata_error::bad_magic: | ||||
|       return "Invalid file format (bad magic)"; | ||||
|     case profiledata_error::unsupported_version: | ||||
|       return "Unsupported format version"; | ||||
|     case profiledata_error::too_large: | ||||
|       return "Too much profile data"; | ||||
|     case profiledata_error::truncated: | ||||
|       return "Truncated profile data"; | ||||
|     case profiledata_error::malformed: | ||||
|       return "Malformed profile data"; | ||||
|     case profiledata_error::unknown_function: | ||||
|       return "No profile data available for function"; | ||||
|     } | ||||
|     llvm_unreachable("A value of profiledata_error has no message."); | ||||
|   } | ||||
|   error_condition default_error_condition(int EV) const { | ||||
|     if (EV == profiledata_error::success) | ||||
|       return errc::success; | ||||
|     return errc::invalid_argument; | ||||
|   } | ||||
| }; | ||||
| } | ||||
|  | ||||
| const error_category &llvm::profiledata_category() { | ||||
|   static ProfileDataErrorCategoryType C; | ||||
|   return C; | ||||
| } | ||||
							
								
								
									
										183
									
								
								lib/Profile/ProfileDataReader.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								lib/Profile/ProfileDataReader.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,183 @@ | ||||
| //=-- ProfileDataReader.cpp - Instrumented profiling reader -----------------=// | ||||
| // | ||||
| //                     The LLVM Compiler Infrastructure | ||||
| // | ||||
| // This file is distributed under the University of Illinois Open Source | ||||
| // License. See LICENSE.TXT for details. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
| // | ||||
| // This file contains support for reading profiling data for clang's | ||||
| // instrumentation based PGO and coverage. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
|  | ||||
| #include "llvm/Profile/ProfileDataReader.h" | ||||
| #include "llvm/Profile/ProfileData.h" | ||||
| #include "llvm/Support/Endian.h" | ||||
|  | ||||
| #include <cassert> | ||||
|  | ||||
| using namespace llvm; | ||||
|  | ||||
| error_code ProfileDataReader::create( | ||||
|     std::string Path, std::unique_ptr<ProfileDataReader> &Result) { | ||||
|   std::unique_ptr<MemoryBuffer> Buffer; | ||||
|   if (error_code EC = MemoryBuffer::getFileOrSTDIN(Path, Buffer)) | ||||
|     return EC; | ||||
|  | ||||
|   if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max()) | ||||
|     return profiledata_error::too_large; | ||||
|  | ||||
|   Result.reset(new ProfileDataReader(Buffer)); | ||||
|   if (error_code EC = Result->readIndex()) | ||||
|     return EC; | ||||
|   return profiledata_error::success; | ||||
| } | ||||
|  | ||||
| class llvm::ProfileDataCursor { | ||||
|   const char *Start; | ||||
|   const char *Next; | ||||
|   const char *End; | ||||
|  | ||||
|   error_code skip(unsigned bytes) { | ||||
|     if (Next + bytes > End) | ||||
|       return profiledata_error::malformed; | ||||
|     Next += bytes; | ||||
|     return profiledata_error::success; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   error_code read(T &Result) { | ||||
|     typedef support::detail::packed_endian_specific_integral | ||||
|         <T, support::little, support::unaligned> Endian_t; | ||||
|     const char *Prev = Next; | ||||
|     if (error_code EC = skip(sizeof(T))) | ||||
|       return EC; | ||||
|     Result = *reinterpret_cast<const Endian_t*>(Prev); | ||||
|     return profiledata_error::success; | ||||
|   } | ||||
| public: | ||||
|   ProfileDataCursor(const MemoryBuffer *Buf) | ||||
|       : Start(Buf->getBufferStart()), Next(Start), End(Buf->getBufferEnd()) {} | ||||
|   bool offsetReached(size_t Offset) { return Start + Offset <= Next; } | ||||
|   bool offsetInBounds(size_t Offset) { return Start + Offset < End; } | ||||
|  | ||||
|   error_code skipToOffset(size_t Offset) { | ||||
|     if (!offsetInBounds(Offset)) | ||||
|       return profiledata_error::malformed; | ||||
|     Next = Start + Offset; | ||||
|     return profiledata_error::success; | ||||
|   } | ||||
|  | ||||
|   error_code skip32() { return skip(4); } | ||||
|   error_code skip64() { return skip(8); } | ||||
|   error_code read32(uint32_t &Result) { return read<uint32_t>(Result); } | ||||
|   error_code read64(uint64_t &Result) { return read<uint64_t>(Result); } | ||||
|  | ||||
|   error_code readChars(StringRef &Result, uint32_t Len) { | ||||
|     error_code EC; | ||||
|     const char *Prev = Next; | ||||
|     if (error_code EC = skip(Len)) | ||||
|       return EC; | ||||
|     Result = StringRef(Prev, Len); | ||||
|     return profiledata_error::success; | ||||
|   } | ||||
|   error_code readString(StringRef &Result) { | ||||
|     uint32_t Len; | ||||
|     if (error_code EC = read32(Len)) | ||||
|       return EC; | ||||
|     return readChars(Result, Len); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| error_code ProfileDataReader::readIndex() { | ||||
|   ProfileDataCursor Cursor(DataBuffer.get()); | ||||
|   error_code EC; | ||||
|   StringRef Magic; | ||||
|   uint32_t Version, IndexEnd, DataStart; | ||||
|  | ||||
|   if ((EC = Cursor.readChars(Magic, 4))) | ||||
|     return EC; | ||||
|   if (StringRef(PROFILEDATA_MAGIC, 4) != Magic) | ||||
|     return profiledata_error::bad_magic; | ||||
|   if ((EC = Cursor.read32(Version))) | ||||
|     return EC; | ||||
|   if (Version != PROFILEDATA_VERSION) | ||||
|     return profiledata_error::unsupported_version; | ||||
|   if ((EC = Cursor.read32(IndexEnd))) | ||||
|     return EC; | ||||
|   if ((EC = Cursor.skip32())) | ||||
|     return EC; | ||||
|   if ((EC = Cursor.read64(MaxFunctionCount))) | ||||
|     return EC; | ||||
|  | ||||
|   DataStart = IndexEnd + (sizeof(uint64_t) - IndexEnd % sizeof(uint64_t)); | ||||
|   while (!Cursor.offsetReached(IndexEnd)) { | ||||
|     StringRef FuncName; | ||||
|     uint32_t Offset, TotalOffset; | ||||
|     if ((EC = Cursor.readString(FuncName))) | ||||
|       return EC; | ||||
|     if ((EC = Cursor.read32(Offset))) | ||||
|       return EC; | ||||
|     TotalOffset = DataStart + Offset; | ||||
|     if (!Cursor.offsetInBounds(TotalOffset)) | ||||
|       return profiledata_error::truncated; | ||||
|     DataOffsets[FuncName] = TotalOffset; | ||||
|   } | ||||
|  | ||||
|   return profiledata_error::success; | ||||
| } | ||||
|  | ||||
| error_code ProfileDataReader::findFunctionCounts(StringRef FuncName, | ||||
|                                                  uint64_t &FunctionHash, | ||||
|                                                  ProfileDataCursor &Cursor) { | ||||
|   error_code EC; | ||||
|   // Find the relevant section of the pgo-data file. | ||||
|   const auto &OffsetIter = DataOffsets.find(FuncName); | ||||
|   if (OffsetIter == DataOffsets.end()) | ||||
|     return profiledata_error::unknown_function; | ||||
|   // Go there and read the function data | ||||
|   if ((EC = Cursor.skipToOffset(OffsetIter->getValue()))) | ||||
|     return EC; | ||||
|   if ((EC = Cursor.read64(FunctionHash))) | ||||
|     return EC; | ||||
|   return profiledata_error::success; | ||||
| } | ||||
|  | ||||
| error_code ProfileDataReader::getFunctionCounts(StringRef FuncName, | ||||
|                                                 uint64_t &FunctionHash, | ||||
|                                                 std::vector<uint64_t> &Counts) { | ||||
|   ProfileDataCursor Cursor(DataBuffer.get()); | ||||
|   error_code EC; | ||||
|   if ((EC = findFunctionCounts(FuncName, FunctionHash, Cursor))) | ||||
|     return EC; | ||||
|  | ||||
|   uint64_t NumCounters; | ||||
|   if ((EC = Cursor.read64(NumCounters))) | ||||
|     return EC; | ||||
|   for (uint64_t I = 0; I < NumCounters; ++I) { | ||||
|     uint64_t Count; | ||||
|     if ((EC = Cursor.read64(Count))) | ||||
|       return EC; | ||||
|     Counts.push_back(Count); | ||||
|   } | ||||
|  | ||||
|   return profiledata_error::success; | ||||
| } | ||||
|  | ||||
| error_code ProfileDataReader::getCallFrequency(StringRef FuncName, | ||||
|                                                uint64_t &FunctionHash, | ||||
|                                                double &Frequency) { | ||||
|   ProfileDataCursor Cursor(DataBuffer.get()); | ||||
|   error_code EC; | ||||
|   if ((EC = findFunctionCounts(FuncName, FunctionHash, Cursor))) | ||||
|     return EC; | ||||
|   if ((EC = Cursor.skip64())) | ||||
|     return EC; | ||||
|   uint64_t CallCount; | ||||
|   if ((EC = Cursor.read64(CallCount))) | ||||
|     return EC; | ||||
|   Frequency = CallCount / (double)MaxFunctionCount; | ||||
|   return profiledata_error::success; | ||||
| } | ||||
							
								
								
									
										71
									
								
								lib/Profile/ProfileDataWriter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								lib/Profile/ProfileDataWriter.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| //=-- ProfileDataWriter.cpp - Instrumented profiling writer -----------------=// | ||||
| // | ||||
| //                     The LLVM Compiler Infrastructure | ||||
| // | ||||
| // This file is distributed under the University of Illinois Open Source | ||||
| // License. See LICENSE.TXT for details. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
| // | ||||
| // This file contains support for writing profiling data for clang's | ||||
| // instrumentation based PGO and coverage. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
|  | ||||
| #include "llvm/Profile/ProfileDataWriter.h" | ||||
| #include "llvm/Profile/ProfileData.h" | ||||
| #include "llvm/Support/Endian.h" | ||||
|  | ||||
| using namespace llvm; | ||||
|  | ||||
| template <typename T> | ||||
| struct LEBytes { | ||||
|   const T &Data; | ||||
|   LEBytes(const T &Data) : Data(Data) {} | ||||
|   void print(raw_ostream &OS) const { | ||||
|     for (uint32_t Shift = 0; Shift < sizeof(Data); ++Shift) | ||||
|       OS << (char)((Data >> (8 * Shift)) & 0xFF); | ||||
|   } | ||||
| }; | ||||
| template <typename T> | ||||
| static raw_ostream &operator<<(raw_ostream &OS, const LEBytes<T> &Bytes) { | ||||
|   Bytes.print(OS); | ||||
|   return OS; | ||||
| } | ||||
|  | ||||
| void ProfileDataWriter::addFunctionCounts(StringRef FuncName, | ||||
|                                           uint64_t FunctionHash, | ||||
|                                           uint64_t NumCounters, | ||||
|                                           const uint64_t *Counters) { | ||||
|   DataStart += 2 * sizeof(uint32_t) + FuncName.size(); | ||||
|   FunctionOffsets[FuncName] = FunctionData.size() * sizeof(uint64_t); | ||||
|   FunctionData.push_back(FunctionHash); | ||||
|   FunctionData.push_back(NumCounters); | ||||
|   assert(NumCounters > 0 && "Function call counter missing!"); | ||||
|   if (Counters[0] > MaxFunctionCount) | ||||
|     MaxFunctionCount = Counters[0]; | ||||
|   for (uint64_t I = 0; I < NumCounters; ++I) | ||||
|     FunctionData.push_back(Counters[I]); | ||||
| } | ||||
|  | ||||
| void ProfileDataWriter::write(raw_ostream &OS) { | ||||
|   for (char C : PROFILEDATA_MAGIC) | ||||
|     OS << C; | ||||
|   OS << LEBytes<uint32_t>(PROFILEDATA_VERSION); | ||||
|   OS << LEBytes<uint32_t>(DataStart); | ||||
|   OS << LEBytes<uint32_t>(0); | ||||
|   OS << LEBytes<uint64_t>(MaxFunctionCount); | ||||
|  | ||||
|   for (const auto &I : FunctionOffsets) { | ||||
|     StringRef Name = I.getKey(); | ||||
|     OS << LEBytes<uint32_t>(Name.size()); | ||||
|     OS << Name; | ||||
|     OS << LEBytes<uint32_t>(I.getValue()); | ||||
|   } | ||||
|  | ||||
|   for (unsigned I = 0; I < sizeof(uint64_t) - DataStart % sizeof(uint64_t); ++I) | ||||
|     OS << '\0'; | ||||
|  | ||||
|   for (uint64_t Value : FunctionData) | ||||
|     OS << LEBytes<uint64_t>(Value); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user