@@ -186,6 +186,10 @@ struct CppEmitter {
186
186
// / Return the existing or a new name for a Value.
187
187
StringRef getOrCreateName (Value val);
188
188
189
+ // / Return the existing or a new name for a loop induction variable of an
190
+ // / emitc::ForOp.
191
+ StringRef getOrCreateInductionVarName (Value val);
192
+
189
193
// Returns the textual representation of a subscript operation.
190
194
std::string getSubscriptName (emitc::SubscriptOp op);
191
195
@@ -201,23 +205,39 @@ struct CppEmitter {
201
205
// / Whether to map an mlir integer to a unsigned integer in C++.
202
206
bool shouldMapToUnsigned (IntegerType::SignednessSemantics val);
203
207
204
- // / RAII helper function to manage entering/exiting C++ scopes.
208
+ // / Abstract RAII helper function to manage entering/exiting C++ scopes.
205
209
struct Scope {
210
+ ~Scope () { emitter.labelInScopeCount .pop (); }
211
+
212
+ private:
213
+ llvm::ScopedHashTableScope<Value, std::string> valueMapperScope;
214
+ llvm::ScopedHashTableScope<Block *, std::string> blockMapperScope;
215
+
216
+ protected:
206
217
Scope (CppEmitter &emitter)
207
218
: valueMapperScope(emitter.valueMapper),
208
219
blockMapperScope (emitter.blockMapper), emitter(emitter) {
209
- emitter.valueInScopeCount .push (emitter.valueInScopeCount .top ());
210
220
emitter.labelInScopeCount .push (emitter.labelInScopeCount .top ());
211
221
}
212
- ~Scope () {
213
- emitter.valueInScopeCount .pop ();
214
- emitter.labelInScopeCount .pop ();
222
+ CppEmitter &emitter;
223
+ };
224
+
225
+ // / RAII helper function to manage entering/exiting functions, while re-using
226
+ // / value names.
227
+ struct FunctionScope : Scope {
228
+ FunctionScope (CppEmitter &emitter) : Scope(emitter) {
229
+ // Re-use value names.
230
+ emitter.resetValueCounter ();
215
231
}
232
+ };
216
233
217
- private:
218
- llvm::ScopedHashTableScope<Value, std::string> valueMapperScope;
219
- llvm::ScopedHashTableScope<Block *, std::string> blockMapperScope;
220
- CppEmitter &emitter;
234
+ // / RAII helper function to manage entering/exiting emitc::forOp loops and
235
+ // / handle induction variable naming.
236
+ struct LoopScope : Scope {
237
+ LoopScope (CppEmitter &emitter) : Scope(emitter) {
238
+ emitter.increaseLoopNestingLevel ();
239
+ }
240
+ ~LoopScope () { emitter.decreaseLoopNestingLevel (); }
221
241
};
222
242
223
243
// / Returns wether the Value is assigned to a C++ variable in the scope.
@@ -253,6 +273,15 @@ struct CppEmitter {
253
273
return operandExpression == emittedExpression;
254
274
};
255
275
276
+ // Resets the value counter to 0.
277
+ void resetValueCounter ();
278
+
279
+ // Increases the loop nesting level by 1.
280
+ void increaseLoopNestingLevel ();
281
+
282
+ // Decreases the loop nesting level by 1.
283
+ void decreaseLoopNestingLevel ();
284
+
256
285
private:
257
286
using ValueMapper = llvm::ScopedHashTable<Value, std::string>;
258
287
using BlockMapper = llvm::ScopedHashTable<Block *, std::string>;
@@ -274,11 +303,19 @@ struct CppEmitter {
274
303
// / Map from block to name of C++ label.
275
304
BlockMapper blockMapper;
276
305
277
- // / The number of values in the current scope. This is used to declare the
278
- // / names of values in a scope.
279
- std::stack<int64_t > valueInScopeCount;
306
+ // / Default values representing outermost scope.
307
+ llvm::ScopedHashTableScope<Value, std::string> defaultValueMapperScope;
308
+ llvm::ScopedHashTableScope<Block *, std::string> defaultBlockMapperScope;
309
+
280
310
std::stack<int64_t > labelInScopeCount;
281
311
312
+ // / Keeps track of the amount of nested loops the emitter currently operates
313
+ // / in.
314
+ uint64_t loopNestingLevel{0 };
315
+
316
+ // / Emitter-level count of created values to enable unique identifiers.
317
+ unsigned int valueCount{0 };
318
+
282
319
// / State of the current expression being emitted.
283
320
ExpressionOp emittedExpression;
284
321
SmallVector<int > emittedExpressionPrecedence;
@@ -860,7 +897,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
860
897
}
861
898
862
899
static LogicalResult printOperation (CppEmitter &emitter, emitc::ForOp forOp) {
863
-
864
900
raw_indented_ostream &os = emitter.ostream ();
865
901
866
902
// Utility function to determine whether a value is an expression that will be
@@ -879,12 +915,12 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
879
915
emitter.emitType (forOp.getLoc (), forOp.getInductionVar ().getType ())))
880
916
return failure ();
881
917
os << " " ;
882
- os << emitter.getOrCreateName (forOp.getInductionVar ());
918
+ os << emitter.getOrCreateInductionVarName (forOp.getInductionVar ());
883
919
os << " = " ;
884
920
if (failed (emitter.emitOperand (forOp.getLowerBound ())))
885
921
return failure ();
886
922
os << " ; " ;
887
- os << emitter.getOrCreateName (forOp.getInductionVar ());
923
+ os << emitter.getOrCreateInductionVarName (forOp.getInductionVar ());
888
924
os << " < " ;
889
925
Value upperBound = forOp.getUpperBound ();
890
926
bool upperBoundRequiresParentheses = requiresParentheses (upperBound);
@@ -895,13 +931,15 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
895
931
if (upperBoundRequiresParentheses)
896
932
os << " )" ;
897
933
os << " ; " ;
898
- os << emitter.getOrCreateName (forOp.getInductionVar ());
934
+ os << emitter.getOrCreateInductionVarName (forOp.getInductionVar ());
899
935
os << " += " ;
900
936
if (failed (emitter.emitOperand (forOp.getStep ())))
901
937
return failure ();
902
938
os << " ) {\n " ;
903
939
os.indent ();
904
940
941
+ CppEmitter::LoopScope lScope (emitter);
942
+
905
943
Region &forRegion = forOp.getRegion ();
906
944
auto regionOps = forRegion.getOps ();
907
945
@@ -988,8 +1026,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
988
1026
}
989
1027
990
1028
static LogicalResult printOperation (CppEmitter &emitter, ModuleOp moduleOp) {
991
- CppEmitter::Scope scope (emitter);
992
-
993
1029
for (Operation &op : moduleOp) {
994
1030
if (failed (emitter.emitOperation (op, /* trailingSemicolon=*/ false )))
995
1031
return failure ();
@@ -998,7 +1034,6 @@ static LogicalResult printOperation(CppEmitter &emitter, ModuleOp moduleOp) {
998
1034
}
999
1035
1000
1036
static LogicalResult printOperation (CppEmitter &emitter, ClassOp classOp) {
1001
- CppEmitter::Scope classScope (emitter);
1002
1037
raw_indented_ostream &os = emitter.ostream ();
1003
1038
os << " class " << classOp.getSymName ();
1004
1039
if (classOp.getFinalSpecifier ())
@@ -1044,8 +1079,6 @@ static LogicalResult printOperation(CppEmitter &emitter, FileOp file) {
1044
1079
if (!emitter.shouldEmitFile (file))
1045
1080
return success ();
1046
1081
1047
- CppEmitter::Scope scope (emitter);
1048
-
1049
1082
for (Operation &op : file) {
1050
1083
if (failed (emitter.emitOperation (op, /* trailingSemicolon=*/ false )))
1051
1084
return failure ();
@@ -1161,7 +1194,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
1161
1194
return functionOp.emitOpError () << " cannot emit array type as result type" ;
1162
1195
}
1163
1196
1164
- CppEmitter::Scope scope (emitter);
1197
+ CppEmitter::FunctionScope scope (emitter);
1165
1198
raw_indented_ostream &os = emitter.ostream ();
1166
1199
if (failed (emitter.emitTypes (functionOp.getLoc (),
1167
1200
functionOp.getFunctionType ().getResults ())))
@@ -1189,7 +1222,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
1189
1222
" with multiple blocks needs variables declared at top" );
1190
1223
}
1191
1224
1192
- CppEmitter::Scope scope (emitter);
1225
+ CppEmitter::FunctionScope scope (emitter);
1193
1226
raw_indented_ostream &os = emitter.ostream ();
1194
1227
if (functionOp.getSpecifiers ()) {
1195
1228
for (Attribute specifier : functionOp.getSpecifiersAttr ()) {
@@ -1223,7 +1256,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
1223
1256
1224
1257
static LogicalResult printOperation (CppEmitter &emitter,
1225
1258
DeclareFuncOp declareFuncOp) {
1226
- CppEmitter::Scope scope (emitter);
1227
1259
raw_indented_ostream &os = emitter.ostream ();
1228
1260
1229
1261
auto functionOp = SymbolTable::lookupNearestSymbolFrom<emitc::FuncOp>(
@@ -1255,8 +1287,8 @@ static LogicalResult printOperation(CppEmitter &emitter,
1255
1287
CppEmitter::CppEmitter (raw_ostream &os, bool declareVariablesAtTop,
1256
1288
StringRef fileId)
1257
1289
: os(os), declareVariablesAtTop(declareVariablesAtTop),
1258
- fileId(fileId.str()) {
1259
- valueInScopeCount. push ( 0 );
1290
+ fileId (fileId.str()), defaultValueMapperScope(valueMapper),
1291
+ defaultBlockMapperScope(blockMapper) {
1260
1292
labelInScopeCount.push (0 );
1261
1293
}
1262
1294
@@ -1297,7 +1329,26 @@ StringRef CppEmitter::getOrCreateName(Value val) {
1297
1329
assert (!hasDeferredEmission (val.getDefiningOp ()) &&
1298
1330
" cacheDeferredOpResult should have been called on this value, "
1299
1331
" update the emitOperation function." );
1300
- valueMapper.insert (val, formatv (" v{0}" , ++valueInScopeCount.top ()));
1332
+
1333
+ valueMapper.insert (val, formatv (" v{0}" , ++valueCount));
1334
+ }
1335
+ return *valueMapper.begin (val);
1336
+ }
1337
+
1338
+ // / Return the existing or a new name for a loop induction variable Value.
1339
+ // / Loop induction variables follow natural naming: i, j, k, ..., t, uX.
1340
+ StringRef CppEmitter::getOrCreateInductionVarName (Value val) {
1341
+ if (!valueMapper.count (val)) {
1342
+
1343
+ int64_t identifier = ' i' + loopNestingLevel;
1344
+
1345
+ if (identifier >= ' i' && identifier <= ' t' ) {
1346
+ valueMapper.insert (val,
1347
+ formatv (" {0}{1}" , (char )identifier, ++valueCount));
1348
+ } else {
1349
+ // If running out of letters, continue with uX.
1350
+ valueMapper.insert (val, formatv (" u{0}" , ++valueCount));
1351
+ }
1301
1352
}
1302
1353
return *valueMapper.begin (val);
1303
1354
}
@@ -1838,6 +1889,12 @@ LogicalResult CppEmitter::emitTupleType(Location loc, ArrayRef<Type> types) {
1838
1889
return success ();
1839
1890
}
1840
1891
1892
+ void CppEmitter::resetValueCounter () { valueCount = 0 ; }
1893
+
1894
+ void CppEmitter::increaseLoopNestingLevel () { loopNestingLevel++; }
1895
+
1896
+ void CppEmitter::decreaseLoopNestingLevel () { loopNestingLevel--; }
1897
+
1841
1898
LogicalResult emitc::translateToCpp (Operation *op, raw_ostream &os,
1842
1899
bool declareVariablesAtTop,
1843
1900
StringRef fileId) {
0 commit comments