CIRCT  20.0.0git
EmissionPrinter.cpp
Go to the documentation of this file.
1 //===- EmissionPrinter.cpp - EmissionPrinter implementation ---------------===//
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 EmissionPrinter class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "EmissionPrinter.h"
14 
15 using namespace circt;
16 using namespace circt::ExportSystemC;
17 
18 void EmissionPrinter::emitOp(Operation *op) {
19  currentLoc = op->getLoc();
20  auto patterns = opPatterns.getSpecificNativePatterns().lookup(op->getName());
21  for (auto *pat : patterns) {
22  if (pat->matchStatement(op)) {
23  pat->emitStatement(op, *this);
24  return;
25  }
26  }
27 
28  // Emit a placeholder to the output and an error to stderr in case no valid
29  // emission pattern was found.
30  mlir::emitError(op->getLoc(), "no emission pattern found for '")
31  << op->getName() << "'\n";
32  os << "\n<<UNSUPPORTED OPERATION (" << op->getName() << ")>>\n";
33  emissionFailed = true;
34 }
35 
36 void EmissionPrinter::emitType(Type type) {
37  auto patterns =
38  typePatterns.getSpecificNativePatterns().lookup(type.getTypeID());
39  for (auto *pat : patterns) {
40  if (pat->match(type)) {
41  pat->emitType(type, *this);
42  return;
43  }
44  }
45 
46  // Emit a placeholder to the output and an error to stderr in case no valid
47  // emission pattern was found.
48  mlir::emitError(currentLoc, "no emission pattern found for type ")
49  << type << "\n";
50  os << "<<UNSUPPORTED TYPE (" << type << ")>>";
51  emissionFailed = true;
52 }
53 
54 void EmissionPrinter::emitAttr(Attribute attr) {
55  auto patterns =
56  attrPatterns.getSpecificNativePatterns().lookup(attr.getTypeID());
57  for (auto *pat : patterns) {
58  if (pat->match(attr)) {
59  pat->emitAttr(attr, *this);
60  return;
61  }
62  }
63 
64  mlir::emitError(currentLoc, "no emission pattern found for attribute ")
65  << attr << "\n";
66  os << "<<UNSUPPORTED ATTRIBUTE (" << attr << ")>>";
67  emissionFailed = true;
68 }
69 
71  auto *op = isa<BlockArgument>(value) ? value.getParentRegion()->getParentOp()
72  : value.getDefiningOp();
73  Location requestLoc = currentLoc;
74  currentLoc = op->getLoc();
75  auto patterns = opPatterns.getSpecificNativePatterns().lookup(op->getName());
76  for (auto *pat : patterns) {
77  MatchResult match = pat->matchInlinable(value);
78  if (!match.failed()) {
79  return InlineEmitter([=]() { pat->emitInlined(value, *this); },
80  match.getPrecedence(), *this);
81  }
82  }
83 
84  // Emit a placeholder to the output and an error to stderr in case no valid
85  // emission pattern was found.
86  emissionFailed = true;
87  auto err =
88  mlir::emitError(value.getLoc(), "inlining not supported for value '")
89  << value << "'\n";
90  err.attachNote(requestLoc) << "requested to be inlined here";
91  return InlineEmitter(
92  [=]() { os << "<<INVALID VALUE TO INLINE (" << value << ")>>"; },
93  Precedence::LIT, *this);
94 }
95 
96 void EmissionPrinter::emitRegion(Region &region) {
97  auto scope = os.scope("{\n", "}\n");
98  emitRegion(region, scope);
99 }
100 
102  Region &region, mlir::raw_indented_ostream::DelimitedScope &scope) {
103  assert(region.hasOneBlock() &&
104  "only regions with exactly one block are supported for now");
105 
106  for (Operation &op : region.getBlocks().front()) {
107  emitOp(&op);
108  }
109 }
110 
111 InFlightDiagnostic EmissionPrinter::emitError(Operation *op,
112  const Twine &message) {
113  emissionFailed = true;
114  os << "<<ERROR (" << message << ")>>";
115  return op->emitOpError();
116 }
117 
118 InFlightDiagnostic EmissionPrinter::emitError(const Twine &message) {
119  emissionFailed = true;
120  os << "<<ERROR (" << message << ")>>";
121  return mlir::emitError(currentLoc, message);
122 }
123 
125  os << str;
126  return *this;
127 }
128 
130  os << std::to_string(num);
131  return *this;
132 }
133 
135  StringRef lParen,
136  StringRef rParen) const {
137  if (precedence >= prec)
138  printer << lParen;
139 
140  emitter();
141 
142  if (precedence >= prec)
143  printer << rParen;
144 }
assert(baseType &&"element must be base type")
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.
void emitOp(Operation *op)
Emit the given operation as a statement to the ostream associated with this printer according to the ...
FrozenAttrEmissionPatternSet attrPatterns
InlineEmitter getInlinable(Value value)
Emit the expression represented by the given value to the ostream associated with this printer accord...
void emitAttr(Attribute attr)
Emit the given attribute to the ostream associated with this printer according to the emission patter...
EmissionPrinter & operator<<(StringRef str)
FrozenTypeEmissionPatternSet typePatterns
void emitType(Type type)
Emit the given type to the ostream associated with this printer according to the emission patterns re...
InFlightDiagnostic emitError(Operation *op, const Twine &message)
Emit an error on the operation and fail emission.
mlir::raw_indented_ostream & os
FrozenOpEmissionPatternSet opPatterns
const OpSpecificNativePatternListT & getSpecificNativePatterns() const
Return the native patterns held by this set.
This class is returned to a pattern that requested inlined emission of a value.
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...
Precedence
This enum encodes the precedence of C++ expressions.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21