Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[CIR] Upstream CompoundLiteralExpr for Scalar#148943

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
AmrDeveloper wants to merge3 commits intollvm:main
base:main
Choose a base branch
Loading
fromAmrDeveloper:cir_upstream_compound_literal_expr

Conversation

AmrDeveloper
Copy link
Member

Upstream CompoundLiteralExpr for Scalar as a prerequisite for CompoundLiteralExpr for ComplexType

@llvmbotllvmbot added clangClang issues not falling into any other category ClangIRAnything related to the ClangIR project labelsJul 15, 2025
@llvmbot
Copy link
Member

@llvm/pr-subscribers-clang

Author: Amr Hesham (AmrDeveloper)

Changes

Upstream CompoundLiteralExpr for Scalar as a prerequisite for CompoundLiteralExpr for ComplexType


Full diff:https://github.com/llvm/llvm-project/pull/148943.diff

5 Files Affected:

  • (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+62)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+4)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+2)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+6)
  • (added) clang/test/CIR/CodeGen/compound_literal.cpp (+42)
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cppindex 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.cppindex 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.cppindex 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.hindex 1346333739bc1..3badb46f61e5f 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.cppnew file mode 100644index 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]]

@llvmbot
Copy link
Member

@llvm/pr-subscribers-clangir

Author: Amr Hesham (AmrDeveloper)

Changes

Upstream CompoundLiteralExpr for Scalar as a prerequisite for CompoundLiteralExpr for ComplexType


Full diff:https://github.com/llvm/llvm-project/pull/148943.diff

5 Files Affected:

  • (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+62)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+4)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+2)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+6)
  • (added) clang/test/CIR/CodeGen/compound_literal.cpp (+42)
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cppindex 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.cppindex 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.cppindex 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.hindex 1346333739bc1..3badb46f61e5f 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.cppnew file mode 100644index 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]]

// FIXME: This function should take an LValue as an argument.
switch (getEvaluationKind(e->getType())) {
case cir::TEK_Complex: {
RValue rv = RValue::get(emitComplexExpr(e));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Classic codegen callsemitComplexExprIntoLValue() here. That's probably because complex is stored using multiple operations there, but since we have this same function, it seems like a good idea to keep the same structure. It will make things easier if we decide to change how we handle complex values later.

AmrDeveloper reacted with thumbs up emoji

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

+1

AmrDeveloper reacted with thumbs up emoji
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG

int foo() {
int e = (int){1};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Can you add test cases for complex and aggregate?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Complex type requires to handle it too in CIRGenExprComplex, i will do that in this PR and update tests

andykaylor and bcardosolopes reacted with thumbs up emoji
Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I used Vector for aggregate test because visitCXXParenListOrInitListExpr is NYI for structure type

@AmrDeveloperAmrDeveloperforce-pushed thecir_upstream_compound_literal_expr branch from57dc1cb toe8d6879CompareJuly 17, 2025 19:36
Copy link
Contributor

@andykaylorandykaylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

lgtm

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@andykaylorandykaylorandykaylor approved these changes

@lanzalanzaAwaiting requested review from lanzalanza is a code owner

@bcardosolopesbcardosolopesAwaiting requested review from bcardosolopesbcardosolopes is a code owner

@xlaukoxlaukoAwaiting requested review from xlaukoxlauko is a code owner

Assignees
No one assigned
Labels
clangClang issues not falling into any other categoryClangIRAnything related to the ClangIR project
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

4 participants
@AmrDeveloper@llvmbot@bcardosolopes@andykaylor

[8]ページ先頭

©2009-2025 Movatter.jp