//===--- CodeGenFunction.cpp - Emit LLVM Code from ASTs for a Function ----===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This coordinates the per-function state used while generating code.
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
#include "CGBlocks.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGHLSLRuntime.h"
#include "CGOpenMPRuntime.h"
#include "CodeGenModule.h"
#include "CodeGenPGO.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/FPEnv.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/Support/CRC.h"
#include "llvm/Support/xxhash.h"
#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include <optional>

using namespace clang;
using namespace CodeGen;

namespace llvm {
extern cl::opt<bool> EnableSingleByteCoverage;
} // namespace llvm

/// shouldEmitLifetimeMarkers - Decide whether we need emit the life-time
/// markers.
static bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
                                      const LangOptions &LangOpts) {
  if (CGOpts.DisableLifetimeMarkers)
    return false;

  // Sanitizers may use markers.
  if (CGOpts.SanitizeAddressUseAfterScope ||
      LangOpts.Sanitize.has(SanitizerKind::HWAddress) ||
      LangOpts.Sanitize.has(SanitizerKind::Memory))
    return true;

  // For now, only in optimized builds.
  return CGOpts.OptimizationLevel != 0;
}

CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
    : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()),
      Builder(cgm, cgm.getModule().getContext(), llvm::ConstantFolder(),
              CGBuilderInserterTy(this)),
      SanOpts(CGM.getLangOpts().Sanitize), CurFPFeatures(CGM.getLangOpts()),
      DebugInfo(CGM.getModuleDebugInfo()), PGO(cgm),
      ShouldEmitLifetimeMarkers(
          shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) {
  if (!suppressNewContext)
    CGM.getCXXABI().getMangleContext().startNewFunction();
  EHStack.setCGF(this);

  SetFastMathFlags(CurFPFeatures);
}

CodeGenFunction::~CodeGenFunction() {
  assert(LifetimeExtendedCleanupStack.empty() && "failed to emit a cleanup");
  assert(DeferredDeactivationCleanupStack.empty() &&
         "missed to deactivate a cleanup");

  if (getLangOpts().OpenMP && CurFn)
    CGM.getOpenMPRuntime().functionFinished(*this);

  // If we have an OpenMPIRBuilder we want to finalize functions (incl.
  // outlining etc) at some point. Doing it once the function codegen is done
  // seems to be a reasonable spot. We do it here, as opposed to the deletion
  // time of the CodeGenModule, because we have to ensure the IR has not yet
  // been "emitted" to the outside, thus, modifications are still sensible.
  if (CGM.getLangOpts().OpenMPIRBuilder && CurFn)
    CGM.getOpenMPRuntime().getOMPBuilder().finalize(CurFn);
}

// Map the LangOption for exception behavior into
// the corresponding enum in the IR.
llvm::fp::ExceptionBehavior
clang::ToConstrainedExceptMD(LangOptions::FPExceptionModeKind Kind) {

  switch (Kind) {
  case LangOptions::FPE_Ignore:  return llvm::fp::ebIgnore;
  case LangOptions::FPE_MayTrap: return llvm::fp::ebMayTrap;
  case LangOptions::FPE_Strict:  return llvm::fp::ebStrict;
  default:
    llvm_unreachable("Unsupported FP Exception Behavior");
  }
}

void CodeGenFunction::SetFastMathFlags(FPOptions FPFeatures) {
  llvm::FastMathFlags FMF;
  FMF.setAllowReassoc(FPFeatures.getAllowFPReassociate());
  FMF.setNoNaNs(FPFeatures.getNoHonorNaNs());
  FMF.setNoInfs(FPFeatures.getNoHonorInfs());
  FMF.setNoSignedZeros(FPFeatures.getNoSignedZero());
  FMF.setAllowReciprocal(FPFeatures.getAllowReciprocal());
  FMF.setApproxFunc(FPFeatures.getAllowApproxFunc());
  FMF.setAllowContract(FPFeatures.allowFPContractAcrossStatement());
  Builder.setFastMathFlags(FMF);
}

CodeGenFunction::CGFPOptionsRAII::CGFPOptionsRAII(CodeGenFunction &CGF,
                                                  const Expr *E)
    : CGF(CGF) {
  ConstructorHelper(E->getFPFeaturesInEffect(CGF.getLangOpts()));
}

CodeGenFunction::CGFPOptionsRAII::CGFPOptionsRAII(CodeGenFunction &CGF,
                                                  FPOptions FPFeatures)
    : CGF(CGF) {
  ConstructorHelper(FPFeatures);
}

void CodeGenFunction::CGFPOptionsRAII::ConstructorHelper(FPOptions FPFeatures) {
  OldFPFeatures = CGF.CurFPFeatures;
  CGF.CurFPFeatures = FPFeatures;

  OldExcept = CGF.Builder.getDefaultConstrainedExcept();
  OldRounding = CGF.Builder.getDefaultConstrainedRounding();

  if (OldFPFeatures == FPFeatures)
    return;

  FMFGuard.emplace(CGF.Builder);

  llvm::RoundingMode NewRoundingBehavior = FPFeatures.getRoundingMode();
  CGF.Builder.setDefaultConstrainedRounding(NewRoundingBehavior);
  auto NewExceptionBehavior =
      ToConstrainedExceptMD(static_cast<LangOptions::FPExceptionModeKind>(
          FPFeatures.getExceptionMode()));
  CGF.Builder.setDefaultConstrainedExcept(NewExceptionBehavior);

  CGF.SetFastMathFlags(FPFeatures);

  assert((CGF.CurFuncDecl == nullptr || CGF.Builder.getIsFPConstrained() ||
          isa<CXXConstructorDecl>(CGF.CurFuncDecl) ||
          isa<CXXDestructorDecl>(CGF.CurFuncDecl) ||
          (NewExceptionBehavior == llvm::fp::ebIgnore &&
           NewRoundingBehavior == llvm::RoundingMode::NearestTiesToEven)) &&
         "FPConstrained should be enabled on entire function");

  auto mergeFnAttrValue = [&](StringRef Name, bool Value) {
    auto OldValue =
        CGF.CurFn->getFnAttribute(Name).getValueAsBool();
    auto NewValue = OldValue & Value;
    if (OldValue != NewValue)
      CGF.CurFn->addFnAttr(Name, llvm::toStringRef(NewValue));
  };
  mergeFnAttrValue("no-infs-fp-math", FPFeatures.getNoHonorInfs());
  mergeFnAttrValue("no-nans-fp-math", FPFeatures.getNoHonorNaNs());
  mergeFnAttrValue("no-signed-zeros-fp-math", FPFeatures.getNoSignedZero());
  mergeFnAttrValue(
      "unsafe-fp-math",
      FPFeatures.getAllowFPReassociate() && FPFeatures.getAllowReciprocal() &&
          FPFeatures.getAllowApproxFunc() && FPFeatures.getNoSignedZero() &&
          FPFeatures.allowFPContractAcrossStatement());
}

CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() {
  CGF.CurFPFeatures = OldFPFeatures;
  CGF.Builder.setDefaultConstrainedExcept(OldExcept);
  CGF.Builder.setDefaultConstrainedRounding(OldRounding);
}

static LValue
makeNaturalAlignAddrLValue(llvm::Value *V, QualType T, bool ForPointeeType,
                           bool MightBeSigned, CodeGenFunction &CGF,
                           KnownNonNull_t IsKnownNonNull = NotKnownNonNull) {
  LValueBaseInfo BaseInfo;
  TBAAAccessInfo TBAAInfo;
  CharUnits Alignment =
      CGF.CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, ForPointeeType);
  Address Addr =
      MightBeSigned
          ? CGF.makeNaturalAddressForPointer(V, T, Alignment, false, nullptr,
                                             nullptr, IsKnownNonNull)
          : Address(V, CGF.ConvertTypeForMem(T), Alignment, IsKnownNonNull);
  return CGF.MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo);
}

LValue
CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T,
                                            KnownNonNull_t IsKnownNonNull) {
  return ::makeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false,
                                      /*MightBeSigned*/ true, *this,
                                      IsKnownNonNull);
}

LValue
CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) {
  return ::makeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true,
                                      /*MightBeSigned*/ true, *this);
}

LValue CodeGenFunction::MakeNaturalAlignRawAddrLValue(llvm::Value *V,
                                                      QualType T) {
  return ::makeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false,
                                      /*MightBeSigned*/ false, *this);
}

LValue CodeGenFunction::MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V,
                                                             QualType T) {
  return ::makeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true,
                                      /*MightBeSigned*/ false, *this);
}

llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) {
  return CGM.getTypes().ConvertTypeForMem(T);
}

llvm::Type *CodeGenFunction::ConvertType(QualType T) {
  return CGM.getTypes().ConvertType(T);
}

llvm::Type *CodeGenFunction::convertTypeForLoadStore(QualType ASTTy,
                                                     llvm::Type *LLVMTy) {
  return CGM.getTypes().convertTypeForLoadStore(ASTTy, LLVMTy);
}

TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
  type = type.getCanonicalType();
  while (true) {
    switch (type->getTypeClass()) {
#define TYPE(name, parent)
#define ABSTRACT_TYPE(name, parent)
#define NON_CANONICAL_TYPE(name, parent) case Type::name:
#define DEPENDENT_TYPE(name, parent) case Type::name:
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(name, parent) case Type::name:
#include "clang/AST/TypeNodes.inc"
      llvm_unreachable("non-canonical or dependent type in IR-generation");

    case Type::Auto:
    case Type::DeducedTemplateSpecialization:
      llvm_unreachable("undeduced type in IR-generation");

    // Various scalar types.
    case Type::Builtin:
    case Type::Pointer:
    case Type::BlockPointer:
    case Type::LValueReference:
    case Type::RValueReference:
    case Type::MemberPointer:
    case Type::Vector:
    case Type::ExtVector:
    case Type::ConstantMatrix:
    case Type::FunctionProto:
    case Type::FunctionNoProto:
    case Type::Enum:
    case Type::ObjCObjectPointer:
    case Type::Pipe:
    case Type::BitInt:
    case Type::HLSLAttributedResource:
      return TEK_Scalar;

    // Complexes.
    case Type::Complex:
      return TEK_Complex;

    // Arrays, records, and Objective-C objects.
    case Type::ConstantArray:
    case Type::IncompleteArray:
    case Type::VariableArray:
    case Type::Record:
    case Type::ObjCObject:
    case Type::ObjCInterface:
    case Type::ArrayParameter:
      return TEK_Aggregate;

    // We operate on atomic values according to their underlying type.
    case Type::Atomic:
      type = cast<AtomicType>(type)->getValueType();
      continue;
    }
    llvm_unreachable("unknown type kind!");
  }
}

llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
  // For cleanliness, we try to avoid emitting the return block for
  // simple cases.
  llvm::BasicBlock *CurBB = Builder.GetInsertBlock();

  if (CurBB) {
    assert(!CurBB->getTerminator() && "Unexpected terminated block.");

    // We have a valid insert point, reuse it if it is empty or there are no
    // explicit jumps to the return block.
    if (CurBB->empty() || ReturnBlock.getBlock()->use_empty()) {
      ReturnBlock.getBlock()->replaceAllUsesWith(CurBB);
      delete ReturnBlock.getBlock();
      ReturnBlock = JumpDest();
    } else
      EmitBlock(ReturnBlock.getBlock());
    return llvm::DebugLoc();
  }

  // Otherwise, if the return block is the target of a single direct
  // branch then we can just put the code in that block instead. This
  // cleans up functions which started with a unified return block.
  if (ReturnBlock.getBlock()->hasOneUse()) {
    llvm::BranchInst *BI =
      dyn_cast<llvm::BranchInst>(*ReturnBlock.getBlock()->user_begin());
    if (BI && BI->isUnconditional() &&
        BI->getSuccessor(0) == ReturnBlock.getBlock()) {
      // Record/return the DebugLoc of the simple 'return' expression to be used
      // later by the actual 'ret' instruction.
      llvm::DebugLoc Loc = BI->getDebugLoc();
      Builder.SetInsertPoint(BI->getParent());
      BI->eraseFromParent();
      delete ReturnBlock.getBlock();
      ReturnBlock = JumpDest();
      return Loc;
    }
  }

  // FIXME: We are at an unreachable point, there is no reason to emit the block
  // unless it has uses. However, we still need a place to put the debug
  // region.end for now.

  EmitBlock(ReturnBlock.getBlock());
  return llvm::DebugLoc();
}

static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) {
  if (!BB) return;
  if (!BB->use_empty()) {
    CGF.CurFn->insert(CGF.CurFn->end(), BB);
    return;
  }
  delete BB;
}

