https://github.com/AmrDeveloper updated 
https://github.com/llvm/llvm-project/pull/148943

>From a83dcd3f747751cf1da861405572fbe94ff6c8f9 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Tue, 15 Jul 2025 21:47:30 +0200
Subject: [PATCH 1/2] [CIR] Upstream CompoundLiteralExpr for Scalar

---
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp        | 62 +++++++++++++++++++++
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp  |  4 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp    |  2 +
 clang/lib/CIR/CodeGen/CIRGenFunction.h      |  6 ++
 clang/test/CIR/CodeGen/compound_literal.cpp | 42 ++++++++++++++
 5 files changed, 116 insertions(+)
 create mode 100644 clang/test/CIR/CodeGen/compound_literal.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 51da48d330f55..11b66f4dda049 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1053,6 +1053,68 @@ LValue CIRGenFunction::emitMemberExpr(const MemberExpr 
*e) {
   llvm_unreachable("Unhandled member declaration!");
 }
 
+/// Evaluate an expression into a given memory location.
+void CIRGenFunction::emitAnyExprToMem(const Expr *e, Address location,
+                                      Qualifiers quals, bool isInit) {
+  // FIXME: This function should take an LValue as an argument.
+  switch (getEvaluationKind(e->getType())) {
+  case cir::TEK_Complex: {
+    RValue rv = RValue::get(emitComplexExpr(e));
+    LValue lv = makeAddrLValue(location, e->getType());
+    emitStoreThroughLValue(rv, lv);
+    return;
+  }
+
+  case cir::TEK_Aggregate: {
+    emitAggExpr(e, AggValueSlot::forAddr(location, quals,
+                                         AggValueSlot::IsDestructed_t(isInit),
+                                         AggValueSlot::IsAliased_t(!isInit),
+                                         AggValueSlot::MayOverlap));
+    return;
+  }
+
+  case cir::TEK_Scalar: {
+    RValue rv = RValue::get(emitScalarExpr(e));
+    LValue lv = makeAddrLValue(location, e->getType());
+    emitStoreThroughLValue(rv, lv);
+    return;
+  }
+  }
+
+  llvm_unreachable("bad evaluation kind");
+}
+
+LValue CIRGenFunction::emitCompoundLiteralLValue(const CompoundLiteralExpr *e) 
{
+  if (e->isFileScope()) {
+    cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope");
+    return {};
+  }
+
+  if (e->getType()->isVariablyModifiedType()) {
+    cgm.errorNYI(e->getSourceRange(),
+                 "emitCompoundLiteralLValue: VariablyModifiedType");
+    return {};
+  }
+
+  Address declPtr = createMemTemp(e->getType(), getLoc(e->getSourceRange()),
+                                  ".compoundliteral");
+  const Expr *initExpr = e->getInitializer();
+  LValue result = makeAddrLValue(declPtr, e->getType(), AlignmentSource::Decl);
+
+  emitAnyExprToMem(initExpr, declPtr, e->getType().getQualifiers(),
+                   /*Init*/ true);
+
+  // Block-scope compound literals are destroyed at the end of the enclosing
+  // scope in C.
+  if (!getLangOpts().CPlusPlus && e->getType().isDestructedType()) {
+    cgm.errorNYI(e->getSourceRange(),
+                 "emitCompoundLiteralLValue: non C++ DestructedType");
+    return {};
+  }
+
+  return result;
+}
+
 LValue CIRGenFunction::emitCallExprLValue(const CallExpr *e) {
   RValue rv = emitCallExpr(e);
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 9e13b4c83e3a8..23112be6bf3e7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -233,6 +233,10 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
 
   mlir::Value VisitMemberExpr(MemberExpr *e);
 
+  mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
+    return emitLoadOfLValue(e);
+  }
+
   mlir::Value VisitInitListExpr(InitListExpr *e);
 
   mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp 
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index e532b9d855843..7e1a44ce602d4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -698,6 +698,8 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
     return emitStringLiteralLValue(cast<StringLiteral>(e));
   case Expr::MemberExprClass:
     return emitMemberExpr(cast<MemberExpr>(e));
+  case Expr::CompoundLiteralExprClass:
+    return emitCompoundLiteralLValue(cast<CompoundLiteralExpr>(e));
   case Expr::BinaryOperatorClass:
     return emitBinaryOperatorLValue(cast<BinaryOperator>(e));
   case Expr::CompoundAssignOperatorClass: {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 9541f4f0725eb..75f9e65719d82 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -757,6 +757,11 @@ class CIRGenFunction : public CIRGenTypeCache {
   RValue emitAnyExpr(const clang::Expr *e,
                      AggValueSlot aggSlot = AggValueSlot::ignored());
 
+  /// Emits the code necessary to evaluate an arbitrary expression into the
+  /// given memory location.
+  void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals,
+                        bool isInitializer);
+
   /// Similarly to emitAnyExpr(), however, the result will always be accessible
   /// even if no aggregate location is provided.
   RValue emitAnyExprToTemp(const clang::Expr *e);
@@ -828,6 +833,7 @@ class CIRGenFunction : public CIRGenTypeCache {
   mlir::Value emitCheckedArgForAssume(const Expr *e);
 
   LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e);
+  LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e);
 
   void emitConstructorBody(FunctionArgList &args);
   void emitDestructorBody(FunctionArgList &args);
