@@ -192,6 +192,9 @@ struct CppEmitter {
192192 // Returns the textual representation of a subscript operation.
193193 std::string getSubscriptName (emitc::SubscriptOp op);
194194
195+ // Returns a string representing the expression of an emitc.apply operation.
196+ std::string getApplyName (emitc::ApplyOp op);
197+
195198 // Returns the textual representation of a member (of object) operation.
196199 std::string createMemberAccess (emitc::MemberOp op);
197200
@@ -830,64 +833,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
830833 return success ();
831834}
832835
833- static LogicalResult printOperation (CppEmitter &emitter,
834- mlir::UnrealizedConversionCastOp castOp) {
835- raw_ostream &os = emitter.ostream ();
836- Operation &op = *castOp.getOperation ();
837-
838- if (castOp.getResults ().size () != 1 || castOp.getOperands ().size () != 1 ) {
839- return castOp.emitOpError (
840- " expected single result and single operand for conversion cast" );
841- }
842-
843- Type destType = castOp.getResult (0 ).getType ();
844-
845- auto srcPtrType =
846- mlir::dyn_cast<emitc::PointerType>(castOp.getOperand (0 ).getType ());
847- auto destArrayType = mlir::dyn_cast<emitc::ArrayType>(destType);
848-
849- if (srcPtrType && destArrayType) {
850-
851- // Emit declaration: (*v13)[dims] =
852- if (failed (emitter.emitType (op.getLoc (), destArrayType.getElementType ())))
853- return failure ();
854- os << " (*" << emitter.getOrCreateName (op.getResult (0 )) << " )" ;
855- for (int64_t dim : destArrayType.getShape ())
856- os << " [" << dim << " ]" ;
857- os << " = " ;
858-
859- os << " (" ;
860-
861- // Emit the C++ type for "datatype (*)[dim1][dim2]..."
862- if (failed (emitter.emitType (op.getLoc (), destArrayType.getElementType ())))
863- return failure ();
864-
865- os << " (*)" ; // Pointer to array
866-
867- for (int64_t dim : destArrayType.getShape ()) {
868- os << " [" << dim << " ]" ;
869- }
870- os << " )" ;
871- if (failed (emitter.emitOperand (castOp.getOperand (0 ))))
872- return failure ();
873-
874- return success ();
875- }
876-
877- // Fallback to generic C-style cast for other cases
878- if (failed (emitter.emitAssignPrefix (op)))
879- return failure ();
880-
881- os << " (" ;
882- if (failed (emitter.emitType (op.getLoc (), destType)))
883- return failure ();
884- os << " )" ;
885- if (failed (emitter.emitOperand (castOp.getOperand (0 ))))
886- return failure ();
887-
888- return success ();
889- }
890-
891836static LogicalResult printOperation (CppEmitter &emitter,
892837 emitc::ApplyOp applyOp) {
893838 raw_ostream &os = emitter.ostream ();
@@ -1399,24 +1344,12 @@ std::string CppEmitter::getSubscriptName(emitc::SubscriptOp op) {
13991344 llvm::raw_string_ostream ss (out);
14001345 Value baseValue = op.getValue ();
14011346
1402- // Check if the baseValue (%arg1) is a result of UnrealizedConversionCastOp
1403- // that converts a pointer to an array type.
1404- if (auto castOp = dyn_cast_or_null<mlir::UnrealizedConversionCastOp>(
1405- baseValue.getDefiningOp ())) {
1406- auto destArrayType =
1407- mlir::dyn_cast<emitc::ArrayType>(castOp.getResult (0 ).getType ());
1408- auto srcPtrType =
1409- mlir::dyn_cast<emitc::PointerType>(castOp.getOperand (0 ).getType ());
1410-
1411- // If it's a pointer being cast to an array, emit (*varName)
1412- if (srcPtrType && destArrayType) {
1413- ss << " (*" << getOrCreateName (baseValue) << " )" ;
1414- } else {
1415- // Fallback if the cast is not our specific pointer-to-array case
1347+ if (auto applyOp = baseValue.getDefiningOp <emitc::ApplyOp>()) {
1348+ if (applyOp.getApplicableOperator () == " *" )
1349+ ss << " (*" << getOrCreateName (applyOp.getOperand ()) << " )" ;
1350+ else
14161351 ss << getOrCreateName (baseValue);
1417- }
14181352 } else {
1419- // Default behavior for a regular array or other base types
14201353 ss << getOrCreateName (baseValue);
14211354 }
14221355
@@ -1426,6 +1359,26 @@ std::string CppEmitter::getSubscriptName(emitc::SubscriptOp op) {
14261359 return out;
14271360}
14281361
1362+ std::string CppEmitter::getApplyName (emitc::ApplyOp op) {
1363+ std::string expr;
1364+ llvm::raw_string_ostream ss (expr);
1365+
1366+ StringRef opStr = op.getApplicableOperator ();
1367+ Value operand = op.getOperand ();
1368+
1369+ // Handle dereference and address-of operators specially
1370+ if (opStr == " *" ) {
1371+ ss << " (*" << getOrCreateName (operand) << " )" ;
1372+ } else if (opStr == " &" ) {
1373+ ss << " &" << getOrCreateName (operand);
1374+ } else {
1375+ // Generic operator form: operand followed by operator
1376+ ss << getOrCreateName (operand) << opStr;
1377+ }
1378+
1379+ return ss.str ();
1380+ }
1381+
14291382std::string CppEmitter::createMemberAccess (emitc::MemberOp op) {
14301383 std::string out;
14311384 llvm::raw_string_ostream ss (out);
@@ -1833,20 +1786,19 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
18331786 .Case <cf::BranchOp, cf::CondBranchOp>(
18341787 [&](auto op) { return printOperation (*this , op); })
18351788 // EmitC ops.
1836- .Case <emitc::AddOp, emitc::ApplyOp, emitc::AssignOp,
1837- emitc::BitwiseAndOp, emitc::BitwiseLeftShiftOp,
1838- emitc::BitwiseNotOp, emitc::BitwiseOrOp,
1839- emitc::BitwiseRightShiftOp, emitc::BitwiseXorOp, emitc::CallOp,
1840- emitc::CallOpaqueOp, emitc::CastOp, emitc::ClassOp,
1841- emitc::CmpOp, emitc::ConditionalOp, emitc::ConstantOp,
1842- emitc::DeclareFuncOp, emitc::DivOp, emitc::DoOp,
1843- emitc::ExpressionOp, emitc::FieldOp, emitc::FileOp,
1844- emitc::ForOp, emitc::FuncOp, emitc::GlobalOp, emitc::IfOp,
1845- emitc::IncludeOp, emitc::LoadOp, emitc::LogicalAndOp,
1846- emitc::LogicalNotOp, emitc::LogicalOrOp, emitc::MulOp,
1847- emitc::RemOp, emitc::ReturnOp, emitc::SubOp, emitc::SwitchOp,
1848- emitc::UnaryMinusOp, emitc::UnaryPlusOp, emitc::VariableOp,
1849- emitc::VerbatimOp>(
1789+ .Case <emitc::AddOp, emitc::AssignOp, emitc::BitwiseAndOp,
1790+ emitc::BitwiseLeftShiftOp, emitc::BitwiseNotOp,
1791+ emitc::BitwiseOrOp, emitc::BitwiseRightShiftOp,
1792+ emitc::BitwiseXorOp, emitc::CallOp, emitc::CallOpaqueOp,
1793+ emitc::CastOp, emitc::ClassOp, emitc::CmpOp,
1794+ emitc::ConditionalOp, emitc::ConstantOp, emitc::DeclareFuncOp,
1795+ emitc::DivOp, emitc::DoOp, emitc::ExpressionOp, emitc::FieldOp,
1796+ emitc::FileOp, emitc::ForOp, emitc::FuncOp, emitc::GlobalOp,
1797+ emitc::IfOp, emitc::IncludeOp, emitc::LoadOp,
1798+ emitc::LogicalAndOp, emitc::LogicalNotOp, emitc::LogicalOrOp,
1799+ emitc::MulOp, emitc::RemOp, emitc::ReturnOp, emitc::SubOp,
1800+ emitc::SwitchOp, emitc::UnaryMinusOp, emitc::UnaryPlusOp,
1801+ emitc::VariableOp, emitc::VerbatimOp>(
18501802
18511803 [&](auto op) { return printOperation (*this , op); })
18521804 // Func ops.
@@ -1876,8 +1828,19 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
18761828 cacheDeferredOpResult (op.getResult (), getSubscriptName (op));
18771829 return success ();
18781830 })
1879- .Case <mlir::UnrealizedConversionCastOp>(
1880- [&](auto op) { return printOperation (*this , op); })
1831+ .Case <emitc::ApplyOp>([&](emitc::ApplyOp op) {
1832+ std::string expr = getApplyName (op);
1833+ cacheDeferredOpResult (op.getResult (), expr);
1834+ // If the result is unused, emit it as a standalone statement.
1835+ if (op->use_empty ()) {
1836+ std::string tmpName = " tmp" + std::to_string (++valueCount);
1837+ if (failed (emitType (op->getLoc (), op.getResult ().getType ())))
1838+ return failure ();
1839+ os << " " << tmpName << " = " << expr << " ;\n " ;
1840+ }
1841+ return success ();
1842+ })
1843+
18811844 .Default ([&](Operation *) {
18821845 return op.emitOpError (" unable to find printer for op" );
18831846 });
@@ -1896,9 +1859,9 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
18961859 // Never emit a semicolon for some operations, especially if endening with
18971860 // `}`.
18981861 trailingSemicolon &=
1899- !isa<cf::CondBranchOp, emitc::DeclareFuncOp, emitc::DoOp , emitc::FileOp ,
1900- emitc::ForOp , emitc::IfOp , emitc::IncludeOp , emitc::SwitchOp ,
1901- emitc::VerbatimOp >(op);
1862+ !isa<cf::CondBranchOp, emitc::DeclareFuncOp, emitc::FileOp , emitc::ForOp ,
1863+ emitc::IfOp , emitc::IncludeOp , emitc::SwitchOp , emitc::VerbatimOp ,
1864+ emitc::ApplyOp >(op);
19021865
19031866 os << (trailingSemicolon ? " ;\n " : " \n " );
19041867
@@ -1916,6 +1879,17 @@ LogicalResult CppEmitter::emitVariableDeclaration(Location loc, Type type,
19161879 }
19171880 return success ();
19181881 }
1882+ // Handle pointer-to-array types: e.g., int (*ptr)[4][8];
1883+ if (auto pType = dyn_cast<emitc::PointerType>(type)) {
1884+ if (auto arrayPointee = dyn_cast<emitc::ArrayType>(pType.getPointee ())) {
1885+ if (failed (emitType (loc, arrayPointee.getElementType ())))
1886+ return failure ();
1887+ os << " (*" << name << " )" ;
1888+ for (auto dim : arrayPointee.getShape ())
1889+ os << " [" << dim << " ]" ;
1890+ return success ();
1891+ }
1892+ }
19191893 if (failed (emitType (loc, type)))
19201894 return failure ();
19211895 os << " " << name;
@@ -1999,8 +1973,21 @@ LogicalResult CppEmitter::emitType(Location loc, Type type) {
19991973 if (auto lType = dyn_cast<emitc::LValueType>(type))
20001974 return emitType (loc, lType.getValueType ());
20011975 if (auto pType = dyn_cast<emitc::PointerType>(type)) {
2002- if (isa<ArrayType>(pType.getPointee ()))
2003- return emitError (loc, " cannot emit pointer to array type " ) << type;
1976+ if (auto arrayPointee = dyn_cast<emitc::ArrayType>(pType.getPointee ())) {
1977+ if (!arrayPointee.hasStaticShape ())
1978+ return emitError (
1979+ loc, " cannot emit pointer to array type with non-static shape" );
1980+ if (arrayPointee.getShape ().empty ())
1981+ return emitError (loc, " cannot emit pointer to empty array type" );
1982+
1983+ if (failed (emitType (loc, arrayPointee.getElementType ())))
1984+ return failure ();
1985+
1986+ os << " (*)" ;
1987+ for (int64_t dim : arrayPointee.getShape ())
1988+ os << " [" << dim << " ]" ;
1989+ return success ();
1990+ }
20041991 if (failed (emitType (loc, pType.getPointee ())))
20051992 return failure ();
20061993 os << " *" ;
0 commit comments