void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
  assert(BreakContinueStack.empty() &&
         "mismatched push/pop in break/continue stack!");
  assert(LifetimeExtendedCleanupStack.empty() &&
         "mismatched push/pop of cleanups in EHStack!");
  assert(DeferredDeactivationCleanupStack.empty() &&
         "mismatched activate/deactivate of cleanups!");

  if (CGM.shouldEmitConvergenceTokens()) {
    ConvergenceTokenStack.pop_back();
    assert(ConvergenceTokenStack.empty() &&
           "mismatched push/pop in convergence stack!");
  }

  bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0
    && NumSimpleReturnExprs == NumReturnExprs
    && ReturnBlock.getBlock()->use_empty();
  // Usually the return expression is evaluated before the cleanup
  // code.  If the function contains only a simple return statement,
  // such as a constant, the location before the cleanup code becomes
  // the last useful breakpoint in the function, because the simple
  // return expression will be evaluated after the cleanup code. To be
  // safe, set the debug location for cleanup code to the location of
  // the return statement.  Otherwise the cleanup code should be at the
  // end of the function's lexical scope.
  //
  // If there are multiple branches to the return block, the branch
  // instructions will get the location of the return statements and
  // all will be fine.
  if (CGDebugInfo *DI = getDebugInfo()) {
    if (OnlySimpleReturnStmts)
      DI->EmitLocation(Builder, LastStopPoint);
    else
      DI->EmitLocation(Builder, EndLoc);
  }

  // Pop any cleanups that might have been associated with the
  // parameters.  Do this in whatever block we're currently in; it's
  // important to do this before we enter the return block or return
  // edges will be *really* confused.
  bool HasCleanups = EHStack.stable_begin() != PrologueCleanupDepth;
  bool HasOnlyNoopCleanups =
      HasCleanups && EHStack.containsOnlyNoopCleanups(PrologueCleanupDepth);
  bool EmitRetDbgLoc = !HasCleanups || HasOnlyNoopCleanups;

  std::optional<ApplyDebugLocation> OAL;
  if (HasCleanups) {
    // Make sure the line table doesn't jump back into the body for
    // the ret after it's been at EndLoc.
    if (CGDebugInfo *DI = getDebugInfo()) {
      if (OnlySimpleReturnStmts)
        DI->EmitLocation(Builder, EndLoc);
      else
        // We may not have a valid end location. Try to apply it anyway, and
        // fall back to an artificial location if needed.
        OAL = ApplyDebugLocation::CreateDefaultArtificial(*this, EndLoc);
    }

    PopCleanupBlocks(PrologueCleanupDepth);
  }

  // Emit function epilog (to return).
  llvm::DebugLoc Loc = EmitReturnBlock();

  if (ShouldInstrumentFunction()) {
    if (CGM.getCodeGenOpts().InstrumentFunctions)
      CurFn->addFnAttr("instrument-function-exit", "__cyg_profile_func_exit");
    if (CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining)
      CurFn->addFnAttr("instrument-function-exit-inlined",
                       "__cyg_profile_func_exit");
  }

  // Emit debug descriptor for function end.
  if (CGDebugInfo *DI = getDebugInfo())
    DI->EmitFunctionEnd(Builder, CurFn);

  // Reset the debug location to that of the simple 'return' expression, if any
  // rather than that of the end of the function's scope '}'.
  ApplyDebugLocation AL(*this, Loc);
  EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc);
  EmitEndEHSpec(CurCodeDecl);

  assert(EHStack.empty() &&
         "did not remove all scopes from cleanup stack!");

  // If someone did an indirect goto, emit the indirect goto block at the end of
  // the function.
  if (IndirectBranch) {
    EmitBlock(IndirectBranch->getParent());
    Builder.ClearInsertionPoint();
  }

  // If some of our locals escaped, insert a call to llvm.localescape in the
  // entry block.
  if (!EscapedLocals.empty()) {
    // Invert the map from local to index into a simple vector. There should be
    // no holes.
    SmallVector<llvm::Value *, 4> EscapeArgs;
    EscapeArgs.resize(EscapedLocals.size());
    for (auto &Pair : EscapedLocals)
      EscapeArgs[Pair.second] = Pair.first;
    llvm::Function *FrameEscapeFn = llvm::Intrinsic::getOrInsertDeclaration(
        &CGM.getModule(), llvm::Intrinsic::localescape);
    CGBuilderTy(*this, AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
  }

  // Remove the AllocaInsertPt instruction, which is just a convenience for us.
  llvm::Instruction *Ptr = AllocaInsertPt;
  AllocaInsertPt = nullptr;
  Ptr->eraseFromParent();

  // PostAllocaInsertPt, if created, was lazily created when it was required,
  // remove it now since it was just created for our own convenience.
  if (PostAllocaInsertPt) {
    llvm::Instruction *PostPtr = PostAllocaInsertPt;
    PostAllocaInsertPt = nullptr;
    PostPtr->eraseFromParent();
  }

  // If someone took the address of a label but never did an indirect goto, we
  // made a zero entry PHI node, which is illegal, zap it now.
  if (IndirectBranch) {
    llvm::PHINode *PN = cast<llvm::PHINode>(IndirectBranch->getAddress());
    if (PN->getNumIncomingValues() == 0) {
      PN->replaceAllUsesWith(llvm::PoisonValue::get(PN->getType()));
      PN->eraseFromParent();
    }
  }

  EmitIfUsed(*this, EHResumeBlock);
  EmitIfUsed(*this, TerminateLandingPad);
  EmitIfUsed(*this, TerminateHandler);
  EmitIfUsed(*this, UnreachableBlock);

  for (const auto &FuncletAndParent : TerminateFunclets)
    EmitIfUsed(*this, FuncletAndParent.second);

  if (CGM.getCodeGenOpts().EmitDeclMetadata)
    EmitDeclMetadata();

  for (const auto &R : DeferredReplacements) {
    if (llvm::Value *Old = R.first) {
      Old->replaceAllUsesWith(R.second);
      cast<llvm::Instruction>(Old)->eraseFromParent();
    }
  }
  DeferredReplacements.clear();

  // Eliminate CleanupDestSlot alloca by replacing it with SSA values and
  // PHIs if the current function is a coroutine. We don't do it for all
  // functions as it may result in slight increase in numbers of instructions
  // if compiled with no optimizations. We do it for coroutine as the lifetime
  // of CleanupDestSlot alloca make correct coroutine frame building very
  // difficult.
  if (NormalCleanupDest.isValid() && isCoroutine()) {
    llvm::DominatorTree DT(*CurFn);
    llvm::PromoteMemToReg(
        cast<llvm::AllocaInst>(NormalCleanupDest.getPointer()), DT);
    NormalCleanupDest = Address::invalid();
  }

  // Scan function arguments for vector width.
  for (llvm::Argument &A : CurFn->args())
    if (auto *VT = dyn_cast<llvm::VectorType>(A.getType()))
      LargestVectorWidth =
          std::max((uint64_t)LargestVectorWidth,
                   VT->getPrimitiveSizeInBits().getKnownMinValue());

  // Update vector width based on return type.
  if (auto *VT = dyn_cast<llvm::VectorType>(CurFn->getReturnType()))
    LargestVectorWidth =
        std::max((uint64_t)LargestVectorWidth,
                 VT->getPrimitiveSizeInBits().getKnownMinValue());

  if (CurFnInfo->getMaxVectorWidth() > LargestVectorWidth)
    LargestVectorWidth = CurFnInfo->getMaxVectorWidth();

  // Add the min-legal-vector-width attribute. This contains the max width from:
  // 1. min-vector-width attribute used in the source program.
  // 2. Any builtins used that have a vector width specified.
  // 3. Values passed in and out of inline assembly.
  // 4. Width of vector arguments and return types for this function.
  // 5. Width of vector arguments and return types for functions called by this
  //    function.
  if (getContext().getTargetInfo().getTriple().isX86())
    CurFn->addFnAttr("min-legal-vector-width",
                     llvm::utostr(LargestVectorWidth));

  // If we generated an unreachable return block, delete it now.
  if (ReturnBlock.isValid() && ReturnBlock.getBlock()->use_empty()) {
    Builder.ClearInsertionPoint();
    ReturnBlock.getBlock()->eraseFromParent();
  }
  if (ReturnValue.isValid()) {
    auto *RetAlloca =
        dyn_cast<llvm::AllocaInst>(ReturnValue.emitRawPointer(*this));
    if (RetAlloca && RetAlloca->use_empty()) {
      RetAlloca->eraseFromParent();
      ReturnValue = Address::invalid();
    }
  }
}

/// ShouldInstrumentFunction - Return true if the current function should be
/// instrumented with __cyg_profile_func_* calls
bool CodeGenFunction::ShouldInstrumentFunction() {
  if (!CGM.getCodeGenOpts().InstrumentFunctions &&
      !CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining &&
      !CGM.getCodeGenOpts().InstrumentFunctionEntryBare)
    return false;
  if (!CurFuncDecl || CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>())
    return false;
  return true;
}

bool CodeGenFunction::ShouldSkipSanitizerInstrumentation() {
  if (!CurFuncDecl)
    return false;
  return CurFuncDecl->hasAttr<DisableSanitizerInstrumentationAttr>();
}

/// ShouldXRayInstrument - Return true if the current function should be
/// instrumented with XRay nop sleds.
bool CodeGenFunction::ShouldXRayInstrumentFunction() const {
  return CGM.getCodeGenOpts().XRayInstrumentFunctions;
}

/// AlwaysEmitXRayCustomEvents - Return true if we should emit IR for calls to
/// the __xray_customevent(...) builtin calls, when doing XRay instrumentation.
bool CodeGenFunction::AlwaysEmitXRayCustomEvents() const {
  return CGM.getCodeGenOpts().XRayInstrumentFunctions &&
         (CGM.getCodeGenOpts().XRayAlwaysEmitCustomEvents ||
          CGM.getCodeGenOpts().XRayInstrumentationBundle.Mask ==
              XRayInstrKind::Custom);
}

bool CodeGenFunction::AlwaysEmitXRayTypedEvents() const {
  return CGM.getCodeGenOpts().XRayInstrumentFunctions &&
         (CGM.getCodeGenOpts().XRayAlwaysEmitTypedEvents ||
          CGM.getCodeGenOpts().XRayInstrumentationBundle.Mask ==
              XRayInstrKind::Typed);
}

llvm::ConstantInt *
CodeGenFunction::getUBSanFunctionTypeHash(QualType Ty) const {
  // Remove any (C++17) exception specifications, to allow calling e.g. a
  // noexcept function through a non-noexcept pointer.
  if (!Ty->isFunctionNoProtoType())
    Ty = getContext().getFunctionTypeWithExceptionSpec(Ty, EST_None);
  std::string Mangled;
  llvm::raw_string_ostream Out(Mangled);
  CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out, false);
  return llvm::ConstantInt::get(
      CGM.Int32Ty, static_cast<uint32_t>(llvm::xxh3_64bits(Mangled)));
}

void CodeGenFunction::EmitKernelMetadata(const FunctionDecl *FD,
                                         llvm::Function *Fn) {
  if (!FD->hasAttr<OpenCLKernelAttr>() && !FD->hasAttr<CUDAGlobalAttr>())
    return;

  llvm::LLVMContext &Context = getLLVMContext();

  CGM.GenKernelArgMetadata(Fn, FD, this);

  if (!(getLangOpts().OpenCL ||
        (getLangOpts().CUDA &&
         getContext().getTargetInfo().getTriple().isSPIRV())))
    return;

  if (const VecTypeHintAttr *A = FD->getAttr<VecTypeHintAttr>()) {
    QualType HintQTy = A->getTypeHint();
    const ExtVectorType *HintEltQTy = HintQTy->getAs<ExtVectorType>();
    bool IsSignedInteger =
        HintQTy->isSignedIntegerType() ||
        (HintEltQTy && HintEltQTy->getElementType()->isSignedIntegerType());
    llvm::Metadata *AttrMDArgs[] = {
        llvm::ConstantAsMetadata::get(llvm::PoisonValue::get(
            CGM.getTypes().ConvertType(A->getTypeHint()))),
        llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
            llvm::IntegerType::get(Context, 32),
            llvm::APInt(32, (uint64_t)(IsSignedInteger ? 1 : 0))))};
    Fn->setMetadata("vec_type_hint", llvm::MDNode::get(Context, AttrMDArgs));
  }

  if (const WorkGroupSizeHintAttr *A = FD->getAttr<WorkGroupSizeHintAttr>()) {
    auto Eval = [&](Expr *E) {
      return E->EvaluateKnownConstInt(FD->getASTContext()).getExtValue();
    };
    llvm::Metadata *AttrMDArgs[] = {
        llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getXDim()))),
        llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getYDim()))),
        llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getZDim())))};
    Fn->setMetadata("work_group_size_hint", llvm::MDNode::get(Context, AttrMDArgs));
  }

  if (const ReqdWorkGroupSizeAttr *A = FD->getAttr<ReqdWorkGroupSizeAttr>()) {
    auto Eval = [&](Expr *E) {
      return E->EvaluateKnownConstInt(FD->getASTContext()).getExtValue();
    };
    llvm::Metadata *AttrMDArgs[] = {
        llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getXDim()))),
        llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getYDim()))),
        llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getZDim())))};
    Fn->setMetadata("reqd_work_group_size", llvm::MDNode::get(Context, AttrMDArgs));
  }

  if (const OpenCLIntelReqdSubGroupSizeAttr *A =
          FD->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) {
    llvm::Metadata *AttrMDArgs[] = {
        llvm::ConstantAsMetadata::get(Builder.getInt32(A->getSubGroupSize()))};
    Fn->setMetadata("intel_reqd_sub_group_size",
                    llvm::MDNode::get(Context, AttrMDArgs));
  }
}

/// Determine whether the function F ends with a return stmt.
static bool endsWithReturn(const Decl* F) {
  const Stmt *Body = nullptr;
  if (auto *FD = dyn_cast_or_null<FunctionDecl>(F))
    Body = FD->getBody();
  else if (auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(F))
    Body = OMD->getBody();

  if (auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
    auto LastStmt = CS->body_rbegin();
    if (LastStmt != CS->body_rend())
      return isa<ReturnStmt>(*LastStmt);
  }
  return false;
}

void CodeGenFunction::markAsIgnoreThreadCheckingAtRuntime(llvm::Function *Fn) {
  if (SanOpts.has(SanitizerKind::Thread)) {
    Fn->addFnAttr("sanitize_thread_no_checking_at_run_time");
    Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
  }
}

/// Check if the return value of this function requires sanitization.
bool CodeGenFunction::requiresReturnValueCheck() const {
  return requiresReturnValueNullabilityCheck() ||
         (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) && CurCodeDecl &&
          CurCodeDecl->getAttr<ReturnsNonNullAttr>());
}

static bool matchesStlAllocatorFn(const Decl *D, const ASTContext &Ctx) {
  auto *MD = dyn_cast_or_null<CXXMethodDecl>(D);
  if (!MD || !MD->getDeclName().getAsIdentifierInfo() ||
      !MD->getDeclName().getAsIdentifierInfo()->isStr("allocate") ||
      (MD->getNumParams() != 1 && MD->getNumParams() != 2))
    return false;

  if (MD->parameters()[0]->getType().getCanonicalType() != Ctx.getSizeType())
    return false;

  if (MD->getNumParams() == 2) {
    auto *PT = MD->parameters()[1]->getType()->getAs<PointerType>();
    if (!PT || !PT->isVoidPointerType() ||
        !PT->getPointeeType().isConstQualified())
      return false;
  }

  return true;
}

bool CodeGenFunction::isInAllocaArgument(CGCXXABI &ABI, QualType Ty) {
  const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
}

bool CodeGenFunction::hasInAllocaArg(const CXXMethodDecl *MD) {
  return getTarget().getTriple().getArch() == llvm::Triple::x86 &&
         getTarget().getCXXABI().isMicrosoft() &&
         llvm::any_of(MD->parameters(), [&](ParmVarDecl *P) {
           return isInAllocaArgument(CGM.getCXXABI(), P->getType());
         });
}

/// Return the UBSan prologue signature for \p FD if one is available.
static llvm::Constant *getPrologueSignature(CodeGenModule &CGM,
                                            const FunctionDecl *FD) {
  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
    if (!MD->isStatic())
      return nullptr;
  return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM);
}

void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
                                    llvm::Function *Fn,
                                    const CGFunctionInfo &FnInfo,
                                    const FunctionArgList &Args,
                                    SourceLocation Loc,
                                    SourceLocation StartLoc) {
  assert(!CurFn &&
         "Do not use a CodeGenFunction object for more than one function");

  const Decl *D = GD.getDecl();

  DidCallStackSave = false;
  CurCodeDecl = D;
  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
  if (FD && FD->usesSEHTry())
    CurSEHParent = GD;
  CurFuncDecl = (D ? D->getNonClosureContext() : nullptr);
  FnRetTy = RetTy;
  CurFn = Fn;
  CurFnInfo = &FnInfo;
  assert(CurFn->isDeclaration() && "Function already has body?");

  // If this function is ignored for any of the enabled sanitizers,
  // disable the sanitizer for the function.
  do {
#define SANITIZER(NAME, ID)                                                    \
  if (SanOpts.empty())                                                         \
    break;                                                                     \
  if (SanOpts.has(SanitizerKind::ID))                                          \
    if (CGM.isInNoSanitizeList(SanitizerKind::ID, Fn, Loc))                    \
      SanOpts.set(SanitizerKind::ID, false);

#include "clang/Basic/Sanitizers.def"
#undef SANITIZER
  } while (false);

  if (D) {
    const bool SanitizeBounds = SanOpts.hasOneOf(SanitizerKind::Bounds);
    SanitizerMask no_sanitize_mask;
    bool NoSanitizeCoverage = false;

    for (auto *Attr : D->specific_attrs<NoSanitizeAttr>()) {
      no_sanitize_mask |= Attr->getMask();
      // SanitizeCoverage is not handled by SanOpts.
      if (Attr->hasCoverage())
        NoSanitizeCoverage = true;
    }

    // Apply the no_sanitize* attributes to SanOpts.
    SanOpts.Mask &= ~no_sanitize_mask;
    if (no_sanitize_mask & SanitizerKind::Address)
      SanOpts.set(SanitizerKind::KernelAddress, false);
    if (no_sanitize_mask & SanitizerKind::KernelAddress)
      SanOpts.set(SanitizerKind::Address, false);
    if (no_sanitize_mask & SanitizerKind::HWAddress)
      SanOpts.set(SanitizerKind::KernelHWAddress, false);
    if (no_sanitize_mask & SanitizerKind::KernelHWAddress)
      SanOpts.set(SanitizerKind::HWAddress, false);

    if (SanitizeBounds && !SanOpts.hasOneOf(SanitizerKind::Bounds))
      Fn->addFnAttr(llvm::Attribute::NoSanitizeBounds);

    if (NoSanitizeCoverage && CGM.getCodeGenOpts().hasSanitizeCoverage())
      Fn->addFnAttr(llvm::Attribute::NoSanitizeCoverage);

    // Some passes need the non-negated no_sanitize attribute. Pass them on.
    if (CGM.getCodeGenOpts().hasSanitizeBinaryMetadata()) {
      if (no_sanitize_mask & SanitizerKind::Thread)
        Fn->addFnAttr("no_sanitize_thread");
    }
  }

  if (ShouldSkipSanitizerInstrumentation()) {
    CurFn->addFnAttr(llvm::Attribute::DisableSanitizerInstrumentation);
  } else {
    // Apply sanitizer attributes to the function.
    if (SanOpts.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress))
      Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
    if (SanOpts.hasOneOf(SanitizerKind::HWAddress |
                         SanitizerKind::KernelHWAddress))
      Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
    if (SanOpts.has(SanitizerKind::MemtagStack))
      Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
    if (SanOpts.has(SanitizerKind::Thread))
      Fn->addFnAttr(llvm::Attribute::SanitizeThread);
    if (SanOpts.has(SanitizerKind::Type))
      Fn->addFnAttr(llvm::Attribute::SanitizeType);
    if (SanOpts.has(SanitizerKind::NumericalStability))
      Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);
    if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory))
      Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
  }
  if (SanOpts.has(SanitizerKind::SafeStack))
    Fn->addFnAttr(llvm::Attribute::SafeStack);
  if (SanOpts.has(SanitizerKind::ShadowCallStack))
    Fn->addFnAttr(llvm::Attribute::ShadowCallStack);

  if (SanOpts.has(SanitizerKind::Realtime))
    if (FD && FD->getASTContext().hasAnyFunctionEffects())
      for (const FunctionEffectWithCondition &Fe : FD->getFunctionEffects()) {
        if (Fe.Effect.kind() == FunctionEffect::Kind::NonBlocking)
          Fn->addFnAttr(llvm::Attribute::SanitizeRealtime);
        else if (Fe.Effect.kind() == FunctionEffect::Kind::Blocking)
          Fn->addFnAttr(llvm::Attribute::SanitizeRealtimeBlocking);
      }

  // Apply fuzzing attribute to the function.
  if (SanOpts.hasOneOf(SanitizerKind::Fuzzer | SanitizerKind::FuzzerNoLink))
    Fn->addFnAttr(llvm::Attribute::OptForFuzzing);

  // Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize,
  // .cxx_destruct, __destroy_helper_block_ and all of their calees at run time.
  if (SanOpts.has(SanitizerKind::Thread)) {
    if (const auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) {
      const IdentifierInfo *II = OMD->getSelector().getIdentifierInfoForSlot(0);
      if (OMD->getMethodFamily() == OMF_dealloc ||
          OMD->getMethodFamily() == OMF_initialize ||
          (OMD->getSelector().isUnarySelector() && II->isStr(".cxx_destruct"))) {
        markAsIgnoreThreadCheckingAtRuntime(Fn);
      }
    }
  }

  // Ignore unrelated casts in STL allocate() since the allocator must cast
  // from void* to T* before object initialization completes. Don't match on the
  // namespace because not all allocators are in std::
  if (D && SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
    if (matchesStlAllocatorFn(D, getContext()))
      SanOpts.Mask &= ~SanitizerKind::CFIUnrelatedCast;
  }

  // Ignore null checks in coroutine functions since the coroutines passes
  // are not aware of how to move the extra UBSan instructions across the split
  // coroutine boundaries.
  if (D && SanOpts.has(SanitizerKind::Null))
    if (FD && FD->getBody() &&
        FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass)
      SanOpts.Mask &= ~SanitizerKind::Null;

  // Add pointer authentication attributes.
  const CodeGenOptions &CodeGenOpts = CGM.getCodeGenOpts();
  if (CodeGenOpts.PointerAuth.ReturnAddresses)
    Fn->addFnAttr("ptrauth-returns");
  if (CodeGenOpts.PointerAuth.FunctionPointers)
    Fn->addFnAttr("ptrauth-calls");
  if (CodeGenOpts.PointerAuth.AuthTraps)
    Fn->addFnAttr("ptrauth-auth-traps");
  if (CodeGenOpts.PointerAuth.IndirectGotos)
    Fn->addFnAttr("ptrauth-indirect-gotos");
  if (CodeGenOpts.PointerAuth.AArch64JumpTableHardening)
    Fn->addFnAttr("aarch64-jump-table-hardening");

  // Apply xray attributes to the function (as a string, for now)
  bool AlwaysXRayAttr = false;
  if (const auto *XRayAttr = D ? D->getAttr<XRayInstrumentAttr>() : nullptr) {
    if (CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
            XRayInstrKind::FunctionEntry) ||
        CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
            XRayInstrKind::FunctionExit)) {
      if (XRayAttr->alwaysXRayInstrument() && ShouldXRayInstrumentFunction()) {
        Fn->addFnAttr("function-instrument", "xray-always");
        AlwaysXRayAttr = true;
      }
      if (XRayAttr->neverXRayInstrument())
        Fn->addFnAttr("function-instrument", "xray-never");
      if (const auto *LogArgs = D->getAttr<XRayLogArgsAttr>())
        if (ShouldXRayInstrumentFunction())
          Fn->addFnAttr("xray-log-args",
                        llvm::utostr(LogArgs->getArgumentCount()));
    }
  } else {
    if (ShouldXRayInstrumentFunction() && !CGM.imbueXRayAttrs(Fn, Loc))
      Fn->addFnAttr(
          "xray-instruction-threshold",
          llvm::itostr(CGM.getCodeGenOpts().XRayInstructionThreshold));
  }

  if (ShouldXRayInstrumentFunction()) {
    if (CGM.getCodeGenOpts().XRayIgnoreLoops)
      Fn->addFnAttr("xray-ignore-loops");

    if (!CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
            XRayInstrKind::FunctionExit))
      Fn->addFnAttr("xray-skip-exit");

    if (!CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
            XRayInstrKind::FunctionEntry))
      Fn->addFnAttr("xray-skip-entry");

    auto FuncGroups = CGM.getCodeGenOpts().XRayTotalFunctionGroups;
    if (FuncGroups > 1) {
      auto FuncName = llvm::ArrayRef<uint8_t>(CurFn->getName().bytes_begin(),
                                              CurFn->getName().bytes_end());
      auto Group = crc32(FuncName) % FuncGroups;
      if (Group != CGM.getCodeGenOpts().XRaySelectedFunctionGroup &&
          !AlwaysXRayAttr)
        Fn->addFnAttr("function-instrument", "xray-never");
    }
  }

  if (CGM.getCodeGenOpts().getProfileInstr() != CodeGenOptions::ProfileNone) {
    switch (CGM.isFunctionBlockedFromProfileInstr(Fn, Loc)) {
    case ProfileList::Skip:
      Fn->addFnAttr(llvm::Attribute::SkipProfile);
      break;
    case ProfileList::Forbid:
      Fn->addFnAttr(llvm::Attribute::NoProfile);
      break;
    case ProfileList::Allow:
      break;
    }
  }

  unsigned Count, Offset;
  StringRef Section;
  if (const auto *Attr =
          D ? D->getAttr<PatchableFunctionEntryAttr>() : nullptr) {
    Count = Attr->getCount();
    Offset = Attr->getOffset();
    Section = Attr->getSection();
  } else {
    Count = CGM.getCodeGenOpts().PatchableFunctionEntryCount;
    Offset = CGM.getCodeGenOpts().PatchableFunctionEntryOffset;
  }
  if (Section.empty())
    Section = CGM.getCodeGenOpts().PatchableFunctionEntrySection;
  if (Count && Offset <= Count) {
    Fn->addFnAttr("patchable-function-entry", std::to_string(Count - Offset));
    if (Offset)
      Fn->addFnAttr("patchable-function-prefix", std::to_string(Offset));
    if (!Section.empty())
      Fn->addFnAttr("patchable-function-entry-section", Section);
  }
  // Instruct that functions for COFF/CodeView targets should start with a
  // patchable instruction, but only on x86/x64. Don't forward this to ARM/ARM64
  // backends as they don't need it -- instructions on these architectures are
  // always atomically patchable at runtime.
  if (CGM.getCodeGenOpts().HotPatch &&
      getContext().getTargetInfo().getTriple().isX86() &&
      getContext().getTargetInfo().getTriple().getEnvironment() !=
          llvm::Triple::CODE16)
    Fn->addFnAttr("patchable-function", "prologue-short-redirect");

  // Add no-jump-tables value.
  if (CGM.getCodeGenOpts().NoUseJumpTables)
    Fn->addFnAttr("no-jump-tables", "true");

  // Add no-inline-line-tables value.
  if (CGM.getCodeGenOpts().NoInlineLineTables)
    Fn->addFnAttr("no-inline-line-tables");

  // Add profile-sample-accurate value.
  if (CGM.getCodeGenOpts().ProfileSampleAccurate)
    Fn->addFnAttr("profile-sample-accurate");

  if (!CGM.getCodeGenOpts().SampleProfileFile.empty())
    Fn->addFnAttr("use-sample-profile");

  if (D && D->hasAttr<CFICanonicalJumpTableAttr>())
    Fn->addFnAttr("cfi-canonical-jump-table");

  if (D && D->hasAttr<NoProfileFunctionAttr>())
    Fn->addFnAttr(llvm::Attribute::NoProfile);

  if (D && D->hasAttr<HybridPatchableAttr>())
    Fn->addFnAttr(llvm::Attribute::HybridPatchable);

  if (D) {
    // Function attributes take precedence over command line flags.
    if (auto *A = D->getAttr<FunctionReturnThunksAttr>()) {
      switch (A->getThunkType()) {
      case FunctionReturnThunksAttr::Kind::Keep:
        break;
      case FunctionReturnThunksAttr::Kind::Extern:
        Fn->addFnAttr(llvm::Attribute::FnRetThunkExtern);
        break;
      }
    } else if (CGM.getCodeGenOpts().FunctionReturnThunks)
      Fn->addFnAttr(llvm::Attribute::FnRetThunkExtern);
  }

  if (FD && (getLangOpts().OpenCL ||
             (getLangOpts().CUDA &&
              getContext().getTargetInfo().getTriple().isSPIRV()) ||
             ((getLangOpts().HIP || getLangOpts().OffloadViaLLVM) &&
              getLangOpts().CUDAIsDevice))) {
    // Add metadata for a kernel function.
    EmitKernelMetadata(FD, Fn);
  }

  if (FD && FD->hasAttr<ClspvLibclcBuiltinAttr>()) {
    Fn->setMetadata("clspv_libclc_builtin",
                    llvm::MDNode::get(getLLVMContext(), {}));
  }

  // If we are checking function types, emit a function type signature as
  // prologue data.
  if (FD && SanOpts.has(SanitizerKind::Function)) {
    if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) {
      llvm::LLVMContext &Ctx = Fn->getContext();
      llvm::MDBuilder MDB(Ctx);
      Fn->setMetadata(
          llvm::LLVMContext::MD_func_sanitize,
          MDB.createRTTIPointerPrologue(
              PrologueSig, getUBSanFunctionTypeHash(FD->getType())));
    }
  }

  // If we're checking nullability, we need to know whether we can check the
  // return value. Initialize the flag to 'true' and refine it in EmitParmDecl.
  if (SanOpts.has(SanitizerKind::NullabilityReturn)) {
    auto Nullability = FnRetTy->getNullability();
    if (Nullability && *Nullability == NullabilityKind::NonNull &&
        !FnRetTy->isRecordType()) {
      if (!(SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) &&
            CurCodeDecl && CurCodeDecl->getAttr<ReturnsNonNullAttr>()))
        RetValNullabilityPrecondition =
            llvm::ConstantInt::getTrue(getLLVMContext());
    }
  }

  // If we're in C++ mode and the function name is "main", it is guaranteed
  // to be norecurse by the standard (3.6.1.3 "The function main shall not be
  // used within a program").
  //
  // OpenCL C 2.0 v2.2-11 s6.9.i:
  //     Recursion is not supported.
  //
  // HLSL
  //     Recursion is not supported.
  //
  // SYCL v1.2.1 s3.10:
  //     kernels cannot include RTTI information, exception classes,
  //     recursive code, virtual functions or make use of C++ libraries that
  //     are not compiled for the device.
  if (FD &&
      ((getLangOpts().CPlusPlus && FD->isMain()) || getLangOpts().OpenCL ||
       getLangOpts().HLSL || getLangOpts().SYCLIsDevice ||
       (getLangOpts().CUDA && FD->hasAttr<CUDAGlobalAttr>())))
    Fn->addFnAttr(llvm::Attribute::NoRecurse);

  llvm::RoundingMode RM = getLangOpts().getDefaultRoundingMode();
  llvm::fp::ExceptionBehavior FPExceptionBehavior =
      ToConstrainedExceptMD(getLangOpts().getDefaultExceptionMode());
  Builder.setDefaultConstrainedRounding(RM);
  Builder.setDefaultConstrainedExcept(FPExceptionBehavior);
  if ((FD && (FD->UsesFPIntrin() || FD->hasAttr<StrictFPAttr>())) ||
      (!FD && (FPExceptionBehavior != llvm::fp::ebIgnore ||
               RM != llvm::RoundingMode::NearestTiesToEven))) {
    Builder.setIsFPConstrained(true);
    Fn->addFnAttr(llvm::Attribute::StrictFP);
  }

  // If a custom alignment is used, force realigning to this alignment on
  // any main function which certainly will need it.
  if (FD && ((FD->isMain() || FD->isMSVCRTEntryPoint()) &&
             CGM.getCodeGenOpts().StackAlignment))
    Fn->addFnAttr("stackrealign");

  // "main" doesn't need to zero out call-used registers.
  if (FD && FD->isMain())
    Fn->removeFnAttr("zero-call-used-regs");

  // Add vscale_range attribute if appropriate.
  std::optional<std::pair<unsigned, unsigned>> VScaleRange =
      getContext().getTargetInfo().getVScaleRange(
          getLangOpts(), FD ? IsArmStreamingFunction(FD, true) : false);
  if (VScaleRange) {
    CurFn->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
        getLLVMContext(), VScaleRange->first, VScaleRange->second));
  }

  llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn);

  // Create a marker to make it easy to insert allocas into the entryblock
  // later.  Don't create this with the builder, because we don't want it
  // folded.
  llvm::Value *Poison = llvm::PoisonValue::get(Int32Ty);
  AllocaInsertPt = new llvm::BitCastInst(Poison, Int32Ty, "allocapt", EntryBB);

  ReturnBlock = getJumpDestInCurrentScope("return");

  Builder.SetInsertPoint(EntryBB);

  // If we're checking the return value, allocate space for a pointer to a
  // precise source location of the checked return statement.
  if (requiresReturnValueCheck()) {
    ReturnLocation = CreateDefaultAlignTempAlloca(Int8PtrTy, "return.sloc.ptr");
    Builder.CreateStore(llvm::ConstantPointerNull::get(Int8PtrTy),
                        ReturnLocation);
  }

  // Emit subprogram debug descriptor.
  if (CGDebugInfo *DI = getDebugInfo()) {
    // Reconstruct the type from the argument list so that implicit parameters,
    // such as 'this' and 'vtt', show up in the debug info. Preserve the calling
    // convention.
    DI->emitFunctionStart(GD, Loc, StartLoc,
                          DI->getFunctionType(FD, RetTy, Args), CurFn,
                          CurFuncIsThunk);
  }

  if (ShouldInstrumentFunction()) {
    if (CGM.getCodeGenOpts().InstrumentFunctions)
      CurFn->addFnAttr("instrument-function-entry", "__cyg_profile_func_enter");
    if (CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining)
      CurFn->addFnAttr("instrument-function-entry-inlined",
                       "__cyg_profile_func_enter");
    if (CGM.getCodeGenOpts().InstrumentFunctionEntryBare)
      CurFn->addFnAttr("instrument-function-entry-inlined",
                       "__cyg_profile_func_enter_bare");
  }

  // Since emitting the mcount call here impacts optimizations such as function
  // inlining, we just add an attribute to insert a mcount call in backend.
  // The attribute "counting-function" is set to mcount function name which is
  // architecture dependent.
  if (CGM.getCodeGenOpts().InstrumentForProfiling) {
    // Calls to fentry/mcount should not be generated if function has
    // the no_instrument_function attribute.
    if (!CurFuncDecl || !CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>()) {
      if (CGM.getCodeGenOpts().CallFEntry)
        Fn->addFnAttr("fentry-call", "true");
      else {
        Fn->addFnAttr("instrument-function-entry-inlined",
                      getTarget().getMCountName());
      }
      if (CGM.getCodeGenOpts().MNopMCount) {
        if (!CGM.getCodeGenOpts().CallFEntry)
          CGM.getDiags().Report(diag::err_opt_not_valid_without_opt)
            << "-mnop-mcount" << "-mfentry";
        Fn->addFnAttr("mnop-mcount");
      }

      if (CGM.getCodeGenOpts().RecordMCount) {
        if (!CGM.getCodeGenOpts().CallFEntry)
          CGM.getDiags().Report(diag::err_opt_not_valid_without_opt)
            << "-mrecord-mcount" << "-mfentry";
        Fn->addFnAttr("mrecord-mcount");
      }
    }
  }

  if (CGM.getCodeGenOpts().PackedStack) {
    if (getContext().getTargetInfo().getTriple().getArch() !=
        llvm::Triple::systemz)
      CGM.getDiags().Report(diag::err_opt_not_valid_on_target)
        << "-mpacked-stack";
    Fn->addFnAttr("packed-stack");
  }

  if (CGM.getCodeGenOpts().WarnStackSize != UINT_MAX &&
      !CGM.getDiags().isIgnored(diag::warn_fe_backend_frame_larger_than, Loc))
    Fn->addFnAttr("warn-stack-size",
                  std::to_string(CGM.getCodeGenOpts().WarnStackSize));

  if (RetTy->isVoidType()) {
    // Void type; nothing to return.
    ReturnValue = Address::invalid();

    // Count the implicit return.
    if (!endsWithReturn(D))
      ++NumReturnExprs;
  } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) {
    // Indirect return; emit returned value directly into sret slot.
    // This reduces code size, and affects correctness in C++.
    auto AI = CurFn->arg_begin();
    if (CurFnInfo->getReturnInfo().isSRetAfterThis())
      ++AI;
    ReturnValue = makeNaturalAddressForPointer(
        &*AI, RetTy, CurFnInfo->getReturnInfo().getIndirectAlign(), false,
        nullptr, nullptr, KnownNonNull);
    if (!CurFnInfo->getReturnInfo().getIndirectByVal()) {
      ReturnValuePointer =
          CreateDefaultAlignTempAlloca(ReturnValue.getType(), "result.ptr");
      Builder.CreateStore(ReturnValue.emitRawPointer(*this),
                          ReturnValuePointer);
    }
  } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca &&
             !hasScalarEvaluationKind(CurFnInfo->getReturnType())) {
    // Load the sret pointer from the argument struct and return into that.
    unsigned Idx = CurFnInfo->getReturnInfo().getInAllocaFieldIndex();
    llvm::Function::arg_iterator EI = CurFn->arg_end();
    --EI;
    llvm::Value *Addr = Builder.CreateStructGEP(
        CurFnInfo->getArgStruct(), &*EI, Idx);
    llvm::Type *Ty =
        cast<llvm::GetElementPtrInst>(Addr)->getResultElementType();
    ReturnValuePointer = Address(Addr, Ty, getPointerAlign());
    Addr = Builder.CreateAlignedLoad(Ty, Addr, getPointerAlign(), "agg.result");
    ReturnValue = Address(Addr, ConvertType(RetTy),
                          CGM.getNaturalTypeAlignment(RetTy), KnownNonNull);
  } else {
    ReturnValue = CreateIRTemp(RetTy, "retval");

    // Tell the epilog emitter to autorelease the result.  We do this
    // now so that various specialized functions can suppress it
    // during their IR-generation.
    if (getLangOpts().ObjCAutoRefCount &&
        !CurFnInfo->isReturnsRetained() &&
        RetTy->isObjCRetainableType())
      AutoreleaseResult = true;
  }

  EmitStartEHSpec(CurCodeDecl);

  PrologueCleanupDepth = EHStack.stable_begin();

  // Emit OpenMP specific initialization of the device functions.
  if (getLangOpts().OpenMP && CurCodeDecl)
    CGM.getOpenMPRuntime().emitFunctionProlog(*this, CurCodeDecl);

  if (FD && getLangOpts().HLSL) {
    // Handle emitting HLSL entry functions.
    if (FD->hasAttr<HLSLShaderAttr>()) {
      CGM.getHLSLRuntime().emitEntryFunction(FD, Fn);
    }
    CGM.getHLSLRuntime().setHLSLFunctionAttributes(FD, Fn);
  }

  EmitFunctionProlog(*CurFnInfo, CurFn, Args);

  if (const CXXMethodDecl *MD = dyn_cast_if_present<CXXMethodDecl>(D);
      MD && !MD->isStatic()) {
    bool IsInLambda =
        MD->getParent()->isLambda() && MD->getOverloadedOperator() == OO_Call;
    if (MD->isImplicitObjectMemberFunction())
      CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
    if (IsInLambda) {
      // We're in a lambda; figure out the captures.
      MD->getParent()->getCaptureFields(LambdaCaptureFields,
                                        LambdaThisCaptureField);
      if (LambdaThisCaptureField) {
        // If the lambda captures the object referred to by '*this' - either by
        // value or by reference, make sure CXXThisValue points to the correct
        // object.

        // Get the lvalue for the field (which is a copy of the enclosing object
        // or contains the address of the enclosing object).
        LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField);
        if (!LambdaThisCaptureField->getType()->isPointerType()) {
          // If the enclosing object was captured by value, just use its
          // address. Sign this pointer.
          CXXThisValue = ThisFieldLValue.getPointer(*this);
        } else {
          // Load the lvalue pointed to by the field, since '*this' was captured
          // by reference.
          CXXThisValue =
              EmitLoadOfLValue(ThisFieldLValue, SourceLocation()).getScalarVal();
        }
      }
      for (auto *FD : MD->getParent()->fields()) {
        if (FD->hasCapturedVLAType()) {
          auto *ExprArg = EmitLoadOfLValue(EmitLValueForLambdaField(FD),
                                           SourceLocation()).getScalarVal();
          auto VAT = FD->getCapturedVLAType();
          VLASizeMap[VAT->getSizeExpr()] = ExprArg;
        }
      }
    } else if (MD->isImplicitObjectMemberFunction()) {
      // Not in a lambda; just use 'this' from the method.
      // FIXME: Should we generate a new load for each use of 'this'?  The
      // fast register allocator would be happier...
      CXXThisValue = CXXABIThisValue;
    }

    // Check the 'this' pointer once per function, if it's available.
    if (CXXABIThisValue) {
      SanitizerSet SkippedChecks;
      SkippedChecks.set(SanitizerKind::ObjectSize, true);
      QualType ThisTy = MD->getThisType();

      // If this is the call operator of a lambda with no captures, it
      // may have a static invoker function, which may call this operator with
      // a null 'this' pointer.
      if (isLambdaCallOperator(MD) && MD->getParent()->isCapturelessLambda())
        SkippedChecks.set(SanitizerKind::Null, true);

      EmitTypeCheck(
          isa<CXXConstructorDecl>(MD) ? TCK_ConstructorCall : TCK_MemberCall,
          Loc, CXXABIThisValue, ThisTy, CXXABIThisAlignment, SkippedChecks);
    }
  }

  // If any of the arguments have a variably modified type, make sure to
  // emit the type size, but only if the function is not naked. Naked functions
  // have no prolog to run this evaluation.
  if (!FD || !FD->hasAttr<NakedAttr>()) {
    for (const VarDecl *VD : Args) {
      // Dig out the type as written from ParmVarDecls; it's unclear whether
      // the standard (C99 6.9.1p10) requires this, but we're following the
      // precedent set by gcc.
      QualType Ty;
      if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD))
        Ty = PVD->getOriginalType();
      else
        Ty = VD->getType();

      if (Ty->isVariablyModifiedType())
        EmitVariablyModifiedType(Ty);
    }
  }
  // Emit a location at the end of the prologue.
  if (CGDebugInfo *DI = getDebugInfo())
    DI->EmitLocation(Builder, StartLoc);
  // TODO: Do we need to handle this in two places like we do with
  // target-features/target-cpu?
  if (CurFuncDecl)
    if (const auto *VecWidth = CurFuncDecl->getAttr<MinVectorWidthAttr>())
      LargestVectorWidth = VecWidth->getVectorWidth();

  if (CGM.shouldEmitConvergenceTokens())
    ConvergenceTokenStack.push_back(getOrEmitConvergenceEntryToken(CurFn));
}

void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
  incrementProfileCounter(Body);
  maybeCreateMCDCCondBitmap();
  if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
    EmitCompoundStmtWithoutScope(*S);
  else
    EmitStmt(Body);
}

/// When instrumenting to collect profile data, the counts for some blocks
/// such as switch cases need to not include the fall-through counts, so
/// emit a branch around the instrumentation code. When not instrumenting,
/// this just calls EmitBlock().
void CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB,
                                               const Stmt *S) {
  llvm::BasicBlock *SkipCountBB = nullptr;
  // Do not skip over the instrumentation when single byte coverage mode is
  // enabled.
  if (HaveInsertPoint() && CGM.getCodeGenOpts().hasProfileClangInstr() &&
      !llvm::EnableSingleByteCoverage) {
    // When instrumenting for profiling, the fallthrough to certain
    // statements needs to skip over the instrumentation code so that we
    // get an accurate count.
    SkipCountBB = createBasicBlock("skipcount");
    EmitBranch(SkipCountBB);
  }
  EmitBlock(BB);
  uint64_t CurrentCount = getCurrentProfileCount();
  incrementProfileCounter(S);
  setCurrentProfileCount(getCurrentProfileCount() + CurrentCount);
  if (SkipCountBB)
    EmitBlock(SkipCountBB);
}

/// Tries to mark the given function nounwind based on the
/// non-existence of any throwing calls within it.  We believe this is
/// lightweight enough to do at -O0.
static void TryMarkNoThrow(llvm::Function *F) {
  // LLVM treats 'nounwind' on a function as part of the type, so we
  // can't do this on functions that can be overwritten.
  if (F->isInterposable()) return;

  for (llvm::BasicBlock &BB : *F)
    for (llvm::Instruction &I : BB)
      if (I.mayThrow())
        return;

  F->setDoesNotThrow();
}

QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD,
                                               FunctionArgList &Args) {
  const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
  QualType ResTy = FD->getReturnType();

  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
  if (MD && MD->isImplicitObjectMemberFunction()) {
    if (CGM.getCXXABI().HasThisReturn(GD))
      ResTy = MD->getThisType();
    else if (CGM.getCXXABI().hasMostDerivedReturn(GD))
      ResTy = CGM.getContext().VoidPtrTy;
    CGM.getCXXABI().buildThisParam(*this, Args);
  }

  // The base version of an inheriting constructor whose constructed base is a
  // virtual base is not passed any arguments (because it doesn't actually call
  // the inherited constructor).
  bool PassedParams = true;
  if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD))
    if (auto Inherited = CD->getInheritedConstructor())
      PassedParams =
          getTypes().inheritingCtorHasParams(Inherited, GD.getCtorType());

  if (PassedParams) {
    for (auto *Param : FD->parameters()) {
      Args.push_back(Param);
      if (!Param->hasAttr<PassObjectSizeAttr>())
        continue;

      auto *Implicit = ImplicitParamDecl::Create(
          getContext(), Param->getDeclContext(), Param->getLocation(),
          /*Id=*/nullptr, getContext().getSizeType(), ImplicitParamKind::Other);
      SizeArguments[Param] = Implicit;
      Args.push_back(Implicit);
    }
  }

  if (MD && (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)))
    CGM.getCXXABI().addImplicitStructorParams(*this, ResTy, Args);

  return ResTy;
}

void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
                                   const CGFunctionInfo &FnInfo) {
  assert(Fn && "generating code for null Function");
  const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
  CurGD = GD;

  FunctionArgList Args;
  QualType ResTy = BuildFunctionArgList(GD, Args);

  CGM.getTargetCodeGenInfo().checkFunctionABI(CGM, FD);

  if (FD->isInlineBuiltinDeclaration()) {
    // When generating code for a builtin with an inline declaration, use a
    // mangled name to hold the actual body, while keeping an external
    // definition in case the function pointer is referenced somewhere.
    std::string FDInlineName = (Fn->getName() + ".inline").str();
    llvm::Module *M = Fn->getParent();
    llvm::Function *Clone = M->getFunction(FDInlineName);
    if (!Clone) {
      Clone = llvm::Function::Create(Fn->getFunctionType(),
                                     llvm::GlobalValue::InternalLinkage,
                                     Fn->getAddressSpace(), FDInlineName, M);
      Clone->addFnAttr(llvm::Attribute::AlwaysInline);
    }
    Fn->setLinkage(llvm::GlobalValue::ExternalLinkage);
    Fn = Clone;
  } else {
    // Detect the unusual situation where an inline version is shadowed by a
    // non-inline version. In that case we should pick the external one
    // everywhere. That's GCC behavior too. Unfortunately, I cannot find a way
    // to detect that situation before we reach codegen, so do some late
    // replacement.
    for (const FunctionDecl *PD = FD->getPreviousDecl(); PD;
         PD = PD->getPreviousDecl()) {
      if (LLVM_UNLIKELY(PD->isInlineBuiltinDeclaration())) {
        std::string FDInlineName = (Fn->getName() + ".inline").str();
        llvm::Module *M = Fn->getParent();
        if (llvm::Function *Clone = M->getFunction(FDInlineName)) {
          Clone->replaceAllUsesWith(Fn);
          Clone->eraseFromParent();
        }
        break;
      }
    }
  }

  // Check if we should generate debug info for this function.
  if (FD->hasAttr<NoDebugAttr>()) {
    // Clear non-distinct debug info that was possibly attached to the function
    // due to an earlier declaration without the nodebug attribute
    Fn->setSubprogram(nullptr);
    // Disable debug info indefinitely for this function
    DebugInfo = nullptr;
  }

  // The function might not have a body if we're generating thunks for a
  // function declaration.
  SourceRange BodyRange;
  if (Stmt *Body = FD->getBody())
    BodyRange = Body->getSourceRange();
  else
    BodyRange = FD->getLocation();
  CurEHLocation = BodyRange.getEnd();

  // Use the location of the start of the function to determine where
  // the function definition is located. By default use the location
  // of the declaration as the location for the subprogram. A function
  // may lack a declaration in the source code if it is created by code
  // gen. (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk).
  SourceLocation Loc = FD->getLocation();

  // If this is a function specialization then use the pattern body
  // as the location for the function.
  if (const FunctionDecl *SpecDecl = FD->getTemplateInstantiationPattern())
    if (SpecDecl->hasBody(SpecDecl))
      Loc = SpecDecl->getLocation();

  Stmt *Body = FD->getBody();

  if (Body) {
    // Coroutines always emit lifetime markers.
    if (isa<CoroutineBodyStmt>(Body))
      ShouldEmitLifetimeMarkers = true;

    // Initialize helper which will detect jumps which can cause invalid
    // lifetime markers.
    if (ShouldEmitLifetimeMarkers)
      Bypasses.Init(CGM, Body);
  }

  // Emit the standard function prologue.
  StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());

  // Save parameters for coroutine function.
  if (Body && isa_and_nonnull<CoroutineBodyStmt>(Body))
    llvm::append_range(FnArgs, FD->parameters());

  // Ensure that the function adheres to the forward progress guarantee, which
  // is required by certain optimizations.
  // In C++11 and up, the attribute will be removed if the body contains a
  // trivial empty loop.
  if (checkIfFunctionMustProgress())
    CurFn->addFnAttr(llvm::Attribute::MustProgress);

  // Generate the body of the function.
  PGO.assignRegionCounters(GD, CurFn);
  if (isa<CXXDestructorDecl>(FD))
    EmitDestructorBody(Args);
  else if (isa<CXXConstructorDecl>(FD))
    EmitConstructorBody(Args);
  else if (getLangOpts().CUDA &&
           !getLangOpts().CUDAIsDevice &&
           FD->hasAttr<CUDAGlobalAttr>())
    CGM.getCUDARuntime().emitDeviceStub(*this, Args);
  else if (isa<CXXMethodDecl>(FD) &&
           cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {
    // The lambda static invoker function is special, because it forwards or
    // clones the body of the function call operator (but is actually static).
    EmitLambdaStaticInvokeBody(cast<CXXMethodDecl>(FD));
  } else if (isa<CXXMethodDecl>(FD) &&
             isLambdaCallOperator(cast<CXXMethodDecl>(FD)) &&
             !FnInfo.isDelegateCall() &&
             cast<CXXMethodDecl>(FD)->getParent()->getLambdaStaticInvoker() &&
             hasInAllocaArg(cast<CXXMethodDecl>(FD))) {
    // If emitting a lambda with static invoker on X86 Windows, change
    // the call operator body.
    // Make sure that this is a call operator with an inalloca arg and check
    // for delegate call to make sure this is the original call op and not the
    // new forwarding function for the static invoker.
    EmitLambdaInAllocaCallOpBody(cast<CXXMethodDecl>(FD));
  } else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) &&
             (cast<CXXMethodDecl>(FD)->isCopyAssignmentOperator() ||
              cast<CXXMethodDecl>(FD)->isMoveAssignmentOperator())) {
    // Implicit copy-assignment gets the same special treatment as implicit
    // copy-constructors.
    emitImplicitAssignmentOperatorBody(Args);
  } else if (Body) {
    EmitFunctionBody(Body);
  } else
    llvm_unreachable("no definition for emitted function");

  // C++11 [stmt.return]p2:
  //   Flowing off the end of a function [...] results in undefined behavior in
  //   a value-returning function.
  // C11 6.9.1p12:
  //   If the '}' that terminates a function is reached, and the value of the
  //   function call is used by the caller, the behavior is undefined.
  if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() && !SawAsmBlock &&
      !FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) {
    bool ShouldEmitUnreachable =
        CGM.getCodeGenOpts().StrictReturn ||
        !CGM.MayDropFunctionReturn(FD->getASTContext(), FD->getReturnType());
    if (SanOpts.has(SanitizerKind::Return)) {
      SanitizerScope SanScope(this);
      llvm::Value *IsFalse = Builder.getFalse();
      EmitCheck(std::make_pair(IsFalse, SanitizerKind::SO_Return),
                SanitizerHandler::MissingReturn,
                EmitCheckSourceLocation(FD->getLocation()), {});
    } else if (ShouldEmitUnreachable) {
      if (CGM.getCodeGenOpts().OptimizationLevel == 0)
        EmitTrapCall(llvm::Intrinsic::trap);
    }
    if (SanOpts.has(SanitizerKind::Return) || ShouldEmitUnreachable) {
      Builder.CreateUnreachable();
      Builder.ClearInsertionPoint();
    }
  }

  // Emit the standard function epilogue.
  FinishFunction(BodyRange.getEnd());

  PGO.verifyCounterMap();

  // If we haven't marked the function nothrow through other means, do
  // a quick pass now to see if we can.
  if (!CurFn->doesNotThrow())
    TryMarkNoThrow(CurFn);
}

/// ContainsLabel - Return true if the statement contains a label in it.  If
/// this statement is not executed normally, it not containing a label means
/// that we can just remove the code.
bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) {
  // Null statement, not a label!
  if (!S) return false;

  // If this is a label, we have to emit the code, consider something like:
  // if (0) {  ...  foo:  bar(); }  goto foo;
  //
  // TODO: If anyone cared, we could track __label__'s, since we know that you
  // can't jump to one from outside their declared region.
  if (isa<LabelStmt>(S))
    return true;

  // If this is a case/default statement, and we haven't seen a switch, we have
  // to emit the code.
  if (isa<SwitchCase>(S) && !IgnoreCaseStmts)
    return true;

  // If this is a switch statement, we want to ignore cases below it.
  if (isa<SwitchStmt>(S))
    IgnoreCaseStmts = true;

  // Scan subexpressions for verboten labels.
  for (const Stmt *SubStmt : S->children())
    if (ContainsLabel(SubStmt, IgnoreCaseStmts))
      return true;

  return false;
}

/// containsBreak - Return true if the statement contains a break out of it.
/// If the statement (recursively) contains a switch or loop with a break
/// inside of it, this is fine.
bool CodeGenFunction::containsBreak(const Stmt *S) {
  // Null statement, not a label!
  if (!S) return false;

  // If this is a switch or loop that defines its own break scope, then we can
  // include it and anything inside of it.
  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || isa<DoStmt>(S) ||
      isa<ForStmt>(S))
    return false;

  if (isa<BreakStmt>(S))
    return true;

  // Scan subexpressions for verboten breaks.
  for (const Stmt *SubStmt : S->children())
    if (containsBreak(SubStmt))
      return true;

  return false;
}

bool CodeGenFunction::mightAddDeclToScope(const Stmt *S) {
  if (!S) return false;

  // Some statement kinds add a scope and thus never add a decl to the current
  // scope. Note, this list is longer than the list of statements that might
  // have an unscoped decl nested within them, but this way is conservatively
  // correct even if more statement kinds are added.
  if (isa<IfStmt>(S) || isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
      isa<DoStmt>(S) || isa<ForStmt>(S) || isa<CompoundStmt>(S) ||
      isa<CXXForRangeStmt>(S) || isa<CXXTryStmt>(S) ||
      isa<ObjCForCollectionStmt>(S) || isa<ObjCAtTryStmt>(S))
    return false;

  if (isa<DeclStmt>(S))
    return true;

  for (const Stmt *SubStmt : S->children())
    if (mightAddDeclToScope(SubStmt))
      return true;

  return false;
}

/// ConstantFoldsToSimpleInteger - If the specified expression does not fold
/// to a constant, or if it does but contains a label, return false.  If it
/// constant folds return true and set the boolean result in Result.
bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
                                                   bool &ResultBool,
                                                   bool AllowLabels) {
  // If MC/DC is enabled, disable folding so that we can instrument all
  // conditions to yield complete test vectors. We still keep track of
  // folded conditions during region mapping and visualization.
  if (!AllowLabels && CGM.getCodeGenOpts().hasProfileClangInstr() &&
      CGM.getCodeGenOpts().MCDCCoverage)
    return false;

  llvm::APSInt ResultInt;
  if (!ConstantFoldsToSimpleInteger(Cond, ResultInt, AllowLabels))
    return false;

  ResultBool = ResultInt.getBoolValue();
  return true;
}

/// ConstantFoldsToSimpleInteger - If the specified expression does not fold
/// to a constant, or if it does but contains a label, return false.  If it
/// constant folds return true and set the folded value.
bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
                                                   llvm::APSInt &ResultInt,
                                                   bool AllowLabels) {
  // FIXME: Rename and handle conversion of other evaluatable things
  // to bool.
  Expr::EvalResult Result;
  if (!Cond->EvaluateAsInt(Result, getContext()))
    return false;  // Not foldable, not integer or not fully evaluatable.

  llvm::APSInt Int = Result.Val.getInt();
  if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond))
    return false;  // Contains a label.

  PGO.markStmtMaybeUsed(Cond);
  ResultInt = Int;
  return true;
}

/// Strip parentheses and simplistic logical-NOT operators.
const Expr *CodeGenFunction::stripCond(const Expr *C) {
  while (const UnaryOperator *Op = dyn_cast<UnaryOperator>(C->IgnoreParens())) {
    if (Op->getOpcode() != UO_LNot)
      break;
    C = Op->getSubExpr();
  }
  return C->IgnoreParens();
}

/// Determine whether the given condition is an instrumentable condition
/// (i.e. no "&&" or "||").
bool CodeGenFunction::isInstrumentedCondition(const Expr *C) {
  const BinaryOperator *BOp = dyn_cast<BinaryOperator>(stripCond(C));
  return (!BOp || !BOp->isLogicalOp());
}

/// EmitBranchToCounterBlock - Emit a conditional branch to a new block that
/// increments a profile counter based on the semantics of the given logical
/// operator opcode.  This is used to instrument branch condition coverage for
/// logical operators.
void CodeGenFunction::EmitBranchToCounterBlock(
    const Expr *Cond, BinaryOperator::Opcode LOp, llvm::BasicBlock *TrueBlock,
    llvm::BasicBlock *FalseBlock, uint64_t TrueCount /* = 0 */,
    Stmt::Likelihood LH /* =None */, const Expr *CntrIdx /* = nullptr */) {
  // If not instrumenting, just emit a branch.
  bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
  if (!InstrumentRegions || !isInstrumentedCondition(Cond))
    return EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount, LH);

  const Stmt *CntrStmt = (CntrIdx ? CntrIdx : Cond);

  llvm::BasicBlock *ThenBlock = nullptr;
  llvm::BasicBlock *ElseBlock = nullptr;
  llvm::BasicBlock *NextBlock = nullptr;

  // Create the block we'll use to increment the appropriate counter.
  llvm::BasicBlock *CounterIncrBlock = createBasicBlock("lop.rhscnt");

  // Set block pointers according to Logical-AND (BO_LAnd) semantics. This
  // means we need to evaluate the condition and increment the counter on TRUE:
  //
  // if (Cond)
  //   goto CounterIncrBlock;
  // else
  //   goto FalseBlock;
  //
  // CounterIncrBlock:
  //   Counter++;
  //   goto TrueBlock;

  if (LOp == BO_LAnd) {
    ThenBlock = CounterIncrBlock;
    ElseBlock = FalseBlock;
    NextBlock = TrueBlock;
  }

  // Set block pointers according to Logical-OR (BO_LOr) semantics. This means
  // we need to evaluate the condition and increment the counter on FALSE:
  //
  // if (Cond)
  //   goto TrueBlock;
  // else
  //   goto CounterIncrBlock;
  //
  // CounterIncrBlock:
  //   Counter++;
  //   goto FalseBlock;

  else if (LOp == BO_LOr) {
    ThenBlock = TrueBlock;
    ElseBlock = CounterIncrBlock;
    NextBlock = FalseBlock;
  } else {
    llvm_unreachable("Expected Opcode must be that of a Logical Operator");
  }

  // Emit Branch based on condition.
  EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, TrueCount, LH);

  // Emit the block containing the counter increment(s).
  EmitBlock(CounterIncrBlock);

  // Increment corresponding counter; if index not provided, use Cond as index.
  incrementProfileCounter(CntrStmt);

  // Go to the next block.
  EmitBranch(NextBlock);
}

/// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an if
/// statement) to the specified blocks.  Based on the condition, this might try
/// to simplify the codegen of the conditional based on the branch.
/// \param LH The value of the likelihood attribute on the True branch.
/// \param ConditionalOp Used by MC/DC code coverage to track the result of the
/// ConditionalOperator (ternary) through a recursive call for the operator's
/// LHS and RHS nodes.
void CodeGenFunction::EmitBranchOnBoolExpr(
    const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock,
    uint64_t TrueCount, Stmt::Likelihood LH, const Expr *ConditionalOp,
    const VarDecl *ConditionalDecl) {
  Cond = Cond->IgnoreParens();

  if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
    // Handle X && Y in a condition.
    if (CondBOp->getOpcode() == BO_LAnd) {
      MCDCLogOpStack.push_back(CondBOp);

      // If we have "1 && X", simplify the code.  "0 && X" would have constant
      // folded if the case was simple enough.
      bool ConstantBool = false;
      if (ConstantFoldsToSimpleInteger(CondBOp->getLHS(), ConstantBool) &&
          ConstantBool) {
        // br(1 && X) -> br(X).
        incrementProfileCounter(CondBOp);
        EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LAnd, TrueBlock,
                                 FalseBlock, TrueCount, LH);
        MCDCLogOpStack.pop_back();
        return;
      }

      // If we have "X && 1", simplify the code to use an uncond branch.
      // "X && 0" would have been constant folded to 0.
      if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) &&
          ConstantBool) {
        // br(X && 1) -> br(X).
        EmitBranchToCounterBlock(CondBOp->getLHS(), BO_LAnd, TrueBlock,
                                 FalseBlock, TrueCount, LH, CondBOp);
        MCDCLogOpStack.pop_back();
        return;
      }

      // Emit the LHS as a conditional.  If the LHS conditional is false, we
      // want to jump to the FalseBlock.
      llvm::BasicBlock *LHSTrue = createBasicBlock("land.lhs.true");
      // The counter tells us how often we evaluate RHS, and all of TrueCount
      // can be propagated to that branch.
      uint64_t RHSCount = getProfileCount(CondBOp->getRHS());

      ConditionalEvaluation eval(*this);
      {
        ApplyDebugLocation DL(*this, Cond);
        // Propagate the likelihood attribute like __builtin_expect
        // __builtin_expect(X && Y, 1) -> X and Y are likely
        // __builtin_expect(X && Y, 0) -> only Y is unlikely
        EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount,
                             LH == Stmt::LH_Unlikely ? Stmt::LH_None : LH);
        EmitBlock(LHSTrue);
      }

      incrementProfileCounter(CondBOp);
      setCurrentProfileCount(getProfileCount(CondBOp->getRHS()));

      // Any temporaries created here are conditional.
      eval.begin(*this);
      EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LAnd, TrueBlock,
                               FalseBlock, TrueCount, LH);
      eval.end(*this);
      MCDCLogOpStack.pop_back();
      return;
    }

    if (CondBOp->getOpcode() == BO_LOr) {
      MCDCLogOpStack.push_back(CondBOp);

      // If we have "0 || X", simplify the code.  "1 || X" would have constant
      // folded if the case was simple enough.
      bool ConstantBool = false;
      if (ConstantFoldsToSimpleInteger(CondBOp->getLHS(), ConstantBool) &&
          !ConstantBool) {
        // br(0 || X) -> br(X).
        incrementProfileCounter(CondBOp);
        EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LOr, TrueBlock,
                                 FalseBlock, TrueCount, LH);
        MCDCLogOpStack.pop_back();
        return;
      }

      // If we have "X || 0", simplify the code to use an uncond branch.
      // "X || 1" would have been constant folded to 1.
      if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) &&
          !ConstantBool) {
        // br(X || 0) -> br(X).
        EmitBranchToCounterBlock(CondBOp->getLHS(), BO_LOr, TrueBlock,
                                 FalseBlock, TrueCount, LH, CondBOp);
        MCDCLogOpStack.pop_back();
        return;
      }
      // Emit the LHS as a conditional.  If the LHS conditional is true, we
      // want to jump to the TrueBlock.
      llvm::BasicBlock *LHSFalse = createBasicBlock("lor.lhs.false");
      // We have the count for entry to the RHS and for the whole expression
      // being true, so we can divy up True count between the short circuit and
      // the RHS.
      uint64_t LHSCount =
          getCurrentProfileCount() - getProfileCount(CondBOp->getRHS());
      uint64_t RHSCount = TrueCount - LHSCount;

      ConditionalEvaluation eval(*this);
      {
        // Propagate the likelihood attribute like __builtin_expect
        // __builtin_expect(X || Y, 1) -> only Y is likely
        // __builtin_expect(X || Y, 0) -> both X and Y are unlikely
        ApplyDebugLocation DL(*this, Cond);
        EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount,
                             LH == Stmt::LH_Likely ? Stmt::LH_None : LH);
        EmitBlock(LHSFalse);
      }

      incrementProfileCounter(CondBOp);
      setCurrentProfileCount(getProfileCount(CondBOp->getRHS()));

      // Any temporaries created here are conditional.
      eval.begin(*this);
      EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LOr, TrueBlock, FalseBlock,
                               RHSCount, LH);

      eval.end(*this);
      MCDCLogOpStack.pop_back();
      return;
    }
  }

  if (const UnaryOperator *CondUOp = dyn_cast<UnaryOperator>(Cond)) {
    // br(!x, t, f) -> br(x, f, t)
    // Avoid doing this optimization when instrumenting a condition for MC/DC.
    // LNot is taken as part of the condition for simplicity, and changing its
    // sense negatively impacts test vector tracking.
    bool MCDCCondition = CGM.getCodeGenOpts().hasProfileClangInstr() &&
                         CGM.getCodeGenOpts().MCDCCoverage &&
                         isInstrumentedCondition(Cond);
    if (CondUOp->getOpcode() == UO_LNot && !MCDCCondition) {
      // Negate the count.
      uint64_t FalseCount = getCurrentProfileCount() - TrueCount;
      // The values of the enum are chosen to make this negation possible.
      LH = static_cast<Stmt::Likelihood>(-LH);
      // Negate the condition and swap the destination blocks.
      return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock,
                                  FalseCount, LH);
    }
  }

  if (const ConditionalOperator *CondOp = dyn_cast<ConditionalOperator>(Cond)) {
    // br(c ? x : y, t, f) -> br(c, br(x, t, f), br(y, t, f))
    llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true");
    llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false");

    // The ConditionalOperator itself has no likelihood information for its
    // true and false branches. This matches the behavior of __builtin_expect.
    ConditionalEvaluation cond(*this);
    EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock,
                         getProfileCount(CondOp), Stmt::LH_None);

    // When computing PGO branch weights, we only know the overall count for
    // the true block. This code is essentially doing tail duplication of the
    // naive code-gen, introducing new edges for which counts are not
    // available. Divide the counts proportionally between the LHS and RHS of
    // the conditional operator.
    uint64_t LHSScaledTrueCount = 0;
    if (TrueCount) {
      double LHSRatio =
          getProfileCount(CondOp) / (double)getCurrentProfileCount();
      LHSScaledTrueCount = TrueCount * LHSRatio;
    }

    cond.begin(*this);
    EmitBlock(LHSBlock);
    incrementProfileCounter(CondOp);
    {
      ApplyDebugLocation DL(*this, Cond);
      EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock,
                           LHSScaledTrueCount, LH, CondOp);
    }
    cond.end(*this);

    cond.begin(*this);
    EmitBlock(RHSBlock);
    EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock,
                         TrueCount - LHSScaledTrueCount, LH, CondOp);
    cond.end(*this);

    return;
  }

  if (const CXXThrowExpr *Throw = dyn_cast<CXXThrowExpr>(Cond)) {
    // Conditional operator handling can give us a throw expression as a
    // condition for a case like:
    //   br(c ? throw x : y, t, f) -> br(c, br(throw x, t, f), br(y, t, f)
    // Fold this to:
    //   br(c, throw x, br(y, t, f))
    EmitCXXThrowExpr(Throw, /*KeepInsertionPoint*/false);
    return;
  }

  // Emit the code with the fully general case.
  llvm::Value *CondV;
  {
    ApplyDebugLocation DL(*this, Cond);
    CondV = EvaluateExprAsBool(Cond);
  }

  MaybeEmitDeferredVarDeclInit(ConditionalDecl);

  // If not at the top of the logical operator nest, update MCDC temp with the
  // boolean result of the evaluated condition.
  if (!MCDCLogOpStack.empty()) {
    const Expr *MCDCBaseExpr = Cond;
    // When a nested ConditionalOperator (ternary) is encountered in a boolean
    // expression, MC/DC tracks the result of the ternary, and this is tied to
    // the ConditionalOperator expression and not the ternary's LHS or RHS. If
    // this is the case, the ConditionalOperator expression is passed through
    // the ConditionalOp parameter and then used as the MCDC base expression.
    if (ConditionalOp)
      MCDCBaseExpr = ConditionalOp;

    maybeUpdateMCDCCondBitmap(MCDCBaseExpr, CondV);
  }

  llvm::MDNode *Weights = nullptr;
  llvm::MDNode *Unpredictable = nullptr;

  // If the branch has a condition wrapped by __builtin_unpredictable,
  // create metadata that specifies that the branch is unpredictable.
  // Don't bother if not optimizing because that metadata would not be used.
  auto *Call = dyn_cast<CallExpr>(Cond->IgnoreImpCasts());
  if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) {
    auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
    if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
      llvm::MDBuilder MDHelper(getLLVMContext());
      Unpredictable = MDHelper.createUnpredictable();
    }
  }

  // If there is a Likelihood knowledge for the cond, lower it.
  // Note that if not optimizing this won't emit anything.
  llvm::Value *NewCondV = emitCondLikelihoodViaExpectIntrinsic(CondV, LH);
  if (CondV != NewCondV)
    CondV = NewCondV;
  else {
    // Otherwise, lower profile counts. Note that we do this even at -O0.
    uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
    Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
  }

  llvm::Instruction *BrInst = Builder.CreateCondBr(CondV, TrueBlock, FalseBlock,
                                                   Weights, Unpredictable);
  switch (HLSLControlFlowAttr) {
  case HLSLControlFlowHintAttr::Microsoft_branch:
  case HLSLControlFlowHintAttr::Microsoft_flatten: {
    llvm::MDBuilder MDHelper(CGM.getLLVMContext());

    llvm::ConstantInt *BranchHintConstant =
        HLSLControlFlowAttr ==
                HLSLControlFlowHintAttr::Spelling::Microsoft_branch
            ? llvm::ConstantInt::get(CGM.Int32Ty, 1)
            : llvm::ConstantInt::get(CGM.Int32Ty, 2);

    SmallVector<llvm::Metadata *, 2> Vals(
        {MDHelper.createString("hlsl.controlflow.hint"),
         MDHelper.createConstant(BranchHintConstant)});
    BrInst->setMetadata("hlsl.controlflow.hint",
                        llvm::MDNode::get(CGM.getLLVMContext(), Vals));
    break;
  }
  // This is required to avoid warnings during compilation
  case HLSLControlFlowHintAttr::SpellingNotCalculated:
    break;
  }
}