diff --git a/clang/test/CIR/CodeGen/compound_literal.cpp 
b/clang/test/CIR/CodeGen/compound_literal.cpp
new file mode 100644
index 0000000000000..a3f15b9437885
--- /dev/null
+++ b/clang/test/CIR/CodeGen/compound_literal.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+int foo() {
+  int e = (int){1};
+  return e;
+}
+
+// CIR: %[[RET:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
+// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init]
+// CIR: %[[COMPOUND:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, 
[".compoundliteral", init]
+// CIR: %[[VALUE:.*]] = cir.const #cir.int<1> : !s32i
+// CIR: cir.store{{.*}} %[[VALUE]], %[[COMPOUND]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[COMPOUND]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store{{.*}}  %[[TMP]], %[[INIT]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[TMP_2:.*]] = cir.load{{.*}} %[[INIT]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store %[[TMP_2]], %[[RET]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[TMP_3:.*]] = cir.load %[[RET]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.return %[[TMP_3]] : !s32i
+
+// LLVM: %[[RET:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[COMPOUND:.*]] = alloca i32, i64 1, align 4
+// LLVM: store i32 1, ptr %[[COMPOUND]], align 4
+// LLVM: %[[TMP:.*]] = load i32, ptr %[[COMPOUND]], align 4
+// LLVM: store i32 %[[TMP]], ptr %[[INIT]], align 4
+// LLVM: %[[TMP_2:.*]] = load i32, ptr %[[INIT]], align 4
+// LLVM: store i32 %[[TMP_2]], ptr %[[RET]], align 4
+// LLVM: %[[TMP_3:.*]] = load i32, ptr %[[RET]], align 4
+// LLVM: ret i32 %[[TMP_3]]
+
+// OGCG: %[[INIT:.*]] = alloca i32, align 4
+// OGCG: %[[COMPOUND:.*]] = alloca i32, align 4
+// OGCG: store i32 1, ptr %[[COMPOUND]], align 4
+// OGCG: %[[TMP:.*]] = load i32, ptr %[[COMPOUND]], align 4
+// OGCG: store i32 %[[TMP]], ptr %[[INIT]], align 4
+// OGCG: %[[TMP_2:.*]] = load i32, ptr %[[INIT]], align 4
+// OGCG: ret i32 %[[TMP_2]]

>From e8d6879bd8dd88e2fea36a19306e77cceb8422f6 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Thu, 17 Jul 2025 20:20:58 +0200
Subject: [PATCH 2/2] Address code review comments

---
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp        |  3 +-
 clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp | 14 +++++
 clang/lib/CIR/CodeGen/CIRGenFunction.h      |  2 +
 clang/test/CIR/CodeGen/compound_literal.cpp | 57 +++++++++++++++++++++
 4 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 11b66f4dda049..ff0096555fbce 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1059,9 +1059,8 @@ void CIRGenFunction::emitAnyExprToMem(const Expr *e, 
Address location,
   // FIXME: This function should take an LValue as an argument.
   switch (getEvaluationKind(e->getType())) {
   case cir::TEK_Complex: {
-    RValue rv = RValue::get(emitComplexExpr(e));
     LValue lv = makeAddrLValue(location, e->getType());
-    emitStoreThroughLValue(rv, lv);
+    emitComplexExprIntoLValue(e, lv, isInit);
     return;
   }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 0a22771378ff1..81cb7f9cf77cb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -52,6 +52,11 @@ class ComplexExprEmitter : public 
StmtVisitor<ComplexExprEmitter, mlir::Value> {
   mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e);
   mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
   mlir::Value VisitInitListExpr(const InitListExpr *e);
+
+  mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
+    return emitLoadOfLValue(e);
+  }
+
   mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
   mlir::Value VisitParenExpr(ParenExpr *e);
   mlir::Value
@@ -467,6 +472,15 @@ mlir::Value CIRGenFunction::emitComplexPrePostIncDec(const 
UnaryOperator *e,
   return isPre ? incVal : inVal;
 }
 
+void CIRGenFunction::emitComplexExprIntoLValue(const Expr *e, LValue dest,
+                                               bool isInit) {
+  assert(e && getComplexType(e->getType()) &&
+         "Invalid complex expression to emit");
+  ComplexExprEmitter emitter(*this);
+  mlir::Value value = emitter.Visit(const_cast<Expr *>(e));
+  emitter.emitStoreOfComplex(getLoc(e->getExprLoc()), value, dest, isInit);
+}
+
 mlir::Value CIRGenFunction::emitLoadOfComplex(LValue src, SourceLocation loc) {
   return ComplexExprEmitter(*this).emitLoadOfLValue(src, loc);
 }
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 75f9e65719d82..e2fa03d03b81e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -936,6 +936,8 @@ class CIRGenFunction : public CIRGenTypeCache {
   /// returning the result.
   mlir::Value emitComplexExpr(const Expr *e);
 
+  void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit);
+
   mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv,
                                        bool isInc, bool isPre);
 
diff --git a/clang/test/CIR/CodeGen/compound_literal.cpp 
b/clang/test/CIR/CodeGen/compound_literal.cpp
index a3f15b9437885..a92af95c62a1b 100644
--- a/clang/test/CIR/CodeGen/compound_literal.cpp
+++ b/clang/test/CIR/CodeGen/compound_literal.cpp
@@ -40,3 +40,60 @@ int foo() {
 // OGCG: store i32 %[[TMP]], ptr %[[INIT]], align 4
 // OGCG: %[[TMP_2:.*]] = load i32, ptr %[[INIT]], align 4
 // OGCG: ret i32 %[[TMP_2]]
+
+void foo2() {
+  int _Complex a = (int _Complex) { 1, 2};
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["a", init]
+// CIR: %[[CL_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, [".compoundliteral"]
+// CIR: %[[COMPLEX:.*]] = cir.const #cir.const_complex<#cir.int<1> : !s32i, 
#cir.int<2> : !s32i> : !cir.complex<!s32i>
+// CIR: cir.store{{.*}} %[[COMPLEX]], %[[CL_ADDR]] : !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>
+// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[CL_ADDR]] : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR: cir.store{{.*}} %[[TMP]], %[[A_ADDR]] : !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>
+
+// LLVM:  %[[A_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[CL_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: store { i32, i32 } { i32 1, i32 2 }, ptr %[[CL_ADDR]], align 4
+// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[CL_ADDR]], align 4
+// LLVM: store { i32, i32 } %[[TMP]], ptr %[[A_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[CL_ADDR:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[CL_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[CL_ADDR]], i32 0, i32 0
+// OGCG: %[[CL_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[CL_ADDR]], i32 0, i32 1
+// OGCG: store i32 1, ptr %[[CL_REAL_PTR]], align 4
+// OGCG: store i32 2, ptr %[[CL_IMAG_PTR]], align 4
+// OGCG: %[[CL_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[CL_ADDR]], i32 0, i32 0
+// OGCG: %[[CL_REAL:.*]] = load i32, ptr %[[CL_REAL_PTR]], align 4
+// OGCG: %[[CL_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[CL_ADDR]], i32 0, i32 1
+// OGCG: %[[CL_IMAG:.*]] = load i32, ptr %[[CL_IMAG_PTR]], align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[A_ADDR]], i32 0, i32 1
+// OGCG: store i32 %[[CL_REAL]], ptr %[[A_REAL_PTR]], align 4
+// OGCG: store i32 %[[CL_IMAG]], ptr %[[A_IMAG_PTR]], align 4
+
+void foo3() {
+  typedef int vi4 __attribute__((vector_size(16)));
+  auto a = (vi4){10, 20, 30, 40};
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>, ["a", init]
+// CIR: %[[CL_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>, [".compoundliteral", init]
+// CIR: %[[VEC:.*]] = cir.const #cir.const_vector<[#cir.int<10> : !s32i, 
#cir.int<20> : !s32i, #cir.int<30> : !s32i, #cir.int<40> : !s32i]> : 
!cir.vector<4 x !s32i>
+// CIR: cir.store{{.*}} %[[VEC]], %[[CL_ADDR]] : !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[CL_ADDR]] : !cir.ptr<!cir.vector<4 x 
!s32i>>, !cir.vector<4 x !s32i>
+// CIR: cir.store{{.*}} %[[TMP]], %[[A_ADDR]] : !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[CL_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: store <4 x i32> <i32 10, i32 20, i32 30, i32 40>, ptr %[[CL_ADDR]], 
align 16
+// LLVM: %[[TMP:.*]] = load <4 x i32>, ptr %[[CL_ADDR]], align 16
+// LLVM: store <4 x i32> %[[TMP]], ptr %[[A_ADDR]], align 16
+
+// OGCG:  %[[A_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[CL_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: store <4 x i32> <i32 10, i32 20, i32 30, i32 40>, ptr %[[CL_ADDR]], 
align 16
+// OGCG: %[[TMP:.*]] = load <4 x i32>, ptr %[[CL_ADDR]], align 16
+// OGCG: store <4 x i32> %[[TMP]], ptr %[[A_ADDR]], align 16
+

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to