[BOLT] Add support for reading profile on Mach-O

Summary: Add support for reading profile on Mach-O.

(cherry picked from FBD25777049)
This commit is contained in:
Alexander Shaposhnikov 2021-01-29 16:37:07 -08:00 committed by Maksim Panchenko
parent a0dd5b05dc
commit 0a8aaf56bb
3 changed files with 74 additions and 0 deletions

View File

@ -14,6 +14,7 @@
#include "BinaryEmitter.h"
#include "BinaryFunction.h"
#include "BinaryPassManager.h"
#include "DataReader.h"
#include "ExecutableFileMemoryManager.h"
#include "JumpTable.h"
#include "Passes/Instrumentation.h"
@ -64,6 +65,42 @@ MachORewriteInstance::MachORewriteInstance(object::MachOObjectFile *InputFile,
DWARFContext::defaultErrorHandler, "",
false))) {}
Error MachORewriteInstance::setProfile(StringRef Filename) {
if (!sys::fs::exists(Filename))
return errorCodeToError(make_error_code(errc::no_such_file_or_directory));
if (ProfileReader) {
// Already exists
return make_error<StringError>(
Twine("multiple profiles specified: ") + ProfileReader->getFilename() +
" and " + Filename, inconvertibleErrorCode());
}
ProfileReader = llvm::make_unique<DataReader>(Filename);
return Error::success();
}
void MachORewriteInstance::preprocessProfileData() {
if (!ProfileReader)
return;
if (auto E = ProfileReader->preprocessProfile(*BC.get()))
report_error("cannot pre-process profile", std::move(E));
}
void MachORewriteInstance::processProfileDataPreCFG() {
if (!ProfileReader)
return;
if (auto E = ProfileReader->readProfilePreCFG(*BC.get()))
report_error("cannot read profile pre-CFG", std::move(E));
}
void MachORewriteInstance::processProfileData() {
if (!ProfileReader)
return;
if (auto E = ProfileReader->readProfile(*BC.get()))
report_error("cannot read profile", std::move(E));
}
void MachORewriteInstance::readSpecialSections() {
for (const auto &Section : InputFile->sections()) {
StringRef SectionName;
@ -252,6 +289,14 @@ void MachORewriteInstance::disassembleFunctions() {
Function.disassemble();
if (opts::PrintDisasm)
Function.print(outs(), "after disassembly", true);
}
}
void MachORewriteInstance::buildFunctionsCFG() {
for (auto &BFI : BC->getBinaryFunctions()) {
BinaryFunction &Function = BFI.second;
if (!Function.isSimple())
continue;
if (!Function.buildCFG(/*AllocId*/ 0)) {
errs() << "BOLT-WARNING: failed to build CFG for the function "
<< Function << "\n";
@ -522,12 +567,27 @@ void MachORewriteInstance::adjustCommandLineOptions() {
void MachORewriteInstance::run() {
adjustCommandLineOptions();
readSpecialSections();
discoverFileObjects();
preprocessProfileData();
disassembleFunctions();
processProfileDataPreCFG();
buildFunctionsCFG();
processProfileData();
postProcessFunctions();
runOptimizationPasses();
emitAndLink();
rewriteFile();
}

View File

@ -15,6 +15,7 @@
#define LLVM_TOOLS_LLVM_BOLT_MACHO_REWRITE_INSTANCE_H
#include "NameResolver.h"
#include "ProfileReaderBase.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/Object/MachO.h"
#include <memory>
@ -48,6 +49,11 @@ class MachORewriteInstance {
std::unique_ptr<ToolOutputFile> Out;
std::unique_ptr<ProfileReaderBase> ProfileReader;
void preprocessProfileData();
void processProfileDataPreCFG();
void processProfileData();
static StringRef getOrgSecPrefix() { return ".bolt.org"; }
void mapInstrumentationSection(orc::VModuleKey Key, StringRef SectionName);
@ -57,6 +63,7 @@ class MachORewriteInstance {
void readSpecialSections();
void discoverFileObjects();
void disassembleFunctions();
void buildFunctionsCFG();
void postProcessFunctions();
void runOptimizationPasses();
void emitAndLink();
@ -68,6 +75,8 @@ public:
MachORewriteInstance(object::MachOObjectFile *InputFile, StringRef ToolPath);
~MachORewriteInstance();
Error setProfile(StringRef FileName);
/// Run all the necessary steps to read, optimize and rewrite the binary.
void run();
};

View File

@ -323,6 +323,11 @@ int main(int argc, char **argv) {
RI.run();
} else if (auto *O = dyn_cast<MachOObjectFile>(&Binary)) {
MachORewriteInstance MachORI(O, ToolPath);
if (!opts::InputDataFilename.empty())
if (auto E = MachORI.setProfile(opts::InputDataFilename))
report_error(opts::InputDataFilename, std::move(E));
MachORI.run();
} else {
report_error(opts::InputFilename, object_error::invalid_file_type);