1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
//===-- llvm-split: command line tool for testing module splitting --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This program can be used to test the llvm::SplitModule and
// TargetMachine::splitModule functions.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/SplitModule.h"
using namespace llvm;
static cl::OptionCategory SplitCategory("Split Options");
static cl::opt<std::string> InputFilename(cl::Positional,
cl::desc("<input bitcode file>"),
cl::init("-"),
cl::value_desc("filename"),
cl::cat(SplitCategory));
static cl::opt<std::string> OutputFilename("o",
cl::desc("Override output filename"),
cl::value_desc("filename"),
cl::cat(SplitCategory));
static cl::opt<unsigned> NumOutputs("j", cl::Prefix, cl::init(2),
cl::desc("Number of output files"),
cl::cat(SplitCategory));
static cl::opt<bool>
PreserveLocals("preserve-locals", cl::Prefix, cl::init(false),
cl::desc("Split without externalizing locals"),
cl::cat(SplitCategory));
static cl::opt<bool>
RoundRobin("round-robin", cl::Prefix, cl::init(false),
cl::desc("Use round-robin distribution of functions to "
"modules instead of the default name-hash-based one"),
cl::cat(SplitCategory));
static cl::opt<std::string>
MTriple("mtriple",
cl::desc("Target triple. When present, a TargetMachine is created "
"and TargetMachine::splitModule is used instead of the "
"common SplitModule logic."),
cl::value_desc("triple"), cl::cat(SplitCategory));
static cl::opt<std::string>
MCPU("mcpu", cl::desc("Target CPU, ignored if -mtriple is not used"),
cl::value_desc("cpu"), cl::cat(SplitCategory));
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
LLVMContext Context;
SMDiagnostic Err;
cl::HideUnrelatedOptions({&SplitCategory, &getColorCategory()});
cl::ParseCommandLineOptions(argc, argv, "LLVM module splitter\n");
std::unique_ptr<TargetMachine> TM;
if (!MTriple.empty()) {
InitializeAllTargets();
InitializeAllTargetMCs();
std::string Error;
const Target *T = TargetRegistry::lookupTarget(MTriple, Error);
if (!T) {
errs() << "unknown target '" << MTriple << "': " << Error << "\n";
return 1;
}
TargetOptions Options;
TM = std::unique_ptr<TargetMachine>(T->createTargetMachine(
MTriple, MCPU, /*FS*/ "", Options, std::nullopt, std::nullopt));
}
std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context);
if (!M) {
Err.print(argv[0], errs());
return 1;
}
unsigned I = 0;
const auto HandleModulePart = [&](std::unique_ptr<Module> MPart) {
std::error_code EC;
std::unique_ptr<ToolOutputFile> Out(
new ToolOutputFile(OutputFilename + utostr(I++), EC, sys::fs::OF_None));
if (EC) {
errs() << EC.message() << '\n';
exit(1);
}
if (verifyModule(*MPart, &errs())) {
errs() << "Broken module!\n";
exit(1);
}
WriteBitcodeToFile(*MPart, Out->os());
// Declare success.
Out->keep();
};
if (TM) {
if (PreserveLocals) {
errs() << "warning: -preserve-locals has no effect when using "
"TargetMachine::splitModule\n";
}
if (RoundRobin)
errs() << "warning: -round-robin has no effect when using "
"TargetMachine::splitModule\n";
if (TM->splitModule(*M, NumOutputs, HandleModulePart))
return 0;
errs() << "warning: "
"TargetMachine::splitModule failed, falling back to default "
"splitModule implementation\n";
}
SplitModule(*M, NumOutputs, HandleModulePart, PreserveLocals, RoundRobin);
return 0;
}
|