[clang] [CIR] Cleanup support for C functions (PR #136854)

2025-04-24 Thread Iris Shi via cfe-commits


@@ -13,20 +13,76 @@
 
 #include "CIRGenCall.h"
 #include "CIRGenFunction.h"
+#include "CIRGenFunctionInfo.h"
 #include "clang/CIR/MissingFeatures.h"
 
 using namespace clang;
 using namespace clang::CIRGen;
 
-CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) {
-  void *buffer = operator new(totalSizeToAlloc(1));
+CIRGenFunctionInfo *
+CIRGenFunctionInfo::create(CanQualType resultType,
+   llvm::ArrayRef argTypes,
+   RequiredArgs required) {
+  void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1));
 
   CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
+
+  fi->required = required;
+  fi->numArgs = argTypes.size();
   fi->getArgsBuffer()[0].type = resultType;
+  for (unsigned i = 0; i < argTypes.size(); ++i)
+fi->getArgsBuffer()[i + 1].type = argTypes[i];
 
   return fi;
 }
 
+cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
+  bool inserted = functionsBeingProcessed.insert(&fi).second;
+  assert(inserted && "Recursively being processed?");
+
+  mlir::Type resultType = nullptr;
+  const cir::ABIArgInfo &retAI = fi.getReturnInfo();
+
+  switch (retAI.getKind()) {
+  case cir::ABIArgInfo::Ignore:
+// TODO(CIR): This should probably be the None type from the builtin
+// dialect.
+resultType = nullptr;
+break;
+
+  case cir::ABIArgInfo::Direct:
+resultType = retAI.getCoerceToType();
+break;
+
+  default:
+assert(false && "NYI");
+  }
+
+  SmallVector argTypes;
+  unsigned argNo = 0;
+  CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(),
+ ie = it + fi.getNumRequiredArgs();
+  for (; it != ie; ++it, ++argNo) {
+const auto &argInfo = it->info;
+
+switch (argInfo.getKind()) {
+default:
+  llvm_unreachable("NYI");
+case cir::ABIArgInfo::Direct:
+  mlir::Type argType = argInfo.getCoerceToType();
+  argTypes.push_back(argType);
+  break;
+}
+  }
+
+  bool erased = functionsBeingProcessed.erase(&fi);
+  assert(erased && "Not in set?");

el-ev wrote:

Thank you! I wasn't aware of the purpose of that line before, and I understand 
its purpose now.

https://github.com/llvm/llvm-project/pull/136854
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Cleanup support for C functions (PR #136854)

2025-04-24 Thread Iris Shi via cfe-commits

https://github.com/el-ev updated 
https://github.com/llvm/llvm-project/pull/136854

>From fd1d37ebf0f1c4a23f573444f30730b0f65630bf Mon Sep 17 00:00:00 2001
From: Iris Shi <0...@owo.li>
Date: Wed, 23 Apr 2025 20:23:09 +0800
Subject: [PATCH 1/2] [CIR] Cleanup support for C functions

---
 clang/lib/CIR/CodeGen/CIRGenCall.cpp   | 82 +++-
 clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 90 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp | 17 +++-
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp  | 37 -
 clang/lib/CIR/CodeGen/CIRGenTypes.h| 12 ++-
 clang/lib/CIR/CodeGen/TargetInfo.cpp   | 10 ++-
 clang/test/CIR/CodeGen/basic.c | 13 
 7 files changed, 232 insertions(+), 29 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 69266f79a88a5..b223bc494f928 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -13,20 +13,76 @@
 
 #include "CIRGenCall.h"
 #include "CIRGenFunction.h"
+#include "CIRGenFunctionInfo.h"
 #include "clang/CIR/MissingFeatures.h"
 
 using namespace clang;
 using namespace clang::CIRGen;
 
-CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) {
-  void *buffer = operator new(totalSizeToAlloc(1));
+CIRGenFunctionInfo *
+CIRGenFunctionInfo::create(CanQualType resultType,
+   llvm::ArrayRef argTypes,
+   RequiredArgs required) {
+  void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1));
 
   CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
+
+  fi->required = required;
+  fi->numArgs = argTypes.size();
   fi->getArgsBuffer()[0].type = resultType;
+  for (unsigned i = 0; i < argTypes.size(); ++i)
+fi->getArgsBuffer()[i + 1].type = argTypes[i];
 
   return fi;
 }
 
+cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
+  bool inserted = functionsBeingProcessed.insert(&fi).second;
+  assert(inserted && "Recursively being processed?");
+
+  mlir::Type resultType = nullptr;
+  const cir::ABIArgInfo &retAI = fi.getReturnInfo();
+
+  switch (retAI.getKind()) {
+  case cir::ABIArgInfo::Ignore:
+// TODO(CIR): This should probably be the None type from the builtin
+// dialect.
+resultType = nullptr;
+break;
+
+  case cir::ABIArgInfo::Direct:
+resultType = retAI.getCoerceToType();
+break;
+
+  default:
+assert(false && "NYI");
+  }
+
+  SmallVector argTypes;
+  unsigned argNo = 0;
+  CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(),
+ ie = it + fi.getNumRequiredArgs();
+  for (; it != ie; ++it, ++argNo) {
+const auto &argInfo = it->info;
+
+switch (argInfo.getKind()) {
+default:
+  llvm_unreachable("NYI");
+case cir::ABIArgInfo::Direct:
+  mlir::Type argType = argInfo.getCoerceToType();
+  argTypes.push_back(argType);
+  break;
+}
+  }
+
+  bool erased = functionsBeingProcessed.erase(&fi);
+  assert(erased && "Not in set?");
+
+  return cir::FuncType::get(argTypes,
+(resultType ? resultType : builder.getVoidTy()),
+fi.isVariadic());
+}
+
 CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
   assert(!cir::MissingFeatures::opCallVirtual());
   return *this;
@@ -35,6 +91,9 @@ CIRGenCallee 
CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
 static const CIRGenFunctionInfo &
 arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
 const FunctionType *fnType) {
+
+  RequiredArgs required = RequiredArgs::All;
+
   if (const auto *proto = dyn_cast(fnType)) {
 if (proto->isVariadic())
   cgm.errorNYI("call to variadic function");
@@ -49,7 +108,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule 
&cgm,
   CanQualType retType = fnType->getReturnType()
 ->getCanonicalTypeUnqualified()
 .getUnqualifiedType();
-  return cgt.arrangeCIRFunctionInfo(retType);
+  return cgt.arrangeCIRFunctionInfo(retType, {}, required);
 }
 
 const CIRGenFunctionInfo &
@@ -71,6 +130,23 @@ static cir::CIRCallOpInterface 
emitCallLikeOp(CIRGenFunction &cgf,
   return builder.createCallOp(callLoc, directFuncOp);
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionType(CanQual fpt) {
+  SmallVector argTypes;
+  for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i)
+argTypes.push_back(fpt->getParamType(i));
+  RequiredArgs required = RequiredArgs::forPrototypePlus(fpt);
+
+  CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
+  return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionType(CanQual fnpt) {
+  CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
+  return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));

[clang] [CIR] Cleanup support for C functions (PR #136854)

2025-04-24 Thread Iris Shi via cfe-commits

https://github.com/el-ev updated 
https://github.com/llvm/llvm-project/pull/136854

>From fd1d37ebf0f1c4a23f573444f30730b0f65630bf Mon Sep 17 00:00:00 2001
From: Iris Shi <0...@owo.li>
Date: Wed, 23 Apr 2025 20:23:09 +0800
Subject: [PATCH 1/2] [CIR] Cleanup support for C functions

---
 clang/lib/CIR/CodeGen/CIRGenCall.cpp   | 82 +++-
 clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 90 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp | 17 +++-
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp  | 37 -
 clang/lib/CIR/CodeGen/CIRGenTypes.h| 12 ++-
 clang/lib/CIR/CodeGen/TargetInfo.cpp   | 10 ++-
 clang/test/CIR/CodeGen/basic.c | 13 
 7 files changed, 232 insertions(+), 29 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 69266f79a88a5..b223bc494f928 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -13,20 +13,76 @@
 
 #include "CIRGenCall.h"
 #include "CIRGenFunction.h"
+#include "CIRGenFunctionInfo.h"
 #include "clang/CIR/MissingFeatures.h"
 
 using namespace clang;
 using namespace clang::CIRGen;
 
-CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) {
-  void *buffer = operator new(totalSizeToAlloc(1));
+CIRGenFunctionInfo *
+CIRGenFunctionInfo::create(CanQualType resultType,
+   llvm::ArrayRef argTypes,
+   RequiredArgs required) {
+  void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1));
 
   CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
+
+  fi->required = required;
+  fi->numArgs = argTypes.size();
   fi->getArgsBuffer()[0].type = resultType;
+  for (unsigned i = 0; i < argTypes.size(); ++i)
+fi->getArgsBuffer()[i + 1].type = argTypes[i];
 
   return fi;
 }
 
+cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
+  bool inserted = functionsBeingProcessed.insert(&fi).second;
+  assert(inserted && "Recursively being processed?");
+
+  mlir::Type resultType = nullptr;
+  const cir::ABIArgInfo &retAI = fi.getReturnInfo();
+
+  switch (retAI.getKind()) {
+  case cir::ABIArgInfo::Ignore:
+// TODO(CIR): This should probably be the None type from the builtin
+// dialect.
+resultType = nullptr;
+break;
+
+  case cir::ABIArgInfo::Direct:
+resultType = retAI.getCoerceToType();
+break;
+
+  default:
+assert(false && "NYI");
+  }
+
+  SmallVector argTypes;
+  unsigned argNo = 0;
+  CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(),
+ ie = it + fi.getNumRequiredArgs();
+  for (; it != ie; ++it, ++argNo) {
+const auto &argInfo = it->info;
+
+switch (argInfo.getKind()) {
+default:
+  llvm_unreachable("NYI");
+case cir::ABIArgInfo::Direct:
+  mlir::Type argType = argInfo.getCoerceToType();
+  argTypes.push_back(argType);
+  break;
+}
+  }
+
+  bool erased = functionsBeingProcessed.erase(&fi);
+  assert(erased && "Not in set?");
+
+  return cir::FuncType::get(argTypes,
+(resultType ? resultType : builder.getVoidTy()),
+fi.isVariadic());
+}
+
 CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
   assert(!cir::MissingFeatures::opCallVirtual());
   return *this;
