Jlm
Loading...
Searching...
No Matches
CommandGraphGenerator.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
10#include <jlm/util/strfmt.hpp>
11
12#include <unordered_map>
13
14#include <unistd.h>
15
16namespace jlm::tooling
17{
18
20
21util::FilePath
22JlcCommandGraphGenerator::CreateJlmOptCommandOutputFile(const util::FilePath & inputFile)
23{
26 inputFile.base() + "-",
27 "-jlm-opt.ll");
28}
29
38
65
68 const JlcCommandLineOptions::OptimizationLevel & optimizationLevel)
69{
70 static std::unordered_map<JlcCommandLineOptions::OptimizationLevel, LlcCommand::OptimizationLevel>
75
76 JLM_ASSERT(map.find(optimizationLevel) != map.end());
77 return map[optimizationLevel];
78}
79
82 CommandGraph & commandGraph,
83 const util::FilePath & outputFile,
84 const JlcCommandLineOptions::Compilation & compilation,
85 const JlcCommandLineOptions & commandLineOptions)
86{
88 commandGraph,
89 compilation.InputFile(),
90 outputFile,
91 compilation.DependencyFile(),
92 commandLineOptions.IncludePaths_,
93 commandLineOptions.MacroDefinitions_,
94 commandLineOptions.Warnings_,
95 commandLineOptions.Flags_,
96 commandLineOptions.Verbose_,
97 commandLineOptions.Rdynamic_,
98 commandLineOptions.Suppress_,
99 commandLineOptions.UsePthreads_,
100 commandLineOptions.Md_,
101 compilation.Mt(),
102 ConvertLanguageStandard(commandLineOptions.LanguageStandard_),
103 {});
104}
105
106std::unique_ptr<CommandGraph>
108{
109 auto commandGraph = CommandGraph::Create();
110
111 std::vector<CommandGraph::Node *> leafNodes;
112 for (auto & compilation : commandLineOptions.Compilations_)
113 {
114 auto lastNode = &commandGraph->GetEntryNode();
115
116 if (compilation.RequiresParsing())
117 {
118 auto & parserCommandNode = CreateParserCommand(
119 *commandGraph,
120 CreateParserCommandOutputFile(compilation.InputFile()),
121 compilation,
122 commandLineOptions);
123
124 lastNode->AddEdge(parserCommandNode);
125 lastNode = &parserCommandNode;
126 }
127
128 if (compilation.RequiresOptimization())
129 {
130 auto clangCommand = util::assertedCast<ClangCommand>(&lastNode->GetCommand());
131
132 util::StatisticsCollectorSettings statisticsCollectorSettings(
133 commandLineOptions.JlmOptPassStatistics_,
135 compilation.InputFile().base());
136
137 JlmOptCommandLineOptions jlmOptCommandLineOptions(
138 clangCommand->OutputFile(),
140 CreateJlmOptCommandOutputFile(compilation.InputFile()),
142 std::move(statisticsCollectorSettings),
144 commandLineOptions.JlmOptOptimizations_,
145 false);
146
147 auto & jlmOptCommandNode =
148 JlmOptCommand::Create(*commandGraph, "jlm-opt", std::move(jlmOptCommandLineOptions));
149 lastNode->AddEdge(jlmOptCommandNode);
150 lastNode = &jlmOptCommandNode;
151 }
152
153 if (compilation.RequiresAssembly())
154 {
155 auto jlmOptCommand = util::assertedCast<JlmOptCommand>(&lastNode->GetCommand());
156 auto & llvmLlcCommandNode = LlcCommand::Create(
157 *commandGraph,
158 jlmOptCommand->GetCommandLineOptions().GetOutputFile(),
159 compilation.OutputFile(),
162 lastNode->AddEdge(llvmLlcCommandNode);
163 lastNode = &llvmLlcCommandNode;
164 }
165
166 leafNodes.push_back(lastNode);
167 }
168
169 std::vector<util::FilePath> linkerInputFiles;
170 for (auto & compilation : commandLineOptions.Compilations_)
171 {
172 if (compilation.RequiresLinking())
173 linkerInputFiles.push_back(compilation.OutputFile());
174 }
175
176 if (!linkerInputFiles.empty())
177 {
178 auto & linkerCommandNode = ClangCommand::CreateLinkerCommand(
179 *commandGraph,
180 linkerInputFiles,
181 commandLineOptions.OutputFile_,
182 commandLineOptions.LibraryPaths_,
183 commandLineOptions.Libraries_,
184 commandLineOptions.UsePthreads_);
185
186 for (const auto & leafNode : leafNodes)
187 leafNode->AddEdge(linkerCommandNode);
188
189 leafNodes.clear();
190 leafNodes.push_back(&linkerCommandNode);
191 }
192
193 for (auto & leafNode : leafNodes)
194 leafNode->AddEdge(commandGraph->GetExitNode());
195
196 if (commandLineOptions.OnlyPrintCommands_)
197 commandGraph = PrintCommandsCommand::Create(std::move(commandGraph));
198
199 return commandGraph;
200}
201
203
204util::FilePath
205JhlsCommandGraphGenerator::CreateParserCommandOutputFile(
206 const util::FilePath & tmpDirectory,
207 const util::FilePath & inputFile)
208{
209 return util::FilePath::createUniqueFileName(tmpDirectory, inputFile.base() + "-", "-clang.ll");
210}
211
214 const util::FilePath & tmpDirectory,
215 const util::FilePath & inputFile)
216{
217 return util::FilePath::createUniqueFileName(tmpDirectory, inputFile.base() + "-", "-jlm-opt.ll");
218}
219
248
264
265std::unique_ptr<CommandGraph>
267{
268 std::unique_ptr<CommandGraph> commandGraph(new CommandGraph());
269
270 std::vector<CommandGraph::Node *> leaves;
271 std::vector<CommandGraph::Node *> llir;
272 std::vector<util::FilePath> llir_files;
273
274 // Create directory in /tmp for storing temporary files
275 std::string tmp_identifier = "jhls-";
276 for (const auto & compilation : commandLineOptions.Compilations_)
277 {
278 tmp_identifier += compilation.InputFile().name() + "-";
279 if (tmp_identifier.length() > 30)
280 break;
281 }
282
283 const auto tmp_folder =
285 auto & mkdir = MkdirCommand::Create(*commandGraph, tmp_folder);
286 commandGraph->GetEntryNode().AddEdge(mkdir);
287
288 for (const auto & compilation : commandLineOptions.Compilations_)
289 {
290 CommandGraph::Node * last = &mkdir;
291
292 if (compilation.RequiresParsing())
293 {
294 auto & parserNode = ClangCommand::CreateParsingCommand(
295 *commandGraph,
296 compilation.InputFile(),
297 CreateParserCommandOutputFile(tmp_folder, compilation.InputFile()),
298 compilation.DependencyFile(),
299 commandLineOptions.IncludePaths_,
300 commandLineOptions.MacroDefinitions_,
301 commandLineOptions.Warnings_,
302 commandLineOptions.Flags_,
303 commandLineOptions.Verbose_,
304 commandLineOptions.Rdynamic_,
305 commandLineOptions.Suppress_,
306 commandLineOptions.UsePthreads_,
307 commandLineOptions.Md_,
308 compilation.Mt(),
309 ConvertLanguageStandard(commandLineOptions.LanguageStandard_),
310 { ClangCommand::ClangArgument::DisableO0OptNone });
311
312 last->AddEdge(parserNode);
313 last = &parserNode;
314
315 // HLS links all files to a single IR
316 // Need to know when the IR has been generated for all input files
317 llir.push_back(&parserNode);
318 llir_files.push_back(dynamic_cast<ClangCommand *>(&parserNode.GetCommand())->OutputFile());
319 }
320
321 leaves.push_back(last);
322 }
323
324 // link all llir into one so inlining can be done across files for HLS
325 util::FilePath ll_merged(tmp_folder.to_str() + "merged.ll");
326 auto & ll_link = LlvmLinkCommand::Create(*commandGraph, llir_files, ll_merged, true, true);
327 // Add edges between each c.parse and the ll_link
328 for (const auto & ll : llir)
329 {
330 ll->AddEdge(ll_link);
331 }
332
333 // need to already run m2r here
334 util::FilePath ll_m2r1(tmp_folder.to_str() + "merged.m2r.ll");
335 auto & m2r1 = LlvmOptCommand::Create(
336 *commandGraph,
337 ll_merged,
338 ll_m2r1,
339 true,
341 ll_link.AddEdge(m2r1);
342 auto & extract = JlmHlsExtractCommand::Create(
343 *commandGraph,
344 dynamic_cast<LlvmOptCommand *>(&m2r1.GetCommand())->OutputFile(),
345 commandLineOptions.HlsFunctionRegex_,
346 commandLineOptions.OutputFile_);
347 m2r1.AddEdge(extract);
348 util::FilePath ll_m2r2(tmp_folder.to_str() + "function.hls.ll");
349 auto & m2r2 = LlvmOptCommand::Create(
350 *commandGraph,
351 dynamic_cast<JlmHlsExtractCommand *>(&extract.GetCommand())->HlsFunctionFile(),
352 ll_m2r2,
353 true,
354 { LlvmOptCommand::Optimization::Mem2Reg });
355 extract.AddEdge(m2r2);
356 // hls
357 auto & hls = JlmHlsCommand::Create(
358 *commandGraph,
359 dynamic_cast<LlvmOptCommand *>(&m2r2.GetCommand())->OutputFile(),
360 commandLineOptions.OutputFile_,
361 commandLineOptions.JlmHls_);
362 m2r2.AddEdge(hls);
363
364 auto linkerInputFiles = util::FilePath(commandLineOptions.OutputFile_.to_str() + ".re*.ll");
365 auto mergedFile = util::FilePath(commandLineOptions.OutputFile_.to_str() + ".merged.ll");
366 auto & llvmLink =
367 LlvmLinkCommand::Create(*commandGraph, { linkerInputFiles }, mergedFile, true, false);
368 hls.AddEdge(llvmLink);
369
370 auto & compileMerged = LlcCommand::Create(
371 *commandGraph,
372 mergedFile,
373 util::FilePath(commandLineOptions.OutputFile_.to_str() + ".o"),
376 llvmLink.AddEdge(compileMerged);
377
378 for (const auto & leave : leaves)
379 leave->AddEdge(commandGraph->GetExitNode());
380
381 if (commandLineOptions.OnlyPrintCommands_)
382 commandGraph = PrintCommandsCommand::Create(std::move(commandGraph));
383
384 return commandGraph;
385}
386
387}
static CommandGraph::Node & CreateParsingCommand(CommandGraph &commandGraph, const util::FilePath &inputFile, const util::FilePath &outputFile, const util::FilePath &dependencyFile, const std::vector< std::string > &includePaths, const std::vector< std::string > &macroDefinitions, const std::vector< std::string > &warnings, const std::vector< std::string > &flags, bool verbose, bool rdynamic, bool suppress, bool usePthread, bool mD, const std::string &mT, const LanguageStandard &languageStandard, const std::vector< ClangArgument > &clangArguments)
Definition Command.hpp:195
const util::FilePath & OutputFile() const noexcept
Definition Command.hpp:169
static CommandGraph::Node & CreateLinkerCommand(CommandGraph &commandGraph, const std::vector< util::FilePath > &inputFiles, const util::FilePath &outputFile, const std::vector< std::string > &libraryPaths, const std::vector< std::string > &libraries, bool usePthreads)
Definition Command.hpp:181
static std::unique_ptr< CommandGraph > Create()
static util::FilePath CreateJlmOptCommandOutputFile(const util::FilePath &tmpDirectory, const util::FilePath &inputFile)
~JhlsCommandGraphGenerator() noexcept override
static LlcCommand::OptimizationLevel ConvertOptimizationLevel(const JhlsCommandLineOptions::OptimizationLevel &optimizationLevel)
std::unique_ptr< CommandGraph > GenerateCommandGraph(const JhlsCommandLineOptions &commandLineOptions) override
static util::FilePath CreateParserCommandOutputFile(const util::FilePath &tmpDirectory, const util::FilePath &inputFile)
static ClangCommand::LanguageStandard ConvertLanguageStandard(const JhlsCommandLineOptions::LanguageStandard &languageStandard)
std::vector< std::string > MacroDefinitions_
std::vector< std::string > IncludePaths_
std::vector< std::string > Flags_
std::vector< Compilation > Compilations_
std::vector< std::string > Warnings_
std::vector< std::string > JlmHls_
std::unique_ptr< CommandGraph > GenerateCommandGraph(const JlcCommandLineOptions &commandLineOptions) override
static util::FilePath CreateParserCommandOutputFile(const util::FilePath &inputFile)
static LlcCommand::OptimizationLevel ConvertOptimizationLevel(const JlcCommandLineOptions::OptimizationLevel &optimizationLevel)
static ClangCommand::LanguageStandard ConvertLanguageStandard(const JlcCommandLineOptions::LanguageStandard &languageStandard)
static CommandGraph::Node & CreateParserCommand(CommandGraph &commandGraph, const util::FilePath &outputFile, const JlcCommandLineOptions::Compilation &compilation, const JlcCommandLineOptions &commandLineOptions)
~JlcCommandGraphGenerator() noexcept override
static util::FilePath CreateJlmOptCommandOutputFile(const util::FilePath &inputFile)
const util::FilePath & DependencyFile() const noexcept
const std::string & Mt() const noexcept
const util::FilePath & InputFile() const noexcept
util::HashSet< util::Statistics::Id > JlmOptPassStatistics_
std::vector< Compilation > Compilations_
std::vector< std::string > Warnings_
std::vector< JlmOptCommandLineOptions::OptimizationId > JlmOptOptimizations_
std::vector< std::string > LibraryPaths_
std::vector< std::string > Libraries_
std::vector< std::string > MacroDefinitions_
std::vector< std::string > Flags_
std::vector< std::string > IncludePaths_
static CommandGraph::Node & Create(CommandGraph &commandGraph, const util::FilePath &inputFile, const util::FilePath &outputFolder, const std::vector< std::string > &options)
Definition Command.hpp:629
util::FilePath HlsFunctionFile() const noexcept
Definition Command.hpp:667
static CommandGraph::Node & Create(CommandGraph &commandGraph, const util::FilePath &inputFile, const std::string &hlsFunctionName, const util::FilePath &outputFolder)
Definition Command.hpp:691
static CommandGraph::Node & Create(CommandGraph &commandGraph, std::string programName, const JlmOptCommandLineOptions &commandLineOptions)
Definition Command.hpp:351
static CommandGraph::Node & Create(CommandGraph &commandGraph, const util::FilePath &inputFile, const util::FilePath &outputFile, const OptimizationLevel &optimizationLevel, const RelocationModel &relocationModel)
Definition Command.hpp:309
static CommandGraph::Node & Create(CommandGraph &commandGraph, const std::vector< util::FilePath > &inputFiles, const util::FilePath &outputFile, bool writeLlvmAssembly, bool verbose)
Definition Command.hpp:558
static CommandGraph::Node & Create(CommandGraph &commandGraph, const util::FilePath &inputFile, const util::FilePath &outputFile, bool writeLlvmAssembly, const std::vector< Optimization > &optimizations)
Definition Command.hpp:499
const util::FilePath & OutputFile() const noexcept
Definition Command.hpp:493
static CommandGraph::Node & Create(CommandGraph &commandGraph, const util::FilePath &path)
Definition Command.hpp:455
static std::unique_ptr< CommandGraph > Create(std::unique_ptr< CommandGraph > commandGraph)
Definition Command.cpp:92
static FilePath createUniqueFileName(const FilePath &directory, const std::string &fileNamePrefix, const std::string &fileNameSuffix)
Generates a unique file in a given directory with a prefix and suffix.
Definition file.hpp:301
static FilePath TempDirectoryPath()
Definition file.hpp:317
std::string base() const noexcept
Returns the base name of the file without the path.
Definition file.hpp:61
const std::string & to_str() const noexcept
Definition file.hpp:275
#define JLM_ASSERT(x)
Definition common.hpp:16