@@ -189,6 +189,10 @@ struct CppEmitter {
189
189
// / Return the existing or a new name for a Value.
190
190
StringRef getOrCreateName (Value val);
191
191
192
+ // / Return the existing or a new name for a loop induction variable of an
193
+ // / emitc::ForOp.
194
+ StringRef getOrCreateName (emitc::ForOp forOp);
195
+
192
196
// Returns the textual representation of a subscript operation.
193
197
std::string getSubscriptName (emitc::SubscriptOp op);
194
198
@@ -204,23 +208,39 @@ struct CppEmitter {
204
208
// / Whether to map an mlir integer to a unsigned integer in C++.
205
209
bool shouldMapToUnsigned (IntegerType::SignednessSemantics val);
206
210
207
- // / RAII helper function to manage entering/exiting C++ scopes.
211
+ // / Abstract RAII helper function to manage entering/exiting C++ scopes.
208
212
struct Scope {
213
+ ~Scope () { emitter.labelInScopeCount .pop (); }
214
+
215
+ private:
216
+ llvm::ScopedHashTableScope<Value, std::string> valueMapperScope;
217
+ llvm::ScopedHashTableScope<Block *, std::string> blockMapperScope;
218
+
219
+ protected:
209
220
Scope (CppEmitter &emitter)
210
221
: valueMapperScope(emitter.valueMapper),
211
222
blockMapperScope (emitter.blockMapper), emitter(emitter) {
212
- emitter.valueInScopeCount .push (emitter.valueInScopeCount .top ());
213
223
emitter.labelInScopeCount .push (emitter.labelInScopeCount .top ());
214
224
}
215
- ~Scope () {
216
- emitter.valueInScopeCount .pop ();
217
- emitter.labelInScopeCount .pop ();
225
+ CppEmitter &emitter;
226
+ };
227
+
228
+ // / RAII helper function to manage entering/exiting functions, while re-using
229
+ // / value names.
230
+ struct FunctionScope : Scope {
231
+ FunctionScope (CppEmitter &emitter) : Scope(emitter) {
232
+ // Re-use value names
233
+ emitter.resetValueCounter ();
218
234
}
235
+ };
219
236
220
- private:
221
- llvm::ScopedHashTableScope<Value, std::string> valueMapperScope;
222
- llvm::ScopedHashTableScope<Block *, std::string> blockMapperScope;
223
- CppEmitter &emitter;
237
+ // / RAII helper function to manage entering/exiting emitc::forOp loops and
238
+ // / handle induction variable naming.
239
+ struct LoopScope : Scope {
240
+ LoopScope (CppEmitter &emitter) : Scope(emitter) {
241
+ emitter.increaseLoopNestingLevel ();
242
+ }
243
+ ~LoopScope () { emitter.decreaseLoopNestingLevel (); }
224
244
};
225
245
226
246
// / Returns wether the Value is assigned to a C++ variable in the scope.
@@ -268,6 +288,15 @@ struct CppEmitter {
268
288
// / This emitter will only emit translation units whos id matches this value.
269
289
StringRef willOnlyEmitTu () { return onlyTu; }
270
290
291
+ // Resets the value counter to 0
292
+ void resetValueCounter ();
293
+
294
+ // Increases the loop nesting level by 1
295
+ void increaseLoopNestingLevel ();
296
+
297
+ // Decreases the loop nesting level by 1
298
+ void decreaseLoopNestingLevel ();
299
+
271
300
private:
272
301
using ValueMapper = llvm::ScopedHashTable<Value, std::string>;
273
302
using BlockMapper = llvm::ScopedHashTable<Block *, std::string>;
@@ -292,11 +321,19 @@ struct CppEmitter {
292
321
// / Map from block to name of C++ label.
293
322
BlockMapper blockMapper;
294
323
295
- // / The number of values in the current scope. This is used to declare the
296
- // / names of values in a scope.
297
- std::stack<int64_t > valueInScopeCount;
324
+ // / Default values representing outermost scope
325
+ llvm::ScopedHashTableScope<Value, std::string> defaultValueMapperScope;
326
+ llvm::ScopedHashTableScope<Block *, std::string> defaultBlockMapperScope;
327
+
298
328
std::stack<int64_t > labelInScopeCount;
299
329
330
+ // / Keeps track of the amount of nested loops the emitter currently operates
331
+ // / in.
332
+ uint64_t loopNestingLevel{0 };
333
+
334
+ // / Emitter-level count of created values to enable unique identifiers.
335
+ unsigned int valueCount{0 };
336
+
300
337
// / State of the current expression being emitted.
301
338
ExpressionOp emittedExpression;
302
339
SmallVector<int > emittedExpressionPrecedence;
@@ -915,7 +952,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
915
952
}
916
953
917
954
static LogicalResult printOperation (CppEmitter &emitter, emitc::ForOp forOp) {
918
-
919
955
raw_indented_ostream &os = emitter.ostream ();
920
956
921
957
// Utility function to determine whether a value is an expression that will be
@@ -934,12 +970,12 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
934
970
emitter.emitType (forOp.getLoc (), forOp.getInductionVar ().getType ())))
935
971
return failure ();
936
972
os << " " ;
937
- os << emitter.getOrCreateName (forOp. getInductionVar () );
973
+ os << emitter.getOrCreateName (forOp);
938
974
os << " = " ;
939
975
if (failed (emitter.emitOperand (forOp.getLowerBound ())))
940
976
return failure ();
941
977
os << " ; " ;
942
- os << emitter.getOrCreateName (forOp. getInductionVar () );
978
+ os << emitter.getOrCreateName (forOp);
943
979
os << " < " ;
944
980
Value upperBound = forOp.getUpperBound ();
945
981
bool upperBoundRequiresParentheses = requiresParentheses (upperBound);
@@ -950,13 +986,15 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
950
986
if (upperBoundRequiresParentheses)
951
987
os << " )" ;
952
988
os << " ; " ;
953
- os << emitter.getOrCreateName (forOp. getInductionVar () );
989
+ os << emitter.getOrCreateName (forOp);
954
990
os << " += " ;
955
991
if (failed (emitter.emitOperand (forOp.getStep ())))
956
992
return failure ();
957
993
os << " ) {\n " ;
958
994
os.indent ();
959
995
996
+ CppEmitter::LoopScope lScope (emitter);
997
+
960
998
Region &forRegion = forOp.getRegion ();
961
999
auto regionOps = forRegion.getOps ();
962
1000
@@ -1043,8 +1081,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
1043
1081
}
1044
1082
1045
1083
static LogicalResult printOperation (CppEmitter &emitter, ModuleOp moduleOp) {
1046
- CppEmitter::Scope scope (emitter);
1047
-
1048
1084
for (Operation &op : moduleOp) {
1049
1085
if (failed (emitter.emitOperation (op, /* trailingSemicolon=*/ false )))
1050
1086
return failure ();
@@ -1056,8 +1092,6 @@ static LogicalResult printOperation(CppEmitter &emitter, TranslationUnitOp tu) {
1056
1092
if (!emitter.shouldEmitTu (tu))
1057
1093
return success ();
1058
1094
1059
- CppEmitter::Scope scope (emitter);
1060
-
1061
1095
for (Operation &op : tu) {
1062
1096
if (failed (emitter.emitOperation (op, /* trailingSemicolon=*/ false )))
1063
1097
return failure ();
@@ -1220,7 +1254,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
1220
1254
return functionOp.emitOpError () << " cannot emit array type as result type" ;
1221
1255
}
1222
1256
1223
- CppEmitter::Scope scope (emitter);
1257
+ CppEmitter::FunctionScope scope (emitter);
1224
1258
raw_indented_ostream &os = emitter.ostream ();
1225
1259
if (failed (emitter.emitTypes (functionOp.getLoc (),
1226
1260
functionOp.getFunctionType ().getResults ())))
@@ -1248,7 +1282,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
1248
1282
" with multiple blocks needs variables declared at top" );
1249
1283
}
1250
1284
1251
- CppEmitter::Scope scope (emitter);
1285
+ CppEmitter::FunctionScope scope (emitter);
1252
1286
raw_indented_ostream &os = emitter.ostream ();
1253
1287
if (functionOp.getSpecifiers ()) {
1254
1288
for (Attribute specifier : functionOp.getSpecifiersAttr ()) {
@@ -1282,7 +1316,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
1282
1316
1283
1317
static LogicalResult printOperation (CppEmitter &emitter,
1284
1318
DeclareFuncOp declareFuncOp) {
1285
- CppEmitter::Scope scope (emitter);
1286
1319
raw_indented_ostream &os = emitter.ostream ();
1287
1320
1288
1321
auto functionOp = SymbolTable::lookupNearestSymbolFrom<emitc::FuncOp>(
@@ -1314,8 +1347,9 @@ static LogicalResult printOperation(CppEmitter &emitter,
1314
1347
CppEmitter::CppEmitter (raw_ostream &os, bool declareVariablesAtTop,
1315
1348
StringRef onlyTu, bool constantsAsVariables)
1316
1349
: os(os), declareVariablesAtTop(declareVariablesAtTop),
1317
- onlyTu(onlyTu.str()), constantsAsVariables(constantsAsVariables) {
1318
- valueInScopeCount.push (0 );
1350
+ onlyTu (onlyTu.str()), constantsAsVariables(constantsAsVariables),
1351
+ defaultValueMapperScope(valueMapper),
1352
+ defaultBlockMapperScope(blockMapper) {
1319
1353
labelInScopeCount.push (0 );
1320
1354
}
1321
1355
@@ -1356,7 +1390,29 @@ StringRef CppEmitter::getOrCreateName(Value val) {
1356
1390
assert (!hasDeferredEmission (val.getDefiningOp ()) &&
1357
1391
" cacheDeferredOpResult should have been called on this value, "
1358
1392
" update the emitOperation function." );
1359
- valueMapper.insert (val, formatv (" v{0}" , ++valueInScopeCount.top ()));
1393
+
1394
+ valueMapper.insert (val, formatv (" v{0}" , ++valueCount));
1395
+ }
1396
+ return *valueMapper.begin (val);
1397
+ }
1398
+
1399
+ // / Return the existing or a new name for a loop induction variable Value.
1400
+ // / Loop induction variables follow natural naming: i, j, k,...
1401
+ StringRef CppEmitter::getOrCreateName (emitc::ForOp forOp) {
1402
+ Value val = forOp.getInductionVar ();
1403
+
1404
+ if (!valueMapper.count (val)) {
1405
+
1406
+ int64_t identifier = ' i' + loopNestingLevel;
1407
+
1408
+ if (identifier >= ' i' && identifier <= ' z' ) {
1409
+ valueMapper.insert (val,
1410
+ formatv (" {0}_{1}" , (char )identifier, ++valueCount));
1411
+ } else {
1412
+ // If running out of letters, continue with zX
1413
+ valueMapper.insert (
1414
+ val, formatv (" z{0}_{1}" , identifier - ' z' - 1 , ++valueCount));
1415
+ }
1360
1416
}
1361
1417
return *valueMapper.begin (val);
1362
1418
}
@@ -1950,6 +2006,12 @@ LogicalResult CppEmitter::emitTupleType(Location loc, ArrayRef<Type> types) {
1950
2006
return success ();
1951
2007
}
1952
2008
2009
+ void CppEmitter::resetValueCounter () { valueCount = 0 ; }
2010
+
2011
+ void CppEmitter::increaseLoopNestingLevel () { loopNestingLevel++; }
2012
+
2013
+ void CppEmitter::decreaseLoopNestingLevel () { loopNestingLevel--; }
2014
+
1953
2015
LogicalResult emitc::translateToCpp (Operation *op, raw_ostream &os,
1954
2016
bool declareVariablesAtTop,
1955
2017
StringRef onlyTu,
0 commit comments