aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen
diff options
context:
space:
mode:
authorAndy Kaylor <akaylor@nvidia.com>2025-04-14 14:40:19 -0700
committerGitHub <noreply@github.com>2025-04-14 14:40:19 -0700
commitcd7d2c3bf89c9f0e6b7467d9d5ac87ddc829975c (patch)
tree9972dba79c98570f5455adea9192d647daa37080 /clang/lib/CIR/CodeGen
parent557e931d958104eb5d11b93ad3a21e4017812fcd (diff)
downloadllvm-cd7d2c3bf89c9f0e6b7467d9d5ac87ddc829975c.zip
llvm-cd7d2c3bf89c9f0e6b7467d9d5ac87ddc829975c.tar.gz
llvm-cd7d2c3bf89c9f0e6b7467d9d5ac87ddc829975c.tar.bz2
[CIR] Upstream minimal support for structure types (#135105)
This change adds minimal support for structure types. To keep the initial change small, only incomplete declarations are being supported in this patch. More complete support will follow.
Diffstat (limited to 'clang/lib/CIR/CodeGen')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenBuilder.h40
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenDecl.cpp7
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp5
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenTypes.cpp61
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenTypes.h9
5 files changed, 118 insertions, 4 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 0d85687..d984167 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -20,11 +20,24 @@ namespace clang::CIRGen {
class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
const CIRGenTypeCache &typeCache;
+ llvm::StringMap<unsigned> recordNames;
public:
CIRGenBuilderTy(mlir::MLIRContext &mlirContext, const CIRGenTypeCache &tc)
: CIRBaseBuilderTy(mlirContext), typeCache(tc) {}
+ std::string getUniqueAnonRecordName() { return getUniqueRecordName("anon"); }
+
+ std::string getUniqueRecordName(const std::string &baseName) {
+ auto it = recordNames.find(baseName);
+ if (it == recordNames.end()) {
+ recordNames[baseName] = 0;
+ return baseName;
+ }
+
+ return baseName + "." + std::to_string(recordNames[baseName]++);
+ }
+
cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const {
if (&format == &llvm::APFloat::IEEEdouble())
return cir::LongDoubleType::get(getContext(), typeCache.DoubleTy);
@@ -37,6 +50,33 @@ public:
llvm_unreachable("Unsupported format for long double");
}
+ /// Get a CIR record kind from a AST declaration tag.
+ cir::RecordType::RecordKind getRecordKind(const clang::TagTypeKind kind) {
+ switch (kind) {
+ case clang::TagTypeKind::Class:
+ case clang::TagTypeKind::Struct:
+ return cir::RecordType::Struct;
+ case clang::TagTypeKind::Union:
+ return cir::RecordType::Union;
+ case clang::TagTypeKind::Interface:
+ llvm_unreachable("interface records are NYI");
+ case clang::TagTypeKind::Enum:
+ llvm_unreachable("enums are not records");
+ }
+ }
+
+ /// Get an incomplete CIR struct type. If we have a complete record
+ /// declaration, we may create an incomplete type and then add the
+ /// members, so \p rd here may be complete.
+ cir::RecordType getIncompleteRecordTy(llvm::StringRef name,
+ const clang::RecordDecl *rd) {
+ const mlir::StringAttr nameAttr = getStringAttr(name);
+ cir::RecordType::RecordKind kind = cir::RecordType::RecordKind::Struct;
+ if (rd)
+ kind = getRecordKind(rd->getTagKind());
+ return getType<cir::RecordType>(nameAttr, kind);
+ }
+
bool isSized(mlir::Type ty) {
if (mlir::isa<cir::PointerType, cir::ArrayType, cir::BoolType,
cir::IntType>(ty))
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index 58797c5..3d15a70 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -260,6 +260,9 @@ void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d,
void CIRGenFunction::emitDecl(const Decl &d) {
switch (d.getKind()) {
+ case Decl::Record: // struct/union/class X;
+ assert(!cir::MissingFeatures::generateDebugInfo());
+ return;
case Decl::Var: {
const VarDecl &vd = cast<VarDecl>(d);
assert(vd.isLocalVarDecl() &&
@@ -274,7 +277,9 @@ void CIRGenFunction::emitDecl(const Decl &d) {
emitOpenACCRoutine(cast<OpenACCRoutineDecl>(d));
return;
default:
- cgm.errorNYI(d.getSourceRange(), "emitDecl: unhandled decl type");
+ cgm.errorNYI(d.getSourceRange(),
+ std::string("emitDecl: unhandled decl type: ") +
+ d.getDeclKindName());
}
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index fd11523..ddcdc0d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -589,6 +589,11 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
case Decl::OpenACCDeclare:
emitGlobalOpenACCDecl(cast<OpenACCDeclareDecl>(decl));
break;
+
+ case Decl::Record:
+ case Decl::CXXRecord:
+ assert(!cir::MissingFeatures::generateDebugInfo());
+ break;
}
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index a5978a4..2635062 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -86,10 +86,64 @@ mlir::Type CIRGenTypes::convertFunctionTypeInternal(QualType qft) {
return cir::FuncType::get(SmallVector<mlir::Type, 1>{}, cgm.VoidTy);
}
+// This is CIR's version of CodeGenTypes::addRecordTypeName. It isn't shareable
+// because CIR has different uniquing requirements.
+std::string CIRGenTypes::getRecordTypeName(const clang::RecordDecl *recordDecl,
+ StringRef suffix) {
+ llvm::SmallString<256> typeName;
+ llvm::raw_svector_ostream outStream(typeName);
+
+ PrintingPolicy policy = recordDecl->getASTContext().getPrintingPolicy();
+ policy.SuppressInlineNamespace = false;
+ policy.AlwaysIncludeTypeForTemplateArgument = true;
+ policy.PrintCanonicalTypes = true;
+ policy.SuppressTagKeyword = true;
+
+ if (recordDecl->getIdentifier())
+ astContext.getRecordType(recordDecl).print(outStream, policy);
+ else if (auto *typedefNameDecl = recordDecl->getTypedefNameForAnonDecl())
+ typedefNameDecl->printQualifiedName(outStream, policy);
+ else
+ outStream << builder.getUniqueAnonRecordName();
+
+ if (!suffix.empty())
+ outStream << suffix;
+
+ return builder.getUniqueRecordName(std::string(typeName));
+}
+
+/// Lay out a tagged decl type like struct or union.
+mlir::Type CIRGenTypes::convertRecordDeclType(const clang::RecordDecl *rd) {
+ // TagDecl's are not necessarily unique, instead use the (clang) type
+ // connected to the decl.
+ const Type *key = astContext.getTagDeclType(rd).getTypePtr();
+ cir::RecordType entry = recordDeclTypes[key];
+
+ // If we don't have an entry for this record yet, create one.
+ // We create an incomplete type initially. If `rd` is complete, we will
+ // add the members below.
+ if (!entry) {
+ auto name = getRecordTypeName(rd, "");
+ entry = builder.getIncompleteRecordTy(name, rd);
+ recordDeclTypes[key] = entry;
+ }
+
+ rd = rd->getDefinition();
+ if (!rd || !rd->isCompleteDefinition() || entry.isComplete())
+ return entry;
+
+ cgm.errorNYI(rd->getSourceRange(), "Complete record type");
+ return entry;
+}
+
mlir::Type CIRGenTypes::convertType(QualType type) {
type = astContext.getCanonicalType(type);
const Type *ty = type.getTypePtr();
+ // Process record types before the type cache lookup.
+ if (const auto *recordType = dyn_cast<RecordType>(type))
+ return convertRecordDeclType(recordType->getDecl());
+
// Has the type already been processed?
TypeCacheTy::iterator tci = typeCache.find(ty);
if (tci != typeCache.end())
@@ -100,9 +154,11 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
mlir::Type resultType = nullptr;
switch (ty->getTypeClass()) {
+ case Type::Record:
+ llvm_unreachable("Should have been handled above");
+
case Type::Builtin: {
switch (cast<BuiltinType>(ty)->getKind()) {
-
// void
case BuiltinType::Void:
resultType = cgm.VoidTy;
@@ -236,7 +292,8 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
}
default:
- cgm.errorNYI(SourceLocation(), "processing of type", type);
+ cgm.errorNYI(SourceLocation(), "processing of type",
+ type->getTypeClassName());
resultType = cgm.SInt32Ty;
break;
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.h b/clang/lib/CIR/CodeGen/CIRGenTypes.h
index 60661ba..fd855bf 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.h
@@ -45,11 +45,13 @@ class CIRGenTypes {
clang::ASTContext &astContext;
CIRGenBuilderTy &builder;
+ /// Contains the CIR type for any converted RecordDecl
+ llvm::DenseMap<const clang::Type *, cir::RecordType> recordDeclTypes;
+
/// Hold memoized CIRGenFunctionInfo results
llvm::FoldingSet<CIRGenFunctionInfo> functionInfos;
llvm::SmallPtrSet<const CIRGenFunctionInfo *, 4> functionsBeingProcessed;
-
/// Heper for convertType.
mlir::Type convertFunctionTypeInternal(clang::QualType ft);
@@ -72,6 +74,11 @@ public:
/// Convert a Clang type into a mlir::Type.
mlir::Type convertType(clang::QualType type);
+ mlir::Type convertRecordDeclType(const clang::RecordDecl *recordDecl);
+
+ std::string getRecordTypeName(const clang::RecordDecl *,
+ llvm::StringRef suffix);
+
/// Convert type T into an mlir::Type. This differs from convertType in that
/// it is used to convert to the memory representation for a type. For
/// example, the scalar representation for bool is i1, but the memory