================
@@ -185,183 +232,348 @@ Type RecordType::parse(mlir::AsmParser &parser) {
if (parser.parseOptionalKeyword("padded").succeeded())
padded = true;
- // Parse record members or lack thereof.
bool incomplete = true;
llvm::SmallVector<mlir::Type> members;
- if (parser.parseOptionalKeyword("incomplete").failed()) {
- incomplete = false;
- const auto delimiter = AsmParser::Delimiter::Braces;
- const auto parseElementFn = [&parser, &members]() {
- return parser.parseType(members.emplace_back());
- };
- if (parser.parseCommaSeparatedList(delimiter, parseElementFn).failed())
- return {};
- }
+ if (parseRecordBody(parser, incomplete, members).failed())
+ return {};
if (parser.parseGreater())
return {};
- // Try to create the proper record type.
- ArrayRef<mlir::Type> membersRef(members); // Needed for template deduction.
+ ArrayRef<mlir::Type> membersRef(members);
mlir::Type type = {};
- if (name && incomplete) { // Identified & incomplete
- type = getChecked(eLoc, context, name, kind);
- } else if (!name && !incomplete) { // Anonymous & complete
- type = getChecked(eLoc, context, membersRef, packed, padded, kind);
- } else if (!incomplete) { // Identified & complete
- type = getChecked(eLoc, context, membersRef, name, packed, padded, kind);
- // If the record has a self-reference, its type already exists in a
- // incomplete state. In this case, we must complete it.
- if (mlir::cast<RecordType>(type).isIncomplete())
- mlir::cast<RecordType>(type).complete(membersRef, packed, padded);
+ if (name && incomplete) {
+ type = StructType::getChecked(eLoc, context, name, is_class);
+ } else if (!name && !incomplete) {
+ type = StructType::getChecked(eLoc, context, membersRef, packed, padded,
+ is_class);
+ if (!type)
+ return {};
+ } else if (!incomplete) {
+ type = StructType::getChecked(eLoc, context, membersRef, name, packed,
+ padded, is_class);
+ if (!type)
+ return {};
+ if (auto structTy = mlir::dyn_cast<StructType>(type))
+ if (structTy.isIncomplete())
+ structTy.complete(membersRef, packed, padded);
assert(!cir::MissingFeatures::astRecordDeclAttr());
- } else { // anonymous & incomplete
+ } else {
parser.emitError(loc, "anonymous records must be complete");
return {};
}
return type;
}
-void RecordType::print(mlir::AsmPrinter &printer) const {
- FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrintGuard;
- printer << '<';
+void StructType::print(mlir::AsmPrinter &printer) const {
+ printRecordBody(printer, *this, getName(), isClass(), getPacked(),
+ getPadded(), isIncomplete(), getMembers());
+}
- switch (getKind()) {
- case RecordKind::Struct:
- printer << "struct ";
- break;
- case RecordKind::Union:
- printer << "union ";
- break;
- case RecordKind::Class:
- printer << "class ";
- break;
- }
+mlir::LogicalResult
+StructType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
+ llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
+ bool incomplete, bool packed, bool padded, bool is_class) {
+ if (name && name.getValue().empty())
+ return emitError() << "identified records cannot have an empty name";
+ return mlir::success();
+}
- if (getName())
- printer << getName();
+// Accessors are hand-written because genStorageClass = 0 suppresses generated
+// implementations.
+llvm::ArrayRef<mlir::Type> StructType::getMembers() const {
+ return getImpl()->members;
+}
+mlir::StringAttr StructType::getName() const { return getImpl()->name; }
+bool StructType::isIncomplete() const { return getImpl()->incomplete; }
+bool StructType::getIncomplete() const { return getImpl()->incomplete; }
+bool StructType::getPacked() const { return getImpl()->packed; }
+bool StructType::getPadded() const { return getImpl()->padded; }
+bool StructType::getIsClass() const { return getImpl()->is_class; }
- // Current type has already been printed: print as self reference.
- cyclicPrintGuard = printer.tryStartCyclicPrint(*this);
- if (failed(cyclicPrintGuard)) {
- printer << '>';
- return;
+bool StructType::isABIConvertedRecord() const {
+ return getName() && getName().getValue().starts_with(abi_conversion_prefix);
+}
+
+mlir::StringAttr StructType::getABIConvertedName() const {
+ assert(!isABIConvertedRecord());
+ return StringAttr::get(getContext(),
+ abi_conversion_prefix + getName().getValue());
+}
+
+void StructType::removeABIConversionNamePrefix() {
+ mlir::StringAttr recordName = getName();
+ if (recordName && recordName.getValue().starts_with(abi_conversion_prefix))
+ getImpl()->name = mlir::StringAttr::get(
+ recordName.getValue().drop_front(sizeof(abi_conversion_prefix) - 1),
+ recordName.getType());
+}
+
+void StructType::complete(ArrayRef<Type> members, bool packed, bool padded) {
+ assert(!cir::MissingFeatures::astRecordDeclAttr());
+ if (mutate(members, packed, padded, /*padding=*/mlir::Type{}).failed())
+ llvm_unreachable("failed to complete struct");
+}
+
+bool StructType::isLayoutIdentical(const StructType &other) {
+ if (getImpl() == other.getImpl())
+ return true;
+ if (getPacked() != other.getPacked())
+ return false;
+ return getMembers() == other.getMembers();
+}
+
+//===----------------------------------------------------------------------===//
+// UnionType
+//===----------------------------------------------------------------------===//
+
+Type UnionType::parse(mlir::AsmParser &parser) {
+ FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
+ const llvm::SMLoc loc = parser.getCurrentLocation();
+ const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
+ bool packed = false;
+ mlir::Type padding;
+ mlir::MLIRContext *context = parser.getContext();
+
+ if (parser.parseLess())
+ return {};
+
+ mlir::StringAttr name;
+ parser.parseOptionalAttribute(name);
+
+ // Self-reference.
+ if (name && parser.parseOptionalGreater().succeeded()) {
+ UnionType type = UnionType::getChecked(eLoc, context, name);
+ if (succeeded(parser.tryStartCyclicParse(type))) {
+ parser.emitError(loc, "invalid self-reference within record");
+ return {};
+ }
+ return type;
}
- // Type not yet printed: continue printing the entire record.
- printer << ' ';
+ // Named definition.
+ if (name) {
+ UnionType type = UnionType::getChecked(eLoc, context, name);
+ cyclicParseGuard = parser.tryStartCyclicParse(type);
+ if (failed(cyclicParseGuard)) {
+ parser.emitError(loc, "record already defined");
+ return {};
+ }
+ }
- if (getPacked())
- printer << "packed ";
+ if (parser.parseOptionalKeyword("packed").succeeded())
+ packed = true;
- if (getPadded())
- printer << "padded ";
+ // "padded" is accepted for backward compatibility but derived from padding.
+ (void)parser.parseOptionalKeyword("padded");
- if (isIncomplete()) {
- printer << "incomplete";
+ bool incomplete = true;
+ llvm::SmallVector<mlir::Type> members;
+ if (parseRecordBody(parser, incomplete, members).failed())
+ return {};
+
+ // Optional tail-padding slot: ", padding = { <type> }".
+ if (!incomplete && parser.parseOptionalComma().succeeded()) {
+ if (parser.parseKeyword("padding").failed())
+ return {};
+ if (parser.parseEqual().failed())
+ return {};
+ if (parser.parseLBrace().failed())
+ return {};
+ if (parser.parseType(padding).failed())
+ return {};
+ if (parser.parseRBrace().failed())
+ return {};
+ }
+
+ if (parser.parseGreater())
+ return {};
+
+ ArrayRef<mlir::Type> membersRef(members);
+ mlir::Type type = {};
+ if (name && incomplete) {
+ type = UnionType::getChecked(eLoc, context, name);
+ } else if (!name && !incomplete) {
+ type = UnionType::getChecked(eLoc, context, membersRef, packed, padding);
+ if (!type)
+ return {};
+ } else if (!incomplete) {
+ type =
+ UnionType::getChecked(eLoc, context, membersRef, name, packed,
padding);
+ if (!type)
+ return {};
+ if (auto unionTy = mlir::dyn_cast<UnionType>(type))
+ if (unionTy.isIncomplete())
+ unionTy.complete(membersRef, packed, padding);
+ assert(!cir::MissingFeatures::astRecordDeclAttr());
} else {
- printer << "{";
- llvm::interleaveComma(getMembers(), printer);
- printer << "}";
+ parser.emitError(loc, "anonymous records must be complete");
+ return {};
}
- printer << '>';
+ return type;
+}
+
+void UnionType::print(mlir::AsmPrinter &printer) const {
+ printRecordBody(printer, *this, getName(), /*hasClassPrefix=*/false,
+ getPacked(), getPadded(), isIncomplete(), getMembers(),
+ getPadding());
}
mlir::LogicalResult
-RecordType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
- llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
- bool incomplete, bool packed, bool padded,
- RecordType::RecordKind kind) {
+UnionType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
+ llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
+ bool incomplete, bool packed, mlir::Type padding) {
if (name && name.getValue().empty())
return emitError() << "identified records cannot have an empty name";
return mlir::success();
}
-::llvm::ArrayRef<mlir::Type> RecordType::getMembers() const {
+// Accessors.
+llvm::ArrayRef<mlir::Type> UnionType::getMembers() const {
return getImpl()->members;
}
+mlir::StringAttr UnionType::getName() const { return getImpl()->name; }
+bool UnionType::isIncomplete() const { return getImpl()->incomplete; }
+bool UnionType::getIncomplete() const { return getImpl()->incomplete; }
+bool UnionType::getPacked() const { return getImpl()->packed; }
+bool UnionType::getPadded() const { return !!getPadding(); }
----------------
erichkeane wrote:
why is the `!!` necessary? This is a bool, return, so the operator conversions
should just work?
Also, this DEFINITELY shows we dont need the 'padded' variable anywhere.
https://github.com/llvm/llvm-project/pull/199790
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits