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

source code of llvm/tools/llvm-split/llvm-split.cpp