[clang] [CIR] Upstream emitAndUpdateRetAlloca (PR #129933)

Amr Hesham via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 5 12:43:14 PST 2025


https://github.com/AmrDeveloper created https://github.com/llvm/llvm-project/pull/129933

This change adds support for the basic case of emitAndUpdateRetAlloca

>From 1db2baafe9ed0ab360517810144300db0e7410f6 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Wed, 5 Mar 2025 18:18:07 +0100
Subject: [PATCH] [CIR] Upstream emitAndUpdateRetAlloca

---
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 22 +++++++++++++
 clang/lib/CIR/CodeGen/CIRGenFunction.h   |  5 +++
 clang/test/CIR/func-simple.cpp           | 40 ++++++++++++++----------
 3 files changed, 51 insertions(+), 16 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 7861a48c93244..69f29826d5ab0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -195,7 +195,16 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType,
     mlir::Location fnBodyBegin = getLoc(fd->getBody()->getBeginLoc());
     builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal, addrVal);
   }
+
   assert(builder.getInsertionBlock() && "Should be valid");
+
+  auto fnEndLoc = getLoc(fd->getBody()->getEndLoc());
+
+  // When the current function is not void, create an address to store the
+  // result value.
+  if (fnRetCIRTy.has_value())
+    emitAndUpdateRetAlloca(fnRetQualTy, fnEndLoc,
+                           getContext().getTypeAlignInChars(fnRetQualTy));
 }
 
 void CIRGenFunction::finishFunction(SourceLocation endLoc) {}
@@ -213,6 +222,11 @@ mlir::LogicalResult CIRGenFunction::emitFunctionBody(const clang::Stmt *body) {
 cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
                                          cir::FuncType funcType) {
   const auto funcDecl = cast<FunctionDecl>(gd.getDecl());
+  fnRetQualTy = funcDecl->getReturnType();
+  if (!fnRetQualTy->isVoidType()) {
+    fnRetCIRTy = convertType(fnRetQualTy);
+  }
+
   SourceLocation loc = funcDecl->getLocation();
   Stmt *body = funcDecl->getBody();
   SourceRange bodyRange =
@@ -312,4 +326,12 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
   }
 }
 
+void CIRGenFunction::emitAndUpdateRetAlloca(QualType ty, mlir::Location loc,
+                                            CharUnits alignment) {
+  if (ty->isVoidType()) {
+    return;
+  }
+
+  emitAlloca("__retval", convertType(ty), loc, alignment);
+}
 } // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 6b383378ae764..482f0e219a299 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -49,6 +49,8 @@ class CIRGenFunction : public CIRGenTypeCache {
 
 public:
   clang::QualType fnRetTy;
+  clang::QualType fnRetQualTy;
+  std::optional<mlir::Type> fnRetCIRTy;
 
   /// This is the current function or global initializer that is generated code
   /// for.
@@ -101,6 +103,9 @@ class CIRGenFunction : public CIRGenTypeCache {
                               clang::QualType ty, mlir::Location loc,
                               clang::CharUnits alignment, bool isParam = false);
 
+  void emitAndUpdateRetAlloca(clang::QualType ty, mlir::Location loc,
+                              clang::CharUnits alignment);
+
 public:
   mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
                          mlir::Location loc, clang::CharUnits alignment);
diff --git a/clang/test/CIR/func-simple.cpp b/clang/test/CIR/func-simple.cpp
index d37ccc7229f22..a8488d628d8f7 100644
--- a/clang/test/CIR/func-simple.cpp
+++ b/clang/test/CIR/func-simple.cpp
@@ -13,8 +13,9 @@ void voidret() { return; }
 
 int intfunc() { return 42; }
 // CHECK: cir.func @intfunc() -> !cir.int<s, 32> {
-// CHECK:   %0 = cir.const #cir.int<42> : !cir.int<s, 32>
-// CHECK:   cir.return %0 : !cir.int<s, 32>
+// CHECK:   %0 = cir.alloca !cir.int<s, 32>, !cir.ptr<!cir.int<s, 32>>, ["__retval"] {alignment = 4 : i64}
+// CHECK:   %1 = cir.const #cir.int<42> : !cir.int<s, 32>
+// CHECK:   cir.return %1 : !cir.int<s, 32>
 // CHECK: }
 
 int scopes() {
@@ -25,10 +26,11 @@ int scopes() {
   }
 }
 // CHECK: cir.func @scopes() -> !cir.int<s, 32> {
