@@ -156,26 +156,36 @@ static const char *const valueRangeReturnCode = R"(
156
156
)" ;
157
157
158
158
// / Read operand/result segment_size from bytecode.
159
- static const char *const readBytecodeSegmentSize = R"(
160
- if ($_reader.getBytecodeVersion() < /*kNativePropertiesODSSegmentSize=*/6) {
161
- ::mlir::DenseI32ArrayAttr attr;
162
- if (::mlir::failed($_reader.readAttribute(attr))) return ::mlir::failure();
163
- if (attr.size() > static_cast<int64_t>(sizeof($_storage) / sizeof(int32_t))) {
164
- $_reader.emitError("size mismatch for operand/result_segment_size");
165
- return ::mlir::failure();
159
+ static const char *const readBytecodeSegmentSizeNative = R"(
160
+ if ($_reader.getBytecodeVersion() >= /*kNativePropertiesODSSegmentSize=*/6)
161
+ return $_reader.readSparseArray(::llvm::MutableArrayRef($_storage));
162
+ )" ;
163
+
164
+ static const char *const readBytecodeSegmentSizeLegacy = R"(
165
+ if ($_reader.getBytecodeVersion() < /*kNativePropertiesODSSegmentSize=*/6) {
166
+ auto &$_storage = prop.$_propName;
167
+ ::mlir::DenseI32ArrayAttr attr;
168
+ if (::mlir::failed($_reader.readAttribute(attr))) return ::mlir::failure();
169
+ if (attr.size() > static_cast<int64_t>(sizeof($_storage) / sizeof(int32_t))) {
170
+ $_reader.emitError("size mismatch for operand/result_segment_size");
171
+ return ::mlir::failure();
172
+ }
173
+ ::llvm::copy(::llvm::ArrayRef<int32_t>(attr), $_storage.begin());
166
174
}
167
- ::llvm::copy(::llvm::ArrayRef<int32_t>(attr), $_storage.begin());
168
- } else {
169
- return $_reader.readSparseArray(::llvm::MutableArrayRef($_storage));
170
- }
171
175
)" ;
172
176
173
177
// / Write operand/result segment_size to bytecode.
174
- static const char *const writeBytecodeSegmentSize = R"(
175
- if ($_writer.getBytecodeVersion() < /*kNativePropertiesODSSegmentSize=*/6)
176
- $_writer.writeAttribute(::mlir::DenseI32ArrayAttr::get(getContext(), $_storage));
177
- else
178
- $_writer.writeSparseArray(::llvm::ArrayRef($_storage));
178
+ static const char *const writeBytecodeSegmentSizeNative = R"(
179
+ if ($_writer.getBytecodeVersion() >= /*kNativePropertiesODSSegmentSize=*/6)
180
+ $_writer.writeSparseArray(::llvm::ArrayRef($_storage));
181
+ )" ;
182
+
183
+ // / Write operand/result segment_size to bytecode.
184
+ static const char *const writeBytecodeSegmentSizeLegacy = R"(
185
+ if ($_writer.getBytecodeVersion() < /*kNativePropertiesODSSegmentSize=*/6) {
186
+ auto &$_storage = prop.$_propName;
187
+ $_writer.writeAttribute(::mlir::DenseI32ArrayAttr::get($_ctxt, $_storage));
188
+ }
179
189
)" ;
180
190
181
191
// / A header for indicating code sections.
@@ -389,6 +399,14 @@ class OpOrAdaptorHelper {
389
399
return resultSegmentsSize;
390
400
}
391
401
402
+ uint32_t getOperandSegmentSizesLegacyIndex () {
403
+ return operandSegmentSizesLegacyIndex;
404
+ }
405
+
406
+ uint32_t getResultSegmentSizesLegacyIndex () {
407
+ return resultSegmentSizesLegacyIndex;
408
+ }
409
+
392
410
private:
393
411
// Compute the attribute metadata.
394
412
void computeAttrMetadata ();
@@ -407,6 +425,12 @@ class OpOrAdaptorHelper {
407
425
std::optional<NamedProperty> resultSegmentsSize;
408
426
std::string resultSegmentsSizeStorage;
409
427
428
+ // Indices to store the position in the emission order of the operand/result
429
+ // segment sizes attribute if emitted as part of the properties for legacy
430
+ // bytecode encodings, i.e. versions less than 6.
431
+ uint32_t operandSegmentSizesLegacyIndex = 0 ;
432
+ uint32_t resultSegmentSizesLegacyIndex = 0 ;
433
+
410
434
// The number of required attributes.
411
435
unsigned numRequired;
412
436
};
@@ -435,8 +459,8 @@ void OpOrAdaptorHelper::computeAttrMetadata() {
435
459
" ::mlir::DenseI32ArrayAttr::get($_ctxt, $_storage)" ,
436
460
/* convertFromAttributeCall=*/
437
461
" return convertFromAttribute($_storage, $_attr, $_diag);" ,
438
- /* readFromMlirBytecodeCall=*/ readBytecodeSegmentSize ,
439
- /* writeToMlirBytecodeCall=*/ writeBytecodeSegmentSize ,
462
+ /* readFromMlirBytecodeCall=*/ readBytecodeSegmentSizeNative ,
463
+ /* writeToMlirBytecodeCall=*/ writeBytecodeSegmentSizeNative ,
440
464
/* hashPropertyCall=*/
441
465
" ::llvm::hash_combine_range(std::begin($_storage), "
442
466
" std::end($_storage));" ,
@@ -478,6 +502,21 @@ void OpOrAdaptorHelper::computeAttrMetadata() {
478
502
return lhs.attrName < rhs.attrName ;
479
503
});
480
504
505
+ // Store the position of the legacy operand_segment_sizes /
506
+ // result_segment_sizes so we can emit a backward compatible property readers
507
+ // and writers.
508
+ StringRef legacyOperandSegmentSizeName =
509
+ StringLiteral (" operand_segment_sizes" );
510
+ StringRef legacyResultSegmentSizeName = StringLiteral (" result_segment_sizes" );
511
+ operandSegmentSizesLegacyIndex = 0 ;
512
+ resultSegmentSizesLegacyIndex = 0 ;
513
+ for (auto item : sortedAttrMetadata) {
514
+ if (item.attrName < legacyOperandSegmentSizeName)
515
+ ++operandSegmentSizesLegacyIndex;
516
+ if (item.attrName < legacyResultSegmentSizeName)
517
+ ++resultSegmentSizesLegacyIndex;
518
+ }
519
+
481
520
// Compute the subrange bounds for each attribute.
482
521
numRequired = 0 ;
483
522
for (AttributeMetadata &attr : sortedAttrMetadata) {
@@ -1580,15 +1619,33 @@ void OpEmitter::genPropertiesSupportForBytecode(
1580
1619
readPropertiesMethod
1581
1620
<< " auto &prop = state.getOrAddProperties<Properties>(); (void)prop;" ;
1582
1621
writePropertiesMethod << " auto &prop = getProperties(); (void)prop;\n " ;
1583
- for (const auto &attrOrProp : attrOrProperties) {
1622
+ for (const auto &item : llvm::enumerate (attrOrProperties)) {
1623
+ auto &attrOrProp = item.value ();
1624
+ FmtContext fctx;
1625
+ fctx.addSubst (" _reader" , " reader" )
1626
+ .addSubst (" _writer" , " writer" )
1627
+ .addSubst (" _storage" , propertyStorage)
1628
+ .addSubst (" _ctxt" , " this->getContext()" );
1629
+ // If the op emits operand/result segment sizes as a property, emit the
1630
+ // legacy reader/writer in the appropriate order to allow backward
1631
+ // compatibility and back deployment.
1632
+ if (emitHelper.getOperandSegmentsSize ().has_value () &&
1633
+ item.index () == emitHelper.getOperandSegmentSizesLegacyIndex ()) {
1634
+ FmtContext fmtCtxt (fctx);
1635
+ fmtCtxt.addSubst (" _propName" , operandSegmentAttrName);
1636
+ readPropertiesMethod << tgfmt (readBytecodeSegmentSizeLegacy, &fmtCtxt);
1637
+ writePropertiesMethod << tgfmt (writeBytecodeSegmentSizeLegacy, &fmtCtxt);
1638
+ }
1639
+ if (emitHelper.getResultSegmentsSize ().has_value () &&
1640
+ item.index () == emitHelper.getResultSegmentSizesLegacyIndex ()) {
1641
+ FmtContext fmtCtxt (fctx);
1642
+ fmtCtxt.addSubst (" _propName" , resultSegmentAttrName);
1643
+ readPropertiesMethod << tgfmt (readBytecodeSegmentSizeLegacy, &fmtCtxt);
1644
+ writePropertiesMethod << tgfmt (writeBytecodeSegmentSizeLegacy, &fmtCtxt);
1645
+ }
1584
1646
if (const auto *namedProperty =
1585
1647
attrOrProp.dyn_cast <const NamedProperty *>()) {
1586
1648
StringRef name = namedProperty->name ;
1587
- FmtContext fctx;
1588
- fctx.addSubst (" _reader" , " reader" )
1589
- .addSubst (" _writer" , " writer" )
1590
- .addSubst (" _storage" , propertyStorage)
1591
- .addSubst (" _ctxt" , " this->getContext()" );
1592
1649
readPropertiesMethod << formatv (
1593
1650
R"(
1594
1651
{{
0 commit comments