/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified stmt yet.
void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type) {
  CGM.ErrorUnsupported(S, Type);
}

/// emitNonZeroVLAInit - Emit the "zero" initialization of a
/// variable-length array whose elements have a non-zero bit-pattern.
///
/// \param baseType the inner-most element type of the array
/// \param src - a char* pointing to the bit-pattern for a single
/// base element of the array
/// \param sizeInChars - the total size of the VLA, in chars
static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType,
                               Address dest, Address src,
                               llvm::Value *sizeInChars) {
  CGBuilderTy &Builder = CGF.Builder;

  CharUnits baseSize = CGF.getContext().getTypeSizeInChars(baseType);
  llvm::Value *baseSizeInChars
    = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity());

  Address begin = dest.withElementType(CGF.Int8Ty);
  llvm::Value *end = Builder.CreateInBoundsGEP(begin.getElementType(),
                                               begin.emitRawPointer(CGF),
                                               sizeInChars, "vla.end");

  llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock();
  llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop");
  llvm::BasicBlock *contBB = CGF.createBasicBlock("vla-init.cont");

  // Make a loop over the VLA.  C99 guarantees that the VLA element
  // count must be nonzero.
  CGF.EmitBlock(loopBB);

  llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur");
  cur->addIncoming(begin.emitRawPointer(CGF), originBB);

  CharUnits curAlign =
    dest.getAlignment().alignmentOfArrayElement(baseSize);

  // memcpy the individual element bit-pattern.
  Builder.CreateMemCpy(Address(cur, CGF.Int8Ty, curAlign), src, baseSizeInChars,
                       /*volatile*/ false);

  // Go to the next element.
  llvm::Value *next =
    Builder.CreateInBoundsGEP(CGF.Int8Ty, cur, baseSizeInChars, "vla.next");

  // Leave if that's the end of the VLA.
  llvm::Value *done = Builder.CreateICmpEQ(next, end, "vla-init.isdone");
  Builder.CreateCondBr(done, contBB, loopBB);
  cur->addIncoming(next, loopBB);

  CGF.EmitBlock(contBB);
}

void
CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) {
  // Ignore empty classes in C++.
  if (getLangOpts().CPlusPlus) {
    if (const RecordType *RT = Ty->getAs<RecordType>()) {
      if (cast<CXXRecordDecl>(RT->getDecl())->isEmpty())
        return;
    }
  }

  if (DestPtr.getElementType() != Int8Ty)
    DestPtr = DestPtr.withElementType(Int8Ty);

  // Get size and alignment info for this aggregate.
  CharUnits size = getContext().getTypeSizeInChars(Ty);

  llvm::Value *SizeVal;
  const VariableArrayType *vla;

  // Don't bother emitting a zero-byte memset.
  if (size.isZero()) {
    // But note that getTypeInfo returns 0 for a VLA.
    if (const VariableArrayType *vlaType =
          dyn_cast_or_null<VariableArrayType>(
                                          getContext().getAsArrayType(Ty))) {
      auto VlaSize = getVLASize(vlaType);
      SizeVal = VlaSize.NumElts;
      CharUnits eltSize = getContext().getTypeSizeInChars(VlaSize.Type);
      if (!eltSize.isOne())
        SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(eltSize));
      vla = vlaType;
    } else {
      return;
    }
  } else {
    SizeVal = CGM.getSize(size);
    vla = nullptr;
  }

  // If the type contains a pointer to data member we can't memset it to zero.
  // Instead, create a null constant and copy it to the destination.
  // TODO: there are other patterns besides zero that we can usefully memset,
  // like -1, which happens to be the pattern used by member-pointers.
  if (!CGM.getTypes().isZeroInitializable(Ty)) {
    // For a VLA, emit a single element, then splat that over the VLA.
    if (vla) Ty = getContext().getBaseElementType(vla);

    llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);

    llvm::GlobalVariable *NullVariable =
      new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(),
                               /*isConstant=*/true,
                               llvm::GlobalVariable::PrivateLinkage,
                               NullConstant, Twine());
    CharUnits NullAlign = DestPtr.getAlignment();
    NullVariable->setAlignment(NullAlign.getAsAlign());
    Address SrcPtr(NullVariable, Builder.getInt8Ty(), NullAlign);

    if (vla) return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal);

    // Get and call the appropriate llvm.memcpy overload.
    Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, false);
    return;
  }

  // Otherwise, just memset the whole thing to zero.  This is legal
  // because in LLVM, all default initializers (other than the ones we just
  // handled above) are guaranteed to have a bit pattern of all zeros.
  Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, false);
}

llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) {
  // Make sure that there is a block for the indirect goto.
  if (!IndirectBranch)
    GetIndirectGotoBlock();

  llvm::BasicBlock *BB = getJumpDestForLabel(L).getBlock();

  // Make sure the indirect branch includes all of the address-taken blocks.
  IndirectBranch->addDestination(BB);
  return llvm::BlockAddress::get(CurFn, BB);
}

llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
  // If we already made the indirect branch for indirect goto, return its block.
  if (IndirectBranch) return IndirectBranch->getParent();

  CGBuilderTy TmpBuilder(*this, createBasicBlock("indirectgoto"));

  // Create the PHI node that indirect gotos will add entries to.
  llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, 0,
                                              "indirect.goto.dest");

  // Create the indirect branch instruction.
  IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal);
  return IndirectBranch->getParent();
}

/// Computes the length of an array in elements, as well as the base
/// element type and a properly-typed first element pointer.
llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,
                                              QualType &baseType,
                                              Address &addr) {
  const ArrayType *arrayType = origArrayType;

  // If it's a VLA, we have to load the stored size.  Note that
  // this is the size of the VLA in bytes, not its size in elements.
  llvm::Value *numVLAElements = nullptr;
  if (isa<VariableArrayType>(arrayType)) {
    numVLAElements = getVLASize(cast<VariableArrayType>(arrayType)).NumElts;

    // Walk into all VLAs.  This doesn't require changes to addr,
    // which has type T* where T is the first non-VLA element type.
    do {
      QualType elementType = arrayType->getElementType();
      arrayType = getContext().getAsArrayType(elementType);

      // If we only have VLA components, 'addr' requires no adjustment.
      if (!arrayType) {
        baseType = elementType;
        return numVLAElements;
      }
    } while (isa<VariableArrayType>(arrayType));

    // We get out here only if we find a constant array type
    // inside the VLA.
  }

  // We have some number of constant-length arrays, so addr should
  // have LLVM type [M x [N x [...]]]*.  Build a GEP that walks
  // down to the first element of addr.
  SmallVector<llvm::Value*, 8> gepIndices;

  // GEP down to the array type.
  llvm::ConstantInt *zero = Builder.getInt32(0);
  gepIndices.push_back(zero);

  uint64_t countFromCLAs = 1;
  QualType eltType;

  llvm::ArrayType *llvmArrayType =
    dyn_cast<llvm::ArrayType>(addr.getElementType());
  while (llvmArrayType) {
    assert(isa<ConstantArrayType>(arrayType));
    assert(cast<ConstantArrayType>(arrayType)->getZExtSize() ==
           llvmArrayType->getNumElements());

    gepIndices.push_back(zero);
    countFromCLAs *= llvmArrayType->getNumElements();
    eltType = arrayType->getElementType();

    llvmArrayType =
      dyn_cast<llvm::ArrayType>(llvmArrayType->getElementType());
    arrayType = getContext().getAsArrayType(arrayType->getElementType());
    assert((!llvmArrayType || arrayType) &&
           "LLVM and Clang types are out-of-synch");
  }

  if (arrayType) {
    // From this point onwards, the Clang array type has been emitted
    // as some other type (probably a packed struct). Compute the array
    // size, and just emit the 'begin' expression as a bitcast.
    while (arrayType) {
      countFromCLAs *= cast<ConstantArrayType>(arrayType)->getZExtSize();
      eltType = arrayType->getElementType();
      arrayType = getContext().getAsArrayType(eltType);
    }

    llvm::Type *baseType = ConvertType(eltType);
    addr = addr.withElementType(baseType);
  } else {
    // Create the actual GEP.
    addr = Address(Builder.CreateInBoundsGEP(addr.getElementType(),
                                             addr.emitRawPointer(*this),
                                             gepIndices, "array.begin"),
                   ConvertTypeForMem(eltType), addr.getAlignment());
  }

  baseType = eltType;

  llvm::Value *numElements
    = llvm::ConstantInt::get(SizeTy, countFromCLAs);

  // If we had any VLA dimensions, factor them in.
  if (numVLAElements)
    numElements = Builder.CreateNUWMul(numVLAElements, numElements);

  return numElements;
}

CodeGenFunction::VlaSizePair CodeGenFunction::getVLASize(QualType type) {
  const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
  assert(vla && "type was not a variable array type!");
  return getVLASize(vla);
}

CodeGenFunction::VlaSizePair
CodeGenFunction::getVLASize(const VariableArrayType *type) {
  // The number of elements so far; always size_t.
  llvm::Value *numElements = nullptr;

  QualType elementType;
  do {
    elementType = type->getElementType();
    llvm::Value *vlaSize = VLASizeMap[type->getSizeExpr()];
    assert(vlaSize && "no size for VLA!");
    assert(vlaSize->getType() == SizeTy);

    if (!numElements) {
      numElements = vlaSize;
    } else {
      // It's undefined behavior if this wraps around, so mark it that way.
      // FIXME: Teach -fsanitize=undefined to trap this.
      numElements = Builder.CreateNUWMul(numElements, vlaSize);
    }
  } while ((type = getContext().getAsVariableArrayType(elementType)));

  return { numElements, elementType };
}

CodeGenFunction::VlaSizePair
CodeGenFunction::getVLAElements1D(QualType type) {
  const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
  assert(vla && "type was not a variable array type!");
  return getVLAElements1D(vla);
}

CodeGenFunction::VlaSizePair
CodeGenFunction::getVLAElements1D(const VariableArrayType *Vla) {
  llvm::Value *VlaSize = VLASizeMap[Vla->getSizeExpr()];
  assert(VlaSize && "no size for VLA!");
  assert(VlaSize->getType() == SizeTy);
  return { VlaSize, Vla->getElementType() };
}

