• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- CodeGenData.h --------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains support for codegen data that has stable summary which
10 // can be used to optimize the code in the subsequent codegen.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CGDATA_CODEGENDATA_H
15 #define LLVM_CGDATA_CODEGENDATA_H
16 
17 #include "llvm/ADT/BitmaskEnum.h"
18 #include "llvm/Bitcode/BitcodeReader.h"
19 #include "llvm/CGData/OutlinedHashTree.h"
20 #include "llvm/CGData/OutlinedHashTreeRecord.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/Object/ObjectFile.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/TargetParser/Triple.h"
25 #include <mutex>
26 
27 namespace llvm {
28 
29 enum CGDataSectKind {
30 #define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Kind,
31 #include "llvm/CGData/CodeGenData.inc"
32 };
33 
34 std::string getCodeGenDataSectionName(CGDataSectKind CGSK,
35                                       Triple::ObjectFormatType OF,
36                                       bool AddSegmentInfo = true);
37 
38 enum class CGDataKind {
39   Unknown = 0x0,
40   // A function outlining info.
41   FunctionOutlinedHashTree = 0x1,
42   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/FunctionOutlinedHashTree)
43 };
44 
45 const std::error_category &cgdata_category();
46 
47 enum class cgdata_error {
48   success = 0,
49   eof,
50   bad_magic,
51   bad_header,
52   empty_cgdata,
53   malformed,
54   unsupported_version,
55 };
56 
make_error_code(cgdata_error E)57 inline std::error_code make_error_code(cgdata_error E) {
58   return std::error_code(static_cast<int>(E), cgdata_category());
59 }
60 
61 class CGDataError : public ErrorInfo<CGDataError> {
62 public:
63   CGDataError(cgdata_error Err, const Twine &ErrStr = Twine())
Err(Err)64       : Err(Err), Msg(ErrStr.str()) {
65     assert(Err != cgdata_error::success && "Not an error");
66   }
67 
68   std::string message() const override;
69 
log(raw_ostream & OS)70   void log(raw_ostream &OS) const override { OS << message(); }
71 
convertToErrorCode()72   std::error_code convertToErrorCode() const override {
73     return make_error_code(Err);
74   }
75 
get()76   cgdata_error get() const { return Err; }
getMessage()77   const std::string &getMessage() const { return Msg; }
78 
79   /// Consume an Error and return the raw enum value contained within it, and
80   /// the optional error message. The Error must either be a success value, or
81   /// contain a single CGDataError.
take(Error E)82   static std::pair<cgdata_error, std::string> take(Error E) {
83     auto Err = cgdata_error::success;
84     std::string Msg;
85     handleAllErrors(std::move(E), [&Err, &Msg](const CGDataError &IPE) {
86       assert(Err == cgdata_error::success && "Multiple errors encountered");
87       Err = IPE.get();
88       Msg = IPE.getMessage();
89     });
90     return {Err, Msg};
91   }
92 
93   static char ID;
94 
95 private:
96   cgdata_error Err;
97   std::string Msg;
98 };
99 
100 enum CGDataMode {
101   None,
102   Read,
103   Write,
104 };
105 
106 class CodeGenData {
107   /// Global outlined hash tree that has oulined hash sequences across modules.
108   std::unique_ptr<OutlinedHashTree> PublishedHashTree;
109 
110   /// This flag is set when -fcodegen-data-generate is passed.
111   /// Or, it can be mutated with -fcodegen-data-thinlto-two-rounds.
112   bool EmitCGData;
113 
114   /// This is a singleton instance which is thread-safe. Unlike profile data
115   /// which is largely function-based, codegen data describes the whole module.
116   /// Therefore, this can be initialized once, and can be used across modules
117   /// instead of constructing the same one for each codegen backend.
118   static std::unique_ptr<CodeGenData> Instance;
119   static std::once_flag OnceFlag;
120 
121   CodeGenData() = default;
122 
123 public:
124   ~CodeGenData() = default;
125 
126   static CodeGenData &getInstance();
127 
128   /// Returns true if we have a valid outlined hash tree.
hasOutlinedHashTree()129   bool hasOutlinedHashTree() {
130     return PublishedHashTree && !PublishedHashTree->empty();
131   }
132 
133   /// Returns the outlined hash tree. This can be globally used in a read-only
134   /// manner.
getOutlinedHashTree()135   const OutlinedHashTree *getOutlinedHashTree() {
136     return PublishedHashTree.get();
137   }
138 
139   /// Returns true if we should write codegen data.
emitCGData()140   bool emitCGData() { return EmitCGData; }
141 
142   /// Publish the (globally) merged or read outlined hash tree.
publishOutlinedHashTree(std::unique_ptr<OutlinedHashTree> HashTree)143   void publishOutlinedHashTree(std::unique_ptr<OutlinedHashTree> HashTree) {
144     PublishedHashTree = std::move(HashTree);
145     // Ensure we disable emitCGData as we do not want to read and write both.
146     EmitCGData = false;
147   }
148 };
149 
150 namespace cgdata {
151 
hasOutlinedHashTree()152 inline bool hasOutlinedHashTree() {
153   return CodeGenData::getInstance().hasOutlinedHashTree();
154 }
155 
getOutlinedHashTree()156 inline const OutlinedHashTree *getOutlinedHashTree() {
157   return CodeGenData::getInstance().getOutlinedHashTree();
158 }
159 
emitCGData()160 inline bool emitCGData() { return CodeGenData::getInstance().emitCGData(); }
161 
162 inline void
publishOutlinedHashTree(std::unique_ptr<OutlinedHashTree> HashTree)163 publishOutlinedHashTree(std::unique_ptr<OutlinedHashTree> HashTree) {
164   CodeGenData::getInstance().publishOutlinedHashTree(std::move(HashTree));
165 }
166 
167 void warn(Error E, StringRef Whence = "");
168 void warn(Twine Message, std::string Whence = "", std::string Hint = "");
169 
170 } // end namespace cgdata
171 
172 namespace IndexedCGData {
173 
174 // A signature for data validation, representing "\xffcgdata\x81" in
175 // little-endian order
176 const uint64_t Magic = 0x81617461646763ff;
177 
178 enum CGDataVersion {
179   // Version 1 is the first version. This version supports the outlined
180   // hash tree.
181   Version1 = 1,
182   CurrentVersion = CG_DATA_INDEX_VERSION
183 };
184 const uint64_t Version = CGDataVersion::CurrentVersion;
185 
186 struct Header {
187   uint64_t Magic;
188   uint32_t Version;
189   uint32_t DataKind;
190   uint64_t OutlinedHashTreeOffset;
191 
192   // New fields should only be added at the end to ensure that the size
193   // computation is correct. The methods below need to be updated to ensure that
194   // the new field is read correctly.
195 
196   // Reads a header struct from the buffer.
197   static Expected<Header> readFromBuffer(const unsigned char *Curr);
198 };
199 
200 } // end namespace IndexedCGData
201 
202 } // end namespace llvm
203 
204 #endif // LLVM_CODEGEN_PREPARE_H
205