llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Sirui Mu (Lancern)

<details>
<summary>Changes</summary>

This PR upstreams support for scalar arguments in `cir.call` operation.

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

---

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


16 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+5-4) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+44-2) 
- (modified) clang/include/clang/CIR/Interfaces/CIROpInterfaces.td (+16-1) 
- (modified) clang/include/clang/CIR/MissingFeatures.h (+11-1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+265-12) 
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.h (+30-2) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+20-4) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+47-1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h (+25-2) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+10-5) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+5-2) 
- (modified) clang/lib/CIR/CodeGen/TargetInfo.cpp (+7-1) 
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+49-9) 
- (modified) clang/test/CIR/CodeGen/call.cpp (+12) 
- (modified) clang/test/CIR/IR/call.cir (+15) 
- (modified) clang/test/CIR/IR/invalid-call.cir (+27) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 539268c6270f4..0a6e47ea43a8c 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -214,14 +214,15 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   
//===--------------------------------------------------------------------===//
 
   cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
-                           mlir::Type returnType) {
-    auto op = create<cir::CallOp>(loc, callee, returnType);
+                           mlir::Type returnType, mlir::ValueRange operands) {
+    auto op = create<cir::CallOp>(loc, callee, returnType, operands);
     return op;
   }
 
-  cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee) {
+  cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee,
+                           mlir::ValueRange operands) {
     return createCallOp(loc, mlir::SymbolRefAttr::get(callee),
-                        callee.getFunctionType().getReturnType());
+                        callee.getFunctionType().getReturnType(), operands);
   }
 
   
//===--------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index bb19de31b4fa5..aa7a9b2de664f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1496,6 +1496,10 @@ def FuncOp : CIR_Op<"func", [
        return getFunctionType().getReturnTypes();
     }
 
+    // TODO(cir): this should be an operand attribute, but for now we just 
hard-
+    // wire this as a function. Will later add a $no_proto argument to this op.
+    bool getNoProto() { return false; }
+
     
//===------------------------------------------------------------------===//
     // SymbolOpInterface Methods
     
//===------------------------------------------------------------------===//
@@ -1516,6 +1520,41 @@ class CIR_CallOpBase<string mnemonic, list<Trait> 
extra_traits = []>
          !listconcat(extra_traits,
                      [DeclareOpInterfaceMethods<CIRCallOpInterface>,
                       DeclareOpInterfaceMethods<SymbolUserOpInterface>])> {
+  let extraClassDeclaration = [{
+    /// Get the argument operands to the called function.
+    mlir::OperandRange getArgOperands() {
+      return {arg_operand_begin(), arg_operand_end()};
+    }
+
+    mlir::MutableOperandRange getArgOperandsMutable() {
+      llvm_unreachable("NYI");
+    }
+
+    /// Return the callee of this operation
+    mlir::CallInterfaceCallable getCallableForCallee() {
+      return (*this)->getAttrOfType<mlir::SymbolRefAttr>("callee");
+    }
+
+    /// Set the callee for this operation.
+    void setCalleeFromCallable(::mlir::CallInterfaceCallable callee) {
+      (*this)->setAttr(getCalleeAttrName(),
+                       mlir::cast<mlir::SymbolRefAttr>(callee));
+    }
+
+    ::mlir::ArrayAttr getArgAttrsAttr() { return {}; }
+    ::mlir::ArrayAttr getResAttrsAttr() { return {}; }
+
+    void setResAttrsAttr(::mlir::ArrayAttr attrs) {}
+    void setArgAttrsAttr(::mlir::ArrayAttr attrs) {}
+
+    ::mlir::Attribute removeArgAttrsAttr() { return {}; }
+    ::mlir::Attribute removeResAttrsAttr() { return {}; }
+
+    void setArg(unsigned index, mlir::Value value) {
+      setOperand(index, value);
+    }
+  }];
+
   let hasCustomAssemblyFormat = 1;
   let skipDefaultBuilders = 1;
   let hasVerifier = 0;
@@ -1525,7 +1564,8 @@ class CIR_CallOpBase<string mnemonic, list<Trait> 
extra_traits = []>
   // the upstreaming process moves on. The verifiers is also missing for now,
   // will add in the future.
 
-  dag commonArgs = (ins FlatSymbolRefAttr:$callee);
+  dag commonArgs = (ins FlatSymbolRefAttr:$callee,
+                        Variadic<CIR_AnyType>:$args);
 }
 
 def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
