#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/MSVCErrorWorkarounds.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/MSVCErrorWorkarounds.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <future>
"manager by RuntimeDyld"),
cl::Hidden);
+static cl::opt<bool> ShowTimes("show-times",
+ cl::desc("Show times for llvm-rtdyld phases"),
+ cl::init(false));
+
ExitOnError ExitOnErr;
+struct RTDyldTimers {
+ TimerGroup RTDyldTimers{"llvm-rtdyld timers",
+ "timers for llvm-rtdyld phases"};
+ Timer LoadObjectsTimer{"load", "time to load/add object files", RTDyldTimers};
+ Timer LinkTimer{"link", "time to link object files", RTDyldTimers};
+ Timer RunTimer{"run", "time to execute jitlink'd code", RTDyldTimers};
+};
+
+std::unique_ptr<RTDyldTimers> Timers;
+
/* *** */
using SectionIDMap = StringMap<unsigned>;
// If we don't have any input files, read from stdin.
if (!InputFileList.size())
InputFileList.push_back("-");
- for (auto &File : InputFileList) {
- // Load the input memory buffer.
- ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
- MemoryBuffer::getFileOrSTDIN(File);
- if (std::error_code EC = InputBuffer.getError())
- ErrorAndExit("unable to read input: '" + EC.message() + "'");
- Expected<std::unique_ptr<ObjectFile>> MaybeObj(
- ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef()));
-
- if (!MaybeObj) {
- std::string Buf;
- raw_string_ostream OS(Buf);
- logAllUnhandledErrors(MaybeObj.takeError(), OS);
- OS.flush();
- ErrorAndExit("unable to create object file: '" + Buf + "'");
- }
+ {
+ TimeRegion TR(Timers ? &Timers->LoadObjectsTimer : nullptr);
+ for (auto &File : InputFileList) {
+ // Load the input memory buffer.
+ ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
+ MemoryBuffer::getFileOrSTDIN(File);
+ if (std::error_code EC = InputBuffer.getError())
+ ErrorAndExit("unable to read input: '" + EC.message() + "'");
+ Expected<std::unique_ptr<ObjectFile>> MaybeObj(
+ ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef()));
+
+ if (!MaybeObj) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(MaybeObj.takeError(), OS);
+ OS.flush();
+ ErrorAndExit("unable to create object file: '" + Buf + "'");
+ }
- ObjectFile &Obj = **MaybeObj;
+ ObjectFile &Obj = **MaybeObj;
- // Load the object file
- Dyld.loadObject(Obj);
- if (Dyld.hasError()) {
- ErrorAndExit(Dyld.getErrorString());
+ // Load the object file
+ Dyld.loadObject(Obj);
+ if (Dyld.hasError()) {
+ ErrorAndExit(Dyld.getErrorString());
+ }
}
}
- // Resove all the relocations we can.
- // FIXME: Error out if there are unresolved relocations.
- Dyld.resolveRelocations();
+ {
+ TimeRegion TR(Timers ? &Timers->LinkTimer : nullptr);
+ // Resove all the relocations we can.
+ // FIXME: Error out if there are unresolved relocations.
+ Dyld.resolveRelocations();
+ }
// Get the address of the entry point (_main by default).
void *MainAddress = Dyld.getSymbolLocalAddress(EntryPoint);
for (auto &Arg : InputArgv)
Argv.push_back(Arg.data());
Argv.push_back(nullptr);
- return Main(Argv.size() - 1, Argv.data());
+ int Result = 0;
+ {
+ TimeRegion TR(Timers ? &Timers->RunTimer : nullptr);
+ Result = Main(Argv.size() - 1, Argv.data());
+ }
+
+ return Result;
}
static int checkAllExpressions(RuntimeDyldChecker &Checker) {
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
+ Timers = ShowTimes ? std::make_unique<RTDyldTimers>() : nullptr;
+
+ int Result;
switch (Action) {
case AC_Execute:
- return executeInput();
+ Result = executeInput();
+ break;
case AC_PrintDebugLineInfo:
- return printLineInfoForInput(/* LoadObjects */ true,/* UseDebugObj */ true);
+ Result =
+ printLineInfoForInput(/* LoadObjects */ true, /* UseDebugObj */ true);
+ break;
case AC_PrintLineInfo:
- return printLineInfoForInput(/* LoadObjects */ true,/* UseDebugObj */false);
+ Result =
+ printLineInfoForInput(/* LoadObjects */ true, /* UseDebugObj */ false);
+ break;
case AC_PrintObjectLineInfo:
- return printLineInfoForInput(/* LoadObjects */false,/* UseDebugObj */false);
+ Result =
+ printLineInfoForInput(/* LoadObjects */ false, /* UseDebugObj */ false);
+ break;
case AC_Verify:
- return linkAndVerify();
+ Result = linkAndVerify();
+ break;
}
}