void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
  assert(type->isVariablyModifiedType() &&
         "Must pass variably modified type to EmitVLASizes!");

  EnsureInsertPoint();

  // We're going to walk down into the type and look for VLA
  // expressions.
  do {
    assert(type->isVariablyModifiedType());

    const Type *ty = type.getTypePtr();
    switch (ty->getTypeClass()) {

#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define NON_CANONICAL_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.inc"
      llvm_unreachable("unexpected dependent type!");

    // These types are never variably-modified.
    case Type::Builtin:
    case Type::Complex:
    case Type::Vector:
    case Type::ExtVector:
    case Type::ConstantMatrix:
    case Type::Record:
    case Type::Enum:
    case Type::Using:
    case Type::TemplateSpecialization:
    case Type::ObjCTypeParam:
    case Type::ObjCObject:
    case Type::ObjCInterface:
    case Type::ObjCObjectPointer:
    case Type::BitInt:
      llvm_unreachable("type class is never variably-modified!");

    case Type::Elaborated:
      type = cast<ElaboratedType>(ty)->getNamedType();
      break;

    case Type::Adjusted:
      type = cast<AdjustedType>(ty)->getAdjustedType();
      break;

    case Type::Decayed:
      type = cast<DecayedType>(ty)->getPointeeType();
      break;

    case Type::Pointer:
      type = cast<PointerType>(ty)->getPointeeType();
      break;

    case Type::BlockPointer:
      type = cast<BlockPointerType>(ty)->getPointeeType();
      break;

    case Type::LValueReference:
    case Type::RValueReference:
      type = cast<ReferenceType>(ty)->getPointeeType();
      break;

    case Type::MemberPointer:
      type = cast<MemberPointerType>(ty)->getPointeeType();
      break;

    case Type::ArrayParameter:
    case Type::ConstantArray:
    case Type::IncompleteArray:
      // Losing element qualification here is fine.
      type = cast<ArrayType>(ty)->getElementType();
      break;

    case Type::VariableArray: {
      // Losing element qualification here is fine.
      const VariableArrayType *vat = cast<VariableArrayType>(ty);

      // Unknown size indication requires no size computation.
      // Otherwise, evaluate and record it.
      if (const Expr *sizeExpr = vat->getSizeExpr()) {
        // It's possible that we might have emitted this already,
        // e.g. with a typedef and a pointer to it.
        llvm::Value *&entry = VLASizeMap[sizeExpr];
        if (!entry) {
          llvm::Value *size = EmitScalarExpr(sizeExpr);

          // C11 6.7.6.2p5:
          //   If the size is an expression that is not an integer constant
          //   expression [...] each time it is evaluated it shall have a value
          //   greater than zero.
          if (SanOpts.has(SanitizerKind::VLABound)) {
            SanitizerScope SanScope(this);
            llvm::Value *Zero = llvm::Constant::getNullValue(size->getType());
            clang::QualType SEType = sizeExpr->getType();
            llvm::Value *CheckCondition =
                SEType->isSignedIntegerType()
                    ? Builder.CreateICmpSGT(size, Zero)
                    : Builder.CreateICmpUGT(size, Zero);
            llvm::Constant *StaticArgs[] = {
                EmitCheckSourceLocation(sizeExpr->getBeginLoc()),
                EmitCheckTypeDescriptor(SEType)};
            EmitCheck(
                std::make_pair(CheckCondition, SanitizerKind::SO_VLABound),
                SanitizerHandler::VLABoundNotPositive, StaticArgs, size);
          }

          // Always zexting here would be wrong if it weren't
          // undefined behavior to have a negative bound.
          // FIXME: What about when size's type is larger than size_t?
          entry = Builder.CreateIntCast(size, SizeTy, /*signed*/ false);
        }
      }
      type = vat->getElementType();
      break;
    }

    case Type::FunctionProto:
    case Type::FunctionNoProto:
      type = cast<FunctionType>(ty)->getReturnType();
      break;

    case Type::Paren:
    case Type::TypeOf:
    case Type::UnaryTransform:
    case Type::Attributed:
    case Type::BTFTagAttributed:
    case Type::HLSLAttributedResource:
    case Type::SubstTemplateTypeParm:
    case Type::MacroQualified:
    case Type::CountAttributed:
      // Keep walking after single level desugaring.
      type = type.getSingleStepDesugaredType(getContext());
      break;

    case Type::Typedef:
    case Type::Decltype:
    case Type::Auto:
    case Type::DeducedTemplateSpecialization:
    case Type::PackIndexing:
      // Stop walking: nothing to do.
      return;

    case Type::TypeOfExpr:
      // Stop walking: emit typeof expression.
      EmitIgnoredExpr(cast<TypeOfExprType>(ty)->getUnderlyingExpr());
      return;

    case Type::Atomic:
      type = cast<AtomicType>(ty)->getValueType();
      break;

    case Type::Pipe:
      type = cast<PipeType>(ty)->getElementType();
      break;
    }
  } while (type->isVariablyModifiedType());
}

Address CodeGenFunction::EmitVAListRef(const Expr* E) {
  if (getContext().getBuiltinVaListType()->isArrayType())
    return EmitPointerWithAlignment(E);
  return EmitLValue(E).getAddress();
}

Address CodeGenFunction::EmitMSVAListRef(const Expr *E) {
  return EmitLValue(E).getAddress();
}

void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E,
                                              const APValue &Init) {
  assert(Init.hasValue() && "Invalid DeclRefExpr initializer!");
  if (CGDebugInfo *Dbg = getDebugInfo())
    if (CGM.getCodeGenOpts().hasReducedDebugInfo())
      Dbg->EmitGlobalVariable(E->getDecl(), Init);
}

CodeGenFunction::PeepholeProtection
CodeGenFunction::protectFromPeepholes(RValue rvalue) {
  // At the moment, the only aggressive peephole we do in IR gen
  // is trunc(zext) folding, but if we add more, we can easily
  // extend this protection.

  if (!rvalue.isScalar()) return PeepholeProtection();
  llvm::Value *value = rvalue.getScalarVal();
  if (!isa<llvm::ZExtInst>(value)) return PeepholeProtection();

  // Just make an extra bitcast.
  assert(HaveInsertPoint());
  llvm::Instruction *inst = new llvm::BitCastInst(value, value->getType(), "",
                                                  Builder.GetInsertBlock());

  PeepholeProtection protection;
  protection.Inst = inst;
  return protection;
}

void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) {
  if (!protection.Inst) return;

  // In theory, we could try to duplicate the peepholes now, but whatever.
  protection.Inst->eraseFromParent();
}

void CodeGenFunction::emitAlignmentAssumption(llvm::Value *PtrValue,
                                              QualType Ty, SourceLocation Loc,
                                              SourceLocation AssumptionLoc,
                                              llvm::Value *Alignment,
                                              llvm::Value *OffsetValue) {
  if (Alignment->getType() != IntPtrTy)
    Alignment =
        Builder.CreateIntCast(Alignment, IntPtrTy, false, "casted.align");
  if (OffsetValue && OffsetValue->getType() != IntPtrTy)
    OffsetValue =
        Builder.CreateIntCast(OffsetValue, IntPtrTy, true, "casted.offset");
  llvm::Value *TheCheck = nullptr;
  if (SanOpts.has(SanitizerKind::Alignment)) {
    llvm::Value *PtrIntValue =
        Builder.CreatePtrToInt(PtrValue, IntPtrTy, "ptrint");

    if (OffsetValue) {
      bool IsOffsetZero = false;
      if (const auto *CI = dyn_cast<llvm::ConstantInt>(OffsetValue))
        IsOffsetZero = CI->isZero();

      if (!IsOffsetZero)
        PtrIntValue = Builder.CreateSub(PtrIntValue, OffsetValue, "offsetptr");
    }

    llvm::Value *Zero = llvm::ConstantInt::get(IntPtrTy, 0);
    llvm::Value *Mask =
        Builder.CreateSub(Alignment, llvm::ConstantInt::get(IntPtrTy, 1));
    llvm::Value *MaskedPtr = Builder.CreateAnd(PtrIntValue, Mask, "maskedptr");
    TheCheck = Builder.CreateICmpEQ(MaskedPtr, Zero, "maskcond");
  }
  llvm::Instruction *Assumption = Builder.CreateAlignmentAssumption(
      CGM.getDataLayout(), PtrValue, Alignment, OffsetValue);

  if (!SanOpts.has(SanitizerKind::Alignment))
    return;
  emitAlignmentAssumptionCheck(PtrValue, Ty, Loc, AssumptionLoc, Alignment,
                               OffsetValue, TheCheck, Assumption);
}

void CodeGenFunction::emitAlignmentAssumption(llvm::Value *PtrValue,
                                              const Expr *E,
                                              SourceLocation AssumptionLoc,
                                              llvm::Value *Alignment,
                                              llvm::Value *OffsetValue) {
  QualType Ty = E->getType();
  SourceLocation Loc = E->getExprLoc();

  emitAlignmentAssumption(PtrValue, Ty, Loc, AssumptionLoc, Alignment,
                          OffsetValue);
}

llvm::Value *CodeGenFunction::EmitAnnotationCall(llvm::Function *AnnotationFn,
                                                 llvm::Value *AnnotatedVal,
                                                 StringRef AnnotationStr,
                                                 SourceLocation Location,
                                                 const AnnotateAttr *Attr) {
  SmallVector<llvm::Value *, 5> Args = {
      AnnotatedVal,
      CGM.EmitAnnotationString(AnnotationStr),
      CGM.EmitAnnotationUnit(Location),
      CGM.EmitAnnotationLineNo(Location),
  };
  if (Attr)
    Args.push_back(CGM.EmitAnnotationArgs(Attr));
  return Builder.CreateCall(AnnotationFn, Args);
}

void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) {
  assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute");
  for (const auto *I : D->specific_attrs<AnnotateAttr>())
    EmitAnnotationCall(CGM.getIntrinsic(llvm::Intrinsic::var_annotation,
                                        {V->getType(), CGM.ConstGlobalsPtrTy}),
                       V, I->getAnnotation(), D->getLocation(), I);
}

Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
                                              Address Addr) {
  assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute");
  llvm::Value *V = Addr.emitRawPointer(*this);
  llvm::Type *VTy = V->getType();
  auto *PTy = dyn_cast<llvm::PointerType>(VTy);
  unsigned AS = PTy ? PTy->getAddressSpace() : 0;
  llvm::PointerType *IntrinTy =
      llvm::PointerType::get(CGM.getLLVMContext(), AS);
  llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::ptr_annotation,
                                       {IntrinTy, CGM.ConstGlobalsPtrTy});

  for (const auto *I : D->specific_attrs<AnnotateAttr>()) {
    // FIXME Always emit the cast inst so we can differentiate between
    // annotation on the first field of a struct and annotation on the struct
    // itself.
    if (VTy != IntrinTy)
      V = Builder.CreateBitCast(V, IntrinTy);
    V = EmitAnnotationCall(F, V, I->getAnnotation(), D->getLocation(), I);
    V = Builder.CreateBitCast(V, VTy);
  }

  return Address(V, Addr.getElementType(), Addr.getAlignment());
}

CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { }

CodeGenFunction::SanitizerScope::SanitizerScope(CodeGenFunction *CGF)
    : CGF(CGF) {
  assert(!CGF->IsSanitizerScope);
  CGF->IsSanitizerScope = true;
}

CodeGenFunction::SanitizerScope::~SanitizerScope() {
  CGF->IsSanitizerScope = false;
}

void CodeGenFunction::InsertHelper(llvm::Instruction *I,
                                   const llvm::Twine &Name,
                                   llvm::BasicBlock::iterator InsertPt) const {
  LoopStack.InsertHelper(I);
  if (IsSanitizerScope)
    I->setNoSanitizeMetadata();
}

void CGBuilderInserter::InsertHelper(
    llvm::Instruction *I, const llvm::Twine &Name,
    llvm::BasicBlock::iterator InsertPt) const {
  llvm::IRBuilderDefaultInserter::InsertHelper(I, Name, InsertPt);
  if (CGF)
    CGF->InsertHelper(I, Name, InsertPt);
}

// Emits an error if we don't have a valid set of target features for the
// called function.
void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
                                          const FunctionDecl *TargetDecl) {
  // SemaChecking cannot handle below x86 builtins because they have different
  // parameter ranges with different TargetAttribute of caller.
  if (CGM.getContext().getTargetInfo().getTriple().isX86()) {
    unsigned BuiltinID = TargetDecl->getBuiltinID();
    if (BuiltinID == X86::BI__builtin_ia32_cmpps ||
        BuiltinID == X86::BI__builtin_ia32_cmpss ||
        BuiltinID == X86::BI__builtin_ia32_cmppd ||
        BuiltinID == X86::BI__builtin_ia32_cmpsd) {
      const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl);
      llvm::StringMap<bool> TargetFetureMap;
      CGM.getContext().getFunctionFeatureMap(TargetFetureMap, FD);
      llvm::APSInt Result =
          *(E->getArg(2)->getIntegerConstantExpr(CGM.getContext()));
      if (Result.getSExtValue() > 7 && !TargetFetureMap.lookup("avx"))
        CGM.getDiags().Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
            << TargetDecl->getDeclName() << "avx";
    }
  }
  return checkTargetFeatures(E->getBeginLoc(), TargetDecl);
}

// Emits an error if we don't have a valid set of target features for the
// called function.
void CodeGenFunction::checkTargetFeatures(SourceLocation Loc,
                                          const FunctionDecl *TargetDecl) {
  // Early exit if this is an indirect call.
  if (!TargetDecl)
    return;

  // Get the current enclosing function if it exists. If it doesn't
  // we can't check the target features anyhow.
  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl);
  if (!FD)
    return;

  // Grab the required features for the call. For a builtin this is listed in
  // the td file with the default cpu, for an always_inline function this is any
  // listed cpu and any listed features.
  unsigned BuiltinID = TargetDecl->getBuiltinID();
  std::string MissingFeature;
  llvm::StringMap<bool> CallerFeatureMap;
  CGM.getContext().getFunctionFeatureMap(CallerFeatureMap, FD);
  // When compiling in HipStdPar mode we have to be conservative in rejecting
  // target specific features in the FE, and defer the possible error to the
  // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is
  // referenced by an accelerator executable function, we emit an error.
  bool IsHipStdPar = getLangOpts().HIPStdPar && getLangOpts().CUDAIsDevice;
  if (BuiltinID) {
    StringRef FeatureList(CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
    if (!Builtin::evaluateRequiredTargetFeatures(
        FeatureList, CallerFeatureMap) && !IsHipStdPar) {
      CGM.getDiags().Report(Loc, diag::err_builtin_needs_feature)
          << TargetDecl->getDeclName()
          << FeatureList;
    }
  } else if (!TargetDecl->isMultiVersion() &&
             TargetDecl->hasAttr<TargetAttr>()) {
    // Get the required features for the callee.

    const TargetAttr *TD = TargetDecl->getAttr<TargetAttr>();
    ParsedTargetAttr ParsedAttr =
        CGM.getContext().filterFunctionTargetAttrs(TD);

    SmallVector<StringRef, 1> ReqFeatures;
    llvm::StringMap<bool> CalleeFeatureMap;
    CGM.getContext().getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);

    for (const auto &F : ParsedAttr.Features) {
      if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1)))
        ReqFeatures.push_back(StringRef(F).substr(1));
    }

    for (const auto &F : CalleeFeatureMap) {
      // Only positive features are "required".
      if (F.getValue())
        ReqFeatures.push_back(F.getKey());
    }
    if (!llvm::all_of(ReqFeatures, [&](StringRef Feature) {
      if (!CallerFeatureMap.lookup(Feature)) {
        MissingFeature = Feature.str();
        return false;
      }
      return true;
    }) && !IsHipStdPar)
      CGM.getDiags().Report(Loc, diag::err_function_needs_feature)
          << FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature;
  } else if (!FD->isMultiVersion() && FD->hasAttr<TargetAttr>()) {
    llvm::StringMap<bool> CalleeFeatureMap;
    CGM.getContext().getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);

    for (const auto &F : CalleeFeatureMap) {
      if (F.getValue() && (!CallerFeatureMap.lookup(F.getKey()) ||
                           !CallerFeatureMap.find(F.getKey())->getValue()) &&
          !IsHipStdPar)
        CGM.getDiags().Report(Loc, diag::err_function_needs_feature)
            << FD->getDeclName() << TargetDecl->getDeclName() << F.getKey();
    }
  }
}

void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) {
  if (!CGM.getCodeGenOpts().SanitizeStats)
    return;

  llvm::IRBuilder<> IRB(Builder.GetInsertBlock(), Builder.GetInsertPoint());
  IRB.SetCurrentDebugLocation(Builder.getCurrentDebugLocation());
  CGM.getSanStats().create(IRB, SSK);
}

void CodeGenFunction::EmitKCFIOperandBundle(
    const CGCallee &Callee, SmallVectorImpl<llvm::OperandBundleDef> &Bundles) {
  const FunctionProtoType *FP =
      Callee.getAbstractInfo().getCalleeFunctionProtoType();
  if (FP)
    Bundles.emplace_back("kcfi", CGM.CreateKCFITypeId(FP->desugar()));
}

llvm::Value *
CodeGenFunction::FormAArch64ResolverCondition(const FMVResolverOption &RO) {
  return RO.Features.empty() ? nullptr : EmitAArch64CpuSupports(RO.Features);
}