@@ -35,6 +91,9 @@ CIRGenCallee 
CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
 static const CIRGenFunctionInfo &
 arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
 const FunctionType *fnType) {
+
+  RequiredArgs required = RequiredArgs::All;
+
   if (const auto *proto = dyn_cast(fnType)) {
 if (proto->isVariadic())
   cgm.errorNYI("call to variadic function");
@@ -49,7 +108,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule 
&cgm,
   CanQualType retType = fnType->getReturnType()
 ->getCanonicalTypeUnqualified()
 .getUnqualifiedType();
-  return cgt.arrangeCIRFunctionInfo(retType);
+  return cgt.arrangeCIRFunctionInfo(retType, {}, required);
 }
 
 const CIRGenFunctionInfo &
@@ -71,6 +130,23 @@ static cir::CIRCallOpInterface 
emitCallLikeOp(CIRGenFunction &cgf,
   return builder.createCallOp(callLoc, directFuncOp);
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionType(CanQual fpt) {
+  SmallVector argTypes;
+  for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i)
+argTypes.push_back(fpt->getParamType(i));
+  RequiredArgs required = RequiredArgs::forPrototypePlus(fpt);
+
+  CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
+  return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionType(CanQual fnpt) {
+  CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
+  return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));

[clang] [CIR] Cleanup support for C functions (PR #136854)

2025-04-24 Thread Iris Shi via cfe-commits


@@ -233,6 +233,19 @@ int f8(int *p) {
 // OGCG:   %[[P2:.*]] = load ptr, ptr %[[P_PTR]], align 8
 // OGCG:   %[[STAR_P:.*]] = load i32, ptr %[[P2]], align 4
 
+
+void f9() {}

el-ev wrote:

 I'm actually unsure what kind of new tests would be appropriate. Do you have 
any suggestions on what I should add?

https://github.com/llvm/llvm-project/pull/136854
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Upstream initial support for union type (PR #137501)

2025-04-27 Thread Iris Shi via cfe-commits

https://github.com/el-ev created 
https://github.com/llvm/llvm-project/pull/137501

Closes #136059

>From f27d8d2f2ecbf65479601f1d21206b1cb4d9ef6a Mon Sep 17 00:00:00 2001
From: Iris Shi <0...@owo.li>
Date: Sun, 27 Apr 2025 15:16:19 +0800
Subject: [PATCH] [CIR] Upstream initial support for union type

---
 .../include/clang/CIR/Dialect/IR/CIRTypes.td  |   1 +
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  |  25 ++--
 clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp |   2 +-
 .../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp |  93 +++-
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp |  39 +++--
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  15 +-
 clang/test/CIR/CodeGen/union.c| 135 +-
 7 files changed, 275 insertions(+), 35 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 0a821e152d353..afb7da1fa011d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -494,6 +494,7 @@ def CIR_RecordType : CIR_Type<"Record", "record",
 bool isComplete() const { return !isIncomplete(); };
 bool isIncomplete() const;
 
+mlir::Type getLargestMember(const mlir::DataLayout &dataLayout) const;
 size_t getNumElements() const { return getMembers().size(); };
 std::string getKindAsStr() {
   switch (getKind()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 0a518c0fd935d..f3bcffe042280 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -317,20 +317,25 @@ LValue CIRGenFunction::emitLValueForField(LValue base, 
const FieldDecl *field) {
   }
 
   unsigned recordCVR = base.getVRQualifiers();
-  if (rec->isUnion()) {
-cgm.errorNYI(field->getSourceRange(), "emitLValueForField: union");
-return LValue();
-  }
 
-  assert(!cir::MissingFeatures::preservedAccessIndexRegion());
   llvm::StringRef fieldName = field->getName();
-  const CIRGenRecordLayout &layout =
-  cgm.getTypes().getCIRGenRecordLayout(field->getParent());
-  unsigned fieldIndex = layout.getCIRFieldNo(field);
 
-  assert(!cir::MissingFeatures::lambdaFieldToName());
+  if (rec->isUnion()) {
+  unsigned fieldIndex = field->getFieldIndex();
+  assert(!cir::MissingFeatures::lambdaFieldToName());
+addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
 
-  addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
+  } else {
+assert(!cir::MissingFeatures::preservedAccessIndexRegion());
+
+const CIRGenRecordLayout &layout =
+cgm.getTypes().getCIRGenRecordLayout(field->getParent());
+unsigned fieldIndex = layout.getCIRFieldNo(field);
+
+assert(!cir::MissingFeatures::lambdaFieldToName());
+
+addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
+  }
 
   // If this is a reference field, load the reference right now.
   if (fieldType->isReferenceType()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 368a6cb27c0fd..e006a77c6e7d6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -1,4 +1,4 @@
-//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions 
-===//
+//===- CIRGenExprAggregrate.cpp - Emit CIR Code from Aggregate Expressions 
===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp 
b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
index 83aba256cd48e..778a178505684 100644
--- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -56,7 +56,7 @@ struct CIRRecordLowering final {
   };
   // The constructor.
   CIRRecordLowering(CIRGenTypes &cirGenTypes, const RecordDecl *recordDecl,
-bool isPacked);
+bool packed);
 
   /// Constructs a MemberInfo instance from an offset and mlir::Type.
   MemberInfo makeStorageInfo(CharUnits offset, mlir::Type data) {
@@ -64,6 +64,7 @@ struct CIRRecordLowering final {
   }
 
   void lower();
+  void lowerUnion();
 
   /// Determines if we need a packed llvm struct.
   void determinePacked();
@@ -83,6 +84,10 @@ struct CIRRecordLowering final {
 return CharUnits::fromQuantity(dataLayout.layout.getTypeABIAlignment(Ty));
   }
 
+  bool isZeroInitializable(const FieldDecl *fd) {
+return cirGenTypes.isZeroInitializable(fd->getType());
+  }
+
   /// Wraps cir::IntType with some implicit arguments.
   mlir::Type getUIntNType(uint64_t numBits) {
 unsigned alignedBits = llvm::PowerOf2Ceil(numBits);
@@ -121,6 +126,13 @@ struct CIRRecordLowering final {
   /// Fills out the structures that are ultimately consumed.
   void fillOutputFields();
 
+  void appen

[clang] [CIR] Upstream initial support for union type (PR #137501)

2025-04-27 Thread Iris Shi via cfe-commits

https://github.com/el-ev updated 
https://github.com/llvm/llvm-project/pull/137501

>From b8011997fdc2548be80dd9305d758466a66cee4c Mon Sep 17 00:00:00 2001
From: Iris Shi <0...@owo.li>
Date: Sun, 27 Apr 2025 15:16:19 +0800
Subject: [PATCH] [CIR] Upstream initial support for union type

---
 .../include/clang/CIR/Dialect/IR/CIRTypes.td  |   1 +
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  |  25 ++--
 clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp |   2 +-
 .../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp |  94 +++-
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp |  40 --
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  15 +-
 clang/test/CIR/CodeGen/union.c| 135 +-
 7 files changed, 276 insertions(+), 36 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 0a821e152d353..afb7da1fa011d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -494,6 +494,7 @@ def CIR_RecordType : CIR_Type<"Record", "record",
 bool isComplete() const { return !isIncomplete(); };
 bool isIncomplete() const;
 
+mlir::Type getLargestMember(const mlir::DataLayout &dataLayout) const;
 size_t getNumElements() const { return getMembers().size(); };
 std::string getKindAsStr() {
   switch (getKind()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 0a518c0fd935d..9069d1a2cf6ac 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -317,20 +317,25 @@ LValue CIRGenFunction::emitLValueForField(LValue base, 
const FieldDecl *field) {
   }
 
   unsigned recordCVR = base.getVRQualifiers();
-  if (rec->isUnion()) {
-cgm.errorNYI(field->getSourceRange(), "emitLValueForField: union");
-return LValue();
-  }
 
-  assert(!cir::MissingFeatures::preservedAccessIndexRegion());
   llvm::StringRef fieldName = field->getName();
-  const CIRGenRecordLayout &layout =
-  cgm.getTypes().getCIRGenRecordLayout(field->getParent());
-  unsigned fieldIndex = layout.getCIRFieldNo(field);
 
-  assert(!cir::MissingFeatures::lambdaFieldToName());
+  if (rec->isUnion()) {
+unsigned fieldIndex = field->getFieldIndex();
+assert(!cir::MissingFeatures::lambdaFieldToName());
+addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
+
+  } else {
+assert(!cir::MissingFeatures::preservedAccessIndexRegion());
+
+const CIRGenRecordLayout &layout =
+cgm.getTypes().getCIRGenRecordLayout(field->getParent());
+unsigned fieldIndex = layout.getCIRFieldNo(field);
 
-  addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
+assert(!cir::MissingFeatures::lambdaFieldToName());
+
+addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
+  }
 
   // If this is a reference field, load the reference right now.
   if (fieldType->isReferenceType()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 368a6cb27c0fd..e006a77c6e7d6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -1,4 +1,4 @@
-//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions 
-===//
+//===- CIRGenExprAggregrate.cpp - Emit CIR Code from Aggregate Expressions 
===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp 
b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
index 83aba256cd48e..7b9631daacfdd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -56,7 +56,7 @@ struct CIRRecordLowering final {
   };
   // The constructor.
   CIRRecordLowering(CIRGenTypes &cirGenTypes, const RecordDecl *recordDecl,
-bool isPacked);
+bool packed);
 
   /// Constructs a MemberInfo instance from an offset and mlir::Type.
   MemberInfo makeStorageInfo(CharUnits offset, mlir::Type data) {
@@ -64,6 +64,7 @@ struct CIRRecordLowering final {
   }
 
   void lower();
+  void lowerUnion();
 
   /// Determines if we need a packed llvm struct.
   void determinePacked();
@@ -83,6 +84,10 @@ struct CIRRecordLowering final {
 return CharUnits::fromQuantity(dataLayout.layout.getTypeABIAlignment(Ty));
   }
 
+  bool isZeroInitializable(const FieldDecl *fd) {
+return cirGenTypes.isZeroInitializable(fd->getType());
+  }
+
   /// Wraps cir::IntType with some implicit arguments.
   mlir::Type getUIntNType(uint64_t numBits) {
 unsigned alignedBits = llvm::PowerOf2Ceil(numBits);
@@ -121,6 +126,13 @@ struct CIRRecordLowering final {
   /// Fills out the structures that are ultimately consumed.
   void fillOutputFields();
 
+  void appendPaddingBytes(CharUnits

[clang] [CIR] Upstream initial support for union type (PR #137501)

2025-04-29 Thread Iris Shi via cfe-commits

https://github.com/el-ev updated 
https://github.com/llvm/llvm-project/pull/137501

>From b8011997fdc2548be80dd9305d758466a66cee4c Mon Sep 17 00:00:00 2001
From: Iris Shi <0...@owo.li>
Date: Sun, 27 Apr 2025 15:16:19 +0800
Subject: [PATCH 1/2] [CIR] Upstream initial support for union type

---
 .../include/clang/CIR/Dialect/IR/CIRTypes.td  |   1 +
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  |  25 ++--
 clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp |   2 +-
 .../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp |  94 +++-
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp |  40 --
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  15 +-
 clang/test/CIR/CodeGen/union.c| 135 +-
 7 files changed, 276 insertions(+), 36 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 0a821e152d353..afb7da1fa011d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -494,6 +494,7 @@ def CIR_RecordType : CIR_Type<"Record", "record",
 bool isComplete() const { return !isIncomplete(); };
 bool isIncomplete() const;
 
+mlir::Type getLargestMember(const mlir::DataLayout &dataLayout) const;
 size_t getNumElements() const { return getMembers().size(); };
 std::string getKindAsStr() {
   switch (getKind()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 0a518c0fd935d..9069d1a2cf6ac 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -317,20 +317,25 @@ LValue CIRGenFunction::emitLValueForField(LValue base, 
const FieldDecl *field) {
   }
 
   unsigned recordCVR = base.getVRQualifiers();
-  if (rec->isUnion()) {
-cgm.errorNYI(field->getSourceRange(), "emitLValueForField: union");
-return LValue();
-  }
 
-  assert(!cir::MissingFeatures::preservedAccessIndexRegion());
   llvm::StringRef fieldName = field->getName();
-  const CIRGenRecordLayout &layout =
-  cgm.getTypes().getCIRGenRecordLayout(field->getParent());
-  unsigned fieldIndex = layout.getCIRFieldNo(field);
 
-  assert(!cir::MissingFeatures::lambdaFieldToName());
+  if (rec->isUnion()) {
+unsigned fieldIndex = field->getFieldIndex();
+assert(!cir::MissingFeatures::lambdaFieldToName());
+addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
+
+  } else {
+assert(!cir::MissingFeatures::preservedAccessIndexRegion());
+
+const CIRGenRecordLayout &layout =
+cgm.getTypes().getCIRGenRecordLayout(field->getParent());
+unsigned fieldIndex = layout.getCIRFieldNo(field);
 
-  addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
+assert(!cir::MissingFeatures::lambdaFieldToName());
+
+addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
+  }
 
   // If this is a reference field, load the reference right now.
   if (fieldType->isReferenceType()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 368a6cb27c0fd..e006a77c6e7d6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -1,4 +1,4 @@
-//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions 
-===//
+//===- CIRGenExprAggregrate.cpp - Emit CIR Code from Aggregate Expressions 
===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp 
b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
index 83aba256cd48e..7b9631daacfdd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -56,7 +56,7 @@ struct CIRRecordLowering final {
   };
   // The constructor.
   CIRRecordLowering(CIRGenTypes &cirGenTypes, const RecordDecl *recordDecl,
-bool isPacked);
+bool packed);
 
   /// Constructs a MemberInfo instance from an offset and mlir::Type.
   MemberInfo makeStorageInfo(CharUnits offset, mlir::Type data) {
@@ -64,6 +64,7 @@ struct CIRRecordLowering final {
   }
 
   void lower();
+  void lowerUnion();
 
   /// Determines if we need a packed llvm struct.
   void determinePacked();
@@ -83,6 +84,10 @@ struct CIRRecordLowering final {
 return CharUnits::fromQuantity(dataLayout.layout.getTypeABIAlignment(Ty));
   }
 
+  bool isZeroInitializable(const FieldDecl *fd) {
+return cirGenTypes.isZeroInitializable(fd->getType());
+  }
+
   /// Wraps cir::IntType with some implicit arguments.
   mlir::Type getUIntNType(uint64_t numBits) {
 unsigned alignedBits = llvm::PowerOf2Ceil(numBits);
@@ -121,6 +126,13 @@ struct CIRRecordLowering final {
   /// Fills out the structures that are ultimately consumed.
   void fillOutputFields();
 
+  void appendPaddingBytes(CharU

[clang] [CIR] Upstream initial support for union type (PR #137501)

2025-04-29 Thread Iris Shi via cfe-commits


@@ -5,25 +5,146 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
 // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
 
+union U1 {

el-ev wrote:

Padded and packed unions are added, `CIRGenTypes::isZeroInitializable` doesn't 
contain a path that returns false without triggering errorNYI.

https://github.com/llvm/llvm-project/pull/137501
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Upstream initial support for union type (PR #137501)

2025-04-29 Thread Iris Shi via cfe-commits


@@ -306,3 +320,71 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, 
cir::RecordType *ty) {
   // TODO: implement verification
   return rl;
 }
+
+void CIRRecordLowering::lowerUnion() {
+  CharUnits layoutSize = astRecordLayout.getSize();
+  mlir::Type storageType = nullptr;
+  bool seenNamedMember = false;
+
+  // Iterate through the fields setting bitFieldInfo and the Fields array. Also
+  // locate the "most appropriate" storage type.  The heuristic for finding the

el-ev wrote:

Removed

https://github.com/llvm/llvm-project/pull/137501
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Upstream initial support for union type (PR #137501)

2025-04-29 Thread Iris Shi via cfe-commits


@@ -306,3 +320,71 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, 
cir::RecordType *ty) {
   // TODO: implement verification
   return rl;
 }
+
+void CIRRecordLowering::lowerUnion() {
+  CharUnits layoutSize = astRecordLayout.getSize();
+  mlir::Type storageType = nullptr;
+  bool seenNamedMember = false;
+
+  // Iterate through the fields setting bitFieldInfo and the Fields array. Also
+  // locate the "most appropriate" storage type.  The heuristic for finding the
+  // storage type isn't necessary, the first (non-0-length-bitfield) field's
+  // type would work fine and be simpler but would be different than what we've
+  // been doing and cause lit tests to change.
+  for (const FieldDecl *field : recordDecl->fields()) {
+mlir::Type fieldType;
+if (field->isBitField())
+  cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
+ "bitfields in lowerUnion");
+else
+  fieldType = getStorageType(field);
+
+fields[field->getCanonicalDecl()] = 0;

el-ev wrote:

Renamed them to `fieldIdxMap`

https://github.com/llvm/llvm-project/pull/137501
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Upstream initial support for union type (PR #137501)

2025-04-29 Thread Iris Shi via cfe-commits


@@ -306,3 +320,71 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, 
cir::RecordType *ty) {
   // TODO: implement verification
   return rl;
 }
+
+void CIRRecordLowering::lowerUnion() {
+  CharUnits layoutSize = astRecordLayout.getSize();
+  mlir::Type storageType = nullptr;
+  bool seenNamedMember = false;
+
+  // Iterate through the fields setting bitFieldInfo and the Fields array. Also
+  // locate the "most appropriate" storage type.  The heuristic for finding the
+  // storage type isn't necessary, the first (non-0-length-bitfield) field's
+  // type would work fine and be simpler but would be different than what we've
+  // been doing and cause lit tests to change.
+  for (const FieldDecl *field : recordDecl->fields()) {
+mlir::Type fieldType;
+if (field->isBitField())
+  cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
+ "bitfields in lowerUnion");
+else
+  fieldType = getStorageType(field);
+
+fields[field->getCanonicalDecl()] = 0;
+
+// Compute zero-initializable status.
+// This union might not be zero initialized: it may contain a pointer to
+// data member which might have some exotic initialization sequence.
+// If this is the case, then we aught not to try and come up with a 
"better"
+// type, it might not be very easy to come up with a Constant which
+// correctly initializes it.
+if (!seenNamedMember) {
+  seenNamedMember = field->getIdentifier();
+  if (!seenNamedMember)
+if (const RecordDecl *fieldRD = field->getType()->getAsRecordDecl())
+  seenNamedMember = fieldRD->findFirstNamedDataMember();
+  if (seenNamedMember && !isZeroInitializable(field)) {
+zeroInitializable = zeroInitializableAsBase = false;
+storageType = fieldType;
+  }
+}
+
+// Because our union isn't zero initializable, we won't be getting a better
+// storage type.
+if (!zeroInitializable)
+  continue;
+
+// Conditionally update our storage type if we've got a new "better" one.
+if (!storageType || getAlignment(fieldType) > getAlignment(storageType) ||
+(getAlignment(fieldType) == getAlignment(storageType) &&
+ getSize(fieldType) > getSize(storageType)))
+  storageType = fieldType;
+
+// NOTE(cir): Track all union member's types, not just the largest one. It
+// allows for proper type-checking and retain more info for analisys.
+fieldTypes.push_back(fieldType);
+  }
+
+  if (!storageType)
+cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
+   "No-storage Union NYI");
+
+  if (layoutSize < getSize(storageType))
+storageType = getByteArrayType(layoutSize);
+
+  // NOTE(cir): Defer padding calculations to the lowering process.

el-ev wrote:

It was indeed confusing and not true, removed.

https://github.com/llvm/llvm-project/pull/137501
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Upstream initial support for union type (PR #137501)

2025-04-29 Thread Iris Shi via cfe-commits


@@ -306,3 +320,71 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, 
cir::RecordType *ty) {
   // TODO: implement verification
   return rl;
 }
+
+void CIRRecordLowering::lowerUnion() {
+  CharUnits layoutSize = astRecordLayout.getSize();
+  mlir::Type storageType = nullptr;
+  bool seenNamedMember = false;
+
+  // Iterate through the fields setting bitFieldInfo and the Fields array. Also
+  // locate the "most appropriate" storage type.  The heuristic for finding the
+  // storage type isn't necessary, the first (non-0-length-bitfield) field's
+  // type would work fine and be simpler but would be different than what we've
+  // been doing and cause lit tests to change.
+  for (const FieldDecl *field : recordDecl->fields()) {
+mlir::Type fieldType;
+if (field->isBitField())
+  cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
+ "bitfields in lowerUnion");
+else
+  fieldType = getStorageType(field);
+
+fields[field->getCanonicalDecl()] = 0;
+
+// Compute zero-initializable status.
+// This union might not be zero initialized: it may contain a pointer to
+// data member which might have some exotic initialization sequence.
+// If this is the case, then we aught not to try and come up with a 
"better"
+// type, it might not be very easy to come up with a Constant which
+// correctly initializes it.
+if (!seenNamedMember) {

el-ev wrote:

If the first named member is a `RecordDecl`, it will trigger `ClangIR code gen 
Not Yet Implemented: isZeroInitializable for RecordType: 'S'`

https://github.com/llvm/llvm-project/pull/137501
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Cleanup support for C functions (PR #136854)

2025-04-29 Thread Iris Shi via cfe-commits

https://github.com/el-ev updated 
https://github.com/llvm/llvm-project/pull/136854

>From fd1d37ebf0f1c4a23f573444f30730b0f65630bf Mon Sep 17 00:00:00 2001
From: Iris Shi <0...@owo.li>
Date: Wed, 23 Apr 2025 20:23:09 +0800
Subject: [PATCH 1/2] [CIR] Cleanup support for C functions

---
 clang/lib/CIR/CodeGen/CIRGenCall.cpp   | 82 +++-
 clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 90 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp | 17 +++-
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp  | 37 -
 clang/lib/CIR/CodeGen/CIRGenTypes.h| 12 ++-
 clang/lib/CIR/CodeGen/TargetInfo.cpp   | 10 ++-
 clang/test/CIR/CodeGen/basic.c | 13 
 7 files changed, 232 insertions(+), 29 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 69266f79a88a5..b223bc494f928 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -13,20 +13,76 @@
 
 #include "CIRGenCall.h"
 #include "CIRGenFunction.h"
+#include "CIRGenFunctionInfo.h"
 #include "clang/CIR/MissingFeatures.h"
 
 using namespace clang;
 using namespace clang::CIRGen;
 
-CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) {
-  void *buffer = operator new(totalSizeToAlloc(1));
+CIRGenFunctionInfo *
+CIRGenFunctionInfo::create(CanQualType resultType,
+   llvm::ArrayRef argTypes,
+   RequiredArgs required) {
+  void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1));
 
   CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
+
+  fi->required = required;
+  fi->numArgs = argTypes.size();
   fi->getArgsBuffer()[0].type = resultType;
+  for (unsigned i = 0; i < argTypes.size(); ++i)
+fi->getArgsBuffer()[i + 1].type = argTypes[i];
 
   return fi;
 }
 
+cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
+  bool inserted = functionsBeingProcessed.insert(&fi).second;
+  assert(inserted && "Recursively being processed?");
+
+  mlir::Type resultType = nullptr;
+  const cir::ABIArgInfo &retAI = fi.getReturnInfo();
+
+  switch (retAI.getKind()) {
+  case cir::ABIArgInfo::Ignore:
+// TODO(CIR): This should probably be the None type from the builtin
+// dialect.
+resultType = nullptr;
+break;
+
+  case cir::ABIArgInfo::Direct:
+resultType = retAI.getCoerceToType();
+break;
+
+  default:
+assert(false && "NYI");
+  }
+
+  SmallVector argTypes;
+  unsigned argNo = 0;
+  CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(),
+ ie = it + fi.getNumRequiredArgs();
+  for (; it != ie; ++it, ++argNo) {
+const auto &argInfo = it->info;
+
+switch (argInfo.getKind()) {
+default:
+  llvm_unreachable("NYI");
+case cir::ABIArgInfo::Direct:
+  mlir::Type argType = argInfo.getCoerceToType();
+  argTypes.push_back(argType);
+  break;
+}
+  }
+
+  bool erased = functionsBeingProcessed.erase(&fi);
+  assert(erased && "Not in set?");
+
+  return cir::FuncType::get(argTypes,
+(resultType ? resultType : builder.getVoidTy()),
+fi.isVariadic());
+}
+
 CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
   assert(!cir::MissingFeatures::opCallVirtual());
   return *this;
@@ -35,6 +91,9 @@ CIRGenCallee 
CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
 static const CIRGenFunctionInfo &
 arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
 const FunctionType *fnType) {
+
+  RequiredArgs required = RequiredArgs::All;
+
   if (const auto *proto = dyn_cast(fnType)) {
 if (proto->isVariadic())
   cgm.errorNYI("call to variadic function");
@@ -49,7 +108,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule 
&cgm,
   CanQualType retType = fnType->getReturnType()
 ->getCanonicalTypeUnqualified()
 .getUnqualifiedType();
-  return cgt.arrangeCIRFunctionInfo(retType);
+  return cgt.arrangeCIRFunctionInfo(retType, {}, required);
 }
 
 const CIRGenFunctionInfo &
@@ -71,6 +130,23 @@ static cir::CIRCallOpInterface 
emitCallLikeOp(CIRGenFunction &cgf,
   return builder.createCallOp(callLoc, directFuncOp);
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionType(CanQual fpt) {
+  SmallVector argTypes;
+  for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i)
+argTypes.push_back(fpt->getParamType(i));
+  RequiredArgs required = RequiredArgs::forPrototypePlus(fpt);
+
+  CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
+  return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionType(CanQual fnpt) {
+  CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
+  return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));

[clang] [clang] ownership_returns attribute takes no more than 2 arguments (PR #137897)

2025-04-30 Thread Iris Shi via cfe-commits

https://github.com/el-ev approved this pull request.

LGTM

https://github.com/llvm/llvm-project/pull/137897
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] ownership_returns attribute takes no more than 2 arguments (PR #137897)

2025-04-30 Thread Iris Shi via cfe-commits

el-ev wrote:

### Merge activity

* **Apr 30, 7:27 AM EDT**: A user started a stack merge that includes this pull 
request via 
[Graphite](https://app.graphite.dev/github/pr/llvm/llvm-project/137897).


https://github.com/llvm/llvm-project/pull/137897
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] ownership_returns attribute takes no more than 2 arguments (PR #137897)

2025-04-30 Thread Iris Shi via cfe-commits

https://github.com/el-ev closed https://github.com/llvm/llvm-project/pull/137897
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Upstream initial support for union type (PR #137501)

2025-04-30 Thread Iris Shi via cfe-commits

https://github.com/el-ev closed https://github.com/llvm/llvm-project/pull/137501
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Cleanup support for C functions (PR #136854)

2025-04-24 Thread Iris Shi via cfe-commits


@@ -47,18 +98,51 @@ class CIRGenFunctionInfo final
 
   // This function has to be CamelCase because llvm::FoldingSet requires so.
   // NOLINTNEXTLINE(readability-identifier-naming)
-  static void Profile(llvm::FoldingSetNodeID &id, CanQualType resultType) {
+  static void Profile(llvm::FoldingSetNodeID &id, RequiredArgs required,
+  CanQualType resultType,
+  llvm::ArrayRef argTypes) {
+id.AddBoolean(required.getOpaqueData());
 resultType.Profile(id);
+for (const auto &arg : argTypes)
+  arg.Profile(id);
   }
 
-  void Profile(llvm::FoldingSetNodeID &id) { getReturnType().Profile(id); }
+  // NOLINTNEXTLINE(readability-identifier-naming)
+  void Profile(llvm::FoldingSetNodeID &id) {
+id.AddBoolean(required.getOpaqueData());
+getReturnType().Profile(id);
+for (const auto &i : arguments())

el-ev wrote:

Yes.

https://github.com/llvm/llvm-project/pull/136854
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Cleanup support for C functions (PR #136854)

2025-04-24 Thread Iris Shi via cfe-commits

https://github.com/el-ev updated 
https://github.com/llvm/llvm-project/pull/136854

>From fd1d37ebf0f1c4a23f573444f30730b0f65630bf Mon Sep 17 00:00:00 2001
From: Iris Shi <0...@owo.li>
Date: Wed, 23 Apr 2025 20:23:09 +0800
Subject: [PATCH 1/2] [CIR] Cleanup support for C functions

---
 clang/lib/CIR/CodeGen/CIRGenCall.cpp   | 82 +++-
 clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 90 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp | 17 +++-
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp  | 37 -
 clang/lib/CIR/CodeGen/CIRGenTypes.h| 12 ++-
 clang/lib/CIR/CodeGen/TargetInfo.cpp   | 10 ++-
 clang/test/CIR/CodeGen/basic.c | 13 
 7 files changed, 232 insertions(+), 29 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 69266f79a88a5..b223bc494f928 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -13,20 +13,76 @@
 
 #include "CIRGenCall.h"
 #include "CIRGenFunction.h"
+#include "CIRGenFunctionInfo.h"
 #include "clang/CIR/MissingFeatures.h"
 
 using namespace clang;
 using namespace clang::CIRGen;
 
-CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) {
-  void *buffer = operator new(totalSizeToAlloc(1));
+CIRGenFunctionInfo *
+CIRGenFunctionInfo::create(CanQualType resultType,
+   llvm::ArrayRef argTypes,
+   RequiredArgs required) {
+  void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1));
 
   CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
+
+  fi->required = required;
+  fi->numArgs = argTypes.size();
   fi->getArgsBuffer()[0].type = resultType;
+  for (unsigned i = 0; i < argTypes.size(); ++i)
+fi->getArgsBuffer()[i + 1].type = argTypes[i];
 
   return fi;
 }
 
+cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
+  bool inserted = functionsBeingProcessed.insert(&fi).second;
+  assert(inserted && "Recursively being processed?");
+
+  mlir::Type resultType = nullptr;
+  const cir::ABIArgInfo &retAI = fi.getReturnInfo();
+
+  switch (retAI.getKind()) {
+  case cir::ABIArgInfo::Ignore:
+// TODO(CIR): This should probably be the None type from the builtin
+// dialect.
+resultType = nullptr;
+break;
+
+  case cir::ABIArgInfo::Direct:
+resultType = retAI.getCoerceToType();
+break;
+
+  default:
+assert(false && "NYI");
+  }
+
+  SmallVector argTypes;
+  unsigned argNo = 0;
+  CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(),
+ ie = it + fi.getNumRequiredArgs();
+  for (; it != ie; ++it, ++argNo) {
+const auto &argInfo = it->info;
+
+switch (argInfo.getKind()) {
+default:
+  llvm_unreachable("NYI");
+case cir::ABIArgInfo::Direct:
+  mlir::Type argType = argInfo.getCoerceToType();
+  argTypes.push_back(argType);
+  break;
+}
+  }
+
+  bool erased = functionsBeingProcessed.erase(&fi);
+  assert(erased && "Not in set?");
+
+  return cir::FuncType::get(argTypes,
+(resultType ? resultType : builder.getVoidTy()),
+fi.isVariadic());
+}
+
 CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
   assert(!cir::MissingFeatures::opCallVirtual());
   return *this;
@@ -35,6 +91,9 @@ CIRGenCallee 
CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
 static const CIRGenFunctionInfo &
 arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
 const FunctionType *fnType) {
+
+  RequiredArgs required = RequiredArgs::All;
+
   if (const auto *proto = dyn_cast(fnType)) {
 if (proto->isVariadic())
   cgm.errorNYI("call to variadic function");
@@ -49,7 +108,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule 
&cgm,
   CanQualType retType = fnType->getReturnType()
 ->getCanonicalTypeUnqualified()
 .getUnqualifiedType();
-  return cgt.arrangeCIRFunctionInfo(retType);
+  return cgt.arrangeCIRFunctionInfo(retType, {}, required);
 }
 
 const CIRGenFunctionInfo &
@@ -71,6 +130,23 @@ static cir::CIRCallOpInterface 
emitCallLikeOp(CIRGenFunction &cgf,
   return builder.createCallOp(callLoc, directFuncOp);
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionType(CanQual fpt) {
+  SmallVector argTypes;
+  for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i)
+argTypes.push_back(fpt->getParamType(i));
+  RequiredArgs required = RequiredArgs::forPrototypePlus(fpt);
+
+  CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
+  return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionType(CanQual fnpt) {
+  CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
+  return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));