LLVM: lib/CGData/CodeGenData.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

24

25#define DEBUG_TYPE "cg-data"

26

27using namespace llvm;

28using namespace cgdata;

29

32 cl::desc("Emit CodeGen Data into custom sections"));

35 cl::desc("File path to where .cgdata file is read"));

38 cl::desc("Enable two-round ThinLTO code generation. The first round "

39 "emits codegen data, while the second round uses the emitted "

40 "codegen data for further optimizations."));

41

43 const std::string &ErrMsg = "") {

44 std::string Msg;

46

47 switch (Err) {

48 case cgdata_error::success:

49 OS << "success";

50 break;

51 case cgdata_error::eof:

52 OS << "end of File";

53 break;

54 case cgdata_error::bad_magic:

55 OS << "invalid codegen data (bad magic)";

56 break;

57 case cgdata_error::bad_header:

58 OS << "invalid codegen data (file header is corrupt)";

59 break;

60 case cgdata_error::empty_cgdata:

61 OS << "empty codegen data";

62 break;

63 case cgdata_error::malformed:

64 OS << "malformed codegen data";

65 break;

66 case cgdata_error::unsupported_version:

67 OS << "unsupported codegen data version";

68 break;

69 }

70

71

72 if (!ErrMsg.empty())

73 OS << ": " << ErrMsg;

74

75 return OS.str();

76}

77

78namespace {

79

80

81

82

83class CGDataErrorCategoryType : public std::error_category {

84 const char *name() const noexcept override { return "llvm.cgdata"; }

85

86 std::string message(int IE) const override {

88 }

89};

90

91}

92

94 static CGDataErrorCategoryType ErrorCategory;

95 return ErrorCategory;

96}

97

100}

101

103

104namespace {

105

106const char *CodeGenDataSectNameCommon[] = {

107#define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \

108 SectNameCommon,

110};

111

112const char *CodeGenDataSectNameCoff[] = {

113#define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \

114 SectNameCoff,

116};

117

118const char *CodeGenDataSectNamePrefix[] = {

119#define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Prefix,

121};

122

123}

124

125namespace llvm {

126

129 bool AddSegmentInfo) {

130 std::string SectName;

131

133 SectName = CodeGenDataSectNamePrefix[CGSK];

134

136 SectName += CodeGenDataSectNameCoff[CGSK];

137 else

138 SectName += CodeGenDataSectNameCommon[CGSK];

139

140 return SectName;

141}

142

143std::unique_ptr CodeGenData::Instance = nullptr;

144std::once_flag CodeGenData::OnceFlag;

145

147 std::call_once(CodeGenData::OnceFlag, []() {

148 Instance = std::unique_ptr(new CodeGenData());

149

151 Instance->EmitCGData = true;

153

154

155

156

159 if (Error E = ReaderOrErr.takeError()) {

161 return;

162 }

163

164 auto Reader = ReaderOrErr->get();

165 if (Reader->hasOutlinedHashTree())

166 Instance->publishOutlinedHashTree(Reader->releaseOutlinedHashTree());

167 if (Reader->hasStableFunctionMap())

168 Instance->publishStableFunctionMap(Reader->releaseStableFunctionMap());

169 }

170 });

171 return *Instance;

172}

173

174namespace IndexedCGData {

175

177 using namespace support;

178

179 static_assert(std::is_standard_layout_vllvm::IndexedCGData::Header,

180 "The header should be standard layout type since we use offset "

181 "of fields to read.");

183 H.Magic = endian::readNext<uint64_t, endianness::little, unaligned>(Curr);

186 H.Version = endian::readNext<uint32_t, endianness::little, unaligned>(Curr);

189 H.DataKind = endian::readNext<uint32_t, endianness::little, unaligned>(Curr);

190

192 "Please update the offset computation below if a new field has "

193 "been added to the header.");

194 H.OutlinedHashTreeOffset =

195 endian::readNext<uint64_t, endianness::little, unaligned>(Curr);

196 if (H.Version >= 2)

197 H.StableFunctionMapOffset =

198 endian::readNext<uint64_t, endianness::little, unaligned>(Curr);

199

200 return H;

201}

202

203}

204

205namespace cgdata {

206

207void warn(Twine Message, std::string Whence, std::string Hint) {

209 if (!Whence.empty())

210 errs() << Whence << ": ";

211 errs() << Message << "\n";

212 if (!Hint.empty())

214}

215

220 });

221 }

222}

223

227 << " in Task " << Task << "\n");

232 std::unique_ptr &Stream = *StreamOrErr;

233

235 true);

236}

237

239 unsigned Task,

243 << " in Task " << Task << "\n");

245 IRFiles[Task], "in-memory IR file", false);

246 auto RestoredModule = parseBitcodeFile(*FileBuffer, Context);

247 if (!RestoredModule)

249 Twine("Failed to parse optimized bitcode loaded for Task: ") +

250 Twine(Task) + "\n");

251

252

253 (*RestoredModule)->setModuleIdentifier(OrigModule.getModuleIdentifier());