llvm::Value *
CodeGenFunction::FormX86ResolverCondition(const FMVResolverOption &RO) {
  llvm::Value *Condition = nullptr;

  if (RO.Architecture) {
    StringRef Arch = *RO.Architecture;
    // If arch= specifies an x86-64 micro-architecture level, test the feature
    // with __builtin_cpu_supports, otherwise use __builtin_cpu_is.
    if (Arch.starts_with("x86-64"))
      Condition = EmitX86CpuSupports({Arch});
    else
      Condition = EmitX86CpuIs(Arch);
  }

  if (!RO.Features.empty()) {
    llvm::Value *FeatureCond = EmitX86CpuSupports(RO.Features);
    Condition =
        Condition ? Builder.CreateAnd(Condition, FeatureCond) : FeatureCond;
  }
  return Condition;
}

static void CreateMultiVersionResolverReturn(CodeGenModule &CGM,
                                             llvm::Function *Resolver,
                                             CGBuilderTy &Builder,
                                             llvm::Function *FuncToReturn,
                                             bool SupportsIFunc) {
  if (SupportsIFunc) {
    Builder.CreateRet(FuncToReturn);
    return;
  }

  llvm::SmallVector<llvm::Value *, 10> Args(
      llvm::make_pointer_range(Resolver->args()));

  llvm::CallInst *Result = Builder.CreateCall(FuncToReturn, Args);
  Result->setTailCallKind(llvm::CallInst::TCK_MustTail);

  if (Resolver->getReturnType()->isVoidTy())
    Builder.CreateRetVoid();
  else
    Builder.CreateRet(Result);
}

void CodeGenFunction::EmitMultiVersionResolver(
    llvm::Function *Resolver, ArrayRef<FMVResolverOption> Options) {

  llvm::Triple::ArchType ArchType =
      getContext().getTargetInfo().getTriple().getArch();

  switch (ArchType) {
  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    EmitX86MultiVersionResolver(Resolver, Options);
    return;
  case llvm::Triple::aarch64:
    EmitAArch64MultiVersionResolver(Resolver, Options);
    return;
  case llvm::Triple::riscv32:
  case llvm::Triple::riscv64:
    EmitRISCVMultiVersionResolver(Resolver, Options);
    return;

  default:
    assert(false && "Only implemented for x86, AArch64 and RISC-V targets");
  }
}

void CodeGenFunction::EmitRISCVMultiVersionResolver(
    llvm::Function *Resolver, ArrayRef<FMVResolverOption> Options) {

  if (getContext().getTargetInfo().getTriple().getOS() !=
      llvm::Triple::OSType::Linux) {
    CGM.getDiags().Report(diag::err_os_unsupport_riscv_fmv);
    return;
  }

  llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
  Builder.SetInsertPoint(CurBlock);
  EmitRISCVCpuInit();

  bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc();
  bool HasDefault = false;
  unsigned DefaultIndex = 0;

  // Check the each candidate function.
  for (unsigned Index = 0; Index < Options.size(); Index++) {

    if (Options[Index].Features.empty()) {
      HasDefault = true;
      DefaultIndex = Index;
      continue;
    }

    Builder.SetInsertPoint(CurBlock);

    // FeaturesCondition: The bitmask of the required extension has been
    // enabled by the runtime object.
    // (__riscv_feature_bits.features[i] & REQUIRED_BITMASK) ==
    // REQUIRED_BITMASK
    //
    // When condition is met, return this version of the function.
    // Otherwise, try the next version.
    //
    // if (FeaturesConditionVersion1)
    //     return Version1;
    // else if (FeaturesConditionVersion2)
    //     return Version2;
    // else if (FeaturesConditionVersion3)
    //     return Version3;
    // ...
    // else
    //     return DefaultVersion;

    // TODO: Add a condition to check the length before accessing elements.
    // Without checking the length first, we may access an incorrect memory
    // address when using different versions.
    llvm::SmallVector<StringRef, 8> CurrTargetAttrFeats;
    llvm::SmallVector<std::string, 8> TargetAttrFeats;

    for (StringRef Feat : Options[Index].Features) {
      std::vector<std::string> FeatStr =
          getContext().getTargetInfo().parseTargetAttr(Feat).Features;

      assert(FeatStr.size() == 1 && "Feature string not delimited");

      std::string &CurrFeat = FeatStr.front();
      if (CurrFeat[0] == '+')
        TargetAttrFeats.push_back(CurrFeat.substr(1));
    }

    if (TargetAttrFeats.empty())
      continue;

    for (std::string &Feat : TargetAttrFeats)
      CurrTargetAttrFeats.push_back(Feat);

    Builder.SetInsertPoint(CurBlock);
    llvm::Value *FeatsCondition = EmitRISCVCpuSupports(CurrTargetAttrFeats);

    llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver);
    CGBuilderTy RetBuilder(*this, RetBlock);
    CreateMultiVersionResolverReturn(CGM, Resolver, RetBuilder,
                                     Options[Index].Function, SupportsIFunc);
    llvm::BasicBlock *ElseBlock = createBasicBlock("resolver_else", Resolver);

    Builder.SetInsertPoint(CurBlock);
    Builder.CreateCondBr(FeatsCondition, RetBlock, ElseBlock);

    CurBlock = ElseBlock;
  }

  // Finally, emit the default one.
  if (HasDefault) {
    Builder.SetInsertPoint(CurBlock);
    CreateMultiVersionResolverReturn(
        CGM, Resolver, Builder, Options[DefaultIndex].Function, SupportsIFunc);
    return;
  }

  // If no generic/default, emit an unreachable.
  Builder.SetInsertPoint(CurBlock);
  llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
  TrapCall->setDoesNotReturn();
  TrapCall->setDoesNotThrow();
  Builder.CreateUnreachable();
  Builder.ClearInsertionPoint();
}

void CodeGenFunction::EmitAArch64MultiVersionResolver(
    llvm::Function *Resolver, ArrayRef<FMVResolverOption> Options) {
  assert(!Options.empty() && "No multiversion resolver options found");
  assert(Options.back().Features.size() == 0 && "Default case must be last");
  bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc();
  assert(SupportsIFunc &&
         "Multiversion resolver requires target IFUNC support");
  bool AArch64CpuInitialized = false;
  llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);

  for (const FMVResolverOption &RO : Options) {
    Builder.SetInsertPoint(CurBlock);
    llvm::Value *Condition = FormAArch64ResolverCondition(RO);

    // The 'default' or 'all features enabled' case.
    if (!Condition) {
      CreateMultiVersionResolverReturn(CGM, Resolver, Builder, RO.Function,
                                       SupportsIFunc);
      return;
    }

    if (!AArch64CpuInitialized) {
      Builder.SetInsertPoint(CurBlock, CurBlock->begin());
      EmitAArch64CpuInit();
      AArch64CpuInitialized = true;
      Builder.SetInsertPoint(CurBlock);
    }

    llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver);
    CGBuilderTy RetBuilder(*this, RetBlock);
    CreateMultiVersionResolverReturn(CGM, Resolver, RetBuilder, RO.Function,
                                     SupportsIFunc);
    CurBlock = createBasicBlock("resolver_else", Resolver);
    Builder.CreateCondBr(Condition, RetBlock, CurBlock);
  }

  // If no default, emit an unreachable.
  Builder.SetInsertPoint(CurBlock);
  llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
  TrapCall->setDoesNotReturn();
  TrapCall->setDoesNotThrow();
  Builder.CreateUnreachable();
  Builder.ClearInsertionPoint();
}

void CodeGenFunction::EmitX86MultiVersionResolver(
    llvm::Function *Resolver, ArrayRef<FMVResolverOption> Options) {

  bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc();

  // Main function's basic block.
  llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
  Builder.SetInsertPoint(CurBlock);
  EmitX86CpuInit();

  for (const FMVResolverOption &RO : Options) {
    Builder.SetInsertPoint(CurBlock);
    llvm::Value *Condition = FormX86ResolverCondition(RO);

    // The 'default' or 'generic' case.
    if (!Condition) {
      assert(&RO == Options.end() - 1 &&
             "Default or Generic case must be last");
      CreateMultiVersionResolverReturn(CGM, Resolver, Builder, RO.Function,
                                       SupportsIFunc);
      return;
    }

    llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver);
    CGBuilderTy RetBuilder(*this, RetBlock);
    CreateMultiVersionResolverReturn(CGM, Resolver, RetBuilder, RO.Function,
                                     SupportsIFunc);
    CurBlock = createBasicBlock("resolver_else", Resolver);
    Builder.CreateCondBr(Condition, RetBlock, CurBlock);
  }

  // If no generic/default, emit an unreachable.
  Builder.SetInsertPoint(CurBlock);
  llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
  TrapCall->setDoesNotReturn();
  TrapCall->setDoesNotThrow();
  Builder.CreateUnreachable();
  Builder.ClearInsertionPoint();
}

// Loc - where the diagnostic will point, where in the source code this
//  alignment has failed.
// SecondaryLoc - if present (will be present if sufficiently different from
//  Loc), the diagnostic will additionally point a "Note:" to this location.
//  It should be the location where the __attribute__((assume_aligned))
//  was written e.g.
void CodeGenFunction::emitAlignmentAssumptionCheck(
    llvm::Value *Ptr, QualType Ty, SourceLocation Loc,
    SourceLocation SecondaryLoc, llvm::Value *Alignment,
    llvm::Value *OffsetValue, llvm::Value *TheCheck,
    llvm::Instruction *Assumption) {
  assert(isa_and_nonnull<llvm::CallInst>(Assumption) &&
         cast<llvm::CallInst>(Assumption)->getCalledOperand() ==
             llvm::Intrinsic::getOrInsertDeclaration(
                 Builder.GetInsertBlock()->getParent()->getParent(),
                 llvm::Intrinsic::assume) &&
         "Assumption should be a call to llvm.assume().");
  assert(&(Builder.GetInsertBlock()->back()) == Assumption &&
         "Assumption should be the last instruction of the basic block, "
         "since the basic block is still being generated.");

  if (!SanOpts.has(SanitizerKind::Alignment))
    return;

  // Don't check pointers to volatile data. The behavior here is implementation-
  // defined.
  if (Ty->getPointeeType().isVolatileQualified())
    return;

  // We need to temorairly remove the assumption so we can insert the
  // sanitizer check before it, else the check will be dropped by optimizations.
  Assumption->removeFromParent();

  {
    SanitizerScope SanScope(this);

    if (!OffsetValue)
      OffsetValue = Builder.getInt1(false); // no offset.

    llvm::Constant *StaticData[] = {EmitCheckSourceLocation(Loc),
                                    EmitCheckSourceLocation(SecondaryLoc),
                                    EmitCheckTypeDescriptor(Ty)};
    llvm::Value *DynamicData[] = {EmitCheckValue(Ptr),
                                  EmitCheckValue(Alignment),
                                  EmitCheckValue(OffsetValue)};
    EmitCheck({std::make_pair(TheCheck, SanitizerKind::SO_Alignment)},
              SanitizerHandler::AlignmentAssumption, StaticData, DynamicData);
  }

  // We are now in the (new, empty) "cont" basic block.
  // Reintroduce the assumption.
  Builder.Insert(Assumption);
  // FIXME: Assumption still has it's original basic block as it's Parent.
}

llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) {
  if (CGDebugInfo *DI = getDebugInfo())
    return DI->SourceLocToDebugLoc(Location);

  return llvm::DebugLoc();
}

llvm::Value *
CodeGenFunction::emitCondLikelihoodViaExpectIntrinsic(llvm::Value *Cond,
                                                      Stmt::Likelihood LH) {
  switch (LH) {
  case Stmt::LH_None:
    return Cond;
  case Stmt::LH_Likely:
  case Stmt::LH_Unlikely:
    // Don't generate llvm.expect on -O0 as the backend won't use it for
    // anything.
    if (CGM.getCodeGenOpts().OptimizationLevel == 0)
      return Cond;
    llvm::Type *CondTy = Cond->getType();
    assert(CondTy->isIntegerTy(1) && "expecting condition to be a boolean");
    llvm::Function *FnExpect =
        CGM.getIntrinsic(llvm::Intrinsic::expect, CondTy);
    llvm::Value *ExpectedValueOfCond =
        llvm::ConstantInt::getBool(CondTy, LH == Stmt::LH_Likely);
    return Builder.CreateCall(FnExpect, {Cond, ExpectedValueOfCond},
                              Cond->getName() + ".expval");
  }
  llvm_unreachable("Unknown Likelihood");
}

llvm::Value *CodeGenFunction::emitBoolVecConversion(llvm::Value *SrcVec,
                                                    unsigned NumElementsDst,
                                                    const llvm::Twine &Name) {
  auto *SrcTy = cast<llvm::FixedVectorType>(SrcVec->getType());
  unsigned NumElementsSrc = SrcTy->getNumElements();
  if (NumElementsSrc == NumElementsDst)
    return SrcVec;

  std::vector<int> ShuffleMask(NumElementsDst, -1);
  for (unsigned MaskIdx = 0;
       MaskIdx < std::min<>(NumElementsDst, NumElementsSrc); ++MaskIdx)
    ShuffleMask[MaskIdx] = MaskIdx;

  return Builder.CreateShuffleVector(SrcVec, ShuffleMask, Name);
}

void CodeGenFunction::EmitPointerAuthOperandBundle(
    const CGPointerAuthInfo &PointerAuth,
    SmallVectorImpl<llvm::OperandBundleDef> &Bundles) {
  if (!PointerAuth.isSigned())
    return;

  auto *Key = Builder.getInt32(PointerAuth.getKey());

  llvm::Value *Discriminator = PointerAuth.getDiscriminator();
  if (!Discriminator)
    Discriminator = Builder.getSize(0);

  llvm::Value *Args[] = {Key, Discriminator};
  Bundles.emplace_back("ptrauth", Args);
}

static llvm::Value *EmitPointerAuthCommon(CodeGenFunction &CGF,
                                          const CGPointerAuthInfo &PointerAuth,
                                          llvm::Value *Pointer,
                                          unsigned IntrinsicID) {
  if (!PointerAuth)
    return Pointer;

  auto Key = CGF.Builder.getInt32(PointerAuth.getKey());

  llvm::Value *Discriminator = PointerAuth.getDiscriminator();
  if (!Discriminator) {
    Discriminator = CGF.Builder.getSize(0);
  }

  // Convert the pointer to intptr_t before signing it.
  auto OrigType = Pointer->getType();
  Pointer = CGF.Builder.CreatePtrToInt(Pointer, CGF.IntPtrTy);

  // call i64 @llvm.ptrauth.sign.i64(i64 %pointer, i32 %key, i64 %discriminator)
  auto Intrinsic = CGF.CGM.getIntrinsic(IntrinsicID);
  Pointer = CGF.EmitRuntimeCall(Intrinsic, {Pointer, Key, Discriminator});

  // Convert back to the original type.
  Pointer = CGF.Builder.CreateIntToPtr(Pointer, OrigType);
  return Pointer;
}

llvm::Value *
CodeGenFunction::EmitPointerAuthSign(const CGPointerAuthInfo &PointerAuth,
                                     llvm::Value *Pointer) {
  if (!PointerAuth.shouldSign())
    return Pointer;
  return EmitPointerAuthCommon(*this, PointerAuth, Pointer,
                               llvm::Intrinsic::ptrauth_sign);
}

static llvm::Value *EmitStrip(CodeGenFunction &CGF,
                              const CGPointerAuthInfo &PointerAuth,
                              llvm::Value *Pointer) {
  auto StripIntrinsic = CGF.CGM.getIntrinsic(llvm::Intrinsic::ptrauth_strip);

  auto Key = CGF.Builder.getInt32(PointerAuth.getKey());
  // Convert the pointer to intptr_t before signing it.
  auto OrigType = Pointer->getType();
  Pointer = CGF.EmitRuntimeCall(
      StripIntrinsic, {CGF.Builder.CreatePtrToInt(Pointer, CGF.IntPtrTy), Key});
  return CGF.Builder.CreateIntToPtr(Pointer, OrigType);
}

llvm::Value *
CodeGenFunction::EmitPointerAuthAuth(const CGPointerAuthInfo &PointerAuth,
                                     llvm::Value *Pointer) {
  if (PointerAuth.shouldStrip()) {
    return EmitStrip(*this, PointerAuth, Pointer);
  }
  if (!PointerAuth.shouldAuth()) {
    return Pointer;
  }

  return EmitPointerAuthCommon(*this, PointerAuth, Pointer,
                               llvm::Intrinsic::ptrauth_auth);
}
