12f0750ddSMarius Brehler //===- TranslateToCpp.cpp - Translating to C++ calls ----------------------===//
22f0750ddSMarius Brehler //
32f0750ddSMarius Brehler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42f0750ddSMarius Brehler // See https://llvm.org/LICENSE.txt for license information.
52f0750ddSMarius Brehler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62f0750ddSMarius Brehler //
72f0750ddSMarius Brehler //===----------------------------------------------------------------------===//
82f0750ddSMarius Brehler 
9eda6f907SRiver Riddle #include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
10ace01605SRiver Riddle #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
112f0750ddSMarius Brehler #include "mlir/Dialect/EmitC/IR/EmitC.h"
1223aa5a74SRiver Riddle #include "mlir/Dialect/Func/IR/FuncOps.h"
138b68da2cSAlex Zinenko #include "mlir/Dialect/SCF/IR/SCF.h"
142f0750ddSMarius Brehler #include "mlir/IR/BuiltinOps.h"
152f0750ddSMarius Brehler #include "mlir/IR/BuiltinTypes.h"
162f0750ddSMarius Brehler #include "mlir/IR/Dialect.h"
172f0750ddSMarius Brehler #include "mlir/IR/Operation.h"
182f0750ddSMarius Brehler #include "mlir/Support/IndentedOstream.h"
192f0750ddSMarius Brehler #include "mlir/Target/Cpp/CppEmitter.h"
202f0750ddSMarius Brehler #include "llvm/ADT/DenseMap.h"
212f0750ddSMarius Brehler #include "llvm/ADT/StringExtras.h"
222f0750ddSMarius Brehler #include "llvm/ADT/StringMap.h"
232f0750ddSMarius Brehler #include "llvm/ADT/TypeSwitch.h"
242f0750ddSMarius Brehler #include "llvm/Support/Debug.h"
252f0750ddSMarius Brehler #include "llvm/Support/FormatVariadic.h"
26ace01605SRiver Riddle #include <utility>
272f0750ddSMarius Brehler 
282f0750ddSMarius Brehler #define DEBUG_TYPE "translate-to-cpp"
292f0750ddSMarius Brehler 
302f0750ddSMarius Brehler using namespace mlir;
312f0750ddSMarius Brehler using namespace mlir::emitc;
322f0750ddSMarius Brehler using llvm::formatv;
332f0750ddSMarius Brehler 
342f0750ddSMarius Brehler /// Convenience functions to produce interleaved output with functions returning
352f0750ddSMarius Brehler /// a LogicalResult. This is different than those in STLExtras as functions used
362f0750ddSMarius Brehler /// on each element doesn't return a string.
372f0750ddSMarius Brehler template <typename ForwardIterator, typename UnaryFunctor,
382f0750ddSMarius Brehler           typename NullaryFunctor>
392f0750ddSMarius Brehler inline LogicalResult
interleaveWithError(ForwardIterator begin,ForwardIterator end,UnaryFunctor eachFn,NullaryFunctor betweenFn)402f0750ddSMarius Brehler interleaveWithError(ForwardIterator begin, ForwardIterator end,
412f0750ddSMarius Brehler                     UnaryFunctor eachFn, NullaryFunctor betweenFn) {
422f0750ddSMarius Brehler   if (begin == end)
432f0750ddSMarius Brehler     return success();
442f0750ddSMarius Brehler   if (failed(eachFn(*begin)))
452f0750ddSMarius Brehler     return failure();
462f0750ddSMarius Brehler   ++begin;
472f0750ddSMarius Brehler   for (; begin != end; ++begin) {
482f0750ddSMarius Brehler     betweenFn();
492f0750ddSMarius Brehler     if (failed(eachFn(*begin)))
502f0750ddSMarius Brehler       return failure();
512f0750ddSMarius Brehler   }
522f0750ddSMarius Brehler   return success();
532f0750ddSMarius Brehler }
542f0750ddSMarius Brehler 
552f0750ddSMarius Brehler template <typename Container, typename UnaryFunctor, typename NullaryFunctor>
interleaveWithError(const Container & c,UnaryFunctor eachFn,NullaryFunctor betweenFn)562f0750ddSMarius Brehler inline LogicalResult interleaveWithError(const Container &c,
572f0750ddSMarius Brehler                                          UnaryFunctor eachFn,
582f0750ddSMarius Brehler                                          NullaryFunctor betweenFn) {
592f0750ddSMarius Brehler   return interleaveWithError(c.begin(), c.end(), eachFn, betweenFn);
602f0750ddSMarius Brehler }
612f0750ddSMarius Brehler 
622f0750ddSMarius Brehler template <typename Container, typename UnaryFunctor>
interleaveCommaWithError(const Container & c,raw_ostream & os,UnaryFunctor eachFn)632f0750ddSMarius Brehler inline LogicalResult interleaveCommaWithError(const Container &c,
642f0750ddSMarius Brehler                                               raw_ostream &os,
652f0750ddSMarius Brehler                                               UnaryFunctor eachFn) {
662f0750ddSMarius Brehler   return interleaveWithError(c.begin(), c.end(), eachFn, [&]() { os << ", "; });
672f0750ddSMarius Brehler }
682f0750ddSMarius Brehler 
692f0750ddSMarius Brehler namespace {
702f0750ddSMarius Brehler /// Emitter that uses dialect specific emitters to emit C++ code.
712f0750ddSMarius Brehler struct CppEmitter {
722f0750ddSMarius Brehler   explicit CppEmitter(raw_ostream &os, bool declareVariablesAtTop);
732f0750ddSMarius Brehler 
742f0750ddSMarius Brehler   /// Emits attribute or returns failure.
752f0750ddSMarius Brehler   LogicalResult emitAttribute(Location loc, Attribute attr);
762f0750ddSMarius Brehler 
772f0750ddSMarius Brehler   /// Emits operation 'op' with/without training semicolon or returns failure.
782f0750ddSMarius Brehler   LogicalResult emitOperation(Operation &op, bool trailingSemicolon);
792f0750ddSMarius Brehler 
802f0750ddSMarius Brehler   /// Emits type 'type' or returns failure.
812f0750ddSMarius Brehler   LogicalResult emitType(Location loc, Type type);
822f0750ddSMarius Brehler 
832f0750ddSMarius Brehler   /// Emits array of types as a std::tuple of the emitted types.
842f0750ddSMarius Brehler   /// - emits void for an empty array;
852f0750ddSMarius Brehler   /// - emits the type of the only element for arrays of size one;
862f0750ddSMarius Brehler   /// - emits a std::tuple otherwise;
872f0750ddSMarius Brehler   LogicalResult emitTypes(Location loc, ArrayRef<Type> types);
882f0750ddSMarius Brehler 
892f0750ddSMarius Brehler   /// Emits array of types as a std::tuple of the emitted types independently of
902f0750ddSMarius Brehler   /// the array size.
912f0750ddSMarius Brehler   LogicalResult emitTupleType(Location loc, ArrayRef<Type> types);
922f0750ddSMarius Brehler 
932f0750ddSMarius Brehler   /// Emits an assignment for a variable which has been declared previously.
942f0750ddSMarius Brehler   LogicalResult emitVariableAssignment(OpResult result);
952f0750ddSMarius Brehler 
962f0750ddSMarius Brehler   /// Emits a variable declaration for a result of an operation.
972f0750ddSMarius Brehler   LogicalResult emitVariableDeclaration(OpResult result,
982f0750ddSMarius Brehler                                         bool trailingSemicolon);
992f0750ddSMarius Brehler 
1002f0750ddSMarius Brehler   /// Emits the variable declaration and assignment prefix for 'op'.
1012f0750ddSMarius Brehler   /// - emits separate variable followed by std::tie for multi-valued operation;
1022f0750ddSMarius Brehler   /// - emits single type followed by variable for single result;
1032f0750ddSMarius Brehler   /// - emits nothing if no value produced by op;
1042f0750ddSMarius Brehler   /// Emits final '=' operator where a type is produced. Returns failure if
1052f0750ddSMarius Brehler   /// any result type could not be converted.
1062f0750ddSMarius Brehler   LogicalResult emitAssignPrefix(Operation &op);
1072f0750ddSMarius Brehler 
1082f0750ddSMarius Brehler   /// Emits a label for the block.
1092f0750ddSMarius Brehler   LogicalResult emitLabel(Block &block);
1102f0750ddSMarius Brehler 
1112f0750ddSMarius Brehler   /// Emits the operands and atttributes of the operation. All operands are
1122f0750ddSMarius Brehler   /// emitted first and then all attributes in alphabetical order.
1132f0750ddSMarius Brehler   LogicalResult emitOperandsAndAttributes(Operation &op,
1142f0750ddSMarius Brehler                                           ArrayRef<StringRef> exclude = {});
1152f0750ddSMarius Brehler 
1162f0750ddSMarius Brehler   /// Emits the operands of the operation. All operands are emitted in order.
1172f0750ddSMarius Brehler   LogicalResult emitOperands(Operation &op);
1182f0750ddSMarius Brehler 
1192f0750ddSMarius Brehler   /// Return the existing or a new name for a Value.
1202f0750ddSMarius Brehler   StringRef getOrCreateName(Value val);
1212f0750ddSMarius Brehler 
1222f0750ddSMarius Brehler   /// Return the existing or a new label of a Block.
1232f0750ddSMarius Brehler   StringRef getOrCreateName(Block &block);
1242f0750ddSMarius Brehler 
1252f0750ddSMarius Brehler   /// Whether to map an mlir integer to a unsigned integer in C++.
1262f0750ddSMarius Brehler   bool shouldMapToUnsigned(IntegerType::SignednessSemantics val);
1272f0750ddSMarius Brehler 
1282f0750ddSMarius Brehler   /// RAII helper function to manage entering/exiting C++ scopes.
1292f0750ddSMarius Brehler   struct Scope {
Scope__anon47891eb50211::CppEmitter::Scope1302f0750ddSMarius Brehler     Scope(CppEmitter &emitter)
1312f0750ddSMarius Brehler         : valueMapperScope(emitter.valueMapper),
1322f0750ddSMarius Brehler           blockMapperScope(emitter.blockMapper), emitter(emitter) {
1332f0750ddSMarius Brehler       emitter.valueInScopeCount.push(emitter.valueInScopeCount.top());
1342f0750ddSMarius Brehler       emitter.labelInScopeCount.push(emitter.labelInScopeCount.top());
1352f0750ddSMarius Brehler     }
~Scope__anon47891eb50211::CppEmitter::Scope1362f0750ddSMarius Brehler     ~Scope() {
1372f0750ddSMarius Brehler       emitter.valueInScopeCount.pop();
1382f0750ddSMarius Brehler       emitter.labelInScopeCount.pop();
1392f0750ddSMarius Brehler     }
1402f0750ddSMarius Brehler 
1412f0750ddSMarius Brehler   private:
1422f0750ddSMarius Brehler     llvm::ScopedHashTableScope<Value, std::string> valueMapperScope;
1432f0750ddSMarius Brehler     llvm::ScopedHashTableScope<Block *, std::string> blockMapperScope;
1442f0750ddSMarius Brehler     CppEmitter &emitter;
1452f0750ddSMarius Brehler   };
1462f0750ddSMarius Brehler 
1472f0750ddSMarius Brehler   /// Returns wether the Value is assigned to a C++ variable in the scope.
1482f0750ddSMarius Brehler   bool hasValueInScope(Value val);
1492f0750ddSMarius Brehler 
1502f0750ddSMarius Brehler   // Returns whether a label is assigned to the block.
1512f0750ddSMarius Brehler   bool hasBlockLabel(Block &block);
1522f0750ddSMarius Brehler 
1532f0750ddSMarius Brehler   /// Returns the output stream.
ostream__anon47891eb50211::CppEmitter1542f0750ddSMarius Brehler   raw_indented_ostream &ostream() { return os; };
1552f0750ddSMarius Brehler 
1562f0750ddSMarius Brehler   /// Returns if all variables for op results and basic block arguments need to
1572f0750ddSMarius Brehler   /// be declared at the beginning of a function.
shouldDeclareVariablesAtTop__anon47891eb50211::CppEmitter1582f0750ddSMarius Brehler   bool shouldDeclareVariablesAtTop() { return declareVariablesAtTop; };
1592f0750ddSMarius Brehler 
1602f0750ddSMarius Brehler private:
1612f0750ddSMarius Brehler   using ValueMapper = llvm::ScopedHashTable<Value, std::string>;
1622f0750ddSMarius Brehler   using BlockMapper = llvm::ScopedHashTable<Block *, std::string>;
1632f0750ddSMarius Brehler 
1642f0750ddSMarius Brehler   /// Output stream to emit to.
1652f0750ddSMarius Brehler   raw_indented_ostream os;
1662f0750ddSMarius Brehler 
1672f0750ddSMarius Brehler   /// Boolean to enforce that all variables for op results and block
1682f0750ddSMarius Brehler   /// arguments are declared at the beginning of the function. This also
1692f0750ddSMarius Brehler   /// includes results from ops located in nested regions.
1702f0750ddSMarius Brehler   bool declareVariablesAtTop;
1712f0750ddSMarius Brehler 
1722f0750ddSMarius Brehler   /// Map from value to name of C++ variable that contain the name.
1732f0750ddSMarius Brehler   ValueMapper valueMapper;
1742f0750ddSMarius Brehler 
1752f0750ddSMarius Brehler   /// Map from block to name of C++ label.
1762f0750ddSMarius Brehler   BlockMapper blockMapper;
1772f0750ddSMarius Brehler 
1782f0750ddSMarius Brehler   /// The number of values in the current scope. This is used to declare the
1792f0750ddSMarius Brehler   /// names of values in a scope.
1802f0750ddSMarius Brehler   std::stack<int64_t> valueInScopeCount;
1812f0750ddSMarius Brehler   std::stack<int64_t> labelInScopeCount;
1822f0750ddSMarius Brehler };
1832f0750ddSMarius Brehler } // namespace
1842f0750ddSMarius Brehler 
printConstantOp(CppEmitter & emitter,Operation * operation,Attribute value)1852f0750ddSMarius Brehler static LogicalResult printConstantOp(CppEmitter &emitter, Operation *operation,
1862f0750ddSMarius Brehler                                      Attribute value) {
1872f0750ddSMarius Brehler   OpResult result = operation->getResult(0);
1882f0750ddSMarius Brehler 
1892f0750ddSMarius Brehler   // Only emit an assignment as the variable was already declared when printing
1902f0750ddSMarius Brehler   // the FuncOp.
1912f0750ddSMarius Brehler   if (emitter.shouldDeclareVariablesAtTop()) {
1922f0750ddSMarius Brehler     // Skip the assignment if the emitc.constant has no value.
1932f0750ddSMarius Brehler     if (auto oAttr = value.dyn_cast<emitc::OpaqueAttr>()) {
1942f0750ddSMarius Brehler       if (oAttr.getValue().empty())
1952f0750ddSMarius Brehler         return success();
1962f0750ddSMarius Brehler     }
1972f0750ddSMarius Brehler 
1982f0750ddSMarius Brehler     if (failed(emitter.emitVariableAssignment(result)))
1992f0750ddSMarius Brehler       return failure();
2002f0750ddSMarius Brehler     return emitter.emitAttribute(operation->getLoc(), value);
2012f0750ddSMarius Brehler   }
2022f0750ddSMarius Brehler 
2032f0750ddSMarius Brehler   // Emit a variable declaration for an emitc.constant op without value.
2042f0750ddSMarius Brehler   if (auto oAttr = value.dyn_cast<emitc::OpaqueAttr>()) {
2052f0750ddSMarius Brehler     if (oAttr.getValue().empty())
2062f0750ddSMarius Brehler       // The semicolon gets printed by the emitOperation function.
2072f0750ddSMarius Brehler       return emitter.emitVariableDeclaration(result,
2082f0750ddSMarius Brehler                                              /*trailingSemicolon=*/false);
2092f0750ddSMarius Brehler   }
2102f0750ddSMarius Brehler 
2112f0750ddSMarius Brehler   // Emit a variable declaration.
2122f0750ddSMarius Brehler   if (failed(emitter.emitAssignPrefix(*operation)))
2132f0750ddSMarius Brehler     return failure();
2142f0750ddSMarius Brehler   return emitter.emitAttribute(operation->getLoc(), value);
2152f0750ddSMarius Brehler }
2162f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,emitc::ConstantOp constantOp)2172f0750ddSMarius Brehler static LogicalResult printOperation(CppEmitter &emitter,
2182f0750ddSMarius Brehler                                     emitc::ConstantOp constantOp) {
2192f0750ddSMarius Brehler   Operation *operation = constantOp.getOperation();
2208df54a6aSJacques Pienaar   Attribute value = constantOp.getValue();
2212f0750ddSMarius Brehler 
2222f0750ddSMarius Brehler   return printConstantOp(emitter, operation, value);
2232f0750ddSMarius Brehler }
2242f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,emitc::VariableOp variableOp)2252f0750ddSMarius Brehler static LogicalResult printOperation(CppEmitter &emitter,
2261fa12511SMarius Brehler                                     emitc::VariableOp variableOp) {
2271fa12511SMarius Brehler   Operation *operation = variableOp.getOperation();
2288df54a6aSJacques Pienaar   Attribute value = variableOp.getValue();
2291fa12511SMarius Brehler 
2301fa12511SMarius Brehler   return printConstantOp(emitter, operation, value);
2311fa12511SMarius Brehler }
2321fa12511SMarius Brehler 
printOperation(CppEmitter & emitter,arith::ConstantOp constantOp)2331fa12511SMarius Brehler static LogicalResult printOperation(CppEmitter &emitter,
234a54f4eaeSMogball                                     arith::ConstantOp constantOp) {
235a54f4eaeSMogball   Operation *operation = constantOp.getOperation();
236cfb72fd3SJacques Pienaar   Attribute value = constantOp.getValue();
237a54f4eaeSMogball 
238a54f4eaeSMogball   return printConstantOp(emitter, operation, value);
239a54f4eaeSMogball }
240a54f4eaeSMogball 
printOperation(CppEmitter & emitter,func::ConstantOp constantOp)241a54f4eaeSMogball static LogicalResult printOperation(CppEmitter &emitter,
24223aa5a74SRiver Riddle                                     func::ConstantOp constantOp) {
2432f0750ddSMarius Brehler   Operation *operation = constantOp.getOperation();
2448e123ca6SRiver Riddle   Attribute value = constantOp.getValueAttr();
2452f0750ddSMarius Brehler 
2462f0750ddSMarius Brehler   return printConstantOp(emitter, operation, value);
2472f0750ddSMarius Brehler }
2482f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,cf::BranchOp branchOp)249ace01605SRiver Riddle static LogicalResult printOperation(CppEmitter &emitter,
250ace01605SRiver Riddle                                     cf::BranchOp branchOp) {
2512f0750ddSMarius Brehler   raw_ostream &os = emitter.ostream();
2522f0750ddSMarius Brehler   Block &successor = *branchOp.getSuccessor();
2532f0750ddSMarius Brehler 
2542f0750ddSMarius Brehler   for (auto pair :
2552f0750ddSMarius Brehler        llvm::zip(branchOp.getOperands(), successor.getArguments())) {
2562f0750ddSMarius Brehler     Value &operand = std::get<0>(pair);
2572f0750ddSMarius Brehler     BlockArgument &argument = std::get<1>(pair);
2582f0750ddSMarius Brehler     os << emitter.getOrCreateName(argument) << " = "
2592f0750ddSMarius Brehler        << emitter.getOrCreateName(operand) << ";\n";
2602f0750ddSMarius Brehler   }
2612f0750ddSMarius Brehler 
2622f0750ddSMarius Brehler   os << "goto ";
2632f0750ddSMarius Brehler   if (!(emitter.hasBlockLabel(successor)))
2642f0750ddSMarius Brehler     return branchOp.emitOpError("unable to find label for successor block");
2652f0750ddSMarius Brehler   os << emitter.getOrCreateName(successor);
2662f0750ddSMarius Brehler   return success();
2672f0750ddSMarius Brehler }
2682f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,cf::CondBranchOp condBranchOp)2692f0750ddSMarius Brehler static LogicalResult printOperation(CppEmitter &emitter,
270ace01605SRiver Riddle                                     cf::CondBranchOp condBranchOp) {
2719de88fc0Sxndcn   raw_indented_ostream &os = emitter.ostream();
2722f0750ddSMarius Brehler   Block &trueSuccessor = *condBranchOp.getTrueDest();
2732f0750ddSMarius Brehler   Block &falseSuccessor = *condBranchOp.getFalseDest();
2742f0750ddSMarius Brehler 
2752f0750ddSMarius Brehler   os << "if (" << emitter.getOrCreateName(condBranchOp.getCondition())
2762f0750ddSMarius Brehler      << ") {\n";
2772f0750ddSMarius Brehler 
2789de88fc0Sxndcn   os.indent();
2799de88fc0Sxndcn 
2802f0750ddSMarius Brehler   // If condition is true.
2812f0750ddSMarius Brehler   for (auto pair : llvm::zip(condBranchOp.getTrueOperands(),
2822f0750ddSMarius Brehler                              trueSuccessor.getArguments())) {
2832f0750ddSMarius Brehler     Value &operand = std::get<0>(pair);
2842f0750ddSMarius Brehler     BlockArgument &argument = std::get<1>(pair);
2852f0750ddSMarius Brehler     os << emitter.getOrCreateName(argument) << " = "
2862f0750ddSMarius Brehler        << emitter.getOrCreateName(operand) << ";\n";
2872f0750ddSMarius Brehler   }
2882f0750ddSMarius Brehler 
2892f0750ddSMarius Brehler   os << "goto ";
2902f0750ddSMarius Brehler   if (!(emitter.hasBlockLabel(trueSuccessor))) {
2912f0750ddSMarius Brehler     return condBranchOp.emitOpError("unable to find label for successor block");
2922f0750ddSMarius Brehler   }
2932f0750ddSMarius Brehler   os << emitter.getOrCreateName(trueSuccessor) << ";\n";
2949de88fc0Sxndcn   os.unindent() << "} else {\n";
2959de88fc0Sxndcn   os.indent();
2962f0750ddSMarius Brehler   // If condition is false.
2972f0750ddSMarius Brehler   for (auto pair : llvm::zip(condBranchOp.getFalseOperands(),
2982f0750ddSMarius Brehler                              falseSuccessor.getArguments())) {
2992f0750ddSMarius Brehler     Value &operand = std::get<0>(pair);
3002f0750ddSMarius Brehler     BlockArgument &argument = std::get<1>(pair);
3012f0750ddSMarius Brehler     os << emitter.getOrCreateName(argument) << " = "
3022f0750ddSMarius Brehler        << emitter.getOrCreateName(operand) << ";\n";
3032f0750ddSMarius Brehler   }
3042f0750ddSMarius Brehler 
3052f0750ddSMarius Brehler   os << "goto ";
3062f0750ddSMarius Brehler   if (!(emitter.hasBlockLabel(falseSuccessor))) {
3072f0750ddSMarius Brehler     return condBranchOp.emitOpError()
3082f0750ddSMarius Brehler            << "unable to find label for successor block";
3092f0750ddSMarius Brehler   }
3102f0750ddSMarius Brehler   os << emitter.getOrCreateName(falseSuccessor) << ";\n";
3119de88fc0Sxndcn   os.unindent() << "}";
3122f0750ddSMarius Brehler   return success();
3132f0750ddSMarius Brehler }
3142f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,func::CallOp callOp)31523aa5a74SRiver Riddle static LogicalResult printOperation(CppEmitter &emitter, func::CallOp callOp) {
3162f0750ddSMarius Brehler   if (failed(emitter.emitAssignPrefix(*callOp.getOperation())))
3172f0750ddSMarius Brehler     return failure();
3182f0750ddSMarius Brehler 
3192f0750ddSMarius Brehler   raw_ostream &os = emitter.ostream();
3202f0750ddSMarius Brehler   os << callOp.getCallee() << "(";
3212f0750ddSMarius Brehler   if (failed(emitter.emitOperands(*callOp.getOperation())))
3222f0750ddSMarius Brehler     return failure();
3232f0750ddSMarius Brehler   os << ")";
3242f0750ddSMarius Brehler   return success();
3252f0750ddSMarius Brehler }
3262f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,emitc::CallOp callOp)3272f0750ddSMarius Brehler static LogicalResult printOperation(CppEmitter &emitter, emitc::CallOp callOp) {
3282f0750ddSMarius Brehler   raw_ostream &os = emitter.ostream();
3292f0750ddSMarius Brehler   Operation &op = *callOp.getOperation();
3302f0750ddSMarius Brehler 
3312f0750ddSMarius Brehler   if (failed(emitter.emitAssignPrefix(op)))
3322f0750ddSMarius Brehler     return failure();
3338df54a6aSJacques Pienaar   os << callOp.getCallee();
3342f0750ddSMarius Brehler 
3352f0750ddSMarius Brehler   auto emitArgs = [&](Attribute attr) -> LogicalResult {
3362f0750ddSMarius Brehler     if (auto t = attr.dyn_cast<IntegerAttr>()) {
3372f0750ddSMarius Brehler       // Index attributes are treated specially as operand index.
3382f0750ddSMarius Brehler       if (t.getType().isIndex()) {
3392f0750ddSMarius Brehler         int64_t idx = t.getInt();
3402f0750ddSMarius Brehler         if ((idx < 0) || (idx >= op.getNumOperands()))
3412f0750ddSMarius Brehler           return op.emitOpError("invalid operand index");
3422f0750ddSMarius Brehler         if (!emitter.hasValueInScope(op.getOperand(idx)))
3432f0750ddSMarius Brehler           return op.emitOpError("operand ")
3442f0750ddSMarius Brehler                  << idx << "'s value not defined in scope";
3452f0750ddSMarius Brehler         os << emitter.getOrCreateName(op.getOperand(idx));
3462f0750ddSMarius Brehler         return success();
3472f0750ddSMarius Brehler       }
3482f0750ddSMarius Brehler     }
3492f0750ddSMarius Brehler     if (failed(emitter.emitAttribute(op.getLoc(), attr)))
3502f0750ddSMarius Brehler       return failure();
3512f0750ddSMarius Brehler 
3522f0750ddSMarius Brehler     return success();
3532f0750ddSMarius Brehler   };
3542f0750ddSMarius Brehler 
3558df54a6aSJacques Pienaar   if (callOp.getTemplateArgs()) {
3562f0750ddSMarius Brehler     os << "<";
3578df54a6aSJacques Pienaar     if (failed(
3588df54a6aSJacques Pienaar             interleaveCommaWithError(*callOp.getTemplateArgs(), os, emitArgs)))
3592f0750ddSMarius Brehler       return failure();
3602f0750ddSMarius Brehler     os << ">";
3612f0750ddSMarius Brehler   }
3622f0750ddSMarius Brehler 
3632f0750ddSMarius Brehler   os << "(";
3642f0750ddSMarius Brehler 
3652f0750ddSMarius Brehler   LogicalResult emittedArgs =
3668df54a6aSJacques Pienaar       callOp.getArgs()
3678df54a6aSJacques Pienaar           ? interleaveCommaWithError(*callOp.getArgs(), os, emitArgs)
3682f0750ddSMarius Brehler           : emitter.emitOperands(op);
3692f0750ddSMarius Brehler   if (failed(emittedArgs))
3702f0750ddSMarius Brehler     return failure();
3712f0750ddSMarius Brehler   os << ")";
3722f0750ddSMarius Brehler   return success();
3732f0750ddSMarius Brehler }
3742f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,emitc::ApplyOp applyOp)3752f0750ddSMarius Brehler static LogicalResult printOperation(CppEmitter &emitter,
3762f0750ddSMarius Brehler                                     emitc::ApplyOp applyOp) {
3772f0750ddSMarius Brehler   raw_ostream &os = emitter.ostream();
3782f0750ddSMarius Brehler   Operation &op = *applyOp.getOperation();
3792f0750ddSMarius Brehler 
3802f0750ddSMarius Brehler   if (failed(emitter.emitAssignPrefix(op)))
3812f0750ddSMarius Brehler     return failure();
3828df54a6aSJacques Pienaar   os << applyOp.getApplicableOperator();
3832f0750ddSMarius Brehler   os << emitter.getOrCreateName(applyOp.getOperand());
3842f0750ddSMarius Brehler 
3852f0750ddSMarius Brehler   return success();
3862f0750ddSMarius Brehler }
3872f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,emitc::CastOp castOp)38884fe39a4SMarius Brehler static LogicalResult printOperation(CppEmitter &emitter, emitc::CastOp castOp) {
38984fe39a4SMarius Brehler   raw_ostream &os = emitter.ostream();
39084fe39a4SMarius Brehler   Operation &op = *castOp.getOperation();
39184fe39a4SMarius Brehler 
39284fe39a4SMarius Brehler   if (failed(emitter.emitAssignPrefix(op)))
39384fe39a4SMarius Brehler     return failure();
39484fe39a4SMarius Brehler   os << "(";
39584fe39a4SMarius Brehler   if (failed(emitter.emitType(op.getLoc(), op.getResult(0).getType())))
39684fe39a4SMarius Brehler     return failure();
39784fe39a4SMarius Brehler   os << ") ";
39884fe39a4SMarius Brehler   os << emitter.getOrCreateName(castOp.getOperand());
39984fe39a4SMarius Brehler 
40084fe39a4SMarius Brehler   return success();
40184fe39a4SMarius Brehler }
40284fe39a4SMarius Brehler 
printOperation(CppEmitter & emitter,emitc::IncludeOp includeOp)4032f0750ddSMarius Brehler static LogicalResult printOperation(CppEmitter &emitter,
4042f0750ddSMarius Brehler                                     emitc::IncludeOp includeOp) {
4052f0750ddSMarius Brehler   raw_ostream &os = emitter.ostream();
4062f0750ddSMarius Brehler 
4072f0750ddSMarius Brehler   os << "#include ";
4088df54a6aSJacques Pienaar   if (includeOp.getIsStandardInclude())
4098df54a6aSJacques Pienaar     os << "<" << includeOp.getInclude() << ">";
4102f0750ddSMarius Brehler   else
4118df54a6aSJacques Pienaar     os << "\"" << includeOp.getInclude() << "\"";
4122f0750ddSMarius Brehler 
4132f0750ddSMarius Brehler   return success();
4142f0750ddSMarius Brehler }
4152f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,scf::ForOp forOp)4162f0750ddSMarius Brehler static LogicalResult printOperation(CppEmitter &emitter, scf::ForOp forOp) {
4172f0750ddSMarius Brehler 
4182f0750ddSMarius Brehler   raw_indented_ostream &os = emitter.ostream();
4192f0750ddSMarius Brehler 
4202f0750ddSMarius Brehler   OperandRange operands = forOp.getIterOperands();
4212f0750ddSMarius Brehler   Block::BlockArgListType iterArgs = forOp.getRegionIterArgs();
4222f0750ddSMarius Brehler   Operation::result_range results = forOp.getResults();
4232f0750ddSMarius Brehler 
4242f0750ddSMarius Brehler   if (!emitter.shouldDeclareVariablesAtTop()) {
4252f0750ddSMarius Brehler     for (OpResult result : results) {
4262f0750ddSMarius Brehler       if (failed(emitter.emitVariableDeclaration(result,
4272f0750ddSMarius Brehler                                                  /*trailingSemicolon=*/true)))
4282f0750ddSMarius Brehler         return failure();
4292f0750ddSMarius Brehler     }
4302f0750ddSMarius Brehler   }
4312f0750ddSMarius Brehler 
4322f0750ddSMarius Brehler   for (auto pair : llvm::zip(iterArgs, operands)) {
4332f0750ddSMarius Brehler     if (failed(emitter.emitType(forOp.getLoc(), std::get<0>(pair).getType())))
4342f0750ddSMarius Brehler       return failure();
4352f0750ddSMarius Brehler     os << " " << emitter.getOrCreateName(std::get<0>(pair)) << " = ";
4362f0750ddSMarius Brehler     os << emitter.getOrCreateName(std::get<1>(pair)) << ";";
4372f0750ddSMarius Brehler     os << "\n";
4382f0750ddSMarius Brehler   }
4392f0750ddSMarius Brehler 
4402f0750ddSMarius Brehler   os << "for (";
4412f0750ddSMarius Brehler   if (failed(
4422f0750ddSMarius Brehler           emitter.emitType(forOp.getLoc(), forOp.getInductionVar().getType())))
4432f0750ddSMarius Brehler     return failure();
4442f0750ddSMarius Brehler   os << " ";
4452f0750ddSMarius Brehler   os << emitter.getOrCreateName(forOp.getInductionVar());
4462f0750ddSMarius Brehler   os << " = ";
447c0342a2dSJacques Pienaar   os << emitter.getOrCreateName(forOp.getLowerBound());
4482f0750ddSMarius Brehler   os << "; ";
4492f0750ddSMarius Brehler   os << emitter.getOrCreateName(forOp.getInductionVar());
4502f0750ddSMarius Brehler   os << " < ";
451c0342a2dSJacques Pienaar   os << emitter.getOrCreateName(forOp.getUpperBound());
4522f0750ddSMarius Brehler   os << "; ";
4532f0750ddSMarius Brehler   os << emitter.getOrCreateName(forOp.getInductionVar());
4542f0750ddSMarius Brehler   os << " += ";
455c0342a2dSJacques Pienaar   os << emitter.getOrCreateName(forOp.getStep());
4562f0750ddSMarius Brehler   os << ") {\n";
4572f0750ddSMarius Brehler   os.indent();
4582f0750ddSMarius Brehler 
459c0342a2dSJacques Pienaar   Region &forRegion = forOp.getRegion();
4602f0750ddSMarius Brehler   auto regionOps = forRegion.getOps();
4612f0750ddSMarius Brehler 
4622f0750ddSMarius Brehler   // We skip the trailing yield op because this updates the result variables
4632f0750ddSMarius Brehler   // of the for op in the generated code. Instead we update the iterArgs at
4642f0750ddSMarius Brehler   // the end of a loop iteration and set the result variables after the for
4652f0750ddSMarius Brehler   // loop.
4662f0750ddSMarius Brehler   for (auto it = regionOps.begin(); std::next(it) != regionOps.end(); ++it) {
4672f0750ddSMarius Brehler     if (failed(emitter.emitOperation(*it, /*trailingSemicolon=*/true)))
4682f0750ddSMarius Brehler       return failure();
4692f0750ddSMarius Brehler   }
4702f0750ddSMarius Brehler 
4712f0750ddSMarius Brehler   Operation *yieldOp = forRegion.getBlocks().front().getTerminator();
4722f0750ddSMarius Brehler   // Copy yield operands into iterArgs at the end of a loop iteration.
4732f0750ddSMarius Brehler   for (auto pair : llvm::zip(iterArgs, yieldOp->getOperands())) {
4742f0750ddSMarius Brehler     BlockArgument iterArg = std::get<0>(pair);
4752f0750ddSMarius Brehler     Value operand = std::get<1>(pair);
4762f0750ddSMarius Brehler     os << emitter.getOrCreateName(iterArg) << " = "
4772f0750ddSMarius Brehler        << emitter.getOrCreateName(operand) << ";\n";
4782f0750ddSMarius Brehler   }
4792f0750ddSMarius Brehler 
4802f0750ddSMarius Brehler   os.unindent() << "}";
4812f0750ddSMarius Brehler 
4822f0750ddSMarius Brehler   // Copy iterArgs into results after the for loop.
4832f0750ddSMarius Brehler   for (auto pair : llvm::zip(results, iterArgs)) {
4842f0750ddSMarius Brehler     OpResult result = std::get<0>(pair);
4852f0750ddSMarius Brehler     BlockArgument iterArg = std::get<1>(pair);
4862f0750ddSMarius Brehler     os << "\n"
4872f0750ddSMarius Brehler        << emitter.getOrCreateName(result) << " = "
4882f0750ddSMarius Brehler        << emitter.getOrCreateName(iterArg) << ";";
4892f0750ddSMarius Brehler   }
4902f0750ddSMarius Brehler 
4912f0750ddSMarius Brehler   return success();
4922f0750ddSMarius Brehler }
4932f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,scf::IfOp ifOp)4942f0750ddSMarius Brehler static LogicalResult printOperation(CppEmitter &emitter, scf::IfOp ifOp) {
4952f0750ddSMarius Brehler   raw_indented_ostream &os = emitter.ostream();
4962f0750ddSMarius Brehler 
4972f0750ddSMarius Brehler   if (!emitter.shouldDeclareVariablesAtTop()) {
4982f0750ddSMarius Brehler     for (OpResult result : ifOp.getResults()) {
4992f0750ddSMarius Brehler       if (failed(emitter.emitVariableDeclaration(result,
5002f0750ddSMarius Brehler                                                  /*trailingSemicolon=*/true)))
5012f0750ddSMarius Brehler         return failure();
5022f0750ddSMarius Brehler     }
5032f0750ddSMarius Brehler   }
5042f0750ddSMarius Brehler 
5052f0750ddSMarius Brehler   os << "if (";
5062f0750ddSMarius Brehler   if (failed(emitter.emitOperands(*ifOp.getOperation())))
5072f0750ddSMarius Brehler     return failure();
5082f0750ddSMarius Brehler   os << ") {\n";
5092f0750ddSMarius Brehler   os.indent();
5102f0750ddSMarius Brehler 
511c0342a2dSJacques Pienaar   Region &thenRegion = ifOp.getThenRegion();
5122f0750ddSMarius Brehler   for (Operation &op : thenRegion.getOps()) {
5132f0750ddSMarius Brehler     // Note: This prints a superfluous semicolon if the terminating yield op has
5142f0750ddSMarius Brehler     // zero results.
5152f0750ddSMarius Brehler     if (failed(emitter.emitOperation(op, /*trailingSemicolon=*/true)))
5162f0750ddSMarius Brehler       return failure();
5172f0750ddSMarius Brehler   }
5182f0750ddSMarius Brehler 
5192f0750ddSMarius Brehler   os.unindent() << "}";
5202f0750ddSMarius Brehler 
521c0342a2dSJacques Pienaar   Region &elseRegion = ifOp.getElseRegion();
5222f0750ddSMarius Brehler   if (!elseRegion.empty()) {
5232f0750ddSMarius Brehler     os << " else {\n";
5242f0750ddSMarius Brehler     os.indent();
5252f0750ddSMarius Brehler 
5262f0750ddSMarius Brehler     for (Operation &op : elseRegion.getOps()) {
5272f0750ddSMarius Brehler       // Note: This prints a superfluous semicolon if the terminating yield op
5282f0750ddSMarius Brehler       // has zero results.
5292f0750ddSMarius Brehler       if (failed(emitter.emitOperation(op, /*trailingSemicolon=*/true)))
5302f0750ddSMarius Brehler         return failure();
5312f0750ddSMarius Brehler     }
5322f0750ddSMarius Brehler 
5332f0750ddSMarius Brehler     os.unindent() << "}";
5342f0750ddSMarius Brehler   }
5352f0750ddSMarius Brehler 
5362f0750ddSMarius Brehler   return success();
5372f0750ddSMarius Brehler }
5382f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,scf::YieldOp yieldOp)5392f0750ddSMarius Brehler static LogicalResult printOperation(CppEmitter &emitter, scf::YieldOp yieldOp) {
5402f0750ddSMarius Brehler   raw_ostream &os = emitter.ostream();
5412f0750ddSMarius Brehler   Operation &parentOp = *yieldOp.getOperation()->getParentOp();
5422f0750ddSMarius Brehler 
5432f0750ddSMarius Brehler   if (yieldOp.getNumOperands() != parentOp.getNumResults()) {
5442f0750ddSMarius Brehler     return yieldOp.emitError("number of operands does not to match the number "
5452f0750ddSMarius Brehler                              "of the parent op's results");
5462f0750ddSMarius Brehler   }
5472f0750ddSMarius Brehler 
5482f0750ddSMarius Brehler   if (failed(interleaveWithError(
5492f0750ddSMarius Brehler           llvm::zip(parentOp.getResults(), yieldOp.getOperands()),
5502f0750ddSMarius Brehler           [&](auto pair) -> LogicalResult {
5512f0750ddSMarius Brehler             auto result = std::get<0>(pair);
5522f0750ddSMarius Brehler             auto operand = std::get<1>(pair);
5532f0750ddSMarius Brehler             os << emitter.getOrCreateName(result) << " = ";
5542f0750ddSMarius Brehler 
5552f0750ddSMarius Brehler             if (!emitter.hasValueInScope(operand))
5562f0750ddSMarius Brehler               return yieldOp.emitError("operand value not in scope");
5572f0750ddSMarius Brehler             os << emitter.getOrCreateName(operand);
5582f0750ddSMarius Brehler             return success();
5592f0750ddSMarius Brehler           },
5602f0750ddSMarius Brehler           [&]() { os << ";\n"; })))
5612f0750ddSMarius Brehler     return failure();
5622f0750ddSMarius Brehler 
5632f0750ddSMarius Brehler   return success();
5642f0750ddSMarius Brehler }
5652f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,func::ReturnOp returnOp)56623aa5a74SRiver Riddle static LogicalResult printOperation(CppEmitter &emitter,
56723aa5a74SRiver Riddle                                     func::ReturnOp returnOp) {
5682f0750ddSMarius Brehler   raw_ostream &os = emitter.ostream();
5692f0750ddSMarius Brehler   os << "return";
5702f0750ddSMarius Brehler   switch (returnOp.getNumOperands()) {
5712f0750ddSMarius Brehler   case 0:
5722f0750ddSMarius Brehler     return success();
5732f0750ddSMarius Brehler   case 1:
5742f0750ddSMarius Brehler     os << " " << emitter.getOrCreateName(returnOp.getOperand(0));
5752f0750ddSMarius Brehler     return success(emitter.hasValueInScope(returnOp.getOperand(0)));
5762f0750ddSMarius Brehler   default:
5772f0750ddSMarius Brehler     os << " std::make_tuple(";
5782f0750ddSMarius Brehler     if (failed(emitter.emitOperandsAndAttributes(*returnOp.getOperation())))
5792f0750ddSMarius Brehler       return failure();
5802f0750ddSMarius Brehler     os << ")";
5812f0750ddSMarius Brehler     return success();
5822f0750ddSMarius Brehler   }
5832f0750ddSMarius Brehler }
5842f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,ModuleOp moduleOp)5852f0750ddSMarius Brehler static LogicalResult printOperation(CppEmitter &emitter, ModuleOp moduleOp) {
5862f0750ddSMarius Brehler   CppEmitter::Scope scope(emitter);
5872f0750ddSMarius Brehler 
5882f0750ddSMarius Brehler   for (Operation &op : moduleOp) {
5892f0750ddSMarius Brehler     if (failed(emitter.emitOperation(op, /*trailingSemicolon=*/false)))
5902f0750ddSMarius Brehler       return failure();
5912f0750ddSMarius Brehler   }
5922f0750ddSMarius Brehler   return success();
5932f0750ddSMarius Brehler }
5942f0750ddSMarius Brehler 
printOperation(CppEmitter & emitter,func::FuncOp functionOp)595c5c9d6e0SMarius Brehler static LogicalResult printOperation(CppEmitter &emitter,
596c5c9d6e0SMarius Brehler                                     func::FuncOp functionOp) {
5972f0750ddSMarius Brehler   // We need to declare variables at top if the function has multiple blocks.
5982f0750ddSMarius Brehler   if (!emitter.shouldDeclareVariablesAtTop() &&
5992f0750ddSMarius Brehler       functionOp.getBlocks().size() > 1) {
6002f0750ddSMarius Brehler     return functionOp.emitOpError(
6012f0750ddSMarius Brehler         "with multiple blocks needs variables declared at top");
6022f0750ddSMarius Brehler   }
6032f0750ddSMarius Brehler 
6042f0750ddSMarius Brehler   CppEmitter::Scope scope(emitter);
6052f0750ddSMarius Brehler   raw_indented_ostream &os = emitter.ostream();
6062f0750ddSMarius Brehler   if (failed(emitter.emitTypes(functionOp.getLoc(),
6074a3460a7SRiver Riddle                                functionOp.getFunctionType().getResults())))
6082f0750ddSMarius Brehler     return failure();
6092f0750ddSMarius Brehler   os << " " << functionOp.getName();
6102f0750ddSMarius Brehler 
6112f0750ddSMarius Brehler   os << "(";
6122f0750ddSMarius Brehler   if (failed(interleaveCommaWithError(
6132f0750ddSMarius Brehler           functionOp.getArguments(), os,
6142f0750ddSMarius Brehler           [&](BlockArgument arg) -> LogicalResult {
6152f0750ddSMarius Brehler             if (failed(emitter.emitType(functionOp.getLoc(), arg.getType())))
6162f0750ddSMarius Brehler               return failure();
6172f0750ddSMarius Brehler             os << " " << emitter.getOrCreateName(arg);
6182f0750ddSMarius Brehler             return success();
6192f0750ddSMarius Brehler           })))
6202f0750ddSMarius Brehler     return failure();
6212f0750ddSMarius Brehler   os << ") {\n";
6222f0750ddSMarius Brehler   os.indent();
6232f0750ddSMarius Brehler   if (emitter.shouldDeclareVariablesAtTop()) {
6242f0750ddSMarius Brehler     // Declare all variables that hold op results including those from nested
6252f0750ddSMarius Brehler     // regions.
6262f0750ddSMarius Brehler     WalkResult result =
6272f0750ddSMarius Brehler         functionOp.walk<WalkOrder::PreOrder>([&](Operation *op) -> WalkResult {
6282f0750ddSMarius Brehler           for (OpResult result : op->getResults()) {
6292f0750ddSMarius Brehler             if (failed(emitter.emitVariableDeclaration(
6302f0750ddSMarius Brehler                     result, /*trailingSemicolon=*/true))) {
6312f0750ddSMarius Brehler               return WalkResult(
6322f0750ddSMarius Brehler                   op->emitError("unable to declare result variable for op"));
6332f0750ddSMarius Brehler             }
6342f0750ddSMarius Brehler           }
6352f0750ddSMarius Brehler           return WalkResult::advance();
6362f0750ddSMarius Brehler         });
6372f0750ddSMarius Brehler     if (result.wasInterrupted())
6382f0750ddSMarius Brehler       return failure();
6392f0750ddSMarius Brehler   }
6402f0750ddSMarius Brehler 
6412f0750ddSMarius Brehler   Region::BlockListType &blocks = functionOp.getBlocks();
6422f0750ddSMarius Brehler   // Create label names for basic blocks.
6432f0750ddSMarius Brehler   for (Block &block : blocks) {
6442f0750ddSMarius Brehler     emitter.getOrCreateName(block);
6452f0750ddSMarius Brehler   }
6462f0750ddSMarius Brehler 
6472f0750ddSMarius Brehler   // Declare variables for basic block arguments.
648*5605a1eeSKazu Hirata   for (Block &block : llvm::drop_begin(blocks)) {
6492f0750ddSMarius Brehler     for (BlockArgument &arg : block.getArguments()) {
6502f0750ddSMarius Brehler       if (emitter.hasValueInScope(arg))
6512f0750ddSMarius Brehler         return functionOp.emitOpError(" block argument #")
6522f0750ddSMarius Brehler                << arg.getArgNumber() << " is out of scope";
6532f0750ddSMarius Brehler       if (failed(
6542f0750ddSMarius Brehler               emitter.emitType(block.getParentOp()->getLoc(), arg.getType()))) {
6552f0750ddSMarius Brehler         return failure();
6562f0750ddSMarius Brehler       }
6572f0750ddSMarius Brehler       os << " " << emitter.getOrCreateName(arg) << ";\n";
6582f0750ddSMarius Brehler     }
6592f0750ddSMarius Brehler   }
6602f0750ddSMarius Brehler 
6612f0750ddSMarius Brehler   for (Block &block : blocks) {
662578122c1SMarius Brehler     // Only print a label if the block has predecessors.
663578122c1SMarius Brehler     if (!block.hasNoPredecessors()) {
6642f0750ddSMarius Brehler       if (failed(emitter.emitLabel(block)))
6652f0750ddSMarius Brehler         return failure();
6662f0750ddSMarius Brehler     }
6672f0750ddSMarius Brehler     for (Operation &op : block.getOperations()) {
668ace01605SRiver Riddle       // When generating code for an scf.if or cf.cond_br op no semicolon needs
6692f0750ddSMarius Brehler       // to be printed after the closing brace.
6702f0750ddSMarius Brehler       // When generating code for an scf.for op, printing a trailing semicolon
6712f0750ddSMarius Brehler       // is handled within the printOperation function.
672ace01605SRiver Riddle       bool trailingSemicolon =
673ace01605SRiver Riddle           !isa<scf::IfOp, scf::ForOp, cf::CondBranchOp>(op);
6742f0750ddSMarius Brehler 
6752f0750ddSMarius Brehler       if (failed(emitter.emitOperation(
6762f0750ddSMarius Brehler               op, /*trailingSemicolon=*/trailingSemicolon)))
6772f0750ddSMarius Brehler         return failure();
6782f0750ddSMarius Brehler     }
6792f0750ddSMarius Brehler   }
6802f0750ddSMarius Brehler   os.unindent() << "}\n";
6812f0750ddSMarius Brehler   return success();
6822f0750ddSMarius Brehler }
6832f0750ddSMarius Brehler 
CppEmitter(raw_ostream & os,bool declareVariablesAtTop)6842f0750ddSMarius Brehler CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop)
6852f0750ddSMarius Brehler     : os(os), declareVariablesAtTop(declareVariablesAtTop) {
6862f0750ddSMarius Brehler   valueInScopeCount.push(0);
6872f0750ddSMarius Brehler   labelInScopeCount.push(0);
6882f0750ddSMarius Brehler }
6892f0750ddSMarius Brehler 
6902f0750ddSMarius Brehler /// Return the existing or a new name for a Value.
getOrCreateName(Value val)6912f0750ddSMarius Brehler StringRef CppEmitter::getOrCreateName(Value val) {
6922f0750ddSMarius Brehler   if (!valueMapper.count(val))
6932f0750ddSMarius Brehler     valueMapper.insert(val, formatv("v{0}", ++valueInScopeCount.top()));
6942f0750ddSMarius Brehler   return *valueMapper.begin(val);
6952f0750ddSMarius Brehler }
6962f0750ddSMarius Brehler 
6972f0750ddSMarius Brehler /// Return the existing or a new label for a Block.
getOrCreateName(Block & block)6982f0750ddSMarius Brehler StringRef CppEmitter::getOrCreateName(Block &block) {
6992f0750ddSMarius Brehler   if (!blockMapper.count(&block))
7002f0750ddSMarius Brehler     blockMapper.insert(&block, formatv("label{0}", ++labelInScopeCount.top()));
7012f0750ddSMarius Brehler   return *blockMapper.begin(&block);
7022f0750ddSMarius Brehler }
7032f0750ddSMarius Brehler 
shouldMapToUnsigned(IntegerType::SignednessSemantics val)7042f0750ddSMarius Brehler bool CppEmitter::shouldMapToUnsigned(IntegerType::SignednessSemantics val) {
7052f0750ddSMarius Brehler   switch (val) {
7062f0750ddSMarius Brehler   case IntegerType::Signless:
7072f0750ddSMarius Brehler     return false;
7082f0750ddSMarius Brehler   case IntegerType::Signed:
7092f0750ddSMarius Brehler     return false;
7102f0750ddSMarius Brehler   case IntegerType::Unsigned:
7112f0750ddSMarius Brehler     return true;
7122f0750ddSMarius Brehler   }
71313237c3bSMehdi Amini   llvm_unreachable("Unexpected IntegerType::SignednessSemantics");
7142f0750ddSMarius Brehler }
7152f0750ddSMarius Brehler 
hasValueInScope(Value val)7162f0750ddSMarius Brehler bool CppEmitter::hasValueInScope(Value val) { return valueMapper.count(val); }
7172f0750ddSMarius Brehler 
hasBlockLabel(Block & block)7182f0750ddSMarius Brehler bool CppEmitter::hasBlockLabel(Block &block) {
7192f0750ddSMarius Brehler   return blockMapper.count(&block);
7202f0750ddSMarius Brehler }
7212f0750ddSMarius Brehler 
emitAttribute(Location loc,Attribute attr)7222f0750ddSMarius Brehler LogicalResult CppEmitter::emitAttribute(Location loc, Attribute attr) {
7231fc096afSMehdi Amini   auto printInt = [&](const APInt &val, bool isUnsigned) {
7242f0750ddSMarius Brehler     if (val.getBitWidth() == 1) {
7252f0750ddSMarius Brehler       if (val.getBoolValue())
7262f0750ddSMarius Brehler         os << "true";
7272f0750ddSMarius Brehler       else
7282f0750ddSMarius Brehler         os << "false";
7292f0750ddSMarius Brehler     } else {
730ec92f788SSimon Camphausen       SmallString<128> strValue;
731ec92f788SSimon Camphausen       val.toString(strValue, 10, !isUnsigned, false);
732ec92f788SSimon Camphausen       os << strValue;
7332f0750ddSMarius Brehler     }
7342f0750ddSMarius Brehler   };
7352f0750ddSMarius Brehler 
7361fc096afSMehdi Amini   auto printFloat = [&](const APFloat &val) {
7372f0750ddSMarius Brehler     if (val.isFinite()) {
7382f0750ddSMarius Brehler       SmallString<128> strValue;
7392f0750ddSMarius Brehler       // Use default values of toString except don't truncate zeros.
7402f0750ddSMarius Brehler       val.toString(strValue, 0, 0, false);
7412f0750ddSMarius Brehler       switch (llvm::APFloatBase::SemanticsToEnum(val.getSemantics())) {
7422f0750ddSMarius Brehler       case llvm::APFloatBase::S_IEEEsingle:
7432f0750ddSMarius Brehler         os << "(float)";
7442f0750ddSMarius Brehler         break;
7452f0750ddSMarius Brehler       case llvm::APFloatBase::S_IEEEdouble:
7462f0750ddSMarius Brehler         os << "(double)";
7472f0750ddSMarius Brehler         break;
7482f0750ddSMarius Brehler       default:
7492f0750ddSMarius Brehler         break;
7502f0750ddSMarius Brehler       };
7512f0750ddSMarius Brehler       os << strValue;
7522f0750ddSMarius Brehler     } else if (val.isNaN()) {
7532f0750ddSMarius Brehler       os << "NAN";
7542f0750ddSMarius Brehler     } else if (val.isInfinity()) {
7552f0750ddSMarius Brehler       if (val.isNegative())
7562f0750ddSMarius Brehler         os << "-";
7572f0750ddSMarius Brehler       os << "INFINITY";
7582f0750ddSMarius Brehler     }
7592f0750ddSMarius Brehler   };
7602f0750ddSMarius Brehler 
7612f0750ddSMarius Brehler   // Print floating point attributes.
7622f0750ddSMarius Brehler   if (auto fAttr = attr.dyn_cast<FloatAttr>()) {
7632f0750ddSMarius Brehler     printFloat(fAttr.getValue());
7642f0750ddSMarius Brehler     return success();
7652f0750ddSMarius Brehler   }
7662f0750ddSMarius Brehler   if (auto dense = attr.dyn_cast<DenseFPElementsAttr>()) {
7672f0750ddSMarius Brehler     os << '{';
7684f415216SMehdi Amini     interleaveComma(dense, os, [&](const APFloat &val) { printFloat(val); });
7692f0750ddSMarius Brehler     os << '}';
7702f0750ddSMarius Brehler     return success();
7712f0750ddSMarius Brehler   }
7722f0750ddSMarius Brehler 
7732f0750ddSMarius Brehler   // Print integer attributes.
7742f0750ddSMarius Brehler   if (auto iAttr = attr.dyn_cast<IntegerAttr>()) {
7752f0750ddSMarius Brehler     if (auto iType = iAttr.getType().dyn_cast<IntegerType>()) {
7762f0750ddSMarius Brehler       printInt(iAttr.getValue(), shouldMapToUnsigned(iType.getSignedness()));
7772f0750ddSMarius Brehler       return success();
7782f0750ddSMarius Brehler     }
7792f0750ddSMarius Brehler     if (auto iType = iAttr.getType().dyn_cast<IndexType>()) {
7802f0750ddSMarius Brehler       printInt(iAttr.getValue(), false);
7812f0750ddSMarius Brehler       return success();
7822f0750ddSMarius Brehler     }
7832f0750ddSMarius Brehler   }
7842f0750ddSMarius Brehler   if (auto dense = attr.dyn_cast<DenseIntElementsAttr>()) {
7852f0750ddSMarius Brehler     if (auto iType = dense.getType()
7862f0750ddSMarius Brehler                          .cast<TensorType>()
7872f0750ddSMarius Brehler                          .getElementType()
7882f0750ddSMarius Brehler                          .dyn_cast<IntegerType>()) {
7892f0750ddSMarius Brehler       os << '{';
7904f415216SMehdi Amini       interleaveComma(dense, os, [&](const APInt &val) {
791337c937dSMehdi Amini         printInt(val, shouldMapToUnsigned(iType.getSignedness()));
7922f0750ddSMarius Brehler       });
7932f0750ddSMarius Brehler       os << '}';
7942f0750ddSMarius Brehler       return success();
7952f0750ddSMarius Brehler     }
7962f0750ddSMarius Brehler     if (auto iType = dense.getType()
7972f0750ddSMarius Brehler                          .cast<TensorType>()
7982f0750ddSMarius Brehler                          .getElementType()
7992f0750ddSMarius Brehler                          .dyn_cast<IndexType>()) {
8002f0750ddSMarius Brehler       os << '{';
8014f415216SMehdi Amini       interleaveComma(dense, os,
8024f415216SMehdi Amini                       [&](const APInt &val) { printInt(val, false); });
8032f0750ddSMarius Brehler       os << '}';
8042f0750ddSMarius Brehler       return success();
8052f0750ddSMarius Brehler     }
8062f0750ddSMarius Brehler   }
8072f0750ddSMarius Brehler 
8082f0750ddSMarius Brehler   // Print opaque attributes.
8092f0750ddSMarius Brehler   if (auto oAttr = attr.dyn_cast<emitc::OpaqueAttr>()) {
8102f0750ddSMarius Brehler     os << oAttr.getValue();
8112f0750ddSMarius Brehler     return success();
8122f0750ddSMarius Brehler   }
8132f0750ddSMarius Brehler 
8142f0750ddSMarius Brehler   // Print symbolic reference attributes.
8152f0750ddSMarius Brehler   if (auto sAttr = attr.dyn_cast<SymbolRefAttr>()) {
8162f0750ddSMarius Brehler     if (sAttr.getNestedReferences().size() > 1)
8172f0750ddSMarius Brehler       return emitError(loc, "attribute has more than 1 nested reference");
8182f0750ddSMarius Brehler     os << sAttr.getRootReference().getValue();
8192f0750ddSMarius Brehler     return success();
8202f0750ddSMarius Brehler   }
8212f0750ddSMarius Brehler 
8222f0750ddSMarius Brehler   // Print type attributes.
8232f0750ddSMarius Brehler   if (auto type = attr.dyn_cast<TypeAttr>())
8242f0750ddSMarius Brehler     return emitType(loc, type.getValue());
8252f0750ddSMarius Brehler 
8262f0750ddSMarius Brehler   return emitError(loc, "cannot emit attribute of type ") << attr.getType();
8272f0750ddSMarius Brehler }
8282f0750ddSMarius Brehler 
emitOperands(Operation & op)8292f0750ddSMarius Brehler LogicalResult CppEmitter::emitOperands(Operation &op) {
8302f0750ddSMarius Brehler   auto emitOperandName = [&](Value result) -> LogicalResult {
8312f0750ddSMarius Brehler     if (!hasValueInScope(result))
8322f0750ddSMarius Brehler       return op.emitOpError() << "operand value not in scope";
8332f0750ddSMarius Brehler     os << getOrCreateName(result);
8342f0750ddSMarius Brehler     return success();
8352f0750ddSMarius Brehler   };
8362f0750ddSMarius Brehler   return interleaveCommaWithError(op.getOperands(), os, emitOperandName);
8372f0750ddSMarius Brehler }
8382f0750ddSMarius Brehler 
8392f0750ddSMarius Brehler LogicalResult
emitOperandsAndAttributes(Operation & op,ArrayRef<StringRef> exclude)8402f0750ddSMarius Brehler CppEmitter::emitOperandsAndAttributes(Operation &op,
8412f0750ddSMarius Brehler                                       ArrayRef<StringRef> exclude) {
8422f0750ddSMarius Brehler   if (failed(emitOperands(op)))
8432f0750ddSMarius Brehler     return failure();
8442f0750ddSMarius Brehler   // Insert comma in between operands and non-filtered attributes if needed.
8452f0750ddSMarius Brehler   if (op.getNumOperands() > 0) {
8462f0750ddSMarius Brehler     for (NamedAttribute attr : op.getAttrs()) {
8470c7890c8SRiver Riddle       if (!llvm::is_contained(exclude, attr.getName().strref())) {
8482f0750ddSMarius Brehler         os << ", ";
8492f0750ddSMarius Brehler         break;
8502f0750ddSMarius Brehler       }
8512f0750ddSMarius Brehler     }
8522f0750ddSMarius Brehler   }
8532f0750ddSMarius Brehler   // Emit attributes.
8542f0750ddSMarius Brehler   auto emitNamedAttribute = [&](NamedAttribute attr) -> LogicalResult {
8550c7890c8SRiver Riddle     if (llvm::is_contained(exclude, attr.getName().strref()))
8562f0750ddSMarius Brehler       return success();
8570c7890c8SRiver Riddle     os << "/* " << attr.getName().getValue() << " */";
8580c7890c8SRiver Riddle     if (failed(emitAttribute(op.getLoc(), attr.getValue())))
8592f0750ddSMarius Brehler       return failure();
8602f0750ddSMarius Brehler     return success();
8612f0750ddSMarius Brehler   };
8622f0750ddSMarius Brehler   return interleaveCommaWithError(op.getAttrs(), os, emitNamedAttribute);
8632f0750ddSMarius Brehler }
8642f0750ddSMarius Brehler 
emitVariableAssignment(OpResult result)8652f0750ddSMarius Brehler LogicalResult CppEmitter::emitVariableAssignment(OpResult result) {
8662f0750ddSMarius Brehler   if (!hasValueInScope(result)) {
8672f0750ddSMarius Brehler     return result.getDefiningOp()->emitOpError(
8682f0750ddSMarius Brehler         "result variable for the operation has not been declared");
8692f0750ddSMarius Brehler   }
8702f0750ddSMarius Brehler   os << getOrCreateName(result) << " = ";
8712f0750ddSMarius Brehler   return success();
8722f0750ddSMarius Brehler }
8732f0750ddSMarius Brehler 
emitVariableDeclaration(OpResult result,bool trailingSemicolon)8742f0750ddSMarius Brehler LogicalResult CppEmitter::emitVariableDeclaration(OpResult result,
8752f0750ddSMarius Brehler                                                   bool trailingSemicolon) {
8762f0750ddSMarius Brehler   if (hasValueInScope(result)) {
8772f0750ddSMarius Brehler     return result.getDefiningOp()->emitError(
8782f0750ddSMarius Brehler         "result variable for the operation already declared");
8792f0750ddSMarius Brehler   }
8802f0750ddSMarius Brehler   if (failed(emitType(result.getOwner()->getLoc(), result.getType())))
8812f0750ddSMarius Brehler     return failure();
8822f0750ddSMarius Brehler   os << " " << getOrCreateName(result);
8832f0750ddSMarius Brehler   if (trailingSemicolon)
8842f0750ddSMarius Brehler     os << ";\n";
8852f0750ddSMarius Brehler   return success();
8862f0750ddSMarius Brehler }
8872f0750ddSMarius Brehler 
emitAssignPrefix(Operation & op)8882f0750ddSMarius Brehler LogicalResult CppEmitter::emitAssignPrefix(Operation &op) {
8892f0750ddSMarius Brehler   switch (op.getNumResults()) {
8902f0750ddSMarius Brehler   case 0:
8912f0750ddSMarius Brehler     break;
8922f0750ddSMarius Brehler   case 1: {
8932f0750ddSMarius Brehler     OpResult result = op.getResult(0);
8942f0750ddSMarius Brehler     if (shouldDeclareVariablesAtTop()) {
8952f0750ddSMarius Brehler       if (failed(emitVariableAssignment(result)))
8962f0750ddSMarius Brehler         return failure();
8972f0750ddSMarius Brehler     } else {
8982f0750ddSMarius Brehler       if (failed(emitVariableDeclaration(result, /*trailingSemicolon=*/false)))
8992f0750ddSMarius Brehler         return failure();
9002f0750ddSMarius Brehler       os << " = ";
9012f0750ddSMarius Brehler     }
9022f0750ddSMarius Brehler     break;
9032f0750ddSMarius Brehler   }
9042f0750ddSMarius Brehler   default:
9052f0750ddSMarius Brehler     if (!shouldDeclareVariablesAtTop()) {
9062f0750ddSMarius Brehler       for (OpResult result : op.getResults()) {
9072f0750ddSMarius Brehler         if (failed(emitVariableDeclaration(result, /*trailingSemicolon=*/true)))
9082f0750ddSMarius Brehler           return failure();
9092f0750ddSMarius Brehler       }
9102f0750ddSMarius Brehler     }
9112f0750ddSMarius Brehler     os << "std::tie(";
9122f0750ddSMarius Brehler     interleaveComma(op.getResults(), os,
9132f0750ddSMarius Brehler                     [&](Value result) { os << getOrCreateName(result); });
9142f0750ddSMarius Brehler     os << ") = ";
9152f0750ddSMarius Brehler   }
9162f0750ddSMarius Brehler   return success();
9172f0750ddSMarius Brehler }
9182f0750ddSMarius Brehler 
emitLabel(Block & block)9192f0750ddSMarius Brehler LogicalResult CppEmitter::emitLabel(Block &block) {
9202f0750ddSMarius Brehler   if (!hasBlockLabel(block))
9212f0750ddSMarius Brehler     return block.getParentOp()->emitError("label for block not found");
9229de88fc0Sxndcn   // FIXME: Add feature in `raw_indented_ostream` to ignore indent for block
9239de88fc0Sxndcn   // label instead of using `getOStream`.
9249de88fc0Sxndcn   os.getOStream() << getOrCreateName(block) << ":\n";
9252f0750ddSMarius Brehler   return success();
9262f0750ddSMarius Brehler }
9272f0750ddSMarius Brehler 
emitOperation(Operation & op,bool trailingSemicolon)9282f0750ddSMarius Brehler LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
9292f0750ddSMarius Brehler   LogicalResult status =
9302f0750ddSMarius Brehler       llvm::TypeSwitch<Operation *, LogicalResult>(&op)
93123aa5a74SRiver Riddle           // Builtin ops.
932c5c9d6e0SMarius Brehler           .Case<ModuleOp>([&](auto op) { return printOperation(*this, op); })
93323aa5a74SRiver Riddle           // CF ops.
93423aa5a74SRiver Riddle           .Case<cf::BranchOp, cf::CondBranchOp>(
93523aa5a74SRiver Riddle               [&](auto op) { return printOperation(*this, op); })
9362f0750ddSMarius Brehler           // EmitC ops.
93784fe39a4SMarius Brehler           .Case<emitc::ApplyOp, emitc::CallOp, emitc::CastOp, emitc::ConstantOp,
9381fa12511SMarius Brehler                 emitc::IncludeOp, emitc::VariableOp>(
9392f0750ddSMarius Brehler               [&](auto op) { return printOperation(*this, op); })
94023aa5a74SRiver Riddle           // Func ops.
941c5c9d6e0SMarius Brehler           .Case<func::CallOp, func::ConstantOp, func::FuncOp, func::ReturnOp>(
94223aa5a74SRiver Riddle               [&](auto op) { return printOperation(*this, op); })
9432f0750ddSMarius Brehler           // SCF ops.
9442f0750ddSMarius Brehler           .Case<scf::ForOp, scf::IfOp, scf::YieldOp>(
9452f0750ddSMarius Brehler               [&](auto op) { return printOperation(*this, op); })
946a54f4eaeSMogball           // Arithmetic ops.
947a54f4eaeSMogball           .Case<arith::ConstantOp>(
948a54f4eaeSMogball               [&](auto op) { return printOperation(*this, op); })
9492f0750ddSMarius Brehler           .Default([&](Operation *) {
9502f0750ddSMarius Brehler             return op.emitOpError("unable to find printer for op");
9512f0750ddSMarius Brehler           });
9522f0750ddSMarius Brehler 
9532f0750ddSMarius Brehler   if (failed(status))
9542f0750ddSMarius Brehler     return failure();
9552f0750ddSMarius Brehler   os << (trailingSemicolon ? ";\n" : "\n");
9562f0750ddSMarius Brehler   return success();
9572f0750ddSMarius Brehler }
9582f0750ddSMarius Brehler 
emitType(Location loc,Type type)9592f0750ddSMarius Brehler LogicalResult CppEmitter::emitType(Location loc, Type type) {
9602f0750ddSMarius Brehler   if (auto iType = type.dyn_cast<IntegerType>()) {
9612f0750ddSMarius Brehler     switch (iType.getWidth()) {
9622f0750ddSMarius Brehler     case 1:
9632f0750ddSMarius Brehler       return (os << "bool"), success();
9642f0750ddSMarius Brehler     case 8:
9652f0750ddSMarius Brehler     case 16:
9662f0750ddSMarius Brehler     case 32:
9672f0750ddSMarius Brehler     case 64:
9682f0750ddSMarius Brehler       if (shouldMapToUnsigned(iType.getSignedness()))
9692f0750ddSMarius Brehler         return (os << "uint" << iType.getWidth() << "_t"), success();
9702f0750ddSMarius Brehler       else
9712f0750ddSMarius Brehler         return (os << "int" << iType.getWidth() << "_t"), success();
9722f0750ddSMarius Brehler     default:
9732f0750ddSMarius Brehler       return emitError(loc, "cannot emit integer type ") << type;
9742f0750ddSMarius Brehler     }
9752f0750ddSMarius Brehler   }
9762f0750ddSMarius Brehler   if (auto fType = type.dyn_cast<FloatType>()) {
9772f0750ddSMarius Brehler     switch (fType.getWidth()) {
9782f0750ddSMarius Brehler     case 32:
9792f0750ddSMarius Brehler       return (os << "float"), success();
9802f0750ddSMarius Brehler     case 64:
9812f0750ddSMarius Brehler       return (os << "double"), success();
9822f0750ddSMarius Brehler     default:
9832f0750ddSMarius Brehler       return emitError(loc, "cannot emit float type ") << type;
9842f0750ddSMarius Brehler     }
9852f0750ddSMarius Brehler   }
9862f0750ddSMarius Brehler   if (auto iType = type.dyn_cast<IndexType>())
9872f0750ddSMarius Brehler     return (os << "size_t"), success();
9882f0750ddSMarius Brehler   if (auto tType = type.dyn_cast<TensorType>()) {
9892f0750ddSMarius Brehler     if (!tType.hasRank())
9902f0750ddSMarius Brehler       return emitError(loc, "cannot emit unranked tensor type");
9912f0750ddSMarius Brehler     if (!tType.hasStaticShape())
9922f0750ddSMarius Brehler       return emitError(loc, "cannot emit tensor type with non static shape");
9932f0750ddSMarius Brehler     os << "Tensor<";
9942f0750ddSMarius Brehler     if (failed(emitType(loc, tType.getElementType())))
9952f0750ddSMarius Brehler       return failure();
9962f0750ddSMarius Brehler     auto shape = tType.getShape();
9972f0750ddSMarius Brehler     for (auto dimSize : shape) {
9982f0750ddSMarius Brehler       os << ", ";
9992f0750ddSMarius Brehler       os << dimSize;
10002f0750ddSMarius Brehler     }
10012f0750ddSMarius Brehler     os << ">";
10022f0750ddSMarius Brehler     return success();
10032f0750ddSMarius Brehler   }
10042f0750ddSMarius Brehler   if (auto tType = type.dyn_cast<TupleType>())
10052f0750ddSMarius Brehler     return emitTupleType(loc, tType.getTypes());
10062f0750ddSMarius Brehler   if (auto oType = type.dyn_cast<emitc::OpaqueType>()) {
10072f0750ddSMarius Brehler     os << oType.getValue();
10082f0750ddSMarius Brehler     return success();
10092f0750ddSMarius Brehler   }
101088b9d1a4SMarius Brehler   if (auto pType = type.dyn_cast<emitc::PointerType>()) {
101188b9d1a4SMarius Brehler     if (failed(emitType(loc, pType.getPointee())))
101288b9d1a4SMarius Brehler       return failure();
101388b9d1a4SMarius Brehler     os << "*";
101488b9d1a4SMarius Brehler     return success();
101588b9d1a4SMarius Brehler   }
10162f0750ddSMarius Brehler   return emitError(loc, "cannot emit type ") << type;
10172f0750ddSMarius Brehler }
10182f0750ddSMarius Brehler 
emitTypes(Location loc,ArrayRef<Type> types)10192f0750ddSMarius Brehler LogicalResult CppEmitter::emitTypes(Location loc, ArrayRef<Type> types) {
10202f0750ddSMarius Brehler   switch (types.size()) {
10212f0750ddSMarius Brehler   case 0:
10222f0750ddSMarius Brehler     os << "void";
10232f0750ddSMarius Brehler     return success();
10242f0750ddSMarius Brehler   case 1:
10252f0750ddSMarius Brehler     return emitType(loc, types.front());
10262f0750ddSMarius Brehler   default:
10272f0750ddSMarius Brehler     return emitTupleType(loc, types);
10282f0750ddSMarius Brehler   }
10292f0750ddSMarius Brehler }
10302f0750ddSMarius Brehler 
emitTupleType(Location loc,ArrayRef<Type> types)10312f0750ddSMarius Brehler LogicalResult CppEmitter::emitTupleType(Location loc, ArrayRef<Type> types) {
10322f0750ddSMarius Brehler   os << "std::tuple<";
10332f0750ddSMarius Brehler   if (failed(interleaveCommaWithError(
10342f0750ddSMarius Brehler           types, os, [&](Type type) { return emitType(loc, type); })))
10352f0750ddSMarius Brehler     return failure();
10362f0750ddSMarius Brehler   os << ">";
10372f0750ddSMarius Brehler   return success();
10382f0750ddSMarius Brehler }
10392f0750ddSMarius Brehler 
translateToCpp(Operation * op,raw_ostream & os,bool declareVariablesAtTop)10402f0750ddSMarius Brehler LogicalResult emitc::translateToCpp(Operation *op, raw_ostream &os,
10412f0750ddSMarius Brehler                                     bool declareVariablesAtTop) {
10422f0750ddSMarius Brehler   CppEmitter emitter(os, declareVariablesAtTop);
10432f0750ddSMarius Brehler   return emitter.emitOperation(*op, /*trailingSemicolon=*/false);
10442f0750ddSMarius Brehler }
1045