254 return std::move(*RestoredModule);

255}

256

261 for (auto File : ObjFiles) {

262 if (File.empty())

263 continue;

265 File, "in-memory object file", false);

268 if (!BinOrErr)

270

271 std::unique_ptrobject::ObjectFile &Obj = BinOrErr.get();

273 Obj.get(), GlobalOutlineRecord, GlobalStableFunctionMapRecord,

274 &CombinedHash))

275 return E;

276 }

277

278 GlobalStableFunctionMapRecord.finalize();

279

280 if (!GlobalOutlineRecord.empty())

282 if (!GlobalStableFunctionMapRecord.empty())

284 std::move(GlobalStableFunctionMapRecord.FunctionMap));

285

286 return CombinedHash;

287}

288

289}

290

291}

static std::string getCGDataErrString(cgdata_error Err, const std::string &ErrMsg="")

cl::opt< bool > CodeGenDataThinLTOTwoRounds("codegen-data-thinlto-two-rounds", cl::init(false), cl::Hidden, cl::desc("Enable two-round ThinLTO code generation. The first round " "emits codegen data, while the second round uses the emitted " "codegen data for further optimizations."))

cl::opt< std::string > CodeGenDataUsePath("codegen-data-use-path", cl::init(""), cl::Hidden, cl::desc("File path to where .cgdata file is read"))

cl::opt< bool > CodeGenDataGenerate("codegen-data-generate", cl::init(false), cl::Hidden, cl::desc("Emit CodeGen Data into custom sections"))

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

Represents a module in a bitcode file.

StringRef getModuleIdentifier() const

std::string message() const override

Return the error message as a string.

static Expected< std::unique_ptr< CodeGenDataReader > > create(const Twine &Path, vfs::FileSystem &FS)

Factory method to create an appropriately typed reader for the given codegen data file path and file ...

static Error mergeFromObjectFile(const object::ObjectFile *Obj, OutlinedHashTreeRecord &GlobalOutlineRecord, StableFunctionMapRecord &GlobalFunctionMapRecord, stable_hash *CombinedHash=nullptr)

Extract the cgdata embedded in sections from the given object file and merge them into the GlobalOutl...

static CodeGenData & getInstance()

Lightweight error class with error context and mandatory checking.

bool isA() const

Check whether one error is a subclass of another.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

reference get()

Returns a reference to the stored T value.

This is an important class for using LLVM in a threaded context.

static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)

Open the specified memory range as a MemoryBuffer.

A Module instance is used to store all the information related to an LLVM module.

const std::string & getModuleIdentifier() const

Get the module identifier which is, essentially, the name of the module.

StringRef - Represent a constant reference to a string, i.e.

std::string str() const

str - Get the contents as an std::string.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

static raw_ostream & warning()

Convenience method for printing "warning: " to stderr.

static raw_ostream & note()

Convenience method for printing "note: " to stderr.

static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)

A raw_ostream that writes to an std::string.

Expected< stable_hash > mergeCodeGenData(ArrayRef< StringRef > ObjectFiles)

Merge the codegen data from the scratch objects ObjectFiles from the first codegen round.

void publishOutlinedHashTree(std::unique_ptr< OutlinedHashTree > HashTree)

void warn(Error E, StringRef Whence="")

void publishStableFunctionMap(std::unique_ptr< StableFunctionMap > FunctionMap)

void saveModuleForTwoRounds(const Module &TheModule, unsigned Task, AddStreamFn AddStream)

Save TheModule before the first codegen round.

std::unique_ptr< Module > loadModuleForTwoRounds(BitcodeModule &OrigModule, unsigned Task, LLVMContext &Context, ArrayRef< StringRef > IRFiles)

Load the optimized bitcode module for the second codegen round.

initializer< Ty > init(const Ty &Val)

IntrusiveRefCntPtr< FileSystem > getRealFileSystem()

Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.

This is an optimization pass for GlobalISel generic memory operations.

Expected< std::unique_ptr< Module > > parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, ParserCallbacks Callbacks={})

Read the specified bitcode file, returning the module.

void WriteBitcodeToFile(const Module &M, raw_ostream &Out, bool ShouldPreserveUseListOrder=false, const ModuleSummaryIndex *Index=nullptr, bool GenerateHash=false, ModuleHash *ModHash=nullptr)

Write the specified module to the specified raw output stream.

void handleAllErrors(Error E, HandlerTs &&... Handlers)

Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...

std::function< Expected< std::unique_ptr< CachedFileStream > >(unsigned Task, const Twine &ModuleName)> AddStreamFn

This type defines the callback to add a file that is generated on the fly.

raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

const std::error_category & cgdata_category()

raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

std::string getCodeGenDataSectionName(CGDataSectKind CGSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)

std::unique_ptr< OutlinedHashTree > HashTree

void finalize(bool SkipTrim=false)

Finalize the stable function map by trimming content.

std::unique_ptr< StableFunctionMap > FunctionMap