brintos

brintos / llvm-project-archived public Read only

0
0
Text · 33.9 KiB · 17f0c6d Raw
880 lines · cpp
1//===--- CIRGenCall.cpp - Encapsulate calling convention details ----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// These classes wrap the information about a call or function definition used10// to handle ABI compliancy.11//12//===----------------------------------------------------------------------===//13 14#include "CIRGenCall.h"15#include "CIRGenCXXABI.h"16#include "CIRGenFunction.h"17#include "CIRGenFunctionInfo.h"18#include "clang/CIR/MissingFeatures.h"19 20using namespace clang;21using namespace clang::CIRGen;22 23CIRGenFunctionInfo *24CIRGenFunctionInfo::create(CanQualType resultType,25                           llvm::ArrayRef<CanQualType> argTypes,26                           RequiredArgs required) {27  // The first slot allocated for arg type slot is for the return value.28  void *buffer = operator new(29      totalSizeToAlloc<CanQualType>(argTypes.size() + 1));30 31  assert(!cir::MissingFeatures::opCallCIRGenFuncInfoParamInfo());32 33  CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();34 35  fi->required = required;36  fi->numArgs = argTypes.size();37 38  fi->getArgTypes()[0] = resultType;39  std::copy(argTypes.begin(), argTypes.end(), fi->argTypesBegin());40  assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());41 42  return fi;43}44 45cir::FuncType CIRGenTypes::getFunctionType(GlobalDecl gd) {46  const CIRGenFunctionInfo &fi = arrangeGlobalDeclaration(gd);47  return getFunctionType(fi);48}49 50cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &info) {51  mlir::Type resultType = convertType(info.getReturnType());52  SmallVector<mlir::Type, 8> argTypes;53  argTypes.reserve(info.getNumRequiredArgs());54 55  for (const CanQualType &argType : info.requiredArguments())56    argTypes.push_back(convertType(argType));57 58  return cir::FuncType::get(argTypes,59                            (resultType ? resultType : builder.getVoidTy()),60                            info.isVariadic());61}62 63cir::FuncType CIRGenTypes::getFunctionTypeForVTable(GlobalDecl gd) {64  const CXXMethodDecl *md = cast<CXXMethodDecl>(gd.getDecl());65  const FunctionProtoType *fpt = md->getType()->getAs<FunctionProtoType>();66 67  if (!isFuncTypeConvertible(fpt))68    cgm.errorNYI("getFunctionTypeForVTable: non-convertible function type");69 70  return getFunctionType(gd);71}72 73CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {74  if (isVirtual()) {75    const CallExpr *ce = getVirtualCallExpr();76    return cgf.cgm.getCXXABI().getVirtualFunctionPointer(77        cgf, getVirtualMethodDecl(), getThisAddress(), getVirtualFunctionType(),78        ce ? ce->getBeginLoc() : SourceLocation());79  }80  return *this;81}82 83void CIRGenFunction::emitAggregateStore(mlir::Value value, Address dest) {84  // In classic codegen:85  // Function to store a first-class aggregate into memory. We prefer to86  // store the elements rather than the aggregate to be more friendly to87  // fast-isel.88  // In CIR codegen:89  // Emit the most simple cir.store possible (e.g. a store for a whole90  // record), which can later be broken down in other CIR levels (or prior91  // to dialect codegen).92 93  // Stored result for the callers of this function expected to be in the same94  // scope as the value, don't make assumptions about current insertion point.95  mlir::OpBuilder::InsertionGuard guard(builder);96  builder.setInsertionPointAfter(value.getDefiningOp());97  builder.createStore(*currSrcLoc, value, dest);98}99 100static void addAttributesFromFunctionProtoType(CIRGenBuilderTy &builder,101                                               mlir::NamedAttrList &attrs,102                                               const FunctionProtoType *fpt) {103  if (!fpt)104    return;105 106  if (!isUnresolvedExceptionSpec(fpt->getExceptionSpecType()) &&107      fpt->isNothrow())108    attrs.set(cir::CIRDialect::getNoThrowAttrName(),109              mlir::UnitAttr::get(builder.getContext()));110}111 112/// Construct the CIR attribute list of a function or call.113void CIRGenModule::constructAttributeList(CIRGenCalleeInfo calleeInfo,114                                          mlir::NamedAttrList &attrs) {115  assert(!cir::MissingFeatures::opCallCallConv());116  auto sideEffect = cir::SideEffect::All;117 118  addAttributesFromFunctionProtoType(getBuilder(), attrs,119                                     calleeInfo.getCalleeFunctionProtoType());120 121  const Decl *targetDecl = calleeInfo.getCalleeDecl().getDecl();122 123  if (targetDecl) {124    if (targetDecl->hasAttr<NoThrowAttr>())125      attrs.set(cir::CIRDialect::getNoThrowAttrName(),126                mlir::UnitAttr::get(&getMLIRContext()));127 128    if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {129      addAttributesFromFunctionProtoType(130          getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());131      assert(!cir::MissingFeatures::opCallAttrs());132    }133 134    assert(!cir::MissingFeatures::opCallAttrs());135 136    // 'const', 'pure' and 'noalias' attributed functions are also nounwind.137    if (targetDecl->hasAttr<ConstAttr>()) {138      // gcc specifies that 'const' functions have greater restrictions than139      // 'pure' functions, so they also cannot have infinite loops.140      sideEffect = cir::SideEffect::Const;141    } else if (targetDecl->hasAttr<PureAttr>()) {142      // gcc specifies that 'pure' functions cannot have infinite loops.143      sideEffect = cir::SideEffect::Pure;144    }145 146    assert(!cir::MissingFeatures::opCallAttrs());147  }148 149  assert(!cir::MissingFeatures::opCallAttrs());150 151  attrs.set(cir::CIRDialect::getSideEffectAttrName(),152            cir::SideEffectAttr::get(&getMLIRContext(), sideEffect));153}154 155/// Returns the canonical formal type of the given C++ method.156static CanQual<FunctionProtoType> getFormalType(const CXXMethodDecl *md) {157  return md->getType()158      ->getCanonicalTypeUnqualified()159      .getAs<FunctionProtoType>();160}161 162/// Adds the formal parameters in FPT to the given prefix. If any parameter in163/// FPT has pass_object_size_attrs, then we'll add parameters for those, too.164/// TODO(cir): this should be shared with LLVM codegen165static void appendParameterTypes(const CIRGenTypes &cgt,166                                 SmallVectorImpl<CanQualType> &prefix,167                                 CanQual<FunctionProtoType> fpt) {168  assert(!cir::MissingFeatures::opCallExtParameterInfo());169  // Fast path: don't touch param info if we don't need to.170  if (!fpt->hasExtParameterInfos()) {171    prefix.append(fpt->param_type_begin(), fpt->param_type_end());172    return;173  }174 175  cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");176}177 178const CIRGenFunctionInfo &179CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {180  auto *md = cast<CXXMethodDecl>(gd.getDecl());181 182  llvm::SmallVector<CanQualType, 16> argTypes;183  argTypes.push_back(deriveThisType(md->getParent(), md));184 185  bool passParams = true;186 187  if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {188    // A base class inheriting constructor doesn't get forwarded arguments189    // needed to construct a virtual base (or base class thereof)190    if (cd->getInheritedConstructor())191      cgm.errorNYI(cd->getSourceRange(),192                   "arrangeCXXStructorDeclaration: inheriting constructor");193  }194 195  CanQual<FunctionProtoType> fpt = getFormalType(md);196 197  if (passParams)198    appendParameterTypes(*this, argTypes, fpt);199 200  // The structor signature may include implicit parameters.201  [[maybe_unused]] CIRGenCXXABI::AddedStructorArgCounts addedArgs =202      theCXXABI.buildStructorSignature(gd, argTypes);203  assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());204 205  RequiredArgs required =206      (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())207                                      : RequiredArgs::All);208 209  CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()210                           : theCXXABI.hasMostDerivedReturn(gd)211                               ? astContext.VoidPtrTy212                               : astContext.VoidTy;213 214  assert(!theCXXABI.hasThisReturn(gd) &&215         "Please send PR with a test and remove this");216 217  assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());218  assert(!cir::MissingFeatures::opCallFnInfoOpts());219 220  return arrangeCIRFunctionInfo(resultType, argTypes, required);221}222 223/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR224/// qualification. Either or both of `rd` and `md` may be null. A null `rd`225/// indicates that there is no meaningful 'this' type, and a null `md` can occur226/// when calling a method pointer.227CanQualType CIRGenTypes::deriveThisType(const CXXRecordDecl *rd,228                                        const CXXMethodDecl *md) {229  CanQualType recTy;230  if (rd) {231    recTy = getASTContext().getCanonicalTagType(rd);232  } else {233    // This can happen with the MS ABI. It shouldn't need anything more than234    // setting recTy to VoidTy here, but we're flagging it for now because we235    // don't have the full handling implemented.236    cgm.errorNYI("deriveThisType: no record decl");237    recTy = getASTContext().VoidTy;238  }239 240  if (md)241    recTy = CanQualType::CreateUnsafe(getASTContext().getAddrSpaceQualType(242        recTy, md->getMethodQualifiers().getAddressSpace()));243  return getASTContext().getPointerType(recTy);244}245 246/// Arrange the CIR function layout for a value of the given function type, on247/// top of any implicit parameters already stored.248static const CIRGenFunctionInfo &249arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl<CanQualType> &prefix,250                       CanQual<FunctionProtoType> fpt) {251  assert(!cir::MissingFeatures::opCallFnInfoOpts());252  RequiredArgs required =253      RequiredArgs::getFromProtoWithExtraSlots(fpt, prefix.size());254  assert(!cir::MissingFeatures::opCallExtParameterInfo());255  appendParameterTypes(cgt, prefix, fpt);256  CanQualType resultType = fpt->getReturnType().getUnqualifiedType();257  return cgt.arrangeCIRFunctionInfo(resultType, prefix, required);258}259 260void CIRGenFunction::emitDelegateCallArg(CallArgList &args,261                                         const VarDecl *param,262                                         SourceLocation loc) {263  // StartFunction converted the ABI-lowered parameter(s) into a local alloca.264  // We need to turn that into an r-value suitable for emitCall265  Address local = getAddrOfLocalVar(param);266 267  QualType type = param->getType();268 269  if (type->getAsCXXRecordDecl()) {270    cgm.errorNYI(param->getSourceRange(),271                 "emitDelegateCallArg: record argument");272    return;273  }274 275  // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the276  // argument needs to be the original pointer.277  if (type->isReferenceType()) {278    args.add(279        RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),280        type);281  } else if (getLangOpts().ObjCAutoRefCount) {282    cgm.errorNYI(param->getSourceRange(),283                 "emitDelegateCallArg: ObjCAutoRefCount");284    // For the most part, we just need to load the alloca, except that aggregate285    // r-values are actually pointers to temporaries.286  } else {287    args.add(convertTempToRValue(local, type, loc), type);288  }289 290  // Deactivate the cleanup for the callee-destructed param that was pushed.291  assert(!cir::MissingFeatures::thunks());292  if (type->isRecordType() &&293      type->castAsRecordDecl()->isParamDestroyedInCallee() &&294      param->needsDestruction(getContext())) {295    cgm.errorNYI(param->getSourceRange(),296                 "emitDelegateCallArg: callee-destructed param");297  }298}299 300static const CIRGenFunctionInfo &301arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,302                            const CallArgList &args,303                            const FunctionType *fnType) {304 305  RequiredArgs required = RequiredArgs::All;306 307  if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {308    if (proto->isVariadic())309      required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);310    if (proto->hasExtParameterInfos())311      cgm.errorNYI("call to functions with extra parameter info");312  } else if (cgm.getTargetCIRGenInfo().isNoProtoCallVariadic(313                 cast<FunctionNoProtoType>(fnType)))314    cgm.errorNYI("call to function without a prototype");315 316  SmallVector<CanQualType, 16> argTypes;317  for (const CallArg &arg : args)318    argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));319 320  CanQualType retType = fnType->getReturnType()321                            ->getCanonicalTypeUnqualified()322                            .getUnqualifiedType();323 324  assert(!cir::MissingFeatures::opCallFnInfoOpts());325  return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);326}327 328/// Arrange a call to a C++ method, passing the given arguments.329///330/// extraPrefixArgs is the number of ABI-specific args passed after the `this`331/// parameter.332/// passProtoArgs indicates whether `args` has args for the parameters in the333/// given CXXConstructorDecl.334const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall(335    const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,336    unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs) {337 338  // FIXME: Kill copy.339  llvm::SmallVector<CanQualType, 16> argTypes;340  for (const auto &arg : args)341    argTypes.push_back(astContext.getCanonicalParamType(arg.ty));342 343  // +1 for implicit this, which should always be args[0]344  unsigned totalPrefixArgs = 1 + extraPrefixArgs;345 346  CanQual<FunctionProtoType> fpt = getFormalType(d);347  RequiredArgs required = passProtoArgs348                              ? RequiredArgs::getFromProtoWithExtraSlots(349                                    fpt, totalPrefixArgs + extraSuffixArgs)350                              : RequiredArgs::All;351 352  GlobalDecl gd(d, ctorKind);353  if (theCXXABI.hasThisReturn(gd))354    cgm.errorNYI(d->getSourceRange(),355                 "arrangeCXXConstructorCall: hasThisReturn");356  if (theCXXABI.hasMostDerivedReturn(gd))357    cgm.errorNYI(d->getSourceRange(),358                 "arrangeCXXConstructorCall: hasMostDerivedReturn");359  CanQualType resultType = astContext.VoidTy;360 361  assert(!cir::MissingFeatures::opCallFnInfoOpts());362  assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());363 364  return arrangeCIRFunctionInfo(resultType, argTypes, required);365}366 367/// Arrange a call to a C++ method, passing the given arguments.368///369/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It370/// does not count `this`.371const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXMethodCall(372    const CallArgList &args, const FunctionProtoType *proto,373    RequiredArgs required, unsigned numPrefixArgs) {374  assert(!cir::MissingFeatures::opCallExtParameterInfo());375  assert(numPrefixArgs + 1 <= args.size() &&376         "Emitting a call with less args than the required prefix?");377 378  // FIXME: Kill copy.379  llvm::SmallVector<CanQualType, 16> argTypes;380  for (const CallArg &arg : args)381    argTypes.push_back(astContext.getCanonicalParamType(arg.ty));382 383  assert(!cir::MissingFeatures::opCallFnInfoOpts());384  return arrangeCIRFunctionInfo(proto->getReturnType()385                                    ->getCanonicalTypeUnqualified()386                                    .getUnqualifiedType(),387                                argTypes, required);388}389 390const CIRGenFunctionInfo &391CIRGenTypes::arrangeFreeFunctionCall(const CallArgList &args,392                                     const FunctionType *fnType) {393  return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);394}395 396/// Arrange the argument and result information for a declaration or definition397/// of the given C++ non-static member function. The member function must be an398/// ordinary function, i.e. not a constructor or destructor.399const CIRGenFunctionInfo &400CIRGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *md) {401  assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");402  assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");403 404  auto prototype =405      md->getType()->getCanonicalTypeUnqualified().getAs<FunctionProtoType>();406  assert(!cir::MissingFeatures::cudaSupport());407 408  if (md->isInstance()) {409    // The abstract case is perfectly fine.410    auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);411    return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);412  }413 414  return arrangeFreeFunctionType(prototype);415}416 417/// Arrange the argument and result information for a call to an unknown C++418/// non-static member function of the given abstract type. (A null RD means we419/// don't have any meaningful "this" argument type, so fall back to a generic420/// pointer type). The member fucntion must be an ordinary function, i.e. not a421/// constructor or destructor.422const CIRGenFunctionInfo &423CIRGenTypes::arrangeCXXMethodType(const CXXRecordDecl *rd,424                                  const FunctionProtoType *fpt,425                                  const CXXMethodDecl *md) {426  llvm::SmallVector<CanQualType, 16> argTypes;427 428  // Add the 'this' pointer.429  argTypes.push_back(deriveThisType(rd, md));430 431  assert(!cir::MissingFeatures::opCallFnInfoOpts());432  return ::arrangeCIRFunctionInfo(433      *this, argTypes,434      fpt->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());435}436 437/// Arrange the argument and result information for the declaration or438/// definition of the given function.439const CIRGenFunctionInfo &440CIRGenTypes::arrangeFunctionDeclaration(const FunctionDecl *fd) {441  if (const auto *md = dyn_cast<CXXMethodDecl>(fd))442    if (md->isInstance())443      return arrangeCXXMethodDeclaration(md);444 445  CanQualType funcTy = fd->getType()->getCanonicalTypeUnqualified();446 447  assert(isa<FunctionType>(funcTy));448  // TODO: setCUDAKernelCallingConvention449  assert(!cir::MissingFeatures::cudaSupport());450 451  // When declaring a function without a prototype, always use a non-variadic452  // type.453  if (CanQual<FunctionNoProtoType> noProto =454          funcTy.getAs<FunctionNoProtoType>()) {455    assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());456    assert(!cir::MissingFeatures::opCallFnInfoOpts());457    return arrangeCIRFunctionInfo(noProto->getReturnType(), {},458                                  RequiredArgs::All);459  }460 461  return arrangeFreeFunctionType(funcTy.castAs<FunctionProtoType>());462}463 464static cir::CIRCallOpInterface465emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,466               cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,467               cir::FuncOp directFuncOp,468               const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,469               const mlir::NamedAttrList &attrs) {470  CIRGenBuilderTy &builder = cgf.getBuilder();471 472  assert(!cir::MissingFeatures::opCallSurroundingTry());473 474  if (isInvoke) {475    // This call may throw and requires catch and/or cleanup handling.476    // If this call does not appear within the `try` region of an existing477    // TryOp, we must create a synthetic TryOp to contain the call. This478    // happens when a call that may throw appears within a cleanup479    // scope.480 481    // In OG, we build the landing pad for this scope. In CIR, we emit a482    // synthetic cir.try because this didn't come from code generating from a483    // try/catch in C++.484    assert(cgf.curLexScope && "expected scope");485    cir::TryOp tryOp = cgf.curLexScope->getClosestTryParent();486    if (!tryOp) {487      cgf.cgm.errorNYI(488          "emitCallLikeOp: call does not have an associated cir.try");489      return {};490    }491 492    if (tryOp.getSynthetic()) {493      cgf.cgm.errorNYI("emitCallLikeOp: tryOp synthetic");494      return {};495    }496 497    cir::CallOp callOpWithExceptions;498    if (indirectFuncTy) {499      cgf.cgm.errorNYI("emitCallLikeOp: indirect function type");500      return {};501    }502 503    callOpWithExceptions =504        builder.createCallOp(callLoc, directFuncOp, cirCallArgs);505 506    cgf.populateCatchHandlersIfRequired(tryOp);507    return callOpWithExceptions;508  }509 510  assert(builder.getInsertionBlock() && "expected valid basic block");511 512  cir::CallOp op;513  if (indirectFuncTy) {514    // TODO(cir): Set calling convention for indirect calls.515    assert(!cir::MissingFeatures::opCallCallConv());516    op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,517                                      cirCallArgs, attrs);518  } else {519    op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs);520  }521 522  return op;523}524 525const CIRGenFunctionInfo &526CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt) {527  SmallVector<CanQualType, 16> argTypes;528  assert(!cir::MissingFeatures::opCallFnInfoOpts());529  return ::arrangeCIRFunctionInfo(*this, argTypes, fpt);530}531 532const CIRGenFunctionInfo &533CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt) {534  CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();535  assert(!cir::MissingFeatures::opCallFnInfoOpts());536  return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));537}538 539RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,540                                const CIRGenCallee &callee,541                                ReturnValueSlot returnValue,542                                const CallArgList &args,543                                cir::CIRCallOpInterface *callOp,544                                mlir::Location loc) {545  QualType retTy = funcInfo.getReturnType();546  cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);547 548  SmallVector<mlir::Value, 16> cirCallArgs(args.size());549 550  assert(!cir::MissingFeatures::emitLifetimeMarkers());551 552  // Translate all of the arguments as necessary to match the CIR lowering.553  for (auto [argNo, arg, canQualArgType] :554       llvm::enumerate(args, funcInfo.argTypes())) {555 556    // Insert a padding argument to ensure proper alignment.557    assert(!cir::MissingFeatures::opCallPaddingArgs());558 559    mlir::Type argType = convertType(canQualArgType);560    if (!mlir::isa<cir::RecordType>(argType) &&561        !mlir::isa<cir::ComplexType>(argType)) {562      mlir::Value v;563      if (arg.isAggregate())564        cgm.errorNYI(loc, "emitCall: aggregate call argument");565      v = arg.getKnownRValue().getValue();566 567      // We might have to widen integers, but we should never truncate.568      if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))569        cgm.errorNYI(loc, "emitCall: widening integer call argument");570 571      // If the argument doesn't match, perform a bitcast to coerce it. This572      // can happen due to trivial type mismatches.573      // TODO(cir): When getFunctionType is added, assert that this isn't574      // needed.575      assert(!cir::MissingFeatures::opCallBitcastArg());576      cirCallArgs[argNo] = v;577    } else {578      Address src = Address::invalid();579      if (!arg.isAggregate()) {580        src = createMemTemp(arg.ty, loc, "coerce");581        arg.copyInto(*this, src, loc);582      } else {583        src = arg.hasLValue() ? arg.getKnownLValue().getAddress()584                              : arg.getKnownRValue().getAggregateAddress();585      }586 587      // Fast-isel and the optimizer generally like scalar values better than588      // FCAs, so we flatten them if this is safe to do for this argument.589      mlir::Type srcTy = src.getElementType();590      // FIXME(cir): get proper location for each argument.591      mlir::Location argLoc = loc;592 593      // If the source type is smaller than the destination type of the594      // coerce-to logic, copy the source value into a temp alloca the size595      // of the destination type to allow loading all of it. The bits past596      // the source value are left undef.597      // FIXME(cir): add data layout info and compare sizes instead of598      // matching the types.599      //600      // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);601      // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);602      // if (SrcSize < DstSize) {603      assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());604      if (srcTy != argType) {605        cgm.errorNYI(loc, "emitCall: source type does not match argument type");606      } else {607        // FIXME(cir): this currently only runs when the types are exactly the608        // same, but should be when alloc sizes are the same, fix this as soon609        // as datalayout gets introduced.610        assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());611      }612 613      // assert(NumCIRArgs == STy.getMembers().size());614      // In LLVMGen: Still only pass the struct without any gaps but mark it615      // as such somehow.616      //617      // In CIRGen: Emit a load from the "whole" struct,618      // which shall be broken later by some lowering step into multiple619      // loads.620      assert(!cir::MissingFeatures::lowerAggregateLoadStore());621      cirCallArgs[argNo] = builder.createLoad(argLoc, src);622    }623  }624 625  const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);626  mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();627 628  assert(!cir::MissingFeatures::opCallInAlloca());629 630  mlir::NamedAttrList attrs;631  StringRef funcName;632  if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))633    funcName = calleeFuncOp.getName();634 635  assert(!cir::MissingFeatures::opCallCallConv());636  assert(!cir::MissingFeatures::opCallAttrs());637  cgm.constructAttributeList(callee.getAbstractInfo(), attrs);638 639  cir::FuncType indirectFuncTy;640  mlir::Value indirectFuncVal;641  cir::FuncOp directFuncOp;642  if (auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {643    directFuncOp = fnOp;644  } else if (auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {645    // FIXME(cir): This peephole optimization avoids indirect calls for646    // builtins. This should be fixed in the builtin declaration instead by647    // not emitting an unecessary get_global in the first place.648    // However, this is also used for no-prototype functions.649    mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());650    assert(globalOp && "undefined global function");651    directFuncOp = mlir::cast<cir::FuncOp>(globalOp);652  } else {653    [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =654        calleePtr->getResultTypes();655    [[maybe_unused]] auto funcPtrTy =656        mlir::dyn_cast<cir::PointerType>(resultTypes.front());657    assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&658           "expected pointer to function");659 660    indirectFuncTy = cirFuncTy;661    indirectFuncVal = calleePtr->getResult(0);662  }663 664  assert(!cir::MissingFeatures::msvcCXXPersonality());665  assert(!cir::MissingFeatures::functionUsesSEHTry());666  assert(!cir::MissingFeatures::nothrowAttr());667 668  bool cannotThrow = attrs.getNamed("nothrow").has_value();669  bool isInvoke = !cannotThrow && isCatchOrCleanupRequired();670 671  mlir::Location callLoc = loc;672  cir::CIRCallOpInterface theCall =673      emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,674                     cirCallArgs, isInvoke, attrs);675 676  if (callOp)677    *callOp = theCall;678 679  assert(!cir::MissingFeatures::opCallMustTail());680  assert(!cir::MissingFeatures::opCallReturn());681 682  mlir::Type retCIRTy = convertType(retTy);683  if (isa<cir::VoidType>(retCIRTy))684    return getUndefRValue(retTy);685  switch (getEvaluationKind(retTy)) {686  case cir::TEK_Aggregate: {687    Address destPtr = returnValue.getValue();688 689    if (!destPtr.isValid())690      destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());691 692    mlir::ResultRange results = theCall->getOpResults();693    assert(results.size() <= 1 && "multiple returns from a call");694 695    SourceLocRAIIObject loc{*this, callLoc};696    emitAggregateStore(results[0], destPtr);697    return RValue::getAggregate(destPtr);698  }699  case cir::TEK_Scalar: {700    mlir::ResultRange results = theCall->getOpResults();701    assert(results.size() == 1 && "unexpected number of returns");702 703    // If the argument doesn't match, perform a bitcast to coerce it. This704    // can happen due to trivial type mismatches.705    if (results[0].getType() != retCIRTy)706      cgm.errorNYI(loc, "bitcast on function return value");707 708    mlir::Region *region = builder.getBlock()->getParent();709    if (region != theCall->getParentRegion())710      cgm.errorNYI(loc, "function calls with cleanup");711 712    return RValue::get(results[0]);713  }714  case cir::TEK_Complex: {715    mlir::ResultRange results = theCall->getOpResults();716    assert(!results.empty() &&717           "Expected at least one result for complex rvalue");718    return RValue::getComplex(results[0]);719  }720  }721  llvm_unreachable("Invalid evaluation kind");722}723 724void CallArg::copyInto(CIRGenFunction &cgf, Address addr,725                       mlir::Location loc) const {726  LValue dst = cgf.makeAddrLValue(addr, ty);727  if (!hasLV && rv.isScalar())728    cgf.cgm.errorNYI(loc, "copyInto scalar value");729  else if (!hasLV && rv.isComplex())730    cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);731  else732    cgf.cgm.errorNYI(loc, "copyInto hasLV");733  isUsed = true;734}735 736mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,737                                            cir::FuncOp callee,738                                            ArrayRef<mlir::Value> args) {739  // TODO(cir): set the calling convention to this runtime call.740  assert(!cir::MissingFeatures::opFuncCallingConv());741 742  cir::CallOp call = builder.createCallOp(loc, callee, args);743  assert(call->getNumResults() <= 1 &&744         "runtime functions have at most 1 result");745 746  if (call->getNumResults() == 0)747    return nullptr;748 749  return call->getResult(0);750}751 752void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,753                                 clang::QualType argType) {754  assert(argType->isReferenceType() == e->isGLValue() &&755         "reference binding to unmaterialized r-value!");756 757  if (e->isGLValue()) {758    assert(e->getObjectKind() == OK_Ordinary);759    return args.add(emitReferenceBindingToExpr(e), argType);760  }761 762  bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);763 764  // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.765  // However, we still have to push an EH-only cleanup in case we unwind before766  // we make it to the call.767  if (argType->isRecordType() &&768      argType->castAsRecordDecl()->isParamDestroyedInCallee()) {769    assert(!cir::MissingFeatures::msabi());770    cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");771  }772 773  if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&774      cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {775    LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());776    assert(lv.isSimple());777    args.addUncopiedAggregate(lv, argType);778    return;779  }780 781  args.add(emitAnyExprToTemp(e), argType);782}783 784QualType CIRGenFunction::getVarArgType(const Expr *arg) {785  // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC786  // implicitly widens null pointer constants that are arguments to varargs787  // functions to pointer-sized ints.788  if (!getTarget().getTriple().isOSWindows())789    return arg->getType();790 791  assert(!cir::MissingFeatures::msabi());792  cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");793  return arg->getType();794}795 796/// Similar to emitAnyExpr(), however, the result will always be accessible797/// even if no aggregate location is provided.798RValue CIRGenFunction::emitAnyExprToTemp(const Expr *e) {799  AggValueSlot aggSlot = AggValueSlot::ignored();800 801  if (hasAggregateEvaluationKind(e->getType()))802    aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),803                            getCounterAggTmpAsString());804 805  return emitAnyExpr(e, aggSlot);806}807 808void CIRGenFunction::emitCallArgs(809    CallArgList &args, PrototypeWrapper prototype,810    llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,811    AbstractCallee callee, unsigned paramsToSkip) {812  llvm::SmallVector<QualType, 16> argTypes;813 814  assert(!cir::MissingFeatures::opCallCallConv());815 816  // First, if a prototype was provided, use those argument types.817  bool isVariadic = false;818  if (prototype.p) {819    assert(!cir::MissingFeatures::opCallObjCMethod());820 821    const auto *fpt = cast<const FunctionProtoType *>(prototype.p);822    isVariadic = fpt->isVariadic();823    assert(!cir::MissingFeatures::opCallCallConv());824    argTypes.assign(fpt->param_type_begin() + paramsToSkip,825                    fpt->param_type_end());826  }827 828  // If we still have any arguments, emit them using the type of the argument.829  for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))830    argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());831  assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));832 833  // We must evaluate arguments from right to left in the MS C++ ABI, because834  // arguments are destroyed left to right in the callee. As a special case,835  // there are certain language constructs taht require left-to-right836  // evaluation, and in those cases we consider the evaluation order requirement837  // to trump the "destruction order is reverse construction order" guarantee.838  auto leftToRight = true;839  assert(!cir::MissingFeatures::msabi());840 841  auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,842                                         RValue emittedArg) {843    if (!callee.hasFunctionDecl() || i >= callee.getNumParams())844      return;845    auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();846    if (!ps)847      return;848 849    assert(!cir::MissingFeatures::opCallImplicitObjectSizeArgs());850    cgm.errorNYI("emit implicit object size for call arg");851  };852 853  // Evaluate each argument in the appropriate order.854  size_t callArgsStart = args.size();855  for (size_t i = 0; i != argTypes.size(); ++i) {856    size_t idx = leftToRight ? i : argTypes.size() - i - 1;857    CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;858    size_t initialArgSize = args.size();859 860    emitCallArg(args, *currentArg, argTypes[idx]);861 862    // In particular, we depend on it being the last arg in Args, and the863    // objectsize bits depend on there only being one arg if !LeftToRight.864    assert(initialArgSize + 1 == args.size() &&865           "The code below depends on only adding one arg per emitCallArg");866    (void)initialArgSize;867 868    // Since pointer argument are never emitted as LValue, it is safe to emit869    // non-null argument check for r-value only.870    if (!args.back().hasLValue()) {871      RValue rvArg = args.back().getKnownRValue();872      assert(!cir::MissingFeatures::sanitizers());873      maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);874    }875 876    if (!leftToRight)877      std::reverse(args.begin() + callArgsStart, args.end());878  }879}880