19bb55568SKyungwoo Lee //===-- CodeGenData.cpp ---------------------------------------------------===// 29bb55568SKyungwoo Lee // 39bb55568SKyungwoo Lee // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49bb55568SKyungwoo Lee // See https://llvm.org/LICENSE.txt for license information. 59bb55568SKyungwoo Lee // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69bb55568SKyungwoo Lee // 79bb55568SKyungwoo Lee //===----------------------------------------------------------------------===// 89bb55568SKyungwoo Lee // 99bb55568SKyungwoo Lee // This file contains support for codegen data that has stable summary which 109bb55568SKyungwoo Lee // can be used to optimize the code in the subsequent codegen. 119bb55568SKyungwoo Lee // 129bb55568SKyungwoo Lee //===----------------------------------------------------------------------===// 139bb55568SKyungwoo Lee 149bb55568SKyungwoo Lee #include "llvm/Bitcode/BitcodeWriter.h" 159bb55568SKyungwoo Lee #include "llvm/CGData/CodeGenDataReader.h" 169bb55568SKyungwoo Lee #include "llvm/CGData/OutlinedHashTreeRecord.h" 179bb55568SKyungwoo Lee #include "llvm/Object/ObjectFile.h" 18*dc85d526SKyungwoo Lee #include "llvm/Support/Caching.h" 199bb55568SKyungwoo Lee #include "llvm/Support/CommandLine.h" 209bb55568SKyungwoo Lee #include "llvm/Support/FileSystem.h" 21*dc85d526SKyungwoo Lee #include "llvm/Support/Path.h" 229bb55568SKyungwoo Lee #include "llvm/Support/WithColor.h" 239bb55568SKyungwoo Lee 249bb55568SKyungwoo Lee #define DEBUG_TYPE "cg-data" 259bb55568SKyungwoo Lee 269bb55568SKyungwoo Lee using namespace llvm; 279bb55568SKyungwoo Lee using namespace cgdata; 289bb55568SKyungwoo Lee 290f525452SKyungwoo Lee cl::opt<bool> 300f525452SKyungwoo Lee CodeGenDataGenerate("codegen-data-generate", cl::init(false), cl::Hidden, 310f525452SKyungwoo Lee cl::desc("Emit CodeGen Data into custom sections")); 320f525452SKyungwoo Lee cl::opt<std::string> 330f525452SKyungwoo Lee CodeGenDataUsePath("codegen-data-use-path", cl::init(""), cl::Hidden, 340f525452SKyungwoo Lee cl::desc("File path to where .cgdata file is read")); 35*dc85d526SKyungwoo Lee cl::opt<bool> CodeGenDataThinLTOTwoRounds( 36*dc85d526SKyungwoo Lee "codegen-data-thinlto-two-rounds", cl::init(false), cl::Hidden, 37*dc85d526SKyungwoo Lee cl::desc("Enable two-round ThinLTO code generation. The first round " 38*dc85d526SKyungwoo Lee "emits codegen data, while the second round uses the emitted " 39*dc85d526SKyungwoo Lee "codegen data for further optimizations.")); 400f525452SKyungwoo Lee 419bb55568SKyungwoo Lee static std::string getCGDataErrString(cgdata_error Err, 429bb55568SKyungwoo Lee const std::string &ErrMsg = "") { 439bb55568SKyungwoo Lee std::string Msg; 449bb55568SKyungwoo Lee raw_string_ostream OS(Msg); 459bb55568SKyungwoo Lee 469bb55568SKyungwoo Lee switch (Err) { 479bb55568SKyungwoo Lee case cgdata_error::success: 489bb55568SKyungwoo Lee OS << "success"; 499bb55568SKyungwoo Lee break; 509bb55568SKyungwoo Lee case cgdata_error::eof: 519bb55568SKyungwoo Lee OS << "end of File"; 529bb55568SKyungwoo Lee break; 539bb55568SKyungwoo Lee case cgdata_error::bad_magic: 549bb55568SKyungwoo Lee OS << "invalid codegen data (bad magic)"; 559bb55568SKyungwoo Lee break; 569bb55568SKyungwoo Lee case cgdata_error::bad_header: 579bb55568SKyungwoo Lee OS << "invalid codegen data (file header is corrupt)"; 589bb55568SKyungwoo Lee break; 599bb55568SKyungwoo Lee case cgdata_error::empty_cgdata: 609bb55568SKyungwoo Lee OS << "empty codegen data"; 619bb55568SKyungwoo Lee break; 629bb55568SKyungwoo Lee case cgdata_error::malformed: 639bb55568SKyungwoo Lee OS << "malformed codegen data"; 649bb55568SKyungwoo Lee break; 659bb55568SKyungwoo Lee case cgdata_error::unsupported_version: 669bb55568SKyungwoo Lee OS << "unsupported codegen data version"; 679bb55568SKyungwoo Lee break; 689bb55568SKyungwoo Lee } 699bb55568SKyungwoo Lee 709bb55568SKyungwoo Lee // If optional error message is not empty, append it to the message. 719bb55568SKyungwoo Lee if (!ErrMsg.empty()) 729bb55568SKyungwoo Lee OS << ": " << ErrMsg; 739bb55568SKyungwoo Lee 749bb55568SKyungwoo Lee return OS.str(); 759bb55568SKyungwoo Lee } 769bb55568SKyungwoo Lee 779bb55568SKyungwoo Lee namespace { 789bb55568SKyungwoo Lee 799bb55568SKyungwoo Lee // FIXME: This class is only here to support the transition to llvm::Error. It 809bb55568SKyungwoo Lee // will be removed once this transition is complete. Clients should prefer to 819bb55568SKyungwoo Lee // deal with the Error value directly, rather than converting to error_code. 829bb55568SKyungwoo Lee class CGDataErrorCategoryType : public std::error_category { 839bb55568SKyungwoo Lee const char *name() const noexcept override { return "llvm.cgdata"; } 849bb55568SKyungwoo Lee 859bb55568SKyungwoo Lee std::string message(int IE) const override { 869bb55568SKyungwoo Lee return getCGDataErrString(static_cast<cgdata_error>(IE)); 879bb55568SKyungwoo Lee } 889bb55568SKyungwoo Lee }; 899bb55568SKyungwoo Lee 909bb55568SKyungwoo Lee } // end anonymous namespace 919bb55568SKyungwoo Lee 929bb55568SKyungwoo Lee const std::error_category &llvm::cgdata_category() { 939bb55568SKyungwoo Lee static CGDataErrorCategoryType ErrorCategory; 949bb55568SKyungwoo Lee return ErrorCategory; 959bb55568SKyungwoo Lee } 969bb55568SKyungwoo Lee 979bb55568SKyungwoo Lee std::string CGDataError::message() const { 989bb55568SKyungwoo Lee return getCGDataErrString(Err, Msg); 999bb55568SKyungwoo Lee } 1009bb55568SKyungwoo Lee 1019bb55568SKyungwoo Lee char CGDataError::ID = 0; 1029bb55568SKyungwoo Lee 1039bb55568SKyungwoo Lee namespace { 1049bb55568SKyungwoo Lee 1059bb55568SKyungwoo Lee const char *CodeGenDataSectNameCommon[] = { 1069bb55568SKyungwoo Lee #define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \ 1079bb55568SKyungwoo Lee SectNameCommon, 1089bb55568SKyungwoo Lee #include "llvm/CGData/CodeGenData.inc" 1099bb55568SKyungwoo Lee }; 1109bb55568SKyungwoo Lee 1119bb55568SKyungwoo Lee const char *CodeGenDataSectNameCoff[] = { 1129bb55568SKyungwoo Lee #define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \ 1139bb55568SKyungwoo Lee SectNameCoff, 1149bb55568SKyungwoo Lee #include "llvm/CGData/CodeGenData.inc" 1159bb55568SKyungwoo Lee }; 1169bb55568SKyungwoo Lee 1179bb55568SKyungwoo Lee const char *CodeGenDataSectNamePrefix[] = { 1189bb55568SKyungwoo Lee #define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Prefix, 1199bb55568SKyungwoo Lee #include "llvm/CGData/CodeGenData.inc" 1209bb55568SKyungwoo Lee }; 1219bb55568SKyungwoo Lee 1229bb55568SKyungwoo Lee } // namespace 1239bb55568SKyungwoo Lee 1249bb55568SKyungwoo Lee namespace llvm { 1259bb55568SKyungwoo Lee 1269bb55568SKyungwoo Lee std::string getCodeGenDataSectionName(CGDataSectKind CGSK, 1279bb55568SKyungwoo Lee Triple::ObjectFormatType OF, 1289bb55568SKyungwoo Lee bool AddSegmentInfo) { 1299bb55568SKyungwoo Lee std::string SectName; 1309bb55568SKyungwoo Lee 1319bb55568SKyungwoo Lee if (OF == Triple::MachO && AddSegmentInfo) 1329bb55568SKyungwoo Lee SectName = CodeGenDataSectNamePrefix[CGSK]; 1339bb55568SKyungwoo Lee 1349bb55568SKyungwoo Lee if (OF == Triple::COFF) 1359bb55568SKyungwoo Lee SectName += CodeGenDataSectNameCoff[CGSK]; 1369bb55568SKyungwoo Lee else 1379bb55568SKyungwoo Lee SectName += CodeGenDataSectNameCommon[CGSK]; 1389bb55568SKyungwoo Lee 1399bb55568SKyungwoo Lee return SectName; 1409bb55568SKyungwoo Lee } 1419bb55568SKyungwoo Lee 1429bb55568SKyungwoo Lee std::unique_ptr<CodeGenData> CodeGenData::Instance = nullptr; 1439bb55568SKyungwoo Lee std::once_flag CodeGenData::OnceFlag; 1449bb55568SKyungwoo Lee 1459bb55568SKyungwoo Lee CodeGenData &CodeGenData::getInstance() { 1469bb55568SKyungwoo Lee std::call_once(CodeGenData::OnceFlag, []() { 1479bb55568SKyungwoo Lee Instance = std::unique_ptr<CodeGenData>(new CodeGenData()); 1489bb55568SKyungwoo Lee 149*dc85d526SKyungwoo Lee if (CodeGenDataGenerate || CodeGenDataThinLTOTwoRounds) 1500f525452SKyungwoo Lee Instance->EmitCGData = true; 1510f525452SKyungwoo Lee else if (!CodeGenDataUsePath.empty()) { 1520f525452SKyungwoo Lee // Initialize the global CGData if the input file name is given. 1530f525452SKyungwoo Lee // We do not error-out when failing to parse the input file. 1540f525452SKyungwoo Lee // Instead, just emit an warning message and fall back as if no CGData 1550f525452SKyungwoo Lee // were available. 1560f525452SKyungwoo Lee auto FS = vfs::getRealFileSystem(); 1570f525452SKyungwoo Lee auto ReaderOrErr = CodeGenDataReader::create(CodeGenDataUsePath, *FS); 1580f525452SKyungwoo Lee if (Error E = ReaderOrErr.takeError()) { 1590f525452SKyungwoo Lee warn(std::move(E), CodeGenDataUsePath); 1600f525452SKyungwoo Lee return; 1610f525452SKyungwoo Lee } 1620f525452SKyungwoo Lee // Publish each CGData based on the data type in the header. 1630f525452SKyungwoo Lee auto Reader = ReaderOrErr->get(); 1640f525452SKyungwoo Lee if (Reader->hasOutlinedHashTree()) 1650f525452SKyungwoo Lee Instance->publishOutlinedHashTree(Reader->releaseOutlinedHashTree()); 1660f525452SKyungwoo Lee } 1679bb55568SKyungwoo Lee }); 1689bb55568SKyungwoo Lee return *(Instance.get()); 1699bb55568SKyungwoo Lee } 1709bb55568SKyungwoo Lee 1719bb55568SKyungwoo Lee namespace IndexedCGData { 1729bb55568SKyungwoo Lee 1739bb55568SKyungwoo Lee Expected<Header> Header::readFromBuffer(const unsigned char *Curr) { 1749bb55568SKyungwoo Lee using namespace support; 1759bb55568SKyungwoo Lee 1769bb55568SKyungwoo Lee static_assert(std::is_standard_layout_v<llvm::IndexedCGData::Header>, 1779bb55568SKyungwoo Lee "The header should be standard layout type since we use offset " 1789bb55568SKyungwoo Lee "of fields to read."); 1799bb55568SKyungwoo Lee Header H; 1809bb55568SKyungwoo Lee H.Magic = endian::readNext<uint64_t, endianness::little, unaligned>(Curr); 1819bb55568SKyungwoo Lee if (H.Magic != IndexedCGData::Magic) 1829bb55568SKyungwoo Lee return make_error<CGDataError>(cgdata_error::bad_magic); 1839bb55568SKyungwoo Lee H.Version = endian::readNext<uint32_t, endianness::little, unaligned>(Curr); 1849bb55568SKyungwoo Lee if (H.Version > IndexedCGData::CGDataVersion::CurrentVersion) 1859bb55568SKyungwoo Lee return make_error<CGDataError>(cgdata_error::unsupported_version); 1869bb55568SKyungwoo Lee H.DataKind = endian::readNext<uint32_t, endianness::little, unaligned>(Curr); 1879bb55568SKyungwoo Lee 1889bb55568SKyungwoo Lee switch (H.Version) { 1899bb55568SKyungwoo Lee // When a new field is added to the header add a case statement here to 1909bb55568SKyungwoo Lee // compute the size as offset of the new field + size of the new field. This 1919bb55568SKyungwoo Lee // relies on the field being added to the end of the list. 1929bb55568SKyungwoo Lee static_assert(IndexedCGData::CGDataVersion::CurrentVersion == Version1, 1939bb55568SKyungwoo Lee "Please update the size computation below if a new field has " 1949bb55568SKyungwoo Lee "been added to the header, if not add a case statement to " 1959bb55568SKyungwoo Lee "fall through to the latest version."); 1969bb55568SKyungwoo Lee case 1ull: 1979bb55568SKyungwoo Lee H.OutlinedHashTreeOffset = 1989bb55568SKyungwoo Lee endian::readNext<uint64_t, endianness::little, unaligned>(Curr); 1999bb55568SKyungwoo Lee } 2009bb55568SKyungwoo Lee 2019bb55568SKyungwoo Lee return H; 2029bb55568SKyungwoo Lee } 2039bb55568SKyungwoo Lee 2049bb55568SKyungwoo Lee } // end namespace IndexedCGData 2059bb55568SKyungwoo Lee 2069bb55568SKyungwoo Lee namespace cgdata { 2079bb55568SKyungwoo Lee 2089bb55568SKyungwoo Lee void warn(Twine Message, std::string Whence, std::string Hint) { 2099bb55568SKyungwoo Lee WithColor::warning(); 2109bb55568SKyungwoo Lee if (!Whence.empty()) 2119bb55568SKyungwoo Lee errs() << Whence << ": "; 2129bb55568SKyungwoo Lee errs() << Message << "\n"; 2139bb55568SKyungwoo Lee if (!Hint.empty()) 2149bb55568SKyungwoo Lee WithColor::note() << Hint << "\n"; 2159bb55568SKyungwoo Lee } 2169bb55568SKyungwoo Lee 2179bb55568SKyungwoo Lee void warn(Error E, StringRef Whence) { 2189bb55568SKyungwoo Lee if (E.isA<CGDataError>()) { 2199bb55568SKyungwoo Lee handleAllErrors(std::move(E), [&](const CGDataError &IPE) { 2209bb55568SKyungwoo Lee warn(IPE.message(), Whence.str(), ""); 2219bb55568SKyungwoo Lee }); 2229bb55568SKyungwoo Lee } 2239bb55568SKyungwoo Lee } 2249bb55568SKyungwoo Lee 225*dc85d526SKyungwoo Lee void saveModuleForTwoRounds(const Module &TheModule, unsigned Task, 226*dc85d526SKyungwoo Lee AddStreamFn AddStream) { 227*dc85d526SKyungwoo Lee LLVM_DEBUG(dbgs() << "Saving module: " << TheModule.getModuleIdentifier() 228*dc85d526SKyungwoo Lee << " in Task " << Task << "\n"); 229*dc85d526SKyungwoo Lee Expected<std::unique_ptr<CachedFileStream>> StreamOrErr = 230*dc85d526SKyungwoo Lee AddStream(Task, TheModule.getModuleIdentifier()); 231*dc85d526SKyungwoo Lee if (Error Err = StreamOrErr.takeError()) 232*dc85d526SKyungwoo Lee report_fatal_error(std::move(Err)); 233*dc85d526SKyungwoo Lee std::unique_ptr<CachedFileStream> &Stream = *StreamOrErr; 234*dc85d526SKyungwoo Lee 235*dc85d526SKyungwoo Lee WriteBitcodeToFile(TheModule, *Stream->OS, 236*dc85d526SKyungwoo Lee /*ShouldPreserveUseListOrder=*/true); 237*dc85d526SKyungwoo Lee } 238*dc85d526SKyungwoo Lee 239*dc85d526SKyungwoo Lee std::unique_ptr<Module> loadModuleForTwoRounds(BitcodeModule &OrigModule, 240*dc85d526SKyungwoo Lee unsigned Task, 241*dc85d526SKyungwoo Lee LLVMContext &Context, 242*dc85d526SKyungwoo Lee ArrayRef<StringRef> IRFiles) { 243*dc85d526SKyungwoo Lee LLVM_DEBUG(dbgs() << "Loading module: " << OrigModule.getModuleIdentifier() 244*dc85d526SKyungwoo Lee << " in Task " << Task << "\n"); 245*dc85d526SKyungwoo Lee auto FileBuffer = MemoryBuffer::getMemBuffer( 246*dc85d526SKyungwoo Lee IRFiles[Task], "in-memory IR file", /*RequiresNullTerminator=*/false); 247*dc85d526SKyungwoo Lee auto RestoredModule = parseBitcodeFile(*FileBuffer, Context); 248*dc85d526SKyungwoo Lee if (!RestoredModule) 249*dc85d526SKyungwoo Lee report_fatal_error( 250*dc85d526SKyungwoo Lee Twine("Failed to parse optimized bitcode loaded for Task: ") + 251*dc85d526SKyungwoo Lee Twine(Task) + "\n"); 252*dc85d526SKyungwoo Lee 253*dc85d526SKyungwoo Lee // Restore the original module identifier. 254*dc85d526SKyungwoo Lee (*RestoredModule)->setModuleIdentifier(OrigModule.getModuleIdentifier()); 255*dc85d526SKyungwoo Lee return std::move(*RestoredModule); 256*dc85d526SKyungwoo Lee } 257*dc85d526SKyungwoo Lee 258*dc85d526SKyungwoo Lee Expected<stable_hash> mergeCodeGenData(ArrayRef<StringRef> ObjFiles) { 259*dc85d526SKyungwoo Lee OutlinedHashTreeRecord GlobalOutlineRecord; 260*dc85d526SKyungwoo Lee stable_hash CombinedHash = 0; 261*dc85d526SKyungwoo Lee for (auto File : ObjFiles) { 262*dc85d526SKyungwoo Lee if (File.empty()) 263*dc85d526SKyungwoo Lee continue; 264*dc85d526SKyungwoo Lee std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer( 265*dc85d526SKyungwoo Lee File, "in-memory object file", /*RequiresNullTerminator=*/false); 266*dc85d526SKyungwoo Lee Expected<std::unique_ptr<object::ObjectFile>> BinOrErr = 267*dc85d526SKyungwoo Lee object::ObjectFile::createObjectFile(Buffer->getMemBufferRef()); 268*dc85d526SKyungwoo Lee if (!BinOrErr) 269*dc85d526SKyungwoo Lee return BinOrErr.takeError(); 270*dc85d526SKyungwoo Lee 271*dc85d526SKyungwoo Lee std::unique_ptr<object::ObjectFile> &Obj = BinOrErr.get(); 272*dc85d526SKyungwoo Lee if (auto E = CodeGenDataReader::mergeFromObjectFile( 273*dc85d526SKyungwoo Lee Obj.get(), GlobalOutlineRecord, &CombinedHash)) 274*dc85d526SKyungwoo Lee return E; 275*dc85d526SKyungwoo Lee } 276*dc85d526SKyungwoo Lee 277*dc85d526SKyungwoo Lee if (!GlobalOutlineRecord.empty()) 278*dc85d526SKyungwoo Lee cgdata::publishOutlinedHashTree(std::move(GlobalOutlineRecord.HashTree)); 279*dc85d526SKyungwoo Lee 280*dc85d526SKyungwoo Lee return CombinedHash; 281*dc85d526SKyungwoo Lee } 282*dc85d526SKyungwoo Lee 2839bb55568SKyungwoo Lee } // end namespace cgdata 2849bb55568SKyungwoo Lee 2859bb55568SKyungwoo Lee } // end namespace llvm 286