Jlm
LlvmModuleConversion.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014 2015 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
12 
13 #include <llvm/ADT/PostOrderIterator.h>
14 #include <llvm/IR/BasicBlock.h>
15 #include <llvm/IR/Function.h>
16 #include <llvm/IR/Instructions.h>
17 #include <llvm/IR/Module.h>
18 
19 namespace jlm::llvm
20 {
21 
22 static std::vector<::llvm::PHINode *>
23 convert_instructions(::llvm::Function & function, Context & ctx)
24 {
25  std::vector<::llvm::PHINode *> phis;
26  ::llvm::ReversePostOrderTraversal<::llvm::Function *> rpotraverser(&function);
27  for (auto & bb : rpotraverser)
28  {
29  for (auto & instruction : *bb)
30  {
31  tacsvector_t tacs;
32  if (auto result = ConvertInstruction(&instruction, tacs, ctx))
33  ctx.insert_value(&instruction, result);
34 
35  // When an LLVM PhiNode is converted to a jlm SsaPhiOperation, some of its operands may not be
36  // ready. The created SsaPhiOperation therefore has no operands, but is instead added to a
37  // list. Once all basic blocks have been converted, all SsaPhiOperations are revisited and
38  // given operands.
39  if (!tacs.empty() && is<SsaPhiOperation>(tacs.back()->operation()))
40  {
41  auto phi = ::llvm::dyn_cast<::llvm::PHINode>(&instruction);
42  phis.push_back(phi);
43  }
44 
45  ctx.get(bb)->append_last(tacs);
46  }
47  }
48 
49  return phis;
50 }
51 
57 static void
58 PatchPhiOperands(const std::vector<::llvm::PHINode *> & phis, Context & ctx)
59 {
60  for (const auto & phi : phis)
61  {
62  std::vector<ControlFlowGraphNode *> incomingNodes;
63  std::vector<const Variable *> operands;
64  for (size_t n = 0; n < phi->getNumOperands(); n++)
65  {
66  // In LLVM, phi instructions may have incoming basic blocks that are unreachable.
67  // These are not visited during convert_basic_blocks, and thus do not have corresponding
68  // jlm::llvm::basic_blocks. The SsaPhiOperation can safely ignore these, as they are dead.
69  if (!ctx.has(phi->getIncomingBlock(n)))
70  continue;
71 
72  // The LLVM phi instruction may have multiple operands with the same incoming cfg node.
73  // When this happens in valid LLVM IR, all operands from the same basic block are identical.
74  // We therefore skip any operands that reference already handled basic blocks.
75  auto predecessor = ctx.get(phi->getIncomingBlock(n));
76  if (std::find(incomingNodes.begin(), incomingNodes.end(), predecessor) != incomingNodes.end())
77  continue;
78 
79  // Convert the operand value in the predecessor basic block, as that is where it is "used".
80  tacsvector_t tacs;
81  operands.push_back(ConvertValue(phi->getIncomingValue(n), tacs, ctx));
82  predecessor->insert_before_branch(tacs);
83  incomingNodes.push_back(predecessor);
84  }
85 
86  JLM_ASSERT(operands.size() >= 1);
87 
88  auto phi_tac = util::assertedCast<const ThreeAddressCodeVariable>(ctx.lookup_value(phi))->tac();
89  phi_tac->replace(
90  SsaPhiOperation(std::move(incomingNodes), phi_tac->result(0)->Type()),
91  operands);
92  }
93 }
94 
95 static BasicBlockMap
96 convert_basic_blocks(::llvm::Function & f, ControlFlowGraph & cfg)
97 {
98  BasicBlockMap bbmap;
99  ::llvm::ReversePostOrderTraversal<::llvm::Function *> rpotraverser(&f);
100  for (auto & bb : rpotraverser)
101  bbmap.Insert(bb, BasicBlock::create(cfg));
102 
103  return bbmap;
104 }
105 
107 ConvertAttributeKind(const ::llvm::Attribute::AttrKind & kind)
108 {
109  typedef ::llvm::Attribute::AttrKind ak;
110 
111  static std::unordered_map<::llvm::Attribute::AttrKind, Attribute::kind> map(
112  { { ak::None, Attribute::kind::None },
113  { ak::FirstEnumAttr, Attribute::kind::FirstEnumAttr },
114  { ak::AllocAlign, Attribute::kind::AllocAlign },
115  { ak::AllocatedPointer, Attribute::kind::AllocatedPointer },
116  { ak::AlwaysInline, Attribute::kind::AlwaysInline },
117  { ak::Builtin, Attribute::kind::Builtin },
118  { ak::Cold, Attribute::kind::Cold },
119  { ak::Convergent, Attribute::kind::Convergent },
120  { ak::CoroDestroyOnlyWhenComplete, Attribute::kind::CoroDestroyOnlyWhenComplete },
121  { ak::DeadOnUnwind, Attribute::kind::DeadOnUnwind },
122  { ak::DisableSanitizerInstrumentation, Attribute::kind::DisableSanitizerInstrumentation },
123  { ak::FnRetThunkExtern, Attribute::kind::FnRetThunkExtern },
124  { ak::Hot, Attribute::kind::Hot },
125  { ak::ImmArg, Attribute::kind::ImmArg },
126  { ak::InReg, Attribute::kind::InReg },
127  { ak::InlineHint, Attribute::kind::InlineHint },
128  { ak::JumpTable, Attribute::kind::JumpTable },
129  { ak::Memory, Attribute::kind::Memory },
130  { ak::MinSize, Attribute::kind::MinSize },
131  { ak::MustProgress, Attribute::kind::MustProgress },
132  { ak::Naked, Attribute::kind::Naked },
133  { ak::Nest, Attribute::kind::Nest },
134  { ak::NoAlias, Attribute::kind::NoAlias },
135  { ak::NoBuiltin, Attribute::kind::NoBuiltin },
136  { ak::NoCallback, Attribute::kind::NoCallback },
137  { ak::NoCapture, Attribute::kind::NoCapture },
138  { ak::NoCfCheck, Attribute::kind::NoCfCheck },
139  { ak::NoDuplicate, Attribute::kind::NoDuplicate },
140  { ak::NoFree, Attribute::kind::NoFree },
141  { ak::NoImplicitFloat, Attribute::kind::NoImplicitFloat },
142  { ak::NoInline, Attribute::kind::NoInline },
143  { ak::NoMerge, Attribute::kind::NoMerge },
144  { ak::NoProfile, Attribute::kind::NoProfile },
145  { ak::NoRecurse, Attribute::kind::NoRecurse },
146  { ak::NoRedZone, Attribute::kind::NoRedZone },
147  { ak::NoReturn, Attribute::kind::NoReturn },
148  { ak::NoSanitizeBounds, Attribute::kind::NoSanitizeBounds },
149  { ak::NoSanitizeCoverage, Attribute::kind::NoSanitizeCoverage },
150  { ak::NoSync, Attribute::kind::NoSync },
151  { ak::NoUndef, Attribute::kind::NoUndef },
152  { ak::NoUnwind, Attribute::kind::NoUnwind },
153  { ak::NonLazyBind, Attribute::kind::NonLazyBind },
154  { ak::NonNull, Attribute::kind::NonNull },
155  { ak::NullPointerIsValid, Attribute::kind::NullPointerIsValid },
156  { ak::OptForFuzzing, Attribute::kind::OptForFuzzing },
157  { ak::OptimizeForDebugging, Attribute::kind::OptimizeForDebugging },
158  { ak::OptimizeForSize, Attribute::kind::OptimizeForSize },
159  { ak::OptimizeNone, Attribute::kind::OptimizeNone },
160  { ak::PresplitCoroutine, Attribute::kind::PresplitCoroutine },
161  { ak::ReadNone, Attribute::kind::ReadNone },
162  { ak::ReadOnly, Attribute::kind::ReadOnly },
163  { ak::Returned, Attribute::kind::Returned },
164  { ak::ReturnsTwice, Attribute::kind::ReturnsTwice },
165  { ak::SExt, Attribute::kind::SExt },
166  { ak::SafeStack, Attribute::kind::SafeStack },
167  { ak::SanitizeAddress, Attribute::kind::SanitizeAddress },
168  { ak::SanitizeHWAddress, Attribute::kind::SanitizeHWAddress },
169  { ak::SanitizeMemTag, Attribute::kind::SanitizeMemTag },
170  { ak::SanitizeMemory, Attribute::kind::SanitizeMemory },
171  { ak::SanitizeThread, Attribute::kind::SanitizeThread },
172  { ak::ShadowCallStack, Attribute::kind::ShadowCallStack },
173  { ak::SkipProfile, Attribute::kind::SkipProfile },
174  { ak::Speculatable, Attribute::kind::Speculatable },
175  { ak::SpeculativeLoadHardening, Attribute::kind::SpeculativeLoadHardening },
176  { ak::StackProtect, Attribute::kind::StackProtect },
177  { ak::StackProtectReq, Attribute::kind::StackProtectReq },
178  { ak::StackProtectStrong, Attribute::kind::StackProtectStrong },
179  { ak::StrictFP, Attribute::kind::StrictFP },
180  { ak::SwiftAsync, Attribute::kind::SwiftAsync },
181  { ak::SwiftError, Attribute::kind::SwiftError },
182  { ak::SwiftSelf, Attribute::kind::SwiftSelf },
183  { ak::WillReturn, Attribute::kind::WillReturn },
184  { ak::Writable, Attribute::kind::Writable },
185  { ak::WriteOnly, Attribute::kind::WriteOnly },
186  { ak::ZExt, Attribute::kind::ZExt },
187  { ak::LastEnumAttr, Attribute::kind::LastEnumAttr },
188  { ak::FirstTypeAttr, Attribute::kind::FirstTypeAttr },
189  { ak::ByRef, Attribute::kind::ByRef },
190  { ak::ByVal, Attribute::kind::ByVal },
191  { ak::ElementType, Attribute::kind::ElementType },
192  { ak::InAlloca, Attribute::kind::InAlloca },
193  { ak::Preallocated, Attribute::kind::Preallocated },
194  { ak::StructRet, Attribute::kind::StructRet },
195  { ak::LastTypeAttr, Attribute::kind::LastTypeAttr },
196  { ak::FirstIntAttr, Attribute::kind::FirstIntAttr },
197  { ak::Alignment, Attribute::kind::Alignment },
198  { ak::AllocKind, Attribute::kind::AllocKind },
199  { ak::AllocSize, Attribute::kind::AllocSize },
200  { ak::Dereferenceable, Attribute::kind::Dereferenceable },
201  { ak::DereferenceableOrNull, Attribute::kind::DereferenceableOrNull },
202  { ak::NoFPClass, Attribute::kind::NoFPClass },
203  { ak::StackAlignment, Attribute::kind::StackAlignment },
204  { ak::UWTable, Attribute::kind::UWTable },
205  { ak::VScaleRange, Attribute::kind::VScaleRange },
206  { ak::LastIntAttr, Attribute::kind::LastIntAttr },
207  { ak::EndAttrKinds, Attribute::kind::EndAttrKinds } });
208 
209  JLM_ASSERT(map.find(kind) != map.end());
210  return map[kind];
211 }
212 
213 static EnumAttribute
214 ConvertEnumAttribute(const ::llvm::Attribute & attribute)
215 {
216  JLM_ASSERT(attribute.isEnumAttribute());
217  auto kind = ConvertAttributeKind(attribute.getKindAsEnum());
218  return EnumAttribute(kind);
219 }
220 
221 static IntAttribute
222 ConvertIntAttribute(const ::llvm::Attribute & attribute)
223 {
224  JLM_ASSERT(attribute.isIntAttribute());
225  auto kind = ConvertAttributeKind(attribute.getKindAsEnum());
226  return { kind, attribute.getValueAsInt() };
227 }
228 
229 static TypeAttribute
230 ConvertTypeAttribute(const ::llvm::Attribute & attribute, Context & ctx)
231 {
232  JLM_ASSERT(attribute.isTypeAttribute());
233 
234  if (attribute.getKindAsEnum() == ::llvm::Attribute::AttrKind::ByVal)
235  {
236  auto type = ctx.GetTypeConverter().ConvertLlvmType(*attribute.getValueAsType());
237  return { Attribute::kind::ByVal, std::move(type) };
238  }
239 
240  if (attribute.getKindAsEnum() == ::llvm::Attribute::AttrKind::StructRet)
241  {
242  auto type = ctx.GetTypeConverter().ConvertLlvmType(*attribute.getValueAsType());
243  return { Attribute::kind::StructRet, std::move(type) };
244  }
245 
246  JLM_UNREACHABLE("Unhandled attribute");
247 }
248 
249 static StringAttribute
250 ConvertStringAttribute(const ::llvm::Attribute & attribute)
251 {
252  JLM_ASSERT(attribute.isStringAttribute());
253  return { attribute.getKindAsString().str(), attribute.getValueAsString().str() };
254 }
255 
256 static AttributeSet
257 convert_attributes(const ::llvm::AttributeSet & as, Context & ctx)
258 {
259  AttributeSet attributeSet;
260  for (auto & attribute : as)
261  {
262  if (attribute.isEnumAttribute())
263  {
264  attributeSet.InsertEnumAttribute(ConvertEnumAttribute(attribute));
265  }
266  else if (attribute.isIntAttribute())
267  {
268  attributeSet.InsertIntAttribute(ConvertIntAttribute(attribute));
269  }
270  else if (attribute.isTypeAttribute())
271  {
272  attributeSet.InsertTypeAttribute(ConvertTypeAttribute(attribute, ctx));
273  }
274  else if (attribute.isStringAttribute())
275  {
276  attributeSet.InsertStringAttribute(ConvertStringAttribute(attribute));
277  }
278  else
279  {
280  JLM_UNREACHABLE("Unhandled attribute");
281  }
282  }
283 
284  return attributeSet;
285 }
286 
287 static std::unique_ptr<llvm::Argument>
288 convert_argument(const ::llvm::Argument & argument, Context & ctx)
289 {
290  auto function = argument.getParent();
291  auto name = argument.getName().str();
292  auto type = ctx.GetTypeConverter().ConvertLlvmType(*argument.getType());
293  auto attributes =
294  convert_attributes(function->getAttributes().getParamAttrs(argument.getArgNo()), ctx);
295 
296  return llvm::Argument::create(name, type, attributes);
297 }
298 
299 static void
301 {
302  auto exitNode = cfg.exit();
303 
304  if (exitNode->NumInEdges() == 0)
305  {
306  /*
307  LLVM can produce CFGs that have no incoming edge to the exit node. This can happen if
308  endless loops are present in the code. For example, this code
309 
310  \code{.cpp}
311  int foo()
312  {
313  while (1) {
314  printf("foo\n");
315  }
316 
317  return 0;
318  }
319  \endcode
320 
321  results in a JLM CFG with no incoming edge to the exit node.
322 
323  We solve this problem by finding the first SCC with no exit edge, i.e., an endless loop, and
324  restructure it to an SCC with an exit edge to the CFG's exit node.
325  */
326  auto stronglyConnectedComponents = find_sccs(cfg);
327  for (auto stronglyConnectedComponent : stronglyConnectedComponents)
328  {
329  auto sccStructure = StronglyConnectedComponentStructure::Create(stronglyConnectedComponent);
330 
331  if (sccStructure->NumExitEdges() == 0)
332  {
333  auto repetitionEdge = *sccStructure->RepetitionEdges().begin();
334 
335  auto basicBlock = BasicBlock::create(cfg);
336 
337  auto op = std::make_unique<rvsdg::ControlConstantOperation>(
339  auto operand =
340  basicBlock->append_last(ThreeAddressCode::create(std::move(op), {}))->result(0);
341  basicBlock->append_last(BranchOperation::create(2, operand));
342 
343  basicBlock->add_outedge(exitNode);
344  basicBlock->add_outedge(repetitionEdge->sink());
345 
346  repetitionEdge->divert(basicBlock);
347  break;
348  }
349  }
350  }
351 
352  if (exitNode->NumInEdges() == 1)
353  return;
354 
355  /*
356  We have multiple incoming edges to the exit node. Insert an empty basic block, divert all
357  incoming edges to this block, and add an outgoing edge from this block to the exit node.
358  */
359  auto basicBlock = BasicBlock::create(cfg);
360  exitNode->divert_inedges(basicBlock);
361  basicBlock->add_outedge(exitNode);
362 }
363 
364 static std::unique_ptr<ControlFlowGraph>
365 create_cfg(::llvm::Function & f, Context & ctx)
366 {
367  auto node = static_cast<const FunctionVariable *>(ctx.lookup_value(&f))->function();
368 
369  auto add_arguments = [](const ::llvm::Function & f, ControlFlowGraph & cfg, Context & ctx)
370  {
371  auto node = static_cast<const FunctionVariable *>(ctx.lookup_value(&f))->function();
372 
373  size_t n = 0;
374  for (const auto & arg : f.args())
375  {
376  auto argument = cfg.entry()->append_argument(convert_argument(arg, ctx));
377  ctx.insert_value(&arg, argument);
378  n++;
379  }
380 
381  if (f.isVarArg())
382  {
383  JLM_ASSERT(n < node->fcttype().NumArguments());
384  auto & type = node->fcttype().Arguments()[n++];
385  cfg.entry()->append_argument(Argument::create("_varg_", type));
386  }
387  JLM_ASSERT(n < node->fcttype().NumArguments());
388 
389  auto & iotype = node->fcttype().Arguments()[n++];
390  auto iostate = cfg.entry()->append_argument(Argument::create("_io_", iotype));
391 
392  auto & memtype = node->fcttype().Arguments()[n++];
393  auto memstate = cfg.entry()->append_argument(Argument::create("_s_", memtype));
394 
395  JLM_ASSERT(n == node->fcttype().NumArguments());
396  ctx.set_iostate(iostate);
397  ctx.set_memory_state(memstate);
398  };
399 
400  auto cfg = ControlFlowGraph::create(ctx.module());
401 
402  add_arguments(f, *cfg, ctx);
403  auto bbmap = convert_basic_blocks(f, *cfg);
404 
405  /* create entry block */
406  auto entry_block = BasicBlock::create(*cfg);
407  cfg->exit()->divert_inedges(entry_block);
408  entry_block->add_outedge(bbmap.LookupKey(&f.getEntryBlock()));
409 
410  /* add results */
411  const ThreeAddressCodeVariable * result = nullptr;
412  if (!f.getReturnType()->isVoidTy())
413  {
414  auto type = ctx.GetTypeConverter().ConvertLlvmType(*f.getReturnType());
415  entry_block->append_last(UndefValueOperation::Create(type, "_r_"));
416  result = entry_block->last()->result(0);
417 
418  JLM_ASSERT(node->fcttype().NumResults() == 3);
419  JLM_ASSERT(result->type() == node->fcttype().ResultType(0));
420  cfg->exit()->append_result(result);
421  }
422  cfg->exit()->append_result(ctx.iostate());
423  cfg->exit()->append_result(ctx.memory_state());
424 
425  /* convert instructions */
426  ctx.set_basic_block_map(std::move(bbmap));
427  ctx.set_result(result);
428  auto phis = convert_instructions(f, ctx);
429  PatchPhiOperands(phis, ctx);
430 
432 
433  // Merge basic blocks A -> B when possible
434  straighten(*cfg);
435  // Remove unreachable nodes
436  prune(*cfg);
437  return cfg;
438 }
439 
440 static void
441 convert_function(::llvm::Function & function, Context & ctx)
442 {
443  if (function.isDeclaration())
444  return;
445 
446  auto fv = static_cast<const FunctionVariable *>(ctx.lookup_value(&function));
447 
448  ctx.set_node(fv->function());
449  fv->function()->add_cfg(create_cfg(function, ctx));
450  ctx.set_node(nullptr);
451 }
452 
453 static const llvm::Linkage &
454 convert_linkage(const ::llvm::GlobalValue::LinkageTypes & linkage)
455 {
456  static std::unordered_map<::llvm::GlobalValue::LinkageTypes, llvm::Linkage> map(
457  { { ::llvm::GlobalValue::ExternalLinkage, llvm::Linkage::externalLinkage },
458  { ::llvm::GlobalValue::AvailableExternallyLinkage,
460  { ::llvm::GlobalValue::LinkOnceAnyLinkage, llvm::Linkage::linkOnceAnyLinkage },
461  { ::llvm::GlobalValue::LinkOnceODRLinkage, llvm::Linkage::linkOnceOdrLinkage },
462  { ::llvm::GlobalValue::WeakAnyLinkage, llvm::Linkage::weakAnyLinkage },
463  { ::llvm::GlobalValue::WeakODRLinkage, llvm::Linkage::weakOdrLinkage },
464  { ::llvm::GlobalValue::AppendingLinkage, llvm::Linkage::appendingLinkage },
465  { ::llvm::GlobalValue::InternalLinkage, llvm::Linkage::internalLinkage },
466  { ::llvm::GlobalValue::PrivateLinkage, llvm::Linkage::privateLinkage },
467  { ::llvm::GlobalValue::ExternalWeakLinkage, llvm::Linkage::externalWeakLinkage },
468  { ::llvm::GlobalValue::CommonLinkage, llvm::Linkage::commonLinkage } });
469 
470  JLM_ASSERT(map.find(linkage) != map.end());
471  return map[linkage];
472 }
473 
474 static void
475 declare_globals(::llvm::Module & lm, Context & ctx)
476 {
477  auto create_data_node = [](const ::llvm::GlobalVariable & gv, Context & ctx)
478  {
479  auto name = gv.getName().str();
480  auto constant = gv.isConstant();
481  auto type = ctx.GetTypeConverter().ConvertLlvmType(*gv.getValueType());
482  auto linkage = convert_linkage(gv.getLinkage());
483  auto section = gv.getSection().str();
484 
485  return DataNode::Create(
486  ctx.module().ipgraph(),
487  name,
488  type,
489  linkage,
490  std::move(section),
491  constant);
492  };
493 
494  auto create_function_node = [](const ::llvm::Function & f, Context & ctx)
495  {
496  auto name = f.getName().str();
497  auto linkage = convert_linkage(f.getLinkage());
498  auto type = ctx.GetTypeConverter().ConvertFunctionType(*f.getFunctionType());
499  auto attributes = convert_attributes(f.getAttributes().getFnAttrs(), ctx);
500 
501  return FunctionNode::create(ctx.module().ipgraph(), name, type, linkage, attributes);
502  };
503 
504  for (auto & gv : lm.globals())
505  {
506  auto node = create_data_node(gv, ctx);
507  ctx.insert_value(&gv, ctx.module().create_global_value(node));
508  }
509 
510  for (auto & f : lm.getFunctionList())
511  {
512  auto node = create_function_node(f, ctx);
513  ctx.insert_value(&f, ctx.module().create_variable(node));
514  }
515 }
516 
517 static std::unique_ptr<DataNodeInit>
519 {
520  if (!gv.hasInitializer())
521  return nullptr;
522 
523  auto init = gv.getInitializer();
524  auto tacs = ConvertConstant(init, ctx);
525  if (tacs.empty())
526  return std::make_unique<DataNodeInit>(ctx.lookup_value(init));
527 
528  return std::make_unique<DataNodeInit>(std::move(tacs));
529 }
530 
531 static void
533 {
534  auto v = static_cast<const GlobalValue *>(ctx.lookup_value(&gv));
535 
536  ctx.set_node(v->node());
537  v->node()->set_initialization(create_initialization(gv, ctx));
538  ctx.set_node(nullptr);
539 }
540 
541 static void
542 convert_globals(::llvm::Module & lm, Context & ctx)
543 {
544  for (auto & gv : lm.globals())
545  convert_global_value(gv, ctx);
546 
547  for (auto & f : lm.getFunctionList())
548  convert_function(f, ctx);
549 }
550 
551 std::unique_ptr<InterProceduralGraphModule>
552 ConvertLlvmModule(::llvm::Module & llvmModule)
553 {
554  auto ipgModule = InterProceduralGraphModule::create(
555  util::FilePath(llvmModule.getSourceFileName()),
556  llvmModule.getTargetTriple(),
557  llvmModule.getDataLayoutStr());
558 
559  Context ctx(*ipgModule);
560  declare_globals(llvmModule, ctx);
561  convert_globals(llvmModule, ctx);
562 
563  return ipgModule;
564 }
565 
566 }
static std::unique_ptr< Argument > create(const std::string &name, std::shared_ptr< const jlm::rvsdg::Type > type, const AttributeSet &attributes)
Definition: cfg.hpp:58
void InsertTypeAttribute(const TypeAttribute &attribute)
Definition: attribute.hpp:344
void InsertStringAttribute(const StringAttribute &attribute)
Definition: attribute.hpp:350
void InsertEnumAttribute(const EnumAttribute &attribute)
Definition: attribute.hpp:332
void InsertIntAttribute(const IntAttribute &attribute)
Definition: attribute.hpp:338
@ None
No attributes have been set.
@ EndAttrKinds
Sentinel value useful for loops.
static BasicBlock * create(ControlFlowGraph &cfg)
Definition: basic-block.cpp:37
llvm::ThreeAddressCode * append_last(std::unique_ptr< llvm::ThreeAddressCode > tac)
static std::unique_ptr< llvm::ThreeAddressCode > create(size_t nalternatives, const Variable *operand)
Definition: operators.hpp:418
const llvm::Variable * lookup_value(const ::llvm::Value *value) const noexcept
llvm::Variable * memory_state() const noexcept
llvm::Variable * iostate() const noexcept
void set_memory_state(llvm::Variable *state)
InterProceduralGraphModule & module() const noexcept
void set_iostate(llvm::Variable *state)
void set_result(const llvm::Variable *result)
void set_basic_block_map(BasicBlockMap bbmap)
BasicBlock * get(const ::llvm::BasicBlock *bb) const noexcept
void set_node(InterProceduralGraphNode *node) noexcept
void insert_value(const ::llvm::Value *value, const llvm::Variable *variable)
TypeConverter & GetTypeConverter() noexcept
bool has(const ::llvm::BasicBlock *bb) const noexcept
static std::unique_ptr< ControlFlowGraph > create(InterProceduralGraphModule &im)
Definition: cfg.hpp:266
ExitNode * exit() const noexcept
Definition: cfg.hpp:211
static DataNode * Create(InterProceduralGraph &clg, const std::string &name, std::shared_ptr< const jlm::rvsdg::Type > valueType, const llvm::Linkage &linkage, std::string section, bool constant)
Definition: ipgraph.hpp:385
static FunctionNode * create(InterProceduralGraph &ipg, const std::string &name, std::shared_ptr< const rvsdg::FunctionType > type, const llvm::Linkage &linkage, const AttributeSet &attributes)
Definition: ipgraph.hpp:209
llvm::Variable * create_variable(std::shared_ptr< const jlm::rvsdg::Type > type, const std::string &name)
GlobalValue * create_global_value(DataNode *node)
static std::unique_ptr< InterProceduralGraphModule > create(const jlm::util::FilePath &sourceFilename, const std::string &targetTriple, const std::string &dataLayout)
InterProceduralGraph & ipgraph() noexcept
static std::unique_ptr< StronglyConnectedComponentStructure > Create(const StronglyConnectedComponent &scc)
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
Definition: tac.hpp:135
::llvm::FunctionType * ConvertFunctionType(const rvsdg::FunctionType &functionType, ::llvm::LLVMContext &context)
std::shared_ptr< const rvsdg::Type > ConvertLlvmType(::llvm::Type &type)
static jlm::rvsdg::Output * Create(rvsdg::Region &region, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1024
const jlm::rvsdg::Type & type() const noexcept
Definition: variable.hpp:56
bool Insert(const K &key, const V &value)
#define JLM_ASSERT(x)
Definition: common.hpp:16
#define JLM_UNREACHABLE(msg)
Definition: common.hpp:43
Global memory state passed between functions.
static void convert_globals(::llvm::Module &lm, Context &ctx)
std::vector< StronglyConnectedComponent > find_sccs(const ControlFlowGraph &cfg)
static IntAttribute ConvertIntAttribute(const ::llvm::Attribute &attribute)
std::vector< std::unique_ptr< llvm::ThreeAddressCode > > tacsvector_t
Definition: tac.hpp:202
static AttributeSet convert_attributes(const ::llvm::AttributeSet &as, Context &ctx)
static BasicBlockMap convert_basic_blocks(::llvm::Function &f, ControlFlowGraph &cfg)
static TypeAttribute ConvertTypeAttribute(const ::llvm::Attribute &attribute, Context &ctx)
static std::unique_ptr< DataNodeInit > create_initialization(::llvm::GlobalVariable &gv, Context &ctx)
static EnumAttribute ConvertEnumAttribute(const ::llvm::Attribute &attribute)
static const llvm::Linkage & convert_linkage(const ::llvm::GlobalValue::LinkageTypes &linkage)
const Variable * ConvertConstant(::llvm::Constant *, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &, Context &)
std::unique_ptr< InterProceduralGraphModule > ConvertLlvmModule(::llvm::Module &llvmModule)
static void PatchPhiOperands(const std::vector<::llvm::PHINode * > &phis, Context &ctx)
const Variable * ConvertValue(::llvm::Value *v, tacsvector_t &tacs, Context &ctx)
static std::unique_ptr< ControlFlowGraph > create_cfg(::llvm::Function &f, Context &ctx)
static void declare_globals(::llvm::Module &lm, Context &ctx)
static StringAttribute ConvertStringAttribute(const ::llvm::Attribute &attribute)
static void convert_global_value(::llvm::GlobalVariable &gv, Context &ctx)
void straighten(ControlFlowGraph &cfg)
static std::vector<::llvm::PHINode * > convert_instructions(::llvm::Function &function, Context &ctx)
static std::unique_ptr< llvm::Argument > convert_argument(const ::llvm::Argument &argument, Context &ctx)
const Variable * ConvertInstruction(::llvm::Instruction *i, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static void EnsureSingleInEdgeToExitNode(ControlFlowGraph &cfg)
static const Variable * convert_function(::llvm::Constant *c, tacsvector_t &tacs, Context &ctx)
Attribute::kind ConvertAttributeKind(const ::llvm::Attribute::AttrKind &kind)
util::BijectiveMap< const ::llvm::BasicBlock *, BasicBlock * > BasicBlockMap
void prune(ControlFlowGraph &cfg)
static std::string type(const Node *n)
Definition: view.cpp:255
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
Definition: node.hpp:1049