================
@@ -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

Reply via email to