CIRCT  20.0.0git
SystemCEmissionPatterns.cpp
Go to the documentation of this file.
1 //===- SystemCEmissionPatterns.cpp - SystemC Dialect Emission Patterns ----===//
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 implements the emission patterns for the systemc dialect.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "../EmissionPrinter.h"
16 
17 using namespace circt;
18 using namespace circt::systemc;
19 using namespace circt::ExportSystemC;
20 
21 //===----------------------------------------------------------------------===//
22 // Operation emission patterns.
23 //===----------------------------------------------------------------------===//
24 
25 namespace {
26 /// Emit a SystemC module using the SC_MODULE macro and emit all ports as fields
27 /// of the module. Users of the ports request an expression to be inlined and we
28 /// simply return the name of the port.
29 struct SCModuleEmitter : OpEmissionPattern<SCModuleOp> {
30  using OpEmissionPattern::OpEmissionPattern;
31  MatchResult matchInlinable(Value value) override {
32  if (isa<BlockArgument>(value) &&
33  value.getParentRegion()->getParentOfType<SCModuleOp>())
34  return Precedence::VAR;
35  return {};
36  }
37 
38  void emitInlined(Value value, EmissionPrinter &p) override {
39  auto module = value.getParentRegion()->getParentOfType<SCModuleOp>();
40  for (size_t i = 0, e = module.getNumArguments(); i < e; ++i) {
41  if (module.getArgument(i) == value) {
42  p << cast<StringAttr>(module.getPortNames()[i]).getValue();
43  return;
44  }
45  }
46  }
47 
48  void emitStatement(SCModuleOp module, EmissionPrinter &p) override {
49  // Emit a newline at the start to ensure an empty line before the module for
50  // better readability.
51  p << "\nSC_MODULE(" << module.getModuleName() << ") ";
52  auto scope = p.getOstream().scope("{\n", "};\n");
53  for (size_t i = 0, e = module.getNumArguments(); i < e; ++i) {
54  p.emitType(module.getArgument(i).getType());
55 
56  auto portName = cast<StringAttr>(module.getPortNames()[i]).getValue();
57  p << " " << portName << ";\n";
58  }
59 
60  p.emitRegion(module.getRegion(), scope);
61  }
62 };
63 
64 /// Emit a systemc.signal.write operation by using the explicit 'write' member
65 /// function of the signal and port classes.
66 struct SignalWriteEmitter : OpEmissionPattern<SignalWriteOp> {
67  using OpEmissionPattern::OpEmissionPattern;
68 
69  void emitStatement(SignalWriteOp op, EmissionPrinter &p) override {
70  p.getInlinable(op.getDest()).emit();
71  p << ".write(";
72  p.getInlinable(op.getSrc()).emit();
73  p << ");\n";
74  }
75 };
76 
77 /// Emit a systemc.signal.read operation by using the explicit 'read' member
78 /// function of the signal and port classes.
79 struct SignalReadEmitter : OpEmissionPattern<SignalReadOp> {
80  using OpEmissionPattern::OpEmissionPattern;
81 
82  MatchResult matchInlinable(Value value) override {
83  if (value.getDefiningOp<SignalReadOp>())
84  return Precedence::FUNCTION_CALL;
85  return {};
86  }
87 
88  void emitInlined(Value value, EmissionPrinter &p) override {
89  p.getInlinable(value.getDefiningOp<SignalReadOp>().getInput()).emit();
90  p << ".read()";
91  }
92 };
93 
94 /// Emit a systemc.cpp.new operation.
95 struct NewEmitter : OpEmissionPattern<NewOp> {
96  using OpEmissionPattern::OpEmissionPattern;
97 
98  MatchResult matchInlinable(Value value) override {
99  if (value.getDefiningOp<NewOp>())
100  return Precedence::NEW;
101  return {};
102  }
103 
104  void emitInlined(Value value, EmissionPrinter &p) override {
105  p << "new ";
106  p.emitType(cast<mlir::emitc::PointerType>(value.getType()).getPointee());
107 
108  auto newOp = value.getDefiningOp<NewOp>();
109  if (newOp.getArgs().empty())
110  return;
111 
112  p << "(";
113  llvm::interleaveComma(newOp.getArgs(), p, [&](Value arg) {
114  p.getInlinable(arg).emitWithParensOnLowerPrecedence(Precedence::COMMA);
115  });
116  p << ")";
117  }
118 };
119 
120 /// Emit a systemc.ctor operation by using the SC_CTOR macro.
121 struct CtorEmitter : OpEmissionPattern<CtorOp> {
122  using OpEmissionPattern::OpEmissionPattern;
123 
124  void emitStatement(CtorOp op, EmissionPrinter &p) override {
125  // Emit a new line before the SC_CTOR to ensure an empty line for better
126  // readability.
127  p << "\nSC_CTOR(" << op->getParentOfType<SCModuleOp>().getModuleName()
128  << ") ";
129  p.emitRegion(op.getBody());
130  }
131 };
132 
133 /// Emit a systemc.cpp.destructor operation.
134 struct DestructorEmitter : OpEmissionPattern<DestructorOp> {
135  using OpEmissionPattern::OpEmissionPattern;
136 
137  void emitStatement(DestructorOp op, EmissionPrinter &p) override {
138  // Emit a new line before the destructor to ensure an empty line for better
139  // readability.
140  // TODO: the 'override' keyword is hardcoded here because the destructor can
141  // only be inside a class inheriting from 'sc_module', if we ever support
142  // custom classes the override should probably be a unitAttr on the
143  // destructor operation.
144  p << "\n~" << op->getParentOfType<SCModuleOp>().getModuleName()
145  << "() override ";
146  p.emitRegion(op.getBody());
147  }
148 };
149 
150 /// Emit a systemc.func operation.
151 struct SCFuncEmitter : OpEmissionPattern<SCFuncOp> {
152  using OpEmissionPattern::OpEmissionPattern;
153 
154  MatchResult matchInlinable(Value value) override {
155  if (value.getDefiningOp<SCFuncOp>())
156  return Precedence::VAR;
157  return {};
158  }
159 
160  void emitInlined(Value value, EmissionPrinter &p) override {
161  p << value.getDefiningOp<SCFuncOp>().getName();
162  }
163 
164  void emitStatement(SCFuncOp op, EmissionPrinter &p) override {
165  // Emit a new line before the member function to ensure an empty line for
166  // better readability.
167  p << "\nvoid " << op.getName() << "() ";
168  p.emitRegion(op.getBody());
169  }
170 };
171 
172 /// Emit a systemc.method operation by using the SC_METHOD macro.
173 struct MethodEmitter : OpEmissionPattern<MethodOp> {
174  using OpEmissionPattern::OpEmissionPattern;
175 
176  void emitStatement(MethodOp op, EmissionPrinter &p) override {
177  p << "SC_METHOD(";
178  p.getInlinable(op.getFuncHandle()).emit();
179  p << ");\n";
180  }
181 };
182 
183 /// Emit a systemc.sensitive operation by using the 'sensitive' data member;
184 struct SensitiveEmitter : OpEmissionPattern<SensitiveOp> {
185  using OpEmissionPattern::OpEmissionPattern;
186 
187  void emitStatement(SensitiveOp op, EmissionPrinter &p) override {
188  if (op.getSensitivities().empty())
189  return;
190 
191  p << "sensitive << ";
192  llvm::interleave(
193  op.getSensitivities(), p,
194  [&](Value sensitive) {
195  p.getInlinable(sensitive).emitWithParensOnLowerPrecedence(
196  Precedence::SHL);
197  },
198  " << ");
199  p << ";\n";
200  }
201 };
202 
203 /// Emit a systemc.thread operation by using the SC_THREAD macro.
204 struct ThreadEmitter : OpEmissionPattern<ThreadOp> {
205  using OpEmissionPattern::OpEmissionPattern;
206 
207  void emitStatement(ThreadOp op, EmissionPrinter &p) override {
208  p << "SC_THREAD(";
209  p.getInlinable(op.getFuncHandle()).emit();
210  p << ");\n";
211  }
212 };
213 
214 /// Emit a systemc.cpp.delete operation.
215 struct DeleteEmitter : OpEmissionPattern<DeleteOp> {
216  using OpEmissionPattern::OpEmissionPattern;
217 
218  void emitStatement(DeleteOp op, EmissionPrinter &p) override {
219  p << "delete ";
220  p.getInlinable(op.getPointer())
221  .emitWithParensOnLowerPrecedence(Precedence::DELETE);
222  p << ";\n";
223  }
224 };
225 
226 /// Emit a systemc.signal operation.
227 struct SignalEmitter : OpEmissionPattern<SignalOp> {
228  using OpEmissionPattern::OpEmissionPattern;
229 
230  MatchResult matchInlinable(Value value) override {
231  if (llvm::isa_and_nonnull<SignalOp>(value.getDefiningOp()))
232  return Precedence::VAR;
233  return {};
234  }
235 
236  void emitInlined(Value value, EmissionPrinter &p) override {
237  p << value.getDefiningOp<SignalOp>().getName();
238  }
239 
240  void emitStatement(SignalOp op, EmissionPrinter &p) override {
241  p.emitType(op.getSignal().getType());
242  p << " ";
243 
244  if (op.getNamed()) {
245  // This style of emitting SC_NAMED requires the printed code to be
246  // compiled with at least C++11.
247  p << "SC_NAMED(" << op.getName() << ");\n";
248  return;
249  }
250 
251  p << op.getName() << ";\n";
252  }
253 };
254 
255 /// Emit a systemc.instance.decl operation.
256 struct InstanceDeclEmitter : OpEmissionPattern<InstanceDeclOp> {
257  using OpEmissionPattern::OpEmissionPattern;
258 
259  MatchResult matchInlinable(Value value) override {
260  if (value.getDefiningOp<InstanceDeclOp>())
261  return Precedence::VAR;
262  return {};
263  }
264 
265  void emitInlined(Value value, EmissionPrinter &p) override {
266  p << value.getDefiningOp<InstanceDeclOp>().getName();
267  }
268 
269  void emitStatement(InstanceDeclOp op, EmissionPrinter &p) override {
270  p.emitType(op.getInstanceType());
271  p << " " << op.getName() << ";\n";
272  }
273 };
274 } // namespace
275 
276 /// Emit a systemc.instance.bind_port operation using the operator() rather than
277 /// .bind() variant.
278 struct BindPortEmitter : OpEmissionPattern<BindPortOp> {
279  using OpEmissionPattern::OpEmissionPattern;
280 
281  void emitStatement(BindPortOp op, EmissionPrinter &p) override {
282  p.getInlinable(op.getInstance())
283  .emitWithParensOnLowerPrecedence(Precedence::MEMBER_ACCESS);
284 
285  p << "." << op.getPortName() << "(";
286  p.getInlinable(op.getChannel()).emit();
287  p << ");\n";
288  }
289 };
290 
291 /// Emit a systemc.cpp.member_access operation.
292 struct MemberAccessEmitter : OpEmissionPattern<MemberAccessOp> {
293  using OpEmissionPattern::OpEmissionPattern;
294 
295  MatchResult matchInlinable(Value value) override {
296  if (value.getDefiningOp<MemberAccessOp>())
297  return Precedence::MEMBER_ACCESS;
298  return {};
299  }
300 
301  void emitInlined(Value value, EmissionPrinter &p) override {
302  auto op = value.getDefiningOp<MemberAccessOp>();
303  p.getInlinable(op.getObject())
304  .emitWithParensOnLowerPrecedence(Precedence::MEMBER_ACCESS);
305 
306  if (op.getAccessKind() == MemberAccessKind::Arrow)
307  p << "->";
308  else if (op.getAccessKind() == MemberAccessKind::Dot)
309  p << ".";
310  else
311  p.emitError(op, "member access kind not implemented");
312 
313  p << op.getMemberName();
314  }
315 };
316 
317 /// Emit a systemc.cpp.assign operation.
318 struct AssignEmitter : OpEmissionPattern<AssignOp> {
319  using OpEmissionPattern::OpEmissionPattern;
320 
321  void emitStatement(AssignOp op, EmissionPrinter &p) override {
322  p.getInlinable(op.getDest())
323  .emitWithParensOnLowerPrecedence(Precedence::ASSIGN);
324  p << " = ";
325  p.getInlinable(op.getSource())
326  .emitWithParensOnLowerPrecedence(Precedence::ASSIGN);
327  p << ";\n";
328  }
329 };
330 
331 /// Emit a systemc.cpp.variable operation.
332 struct VariableEmitter : OpEmissionPattern<VariableOp> {
333  using OpEmissionPattern::OpEmissionPattern;
334 
335  MatchResult matchInlinable(Value value) override {
336  if (value.getDefiningOp<VariableOp>())
337  return Precedence::VAR;
338  return {};
339  }
340 
341  void emitInlined(Value value, EmissionPrinter &p) override {
342  p << value.getDefiningOp<VariableOp>().getName();
343  }
344 
345  void emitStatement(VariableOp op, EmissionPrinter &p) override {
346  p.emitType(op.getVariable().getType());
347  p << " " << op.getName();
348 
349  if (op.getInit()) {
350  p << " = ";
351  p.getInlinable(op.getInit())
352  .emitWithParensOnLowerPrecedence(Precedence::ASSIGN);
353  }
354 
355  p << ";\n";
356  }
357 };
358 
359 /// Emit a systemc.cpp.func function. Users of the function arguments request an
360 /// expression to be inlined and we simply return the name of the argument. This
361 /// name has to be passed to this emission pattern via an array of strings
362 /// attribute called 'argNames' because the emitter cannot do any name uniquing
363 /// as it just emits the IR statement by statement. However, relying on an
364 /// attribute for the argument names also has the advantage that the names
365 /// can be preserved 1-1 during a lowering pipeline and upstream passes have
366 /// more control on how the arguments should be named (e.g. when they create a
367 /// function and have some context to assign better names).
368 struct FuncEmitter : OpEmissionPattern<FuncOp> {
369  using OpEmissionPattern::OpEmissionPattern;
370  MatchResult matchInlinable(Value value) override {
371  // Note that the verifier of systemc::FuncOp guarantees that whenever the
372  // function has a body, argNames is present and of the correct length
373  if (isa<BlockArgument>(value) &&
374  value.getParentRegion()->getParentOfType<FuncOp>())
375  return Precedence::VAR;
376 
377  return {};
378  }
379 
380  void emitInlined(Value value, EmissionPrinter &p) override {
381  auto func = value.getParentRegion()->getParentOfType<FuncOp>();
382  for (auto [arg, name] :
383  llvm::zip(func.getArguments(), func.getArgNames())) {
384  if (arg == value) {
385  p << cast<StringAttr>(name).getValue();
386  return;
387  }
388  }
389  }
390 
391  void emitStatement(FuncOp func, EmissionPrinter &p) override {
392  // Emit a newline at the start to ensure an empty line before the function
393  // for better readability.
394  p << "\n";
395 
396  if (func.getExternC())
397  p << "extern \"C\" ";
398 
399  // Emit return type.
400  if (func.getFunctionType().getNumResults() == 0)
401  p << "void";
402  else
403  p.emitType(func.getFunctionType().getResult(0));
404 
405  p << " " << func.getSymName() << "(";
406 
407  // Emit the argument list. When the function is a declaration, it is not
408  // required to have argument names, in that case just print the types.
409  if (func.isDeclaration() && func.getArgNames().empty())
410  llvm::interleaveComma(func.getFunctionType().getInputs(), p,
411  [&](Type ty) { p.emitType(ty); });
412  else
413  llvm::interleaveComma(
414  llvm::zip(func.getFunctionType().getInputs(), func.getArgNames()), p,
415  [&](std::tuple<Type, Attribute> arg) {
416  p.emitType(std::get<0>(arg));
417  p << " " << cast<StringAttr>(std::get<1>(arg)).getValue();
418  });
419 
420  p << ")";
421 
422  // Emit body when present.
423  if (func.isDeclaration()) {
424  p << ";\n";
425  } else {
426  p << " ";
427  p.emitRegion(func.getRegion());
428  }
429  }
430 };
431 
432 /// Emit a systemc.cpp.call operation. If it has no result, it is treated as a
433 /// statement, otherwise as an expression that will always be inlined. That
434 /// means, an emission preparation pass has to insert a VariableOp to bind the
435 /// call result to such that reordering of the call cannot lead to incorrectness
436 /// due to interference of side-effects.
437 class CallEmitter : public OpEmissionPattern<CallOp> {
438  using OpEmissionPattern::OpEmissionPattern;
439 
440  MatchResult matchInlinable(Value value) override {
441  if (value.getDefiningOp<CallOp>())
442  return Precedence::FUNCTION_CALL;
443  return {};
444  }
445 
446  void emitInlined(Value value, EmissionPrinter &p) override {
447  printCall(value.getDefiningOp<CallOp>(), p);
448  }
449 
450  void emitStatement(CallOp op, EmissionPrinter &p) override {
451  // If the call returns values, then it is treated as an expression rather
452  // than a statement.
453  if (op.getNumResults() > 0)
454  return;
455 
456  printCall(op, p);
457  p << ";\n";
458  }
459 
460 private:
461  void printCall(CallOp op, EmissionPrinter &p) {
462  p << op.getCallee() << "(";
463  llvm::interleaveComma(op.getOperands(), p, [&](auto arg) {
464  p.getInlinable(arg).emitWithParensOnLowerPrecedence(Precedence::COMMA);
465  });
466  p << ")";
467  }
468 };
469 
470 /// Emit a systemc.cpp.call_indirect operation. If it has no result, it is
471 /// treated as a statement, otherwise as an expression that will always be
472 /// inlined. That means, an emission preparation pass has to insert a VariableOp
473 /// to bind the call result to such that reordering of the call cannot lead to
474 /// incorrectness due to interference of side-effects.
475 class CallIndirectEmitter : public OpEmissionPattern<CallIndirectOp> {
476  using OpEmissionPattern::OpEmissionPattern;
477 
478  MatchResult matchInlinable(Value value) override {
479  if (value.getDefiningOp<CallIndirectOp>())
480  return Precedence::FUNCTION_CALL;
481 
482  return {};
483  }
484 
485  void emitInlined(Value value, EmissionPrinter &p) override {
486  printCall(value.getDefiningOp<CallIndirectOp>(), p);
487  }
488 
489  void emitStatement(CallIndirectOp op, EmissionPrinter &p) override {
490  // If the call returns values, then it is treated as an expression rather
491  // than a statement.
492  if (op.getNumResults() > 0)
493  return;
494 
495  printCall(op, p);
496  p << ";\n";
497  }
498 
499 private:
500  void printCall(CallIndirectOp op, EmissionPrinter &p) {
501  p.getInlinable(op.getCallee())
502  .emitWithParensOnLowerPrecedence(Precedence::FUNCTION_CALL);
503  p << "(";
504  llvm::interleaveComma(op.getCalleeOperands(), p, [&](auto arg) {
505  p.getInlinable(arg).emitWithParensOnLowerPrecedence(Precedence::COMMA);
506  });
507  p << ")";
508  }
509 };
510 
511 /// Emit a systemc.cpp.return operation.
512 struct ReturnEmitter : OpEmissionPattern<ReturnOp> {
513  using OpEmissionPattern::OpEmissionPattern;
514 
515  bool matchStatement(Operation *op) override {
516  return isa<ReturnOp>(op) && cast<ReturnOp>(op)->getNumOperands() <= 1;
517  }
518 
519  void emitStatement(ReturnOp op, EmissionPrinter &p) override {
520  p << "return";
521  if (!op.getReturnValues().empty()) {
522  p << " ";
523  p.getInlinable(op.getReturnValues()[0]).emit();
524  }
525  p << ";\n";
526  }
527 };
528 
529 //===----------------------------------------------------------------------===//
530 // Type emission patterns.
531 //===----------------------------------------------------------------------===//
532 
533 namespace {
534 /// Emit SystemC signal and port types according to the specification listed in
535 /// their ODS description.
536 template <typename Ty, const char Mn[]>
537 struct SignalTypeEmitter : public TypeEmissionPattern<Ty> {
538  void emitType(Ty type, EmissionPrinter &p) override {
539  p << Mn << "<";
540  p.emitType(type.getBaseType());
541  p << ">";
542  }
543 };
544 
545 /// Emit a systemc::ModuleType by just printing the module name as we are
546 /// dealing with a nominal type system.
547 struct ModuleTypeEmitter : public TypeEmissionPattern<ModuleType> {
548  void emitType(ModuleType type, EmissionPrinter &p) override {
549  p << type.getModuleName().getValue();
550  }
551 };
552 
553 /// Emit SystemC integer and bit-vector types with known-at-compile-time
554 /// bit-width according to the specification listed in their class description.
555 template <typename Ty>
556 struct IntegerTypeEmitter : public TypeEmissionPattern<Ty> {
557  void emitType(Ty type, EmissionPrinter &p) override {
558  p << "sc_" << Ty::getMnemonic() << "<" << type.getWidth() << ">";
559  }
560 };
561 
562 /// Emit SystemC integer and bit-vector types without known bit-width according
563 /// to the specification listed in their class description.
564 template <typename Ty>
565 struct DynIntegerTypeEmitter : public TypeEmissionPattern<Ty> {
566  void emitType(Ty type, EmissionPrinter &p) override {
567  p << "sc_" << Ty::getMnemonic();
568  }
569 };
570 } // namespace
571 
572 //===----------------------------------------------------------------------===//
573 // Register Operation and Type emission patterns.
574 //===----------------------------------------------------------------------===//
575 
577  OpEmissionPatternSet &patterns, MLIRContext *context) {
578  patterns.add<
579  SCModuleEmitter, CtorEmitter, SCFuncEmitter, MethodEmitter, ThreadEmitter,
580  // Signal and port related emitters
581  SignalWriteEmitter, SignalReadEmitter, SignalEmitter, SensitiveEmitter,
582  // Instance-related emitters
583  InstanceDeclEmitter, BindPortEmitter,
584  // CPP-level operation emitters
585  AssignEmitter, VariableEmitter, NewEmitter, DestructorEmitter,
586  DeleteEmitter, MemberAccessEmitter,
587  // Function related emitters
589 }
590 
593  static constexpr const char in[] = "sc_in";
594  static constexpr const char inout[] = "sc_inout";
595  static constexpr const char out[] = "sc_out";
596  static constexpr const char signal[] = "sc_signal";
597 
598  patterns.add<
599  // Port and signal types
600  SignalTypeEmitter<InputType, in>, SignalTypeEmitter<InOutType, inout>,
601  SignalTypeEmitter<OutputType, out>, SignalTypeEmitter<SignalType, signal>,
602  // SystemC integers with statically known bit-width
603  IntegerTypeEmitter<IntType>, IntegerTypeEmitter<UIntType>,
604  IntegerTypeEmitter<BigIntType>, IntegerTypeEmitter<BigUIntType>,
605  // SystemC integers without statically known bit-width
606  DynIntegerTypeEmitter<IntBaseType>, DynIntegerTypeEmitter<UIntBaseType>,
607  DynIntegerTypeEmitter<SignedType>, DynIntegerTypeEmitter<UnsignedType>,
608  // Vector types with statically known bit-width
609  IntegerTypeEmitter<BitVectorType>, IntegerTypeEmitter<LogicVectorType>,
610  // Vector types without statically known bit-width
611  DynIntegerTypeEmitter<BitVectorBaseType>,
612  DynIntegerTypeEmitter<LogicVectorBaseType>,
613  // Misc types
614  DynIntegerTypeEmitter<LogicType>, ModuleTypeEmitter>();
615 }
Emit a systemc.cpp.call operation.
void printCall(CallOp op, EmissionPrinter &p)
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
void emitInlined(Value value, EmissionPrinter &p) override
void emitStatement(CallOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
Emit a systemc.cpp.call_indirect operation.
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
void printCall(CallIndirectOp op, EmissionPrinter &p)
void emitInlined(Value value, EmissionPrinter &p) override
void emitStatement(CallIndirectOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
This class collects a set of emission patterns with base type 'PatternTy'.
This is intended to be the driving class for all pattern-based IR emission.
void emitRegion(Region &region)
Emit the given region to the ostream associated with this printer.
InlineEmitter getInlinable(Value value)
Emit the expression represented by the given value to the ostream associated with this printer accord...
void emitType(Type type)
Emit the given type to the ostream associated with this printer according to the emission patterns re...
mlir::raw_indented_ostream & getOstream() const
InFlightDiagnostic emitError(Operation *op, const Twine &message)
Emit an error on the operation and fail emission.
void emitWithParensOnLowerPrecedence(Precedence prec, StringRef lParen="(", StringRef rParen=")") const
This class allows a pattern's match function for inlining to pass its result's precedence to the patt...
void populateSystemCOpEmitters(OpEmissionPatternSet &patterns, MLIRContext *context)
Register SystemC operation emission patterns.
void populateSystemCTypeEmitters(TypeEmissionPatternSet &patterns)
Register SystemC type emission patterns.
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
Emit a systemc.cpp.assign operation.
void emitStatement(AssignOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
Emit a systemc.instance.bind_port operation using the operator() rather than .bind() variant.
void emitStatement(BindPortOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
Emit a systemc.cpp.func function.
void emitInlined(Value value, EmissionPrinter &p) override
void emitStatement(FuncOp func, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
Emit a systemc.cpp.member_access operation.
void emitInlined(Value value, EmissionPrinter &p) override
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
Emit a systemc.cpp.return operation.
void emitStatement(ReturnOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
bool matchStatement(Operation *op) override
Emit a systemc.cpp.variable operation.
void emitStatement(VariableOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
void emitInlined(Value value, EmissionPrinter &p) override
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
This is a convenience class providing default implementations for operation emission patterns.
This is a convenience class providing default implementations for type emission patterns.