+// CHECK:   %0 = cir.alloca !cir.int<s, 32>, !cir.ptr<!cir.int<s, 32>>, ["__retval"] {alignment = 4 : i64}
 // CHECK:   cir.scope {
 // CHECK:     cir.scope {
-// CHECK:       %0 = cir.const #cir.int<99> : !cir.int<s, 32>
-// CHECK:       cir.return %0 : !cir.int<s, 32>
+// CHECK:       %1 = cir.const #cir.int<99> : !cir.int<s, 32>
+// CHECK:       cir.return %1 : !cir.int<s, 32>
 // CHECK:     }
 // CHECK:   }
 // CHECK:   cir.trap
@@ -36,36 +38,42 @@ int scopes() {
 
 long longfunc() { return 42l; }
 // CHECK: cir.func @longfunc() -> !cir.int<s, 64>
-// CHECK:   %0 = cir.const #cir.int<42> : !cir.int<s, 64>
-// CHECK:   cir.return %0 : !cir.int<s, 64>
+// CHECK:   %0 = cir.alloca !cir.int<s, 64>, !cir.ptr<!cir.int<s, 64>>, ["__retval"] {alignment = 8 : i64}
+// CHECK:   %1 = cir.const #cir.int<42> : !cir.int<s, 64>
+// CHECK:   cir.return %1 : !cir.int<s, 64>
 // CHECK: }
 
 unsigned unsignedfunc() { return 42u; }
 // CHECK: cir.func @unsignedfunc() -> !cir.int<u, 32>
-// CHECK:   %0 = cir.const #cir.int<42> : !cir.int<u, 32>
-// CHECK:   cir.return %0 : !cir.int<u, 32>
+// CHECK:   %0 = cir.alloca !cir.int<u, 32>, !cir.ptr<!cir.int<u, 32>>, ["__retval"] {alignment = 4 : i64}
+// CHECK:   %1 = cir.const #cir.int<42> : !cir.int<u, 32>
+// CHECK:   cir.return %1 : !cir.int<u, 32>
 // CHECK: }
 
 unsigned long long ullfunc() { return 42ull; }
 // CHECK: cir.func @ullfunc() -> !cir.int<u, 64>
-// CHECK:   %0 = cir.const #cir.int<42> : !cir.int<u, 64>
-// CHECK:   cir.return %0 : !cir.int<u, 64>
+// CHECK:   %0 = cir.alloca !cir.int<u, 64>, !cir.ptr<!cir.int<u, 64>>, ["__retval"] {alignment = 8 : i64}
+// CHECK:   %1 = cir.const #cir.int<42> : !cir.int<u, 64>
+// CHECK:   cir.return %1 : !cir.int<u, 64>
 // CHECK: }
 
 bool boolfunc() { return true; }
 // CHECK: cir.func @boolfunc() -> !cir.bool {
-// CHECK:   %0 = cir.const #true
-// CHECK:   cir.return %0 : !cir.bool
+// CHECK:   %0 = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["__retval"] {alignment = 1 : i64}
+// CHECK:   %1 = cir.const #true
+// CHECK:   cir.return %1 : !cir.bool
 // CHECK: }
 
 float floatfunc() { return 42.42f; }
 // CHECK: cir.func @floatfunc() -> !cir.float {
-// CHECK:   %0 = cir.const #cir.fp<4.242
-// CHECK:   cir.return %0 : !cir.float
+// CHECK:   %0 = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["__retval"] {alignment = 4 : i64}
+// CHECK:   %1 = cir.const #cir.fp<4.242
+// CHECK:   cir.return %1 : !cir.float
 // CHECK: }
 
 double doublefunc() { return 42.42; }
 // CHECK: cir.func @doublefunc() -> !cir.double {
-// CHECK:   %0 = cir.const #cir.fp<4.242
-// CHECK:   cir.return %0 : !cir.double
+// CHECK:   %0 = cir.alloca !cir.double, !cir.ptr<!cir.double>, ["__retval"] {alignment = 8 : i64}
+// CHECK:   %1 = cir.const #cir.fp<4.242
+// CHECK:   cir.return %1 : !cir.double
 // CHECK: }



More information about the cfe-commits mailing list