[clang] [CIR] cir.call with scalar return type (PR #135552)

via cfe-commits cfe-commits at lists.llvm.org
Sun Apr 13 08:41:19 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Sirui Mu (Lancern)

<details>
<summary>Changes</summary>

This PR introduces support for calling functions with a scalar return type to the upstream. This PR also includes an initial version of `CIRGenTargetInfo` and related definitions which are essential for the CIRGen of call ops.

Related to #<!-- -->132487 .

---

Patch is 32.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135552.diff


21 Files Affected:

- (added) clang/include/clang/CIR/ABIArgInfo.h (+89) 
- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+5-3) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+5-1) 
- (modified) clang/include/clang/CIR/MissingFeatures.h (+4) 
- (added) clang/lib/CIR/CodeGen/ABIInfo.h (+32) 
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+72-10) 
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.h (+4) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+19-5) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+2-5) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+11-4) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h (+35-4) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+30) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+6) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+15-4) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+7-2) 
- (modified) clang/lib/CIR/CodeGen/CMakeLists.txt (+1) 
- (added) clang/lib/CIR/CodeGen/TargetInfo.cpp (+50) 
- (added) clang/lib/CIR/CodeGen/TargetInfo.h (+41) 
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+28-1) 
- (modified) clang/test/CIR/CodeGen/call.cpp (+10) 
- (modified) clang/test/CIR/IR/call.cir (+14) 


``````````diff
diff --git a/clang/include/clang/CIR/ABIArgInfo.h b/clang/include/clang/CIR/ABIArgInfo.h
new file mode 100644
index 0000000000000..0c2cd85915aa7
--- /dev/null
+++ b/clang/include/clang/CIR/ABIArgInfo.h
@@ -0,0 +1,89 @@
+//==-- ABIArgInfo.h - Abstract info regarding ABI-specific arguments -------==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines ABIArgInfo and associated types used by CIR to track information
+// regarding ABI-coerced types for function arguments and return values. This
+// was moved to the common library as it might be used by both CIRGen and
+// passes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_ABIARGINFO_H
+#define LLVM_CLANG_CIR_ABIARGINFO_H
+
+#include "MissingFeatures.h"
+#include "mlir/IR/Types.h"
+
+namespace cir {
+
+class ABIArgInfo {
+public:
+  enum Kind : uint8_t {
+    /// Pass the argument directly using the normal converted CIR type,
+    /// or by coercing to another specified type stored in 'CoerceToType'). If
+    /// an offset is specified (in UIntData), then the argument passed is offset
+    /// by some number of bytes in the memory representation. A dummy argument
+    /// is emitted before the real argument if the specified type stored in
+    /// "PaddingType" is not zero.
+    Direct,
+
+    /// Ignore the argument (treat as void). Useful for void and empty
+    /// structs.
+    Ignore,
+  };
+
+private:
+  mlir::Type typeData;
+  struct DirectAttrInfo {
+    unsigned offset;
+    unsigned align;
+  };
+  union {
+    DirectAttrInfo directAttr;
+  };
+  Kind theKind;
+
+public:
+  ABIArgInfo(Kind k = Direct) : directAttr{0, 0}, theKind(k) {}
+
+  static ABIArgInfo getDirect(mlir::Type ty = nullptr) {
+    ABIArgInfo info(Direct);
+    info.setCoerceToType(ty);
+    return info;
+  }
+
+  static ABIArgInfo getIgnore() { return ABIArgInfo(Ignore); }
+
+  Kind getKind() const { return theKind; }
+  bool isDirect() const { return theKind == Direct; }
+  bool isIgnore() const { return theKind == Ignore; }
+
+  bool canHaveCoerceToType() const {
+    assert(!cir::MissingFeatures::abiArgInfo());
+    return isDirect();
+  }
+
+  unsigned getDirectOffset() const {
+    assert(!cir::MissingFeatures::abiArgInfo());
+    return directAttr.offset;
+  }
+
+  mlir::Type getCoerceToType() const {
+    assert(canHaveCoerceToType() && "invalid kind!");
+    return typeData;
+  }
+
+  void setCoerceToType(mlir::Type ty) {
+    assert(canHaveCoerceToType() && "invalid kind!");
+    typeData = ty;
+  }
+};
+
+} // namespace cir
+
+#endif // LLVM_CLANG_CIR_ABIARGINFO_H
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 68a4505ca7a5a..a24006810c1f5 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -205,13 +205,15 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   // Call operators
   //===--------------------------------------------------------------------===//
 
