Jlm
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 
16 namespace jlm::tooling
17 {
18 
20 
21 util::FilePath
22 JlcCommandGraphGenerator::CreateJlmOptCommandOutputFile(const util::FilePath & inputFile)
23 {
26  inputFile.base() + "-",
27  "-jlm-opt.ll");
28 }
29 
32 {
35  inputFile.base() + "-",
36  "-clang.ll");
37 }
38 
41  const JlcCommandLineOptions::LanguageStandard & languageStandard)
42 {
43  static std::unordered_map<JlcCommandLineOptions::LanguageStandard, ClangCommand::LanguageStandard>
61 
62  JLM_ASSERT(map.find(languageStandard) != map.end());
63  return map[languageStandard];
64 }
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 
106 std::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(),
160  ConvertOptimizationLevel(commandLineOptions.OptimizationLevel_),
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 
204 util::FilePath
205 JhlsCommandGraphGenerator::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 
222  const JhlsCommandLineOptions::LanguageStandard & languageStandard)
223 {
224  static std::unordered_map<
244 
245  JLM_ASSERT(map.find(languageStandard) != map.end());
246  return map[languageStandard];
247 }
248 
251  const JhlsCommandLineOptions::OptimizationLevel & optimizationLevel)
252 {
253  static std::unordered_map<
260 
261  JLM_ASSERT(map.find(optimizationLevel) != map.end());
262  return map[optimizationLevel];
263 }
264 
265 std::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 }
const util::FilePath & OutputFile() const noexcept
Definition: Command.hpp:168
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:180
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:194
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:627
static CommandGraph::Node & Create(CommandGraph &commandGraph, const util::FilePath &inputFile, const std::string &hlsFunctionName, const util::FilePath &outputFolder)
Definition: Command.hpp:689
util::FilePath HlsFunctionFile() const noexcept
Definition: Command.hpp:665
static CommandGraph::Node & Create(CommandGraph &commandGraph, std::string programName, const JlmOptCommandLineOptions &commandLineOptions)
Definition: Command.hpp:350
static CommandGraph::Node & Create(CommandGraph &commandGraph, const util::FilePath &inputFile, const util::FilePath &outputFile, const OptimizationLevel &optimizationLevel, const RelocationModel &relocationModel)
Definition: Command.hpp:308
static CommandGraph::Node & Create(CommandGraph &commandGraph, const std::vector< util::FilePath > &inputFiles, const util::FilePath &outputFile, bool writeLlvmAssembly, bool verbose)
Definition: Command.hpp:556
const util::FilePath & OutputFile() const noexcept
Definition: Command.hpp:491
static CommandGraph::Node & Create(CommandGraph &commandGraph, const util::FilePath &inputFile, const util::FilePath &outputFile, bool writeLlvmAssembly, const std::vector< Optimization > &optimizations)
Definition: Command.hpp:497
static CommandGraph::Node & Create(CommandGraph &commandGraph, const util::FilePath &path)
Definition: Command.hpp:453
static std::unique_ptr< CommandGraph > Create(std::unique_ptr< CommandGraph > commandGraph)
Definition: Command.cpp:88
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
const std::string & to_str() const noexcept
Definition: file.hpp:275
std::string base() const noexcept
Returns the base name of the file without the path.
Definition: file.hpp:61
#define JLM_ASSERT(x)
Definition: common.hpp:16