@@ -1546,7 +1586,9 @@ def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
   let arguments = commonArgs;
 
   let builders = [OpBuilder<(ins "mlir::SymbolRefAttr":$callee,
-                                 "mlir::Type":$resType), [{
+                                 "mlir::Type":$resType,
+                                 "mlir::ValueRange":$operands), [{
+      $_state.addOperands(operands);
       $_state.addAttribute("callee", callee);
       if (resType && !isa<VoidType>(resType))
         $_state.addTypes(resType);
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td 
b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
index c6c6356118ac6..8227ce4bea5a3 100644
--- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
@@ -21,9 +21,24 @@ let cppNamespace = "::cir" in {
   // The CIRCallOpInterface must be used instead of CallOpInterface when 
looking
   // at arguments and other bits of CallOp. This creates a level of abstraction
   // that's useful for handling indirect calls and other details.
-  def CIRCallOpInterface : OpInterface<"CIRCallOpInterface", []> {
+  def CIRCallOpInterface : OpInterface<"CIRCallOpInterface", 
[CallOpInterface]> {
     // Currently we don't have any methods defined in CIRCallOpInterface. We'll
     // add more methods as the upstreaming proceeds.
+    let methods = [
+      InterfaceMethod<"", "mlir::Operation::operand_iterator",
+                      "arg_operand_begin", (ins)>,
+      InterfaceMethod<"", "mlir::Operation::operand_iterator",
+                      "arg_operand_end", (ins)>,
+      InterfaceMethod<
+          "Return the operand at index 'i', accounts for indirect call or "
+          "exception info",
+          "mlir::Value", "getArgOperand",
+          (ins "unsigned":$i)>,
+      InterfaceMethod<
+          "Return the number of operands, accounts for indirect call or "
+          "exception info",
+          "unsigned", "getNumArgOperands", (ins)>,
+    ];
   }
 
   def CIRGlobalValueInterface
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 6bfc1199aea55..370d82d26ebe7 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -76,7 +76,13 @@ struct MissingFeatures {
   // CallOp handling
   static bool opCallBuiltinFunc() { return false; }
   static bool opCallPseudoDtor() { return false; }
-  static bool opCallArgs() { return false; }
+  static bool opCallAggregateArgs() { return false; }
+  static bool opCallPaddingArgs() { return false; }
+  static bool opCallABIExtendArg() { return false; }
+  static bool opCallABIIndirectArg() { return false; }
+  static bool opCallWidenArg() { return false; }
+  static bool opCallBitcastArg() { return false; }
+  static bool opCallImplicitObjectSizeArgs() { return false; }
   static bool opCallReturn() { return false; }
   static bool opCallArgEvaluationOrder() { return false; }
   static bool opCallCallConv() { return false; }
@@ -90,6 +96,9 @@ struct MissingFeatures {
   static bool opCallAttrs() { return false; }
   static bool opCallSurroundingTry() { return false; }
   static bool opCallASTAttr() { return false; }
+  static bool opCallVariadic() { return false; }
+  static bool opCallObjCMethod() { return false; }
+  static bool opCallExtParameterInfo() { return false; }
 
   // ScopeOp handling
   static bool opScopeCleanupRegion() { return false; }
@@ -157,6 +166,7 @@ struct MissingFeatures {
   static bool emitCheckedInBoundsGEP() { return false; }
   static bool preservedAccessIndexRegion() { return false; }
   static bool bitfields() { return false; }
+  static bool msabi() { return false; }
   static bool typeChecks() { return false; }
   static bool lambdaFieldToName() { return false; }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 69266f79a88a5..bea91f8ec0ec7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -18,15 +18,110 @@
 using namespace clang;
 using namespace clang::CIRGen;
 
-CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) {
-  void *buffer = operator new(totalSizeToAlloc<ArgInfo>(1));
+CIRGenFunctionInfo *
+CIRGenFunctionInfo::create(CanQualType resultType,
+                           llvm::ArrayRef<CanQualType> argTypes) {
+  void *buffer = operator new(totalSizeToAlloc<ArgInfo>(argTypes.size() + 1));
 
   CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
+  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;
 }
 
+namespace {
+
+/// Encapsulates information about the way function arguments from
+/// CIRGenFunctionInfo should be passed to actual CIR function.
+class ClangToCIRArgMapping {
+  static constexpr unsigned invalidIndex = ~0U;
+  unsigned totalNumCIRArgs;
+
+  /// Arguments of CIR function corresponding to single Clang argument.
+  struct CIRArgs {
+    // Argument is expanded to CIR arguments at positions
+    // [FirstArgIndex, FirstArgIndex + NumberOfArgs).
+    unsigned firstArgIndex = 0;
+    unsigned numberOfArgs = 0;
+
+    CIRArgs() : firstArgIndex(invalidIndex), numberOfArgs(0) {}
+  };
+
+  SmallVector<CIRArgs, 8> argInfo;
+
+public:
+  ClangToCIRArgMapping(const ASTContext &astContext,
+                       const CIRGenFunctionInfo &funcInfo)
+      : totalNumCIRArgs(0), argInfo(funcInfo.arg_size()) {
+    construct(astContext, funcInfo);
+  }
+
+  unsigned totalCIRArgs() const { return totalNumCIRArgs; }
+
+  /// Returns index of first CIR argument corresponding to argNo, and their
+  /// quantity.
+  std::pair<unsigned, unsigned> getCIRArgs(unsigned argNo) const {
+    assert(argNo < argInfo.size());
+    return std::make_pair(argInfo[argNo].firstArgIndex,
+                          argInfo[argNo].numberOfArgs);
+  }
+
+private:
+  void construct(const ASTContext &astContext,
+                 const CIRGenFunctionInfo &funcInfo);
+};
+
+void ClangToCIRArgMapping::construct(const ASTContext &astContext,
+                                     const CIRGenFunctionInfo &funcInfo) {
+  unsigned cirArgNo = 0;
+
+  assert(!cir::MissingFeatures::opCallABIIndirectArg());
+
+  unsigned argNo = 0;
+  unsigned numArgs = funcInfo.arg_size();
+  for (const auto *i = funcInfo.arg_begin(); argNo < numArgs; ++i, ++argNo) {
+    assert(i != funcInfo.arg_end());
+    const cir::ABIArgInfo &ai = i->info;
+    // Collect data about CIR arguments corresponding to Clang argument ArgNo.
+    auto &cirArgs = argInfo[argNo];
+
+    assert(!cir::MissingFeatures::opCallPaddingArgs());
+
+    switch (ai.getKind()) {
+    default:
+      assert(!cir::MissingFeatures::abiArgInfo());
+      // For now we just fall through. More argument kinds will be added later
+      // as the upstreaming proceeds.
+      [[fallthrough]];
+    case cir::ABIArgInfo::Direct:
+      // Postpone splitting structs into elements since this makes it way
+      // more complicated for analysis to obtain information on the original
+      // arguments.
+      //
+      // TODO(cir): a LLVM lowering prepare pass should break this down into
+      // the appropriated pieces.
+      assert(!cir::MissingFeatures::opCallABIExtendArg());
+      cirArgs.numberOfArgs = 1;
+      break;
+    }
+
+    if (cirArgs.numberOfArgs > 0) {
+      cirArgs.firstArgIndex = cirArgNo;
+      cirArgNo += cirArgs.numberOfArgs;
+    }
+  }
+
+  assert(argNo == argInfo.size());
+  assert(!cir::MissingFeatures::opCallInAlloca());
+
+  totalNumCIRArgs = cirArgNo;
+}
+
+} // namespace
+
 CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
   assert(!cir::MissingFeatures::opCallVirtual());
   return *this;
@@ -34,6 +129,7 @@ CIRGenCallee 
CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
 
 static const CIRGenFunctionInfo &
 arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
+                            const CallArgList &args,
                             const FunctionType *fnType) {
   if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
     if (proto->isVariadic())
@@ -44,22 +140,26 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule 
&cgm,
                  cast<FunctionNoProtoType>(fnType)))
     cgm.errorNYI("call to function without a prototype");
 
-  assert(!cir::MissingFeatures::opCallArgs());
+  SmallVector<CanQualType, 16> argTypes;
+  for (const CallArg &arg : args)
+    argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
 
   CanQualType retType = fnType->getReturnType()
                             ->getCanonicalTypeUnqualified()
                             .getUnqualifiedType();
-  return cgt.arrangeCIRFunctionInfo(retType);
+  return cgt.arrangeCIRFunctionInfo(retType, argTypes);
 }
 
 const CIRGenFunctionInfo &
-CIRGenTypes::arrangeFreeFunctionCall(const FunctionType *fnType) {
-  return arrangeFreeFunctionLikeCall(*this, cgm, fnType);
+CIRGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
+                                     const FunctionType *fnType) {
+  return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
 }
 
-static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf,
-                                              mlir::Location callLoc,
-                                              cir::FuncOp directFuncOp) {
+static cir::CIRCallOpInterface
+emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
+               cir::FuncOp directFuncOp,
+               const SmallVectorImpl<mlir::Value> &cirCallArgs) {
   CIRGenBuilderTy &builder = cgf.getBuilder();
 
   assert(!cir::MissingFeatures::opCallSurroundingTry());
@@ -68,20 +168,70 @@ static cir::CIRCallOpInterface 
emitCallLikeOp(CIRGenFunction &cgf,
   assert(builder.getInsertionBlock() && "expected valid basic block");
   assert(!cir::MissingFeatures::opCallIndirect());
 
-  return builder.createCallOp(callLoc, directFuncOp);
+  return builder.createCallOp(callLoc, directFuncOp, cirCallArgs);
 }
 
 RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
                                 const CIRGenCallee &callee,
                                 ReturnValueSlot returnValue,
+                                const CallArgList &args,
                                 cir::CIRCallOpInterface *callOp,
                                 mlir::Location loc) {
   QualType retTy = funcInfo.getReturnType();
   const cir::ABIArgInfo &retInfo = funcInfo.getReturnInfo();
 
-  assert(!cir::MissingFeatures::opCallArgs());
+  ClangToCIRArgMapping cirFuncArgs(cgm.getASTContext(), funcInfo);
+  SmallVector<mlir::Value, 16> cirCallArgs(cirFuncArgs.totalCIRArgs());
+
   assert(!cir::MissingFeatures::emitLifetimeMarkers());
 
+  // Translate all of the arguments as necessary to match the CIR lowering.
+  assert(funcInfo.arg_size() == args.size() &&
+         "Mismatch between function signature & arguments.");
+  unsigned argNo = 0;
+  const auto *infoIter = funcInfo.arg_begin();
+  for (auto i = args.begin(), e = args.end(); i != e;
+       ++i, ++infoIter, ++argNo) {
+    const cir::ABIArgInfo &argInfo = infoIter->info;
+
+    // Insert a padding argument to ensure proper alignment.
+    assert(!cir::MissingFeatures::opCallPaddingArgs());
+
+    unsigned firstCIRArg;
+    unsigned numCIRArgs;
+    std::tie(firstCIRArg, numCIRArgs) = cirFuncArgs.getCIRArgs(argNo);
+
+    switch (argInfo.getKind()) {
+    case cir::ABIArgInfo::Direct: {
+      if (!mlir::isa<cir::RecordType>(argInfo.getCoerceToType()) &&
+          argInfo.getCoerceToType() == convertType(infoIter->type) &&
+          argInfo.getDirectOffset() == 0) {
+        assert(numCIRArgs == 1);
+        assert(!cir::MissingFeatures::opCallAggregateArgs());
+        mlir::Value v = i->getKnownRValue().getScalarVal();
+
+        assert(!cir::MissingFeatures::opCallExtParameterInfo());
+
+        // We might have to widen integers, but we should never truncate.
+        assert(!cir::MissingFeatures::opCallWidenArg());
+
+        // If the argument doesn't match, perform a bitcast to coerce it. This
+        // can happen due to trivial type mismatches.
+        assert(!cir::MissingFeatures::opCallBitcastArg());
+
+        cirCallArgs[firstCIRArg] = v;
+        break;
+      }
+
+      assert(!cir::MissingFeatures::opCallAggregateArgs());
+      cgm.errorNYI("aggregate function call argument");
+      break;
+    }
+    default:
+      cgm.errorNYI("unsupported argument kind");
+    }
+  }
+
   const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
   mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
 
@@ -102,7 +252,8 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo 
&funcInfo,
   assert(!cir::MissingFeatures::opCallIndirect());
   assert(!cir::MissingFeatures::opCallAttrs());
 
-  cir::CIRCallOpInterface theCall = emitCallLikeOp(*this, loc, directFuncOp);
+  cir::CIRCallOpInterface theCall =
+      emitCallLikeOp(*this, loc, directFuncOp, cirCallArgs);
 
   if (callOp)
     *callOp = theCall;
@@ -152,3 +303,105 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo 
&funcInfo,
 
   return ret;
 }
+
+void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,
+                                 clang::QualType argType) {
+  assert(argType->isReferenceType() == e->isGLValue() &&
+         "reference binding to unmaterialized r-value!");
+
+  if (e->isGLValue()) {
+    assert(e->getObjectKind() == OK_Ordinary);
+    args.add(emitReferenceBindingToExpr(e), argType);
+  }
+
+  bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
+
+  if (hasAggregateEvalKind) {
+    assert(!cir::MissingFeatures::opCallAggregateArgs());
+    cgm.errorNYI(e->getSourceRange(), "aggregate function call argument");
+  }
+
+  args.add(emitAnyExprToTemp(e), argType);
+}
+
+/// Similar to emitAnyExpr(), however, the result will always be accessible
+/// even if no aggregate location is provided.
+RValue CIRGenFunction::emitAnyExprToTemp(const Expr *e) {
+  assert(!cir::MissingFeatures::opCallAggregateArgs());
+
+  if (hasAggregateEvaluationKind(e->getType()))
+    cgm.errorNYI(e->getSourceRange(), "emit aggregate value to temp");
+
+  return emitAnyExpr(e);
+}
+
+void CIRGenFunction::emitCallArgs(
+    CallArgList &args, PrototypeWrapper prototype,
+    llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
+    AbstractCallee callee, unsigned paramsToSkip) {
+  llvm::SmallVector<QualType, 16> argTypes;
+
+  assert(!cir::MissingFeatures::opCallCallConv());
+
+  // First, if a prototype was provided, use those argument types.
+  assert(!cir::MissingFeatures::opCallVariadic());
+  if (prototype.p) {
+    assert(!cir::MissingFeatures::opCallObjCMethod());
+
+    const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
+    argTypes.assign(fpt->param_type_begin() + paramsToSkip,
+                    fpt->param_type_end());
+  }
+
+  // If we still have any arguments, emit them using the type of the argument.
+  for (auto *a : llvm::drop_begin(argRange, argTypes.size()))
+    argTypes.push_back(a->getType());
+  assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
+
+  // We must evaluate arguments from right to left in the MS C++ ABI, because
+  // arguments are destroyed left to right in the callee. As a special case,
+  // there are certain language constructs taht require left-to-right
+  // evaluation, and in those cases we consider the evaluation order 
requirement
+  // to trump the "destruction order is reverse construction order" guarantee.
+  auto leftToRight = true;
+  assert(!cir::MissingFeatures::msabi());
+
+  auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
+                                         RValue emittedArg) {
+    if (callee.hasFunctionDecl() || i >= callee.getNumParams())
+      return;
+    auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
+    if (!ps)
+      return;
+
+    assert(!cir::MissingFeatures::opCallImplicitObjectSizeArgs());
+    cgm.errorNYI("emit implicit object size for call arg");
+  };
+
+  // Evaluate each argument in the appropriate order.
+  size_t callArgsStart = args.size();
+  for (size_t i = 0; i != argTypes.size(); ++i) {
+...
[truncated]

``````````

</details>


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

Reply via email to