-  cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee) {
-    auto op = create<cir::CallOp>(loc, callee);
+  cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
+                           mlir::Type returnType = cir::VoidType()) {
+    auto op = create<cir::CallOp>(loc, callee, /*resType=*/returnType);
     return op;
   }
 
   cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee) {
-    return createCallOp(loc, mlir::SymbolRefAttr::get(callee));
+    return createCallOp(loc, mlir::SymbolRefAttr::get(callee),
+                        callee.getFunctionType().getReturnType());
   }
 
   //===--------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 0d3c2065cd58c..5ba4b33dc1a12 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1408,10 +1408,14 @@ def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
     ```
   }];
 
+  let results = (outs Optional<CIR_AnyType>:$result);
   let arguments = commonArgs;
 
-  let builders = [OpBuilder<(ins "mlir::SymbolRefAttr":$callee), [{
+  let builders = [OpBuilder<(ins "mlir::SymbolRefAttr":$callee,
+                                 "mlir::Type":$resType), [{
       $_state.addAttribute("callee", callee);
+      if (resType && !isa<VoidType>(resType))
+        $_state.addTypes(resType);
     }]>];
 }
 
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index d6a28d4324b32..f692dc661e9d5 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -103,6 +103,8 @@ struct MissingFeatures {
 
   // Misc
   static bool cxxABI() { return false; }
+  static bool cirgenABIInfo() { return false; }
+  static bool abiArgInfo() { return false; }
   static bool tryEmitAsConstant() { return false; }
   static bool constructABIArgDirectExtend() { return false; }
   static bool opGlobalViewAttr() { return false; }
@@ -121,6 +123,8 @@ struct MissingFeatures {
   static bool fpConstraints() { return false; }
   static bool sanitizers() { return false; }
   static bool addHeapAllocSiteMetadata() { return false; }
+  static bool targetCIRGenInfoArch() { return false; }
+  static bool targetCIRGenInfoOS() { return false; }
   static bool targetCodeGenInfoGetNullPointer() { return false; }
   static bool loopInfoStack() { return false; }
   static bool requiresCleanups() { return false; }
diff --git a/clang/lib/CIR/CodeGen/ABIInfo.h b/clang/lib/CIR/CodeGen/ABIInfo.h
new file mode 100644
index 0000000000000..157e80f67a67c
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/ABIInfo.h
@@ -0,0 +1,32 @@
+//===----- ABIInfo.h - ABI information access & encapsulation ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CIR_ABIINFO_H
+#define LLVM_CLANG_LIB_CIR_ABIINFO_H
+
+namespace clang::CIRGen {
+
+class CIRGenFunctionInfo;
+class CIRGenTypes;
+
+class ABIInfo {
+  ABIInfo() = delete;
+
+public:
+  CIRGenTypes &cgt;
+
+  ABIInfo(CIRGenTypes &cgt) : cgt(cgt) {}
+
+  virtual ~ABIInfo();
+
+  virtual void computeInfo(CIRGenFunctionInfo &funcInfo) const = 0;
+};
+
+} // namespace clang::CIRGen
+
+#endif // LLVM_CLANG_LIB_CIR_ABIINFO_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 1a936458782ea..811750ebfc8b4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -18,9 +18,12 @@
 using namespace clang;
 using namespace clang::CIRGen;
 
-CIRGenFunctionInfo *CIRGenFunctionInfo::create() {
-  // For now we just create an empty CIRGenFunctionInfo.
-  CIRGenFunctionInfo *fi = new CIRGenFunctionInfo();
+CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) {
+  void *buffer = operator new(totalSizeToAlloc<ArgInfo>(1));
+
+  CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
+  fi->getArgsBuffer()[0].type = resultType;
+
   return fi;
 }
 
@@ -29,13 +32,29 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
   return *this;
 }
 
-static const CIRGenFunctionInfo &arrangeFreeFunctionLikeCall(CIRGenTypes &cgt) {
+static const CIRGenFunctionInfo &
+arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
+                            const FunctionType *fnType) {
+  if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
+    if (proto->isVariadic())
+      cgm.errorNYI("call to variadic function");
+    if (proto->hasExtParameterInfos())
+      cgm.errorNYI("call to functions with extra parameter info");
+  } else if (isa<FunctionNoProtoType>(fnType)) {
+    cgm.errorNYI("call to function without a prototype");
+  }
+
   assert(!cir::MissingFeatures::opCallArgs());
-  return cgt.arrangeCIRFunctionInfo();
+
+  CanQualType retType = fnType->getReturnType()
+                            ->getCanonicalTypeUnqualified()
+                            .getUnqualifiedType();
+  return cgt.arrangeCIRFunctionInfo(retType);
 }
 
-const CIRGenFunctionInfo &CIRGenTypes::arrangeFreeFunctionCall() {
-  return arrangeFreeFunctionLikeCall(*this);
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionCall(const FunctionType *fnType) {
+  return arrangeFreeFunctionLikeCall(*this, cgm, fnType);
 }
 
 static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf,
@@ -54,8 +73,12 @@ static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf,
 
 RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
                                 const CIRGenCallee &callee,
+                                ReturnValueSlot returnValue,
                                 cir::CIRCallOpInterface *callOp,
                                 mlir::Location loc) {
+  QualType retTy = funcInfo.getReturnType();
+  const cir::ABIArgInfo &retInfo = funcInfo.getReturnInfo();
+
   assert(!cir::MissingFeatures::opCallArgs());
   assert(!cir::MissingFeatures::emitLifetimeMarkers());
 
@@ -87,9 +110,48 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
   assert(!cir::MissingFeatures::opCallMustTail());
   assert(!cir::MissingFeatures::opCallReturn());
 
-  // For now we just return nothing because we don't have support for return
-  // values yet.
-  RValue ret = RValue::get(nullptr);
+  RValue ret;
+  switch (retInfo.getKind()) {
+  case cir::ABIArgInfo::Direct: {
+    mlir::Type retCIRTy = convertType(retTy);
+    if (retInfo.getCoerceToType() == retCIRTy &&
+        retInfo.getDirectOffset() == 0) {
+      switch (getEvaluationKind(retTy)) {
+      case cir::TEK_Scalar: {
+        mlir::ResultRange results = theCall->getOpResults();
+        assert(results.size() == 1 && "unexpected number of returns");
+
+        // If the argument doesn't match, perform a bitcast to coerce it. This
+        // can happen due to trivial type mismatches.
+        if (results[0].getType() != retCIRTy) {
+          cgm.errorNYI(loc, "bitcast on function return value");
+        }
+
+        mlir::Region *region = builder.getBlock()->getParent();
+        if (region != theCall->getParentRegion()) {
+          cgm.errorNYI(loc, "function calls with cleanup");
+        }
+
+        return RValue::get(results[0]);
+      }
+      default:
+        cgm.errorNYI(loc,
+                     "unsupported evaluation kind of function call result");
+      }
+    } else {
+      cgm.errorNYI(loc, "unsupported function call form");
+    }
+
+    break;
+  }
+  case cir::ABIArgInfo::Ignore:
+    // If we are ignoring an argument that had a result, make sure to construct
+    // the appropriate return value for our caller.
+    ret = getUndefRValue(retTy);
+    break;
+  default:
+    cgm.errorNYI(loc, "unsupported return value information");
+  }
 
   return ret;
 }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.h b/clang/lib/CIR/CodeGen/CIRGenCall.h
index 76fefdca9e45e..4427fda863d7e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.h
@@ -81,6 +81,10 @@ struct CallArg {};
 
 class CallArgList : public llvm::SmallVector<CallArg, 8> {};
 
+/// Contains the address where the return value of a function can be stored, and
+/// whether the address is volatile or not.
+class ReturnValueSlot {};
+
 } // namespace clang::CIRGen
 
 #endif // CLANG_LIB_CODEGEN_CIRGENCALL_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index f0732a8ea60af..550231132ab53 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -662,23 +662,36 @@ static CIRGenCallee emitDirectCallee(CIRGenModule &cgm, GlobalDecl gd) {
   return CIRGenCallee::forDirect(callee, gd);
 }
 
+RValue CIRGenFunction::getUndefRValue(QualType ty) {
+  if (ty->isVoidType())
+    return RValue::get(nullptr);
+
+  cgm.errorNYI("unsupported type for undef rvalue");
+  return RValue::get(nullptr);
+}
+
 RValue CIRGenFunction::emitCall(clang::QualType calleeTy,
                                 const CIRGenCallee &callee,
-                                const clang::CallExpr *e) {
+                                const clang::CallExpr *e,
+                                ReturnValueSlot returnValue) {
   // Get the actual function type. The callee type will always be a pointer to
   // function type or a block pointer type.
   assert(calleeTy->isFunctionPointerType() &&
          "Callee must have function pointer type!");
 
   calleeTy = getContext().getCanonicalType(calleeTy);
+  auto pointeeTy = cast<PointerType>(calleeTy)->getPointeeType();
 
   if (getLangOpts().CPlusPlus)
     assert(!cir::MissingFeatures::sanitizers());
 
+  const auto *fnType = cast<FunctionType>(pointeeTy);
+
   assert(!cir::MissingFeatures::sanitizers());
   assert(!cir::MissingFeatures::opCallArgs());
 
-  const CIRGenFunctionInfo &funcInfo = cgm.getTypes().arrangeFreeFunctionCall();
+  const CIRGenFunctionInfo &funcInfo =
+      cgm.getTypes().arrangeFreeFunctionCall(fnType);
 
   assert(!cir::MissingFeatures::opCallNoPrototypeFunc());
   assert(!cir::MissingFeatures::opCallChainCall());
@@ -687,7 +700,7 @@ RValue CIRGenFunction::emitCall(clang::QualType calleeTy,
 
   cir::CIRCallOpInterface callOp;
   RValue callResult =
-      emitCall(funcInfo, callee, &callOp, getLoc(e->getExprLoc()));
+      emitCall(funcInfo, callee, returnValue, &callOp, getLoc(e->getExprLoc()));
 
   assert(!cir::MissingFeatures::generateDebugInfo());
 
@@ -713,7 +726,8 @@ CIRGenCallee CIRGenFunction::emitCallee(const clang::Expr *e) {
   return {};
 }
 
-RValue CIRGenFunction::emitCallExpr(const clang::CallExpr *e) {
+RValue CIRGenFunction::emitCallExpr(const clang::CallExpr *e,
+                                    ReturnValueSlot returnValue) {
   assert(!cir::MissingFeatures::objCBlocks());
 
   if (isa<CXXMemberCallExpr>(e)) {
@@ -745,7 +759,7 @@ RValue CIRGenFunction::emitCallExpr(const clang::CallExpr *e) {
   }
   assert(!cir::MissingFeatures::opCallPseudoDtor());
 
-  return emitCall(e->getCallee()->getType(), callee, e);
+  return emitCall(e->getCallee()->getType(), callee, e, returnValue);
 }
 
 /// Emit code to compute the specified expression, ignoring the result.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 38104f8533c7d..3dae26dc86f85 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1519,11 +1519,8 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
 }
 
 mlir::Value ScalarExprEmitter::VisitCallExpr(const CallExpr *e) {
-  if (e->getCallReturnType(cgf.getContext())->isReferenceType()) {
-    cgf.getCIRGenModule().errorNYI(
-        e->getSourceRange(), "call to function with non-void return type");
-    return {};
-  }
+  if (e->getCallReturnType(cgf.getContext())->isReferenceType())
+    return emitLoadOfLValue(e);
 
   auto v = cgf.emitCallExpr(e).getScalarVal();
   assert(!cir::MissingFeatures::emitLValueAlignmentAssumption());
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index a96d277d0bc0b..01abd84ce1c85 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -269,6 +269,12 @@ class CIRGenFunction : public CIRGenTypeCache {
     return LValue::makeAddr(addr, ty, baseInfo);
   }
 
+  /// Get an appropriate 'undef' rvalue for the given type.
+  /// TODO: What's the equivalent for MLIR? Currently we're only using this for
+  /// void types so it just returns RValue::get(nullptr) but it'll need
+  /// addressed later.
+  RValue getUndefRValue(clang::QualType ty);
+
   cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
                            cir::FuncType funcType);
 
@@ -451,11 +457,12 @@ class CIRGenFunction : public CIRGenTypeCache {
   mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s);
 
   RValue emitCall(const CIRGenFunctionInfo &funcInfo,
-                  const CIRGenCallee &callee, cir::CIRCallOpInterface *callOp,
-                  mlir::Location loc);
+                  const CIRGenCallee &callee, ReturnValueSlot returnValue,
+                  cir::CIRCallOpInterface *callOp, mlir::Location loc);
   RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
-                  const clang::CallExpr *e);
-  RValue emitCallExpr(const clang::CallExpr *e);
+                  const clang::CallExpr *e, ReturnValueSlot returnValue);
+  RValue emitCallExpr(const clang::CallExpr *e,
+                      ReturnValueSlot returnValue = ReturnValueSlot());
   CIRGenCallee emitCallee(const clang::Expr *e);
 
   mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
index da73e7a7a9059..c4a2b238c96ae 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
@@ -15,18 +15,49 @@
 #ifndef LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
 #define LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
 
+#include "clang/AST/CanonicalType.h"
+#include "clang/CIR/ABIArgInfo.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/TrailingObjects.h"
 
 namespace clang::CIRGen {
 
-class CIRGenFunctionInfo final : public llvm::FoldingSetNode {
+struct CIRGenFunctionInfoArgInfo {
+  CanQualType type;
+  cir::ABIArgInfo info;
+};
+
+class CIRGenFunctionInfo final
+    : public llvm::FoldingSetNode,
+      private llvm::TrailingObjects<CIRGenFunctionInfo,
+                                    CIRGenFunctionInfoArgInfo> {
+  using ArgInfo = CIRGenFunctionInfoArgInfo;
+
+  ArgInfo *getArgsBuffer() { return getTrailingObjects<ArgInfo>(); }
+  const ArgInfo *getArgsBuffer() const { return getTrailingObjects<ArgInfo>(); }
+
 public:
-  static CIRGenFunctionInfo *create();
+  static CIRGenFunctionInfo *create(CanQualType resultType);
+
+  void operator delete(void *p) { ::operator delete(p); }
+
+  // Friending class TrailingObjects is apparantly not good enough for MSVC, so
+  // these have to be public.
+  friend class TrailingObjects;
 
   // This function has to be CamelCase because llvm::FoldingSet requires so.
   // NOLINTNEXTLINE(readability-identifier-naming)
-  static void Profile(llvm::FoldingSetNodeID &id) {
-    // We don't have anything to profile yet.
+  static void Profile(llvm::FoldingSetNodeID &id, CanQualType resultType) {
+    resultType.Profile(id);
+  }
+
+  void Profile(llvm::FoldingSetNodeID &id) { getReturnType().Profile(id); }
+
+  CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
+
+  cir::ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
+  const cir::ABIArgInfo &getReturnInfo() const {
+    return getArgsBuffer()[0].info;
   }
 };
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index fd11523ebba61..cbfaa3d89836b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -129,6 +129,36 @@ CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,
   return alignment;
 }
 
+const TargetCIRGenInfo &CIRGenModule::getTargetCIRGenInfo() {
+  if (theTargetCIRGenInfo)
+    return *theTargetCIRGenInfo;
+
+  const llvm::Triple &triple = getTarget().getTriple();
+  switch (triple.getArch()) {
+  default:
+    assert(!cir::MissingFeatures::targetCIRGenInfoArch());
+    errorNYI("unsupported target arch");
+
+    // Currently we just fall through to x86_64.
+    [[fallthrough]];
+
+  case llvm::Triple::x86_64: {
+    switch (triple.getOS()) {
+    default:
+      assert(!cir::MissingFeatures::targetCIRGenInfoOS());
+      errorNYI("unsupported target OS");
+
+      // Currently we just fall through to x86_64.
+      [[fallthrough]];
+
+    case llvm::Triple::...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/135552


More information about the cfe-commits mailing list